From 3c09ae32c401e3ba77155e73bb83d55b105e09b9 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 12:51:51 +0200 Subject: [PATCH 1/7] Add MakeTypesInternalAnalyzer --- .../CSharpMakeTypesInternal.Fixer.cs | 37 ++ .../CSharpMakeTypesInternal.cs | 39 ++ .../Core/AnalyzerReleases.Unshipped.md | 1 + .../MakeTypesInternal.Fixer.cs | 37 ++ .../Maintainability/MakeTypesInternal.cs | 55 ++ ...icrosoftCodeQualityAnalyzersResources.resx | 12 + ...rosoftCodeQualityAnalyzersResources.cs.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.de.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.es.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.fr.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.it.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.ja.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.ko.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.pl.xlf | 20 + ...oftCodeQualityAnalyzersResources.pt-BR.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.ru.xlf | 20 + ...rosoftCodeQualityAnalyzersResources.tr.xlf | 20 + ...tCodeQualityAnalyzersResources.zh-Hans.xlf | 20 + ...tCodeQualityAnalyzersResources.zh-Hant.xlf | 20 + .../Microsoft.CodeAnalysis.NetAnalyzers.md | 12 + .../Microsoft.CodeAnalysis.NetAnalyzers.sarif | 38 ++ src/NetAnalyzers/RulesMissingDocumentation.md | 1 + .../Maintainability/MakeTypesInternalTests.cs | 477 ++++++++++++++++++ .../BasicMakeTypesInternal.Fixer.vb | 33 ++ .../Maintainability/BasicMakeTypesInternal.vb | 31 ++ .../DiagnosticCategoryAndIdRanges.txt | 4 +- 26 files changed, 1035 insertions(+), 2 deletions(-) create mode 100644 src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs create mode 100644 src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs create mode 100644 src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs create mode 100644 src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs create mode 100644 src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs create mode 100644 src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb create mode 100644 src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs new file mode 100644 index 0000000000..0322888d40 --- /dev/null +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +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) + { + if (node is TypeDeclarationSyntax 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); + } + + if (node is EnumDeclarationSyntax @enum) + { + var publicKeyword = @enum.Modifiers.First(m => m.IsKind(SyntaxKind.PublicKeyword)); + var modifiers = @enum.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.InternalKeyword)); + + return @enum.WithModifiers(modifiers); + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs new file mode 100644 index 0000000000..15d98d7c1e --- /dev/null +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs @@ -0,0 +1,39 @@ +// 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 + { + protected override ImmutableArray TypeKinds { get; } = + ImmutableArray.Create(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.RecordDeclaration); + + protected override SyntaxKind EnumKind { get; } = SyntaxKind.EnumDeclaration; + + protected override void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context) + { + var type = (TypeDeclarationSyntax)context.Node; + if (type.Modifiers.Any(SyntaxKind.PublicKeyword)) + { + context.ReportDiagnostic(type.Identifier.CreateDiagnostic(Rule)); + } + } + + protected override void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context) + { + var @enum = (EnumDeclarationSyntax)context.Node; + if (@enum.Modifiers.Any(SyntaxKind.PublicKeyword)) + { + context.ReportDiagnostic(@enum.Identifier.CreateDiagnostic(Rule)); + } + } + } +} \ No newline at end of file diff --git a/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md b/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md index ecd6860b49..928f8ca77e 100644 --- a/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md +++ b/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md @@ -4,6 +4,7 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- +CA1514 | Maintainability | Disabled | MakeTypesInternal, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514) CA1865 | Performance | Info | UseStringMethodCharOverloadWithSingleCharacters, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1865) CA1866 | Performance | Info | UseStringMethodCharOverloadWithSingleCharacters, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866) CA1867 | Performance | Disabled | UseStringMethodCharOverloadWithSingleCharacters, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1867) diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs new file mode 100644 index 0000000000..3066d9eba1 --- /dev/null +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs @@ -0,0 +1,37 @@ +// 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 newNode = MakeInternal(node); + if (newNode is null) + { + return; + } + + root = root.ReplaceNode(node, newNode.WithTriviaFrom(node)); + + var codeAction = CodeAction.Create( + MicrosoftCodeQualityAnalyzersResources.MakeTypesInternalCodeFixTitle, + _ => Task.FromResult(context.Document.WithSyntaxRoot(root)), + MicrosoftCodeQualityAnalyzersResources.MakeTypesInternalCodeFixTitle); + context.RegisterCodeFix(codeAction, context.Diagnostics); + } + + protected abstract SyntaxNode? MakeInternal(SyntaxNode node); + + public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(MakeTypesInternal.RuleId); + } +} \ No newline at end of file diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs new file mode 100644 index 0000000000..744b9031ea --- /dev/null +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs @@ -0,0 +1,55 @@ +// 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 Analyzer.Utilities; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeQuality.Analyzers.Maintainability +{ + using static MicrosoftCodeQualityAnalyzersResources; + + public abstract class MakeTypesInternal : DiagnosticAnalyzer + where TSyntaxKind : struct, Enum + { + internal const string RuleId = "CA1514"; + + 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(compilationStartContext => + { + var compilation = compilationStartContext.Compilation; + if (compilation.Options.OutputKind is not (OutputKind.ConsoleApplication or OutputKind.WindowsApplication or OutputKind.WindowsRuntimeApplication)) + { + return; + } + + compilationStartContext.RegisterSyntaxNodeAction(AnalyzeTypeDeclaration, TypeKinds); + compilationStartContext.RegisterSyntaxNodeAction(AnalyzeEnumDeclaration, EnumKind); + }); + } + + protected abstract ImmutableArray TypeKinds { get; } + + protected abstract TSyntaxKind EnumKind { get; } + + protected abstract void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context); + + protected abstract void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context); + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); + } +} \ No newline at end of file diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx index 50622c812c..8ced6e19dd 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx @@ -1281,4 +1281,16 @@ Type '{0}' directly or indirectly inherits '{1}' without implementing any of '{2}'. Publicly-visible types should implement the generic version to broaden usability. + + Make all public types internal + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + Since applications' code isn't referenced, all types can be made internal + + + Make all public types internal + \ No newline at end of file diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf index adc146e79f..6e90b4336c 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf @@ -337,6 +337,26 @@ Používat PascalCase pro pojmenované zástupné objekty + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' Použít AttributeUsageAttribute diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf index 7dea49d786..c9c44070ec 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf @@ -337,6 +337,26 @@ PascalCase für benannte Platzhalter verwenden + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' "AttributeUsageAttribute" anwenden diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf index d5c1da1c1f..db87255c90 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf @@ -337,6 +337,26 @@ Usar PascalCase para marcadores de posición con nombre + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' Aplicar "AttributeUsageAttribute" diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf index f943caa998..2f06cf03e7 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf @@ -337,6 +337,26 @@ Utiliser casse Pascal pour les espaces réservés nommés + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' Appliquer 'AttributeUsageAttribute' diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf index 3736b5adf5..7667af2c42 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf @@ -337,6 +337,26 @@ Usare la notazione Pascal per i segnaposto denominati + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' Applica 'AttributeUsageAttribute' diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf index 56ae2a3168..26e401b9fe 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf @@ -337,6 +337,26 @@ 名前付きプレースホルダーに PascalCase を使用してください + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' 'AttributeUsageAttribute' の適用 diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf index a99a30ceec..e306fa4f84 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf @@ -337,6 +337,26 @@ 명명된 자리 표시자에 대해 PascalCase 사용 + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' 'AttributeUsageAttribute' 적용 diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf index 4ee437fffc..abb0f74da7 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf @@ -337,6 +337,26 @@ Używanie języka PascalCase dla nazwanych symboli zastępczych + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' Zastosuj element „AttributeUsageAttribute” diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf index 0ac5310dc0..b2b13f691f 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf @@ -337,6 +337,26 @@ Usar o PascalCase nos espaços reservados nomeados + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' Aplicar 'AttributeUsageAttribute' diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf index 9f2d8f37f6..37b36b9c3a 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf @@ -337,6 +337,26 @@ Использовать PascalCase для именованных заполнителей + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' Применить "AttributeUsageAttribute" diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf index b744ce390b..2cb4886d4c 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf @@ -337,6 +337,26 @@ Adlandırılmış yer tutucular için PascalCase kullanın + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' 'AttributeUsageAttribute' uygula diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf index 922bab9faf..195076c4cd 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf @@ -337,6 +337,26 @@ 将 PascalCase 用于已命名占位符 + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' 应用 "AttributeUsageAttribute" diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf index 01a9abbdd9..fc1808fbe8 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf @@ -337,6 +337,26 @@ 將 PascalCase 用於已命名的預留位置 + + Make all public types internal + Make all public types internal + + + + Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications aren't referenced and thus all types can be made internal. + + + + Since applications' code isn't referenced, all types can be made internal + Since applications' code isn't referenced, all types can be made internal + + + + Make all public types internal + Make all public types internal + + Apply 'AttributeUsageAttribute' 套用 'AttributeUsageAttribute' diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md index 5b4eae4792..e93544a9a2 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md @@ -912,6 +912,18 @@ Throw helpers are simpler and more efficient than an if block constructing a new |CodeFix|True| --- +## [CA1514](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514): Make all public types internal + +Different than libraries, applications aren't referenced and thus all types can be made internal. + +|Item|Value| +|-|-| +|Category|Maintainability| +|Enabled|False| +|Severity|Warning| +|CodeFix|True| +--- + ## [CA1700](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1700): Do not name enum values 'Reserved' This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change. diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index 368a728f59..7a0621a5b1 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -126,6 +126,25 @@ ] } }, + "CA1514": { + "id": "CA1514", + "shortDescription": "Make all public types internal", + "fullDescription": "Different than libraries, applications aren't referenced and thus all types can be made internal.", + "defaultLevel": "warning", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514", + "properties": { + "category": "Maintainability", + "isEnabledByDefault": false, + "typeName": "CSharpMakeTypesInternal", + "languages": [ + "C#" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA1802": { "id": "CA1802", "shortDescription": "Use literals where appropriate", @@ -6290,6 +6309,25 @@ ] } }, + "CA1514": { + "id": "CA1514", + "shortDescription": "Make all public types internal", + "fullDescription": "Different than libraries, applications aren't referenced and thus all types can be made internal.", + "defaultLevel": "warning", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514", + "properties": { + "category": "Maintainability", + "isEnabledByDefault": false, + "typeName": "BasicMakeTypesInternal", + "languages": [ + "Visual Basic" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA1802": { "id": "CA1802", "shortDescription": "Use literals where appropriate", diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md index 50fa5fb52f..af429f867e 100644 --- a/src/NetAnalyzers/RulesMissingDocumentation.md +++ b/src/NetAnalyzers/RulesMissingDocumentation.md @@ -6,6 +6,7 @@ CA1510 | | Use ArgumentException throw helper | CA1512 | | Use ArgumentOutOfRangeException throw helper | CA1513 | | Use ObjectDisposedException throw helper | +CA1514 | | Make all public types internal | CA1856 | | Incorrect usage of ConstantExpected attribute | CA1857 | | A constant is expected for the parameter | CA1862 | | Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons | diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs new file mode 100644 index 0000000000..28b0e2f351 --- /dev/null +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs @@ -0,0 +1,477 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Xunit; +using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< + Microsoft.CodeQuality.CSharp.Analyzers.Maintainability.CSharpMakeTypesInternal, + Microsoft.CodeQuality.CSharp.Analyzers.Maintainability.CSharpMakeTypesInternalFixer>; +using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< + Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability.BasicMakeTypesInternal, + Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability.BasicMakeTypesInternalFixer>; + +namespace Microsoft.CodeQuality.Analyzers.Maintainability.UnitTests +{ + public sealed class MakeTypesInternalTests + { + [Theory] + [MemberData(nameof(NonDiagnosticTriggeringOutputKinds))] + public async Task LibraryCode_NoDiagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, "public class MyService {}"); + + await VerifyVbAsync(outputKind, "Public Class MyService\nEnd Class"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task ApplicationCode_Diagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public class [|Program|] +{ + public static void Main() {} +}", + @" +internal class Program +{ + public static void Main() {} +}"); + + await VerifyVbAsync(outputKind, @" +Public Class [|Program|] + Public Shared Sub Main() + End Sub +End Class", + @" +Friend Class Program + Public Shared Sub Main() + End Sub +End Class"); + } + + [Theory] + [MemberData(nameof(NonDiagnosticTriggeringOutputKinds))] + public async Task MultipleTypes_LibraryCode_NoDiagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public class MyTests {} + +internal class MyService {} + +public class MyValidator {}"); + + await VerifyVbAsync(outputKind, @" +Public Class MyTests +End Class + +Friend Class MyService +End Class + +Public Class MyValidator +End Class"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task MultipleTypes_ApplicationCode_Diagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public class [|Program|] +{ + public static void Main() {} +} + +internal class MyService {} + +public class [|MyValidator|] {}", + @" +internal class Program +{ + public static void Main() {} +} + +internal class MyService {} + +internal class MyValidator {}"); + await VerifyVbAsync(outputKind, @" +Public Class [|Program|] + Public Shared Sub Main() + End Sub +End Class + +Friend Class MyService +End Class + +Public Class [|MyValidator|] +End Class", + @" +Friend Class Program + Public Shared Sub Main() + End Sub +End Class + +Friend Class MyService +End Class + +Friend Class MyValidator +End Class"); + } + + [Theory] + [MemberData(nameof(NonDiagnosticTriggeringOutputKinds))] + public async Task MultipleDifferentTypes_LibraryCode_NoDiagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public class MyTests {} + +public abstract class MyBaseType {} + +public struct MyValueType {} + +public interface IValidator {} + +public enum Types {}"); + + await VerifyVbAsync(outputKind, @" +Public Class MyTests +End Class + +Public MustInherit Class MyBaseType +End Class + +Public Structure MyValueType +End Structure + +Public Interface IValidator +End Interface + +Public Enum Types + None +End Enum"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task MultipleDifferentTypes_ApplicationCode_Diagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public class [|Program|] +{ + public static void Main() {} +} + +public abstract class [|MyBaseType|] {} + +public struct [|MyValueType|] {} + +public interface [|IValidator|] {} + +public record [|Person|]; + +public enum [|Types|] {}", + @" +internal class Program +{ + public static void Main() {} +} + +internal abstract class MyBaseType {} + +internal struct MyValueType {} + +internal interface IValidator {} + +internal record Person; + +internal enum Types {}"); + + await VerifyVbAsync(outputKind, @" +Public Class [|Program|] + Public Shared Sub Main() + End Sub +End Class + +Public MustInherit Class [|MyBaseType|] +End Class + +Public Structure [|MyValueType|] +End Structure + +Public Interface [|IValidator|] +End Interface + +Public Enum [|Types|] + None +End Enum", + @" +Friend Class Program + Public Shared Sub Main() + End Sub +End Class + +Friend MustInherit Class MyBaseType +End Class + +Friend Structure MyValueType +End Structure + +Friend Interface IValidator +End Interface + +Friend Enum Types + None +End Enum"); + } + + [Theory] + [InlineData(OutputKind.DynamicallyLinkedLibrary)] + [InlineData(OutputKind.WindowsRuntimeMetadata)] + public Task Records_LibraryCode_NoDiagnostic(OutputKind outputKind) + { + return VerifyCsAsync(outputKind, @"public record Person;"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public Task Records_ApplicationCode_Diagnostic(OutputKind outputKind) + { + return VerifyCsAsync(outputKind, @" +public class [|Program|] +{ + public static void Main() {} +} + +public record [|Person|];", + @" +internal class Program +{ + public static void Main() {} +} + +internal record Person;"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task NoModifier_ApplicationCode_NoDiagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +class Program +{ + public static void Main() {} +} + +class MyService {} + +sealed class MyValidator {}"); + await VerifyVbAsync(outputKind, @" +Class Program + Public Shared Sub Main() + End Sub +End Class + +Class MyService +End Class + +NotInheritable Class MyValidator +End Class"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task MultipleModifiers_ApplicationCode_Diagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public class [|Program|] +{ + public static void Main() {} +} + +public sealed class [|MyService|] {} + +public abstract partial class [|MyValidator|] {} + +public partial interface [|IValidator|] {}", + @" +internal class Program +{ + public static void Main() {} +} + +internal sealed class MyService {} + +internal abstract partial class MyValidator {} + +internal partial interface IValidator {}"); + await VerifyVbAsync(outputKind, @" +Public Class [|Program|] + Public Shared Sub Main() + End Sub +End Class + +Public NotInheritable Class [|MyService|] +End Class + +Public Partial MustInherit Class [|MyValidator|] +End Class + +Public Partial Interface [|IValidator|] +End Interface", + @" +Friend Class Program + Public Shared Sub Main() + End Sub +End Class + +Friend NotInheritable Class MyService +End Class + +Friend Partial MustInherit Class MyValidator +End Class + +Friend Partial Interface IValidator +End Interface"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task MultipleUnorderedModifiers_ApplicationCode_Diagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public class [|Program|] +{ + public static void Main() {} +} + +sealed public class [|MyService|] {}", + @" +internal class Program +{ + public static void Main() {} +} + +sealed internal class MyService {}"); + await VerifyVbAsync(outputKind, @" +Public Class [|Program|] + Public Shared Sub Main() + End Sub +End Class + +NotInheritable Public Class [|MyService|] +End Class", + @" +Friend Class Program + Public Shared Sub Main() + End Sub +End Class + +NotInheritable Friend Class MyService +End Class"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task NestedTypes_ApplicationCode_NoDiagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +class Program +{ + public static void Main() {} + + public struct [|MyValueType|] + { + public class [|Nested|] {} + } +}", + @" +class Program +{ + public static void Main() {} + + internal struct MyValueType + { + internal class Nested {} + } +}"); + await VerifyVbAsync(outputKind, @" +Class Program + Public Shared Sub Main() + End Sub + + Public Structure [|MyValueType|] + Public Class [|Nested|] + End Class + End Structure +End Class", + @" +Class Program + Public Shared Sub Main() + End Sub + + Friend Structure MyValueType + Friend Class Nested + End Class + End Structure +End Class"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task ProtectedTypes_ApplicationCode_NoDiagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +class Program +{ + public static void Main() {} + + protected abstract class MyService {} +}"); + await VerifyVbAsync(outputKind, @" +Class Program + Public Shared Sub Main() + End Sub + + Protected MustInherit Class MyService + End Class +End Class"); + } + + private Task VerifyCsAsync(OutputKind outputKind, string testCode, string fixedCode = null) + { + return new VerifyCS.Test + { + TestCode = testCode, + FixedCode = fixedCode!, + TestState = { OutputKind = outputKind }, + LanguageVersion = LanguageVersion.CSharp10 + }.RunAsync(); + } + + private Task VerifyVbAsync(OutputKind outputKind, string testCode, string fixedCode = null) + { + return new VerifyVB.Test + { + TestCode = testCode, + FixedCode = fixedCode!, + TestState = { OutputKind = outputKind } + }.RunAsync(); + } + + public static IEnumerable DiagnosticTriggeringOutputKinds() + { + yield return new object[] { OutputKind.ConsoleApplication }; + yield return new object[] { OutputKind.WindowsRuntimeApplication }; + yield return new object[] { OutputKind.WindowsApplication }; + } + + public static IEnumerable NonDiagnosticTriggeringOutputKinds() + { + yield return new object[] { OutputKind.NetModule }; + yield return new object[] { OutputKind.DynamicallyLinkedLibrary }; + yield return new object[] { OutputKind.WindowsRuntimeMetadata }; + } + } +} \ No newline at end of file diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb new file mode 100644 index 0000000000..73eec371ef --- /dev/null +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb @@ -0,0 +1,33 @@ +Imports System.Composition +Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.CodeFixes +Imports Microsoft.CodeAnalysis.VisualBasic +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Microsoft.CodeQuality.Analyzers.Maintainability + +Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability + + Public Class BasicMakeTypesInternalFixer + Inherits MakeTypesInternalFixer + + Protected Overrides Function MakeInternal(node As SyntaxNode) As SyntaxNode + Dim type = TryCast(node, TypeStatementSyntax) + If type IsNot Nothing + Dim publicKeyword = type.Modifiers.First(Function(m) m.IsKind(SyntaxKind.PublicKeyword)) + Dim modifiers = type.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.FriendKeyword)) + + Return type.WithModifiers(modifiers) + End If + + Dim enumStatement = TryCast(node, EnumStatementSyntax) + If enumStatement IsNot Nothing + Dim publicKeyword = enumStatement.Modifiers.First(Function(m) m.IsKind(SyntaxKind.PublicKeyword)) + Dim modifiers = enumStatement.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.FriendKeyword)) + + Return enumStatement.WithModifiers(modifiers) + End If + + Return Nothing + End Function + End Class +End Namespace \ No newline at end of file diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb new file mode 100644 index 0000000000..b5089e33dd --- /dev/null +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb @@ -0,0 +1,31 @@ +Imports System.Collections.Immutable +Imports Analyzer.Utilities.Extensions +Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.VisualBasic +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Microsoft.CodeQuality.Analyzers.Maintainability + +Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability + + Public NotInheritable Class BasicMakeTypesInternal + Inherits MakeTypesInternal(Of SyntaxKind) + + Protected Overrides ReadOnly Property TypeKinds As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create(SyntaxKind.ClassStatement, SyntaxKind.StructureStatement, SyntaxKind.InterfaceStatement) + Protected Overrides ReadOnly Property EnumKind As SyntaxKind = SyntaxKind.EnumStatement + + Protected Overrides Sub AnalyzeTypeDeclaration(context As SyntaxNodeAnalysisContext) + Dim type = DirectCast(context.Node, TypeStatementSyntax) + If type.Modifiers.Any(SyntaxKind.PublicKeyword) Then + context.ReportDiagnostic(type.Identifier.CreateDiagnostic(Rule)) + End If + End Sub + + Protected Overrides Sub AnalyzeEnumDeclaration(context As SyntaxNodeAnalysisContext) + Dim enumStatement = DirectCast(context.Node, EnumStatementSyntax) + If enumStatement.Modifiers.Any(SyntaxKind.PublicKeyword) Then + context.ReportDiagnostic(enumStatement.Identifier.CreateDiagnostic(Rule)) + End If + End Sub + End Class +End Namespace \ No newline at end of file diff --git a/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt b/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt index 1da70dbbb5..432ccb878c 100644 --- a/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt +++ b/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt @@ -1,4 +1,4 @@ -# This file contains the allowed analyzer rule "Category" and corresponding "Diagnostic ID range" +# This file contains the allowed analyzer rule "Category" and corresponding "Diagnostic ID range" # FORMAT: # 'Category': Comma separate list of 'StartId-EndId' or 'Id' or 'Prefix' @@ -17,7 +17,7 @@ Security: CA2100-CA2153, CA2300-CA2330, CA3000-CA3147, CA5300-CA5405 Usage: CA1801, CA1806, CA1816, CA2200-CA2209, CA2211-CA2261 Naming: CA1700-CA1727 Interoperability: CA1400-CA1422 -Maintainability: CA1500-CA1513 +Maintainability: CA1500-CA1514 Reliability: CA9998-CA9999, CA2000-CA2021 Documentation: CA1200-CA1200 From 8607e16cceafe26afaee5dd591f76524cdefb4ae Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 13:16:13 +0200 Subject: [PATCH 2/7] Add FixAll support --- .../Maintainability/MakeTypesInternal.Fixer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs index 3066d9eba1..daf2edf566 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs @@ -30,6 +30,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix(codeAction, context.Diagnostics); } + public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + protected abstract SyntaxNode? MakeInternal(SyntaxNode node); public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(MakeTypesInternal.RuleId); From ef03d124116b7b6576acc80b3a8f9b4ef44f75f2 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 13:22:29 +0200 Subject: [PATCH 3/7] Add header comment. --- .../Maintainability/BasicMakeTypesInternal.vb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb index b5089e33dd..ccbb6cb890 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb @@ -1,3 +1,5 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + Imports System.Collections.Immutable Imports Analyzer.Utilities.Extensions Imports Microsoft.CodeAnalysis From e2ecef91b9e948ed6ca68adf20ec999bae3af357 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 13:28:11 +0200 Subject: [PATCH 4/7] Add file header --- .../Maintainability/BasicMakeTypesInternal.Fixer.vb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb index 73eec371ef..03dc79add7 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb @@ -1,4 +1,6 @@ -Imports System.Composition +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +Imports System.Composition Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.CodeFixes Imports Microsoft.CodeAnalysis.VisualBasic From fa70d870f58d1961e1515133aaa047840e437835 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Sun, 6 Aug 2023 13:30:26 +0200 Subject: [PATCH 5/7] Address PR feedback --- .../CSharpMakeTypesInternal.Fixer.cs | 8 +++ .../CSharpMakeTypesInternal.cs | 22 ++++-- .../MakeTypesInternal.Fixer.cs | 20 +++--- .../Maintainability/MakeTypesInternal.cs | 13 ++-- .../Maintainability/MakeTypesInternalTests.cs | 68 +++++++++++++++++++ .../BasicMakeTypesInternal.Fixer.vb | 8 +++ .../Maintainability/BasicMakeTypesInternal.vb | 18 +++-- 7 files changed, 134 insertions(+), 23 deletions(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs index 0322888d40..972d0455b4 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs @@ -31,6 +31,14 @@ public sealed class CSharpMakeTypesInternalFixer : MakeTypesInternalFixer return @enum.WithModifiers(modifiers); } + if (node is DelegateDeclarationSyntax @delegate) + { + var publicKeyword = @delegate.Modifiers.First(m => m.IsKind(SyntaxKind.PublicKeyword)); + var modifiers = @delegate.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.InternalKeyword)); + + return @delegate.WithModifiers(modifiers); + } + return null; } } diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs index 15d98d7c1e..89abddcc82 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.cs @@ -18,21 +18,31 @@ public sealed class CSharpMakeTypesInternal : MakeTypesInternal protected override SyntaxKind EnumKind { get; } = SyntaxKind.EnumDeclaration; + protected override ImmutableArray DelegateKinds { get; } = ImmutableArray.Create(SyntaxKind.DelegateDeclaration); + protected override void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context) { var type = (TypeDeclarationSyntax)context.Node; - if (type.Modifiers.Any(SyntaxKind.PublicKeyword)) - { - context.ReportDiagnostic(type.Identifier.CreateDiagnostic(Rule)); - } + ReportIfPublic(context, type.Modifiers, type.Identifier); } protected override void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context) { var @enum = (EnumDeclarationSyntax)context.Node; - if (@enum.Modifiers.Any(SyntaxKind.PublicKeyword)) + 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(@enum.Identifier.CreateDiagnostic(Rule)); + context.ReportDiagnostic(identifier.CreateDiagnostic(Rule)); } } } diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs index daf2edf566..f46b676a7c 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs @@ -15,17 +15,21 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var node = root.FindNode(context.Span); - var newNode = MakeInternal(node); - if (newNode is null) - { - return; - } - - root = root.ReplaceNode(node, newNode.WithTriviaFrom(node)); var codeAction = CodeAction.Create( MicrosoftCodeQualityAnalyzersResources.MakeTypesInternalCodeFixTitle, - _ => Task.FromResult(context.Document.WithSyntaxRoot(root)), + _ => + { + var newNode = MakeInternal(node); + if (newNode is null) + { + return Task.FromResult(context.Document); + } + + var newRoot = root.ReplaceNode(node, newNode.WithTriviaFrom(node)); + + return Task.FromResult(context.Document.WithSyntaxRoot(newRoot)); + }, MicrosoftCodeQualityAnalyzersResources.MakeTypesInternalCodeFixTitle); context.RegisterCodeFix(codeAction, context.Diagnostics); } diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs index 744b9031ea..9487c5209c 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs @@ -29,16 +29,17 @@ public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); - context.RegisterCompilationStartAction(compilationStartContext => + context.RegisterCompilationStartAction(context => { - var compilation = compilationStartContext.Compilation; + var compilation = context.Compilation; if (compilation.Options.OutputKind is not (OutputKind.ConsoleApplication or OutputKind.WindowsApplication or OutputKind.WindowsRuntimeApplication)) { return; } - compilationStartContext.RegisterSyntaxNodeAction(AnalyzeTypeDeclaration, TypeKinds); - compilationStartContext.RegisterSyntaxNodeAction(AnalyzeEnumDeclaration, EnumKind); + context.RegisterSyntaxNodeAction(AnalyzeTypeDeclaration, TypeKinds); + context.RegisterSyntaxNodeAction(AnalyzeEnumDeclaration, EnumKind); + context.RegisterSyntaxNodeAction(AnalyzeDelegateDeclaration, DelegateKinds); }); } @@ -46,10 +47,14 @@ public override void Initialize(AnalysisContext context) protected abstract TSyntaxKind EnumKind { get; } + protected abstract ImmutableArray DelegateKinds { get; } + protected abstract void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context); protected abstract void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context); + protected abstract void AnalyzeDelegateDeclaration(SyntaxNodeAnalysisContext context); + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); } } \ No newline at end of file diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs index 28b0e2f351..448768584a 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs @@ -439,6 +439,74 @@ End Class End Class"); } + [Theory] + [MemberData(nameof(NonDiagnosticTriggeringOutputKinds))] + public async Task Delegates_LibraryCode_NoDiagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public delegate int GetValue(string s); +public delegate void Print(object x); +public delegate bool Match(); +"); + + await VerifyVbAsync(outputKind, @" +Imports System + +Public Delegate Function GetValue(s As String) As Int32 +Public Delegate Sub Print(x As Object) +Public Delegate Function Match() As Boolean +"); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task Delegates_ApplicationCode_Diagnostic(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, @" +public delegate int [|GetValue|](string s); +public delegate void [|Print|](object x); +public delegate bool [|Match|](); +internal delegate char GetFirst(string s); + +class Program { + public static void Main() {} +}", + @" +internal delegate int GetValue(string s); +internal delegate void Print(object x); +internal delegate bool Match(); +internal delegate char GetFirst(string s); + +class Program { + public static void Main() {} +}"); + + await VerifyVbAsync(outputKind, @" +Imports System + +Public Delegate Function [|GetValue|](s As String) As Int32 +Public Delegate Sub [|Print|](x As Object) +Public Delegate Function [|Match|]() As Boolean +Friend Delegate Function GetFirst(s As String) As Char + +Class Program + Public Shared Sub Main() + End Sub +End Class", + @" +Imports System + +Friend Delegate Function GetValue(s As String) As Int32 +Friend Delegate Sub Print(x As Object) +Friend Delegate Function Match() As Boolean +Friend Delegate Function GetFirst(s As String) As Char + +Class Program + Public Shared Sub Main() + End Sub +End Class"); + } + private Task VerifyCsAsync(OutputKind outputKind, string testCode, string fixedCode = null) { return new VerifyCS.Test diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb index 03dc79add7..e622c18f5f 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb @@ -29,6 +29,14 @@ Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability Return enumStatement.WithModifiers(modifiers) End If + Dim delegateStatement = TryCast(node, DelegateStatementSyntax) + If delegateStatement IsNot Nothing + Dim publicKeyword = delegateStatement.Modifiers.First(Function(m) m.IsKind(SyntaxKind.PublicKeyword)) + Dim modifiers = delegateStatement.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.FriendKeyword)) + + Return delegateStatement.WithModifiers(modifiers) + End If + Return Nothing End Function End Class diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb index ccbb6cb890..f71e2050bd 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.vb @@ -15,18 +15,26 @@ Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability Protected Overrides ReadOnly Property TypeKinds As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create(SyntaxKind.ClassStatement, SyntaxKind.StructureStatement, SyntaxKind.InterfaceStatement) Protected Overrides ReadOnly Property EnumKind As SyntaxKind = SyntaxKind.EnumStatement + Protected Overrides ReadOnly Property DelegateKinds As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create(SyntaxKind.DelegateFunctionStatement, SyntaxKind.DelegateSubStatement) Protected Overrides Sub AnalyzeTypeDeclaration(context As SyntaxNodeAnalysisContext) Dim type = DirectCast(context.Node, TypeStatementSyntax) - If type.Modifiers.Any(SyntaxKind.PublicKeyword) Then - context.ReportDiagnostic(type.Identifier.CreateDiagnostic(Rule)) - End If + ReportIfPublic(context, type.Modifiers, type.Identifier) End Sub Protected Overrides Sub AnalyzeEnumDeclaration(context As SyntaxNodeAnalysisContext) Dim enumStatement = DirectCast(context.Node, EnumStatementSyntax) - If enumStatement.Modifiers.Any(SyntaxKind.PublicKeyword) Then - context.ReportDiagnostic(enumStatement.Identifier.CreateDiagnostic(Rule)) + ReportIfPublic(context, enumStatement.Modifiers, enumStatement.Identifier) + End Sub + + Protected Overrides Sub AnalyzeDelegateDeclaration(context As SyntaxNodeAnalysisContext) + Dim delegateStatement = DirectCast(context.Node, DelegateStatementSyntax) + ReportIfPublic(context, delegateStatement.Modifiers, delegateStatement.Identifier) + End Sub + + Private Shared Sub ReportIfPublic(context As SyntaxNodeAnalysisContext, modifiers As SyntaxTokenList, identifier As SyntaxToken) + If modifiers.Any(SyntaxKind.PublicKeyword) Then + context.ReportDiagnostic(identifier.CreateDiagnostic(Rule)) End If End Sub End Class From 075c13035a1f44336cbadb46ee826269c49af194 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Sun, 24 Sep 2023 22:06:16 +0200 Subject: [PATCH 6/7] Applied code review suggestions. --- .../CSharpMakeTypesInternal.Fixer.cs | 37 ++-- .../Core/AnalyzerReleases.Unshipped.md | 1 + .../MakeTypesInternal.Fixer.cs | 7 +- .../Maintainability/MakeTypesInternal.cs | 8 +- ...icrosoftCodeQualityAnalyzersResources.resx | 8 +- ...rosoftCodeQualityAnalyzersResources.cs.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.de.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.es.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.fr.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.it.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.ja.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.ko.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.pl.xlf | 16 +- ...oftCodeQualityAnalyzersResources.pt-BR.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.ru.xlf | 16 +- ...rosoftCodeQualityAnalyzersResources.tr.xlf | 16 +- ...tCodeQualityAnalyzersResources.zh-Hans.xlf | 16 +- ...tCodeQualityAnalyzersResources.zh-Hant.xlf | 16 +- .../Microsoft.CodeAnalysis.NetAnalyzers.md | 51 +----- .../Microsoft.CodeAnalysis.NetAnalyzers.sarif | 20 +-- src/NetAnalyzers/RulesMissingDocumentation.md | 7 +- .../Maintainability/MakeTypesInternalTests.cs | 165 ++++++++++++++++++ .../BasicMakeTypesInternal.Fixer.vb | 2 +- .../DiagnosticCategoryAndIdRanges.txt | 2 +- 24 files changed, 309 insertions(+), 207 deletions(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs index 972d0455b4..8aa2a00380 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/Maintainability/CSharpMakeTypesInternal.Fixer.cs @@ -1,5 +1,6 @@ // 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; @@ -13,33 +14,21 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.Maintainability [ExportCodeFixProvider(LanguageNames.CSharp), Shared] public sealed class CSharpMakeTypesInternalFixer : MakeTypesInternalFixer { - protected override SyntaxNode? MakeInternal(SyntaxNode node) - { - if (node is TypeDeclarationSyntax 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); - } - - if (node is EnumDeclarationSyntax @enum) + protected override SyntaxNode MakeInternal(SyntaxNode node) => + node switch { - var publicKeyword = @enum.Modifiers.First(m => m.IsKind(SyntaxKind.PublicKeyword)); - var modifiers = @enum.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.InternalKeyword)); + TypeDeclarationSyntax type => MakeMemberInternal(type), + EnumDeclarationSyntax @enum => MakeMemberInternal(@enum), + DelegateDeclarationSyntax @delegate => MakeMemberInternal(@delegate), + _ => throw new NotSupportedException() + }; - return @enum.WithModifiers(modifiers); - } - - if (node is DelegateDeclarationSyntax @delegate) - { - var publicKeyword = @delegate.Modifiers.First(m => m.IsKind(SyntaxKind.PublicKeyword)); - var modifiers = @delegate.Modifiers.Replace(publicKeyword, SyntaxFactory.Token(SyntaxKind.InternalKeyword)); - - return @delegate.WithModifiers(modifiers); - } + 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 null; + return type.WithModifiers(modifiers); } } } \ No newline at end of file diff --git a/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md b/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md index c0945d156a..0d9fcab48b 100644 --- a/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md +++ b/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md @@ -5,3 +5,4 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- CA1514 | Maintainability | Info | AvoidLengthCheckWhenSlicingToEndAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514) +CA1515 | Maintainability | Disabled | MakeTypesInternal, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515) diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs index f46b676a7c..acf8174fde 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.Fixer.cs @@ -21,11 +21,6 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) _ => { var newNode = MakeInternal(node); - if (newNode is null) - { - return Task.FromResult(context.Document); - } - var newRoot = root.ReplaceNode(node, newNode.WithTriviaFrom(node)); return Task.FromResult(context.Document.WithSyntaxRoot(newRoot)); @@ -36,7 +31,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - protected abstract SyntaxNode? MakeInternal(SyntaxNode node); + protected abstract SyntaxNode MakeInternal(SyntaxNode node); public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(MakeTypesInternal.RuleId); } diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs index 9487c5209c..197d96624a 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Immutable; +using System.Linq; using Analyzer.Utilities; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -13,7 +14,7 @@ namespace Microsoft.CodeQuality.Analyzers.Maintainability public abstract class MakeTypesInternal : DiagnosticAnalyzer where TSyntaxKind : struct, Enum { - internal const string RuleId = "CA1514"; + internal const string RuleId = "CA1515"; protected static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create( RuleId, @@ -32,7 +33,10 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(context => { var compilation = context.Compilation; - if (compilation.Options.OutputKind is not (OutputKind.ConsoleApplication or OutputKind.WindowsApplication or OutputKind.WindowsRuntimeApplication)) + 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; } diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx index 34ece0a934..b7d7eb650f 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx @@ -1294,15 +1294,15 @@ Type '{0}' directly or indirectly inherits '{1}' without implementing any of '{2}'. Publicly-visible types should implement the generic version to broaden usability. - Make all public types internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal + Consider making public types internal \ No newline at end of file diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf index d112f8c402..1e1bb2b4b5 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf index 1071cc81f2..deccea62ae 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf index f6607e8819..3882e8c851 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf index af3d5e58fe..4db878d41f 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf index cf7dd687f0..8fe45e1ea8 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf index d76686de13..6fa1f5303a 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf index c7509fba8d..6038e07a02 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf index bd370c04e7..083544e16b 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf index 9f2e614ed7..adacdd0278 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf index c986b81645..bbd828f8e0 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf index 904a06008e..5850f72d36 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf index 61fe159945..dcb4ef7046 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf index ae479f2bfd..467492f6f3 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf @@ -358,23 +358,23 @@ - Make all public types internal - Make all public types internal + Make the public type internal + Make the public type internal - Different than libraries, applications aren't referenced and thus all types can be made internal. - Different than libraries, applications aren't referenced and thus all types can be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Since applications' code isn't referenced, all types can be made internal - Since applications' code isn't referenced, all types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal + Since an application's code is typically not referenced publicly, types can be made internal - Make all public types internal - Make all public types internal + Consider making public types internal + Consider making public types internal diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md index 94729d5462..24e7d00819 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md @@ -924,9 +924,9 @@ An explicit length calculation can be error-prone and can be avoided when slicin |CodeFix|True| --- -## [CA1515](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515): Make all public types internal +## [CA1515](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515): Consider making public types internal -Different than libraries, applications aren't referenced and thus all types can be made internal. +Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. |Item|Value| |-|-| @@ -936,29 +936,6 @@ Different than libraries, applications aren't referenced and thus all types can |CodeFix|True| --- -<<<<<<< HEAD -## [CA1514](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514): Make all public types internal - -Different than libraries, applications aren't referenced and thus all types can be made internal. -======= -## [CA1514](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514): Avoid redundant length argument - -An explicit length calculation can be error-prone and can be avoided when slicing to end of the buffer. ->>>>>>> master - -|Item|Value| -|-|-| -|Category|Maintainability| -<<<<<<< HEAD -|Enabled|False| -|Severity|Warning| -======= -|Enabled|True| -|Severity|Info| ->>>>>>> master -|CodeFix|True| ---- - ## [CA1700](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1700): Do not name enum values 'Reserved' This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change. @@ -2295,30 +2272,6 @@ A writable collection property allows a user to replace the collection with a di |Enabled|False| |Severity|Warning| |CodeFix|False| -## [CA1862](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862): Use the 'StringComparison' method overloads to perform case-insensitive string comparisons -Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. -## [CA1869](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1869): Cache and reuse 'JsonSerializerOptions' instances - -Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application. - -|Item|Value| -|-|-| -|Category|Performance| -|Enabled|True| -|Severity|Info| -|CodeFix|False| ---- - -## [CA1870](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1870): Use a cached 'SearchValues' instance - -Using a cached 'SearchValues' instance is more efficient than passing values to 'IndexOfAny'/'ContainsAny' directly. - -|Item|Value| -|-|-| -|Category|Performance| -|Enabled|True| -|Severity|Info| -|CodeFix|True| --- ## [CA2231](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2231): Overload operator equals on overriding value type Equals diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index 2a6c6b2b3e..7caacc7db2 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -126,12 +126,12 @@ ] } }, - "CA1514": { - "id": "CA1514", - "shortDescription": "Make all public types internal", - "fullDescription": "Different than libraries, applications aren't referenced and thus all types can be made internal.", + "CA1515": { + "id": "CA1515", + "shortDescription": "Consider making public types internal", + "fullDescription": "Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal.", "defaultLevel": "warning", - "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515", "properties": { "category": "Maintainability", "isEnabledByDefault": false, @@ -6347,12 +6347,12 @@ ] } }, - "CA1514": { - "id": "CA1514", - "shortDescription": "Make all public types internal", - "fullDescription": "Different than libraries, applications aren't referenced and thus all types can be made internal.", + "CA1515": { + "id": "CA1515", + "shortDescription": "Consider making public types internal", + "fullDescription": "Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal.", "defaultLevel": "warning", - "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515", "properties": { "category": "Maintainability", "isEnabledByDefault": false, diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md index 4e5c693698..a0aea3b9a8 100644 --- a/src/NetAnalyzers/RulesMissingDocumentation.md +++ b/src/NetAnalyzers/RulesMissingDocumentation.md @@ -7,15 +7,10 @@ CA1511 | | Use ArgumentOutOfRangeException throw helper | CA1513 | | Use ObjectDisposedException throw helper | CA1514 | | Avoid redundant length argument | -<<<<<<< HEAD -CA1514 | | Make all public types internal | -======= -CA1514 | | Avoid redundant length argument | ->>>>>>> master +CA1515 | | Consider making public types internal | CA1856 | | Incorrect usage of ConstantExpected attribute | CA1857 | | A constant is expected for the parameter | CA1862 | | Use the 'StringComparison' method overloads to perform case-insensitive string comparisons | -CA1862 | | Use the 'StringComparison' method overloads to perform case-insensitive string comparisons | CA1863 | | Use 'CompositeFormat' | CA1865 | | Use char overload | CA1866 | | Use char overload | diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs index 448768584a..ec1cd45354 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs @@ -507,6 +507,171 @@ End Sub End Class"); } + [Theory] + [InlineData("ConsoleApplication", OutputKind.ConsoleApplication)] + [InlineData("WindowsApplication", OutputKind.WindowsApplication)] + [InlineData("WindowsRuntimeApplication", OutputKind.WindowsRuntimeApplication)] + [InlineData("ConsoleApplication,WindowsApplication", OutputKind.WindowsApplication)] + [InlineData("ConsoleApplication,WindowsApplication,WindowsRuntimeApplication", OutputKind.WindowsRuntimeApplication)] + public async Task CompilationOptions_Diagnostic(string optionsText, OutputKind outputKind) + { + await new VerifyCS.Test + { + TestCode = """ + public class [|Program|] + { + public static void Main() {} + } + """, + FixedCode = """ + internal class Program + { + public static void Main() {} + } + """, + TestState = + { + OutputKind = outputKind, + AnalyzerConfigFiles = + { + ("/.editorconfig", + $""" + root = true + + [*] + dotnet_code_quality.CA1515.output_kind = {optionsText} + """) + } + }, + LanguageVersion = LanguageVersion.CSharp10 + }.RunAsync(); + + await new VerifyVB.Test + { + TestCode = """ + Public Class [|Program|] + Public Shared Sub Main() + End Sub + End Class + """, + FixedCode = """ + Friend Class Program + Public Shared Sub Main() + End Sub + End Class + """, + TestState = + { + OutputKind = outputKind, + AnalyzerConfigFiles = + { + ("/.editorconfig", + $""" + root = true + + [*] + dotnet_code_quality.CA1515.output_kind = {optionsText} + """) + } + }, + }.RunAsync(); + } + + [Theory] + [InlineData("ConsoleApplication", OutputKind.DynamicallyLinkedLibrary)] + [InlineData("WindowsApplication", OutputKind.ConsoleApplication)] + [InlineData("WindowsRuntimeApplication", OutputKind.ConsoleApplication)] + [InlineData("ConsoleApplication,WindowsApplication", OutputKind.WindowsRuntimeApplication)] + [InlineData("ConsoleApplication,WindowsApplication,WindowsRuntimeApplication", OutputKind.DynamicallyLinkedLibrary)] + public async Task CompilationOptions_NoDiagnostic(string optionsText, OutputKind outputKind) + { + await new VerifyCS.Test + { + TestCode = """ + public class Program + { + public static void Main() {} + } + """, + TestState = + { + OutputKind = outputKind, + AnalyzerConfigFiles = + { + ("/.editorconfig", + $""" + root = true + + [*] + dotnet_code_quality.CA1515.output_kind = {optionsText} + """) + } + }, + LanguageVersion = LanguageVersion.CSharp10 + }.RunAsync(); + + await new VerifyVB.Test + { + TestCode = """ + Public Class Program + Public Shared Sub Main() + End Sub + End Class + """, + TestState = + { + OutputKind = outputKind, + AnalyzerConfigFiles = + { + ("/.editorconfig", + $""" + root = true + + [*] + dotnet_code_quality.CA1515.output_kind = {optionsText} + """) + } + }, + }.RunAsync(); + } + + [Theory] + [MemberData(nameof(DiagnosticTriggeringOutputKinds))] + public async Task Trivia(OutputKind outputKind) + { + await VerifyCsAsync(outputKind, + """ + // This is the entry point class. + public class [|Program|] + { + public static void Main() {} + } + """, + """ + // This is the entry point class. + internal class Program + { + public static void Main() {} + } + """); + + await VerifyVbAsync(outputKind, + """ + ' This is the entry point class. + Public Class [|Program|] + Public Shared Sub Main() + End Sub + End Class + """, + """ + ' This is the entry point class. + Friend Class Program + Public Shared Sub Main() + End Sub + End Class + """); + } + private Task VerifyCsAsync(OutputKind outputKind, string testCode, string fixedCode = null) { return new VerifyCS.Test diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb index e622c18f5f..d7211df683 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/Maintainability/BasicMakeTypesInternal.Fixer.vb @@ -37,7 +37,7 @@ Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability Return delegateStatement.WithModifiers(modifiers) End If - Return Nothing + Throw New NotSupportedException() End Function End Class End Namespace \ No newline at end of file diff --git a/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt b/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt index 25e773b710..2423ad707e 100644 --- a/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt +++ b/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt @@ -17,7 +17,7 @@ Security: CA2100-CA2153, CA2300-CA2330, CA3000-CA3147, CA5300-CA5405 Usage: CA1801, CA1806, CA1816, CA2200-CA2209, CA2211-CA2261 Naming: CA1700-CA1727 Interoperability: CA1400-CA1422 -Maintainability: CA1500-CA1514 +Maintainability: CA1500-CA1515 Reliability: CA9998-CA9999, CA2000-CA2021 Documentation: CA1200-CA1200 From bda3e0bfd1e8ceda5b6510146cb1dc4f2593b3e4 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 25 Sep 2023 21:52:00 +0200 Subject: [PATCH 7/7] Make all OutputKinds configurable. --- docs/Analyzer Configuration.md | 4 +++- .../Maintainability/MakeTypesInternal.cs | 9 +++++---- .../MicrosoftCodeQualityAnalyzersResources.resx | 4 ++-- .../xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf | 8 ++++---- .../MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf | 8 ++++---- .../xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf | 8 ++++---- .../MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf | 8 ++++---- .../MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf | 8 ++++---- .../Microsoft.CodeAnalysis.NetAnalyzers.md | 2 +- .../Microsoft.CodeAnalysis.NetAnalyzers.sarif | 4 ++-- .../Maintainability/MakeTypesInternalTests.cs | 3 +++ .../Compiler/Options/AnalyzerOptionsExtensions.cs | 10 +++++++++- 20 files changed, 77 insertions(+), 63 deletions(-) diff --git a/docs/Analyzer Configuration.md b/docs/Analyzer Configuration.md index 0b6a0ae03c..7a5433b3db 100644 --- a/docs/Analyzer Configuration.md +++ b/docs/Analyzer Configuration.md @@ -133,7 +133,9 @@ Users can also provide a comma separated list of above option values. For exampl Option Name: `output_kind` -Configurable Rules: [CA2007](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007) +Configurable Rules: +[CA1515](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515), +[CA2007](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007) Option Values: One or more fields of enum [Microsoft.CodeAnalysis.CompilationOptions.OutputKind](https://learn.microsoft.com/dotnet/api/microsoft.codeanalysis.outputkind) as a comma separated list. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs index 197d96624a..91dc865da7 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternal.cs @@ -26,6 +26,9 @@ public abstract class MakeTypesInternal : DiagnosticAnalyzer isPortedFxCopRule: false, isDataflowRule: false); + private static readonly ImmutableHashSet DefaultOutputKinds = + ImmutableHashSet.Create(OutputKind.ConsoleApplication, OutputKind.WindowsApplication, OutputKind.WindowsRuntimeApplication); + public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); @@ -33,10 +36,8 @@ public override void Initialize(AnalysisContext context) 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)) + if (context.Compilation.SyntaxTrees.FirstOrDefault() is not { } firstSyntaxTree + || !context.Options.GetOutputKindsOption(Rule, firstSyntaxTree, compilation, DefaultOutputKinds).Contains(compilation.Options.OutputKind)) { return; } diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx index b7d7eb650f..8b34419a26 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx @@ -1297,10 +1297,10 @@ Make the public type internal - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal Consider making public types internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf index 1e1bb2b4b5..d63c86cbb6 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf index deccea62ae..24e2f15e50 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf index 3882e8c851..c4fe99845c 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf index 4db878d41f..e8431701fe 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf index 8fe45e1ea8..7766e82aae 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf index 6fa1f5303a..b58d93a6e3 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf index 6038e07a02..b62fe91d5f 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf index 083544e16b..ee98d90312 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf index adacdd0278..0122596824 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf index bbd828f8e0..2c1811f690 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf index 5850f72d36..497906cf68 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf index dcb4ef7046..b1d8af775a 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf index 467492f6f3..be2991b0b3 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf @@ -363,13 +363,13 @@ - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. - Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. + Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. - Since an application's code is typically not referenced publicly, types can be made internal - Since an application's code is typically not referenced publicly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal + Because an application's API isn't typically referenced from outside the assembly, types can be made internal diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md index 24e7d00819..146dc408da 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md @@ -926,7 +926,7 @@ An explicit length calculation can be error-prone and can be avoided when slicin ## [CA1515](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515): Consider making public types internal -Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal. +Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal. |Item|Value| |-|-| diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index 7caacc7db2..0e10ba0b36 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -129,7 +129,7 @@ "CA1515": { "id": "CA1515", "shortDescription": "Consider making public types internal", - "fullDescription": "Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal.", + "fullDescription": "Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal.", "defaultLevel": "warning", "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515", "properties": { @@ -6350,7 +6350,7 @@ "CA1515": { "id": "CA1515", "shortDescription": "Consider making public types internal", - "fullDescription": "Different than libraries, applications' members aren't typically referenced publicly, therefore types could be made internal.", + "fullDescription": "Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal.", "defaultLevel": "warning", "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515", "properties": { diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs index ec1cd45354..da107531b7 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/Maintainability/MakeTypesInternalTests.cs @@ -508,7 +508,9 @@ End Sub } [Theory] + [InlineData("DynamicallyLinkedLibrary", OutputKind.DynamicallyLinkedLibrary)] [InlineData("ConsoleApplication", OutputKind.ConsoleApplication)] + [InlineData("ConsoleApplication,DynamicallyLinkedLibrary", OutputKind.DynamicallyLinkedLibrary)] [InlineData("WindowsApplication", OutputKind.WindowsApplication)] [InlineData("WindowsRuntimeApplication", OutputKind.WindowsRuntimeApplication)] [InlineData("ConsoleApplication,WindowsApplication", OutputKind.WindowsApplication)] @@ -579,6 +581,7 @@ End Class [Theory] [InlineData("ConsoleApplication", OutputKind.DynamicallyLinkedLibrary)] + [InlineData("DynamicallyLinkedLibrary", OutputKind.ConsoleApplication)] [InlineData("WindowsApplication", OutputKind.ConsoleApplication)] [InlineData("WindowsRuntimeApplication", OutputKind.ConsoleApplication)] [InlineData("ConsoleApplication,WindowsApplication", OutputKind.WindowsRuntimeApplication)] diff --git a/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs b/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs index 6905b5e50d..c3fc07b0e8 100644 --- a/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs +++ b/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs @@ -95,7 +95,15 @@ public static ImmutableHashSet GetOutputKindsOption( DiagnosticDescriptor rule, SyntaxTree tree, Compilation compilation) - => options.GetNonFlagsEnumOptionValue(EditorConfigOptionNames.OutputKind, rule, tree, compilation, s_defaultOutputKinds); + => options.GetOutputKindsOption(rule, tree, compilation, s_defaultOutputKinds); + + public static ImmutableHashSet GetOutputKindsOption( + this AnalyzerOptions options, + DiagnosticDescriptor rule, + SyntaxTree tree, + Compilation compilation, + ImmutableHashSet defaultValue) + => options.GetNonFlagsEnumOptionValue(EditorConfigOptionNames.OutputKind, rule, tree, compilation, defaultValue); public static ImmutableHashSet GetAnalyzedSymbolKindsOption( this AnalyzerOptions options,