diff --git a/eng/Versions.props b/eng/Versions.props index d54f9ccc12..54e9a1bf1f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -45,7 +45,7 @@ 3.3.1 3.7.0 - 4.3.0-2.final + 4.4.0-2.22416.9 3.3.4-beta1.22418.3 5.0.4-preview1.21126.5 $(DogfoodAnalyzersVersion) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/StartActionWithNoRegisteredActionsRuleTests.cs b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/StartActionWithNoRegisteredActionsRuleTests.cs index b2963d9e6f..bfae9a6b26 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/StartActionWithNoRegisteredActionsRuleTests.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/StartActionWithNoRegisteredActionsRuleTests.cs @@ -260,70 +260,7 @@ private static void AnalyzeOperationBlock(OperationBlockAnalysisContext context) { } }"; - await new VerifyCS.Test - { - ReferenceAssemblies = ReferenceAssemblies.Default, - TestState = - { - Sources = { source }, - ExpectedDiagnostics = - { -#if !NETCOREAPP - // Test0.cs(3,26): error CS0234: The type or namespace name 'Immutable' does not exist in the namespace 'System.Collections' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(3, 26, 3, 35).WithArguments("Immutable", "System.Collections"), - // Test0.cs(4,17): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(4, 17, 4, 29).WithArguments("CodeAnalysis", "Microsoft"), - // Test0.cs(5,17): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(5, 17, 5, 29).WithArguments("CodeAnalysis", "Microsoft"), -#else - // Test0.cs(5,30): error CS0234: The type or namespace name 'Diagnostics' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(5, 30, 5, 41).WithArguments("Diagnostics", "Microsoft.CodeAnalysis"), -#endif - // Test0.cs(7,2): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzer"), - // Test0.cs(7,2): error CS0246: The type or namespace name 'DiagnosticAnalyzerAttribute' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzerAttribute"), - // Test0.cs(7,21): error CS0103: The name 'LanguageNames' does not exist in the current context - DiagnosticResult.CompilerError("CS0103").WithSpan(7, 21, 7, 34).WithArguments("LanguageNames"), - // Test0.cs(8,20): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(8, 20, 8, 38).WithArguments("DiagnosticAnalyzer"), -#if !NETCOREAPP - // Test0.cs(10,21): error CS0246: The type or namespace name 'ImmutableArray<>' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(10, 21, 10, 57).WithArguments("ImmutableArray<>"), -#endif - // Test0.cs(10,36): error CS0246: The type or namespace name 'DiagnosticDescriptor' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(10, 36, 10, 56).WithArguments("DiagnosticDescriptor"), - // Test0.cs(10,58): error CS0115: 'MyAnalyzer.SupportedDiagnostics': no suitable method found to override - DiagnosticResult.CompilerError("CS0115").WithSpan(10, 58, 10, 78).WithArguments("MyAnalyzer.SupportedDiagnostics"), - // Test0.cs(18,37): error CS0246: The type or namespace name 'AnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(18, 37, 18, 52).WithArguments("AnalysisContext"), - // Test0.cs(20,59): error CS0103: The name 'OperationKind' does not exist in the current context - DiagnosticResult.CompilerError("CS0103").WithSpan(20, 59, 20, 72).WithArguments("OperationKind"), - // Test0.cs(23,42): error CS0246: The type or namespace name 'OperationAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(23, 42, 23, 66).WithArguments("OperationAnalysisContext"), - // Test0.cs(28,2): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(28, 2, 28, 20).WithArguments("DiagnosticAnalyzer"), - // Test0.cs(28,2): error CS0246: The type or namespace name 'DiagnosticAnalyzerAttribute' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(28, 2, 28, 20).WithArguments("DiagnosticAnalyzerAttribute"), - // Test0.cs(28,21): error CS0103: The name 'LanguageNames' does not exist in the current context - DiagnosticResult.CompilerError("CS0103").WithSpan(28, 21, 28, 34).WithArguments("LanguageNames"), - // Test0.cs(29,21): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(29, 21, 29, 39).WithArguments("DiagnosticAnalyzer"), -#if !NETCOREAPP - // Test0.cs(31,21): error CS0246: The type or namespace name 'ImmutableArray<>' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(31, 21, 31, 57).WithArguments("ImmutableArray<>"), -#endif - // Test0.cs(31,36): error CS0246: The type or namespace name 'DiagnosticDescriptor' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(31, 36, 31, 56).WithArguments("DiagnosticDescriptor"), - // Test0.cs(31,58): error CS0115: 'MyAnalyzer2.SupportedDiagnostics': no suitable method found to override - DiagnosticResult.CompilerError("CS0115").WithSpan(31, 58, 31, 78).WithArguments("MyAnalyzer2.SupportedDiagnostics"), - // Test0.cs(39,37): error CS0246: The type or namespace name 'AnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(39, 37, 39, 52).WithArguments("AnalysisContext"), - // Test0.cs(44,47): error CS0246: The type or namespace name 'OperationBlockAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(44, 47, 44, 76).WithArguments("OperationBlockAnalysisContext") - }, - } - }.RunAsync(); + await VerifyCS.VerifyAnalyzerAsync(source); } [Fact] @@ -381,54 +318,7 @@ private static void AnalyzeOperationBlockStart(OperationBlockStartAnalysisContex } }"; - await new VerifyCS.Test - { - ReferenceAssemblies = ReferenceAssemblies.Default, - TestState = - { - Sources = { source }, - ExpectedDiagnostics = - { -#if !NETCOREAPP - // Test0.cs(3,26): error CS0234: The type or namespace name 'Immutable' does not exist in the namespace 'System.Collections' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(3, 26, 3, 35).WithArguments("Immutable", "System.Collections"), - // Test0.cs(4,17): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(4, 17, 4, 29).WithArguments("CodeAnalysis", "Microsoft"), - // Test0.cs(5,17): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(5, 17, 5, 29).WithArguments("CodeAnalysis", "Microsoft"), -#else - // Test0.cs(5,30): error CS0234: The type or namespace name 'Diagnostics' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) - DiagnosticResult.CompilerError("CS0234").WithSpan(5, 30, 5, 41).WithArguments("Diagnostics", "Microsoft.CodeAnalysis"), -#endif - // Test0.cs(7,2): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzer"), - // Test0.cs(7,2): error CS0246: The type or namespace name 'DiagnosticAnalyzerAttribute' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzerAttribute"), - // Test0.cs(7,21): error CS0103: The name 'LanguageNames' does not exist in the current context - DiagnosticResult.CompilerError("CS0103").WithSpan(7, 21, 7, 34).WithArguments("LanguageNames"), - // Test0.cs(8,20): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(8, 20, 8, 38).WithArguments("DiagnosticAnalyzer"), -#if !NETCOREAPP - // Test0.cs(10,21): error CS0246: The type or namespace name 'ImmutableArray<>' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(10, 21, 10, 57).WithArguments("ImmutableArray<>"), -#endif - // Test0.cs(10,36): error CS0246: The type or namespace name 'DiagnosticDescriptor' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(10, 36, 10, 56).WithArguments("DiagnosticDescriptor"), - // Test0.cs(10,58): error CS0115: 'MyAnalyzer.SupportedDiagnostics': no suitable method found to override - DiagnosticResult.CompilerError("CS0115").WithSpan(10, 58, 10, 78).WithArguments("MyAnalyzer.SupportedDiagnostics"), - // Test0.cs(18,37): error CS0246: The type or namespace name 'AnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(18, 37, 18, 52).WithArguments("AnalysisContext"), - // Test0.cs(39,42): error CS0246: The type or namespace name 'OperationAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(39, 42, 39, 66).WithArguments("OperationAnalysisContext"), - // Test0.cs(43,47): error CS0246: The type or namespace name 'OperationBlockAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(43, 47, 43, 76).WithArguments("OperationBlockAnalysisContext"), - // Test0.cs(47,52): error CS0246: The type or namespace name 'OperationBlockStartAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(47, 52, 47, 86).WithArguments("OperationBlockStartAnalysisContext"), - // Test0.cs(49,59): error CS0103: The name 'OperationKind' does not exist in the current context - DiagnosticResult.CompilerError("CS0103").WithSpan(49, 59, 49, 72).WithArguments("OperationKind"), - }, - }, - }.RunAsync(); + await VerifyCS.VerifyAnalyzerAsync(source); } [Fact] @@ -558,59 +448,7 @@ Private Shared Sub AnalyzeOperationBlock(context As OperationBlockAnalysisContex End Sub End Class "; - await new VerifyVB.Test - { - ReferenceAssemblies = ReferenceAssemblies.Default, - TestState = - { - Sources = { source }, - ExpectedDiagnostics = - { - // Test0.vb(7) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzer"), - // Test0.vb(7) : error BC30451: 'LanguageNames' is not declared. It may be inaccessible due to its protection level. - DiagnosticResult.CompilerError("BC30451").WithSpan(7, 21, 7, 34).WithArguments("LanguageNames"), - // Test0.vb(9) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(9, 11, 9, 29).WithArguments("DiagnosticAnalyzer"), - // Test0.vb(10) : error BC30284: property 'SupportedDiagnostics' cannot be declared 'Overrides' because it does not override a property in a base class. - DiagnosticResult.CompilerError("BC30284").WithSpan(10, 37, 10, 57).WithArguments("property", "SupportedDiagnostics"), -#if !NETCOREAPP - // Test0.vb(10) : error BC30002: Type 'ImmutableArray' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(10, 63, 10, 102).WithArguments("ImmutableArray"), -#endif - // Test0.vb(10) : error BC30002: Type 'DiagnosticDescriptor' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(10, 81, 10, 101).WithArguments("DiagnosticDescriptor"), - // Test0.vb(16) : error BC30284: sub 'Initialize' cannot be declared 'Overrides' because it does not override a sub in a base class. - DiagnosticResult.CompilerError("BC30284").WithSpan(16, 23, 16, 33).WithArguments("sub", "Initialize"), - // Test0.vb(16) : error BC30002: Type 'AnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(16, 45, 16, 60).WithArguments("AnalysisContext"), - // Test0.vb(17) : error BC30451: 'OperationKind' is not declared. It may be inaccessible due to its protection level. - DiagnosticResult.CompilerError("BC30451").WithSpan(17, 63, 17, 76).WithArguments("OperationKind"), - // Test0.vb(20) : error BC30002: Type 'OperationAnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(20, 49, 20, 73).WithArguments("OperationAnalysisContext"), - // Test0.vb(24) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(24, 2, 24, 20).WithArguments("DiagnosticAnalyzer"), - // Test0.vb(24) : error BC30451: 'LanguageNames' is not declared. It may be inaccessible due to its protection level. - DiagnosticResult.CompilerError("BC30451").WithSpan(24, 21, 24, 34).WithArguments("LanguageNames"), - // Test0.vb(26) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(26, 11, 26, 29).WithArguments("DiagnosticAnalyzer"), - // Test0.vb(27) : error BC30284: property 'SupportedDiagnostics' cannot be declared 'Overrides' because it does not override a property in a base class. - DiagnosticResult.CompilerError("BC30284").WithSpan(27, 37, 27, 57).WithArguments("property", "SupportedDiagnostics"), -#if !NETCOREAPP - // Test0.vb(27) : error BC30002: Type 'ImmutableArray' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(27, 63, 27, 102).WithArguments("ImmutableArray"), -#endif - // Test0.vb(27) : error BC30002: Type 'DiagnosticDescriptor' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(27, 81, 27, 101).WithArguments("DiagnosticDescriptor"), - // Test0.vb(33) : error BC30284: sub 'Initialize' cannot be declared 'Overrides' because it does not override a sub in a base class. - DiagnosticResult.CompilerError("BC30284").WithSpan(33, 23, 33, 33).WithArguments("sub", "Initialize"), - // Test0.vb(33) : error BC30002: Type 'AnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(33, 45, 33, 60).WithArguments("AnalysisContext"), - // Test0.vb(37) : error BC30002: Type 'OperationBlockAnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(37, 54, 37, 83).WithArguments("OperationBlockAnalysisContext") - }, - }, - }.RunAsync(); + await VerifyVB.VerifyAnalyzerAsync(source); } [Fact] @@ -659,43 +497,7 @@ End Sub End Class "; - await new VerifyVB.Test - { - ReferenceAssemblies = ReferenceAssemblies.Default, - TestState = - { - Sources = { source }, - ExpectedDiagnostics = - { - // Test0.vb(7) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzer"), - // Test0.vb(7) : error BC30451: 'LanguageNames' is not declared. It may be inaccessible due to its protection level. - DiagnosticResult.CompilerError("BC30451").WithSpan(7, 21, 7, 34).WithArguments("LanguageNames"), - // Test0.vb(9) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(9, 11, 9, 29).WithArguments("DiagnosticAnalyzer"), - // Test0.vb(10) : error BC30284: property 'SupportedDiagnostics' cannot be declared 'Overrides' because it does not override a property in a base class. - DiagnosticResult.CompilerError("BC30284").WithSpan(10, 37, 10, 57).WithArguments("property", "SupportedDiagnostics"), -#if !NETCOREAPP - // Test0.vb(10) : error BC30002: Type 'ImmutableArray' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(10, 63, 10, 102).WithArguments("ImmutableArray"), -#endif - // Test0.vb(10) : error BC30002: Type 'DiagnosticDescriptor' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(10, 81, 10, 101).WithArguments("DiagnosticDescriptor"), - // Test0.vb(16) : error BC30284: sub 'Initialize' cannot be declared 'Overrides' because it does not override a sub in a base class. - DiagnosticResult.CompilerError("BC30284").WithSpan(16, 23, 16, 33).WithArguments("sub", "Initialize"), - // Test0.vb(16) : error BC30002: Type 'AnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(16, 45, 16, 60).WithArguments("AnalysisContext"), - // Test0.vb(32) : error BC30002: Type 'OperationAnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(32, 49, 32, 73).WithArguments("OperationAnalysisContext"), - // Test0.vb(35) : error BC30002: Type 'OperationBlockAnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(35, 54, 35, 83).WithArguments("OperationBlockAnalysisContext"), - // Test0.vb(38) : error BC30002: Type 'OperationBlockStartAnalysisContext' is not defined. - DiagnosticResult.CompilerError("BC30002").WithSpan(38, 59, 38, 93).WithArguments("OperationBlockStartAnalysisContext"), - // Test0.vb(39) : error BC30451: 'OperationKind' is not declared. It may be inaccessible due to its protection level. - DiagnosticResult.CompilerError("BC30451").WithSpan(39, 63, 39, 76).WithArguments("OperationKind") - }, - } - }.RunAsync(); + await VerifyVB.VerifyAnalyzerAsync(source); } private static DiagnosticResult GetCSharpExpectedDiagnostic(int line, int column, string parameterName, StartActionKind kind) => diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs index 68079a2010..eeb9e88ee1 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs @@ -4,6 +4,7 @@ using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; +using Analyzer.Utilities.Lightup; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; @@ -532,7 +533,7 @@ private bool ValidateOperations(ImmutableArray operations) { foreach (IOperation operation in operations) { - if (!operation.IsImplicit && !ValidateOperation(operation)) + if (!operation.IsImplicit && operation.Kind != OperationKindEx.Attribute && !ValidateOperation(operation)) { return false; } @@ -660,7 +661,7 @@ private bool ValidateOperations(ImmutableArray operations) // call to the base finalizer in the finally section. We need to validate the contents // of the try block // Also analyze the implicit expression statement created for expression bodied implementation. - var shouldAnalyze = !operation.IsImplicit || operation.Kind == OperationKind.Try || operation.Kind == OperationKind.ExpressionStatement; + var shouldAnalyze = (!operation.IsImplicit && operation.Kind != OperationKindEx.Attribute) || operation.Kind == OperationKind.Try || operation.Kind == OperationKind.ExpressionStatement; if (shouldAnalyze && !ValidateOperation(operation)) { return false; diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocations.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocations.cs index 4e15b77896..4d4ab2ac6c 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocations.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocations.cs @@ -66,13 +66,13 @@ private void AnalyzeOperation(OperationAnalysisContext context, IMethodSymbol ar AnalyzeOperation(context, arrayEmptyMethodSymbol, IsAttributeSyntax); } - private static void AnalyzeOperation(OperationAnalysisContext context, IMethodSymbol arrayEmptyMethodSymbol, Func isAttributeSytnax) + private static void AnalyzeOperation(OperationAnalysisContext context, IMethodSymbol arrayEmptyMethodSymbol, Func isAttributeSyntax) { IArrayCreationOperation arrayCreationExpression = (IArrayCreationOperation)context.Operation; // We can't replace array allocations in attributes, as they're persisted to metadata // TODO: Once we have operation walkers, we can replace this syntactic check with an operation-based check. - if (arrayCreationExpression.Syntax.Ancestors().Any(isAttributeSytnax)) + if (arrayCreationExpression.Syntax.AncestorsAndSelf().Any(isAttributeSyntax)) { return; } diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureAnalyzer.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureAnalyzer.cs index 6d0df2c9eb..3d92e3e30d 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureAnalyzer.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureAnalyzer.cs @@ -417,11 +417,6 @@ private void ProcessTypeSymbolAttributes(SymbolAnalysisContext context, } } - if (ProcessTypeAttributeForPreviewness(symbol, requiresPreviewFeaturesSymbols, previewFeatureAttributeSymbol, out SyntaxReference? attributeSyntaxReference, out string? attributeName, out ISymbol? previewAttributeSymbol)) - { - ReportDiagnosticWithCustomMessageIfItExists(context, attributeSyntaxReference.GetSyntax(context.CancellationToken), previewAttributeSymbol, requiresPreviewFeaturesSymbols, GeneralPreviewFeatureAttributeRule, GeneralPreviewFeatureAttributeRuleWithCustomMessage, attributeName); - } - INamedTypeSymbol? baseType = symbol.BaseType; if (baseType != null) { @@ -440,40 +435,6 @@ private void ProcessTypeSymbolAttributes(SymbolAnalysisContext context, } } - private static bool ProcessTypeAttributeForPreviewness(ISymbol symbol, - ConcurrentDictionary requiresPreviewFeaturesSymbols, - INamedTypeSymbol previewFeatureAttribute, - [NotNullWhen(true)] out SyntaxReference? attributeSyntaxReference, - [NotNullWhen(true)] out string? attributeName, - [NotNullWhen(true)] out ISymbol? previewSymbol) - { - ImmutableArray attributes = symbol.GetAttributes(); - for (int i = 0; i < attributes.Length; i++) - { - AttributeData attribute = attributes[i]; - if (SymbolIsAnnotatedAsPreview(attribute.AttributeClass, requiresPreviewFeaturesSymbols, previewFeatureAttribute)) - { - attributeName = attribute.AttributeClass.Name; - attributeSyntaxReference = attribute.ApplicationSyntaxReference; - previewSymbol = attribute.AttributeClass; - return true; - } - - if (SymbolIsAnnotatedAsPreview(attribute.AttributeConstructor, requiresPreviewFeaturesSymbols, previewFeatureAttribute)) - { - attributeName = attribute.AttributeClass.Name; - attributeSyntaxReference = attribute.ApplicationSyntaxReference; - previewSymbol = attribute.AttributeConstructor; - return true; - } - } - - attributeName = null; - attributeSyntaxReference = null; - previewSymbol = null; - return false; - } - private SyntaxNode? GetPreviewSyntaxNodeFromSymbols(ISymbol symbol, ISymbol previewType) { @@ -985,32 +946,6 @@ private static void ReportDiagnosticWithCustomMessageIfItExists(SymbolAnalysisCo } } - private static void ReportDiagnosticWithCustomMessageIfItExists(SymbolAnalysisContext context, - SyntaxNode node, - ISymbol previewSymbol, - ConcurrentDictionary requiresPreviewFeaturesSymbols, - DiagnosticDescriptor diagnosticDescriptor, - DiagnosticDescriptor diagnosticDescriptorWithPlaceholdersForCustomMessage, - string diagnosticMessageArgument0) - { - if (!requiresPreviewFeaturesSymbols.TryGetValue(previewSymbol, out (bool isPreview, string? message, string? url) existing)) - { - Debug.Fail($"Should never reach this line. This means the symbol {previewSymbol.Name} was not processed in this analyzer"); - } - else - { - string url = existing.url ?? DefaultURL; - if (existing.message is string customMessage) - { - context.ReportDiagnostic(node.CreateDiagnostic(diagnosticDescriptorWithPlaceholdersForCustomMessage, diagnosticMessageArgument0, url, customMessage)); - } - else - { - context.ReportDiagnostic(node.CreateDiagnostic(diagnosticDescriptor, diagnosticMessageArgument0, url)); - } - } - } - private static void ReportDiagnosticWithCustomMessageIfItExists(SymbolAnalysisContext context, ISymbol previewSymbol, ISymbol symbolToRaiseDiagnosticOn, diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocationsTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocationsTests.cs index 2971810125..ab01eccdce 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocationsTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/AvoidZeroLengthArrayAllocationsTests.cs @@ -422,6 +422,29 @@ class C await VerifyCS.VerifyAnalyzerAsync(source); } + [Fact] + public async Task EmptyArrayCSharp_UsedInAttributeParams_NoDiagnosticsAsync() + { + const string source = @" +using System; + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class CustomAttribute : Attribute +{ + public CustomAttribute(params int[] i) + { + } +} + +[Custom(new int[0])] +[Custom] +class C +{ +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + [WorkItem(1298, "https://github.com/dotnet/roslyn-analyzers/issues/1298")] [Fact] public async Task EmptyArrayCSharp_FieldOrPropertyInitializerAsync() diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureUnitTests.Misc.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureUnitTests.Misc.cs index a8a0a980f7..b3fea0791d 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureUnitTests.Misc.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureUnitTests.Misc.cs @@ -515,7 +515,7 @@ class MyAttribute : Attribute await test.RunAsync(); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn-analyzers/issues/6134")] public async Task TestCustomAttribute() { var csInput = @" @@ -803,4 +803,4 @@ End Module await testVb.RunAsync(); } } -} \ No newline at end of file +} diff --git a/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs b/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs index a13df4a6cb..b222d6e891 100644 --- a/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs +++ b/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Immutable; using System.Linq; +using Analyzer.Utilities.Lightup; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; @@ -99,7 +100,7 @@ public static ComputationalComplexityMetrics Compute(IOperation operationBlock) ImmutableHashSet.Builder? distinctReferencedConstantsBuilder = null; // Explicit user applied attribute. - if (operationBlock.Kind == OperationKind.None && + if ((operationBlock.Kind is OperationKind.None or OperationKindEx.Attribute) && hasAnyExplicitExpression(operationBlock)) { executableLinesOfCode += 1; @@ -318,8 +319,8 @@ static int getExecutableLinesOfCode(IOperation operation, ref bool hasSymbolInit static bool hasAnyExplicitExpression(IOperation operation) { - // Check if all descendants are either implicit or are explicit non-branch operations with no constant value or type, indicating it is not user written code. - return !operation.DescendantsAndSelf().All(o => o.IsImplicit || (!o.ConstantValue.HasValue && o.Type == null && o.Kind != OperationKind.Branch)); + // Check if all descendants are either implicit or are explicit non-branch, non-attribute operations with no constant value or type, indicating it is not user written code. + return !operation.DescendantsAndSelf().All(o => o.IsImplicit || (!o.ConstantValue.HasValue && o.Type == null && o.Kind is not (OperationKind.Branch or OperationKindEx.Attribute))); } void countOperator(IOperation operation) diff --git a/src/Utilities/Compiler/CodeMetrics/MetricsHelper.cs b/src/Utilities/Compiler/CodeMetrics/MetricsHelper.cs index 69d2bde34b..39e4802591 100644 --- a/src/Utilities/Compiler/CodeMetrics/MetricsHelper.cs +++ b/src/Utilities/Compiler/CodeMetrics/MetricsHelper.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Threading.Tasks; using Analyzer.Utilities; +using Analyzer.Utilities.Lightup; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis.Operations; @@ -219,6 +220,7 @@ internal static async Task GetTopmostSyntaxNodeForDeclarationAsync(S cyclomaticComplexity += 1; break; + case OperationKindEx.Attribute: case OperationKind.None: // Skip non-applicable attributes. if (!applicableAttributeNodes.Contains(node)) diff --git a/src/Utilities/Compiler/Extensions/IOperationExtensions.cs b/src/Utilities/Compiler/Extensions/IOperationExtensions.cs index 421e031511..cea424e88e 100644 --- a/src/Utilities/Compiler/Extensions/IOperationExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IOperationExtensions.cs @@ -10,6 +10,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; +using Analyzer.Utilities.Lightup; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis; @@ -463,10 +464,10 @@ public static bool TryGetEnclosingControlFlowGraph(this IOperation operation, [N return null; default: - // Attribute blocks have OperationKind.None, but ControlFlowGraph.Create does not - // have an overload for such operation roots. + // Attribute blocks have OperationKind.None (prior to IAttributeOperation support) or + // OperationKind.Attribute, but we do not support flow analysis for attributes. // Gracefully return null for this case and fire an assert for any other OperationKind. - Debug.Assert(operation.Kind == OperationKind.None, $"Unexpected root operation kind: {operation.Kind}"); + Debug.Assert(operation.Kind is OperationKind.None or OperationKindEx.Attribute, $"Unexpected root operation kind: {operation.Kind}"); return null; } } diff --git a/src/Utilities/Compiler/Lightup/OperationKindEx.cs b/src/Utilities/Compiler/Lightup/OperationKindEx.cs index 75bda287ff..83187189d8 100644 --- a/src/Utilities/Compiler/Lightup/OperationKindEx.cs +++ b/src/Utilities/Compiler/Lightup/OperationKindEx.cs @@ -11,6 +11,7 @@ internal static class OperationKindEx public const OperationKind UsingDeclaration = (OperationKind)0x6c; public const OperationKind FunctionPointerInvocation = (OperationKind)0x78; public const OperationKind ImplicitIndexerReference = (OperationKind)0x7b; + public const OperationKind Attribute = (OperationKind)0x7d; } } diff --git a/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs b/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs index 97d42a9eb4..f4bd17679a 100644 --- a/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs +++ b/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Analyzer.Utilities.Extensions; +using Analyzer.Utilities.Lightup; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.CodeAnalysis.FlowAnalysis @@ -38,11 +39,10 @@ internal static bool SupportsFlowAnalysis(this ControlFlowGraph cfg) { // Skip flow analysis for following root operation blocks: // 1. Null root operation (error case) - // 2. OperationKind.None (used for attributes). + // 2. OperationKindEx.Attribute or OperationKind.None (used for attributes before IAttributeOperation support). // 3. OperationKind.ParameterInitialzer (default parameter values). if (cfg.OriginalOperation == null || - cfg.OriginalOperation.Kind == OperationKind.None || - cfg.OriginalOperation.Kind == OperationKind.ParameterInitializer) + cfg.OriginalOperation.Kind is OperationKindEx.Attribute or OperationKind.None or OperationKind.ParameterInitializer) { return false; }