-
Notifications
You must be signed in to change notification settings - Fork 480
Add MakeTypesInternalAnalyzer #6820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
3c09ae3
8607e16
ef03d12
7244561
e2ecef9
59c2ace
fa70d87
bc210a0
075c130
bda3e0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
| using System.Composition; | ||
| using System.Linq; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CodeFixes; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
| using Microsoft.CodeQuality.Analyzers.Maintainability; | ||
|
|
||
| namespace Microsoft.CodeQuality.CSharp.Analyzers.Maintainability | ||
| { | ||
| [ExportCodeFixProvider(LanguageNames.CSharp), Shared] | ||
| public sealed class CSharpMakeTypesInternalFixer : MakeTypesInternalFixer | ||
| { | ||
| protected override SyntaxNode MakeInternal(SyntaxNode node) => | ||
| node switch | ||
| { | ||
| TypeDeclarationSyntax type => MakeMemberInternal(type), | ||
| EnumDeclarationSyntax @enum => MakeMemberInternal(@enum), | ||
| DelegateDeclarationSyntax @delegate => MakeMemberInternal(@delegate), | ||
| _ => throw new NotSupportedException() | ||
| }; | ||
|
|
||
| private static SyntaxNode MakeMemberInternal(MemberDeclarationSyntax type) | ||
| { | ||
| var publicKeyword = type.Modifiers.First(m => m.IsKind(SyntaxKind.PublicKeyword)); | ||
| var modifiers = type.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.InternalKeyword)); | ||
|
|
||
| return type.WithModifiers(modifiers); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. | ||
|
|
||
| using System.Collections.Immutable; | ||
| using Analyzer.Utilities.Extensions; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
| using Microsoft.CodeAnalysis.Diagnostics; | ||
| using Microsoft.CodeQuality.Analyzers.Maintainability; | ||
|
|
||
| namespace Microsoft.CodeQuality.CSharp.Analyzers.Maintainability | ||
| { | ||
| [DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
| public sealed class CSharpMakeTypesInternal : MakeTypesInternal<SyntaxKind> | ||
| { | ||
| protected override ImmutableArray<SyntaxKind> TypeKinds { get; } = | ||
| ImmutableArray.Create(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.RecordDeclaration); | ||
|
|
||
| protected override SyntaxKind EnumKind { get; } = SyntaxKind.EnumDeclaration; | ||
|
|
||
| protected override ImmutableArray<SyntaxKind> DelegateKinds { get; } = ImmutableArray.Create(SyntaxKind.DelegateDeclaration); | ||
|
|
||
| protected override void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context) | ||
| { | ||
| var type = (TypeDeclarationSyntax)context.Node; | ||
| ReportIfPublic(context, type.Modifiers, type.Identifier); | ||
| } | ||
|
|
||
| protected override void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context) | ||
| { | ||
| var @enum = (EnumDeclarationSyntax)context.Node; | ||
| ReportIfPublic(context, @enum.Modifiers, @enum.Identifier); | ||
| } | ||
|
|
||
| protected override void AnalyzeDelegateDeclaration(SyntaxNodeAnalysisContext context) | ||
| { | ||
| var @delegate = (DelegateDeclarationSyntax)context.Node; | ||
| ReportIfPublic(context, @delegate.Modifiers, @delegate.Identifier); | ||
| } | ||
|
|
||
| private static void ReportIfPublic(SyntaxNodeAnalysisContext context, SyntaxTokenList modifiers, SyntaxToken identifier) | ||
| { | ||
| if (modifiers.Any(SyntaxKind.PublicKeyword)) | ||
| { | ||
| context.ReportDiagnostic(identifier.CreateDiagnostic(Rule)); | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. | ||
|
|
||
| using System.Collections.Immutable; | ||
| using System.Threading.Tasks; | ||
| using Analyzer.Utilities; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CodeActions; | ||
| using Microsoft.CodeAnalysis.CodeFixes; | ||
|
|
||
| namespace Microsoft.CodeQuality.Analyzers.Maintainability | ||
| { | ||
| public abstract class MakeTypesInternalFixer : CodeFixProvider | ||
| { | ||
| public override async Task RegisterCodeFixesAsync(CodeFixContext context) | ||
| { | ||
| var root = await context.Document.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||
| var node = root.FindNode(context.Span); | ||
|
|
||
| var codeAction = CodeAction.Create( | ||
| MicrosoftCodeQualityAnalyzersResources.MakeTypesInternalCodeFixTitle, | ||
| _ => | ||
| { | ||
| var newNode = MakeInternal(node); | ||
| var newRoot = root.ReplaceNode(node, newNode.WithTriviaFrom(node)); | ||
|
|
||
| return Task.FromResult(context.Document.WithSyntaxRoot(newRoot)); | ||
| }, | ||
| MicrosoftCodeQualityAnalyzersResources.MakeTypesInternalCodeFixTitle); | ||
| context.RegisterCodeFix(codeAction, context.Diagnostics); | ||
| } | ||
|
|
||
| public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; | ||
|
|
||
| protected abstract SyntaxNode MakeInternal(SyntaxNode node); | ||
|
|
||
| public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(MakeTypesInternal<SymbolKind>.RuleId); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. | ||
|
|
||
| using System; | ||
| using System.Collections.Immutable; | ||
| using System.Linq; | ||
| using Analyzer.Utilities; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.Diagnostics; | ||
|
|
||
| namespace Microsoft.CodeQuality.Analyzers.Maintainability | ||
| { | ||
| using static MicrosoftCodeQualityAnalyzersResources; | ||
|
|
||
| public abstract class MakeTypesInternal<TSyntaxKind> : DiagnosticAnalyzer | ||
| where TSyntaxKind : struct, Enum | ||
| { | ||
| internal const string RuleId = "CA1515"; | ||
|
|
||
| protected static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create( | ||
| RuleId, | ||
| CreateLocalizableResourceString(nameof(MakeTypesInternalTitle)), | ||
| CreateLocalizableResourceString(nameof(MakeTypesInternalMessage)), | ||
| DiagnosticCategory.Maintainability, | ||
| RuleLevel.Disabled, | ||
| description: CreateLocalizableResourceString(nameof(MakeTypesInternalDescription)), | ||
| isPortedFxCopRule: false, | ||
| isDataflowRule: false); | ||
|
|
||
| public override void Initialize(AnalysisContext context) | ||
| { | ||
| context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); | ||
| context.EnableConcurrentExecution(); | ||
| context.RegisterCompilationStartAction(context => | ||
| { | ||
| var compilation = context.Compilation; | ||
| SyntaxTree? firstSyntaxTree; | ||
| if (compilation.Options.OutputKind is not (OutputKind.ConsoleApplication or OutputKind.WindowsApplication or OutputKind.WindowsRuntimeApplication) | ||
| || (firstSyntaxTree = context.Compilation.SyntaxTrees.FirstOrDefault()) is null | ||
| || !context.Options.GetOutputKindsOption(Rule, firstSyntaxTree, compilation).Contains(compilation.Options.OutputKind)) | ||
|
||
| { | ||
| return; | ||
| } | ||
|
|
||
| context.RegisterSyntaxNodeAction(AnalyzeTypeDeclaration, TypeKinds); | ||
| context.RegisterSyntaxNodeAction(AnalyzeEnumDeclaration, EnumKind); | ||
| context.RegisterSyntaxNodeAction(AnalyzeDelegateDeclaration, DelegateKinds); | ||
| }); | ||
| } | ||
|
|
||
| protected abstract ImmutableArray<TSyntaxKind> TypeKinds { get; } | ||
|
|
||
| protected abstract TSyntaxKind EnumKind { get; } | ||
|
|
||
| protected abstract ImmutableArray<TSyntaxKind> DelegateKinds { get; } | ||
|
|
||
| protected abstract void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context); | ||
|
|
||
| protected abstract void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context); | ||
|
|
||
| protected abstract void AnalyzeDelegateDeclaration(SyntaxNodeAnalysisContext context); | ||
|
|
||
| public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.