From afd83a54fe09a63805c877c6016c88fe4d2ada84 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Sun, 11 Jun 2023 21:58:45 +0200 Subject: [PATCH 01/30] Suggest CA2007 for await foreach without specified cancellation. --- .../CSharpDoNotDirectlyAwaitATask.cs | 31 +++++++ .../DoNotDirectlyAwaitATask.cs | 20 ++++- .../DoNotDirectlyAwaitATaskTests.cs | 83 ++++++++++++++++++- src/Utilities/Compiler/WellKnownTypeNames.cs | 1 + 4 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs new file mode 100644 index 0000000000..8bd2b8afeb --- /dev/null +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using Analyzer.Utilities.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; +using Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines; + +namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public sealed class CSharpDoNotDirectlyAwaitATask : DoNotDirectlyAwaitATaskAnalyzer + { + public override (Action Analysis, OperationKind OperationKind) AnalyzeAwaitForEachLoopOperation(INamedTypeSymbol configuredAsyncEnumerable) + { + return (ctx => AnalyzeAwaitForEachLoopOperation(ctx, configuredAsyncEnumerable), OperationKind.Loop); + } + + private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) + { + if (context.Operation is IForEachLoopOperation {Syntax: ForEachStatementSyntax {AwaitKeyword.RawKind: not (int)SyntaxKind.None}} forEachOperation + && !forEachOperation.Collection.Type.OriginalDefinition.Equals(configuredAsyncEnumerable, SymbolEqualityComparer.Default)) + { + context.ReportDiagnostic(forEachOperation.Collection.Syntax.CreateDiagnostic(Rule)); + } + } + } +} \ No newline at end of file diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs index 16900225d1..4a6544422c 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.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.Collections.Immutable; using System.Linq; using Analyzer.Utilities; @@ -16,8 +17,8 @@ namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines /// /// CA2007: /// - [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public sealed class DoNotDirectlyAwaitATaskAnalyzer : DiagnosticAnalyzer + [DiagnosticAnalyzer(LanguageNames.VisualBasic)] + public class DoNotDirectlyAwaitATaskAnalyzer : DiagnosticAnalyzer { internal const string RuleId = "CA2007"; @@ -52,7 +53,9 @@ public override void Initialize(AnalysisContext context) return; } - var configuredAsyncDisposable = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeCompilerServicesConfiguredAsyncDisposable); + var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); + var configuredAsyncDisposable = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeCompilerServicesConfiguredAsyncDisposable); + var configuredAsyncEnumerable = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeCompilerServicesConfiguredCancelableAsyncEnumerable); context.RegisterOperationBlockStartAction(context => { @@ -77,11 +80,22 @@ public override void Initialize(AnalysisContext context) context.RegisterOperationAction(context => AnalyzeUsingOperation(context, configuredAsyncDisposable), OperationKind.Using); context.RegisterOperationAction(context => AnalyzeUsingDeclarationOperation(context, configuredAsyncDisposable), OperationKindEx.UsingDeclaration); } + + if (configuredAsyncEnumerable is not null) + { + var (analysis, operationKind) = AnalyzeAwaitForEachLoopOperation(configuredAsyncEnumerable); + context.RegisterOperationAction(analysis, operationKind); + } } }); }); } + public virtual (Action Analysis, OperationKind OperationKind) AnalyzeAwaitForEachLoopOperation(INamedTypeSymbol configuredAsyncEnumerable) + { + return (_ => { }, OperationKind.None); + } + private static void AnalyzeAwaitOperation(OperationAnalysisContext context, ImmutableArray taskTypes) { var awaitExpression = (IAwaitOperation)context.Operation; diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs index 65ff231094..ae6c345a83 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs @@ -7,7 +7,7 @@ using Xunit; using CSharpLanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion; using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< - Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskAnalyzer, + Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines.CSharpDoNotDirectlyAwaitATask, Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskFixer>; using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskAnalyzer, @@ -741,5 +741,86 @@ async Task CoreAsync() await VerifyCS.VerifyCodeFixAsync(code, fixedCode); } + + [Fact, WorkItem(6652, "https://github.com/dotnet/roslyn-analyzers/issues/6652")] + public Task CsharpAwaitIAsyncEnumerable_DiagnosticAsync() + { + return new VerifyCS.Test + { + TestCode = @" +using System.Collections.Generic; +using System.Threading.Tasks; + +public class C +{ + public async Task Test(IAsyncEnumerable enumerable) + { + await foreach(var i in [|enumerable|]) + { + } + } +}", + FixedCode = @" +using System.Collections.Generic; +using System.Threading.Tasks; + +public class C +{ + public async Task Test(IAsyncEnumerable enumerable) + { + await foreach(var i in enumerable.ConfigureAwait(false)) + { + } + } +}", + LanguageVersion = CSharpLanguageVersion.CSharp8 + }.RunAsync(); + } + + [Theory, WorkItem(6652, "https://github.com/dotnet/roslyn-analyzers/issues/6652")] + [InlineData("true")] + [InlineData("false")] + public Task CsharpAwaitIAsyncEnumerable_NoDiagnosticAsync(string continueOnCapturedContext) + { + return new VerifyCS.Test + { + TestCode = @$" +using System.Collections.Generic; +using System.Threading.Tasks; + +public class C +{{ + public async Task Test(IAsyncEnumerable enumerable) + {{ + await foreach(var i in enumerable.ConfigureAwait({continueOnCapturedContext})) + {{ + }} + }} +}}", + LanguageVersion = CSharpLanguageVersion.CSharp8 + }.RunAsync(); + } + + [Fact, WorkItem(6652, "https://github.com/dotnet/roslyn-analyzers/issues/6652")] + public Task CsharpForEachEnumerable_NoDiagnosticAsync() + { + return new VerifyCS.Test + { + TestCode = @" +using System.Collections.Generic; +using System.Threading.Tasks; + +public class C +{ + public void Test(IEnumerable enumerable) + { + foreach(var i in enumerable) + { + } + } +}", + LanguageVersion = CSharpLanguageVersion.CSharp8 + }.RunAsync(); + } } } \ No newline at end of file diff --git a/src/Utilities/Compiler/WellKnownTypeNames.cs b/src/Utilities/Compiler/WellKnownTypeNames.cs index bd800d4ee3..39a285c075 100644 --- a/src/Utilities/Compiler/WellKnownTypeNames.cs +++ b/src/Utilities/Compiler/WellKnownTypeNames.cs @@ -298,6 +298,7 @@ internal static class WellKnownTypeNames public const string SystemRuntimeCompilerServicesCallerArgumentExpressionAttribute = "System.Runtime.CompilerServices.CallerArgumentExpressionAttribute"; public const string SystemRuntimeCompilerServicesCompilerGeneratedAttribute = "System.Runtime.CompilerServices.CompilerGeneratedAttribute"; public const string SystemRuntimeCompilerServicesConfiguredAsyncDisposable = "System.Runtime.CompilerServices.ConfiguredAsyncDisposable"; + public const string SystemRuntimeCompilerServicesConfiguredCancelableAsyncEnumerable = "System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1"; public const string SystemRuntimeCompilerServicesConfiguredValueTaskAwaitable1 = "System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1"; public const string SystemRuntimeCompilerServicesDisableRuntimeMarshallingAttribute = "System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute"; public const string SystemRuntimeCompilerServicesICriticalNotifyCompletion = "System.Runtime.CompilerServices.ICriticalNotifyCompletion"; From 97c69a20995ccbafa575614c2709236107a0df77 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 20 Jun 2023 18:46:41 +0200 Subject: [PATCH 02/30] PR comments. --- .../CSharpDoNotDirectlyAwaitATask.cs | 6 ++--- .../DoNotDirectlyAwaitATask.cs | 25 +++++++++---------- .../DoNotDirectlyAwaitATaskTests.cs | 12 ++++----- .../BasicDoNotDirectlyAwaitATask.vb | 11 ++++++++ 4 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs index 8bd2b8afeb..733f1dec3c 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs @@ -14,9 +14,9 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class CSharpDoNotDirectlyAwaitATask : DoNotDirectlyAwaitATaskAnalyzer { - public override (Action Analysis, OperationKind OperationKind) AnalyzeAwaitForEachLoopOperation(INamedTypeSymbol configuredAsyncEnumerable) + protected override void RegisterLanguageSpecificChecks(OperationBlockStartAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) { - return (ctx => AnalyzeAwaitForEachLoopOperation(ctx, configuredAsyncEnumerable), OperationKind.Loop); + context.RegisterOperationAction(ctx => AnalyzeAwaitForEachLoopOperation(ctx, configuredAsyncEnumerable), OperationKind.Loop); } private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) @@ -24,7 +24,7 @@ private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext co if (context.Operation is IForEachLoopOperation {Syntax: ForEachStatementSyntax {AwaitKeyword.RawKind: not (int)SyntaxKind.None}} forEachOperation && !forEachOperation.Collection.Type.OriginalDefinition.Equals(configuredAsyncEnumerable, SymbolEqualityComparer.Default)) { - context.ReportDiagnostic(forEachOperation.Collection.Syntax.CreateDiagnostic(Rule)); + context.ReportDiagnostic(forEachOperation.Collection.CreateDiagnostic(Rule)); } } } diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs index 4a6544422c..b76612ddaa 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs @@ -17,8 +17,7 @@ namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines /// /// CA2007: /// - [DiagnosticAnalyzer(LanguageNames.VisualBasic)] - public class DoNotDirectlyAwaitATaskAnalyzer : DiagnosticAnalyzer + public abstract class DoNotDirectlyAwaitATaskAnalyzer : DiagnosticAnalyzer { internal const string RuleId = "CA2007"; @@ -48,12 +47,12 @@ public override void Initialize(AnalysisContext context) return; } - if (!TryGetTaskTypes(context.Compilation, out ImmutableArray taskTypes)) + var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); + if (!TryGetTaskTypes(wellKnownTypeProvider, out ImmutableArray taskTypes)) { return; } - var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); var configuredAsyncDisposable = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeCompilerServicesConfiguredAsyncDisposable); var configuredAsyncEnumerable = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeCompilerServicesConfiguredCancelableAsyncEnumerable); @@ -83,17 +82,17 @@ public override void Initialize(AnalysisContext context) if (configuredAsyncEnumerable is not null) { - var (analysis, operationKind) = AnalyzeAwaitForEachLoopOperation(configuredAsyncEnumerable); - context.RegisterOperationAction(analysis, operationKind); + RegisterLanguageSpecificChecks(context, configuredAsyncEnumerable); } } }); }); } - public virtual (Action Analysis, OperationKind OperationKind) AnalyzeAwaitForEachLoopOperation(INamedTypeSymbol configuredAsyncEnumerable) +#pragma warning disable RS1012 + protected virtual void RegisterLanguageSpecificChecks(OperationBlockStartAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) +#pragma warning restore RS1012 { - return (_ => { }, OperationKind.None); } private static void AnalyzeAwaitOperation(OperationAnalysisContext context, ImmutableArray taskTypes) @@ -153,10 +152,10 @@ private static void AnalyzeUsingDeclarationOperation(OperationAnalysisContext co } } - private static bool TryGetTaskTypes(Compilation compilation, out ImmutableArray taskTypes) + private static bool TryGetTaskTypes(WellKnownTypeProvider typeProvider, out ImmutableArray taskTypes) { - INamedTypeSymbol? taskType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); - INamedTypeSymbol? taskOfTType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask1); + INamedTypeSymbol? taskType = typeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); + INamedTypeSymbol? taskOfTType = typeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask1); if (taskType == null || taskOfTType == null) { @@ -164,8 +163,8 @@ private static bool TryGetTaskTypes(Compilation compilation, out ImmutableArray< return false; } - INamedTypeSymbol? valueTaskType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksValueTask); - INamedTypeSymbol? valueTaskOfTType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksValueTask1); + INamedTypeSymbol? valueTaskType = typeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksValueTask); + INamedTypeSymbol? valueTaskOfTType = typeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksValueTask1); taskTypes = valueTaskType != null && valueTaskOfTType != null ? ImmutableArray.Create(taskType, taskOfTType, valueTaskType, valueTaskOfTType) : diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs index ae6c345a83..25b5179c15 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs @@ -5,12 +5,12 @@ using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; -using CSharpLanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion; +using Microsoft.CodeAnalysis.CSharp; using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines.CSharpDoNotDirectlyAwaitATask, Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskFixer>; using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< - Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskAnalyzer, + Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines.BasicDoNotDirectlyAwaitATask, Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskFixer>; namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.UnitTests @@ -174,7 +174,7 @@ public async Task M4() { ReferenceAssemblies = ReferenceAssemblies.Default.AddPackages( ImmutableArray.Create(new PackageIdentity("Microsoft.Bcl.AsyncInterfaces", "5.0.0"))), - LanguageVersion = CSharpLanguageVersion.CSharp8, + LanguageVersion = LanguageVersion.CSharp8, TestCode = code, FixedCode = fixedCode, }.RunAsync(); @@ -773,7 +773,7 @@ public async Task Test(IAsyncEnumerable enumerable) } } }", - LanguageVersion = CSharpLanguageVersion.CSharp8 + LanguageVersion = LanguageVersion.CSharp8 }.RunAsync(); } @@ -797,7 +797,7 @@ public async Task Test(IAsyncEnumerable enumerable) }} }} }}", - LanguageVersion = CSharpLanguageVersion.CSharp8 + LanguageVersion = LanguageVersion.CSharp8 }.RunAsync(); } @@ -819,7 +819,7 @@ public void Test(IEnumerable enumerable) } } }", - LanguageVersion = CSharpLanguageVersion.CSharp8 + LanguageVersion = LanguageVersion.CSharp8 }.RunAsync(); } } diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb new file mode 100644 index 0000000000..b608dcd576 --- /dev/null +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb @@ -0,0 +1,11 @@ +Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines + +Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines + + + Public NotInheritable Class BasicDoNotDirectlyAwaitATask + Inherits DoNotDirectlyAwaitATaskAnalyzer + End Class +End Namespace \ No newline at end of file From 30dbd891577c41338c19dade6e872ac82e5e3888 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Fri, 23 Jun 2023 18:45:03 +0200 Subject: [PATCH 03/30] PR fixes. --- .../RulesMissingDocumentation.md | 2 - .../CSharpDoNotDirectlyAwaitATask.cs | 3 +- .../Microsoft.CodeAnalysis.NetAnalyzers.sarif | 58 ++++++++++++------- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md index 9a86eec801..c82804252c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md @@ -23,7 +23,6 @@ RS1018 | | DiagnosticId for analyzers must be in specified format | RS1019 | | DiagnosticId must be unique across analyzers | RS1020 | | Category for analyzers must be from the specified values | RS1021 | | Invalid entry in analyzer category and diagnostic ID range specification file | -RS1022 | | Do not use types from Workspaces assembly in an analyzer | RS1024 | | Symbols should be compared for equality | RS1025 | | Configure generated code analysis | RS1026 | | Enable concurrent execution | @@ -38,4 +37,3 @@ RS1034 | | Prefer 'IsKind' for checking syntax kinds | RS1035 | | Do not use APIs banned for analyzers | RS1036 | | Specify analyzer banned API enforcement setting | RS1037 | | Add "CompilationEnd" custom tag to compilation end diagnostic descriptor | -RS1038 | | Compiler extensions should be implemented in assemblies with compiler-provided references | diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs index 733f1dec3c..d622717c29 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. -using System; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -21,7 +20,7 @@ protected override void RegisterLanguageSpecificChecks(OperationBlockStartAnalys private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) { - if (context.Operation is IForEachLoopOperation {Syntax: ForEachStatementSyntax {AwaitKeyword.RawKind: not (int)SyntaxKind.None}} forEachOperation + if (context.Operation is IForEachLoopOperation { Syntax: ForEachStatementSyntax { AwaitKeyword.RawKind: not (int)SyntaxKind.None } } forEachOperation && !forEachOperation.Collection.Type.OriginalDefinition.Equals(configuredAsyncEnumerable, SymbolEqualityComparer.Default)) { context.ReportDiagnostic(forEachOperation.Collection.CreateDiagnostic(Rule)); diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index f767562783..ac89c722e8 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -342,6 +342,25 @@ ] } }, + "CA2007": { + "id": "CA2007", + "shortDescription": "Consider calling ConfigureAwait on the awaited task", + "fullDescription": "When an asynchronous method awaits a Task directly, continuation occurs in the same thread that created the task. Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. Call ConfigureAwait(false) on the task to schedule continuations to the thread pool, thereby avoiding a deadlock on the UI thread. Passing false is a good option for app-independent libraries. Calling ConfigureAwait(true) on the task has the same behavior as not explicitly calling ConfigureAwait. By explicitly calling this method, you're letting readers know you intentionally want to perform the continuation on the original synchronization context.", + "defaultLevel": "warning", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007", + "properties": { + "category": "Reliability", + "isEnabledByDefault": false, + "typeName": "CSharpDoNotDirectlyAwaitATask", + "languages": [ + "C#" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA2014": { "id": "CA2014", "shortDescription": "Do not use stackalloc in loops", @@ -3218,26 +3237,6 @@ ] } }, - "CA2007": { - "id": "CA2007", - "shortDescription": "Consider calling ConfigureAwait on the awaited task", - "fullDescription": "When an asynchronous method awaits a Task directly, continuation occurs in the same thread that created the task. Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. Call ConfigureAwait(false) on the task to schedule continuations to the thread pool, thereby avoiding a deadlock on the UI thread. Passing false is a good option for app-independent libraries. Calling ConfigureAwait(true) on the task has the same behavior as not explicitly calling ConfigureAwait. By explicitly calling this method, you're letting readers know you intentionally want to perform the continuation on the original synchronization context.", - "defaultLevel": "warning", - "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007", - "properties": { - "category": "Reliability", - "isEnabledByDefault": false, - "typeName": "DoNotDirectlyAwaitATaskAnalyzer", - "languages": [ - "C#", - "Visual Basic" - ], - "tags": [ - "Telemetry", - "EnabledRuleInAggressiveMode" - ] - } - }, "CA2008": { "id": "CA2008", "shortDescription": "Do not create tasks without passing a TaskScheduler", @@ -6312,6 +6311,25 @@ ] } }, + "CA2007": { + "id": "CA2007", + "shortDescription": "Consider calling ConfigureAwait on the awaited task", + "fullDescription": "When an asynchronous method awaits a Task directly, continuation occurs in the same thread that created the task. Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. Call ConfigureAwait(false) on the task to schedule continuations to the thread pool, thereby avoiding a deadlock on the UI thread. Passing false is a good option for app-independent libraries. Calling ConfigureAwait(true) on the task has the same behavior as not explicitly calling ConfigureAwait. By explicitly calling this method, you're letting readers know you intentionally want to perform the continuation on the original synchronization context.", + "defaultLevel": "warning", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007", + "properties": { + "category": "Reliability", + "isEnabledByDefault": false, + "typeName": "BasicDoNotDirectlyAwaitATask", + "languages": [ + "Visual Basic" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA2016": { "id": "CA2016", "shortDescription": "Forward the 'CancellationToken' parameter to methods", From 3fe1d7c03a751dceb72af47daeceac002002bb2f Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 17 Jul 2023 22:04:43 +0200 Subject: [PATCH 04/30] Add analyzer for SemanticModel.GetDeclaredSymbol --- .../CSharp/AnalyzerReleases.Unshipped.md | 5 ++ ...DeclaredSymbolAlwaysReturnsNullAnalyzer.cs | 66 +++++++++++++++++++ .../CodeAnalysisDiagnosticsResources.resx | 9 +++ .../Core/DiagnosticIds.cs | 1 + .../CodeAnalysisDiagnosticsResources.cs.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.de.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.es.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.fr.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.it.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.ja.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.ko.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.pl.xlf | 15 +++++ ...CodeAnalysisDiagnosticsResources.pt-BR.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.ru.xlf | 15 +++++ .../CodeAnalysisDiagnosticsResources.tr.xlf | 15 +++++ ...deAnalysisDiagnosticsResources.zh-Hans.xlf | 15 +++++ ...deAnalysisDiagnosticsResources.zh-Hant.xlf | 15 +++++ .../Microsoft.CodeAnalysis.Analyzers.md | 12 ++++ .../Microsoft.CodeAnalysis.Analyzers.sarif | 17 +++++ ...redSymbolAlwaysReturnsNullAnalyzerTests.cs | 58 ++++++++++++++++ src/Utilities/Compiler/WellKnownTypeNames.cs | 4 ++ 21 files changed, 367 insertions(+) create mode 100644 src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs create mode 100644 src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md index cdf4f1397e..105659ad83 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md @@ -1 +1,6 @@ ; Please do not edit this file manually, it should only be updated through code fix application. +### New Rules + +Rule ID | Category | Severity | Notes +--------|----------|----------|------- +RS1039 | MicrosoftCodeAnalysisCorrectness | Warning | SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs new file mode 100644 index 0000000000..36ec6422e2 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs @@ -0,0 +1,66 @@ +// 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.Linq; +using Analyzer.Utilities; +using Analyzer.Utilities.Extensions; +using Microsoft.CodeAnalysis.Analyzers; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; + +namespace Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers +{ + using static CodeAnalysisDiagnosticsResources; + + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public sealed class CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer : DiagnosticAnalyzer + { + private static readonly DiagnosticDescriptor DiagnosticDescriptor = new( + DiagnosticIds.SemanticModelGetDeclaredSymbolAlwaysReturnsNull, + CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullTitle)), + CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullMessage)), + DiagnosticCategory.MicrosoftCodeAnalysisCorrectness, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullDescription)), + helpLinkUri: null, + customTags: WellKnownDiagnosticTagsExtensions.Telemetry); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterCompilationStartAction(static compilationContext => + { + var typeProvider = WellKnownTypeProvider.GetOrCreate(compilationContext.Compilation); + IMethodSymbol? getDeclaredSymbolMethod; + if (!typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisModelExtensions, out var modelExtensions) + || (getDeclaredSymbolMethod = modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault() as IMethodSymbol) is null + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxGlobalStatementSyntax, out var globalStatementSymbol) + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxIncompleteMemberSyntax, out var incompleteMemberSymbol) + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax, out var baseFieldDeclarationSymbol)) + { + return; + } + + compilationContext.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, globalStatementSymbol, incompleteMemberSymbol, baseFieldDeclarationSymbol), OperationKind.Invocation); + }); + } + + private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodSymbol getDeclaredSymbolMethod, INamedTypeSymbol globalStatementSymbol, INamedTypeSymbol incompleteMemberSymbol, INamedTypeSymbol baseFieldDeclarationSymbol) + { + var invocation = (IInvocationOperation)context.Operation; + if (SymbolEqualityComparer.Default.Equals(invocation.TargetMethod, getDeclaredSymbolMethod)) + { + var syntaxNodeType = invocation.Arguments[1].Value.WalkDownConversion().Type; + if (syntaxNodeType is not null && syntaxNodeType.GetBaseTypesAndThis().ToSet().Overlaps(new[] { globalStatementSymbol, incompleteMemberSymbol, baseFieldDeclarationSymbol })) + { + var diagnostic = invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeType.Name); + context.ReportDiagnostic(diagnostic); + } + } + } + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptor); + } +} \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx index d7b9aa587c..b8992894d6 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx @@ -571,4 +571,13 @@ Compiler extensions should be implemented in assemblies with compiler-provided references + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs index 41700c3cba..58a94c951a 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs @@ -42,6 +42,7 @@ internal static class DiagnosticIds public const string NoSettingSpecifiedSymbolIsBannedInAnalyzersRuleId = "RS1036"; public const string AddCompilationEndCustomTagRuleId = "RS1037"; public const string DoNotRegisterCompilerTypesWithBadAssemblyReferenceRuleId = "RS1038"; + public const string SemanticModelGetDeclaredSymbolAlwaysReturnsNull = "RS1039"; // Release tracking analyzer IDs public const string DeclareDiagnosticIdInAnalyzerReleaseRuleId = "RS2000"; diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf index 7e46c4495e..f3cd6189e7 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf @@ -407,6 +407,21 @@ Nepřidávat odebraná ID diagnostiky analyzátoru do nevydané verze analyzátoru + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. Symbol byl označen jako zakázaný pro použití v analyzátorech a místo toho by se měla použít náhrada. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf index b01365c239..deaee97afd 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf @@ -407,6 +407,21 @@ Fügen Sie einem nicht veröffentlichten Analysetoolrelease keine entfernten Analysetooldiagnose-IDs hinzu. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. Das Symbol wurde für die Verwendung in dem Analysetool als gesperrt gekennzeichnet, und es muss stattdessen eine Alternative verwendet werden. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf index 7c1c4c9c67..b7b173c0e1 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf @@ -407,6 +407,21 @@ No agregar identificadores de diagnóstico del analizador eliminados a una versión del analizador no incluida + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. El símbolo ha sido marcado como de uso prohibido en los analizadores, y en su lugar debe usarse uno alternativo. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf index 987a662fda..7cb13ef044 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf @@ -407,6 +407,21 @@ Ne pas ajouter d'ID de diagnostic d'analyseur supprimé à une version d'analyseur non fournie + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. Le symbole a été marqué comme étant interdit d’utilisation dans les analyseurs, et un autre symbole doit être utilisé à la place. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf index 17ad5f67b0..f230493a53 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf @@ -407,6 +407,21 @@ Non aggiungere gli ID diagnostica dell'analizzatore rimossi alla versione dell'analizzatore non distribuita + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. Il simbolo è stato contrassegnato come escluso dall'uso negli analizzatori e al suo posto deve esserne usato uno alternativo. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf index 2f1e534b2c..c443536465 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf @@ -407,6 +407,21 @@ 削除したアナライザー診断 ID を未出荷のアナライザー リリースに追加しない + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. シンボルはこのアナライザーで禁止とマークされているため、代替を使用する必要があります。 diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf index 7e898bf104..910d86aa7e 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf @@ -407,6 +407,21 @@ 제거된 분석기 진단 ID를 제공되지 않은 분석기 릴리스에 추가하면 안 됩니다. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. 기호가 분석기에서 사용 금지된 것으로 표시되었으며 대신 대체 기호를 사용해야 합니다. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf index b2b0c4c6ef..3e5451c6e7 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf @@ -407,6 +407,21 @@ Nie dodawaj usuniętych identyfikatorów diagnostyki analizatora do niedostarczonego wydania analizatora + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. Symbol został oznaczony jako zabroniony do użytku w analizatorze i zamiast niego powinien być używany alternatywny. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf index 9267d2dc81..4028cb7502 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf @@ -407,6 +407,21 @@ Não adicione as IDs de diagnóstico do analisador removidas à versão do analisador não enviada + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. O símbolo foi marcado como proibido para uso em analisadores. É necessário usar um símbolo alternativo. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf index 01d709fdbb..c2272e3461 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf @@ -407,6 +407,21 @@ Не добавляйте удаленные идентификаторы диагностики анализатора в неотправленный выпуск анализатора + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. Символ был помечен как запрещенный к использованию в анализаторах. Вместо него следует использовать альтернативный вариант. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf index f35ebd0746..a3393014ec 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf @@ -407,6 +407,21 @@ Kaldırılmış çözümleyici tanılama kimliklerini gönderilmeyen çözümleyici sürümüne ekleme + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. Sembol, çözümleyicilerde kullanılması yasaklı olarak işaretlendiğinden bunun yerine başka bir sembol kullanılması gerekiyor. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf index dd1e14645d..736e3e69d7 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf @@ -407,6 +407,21 @@ 请勿将已删除的分析器诊断 ID 添加到未提供的分析器版本中 + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. 已将该符号标记为禁止在分析器中使用,并应改用备用符号。 diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf index ca3b2ceb4f..f4b811bd8c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf @@ -407,6 +407,21 @@ 請勿將已移除的分析器診斷識別碼,新增至未送出的分析器版本 + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + The symbol has been marked as banned for use in analyzers, and an alternate should be used instead. 已將符號標示為禁用於分析器,因此應改用替代符號。 diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md index 2d45eaeb90..502810a92c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md @@ -472,6 +472,18 @@ Types which implement compiler extension points should not be declared in assemb |CodeFix|False| --- +## RS1039: A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + +Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + +|Item|Value| +|-|-| +|Category|MicrosoftCodeAnalysisCorrectness| +|Enabled|True| +|Severity|Warning| +|CodeFix|False| +--- + ## [RS2000](https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md): Add analyzer diagnostic IDs to analyzer release All supported analyzer diagnostic IDs should be part of an analyzer release. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif index cb8c6b9ac7..42ff748157 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif @@ -868,6 +868,23 @@ "Telemetry" ] } + }, + "RS1039": { + "id": "RS1039", + "shortDescription": "A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null'", + "fullDescription": "Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'.", + "defaultLevel": "warning", + "properties": { + "category": "MicrosoftCodeAnalysisCorrectness", + "isEnabledByDefault": true, + "typeName": "CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer", + "languages": [ + "C#" + ], + "tags": [ + "Telemetry" + ] + } } } }, diff --git a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs new file mode 100644 index 0000000000..b784eb7228 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Xunit; +using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< + Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers.CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; + +namespace Microsoft.CodeAnalysis.Analyzers.UnitTests.MetaAnalyzers +{ + public sealed class SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests + { + [Theory] + [InlineData("GlobalStatementSyntax")] + [InlineData("IncompleteMemberSyntax")] + [InlineData("BaseFieldDeclarationSyntax")] + [InlineData("FieldDeclarationSyntax")] + [InlineData("EventFieldDeclarationSyntax")] + public Task Diagnostic(string type) + { + var code = $@" +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +public class Test {{ + public void M(SemanticModel semanticModel, {type} syntax) {{ + var x = [|semanticModel.GetDeclaredSymbol(syntax)|]; + }} +}}"; + + return new VerifyCS.Test + { + TestCode = code + }.RunAsync(); + } + + [Theory] + [InlineData("SyntaxNode")] + [InlineData("TypeDeclarationSyntax")] + public Task NoDiagnostic(string type) + { + var code = $@" +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +public class Test {{ + public void M(SemanticModel semanticModel, {type} syntax) {{ + var x = semanticModel.GetDeclaredSymbol(syntax); + }} +}}"; + + return new VerifyCS.Test + { + TestCode = code + }.RunAsync(); + } + } +} \ No newline at end of file diff --git a/src/Utilities/Compiler/WellKnownTypeNames.cs b/src/Utilities/Compiler/WellKnownTypeNames.cs index 020d6151d9..6a786dcee9 100644 --- a/src/Utilities/Compiler/WellKnownTypeNames.cs +++ b/src/Utilities/Compiler/WellKnownTypeNames.cs @@ -36,6 +36,9 @@ internal static class WellKnownTypeNames public const string MicrosoftCodeAnalysisCSharpCSharpCompilation = "Microsoft.CodeAnalysis.CSharp.CSharpCompilation"; public const string MicrosoftCodeAnalysisCSharpCSharpExtensions = "Microsoft.CodeAnalysis.CSharp.CSharpExtensions"; public const string MicrosoftCodeAnalysisCSharpExtensions = "Microsoft.CodeAnalysis.CSharpExtensions"; + public const string MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.BaseFieldDeclarationSyntax"; + public const string MicrosoftCodeAnalysisCSharpSyntaxGlobalStatementSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.GlobalStatementSyntax"; + public const string MicrosoftCodeAnalysisCSharpSyntaxIncompleteMemberSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.IncompleteMemberSyntax"; public const string MicrosoftCodeAnalysisDiagnostic = "Microsoft.CodeAnalysis.Diagnostic"; public const string MicrosoftCodeAnalysisDiagnosticDescriptor = "Microsoft.CodeAnalysis.DiagnosticDescriptor"; public const string MicrosoftCodeAnalysisDiagnosticsAnalysisContext = "Microsoft.CodeAnalysis.Diagnostics.AnalysisContext"; @@ -59,6 +62,7 @@ internal static class WellKnownTypeNames public const string MicrosoftCodeAnalysisISourceGenerator = "Microsoft.CodeAnalysis.ISourceGenerator"; public const string MicrosoftCodeAnalysisLocalizableResourceString = "Microsoft.CodeAnalysis.LocalizableResourceString"; public const string MicrosoftCodeAnalysisLocalizableString = "Microsoft.CodeAnalysis.LocalizableString"; + public const string MicrosoftCodeAnalysisModelExtensions = "Microsoft.CodeAnalysis.ModelExtensions"; public const string MicrosoftCodeAnalysisSharedCollectionsTemporaryArrayExtensions = "Microsoft.CodeAnalysis.Shared.Collections.TemporaryArrayExtensions"; public const string MicrosoftCodeAnalysisSymbolKind = "Microsoft.CodeAnalysis.SymbolKind"; public const string MicrosoftCodeAnalysisVisualBasicExtensions = "Microsoft.CodeAnalysis.VisualBasicExtensions"; From ae44cc94f7f5a9feb6acd13b23a5633cc853dc05 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 25 Jul 2023 18:48:08 +0200 Subject: [PATCH 05/30] PR comments. --- ...DeclaredSymbolAlwaysReturnsNullAnalyzer.cs | 6 ++--- ...redSymbolAlwaysReturnsNullAnalyzerTests.cs | 26 +++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs index 36ec6422e2..59f84ac615 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs @@ -30,9 +30,9 @@ public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); - context.RegisterCompilationStartAction(static compilationContext => + context.RegisterCompilationStartAction(static context => { - var typeProvider = WellKnownTypeProvider.GetOrCreate(compilationContext.Compilation); + var typeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); IMethodSymbol? getDeclaredSymbolMethod; if (!typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisModelExtensions, out var modelExtensions) || (getDeclaredSymbolMethod = modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault() as IMethodSymbol) is null @@ -43,7 +43,7 @@ public override void Initialize(AnalysisContext context) return; } - compilationContext.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, globalStatementSymbol, incompleteMemberSymbol, baseFieldDeclarationSymbol), OperationKind.Invocation); + context.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, globalStatementSymbol, incompleteMemberSymbol, baseFieldDeclarationSymbol), OperationKind.Invocation); }); } diff --git a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs index b784eb7228..57c8a1eec1 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs @@ -28,10 +28,7 @@ public void M(SemanticModel semanticModel, {type} syntax) {{ }} }}"; - return new VerifyCS.Test - { - TestCode = code - }.RunAsync(); + return VerifyCS.VerifyAnalyzerAsync(code); } [Theory] @@ -49,10 +46,23 @@ public void M(SemanticModel semanticModel, {type} syntax) {{ }} }}"; - return new VerifyCS.Test - { - TestCode = code - }.RunAsync(); + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact] + public Task NoDiagnosticForCompilationError() + { + const string code = @" +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +public class Test { + public void M(SemanticModel semanticModel) { + var x = semanticModel.{|CS7036:GetDeclaredSymbol|}(); + } +}"; + + return VerifyCS.VerifyAnalyzerAsync(code); } } } \ No newline at end of file From de68e846c3f2f7ef2f63854461bc37c473d7790e Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 25 Jul 2023 21:06:53 +0200 Subject: [PATCH 06/30] Update RulesMissingDocumentation.md --- .../RulesMissingDocumentation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md index c82804252c..6d17f6bd6f 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md @@ -37,3 +37,4 @@ RS1034 | | Prefer 'IsKind' for checking syntax kinds | RS1035 | | Do not use APIs banned for analyzers | RS1036 | | Specify analyzer banned API enforcement setting | RS1037 | | Add "CompilationEnd" custom tag to compilation end diagnostic descriptor | +RS1039 | | A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' | From 169dcbb91a3e2ca02cd1f8097a82e58c42112e3c Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 13:11:34 +0200 Subject: [PATCH 07/30] Remove warning. --- .../ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs index d622717c29..65ef41a3d6 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs @@ -20,7 +20,7 @@ protected override void RegisterLanguageSpecificChecks(OperationBlockStartAnalys private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) { - if (context.Operation is IForEachLoopOperation { Syntax: ForEachStatementSyntax { AwaitKeyword.RawKind: not (int)SyntaxKind.None } } forEachOperation + if (context.Operation is IForEachLoopOperation { Syntax: ForEachStatementSyntax { AwaitKeyword.RawKind: not (int)SyntaxKind.None }, Collection.Type: not null } forEachOperation && !forEachOperation.Collection.Type.OriginalDefinition.Equals(configuredAsyncEnumerable, SymbolEqualityComparer.Default)) { context.ReportDiagnostic(forEachOperation.Collection.CreateDiagnostic(Rule)); From 6bfef067c33cc1534242c71245f9d23df91a46d1 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 13:26:25 +0200 Subject: [PATCH 08/30] Add file header --- .../ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb index b608dcd576..dc8297e200 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb @@ -1,4 +1,6 @@ -Imports Microsoft.CodeAnalysis +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines From ccb6a777f36170c42c6ea248261f7a3d775e7a0f Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 21:10:53 +0200 Subject: [PATCH 09/30] Use IsAsynchronous property --- .../ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs index 65ef41a3d6..71b9323e07 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs @@ -2,8 +2,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines; @@ -20,7 +18,7 @@ protected override void RegisterLanguageSpecificChecks(OperationBlockStartAnalys private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) { - if (context.Operation is IForEachLoopOperation { Syntax: ForEachStatementSyntax { AwaitKeyword.RawKind: not (int)SyntaxKind.None }, Collection.Type: not null } forEachOperation + if (context.Operation is IForEachLoopOperation { IsAsynchronous: true, Collection.Type: not null } forEachOperation && !forEachOperation.Collection.Type.OriginalDefinition.Equals(configuredAsyncEnumerable, SymbolEqualityComparer.Default)) { context.ReportDiagnostic(forEachOperation.Collection.CreateDiagnostic(Rule)); From 40e64c0570f8f160a56c8aaebd110e8265a7e602 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 1 Aug 2023 10:41:13 +0200 Subject: [PATCH 10/30] PR comments --- .../CSharp/AnalyzerReleases.Unshipped.md | 1 + ...emanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs | 5 ++++- .../Core/CodeAnalysisDiagnosticsResources.resx | 2 +- .../Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf | 4 ++-- .../Microsoft.CodeAnalysis.Analyzers.md | 2 +- .../Microsoft.CodeAnalysis.Analyzers.sarif | 2 +- .../RulesMissingDocumentation.md | 2 +- src/NetAnalyzers/RulesMissingDocumentation.md | 1 - 20 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md index 105659ad83..c989a082ec 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md @@ -1,4 +1,5 @@ ; Please do not edit this file manually, it should only be updated through code fix application. + ### New Rules Rule ID | Category | Severity | Notes diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs index 59f84ac615..12c71b8310 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs @@ -53,7 +53,10 @@ private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodS if (SymbolEqualityComparer.Default.Equals(invocation.TargetMethod, getDeclaredSymbolMethod)) { var syntaxNodeType = invocation.Arguments[1].Value.WalkDownConversion().Type; - if (syntaxNodeType is not null && syntaxNodeType.GetBaseTypesAndThis().ToSet().Overlaps(new[] { globalStatementSymbol, incompleteMemberSymbol, baseFieldDeclarationSymbol })) + if (syntaxNodeType is not null && + (syntaxNodeType.DerivesFrom(globalStatementSymbol, baseTypesOnly: true, checkTypeParameterConstraints: false) + || syntaxNodeType.DerivesFrom(incompleteMemberSymbol, baseTypesOnly: true, checkTypeParameterConstraints: false) + || syntaxNodeType.DerivesFrom(baseFieldDeclarationSymbol, baseTypesOnly: true, checkTypeParameterConstraints: false))) { var diagnostic = invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeType.Name); context.ReportDiagnostic(diagnostic); diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx index b8992894d6..1411085b89 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx @@ -578,6 +578,6 @@ A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf index f3cd6189e7..8527c2a633 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf index deaee97afd..030c4ef9b2 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf index b7b173c0e1..11de3e5e6d 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf index 7cb13ef044..359d9f7536 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf index f230493a53..8f5478263f 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf index c443536465..cfafe2747f 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf index 910d86aa7e..8deca64dff 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf index 3e5451c6e7..4bd77f1580 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf index 4028cb7502..527466cc15 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf index c2272e3461..501dbe8278 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf index a3393014ec..259dcbe2eb 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf index 736e3e69d7..1681f561c0 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf index f4b811bd8c..6c23713b84 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf @@ -418,8 +418,8 @@ - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' - A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md index 502810a92c..6eb637de81 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md @@ -472,7 +472,7 @@ Types which implement compiler extension points should not be declared in assemb |CodeFix|False| --- -## RS1039: A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' +## RS1039: This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif index 42ff748157..7ff512e604 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif @@ -871,7 +871,7 @@ }, "RS1039": { "id": "RS1039", - "shortDescription": "A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null'", + "shortDescription": "This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null'", "fullDescription": "Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'.", "defaultLevel": "warning", "properties": { diff --git a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md index 6d17f6bd6f..11a466eff1 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md @@ -37,4 +37,4 @@ RS1034 | | Prefer 'IsKind' for checking syntax kinds | RS1035 | | Do not use APIs banned for analyzers | RS1036 | | Specify analyzer banned API enforcement setting | RS1037 | | Add "CompilationEnd" custom tag to compilation end diagnostic descriptor | -RS1039 | | A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' | +RS1039 | | This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' | diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md index 50fa5fb52f..42df726b08 100644 --- a/src/NetAnalyzers/RulesMissingDocumentation.md +++ b/src/NetAnalyzers/RulesMissingDocumentation.md @@ -13,6 +13,5 @@ CA1863 | | Use char overload | CA1866 | | Use char overload | CA1867 | | Use char overload | -CA1868 | | Unnecessary call to 'Contains(item)' | CA2021 | | Do not call Enumerable.Cast\ or Enumerable.OfType\ with incompatible types | CA2261 | | Do not use ConfigureAwaitOptions.SuppressThrowing with Task\ | From 375fc288fd86456eadd51623ac1ca0b2a1746ebd Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Sun, 20 Aug 2023 12:36:15 +0300 Subject: [PATCH 11/30] Write CA1824 as non-compilation-end --- ...kAssembliesWithNeutralResourcesLanguage.cs | 9 ++- ...kAssembliesWithNeutralResourcesLanguage.cs | 64 ++++++++++++------- ...mbliesWithNeutralResourcesLanguageTests.cs | 16 ++++- ...kAssembliesWithNeutralResourcesLanguage.vb | 10 ++- .../Extensions/DiagnosticExtensions.cs | 6 ++ 5 files changed, 77 insertions(+), 28 deletions(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Resources/CSharpMarkAssembliesWithNeutralResourcesLanguage.cs b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Resources/CSharpMarkAssembliesWithNeutralResourcesLanguage.cs index 5a3653b072..271b35d4bc 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Resources/CSharpMarkAssembliesWithNeutralResourcesLanguage.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Resources/CSharpMarkAssembliesWithNeutralResourcesLanguage.cs @@ -15,10 +15,15 @@ namespace Microsoft.NetCore.CSharp.Analyzers.Resources [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class CSharpMarkAssembliesWithNeutralResourcesLanguageAnalyzer : MarkAssembliesWithNeutralResourcesLanguageAnalyzer { - protected override void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Action onResourceFound, INamedTypeSymbol generatedCode) + protected override void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Func shouldAnalyze, Action onResourceFound, INamedTypeSymbol generatedCode) { context.RegisterSyntaxNodeAction(context => { + if (!shouldAnalyze()) + { + return; + } + var attributeSyntax = (AttributeSyntax)context.Node; if (!CheckAttribute(attributeSyntax)) { @@ -30,7 +35,7 @@ protected override void RegisterAttributeAnalyzer(CompilationStartAnalysisContex return; } - onResourceFound(); + onResourceFound(context); }, SyntaxKind.Attribute); } diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs index 67908c2891..c2dfeed322 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -33,10 +34,9 @@ public abstract class MarkAssembliesWithNeutralResourcesLanguageAnalyzer : Diagn RuleLevel.IdeSuggestion, description: CreateLocalizableResourceString(nameof(MarkAssembliesWithNeutralResourcesLanguageDescription)), isPortedFxCopRule: true, - isDataflowRule: false, - isReportedAtCompilationEnd: true); + isDataflowRule: false); - protected abstract void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Action onResourceFound, INamedTypeSymbol generatedCode); + protected abstract void RegisterAttributeAnalyzer(CompilationStartAnalysisContext context, Func shouldAnalyze, Action onResourceFound, INamedTypeSymbol generatedCode); public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); @@ -68,28 +68,48 @@ public override void Initialize(AnalysisContext context) return; } - var hasResource = false; - RegisterAttributeAnalyzer(context, () => hasResource = true, generatedCode); + var alreadyReportedDiagnostic = new StrongBox(false); + var @lock = new object(); - context.RegisterCompilationEndAction(context => - { - // there is nothing to do. - if (!hasResource) + RegisterAttributeAnalyzer( + context, + shouldAnalyze: () => { - return; - } - - if (data != null && - data.ApplicationSyntaxReference?.GetSyntax(context.CancellationToken) is { } attributeSyntax) + // This value can only change from false to true. So no need to lock if it's already true here. + if (alreadyReportedDiagnostic.Value) + { + return false; + } + + lock (@lock) + { + return !alreadyReportedDiagnostic.Value; + } + }, + onResourceFound: context => { - // we have the attribute but its doing it wrong. - context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(Rule)); - return; - } - - // attribute just don't exist - context.ReportNoLocationDiagnostic(Rule); - }); + lock (@lock) + { + if (alreadyReportedDiagnostic.Value) + { + return; + } + + alreadyReportedDiagnostic.Value = true; + + if (data != null && + data.ApplicationSyntaxReference?.GetSyntax(context.CancellationToken) is { } attributeSyntax) + { + // we have the attribute but its doing it wrong. + context.ReportDiagnostic(attributeSyntax.CreateDiagnostic(Rule)); + return; + } + + // attribute just don't exist + context.ReportNoLocationDiagnostic(Rule); + } + }, + generatedCode); }); } diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguageTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguageTests.cs index 859e0a5e9e..2c856b6982 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguageTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Resources/MarkAssembliesWithNeutralResourcesLanguageTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; @@ -18,6 +18,12 @@ public class MarkAssembliesWithNeutralResourcesLanguageTests namespace DesignerFile { [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")] internal class Resource1 { } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")] + internal class Resource2 { } + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")] + internal class Resource3 { } }"; private const string BasicDesignerFile = @" @@ -25,6 +31,14 @@ Namespace My.Resources _ Friend Class Resource1 End Class + + _ + Friend Class Resource2 + End Class + + _ + Friend Class Resource3 + End Class End Namespace"; [Fact] diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Resources/BasicMarkAssembliesWithNeutralResourcesLanguage.vb b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Resources/BasicMarkAssembliesWithNeutralResourcesLanguage.vb index 2bdf17c54b..dfac22b3d2 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Resources/BasicMarkAssembliesWithNeutralResourcesLanguage.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Resources/BasicMarkAssembliesWithNeutralResourcesLanguage.vb @@ -1,4 +1,4 @@ -' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. Imports Microsoft.NetCore.Analyzers.Resources Imports Microsoft.CodeAnalysis @@ -13,9 +13,13 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Resources Public NotInheritable Class BasicMarkAssembliesWithNeutralResourcesLanguageAnalyzer Inherits MarkAssembliesWithNeutralResourcesLanguageAnalyzer - Protected Overrides Sub RegisterAttributeAnalyzer(context As CompilationStartAnalysisContext, onResourceFound As Action, generatedCode As INamedTypeSymbol) + Protected Overrides Sub RegisterAttributeAnalyzer(context As CompilationStartAnalysisContext, shouldAnalyze As Func(Of Boolean), onResourceFound As Action(Of SyntaxNodeAnalysisContext), generatedCode As INamedTypeSymbol) context.RegisterSyntaxNodeAction( Sub(nc) + If Not shouldAnalyze() Then + Return + End If + Dim attributeSyntax = DirectCast(nc.Node, AttributeSyntax) If Not CheckBasicAttribute(attributeSyntax) Then Return @@ -25,7 +29,7 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Resources Return End If - onResourceFound() + onResourceFound(nc) End Sub, SyntaxKind.Attribute) End Sub diff --git a/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs b/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs index a5bb4455e4..4bb3bd337b 100644 --- a/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs +++ b/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs @@ -169,6 +169,12 @@ public static void ReportNoLocationDiagnostic( params object[] args) => context.Compilation.ReportNoLocationDiagnostic(rule, context.ReportDiagnostic, properties: null, args); + public static void ReportNoLocationDiagnostic( + this SyntaxNodeAnalysisContext context, + DiagnosticDescriptor rule, + params object[] args) + => context.Compilation.ReportNoLocationDiagnostic(rule, context.ReportDiagnostic, properties: null, args); + public static void ReportNoLocationDiagnostic( this Compilation compilation, DiagnosticDescriptor rule, From 2073e40a7f17b07c9248b7d93edb9d37f30d895e Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Sun, 20 Aug 2023 13:07:25 +0300 Subject: [PATCH 12/30] Update Microsoft.CodeAnalysis.NetAnalyzers.sarif --- src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index b80746b7b8..1a3f54a2ce 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -203,8 +203,7 @@ "tags": [ "PortedFromFxCop", "Telemetry", - "EnabledRuleInAggressiveMode", - "CompilationEnd" + "EnabledRuleInAggressiveMode" ] } }, @@ -6387,8 +6386,7 @@ "tags": [ "PortedFromFxCop", "Telemetry", - "EnabledRuleInAggressiveMode", - "CompilationEnd" + "EnabledRuleInAggressiveMode" ] } }, From f34878eaf4466bd12e20617912bef2f3369abdc5 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 25 Sep 2023 21:32:52 +0200 Subject: [PATCH 13/30] Source types from GetDeclaredSymbol extension methods --- ...DeclaredSymbolAlwaysReturnsNullAnalyzer.cs | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs index 12c71b8310..5920eb60cd 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.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.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Analyzer.Utilities; @@ -34,29 +35,29 @@ public override void Initialize(AnalysisContext context) { var typeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); IMethodSymbol? getDeclaredSymbolMethod; - if (!typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisModelExtensions, out var modelExtensions) - || (getDeclaredSymbolMethod = modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault() as IMethodSymbol) is null - || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxGlobalStatementSyntax, out var globalStatementSymbol) - || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxIncompleteMemberSyntax, out var incompleteMemberSymbol) - || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax, out var baseFieldDeclarationSymbol)) + if (!typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpCSharpExtensions, out var csharpExtensions) + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisModelExtensions, out var modelExtensions) + || (getDeclaredSymbolMethod = modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault() as IMethodSymbol) is null) { return; } - context.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, globalStatementSymbol, incompleteMemberSymbol, baseFieldDeclarationSymbol), OperationKind.Invocation); + var allowedTypes = csharpExtensions.GetMembers(nameof(CSharpExtensions.GetDeclaredSymbol)) + .OfType() + .Where(m => m.Parameters.Length >= 2) + .Select(m => m.Parameters[1].Type); + + context.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, allowedTypes), OperationKind.Invocation); }); } - private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodSymbol getDeclaredSymbolMethod, INamedTypeSymbol globalStatementSymbol, INamedTypeSymbol incompleteMemberSymbol, INamedTypeSymbol baseFieldDeclarationSymbol) + private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodSymbol getDeclaredSymbolMethod, IEnumerable allowedTypes) { var invocation = (IInvocationOperation)context.Operation; if (SymbolEqualityComparer.Default.Equals(invocation.TargetMethod, getDeclaredSymbolMethod)) { var syntaxNodeType = invocation.Arguments[1].Value.WalkDownConversion().Type; - if (syntaxNodeType is not null && - (syntaxNodeType.DerivesFrom(globalStatementSymbol, baseTypesOnly: true, checkTypeParameterConstraints: false) - || syntaxNodeType.DerivesFrom(incompleteMemberSymbol, baseTypesOnly: true, checkTypeParameterConstraints: false) - || syntaxNodeType.DerivesFrom(baseFieldDeclarationSymbol, baseTypesOnly: true, checkTypeParameterConstraints: false))) + if (syntaxNodeType is not null && allowedTypes.Any(type => syntaxNodeType.DerivesFrom(type, baseTypesOnly: true, checkTypeParameterConstraints: false))) { var diagnostic = invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeType.Name); context.ReportDiagnostic(diagnostic); From dab5d0ea88cd40ea6ce190786818d3e7b4194a7d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 3 Oct 2023 11:05:47 -0500 Subject: [PATCH 14/30] Add support for ExperimentalAttribute Fixes #6759 --- .../DeclarePublicApiAnalyzer.Impl.cs | 35 ++++++++- .../DeclarePublicAPIAnalyzerTestsBase.cs | 76 +++++++++++++++++++ 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs b/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs index fd650d6f4a..ccf58ea289 100644 --- a/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs +++ b/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs @@ -589,11 +589,33 @@ private static bool UsesOblivious(ISymbol symbol) private ApiName GetApiName(ISymbol symbol) { + var experimentName = getExperimentName(symbol); + return new ApiName( - getApiString(symbol, s_publicApiFormat), - getApiString(symbol, s_publicApiFormatWithNullability)); + getApiString(_compilation, symbol, experimentName, s_publicApiFormat), + getApiString(_compilation, symbol, experimentName, s_publicApiFormatWithNullability)); + + static string? getExperimentName(ISymbol symbol) + { + for (var current = symbol; current is not null; current = current.ContainingSymbol) + { + foreach (var attribute in current.GetAttributes()) + { + if (attribute.AttributeClass is { Name: "ExperimentalAttribute", ContainingSymbol: INamespaceSymbol { Name: nameof(System.Diagnostics.CodeAnalysis), ContainingNamespace: { Name: nameof(System.Diagnostics), ContainingNamespace: { Name: nameof(System), ContainingNamespace.IsGlobalNamespace: true } } } }) + { + if (attribute.ConstructorArguments is not [{ Kind: TypedConstantKind.Primitive, Type.SpecialType: SpecialType.System_String, Value: string diagnosticId }]) + return "???"; + + return diagnosticId; + + } + } + } + + return null; + } - string getApiString(ISymbol symbol, SymbolDisplayFormat format) + static string getApiString(Compilation compilation, ISymbol symbol, string? experimentName, SymbolDisplayFormat format) { string publicApiName = symbol.ToDisplayString(format); @@ -625,11 +647,16 @@ string getApiString(ISymbol symbol, SymbolDisplayFormat format) return string.Empty; } - if (symbol.ContainingAssembly != null && !symbol.ContainingAssembly.Equals(_compilation.Assembly)) + if (symbol.ContainingAssembly != null && !symbol.ContainingAssembly.Equals(compilation.Assembly)) { publicApiName += $" (forwarded, contained in {symbol.ContainingAssembly.Name})"; } + if (experimentName != null) + { + publicApiName = "[" + experimentName + "]" + publicApiName; + } + return publicApiName; } } diff --git a/src/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs b/src/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs index 3dba443976..13d62c956d 100644 --- a/src/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs +++ b/src/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs @@ -214,6 +214,11 @@ private async Task VerifyNet50CSharpAdditionalFileFixAsync(string source, string await VerifyAdditionalFileFixAsync(LanguageNames.CSharp, source, shippedApiText, oldUnshippedApiText, newUnshippedApiText, ReferenceAssemblies.Net.Net50); } + private async Task VerifyNet80CSharpAdditionalFileFixAsync(string source, string? shippedApiText, string? oldUnshippedApiText, string newUnshippedApiText) + { + await VerifyAdditionalFileFixAsync(LanguageNames.CSharp, source, shippedApiText, oldUnshippedApiText, newUnshippedApiText, AdditionalMetadataReferences.Net80); + } + private async Task VerifyAdditionalFileFixAsync(string language, string source, string? shippedApiText, string? oldUnshippedApiText, string newUnshippedApiText, ReferenceAssemblies? referenceAssemblies = null) { @@ -3219,6 +3224,77 @@ virtual R.PrintMembers(System.Text.StringBuilder! builder) -> bool await VerifyNet50CSharpAdditionalFileFixAsync(source, shippedText, unshippedText, fixedUnshippedText); } + [Fact] + [WorkItem(6759, "https://github.com/dotnet/roslyn-analyzers/issues/6759")] + public async Task TestExperimentalApiAsync() + { + var source = $$""" + using System.Diagnostics.CodeAnalysis; + + [Experimental("ID1")] + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + } + """; + + var shippedText = @""; + var unshippedText = @""; + var fixedUnshippedText = @"[ID1]C +[ID1]C.C() -> void"; + + await VerifyNet80CSharpAdditionalFileFixAsync(source, shippedText, unshippedText, fixedUnshippedText); + } + + [Theory] + [InlineData("")] + [InlineData("null")] + [InlineData("1")] + [InlineData("1, 2")] + [WorkItem(6759, "https://github.com/dotnet/roslyn-analyzers/issues/6759")] + public async Task TestExperimentalApiWithInvalidArgumentAsync(string invalidArgument) + { + var source = $$""" + using System.Diagnostics.CodeAnalysis; + + [Experimental({{invalidArgument}})] + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + } + """; + + var shippedText = @""; + var unshippedText = @""; + var fixedUnshippedText = @"[???]C +[???]C.C() -> void"; + + var test = new CSharpCodeFixTest() + { + ReferenceAssemblies = AdditionalMetadataReferences.Net80, + CompilerDiagnostics = CompilerDiagnostics.None, + TestState = + { + Sources = { source }, + AdditionalFiles = + { + (ShippedFileName, shippedText), + (UnshippedFileName, unshippedText), + }, + }, + FixedState = + { + AdditionalFiles = + { + (ShippedFileName, shippedText), + (UnshippedFileName, fixedUnshippedText), + }, + }, + }; + + test.DisabledDiagnostics.AddRange(DisabledDiagnostics); + + await test.RunAsync(); + } + #endregion } } From 1a059beed138ad488f1b3308a1c99467a79e3fdd Mon Sep 17 00:00:00 2001 From: Mario Pistrich Date: Fri, 13 Oct 2023 18:18:57 +0200 Subject: [PATCH 15/30] Update to Microsoft.CodeAnalysis.Testing 1.1.2-beta1.23509.1 --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 27a6d9ad2c..f820a29b88 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -90,7 +90,7 @@ 2.0.0-pre-20160714 17.0.26-alpha - 1.1.2-beta1.23357.1 + 1.1.2-beta1.23509.1 0.13.0 2.14.1 From ac6c7031da6d84451cc7ab704107c9e92012f8af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Fri, 13 Oct 2023 14:06:22 -0500 Subject: [PATCH 16/30] Fix false-flag of CompareExchange and re-usage with loops (#6979) * Don't warn if object creation in local assignment is used as argument * Do not warn if options are used in a loop * Remove whitespace * Improve comment in IsLocalReferenceInsideChildLoop --- ...idSingleUseOfLocalJsonSerializerOptions.cs | 50 ++- ...gleUseOfLocalJsonSerializerOptionsTests.cs | 335 ++++++++++++++++-- 2 files changed, 354 insertions(+), 31 deletions(-) diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptions.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptions.cs index 94f84bfc06..1744f92266 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptions.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptions.cs @@ -9,6 +9,7 @@ using System.Diagnostics.CodeAnalysis; using System; using System.Collections.Generic; +using System.Diagnostics; namespace Microsoft.NetCore.Analyzers.Performance { @@ -60,7 +61,7 @@ private static void OnCompilationStart(CompilationStartAnalysisContext context) if (SymbolEqualityComparer.Default.Equals(typeSymbol, jsonSerializerOptionsSymbol)) { if (IsCtorUsedAsArgumentForJsonSerializer(operation, jsonSerializerSymbol) || - IsLocalUsedAsArgumentForJsonSerializerOnly(operation, jsonSerializerSymbol)) + IsLocalUsedAsArgumentForJsonSerializerOnly(operation, jsonSerializerSymbol, jsonSerializerOptionsSymbol)) { context.ReportDiagnostic(operation.CreateDiagnostic(s_Rule)); } @@ -83,11 +84,10 @@ private static bool IsArgumentForJsonSerializer(IArgumentOperation argumentOpera SymbolEqualityComparer.Default.Equals(invocationOperation.TargetMethod.ContainingType, jsonSerializerSymbol); } - private static bool IsLocalUsedAsArgumentForJsonSerializerOnly(IObjectCreationOperation objCreation, INamedTypeSymbol jsonSerializerSymbol) + private static bool IsLocalUsedAsArgumentForJsonSerializerOnly(IObjectCreationOperation objCreation, INamedTypeSymbol jsonSerializerSymbol, INamedTypeSymbol jsonSerializerOptionsSymbol) { IOperation operation = WalkUpConditional(objCreation); - - if (!IsLocalAssignment(operation, out List? localSymbols)) + if (!IsLocalAssignment(operation, jsonSerializerOptionsSymbol, out List? localSymbols)) { return false; } @@ -103,6 +103,13 @@ private static bool IsLocalUsedAsArgumentForJsonSerializerOnly(IObjectCreationOp continue; } + // Symbol is declared in a parent scope and referenced inside a loop, + // this implies that options are used more than once. + if (IsLocalReferenceInsideChildLoop(localRefOperation, localBlock!)) + { + return false; + } + // Avoid cases that would potentially make the local escape current block scope. if (IsArgumentOfJsonSerializer(descendant, jsonSerializerSymbol, out bool isArgumentOfInvocation)) { @@ -156,6 +163,26 @@ private static bool IsLocalUsedAsArgumentForJsonSerializerOnly(IObjectCreationOp return operation; } + private static bool IsLocalReferenceInsideChildLoop(ILocalReferenceOperation localRef, IBlockOperation symbolBlock) + { + IOperation? current = localRef; + while ((current = current?.Parent) is not null) + { + if (current is ILoopOperation loop) + { + Debug.Assert(loop.Body is IBlockOperation); + return loop.Body != symbolBlock; + } + + if (current == symbolBlock) + { + return false; + } + } + + return false; + } + private static bool IsArgumentOfJsonSerializer(IOperation operation, INamedTypeSymbol jsonSerializerSymbol, out bool isArgumentOfInvocation) { if (operation.Parent is IArgumentOperation arg && arg.Parent is IInvocationOperation inv) @@ -254,13 +281,19 @@ private static bool IsClosureOnLambdaOrLocalFunction(IOperation operation, IBloc return block != localBlock; } - private static bool IsLocalAssignment(IOperation operation, [NotNullWhen(true)] out List? localSymbols) + private static bool IsLocalAssignment(IOperation operation, INamedTypeSymbol jsonSerializerOptionsSymbol, [NotNullWhen(true)] out List? localSymbols) { localSymbols = null; IOperation? currentOperation = operation.Parent; while (currentOperation is not null) { + // ignore cases where the object creation or one of its parents is used as argument. + if (currentOperation is IArgumentOperation) + { + return false; + } + // for cases like: // var options; // options = new JsonSerializerOptions(); @@ -273,7 +306,8 @@ private static bool IsLocalAssignment(IOperation operation, [NotNullWhen(true)] { return false; } - else if (assignment.Target is ILocalReferenceOperation localRef) + else if (assignment.Target is ILocalReferenceOperation localRef && + SymbolEqualityComparer.Default.Equals(localRef.Local.Type, jsonSerializerOptionsSymbol)) { localSymbols ??= new List(); localSymbols.Add(localRef.Local); @@ -300,12 +334,12 @@ private static bool IsLocalAssignment(IOperation operation, [NotNullWhen(true)] } var local = GetLocalSymbolFromDeclaration(declaration); - if (local != null) + if (local != null && SymbolEqualityComparer.Default.Equals(local.Type, jsonSerializerOptionsSymbol)) { localSymbols = new List { local }; } - return local != null; + return localSymbols != null; } currentOperation = currentOperation.Parent; diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptionsTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptionsTests.cs index 63ec104493..fad3c65d7c 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptionsTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/AvoidSingleUseOfLocalJsonSerializerOptionsTests.cs @@ -45,7 +45,7 @@ internal class Program static void Main(string[] args) { JsonSerializerOptions options = {|CA1869:new JsonSerializerOptions()|}; - options.AllowTrailingCommas = true; + options.AllowTrailingCommas = true; string json = JsonSerializer.Serialize(args, options); Console.WriteLine(json); @@ -237,6 +237,101 @@ string LocalFunc() } """); + [Theory] + [InlineData(""" + for (int i = 0; i < values.Length; i++) + { + JsonSerializerOptions opt = {|CA1869:new JsonSerializerOptions()|}; + concatJson += JsonSerializer.Serialize(values[i], opt); + } + """)] + [InlineData(""" + foreach (T value in values) + { + JsonSerializerOptions opt = {|CA1869:new JsonSerializerOptions()|}; + concatJson += JsonSerializer.Serialize(value, opt); + } + """)] + [InlineData(""" + if (values.Length == 0) + return concatJson; + + int i = 0; + do + { + JsonSerializerOptions opt = {|CA1869:new JsonSerializerOptions()|}; + concatJson += JsonSerializer.Serialize(values[i++], opt); + } + while (i < values.Length); + """)] + [InlineData(""" + int i = 0; + while (i < values.Length) + { + JsonSerializerOptions opt = {|CA1869:new JsonSerializerOptions()|}; + concatJson += JsonSerializer.Serialize(values[i++], opt); + } + """)] + public Task CS_UseNewLocalOptionsAsArgument_JsonSerializerOptions_OnLoop(string loop) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System.Text.Json; + + class Program + { + static string Serialize(T[] values) + { + string concatJson = ""; + + {{loop}} + + return concatJson; + } + } + """); + + [Theory] + [InlineData(""" + For i = 0 To values.Length + Dim opt = {|CA1869:New JsonSerializerOptions()|} + concatJson += JsonSerializer.Serialize(values(i), opt) + Next + """)] + [InlineData(""" + For Each value In values + Dim opt = {|CA1869:New JsonSerializerOptions()|} + concatJson += JsonSerializer.Serialize(value, opt) + Next + """)] + [InlineData(""" + Dim i = 0 + Do While i < values.Length + Dim opt = {|CA1869:New JsonSerializerOptions()|} + concatJson += JsonSerializer.Serialize(values(i), opt) + i = i + 1 + Loop + """)] + [InlineData(""" + Dim i = 0 + Do + Dim opt = {|CA1869:New JsonSerializerOptions()|} + concatJson += JsonSerializer.Serialize(values(i), opt) + i = i + 1 + Loop While i < values.Length + """)] + public Task VB_UseNewLocalOptionsAsArgument_JsonSerializerOptions_OnLoop(string loop) + => VerifyVB.VerifyAnalyzerAsync($$""" + Imports System.Text.Json + + Class Program + Shared Function Serialize(Of T)(values As T()) As String + Dim concatJson = "" + + {{loop}} + + return concatJson + End Function + End Class + """); #endregion #region No Diagnostic Tests @@ -275,6 +370,87 @@ static string MyCustomSerializeMethod(T value, JsonSerializerOptions options) } """); + [Fact] + public Task CS_UseNewOptionsAsArgument_InterlockedCompareExchange_NoWarn() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Text.Json; + using System.Threading; + + class Program + { + static JsonSerializerOptions s_options; + static string Serialize(T value) + { + return JsonSerializer.Serialize(value, + s_options ?? + Interlocked.CompareExchange(ref s_options, new JsonSerializerOptions() {WriteIndented = true}, null) ?? + s_options); + } + } + """); + + [Fact] + public Task CS_UseNewLocalOptionsAsArgument_MethodWithJsonOptionsArgument_NoWarn() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Text.Json; + + class Program + { + static string Serialize(T value) + { + JsonSerializerOptions options = TweakOptions(new JsonSerializerOptions()); + return JsonSerializer.Serialize(value, options); + } + + static JsonSerializerOptions TweakOptions(JsonSerializerOptions options) + { + options.WriteIndented = true; + return options; + } + } + """); + + [Fact] + public Task CS_UseNewLocalOptionsAsArgument_MethodWithJsonOptionsArgument_VarDeclaration_ReturnsNonOptions_NoWarn() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Text.Json; + + class Program + { + static string Serialize(T value) + { + T newValue = ProcessOptions(new JsonSerializerOptions()); + return JsonSerializer.Serialize(newValue); + } + + static T ProcessOptions(JsonSerializerOptions options) + { + return default; + } + } + """); + + [Fact] + public Task CS_UseNewLocalOptionsAsArgument_MethodWithJsonOptionsArgument_ExprStatement_ReturnsNonOptions_NoWarn() + => VerifyCS.VerifyAnalyzerAsync(""" + using System.Text.Json; + + class Program + { + static string Serialize(T value) + { + T newValue; + newValue = ProcessOptions(new JsonSerializerOptions()); + return JsonSerializer.Serialize(newValue); + } + + static T ProcessOptions(JsonSerializerOptions options) + { + return default; + } + } + """); + [Fact] public Task CS_UseNewLocalOptionsAsArgument_EscapeCurrentScope_NonSerializerMethod_NoWarn() => VerifyCS.VerifyAnalyzerAsync(""" @@ -304,6 +480,7 @@ public Task CS_UseNewLocalOptionsAsArgument_FieldAssignment_NoWarn(string snippe test.TestCode = $$""" using System; using System.Text.Json; + using System.Threading; class Program { @@ -358,27 +535,49 @@ private static List CS_UseNewLocalOptionsAsArgument_Assignment_TheoryDat { string target = useField ? "s_options" : "Options"; - return new List() + var l = new List() { - $@"JsonSerializerOptions opt = new JsonSerializerOptions(); - {target} = opt;", - - $@"JsonSerializerOptions opt; - {target} = opt = new JsonSerializerOptions();", - - $@"JsonSerializerOptions opt = {target} = new JsonSerializerOptions();", - - $@"JsonSerializerOptions opt = {target} ??= new JsonSerializerOptions();", - - $@"JsonSerializerOptions opt = new JsonSerializerOptions(); - {target} ??= opt;", + $""" + JsonSerializerOptions opt = new JsonSerializerOptions(); + {target} = opt; + """, + + $""" + JsonSerializerOptions opt; + {target} = opt = new JsonSerializerOptions(); + """, + + $"JsonSerializerOptions opt = {target} = new JsonSerializerOptions();", + + $"JsonSerializerOptions opt = {target} ??= new JsonSerializerOptions();", + + $""" + JsonSerializerOptions opt = new JsonSerializerOptions(); + {target} ??= opt; + """, + + $""" + JsonSerializerOptions opt = new JsonSerializerOptions(); + ({target}, _) = (opt, 42); + """, + + $""" + JsonSerializerOptions opt = new JsonSerializerOptions(); + (({target}, _), _) = ((opt, 42), 42); + """ + }; - $@"JsonSerializerOptions opt = new JsonSerializerOptions(); - ({target}, _) = (opt, 42);", + if (useField) + { + l.Add(""" + JsonSerializerOptions opt = + s_options ?? + Interlocked.CompareExchange(ref s_options, new JsonSerializerOptions() {WriteIndented = true}, null) ?? + s_options; + """); + } - $@"JsonSerializerOptions opt = new JsonSerializerOptions(); - (({target}, _), _) = ((opt, 42), 42);" - }; + return l; } [Fact] @@ -433,7 +632,7 @@ public Task CS_UseNewLocalOptionsAsArgument_MultiAssignment_EscapeCurrentScope_F class Program { - static JsonSerializerOptions s_options; + static JsonSerializerOptions s_options; static string Serialize(T value) { @@ -442,7 +641,7 @@ static string Serialize(T value) s_options = {{expression}}; - return JsonSerializer.Serialize(value, opt1); + return JsonSerializer.Serialize(value, opt1); } } """); @@ -457,14 +656,14 @@ public Task CS_UseNewLocalOptionsAsArgument_MultiAssignment_EscapeCurrentScope_F class Program { - static JsonSerializerOptions s_options; + static JsonSerializerOptions s_options; static string Serialize(T value) { JsonSerializerOptions opt1, opt2; {{expression}} = new JsonSerializerOptions(); - return JsonSerializer.Serialize(value, opt1); + return JsonSerializer.Serialize(value, opt1); } } """); @@ -531,6 +730,96 @@ string LocalFunc() } } """); + + [Theory] + [InlineData(""" + for (int i = 0; i < values.Length; i++) + { + concatJson += JsonSerializer.Serialize(values[i], opt); + } + """)] + [InlineData(""" + foreach (T value in values) + { + concatJson += JsonSerializer.Serialize(value, opt); + } + """)] + [InlineData(""" + if (values.Length == 0) + return concatJson; + + int i = 0; + do + { + concatJson += JsonSerializer.Serialize(values[i++], opt); + } + while (i < values.Length); + """)] + [InlineData(""" + int i = 0; + while (i < values.Length) + { + concatJson += JsonSerializer.Serialize(values[i++], opt); + } + """)] + public Task CS_UseNewLocalOptionsAsArgument_JsonSerializerOptions_BeforeLoop_NoWarn(string loop) + => VerifyCS.VerifyAnalyzerAsync($$""" + using System.Text.Json; + + class Program + { + static string Serialize(T[] values) + { + JsonSerializerOptions opt = new JsonSerializerOptions(); + string concatJson = ""; + + {{loop}} + + return concatJson; + } + } + """); + + [Theory] + [InlineData(""" + For i = 0 To values.Length + concatJson += JsonSerializer.Serialize(values(i), opt) + Next + """)] + [InlineData(""" + For Each value In values + concatJson += JsonSerializer.Serialize(value, opt) + Next + """)] + [InlineData(""" + Dim i = 0 + Do While i < values.Length + concatJson += JsonSerializer.Serialize(values(i), opt) + i = i + 1 + Loop + """)] + [InlineData(""" + Dim i = 0 + Do + concatJson += JsonSerializer.Serialize(values(i), opt) + i = i + 1 + Loop While i < values.Length + """)] + public Task VB_UseNewLocalOptionsAsArgument_JsonSerializerOptions_BeforeLoop_NoWarn(string loop) + => VerifyVB.VerifyAnalyzerAsync($$""" + Imports System.Text.Json + + Class Program + Shared Function Serialize(Of T)(values As T()) As String + Dim opt = New JsonSerializerOptions() + Dim concatJson = "" + + {{loop}} + + return concatJson + End Function + End Class + """); #endregion } } From ab446be2117eeeca4da239226804a968c9628808 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Sun, 15 Oct 2023 21:36:08 +0200 Subject: [PATCH 17/30] Apply PR comments --- .../CSharpDoNotDirectlyAwaitATask.cs | 28 --------- .../DoNotDirectlyAwaitATask.cs | 14 +++-- .../Microsoft.CodeAnalysis.NetAnalyzers.sarif | 58 +++++++------------ src/NetAnalyzers/RulesMissingDocumentation.md | 1 - .../DoNotDirectlyAwaitATaskTests.cs | 4 +- .../BasicDoNotDirectlyAwaitATask.vb | 13 ----- 6 files changed, 31 insertions(+), 87 deletions(-) delete mode 100644 src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs delete mode 100644 src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs deleted file mode 100644 index 71b9323e07..0000000000 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpDoNotDirectlyAwaitATask.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. - -using Analyzer.Utilities.Extensions; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Operations; -using Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines; - -namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines -{ - [DiagnosticAnalyzer(LanguageNames.CSharp)] - public sealed class CSharpDoNotDirectlyAwaitATask : DoNotDirectlyAwaitATaskAnalyzer - { - protected override void RegisterLanguageSpecificChecks(OperationBlockStartAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) - { - context.RegisterOperationAction(ctx => AnalyzeAwaitForEachLoopOperation(ctx, configuredAsyncEnumerable), OperationKind.Loop); - } - - private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) - { - if (context.Operation is IForEachLoopOperation { IsAsynchronous: true, Collection.Type: not null } forEachOperation - && !forEachOperation.Collection.Type.OriginalDefinition.Equals(configuredAsyncEnumerable, SymbolEqualityComparer.Default)) - { - context.ReportDiagnostic(forEachOperation.Collection.CreateDiagnostic(Rule)); - } - } - } -} \ No newline at end of file diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs index b5cb5b3524..40c706b9a1 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs @@ -16,7 +16,8 @@ namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines /// /// CA2007: /// - public abstract class DoNotDirectlyAwaitATaskAnalyzer : DiagnosticAnalyzer + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public sealed class DoNotDirectlyAwaitATaskAnalyzer : DiagnosticAnalyzer { internal const string RuleId = "CA2007"; @@ -81,17 +82,20 @@ public override void Initialize(AnalysisContext context) if (configuredAsyncEnumerable is not null) { - RegisterLanguageSpecificChecks(context, configuredAsyncEnumerable); + context.RegisterOperationAction(ctx => AnalyzeAwaitForEachLoopOperation(ctx, configuredAsyncEnumerable), OperationKind.Loop); } } }); }); } -#pragma warning disable RS1012 - protected virtual void RegisterLanguageSpecificChecks(OperationBlockStartAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) -#pragma warning restore RS1012 + private static void AnalyzeAwaitForEachLoopOperation(OperationAnalysisContext context, INamedTypeSymbol configuredAsyncEnumerable) { + if (context.Operation is IForEachLoopOperation { IsAsynchronous: true, Collection.Type: not null } forEachOperation + && !forEachOperation.Collection.Type.OriginalDefinition.Equals(configuredAsyncEnumerable, SymbolEqualityComparer.Default)) + { + context.ReportDiagnostic(forEachOperation.Collection.CreateDiagnostic(Rule)); + } } private static void AnalyzeAwaitOperation(OperationAnalysisContext context, ImmutableArray taskTypes) diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index 60c063c1b3..e9e8855061 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -436,25 +436,6 @@ ] } }, - "CA2007": { - "id": "CA2007", - "shortDescription": "Consider calling ConfigureAwait on the awaited task", - "fullDescription": "When an asynchronous method awaits a Task directly, continuation occurs in the same thread that created the task. Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. Call ConfigureAwait(false) on the task to schedule continuations to the thread pool, thereby avoiding a deadlock on the UI thread. Passing false is a good option for app-independent libraries. Calling ConfigureAwait(true) on the task has the same behavior as not explicitly calling ConfigureAwait. By explicitly calling this method, you're letting readers know you intentionally want to perform the continuation on the original synchronization context.", - "defaultLevel": "warning", - "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007", - "properties": { - "category": "Reliability", - "isEnabledByDefault": false, - "typeName": "CSharpDoNotDirectlyAwaitATask", - "languages": [ - "C#" - ], - "tags": [ - "Telemetry", - "EnabledRuleInAggressiveMode" - ] - } - }, "CA2014": { "id": "CA2014", "shortDescription": "Do not use stackalloc in loops", @@ -3431,6 +3412,26 @@ ] } }, + "CA2007": { + "id": "CA2007", + "shortDescription": "Consider calling ConfigureAwait on the awaited task", + "fullDescription": "When an asynchronous method awaits a Task directly, continuation occurs in the same thread that created the task. Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. Call ConfigureAwait(false) on the task to schedule continuations to the thread pool, thereby avoiding a deadlock on the UI thread. Passing false is a good option for app-independent libraries. Calling ConfigureAwait(true) on the task has the same behavior as not explicitly calling ConfigureAwait. By explicitly calling this method, you're letting readers know you intentionally want to perform the continuation on the original synchronization context.", + "defaultLevel": "warning", + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007", + "properties": { + "category": "Reliability", + "isEnabledByDefault": false, + "typeName": "DoNotDirectlyAwaitATaskAnalyzer", + "languages": [ + "C#", + "Visual Basic" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA2008": { "id": "CA2008", "shortDescription": "Do not create tasks without passing a TaskScheduler", @@ -6599,25 +6600,6 @@ ] } }, - "CA2007": { - "id": "CA2007", - "shortDescription": "Consider calling ConfigureAwait on the awaited task", - "fullDescription": "When an asynchronous method awaits a Task directly, continuation occurs in the same thread that created the task. Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. Call ConfigureAwait(false) on the task to schedule continuations to the thread pool, thereby avoiding a deadlock on the UI thread. Passing false is a good option for app-independent libraries. Calling ConfigureAwait(true) on the task has the same behavior as not explicitly calling ConfigureAwait. By explicitly calling this method, you're letting readers know you intentionally want to perform the continuation on the original synchronization context.", - "defaultLevel": "warning", - "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007", - "properties": { - "category": "Reliability", - "isEnabledByDefault": false, - "typeName": "BasicDoNotDirectlyAwaitATask", - "languages": [ - "Visual Basic" - ], - "tags": [ - "Telemetry", - "EnabledRuleInAggressiveMode" - ] - } - }, "CA2016": { "id": "CA2016", "shortDescription": "Forward the 'CancellationToken' parameter to methods", diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md index 26c9c1b9bb..118c7c6d88 100644 --- a/src/NetAnalyzers/RulesMissingDocumentation.md +++ b/src/NetAnalyzers/RulesMissingDocumentation.md @@ -6,7 +6,6 @@ CA1510 | | Use ArgumentException throw helper | CA1512 | | Use ArgumentOutOfRangeException throw helper | CA1513 | | Use ObjectDisposedException throw helper | -CA1514 | | Avoid redundant length argument | CA1515 | | Consider making public types internal | CA1856 | | Incorrect usage of ConstantExpected attribute | CA1857 | | A constant is expected for the parameter | diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs index 25b5179c15..189ea95876 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotDirectlyAwaitATaskTests.cs @@ -7,10 +7,10 @@ using Xunit; using Microsoft.CodeAnalysis.CSharp; using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< - Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines.CSharpDoNotDirectlyAwaitATask, + Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskAnalyzer, Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskFixer>; using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< - Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines.BasicDoNotDirectlyAwaitATask, + Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskAnalyzer, Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.DoNotDirectlyAwaitATaskFixer>; namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.UnitTests diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb deleted file mode 100644 index dc8297e200..0000000000 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicDoNotDirectlyAwaitATask.vb +++ /dev/null @@ -1,13 +0,0 @@ -' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. - -Imports Microsoft.CodeAnalysis -Imports Microsoft.CodeAnalysis.Diagnostics -Imports Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines - -Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines - - - Public NotInheritable Class BasicDoNotDirectlyAwaitATask - Inherits DoNotDirectlyAwaitATaskAnalyzer - End Class -End Namespace \ No newline at end of file From ea2bf5141f41ac972c0f2feebcabad42881a9df7 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 16 Oct 2023 22:31:22 +0200 Subject: [PATCH 18/30] Apply PR comments. --- .../CSharp/AnalyzerReleases.Unshipped.md | 3 +- ...DeclaredSymbolAlwaysReturnsNullAnalyzer.cs | 41 +++++++++++++++--- .../CodeAnalysisDiagnosticsResources.resx | 6 +++ .../Core/DiagnosticIds.cs | 1 + .../CodeAnalysisDiagnosticsResources.cs.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.de.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.es.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.fr.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.it.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.ja.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.ko.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.pl.xlf | 10 +++++ ...CodeAnalysisDiagnosticsResources.pt-BR.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.ru.xlf | 10 +++++ .../CodeAnalysisDiagnosticsResources.tr.xlf | 10 +++++ ...deAnalysisDiagnosticsResources.zh-Hans.xlf | 10 +++++ ...deAnalysisDiagnosticsResources.zh-Hant.xlf | 10 +++++ .../Microsoft.CodeAnalysis.Analyzers.md | 12 ++++++ .../Microsoft.CodeAnalysis.Analyzers.sarif | 17 ++++++++ .../RulesMissingDocumentation.md | 1 + ...redSymbolAlwaysReturnsNullAnalyzerTests.cs | 43 ++++++++++++++++--- src/NetAnalyzers/RulesMissingDocumentation.md | 1 - src/Utilities/Compiler/WellKnownTypeNames.cs | 3 +- 23 files changed, 242 insertions(+), 16 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md index c989a082ec..1e4fb7afae 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md @@ -4,4 +4,5 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- -RS1039 | MicrosoftCodeAnalysisCorrectness | Warning | SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer \ No newline at end of file +RS1039 | MicrosoftCodeAnalysisCorrectness | Warning | SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer +RS1040 | MicrosoftCodeAnalysisCorrectness | Warning | CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs index 5920eb60cd..6fd1aa6086 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer : DiagnosticAnalyzer { - private static readonly DiagnosticDescriptor DiagnosticDescriptor = new( + internal static readonly DiagnosticDescriptor DiagnosticDescriptor = new( DiagnosticIds.SemanticModelGetDeclaredSymbolAlwaysReturnsNull, CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullTitle)), CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullMessage)), @@ -27,6 +27,17 @@ public sealed class CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyze helpLinkUri: null, customTags: WellKnownDiagnosticTagsExtensions.Telemetry); + internal static readonly DiagnosticDescriptor FieldDiagnosticDescriptor = new( + DiagnosticIds.SemanticModelGetDeclaredSymbolAlwaysReturnsNullForField, + CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullTitle)), + CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullForFieldMessage)), + DiagnosticCategory.MicrosoftCodeAnalysisCorrectness, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: CreateLocalizableResourceString(nameof(SemanticModelGetDeclaredSymbolAlwaysReturnsNullForFieldDescription)), + helpLinkUri: null, + customTags: WellKnownDiagnosticTagsExtensions.Telemetry); + public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); @@ -37,6 +48,8 @@ public override void Initialize(AnalysisContext context) IMethodSymbol? getDeclaredSymbolMethod; if (!typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpCSharpExtensions, out var csharpExtensions) || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisModelExtensions, out var modelExtensions) + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax, out var baseFieldDeclaration) + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisSyntaxNode, out var syntaxNode) || (getDeclaredSymbolMethod = modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault() as IMethodSymbol) is null) { return; @@ -47,24 +60,38 @@ public override void Initialize(AnalysisContext context) .Where(m => m.Parameters.Length >= 2) .Select(m => m.Parameters[1].Type); - context.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, allowedTypes), OperationKind.Invocation); + context.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, allowedTypes, baseFieldDeclaration, syntaxNode), OperationKind.Invocation); }); } - private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodSymbol getDeclaredSymbolMethod, IEnumerable allowedTypes) + private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodSymbol getDeclaredSymbolMethod, IEnumerable allowedTypes, INamedTypeSymbol baseFieldDeclarationType, INamedTypeSymbol syntaxNodeType) { var invocation = (IInvocationOperation)context.Operation; if (SymbolEqualityComparer.Default.Equals(invocation.TargetMethod, getDeclaredSymbolMethod)) { - var syntaxNodeType = invocation.Arguments[1].Value.WalkDownConversion().Type; - if (syntaxNodeType is not null && allowedTypes.Any(type => syntaxNodeType.DerivesFrom(type, baseTypesOnly: true, checkTypeParameterConstraints: false))) + var syntaxNodeDerivingType = invocation.Arguments[1].Value.WalkDownConversion().Type; + if (syntaxNodeDerivingType is null || syntaxNodeDerivingType.Equals(syntaxNodeType)) + { + return; + } + + Diagnostic? diagnostic = null; + if (syntaxNodeDerivingType.DerivesFrom(baseFieldDeclarationType)) + { + diagnostic = invocation.CreateDiagnostic(FieldDiagnosticDescriptor, syntaxNodeDerivingType.Name); + } + else if (allowedTypes.All(type => !syntaxNodeDerivingType.DerivesFrom(type, baseTypesOnly: true, checkTypeParameterConstraints: false))) + { + diagnostic = invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeDerivingType.Name); + } + + if (diagnostic is not null) { - var diagnostic = invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeType.Name); context.ReportDiagnostic(diagnostic); } } } - public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptor); + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptor, FieldDiagnosticDescriptor); } } \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx index 1411085b89..e5ee9451e4 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx @@ -580,4 +580,10 @@ This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs index 58a94c951a..9d2f470ee2 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/DiagnosticIds.cs @@ -43,6 +43,7 @@ internal static class DiagnosticIds public const string AddCompilationEndCustomTagRuleId = "RS1037"; public const string DoNotRegisterCompilerTypesWithBadAssemblyReferenceRuleId = "RS1038"; public const string SemanticModelGetDeclaredSymbolAlwaysReturnsNull = "RS1039"; + public const string SemanticModelGetDeclaredSymbolAlwaysReturnsNullForField = "RS1040"; // Release tracking analyzer IDs public const string DeclareDiagnosticIdInAnalyzerReleaseRuleId = "RS2000"; diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf index 8527c2a633..2de74967db 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf index 030c4ef9b2..1e6fd9932e 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf index 11de3e5e6d..edc7945de6 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf index 359d9f7536..8744cff59f 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf index 8f5478263f..c685f4bbd4 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf index cfafe2747f..c2e3ff5057 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf index 8deca64dff..c2a965346c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf index 4bd77f1580..458bfbd183 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf index 527466cc15..e3ad15a9ef 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf index 501dbe8278..936f61a9c3 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf index 259dcbe2eb..f04be9091c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf index 1681f561c0..a8e66576e4 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf index 6c23713b84..f0a53f7c28 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf @@ -412,6 +412,16 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + + + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' + + A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md index 6eb637de81..758b5278b2 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md @@ -484,6 +484,18 @@ Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatem |CodeFix|False| --- +## RS1040: This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' + +Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead. + +|Item|Value| +|-|-| +|Category|MicrosoftCodeAnalysisCorrectness| +|Enabled|True| +|Severity|Warning| +|CodeFix|False| +--- + ## [RS2000](https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md): Add analyzer diagnostic IDs to analyzer release All supported analyzer diagnostic IDs should be part of an analyzer release. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif index 7ff512e604..f4e68012a4 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif @@ -885,6 +885,23 @@ "Telemetry" ] } + }, + "RS1040": { + "id": "RS1040", + "shortDescription": "This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null'", + "fullDescription": "Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'FieldDeclarationSyntax' or 'EventFieldDeclarationSyntax' will always return 'null'. Call 'GetDeclaredSymbol' with the variable declarators from the field instead.", + "defaultLevel": "warning", + "properties": { + "category": "MicrosoftCodeAnalysisCorrectness", + "isEnabledByDefault": true, + "typeName": "CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer", + "languages": [ + "C#" + ], + "tags": [ + "Telemetry" + ] + } } } }, diff --git a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md index 11a466eff1..07dab69c39 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/RulesMissingDocumentation.md @@ -38,3 +38,4 @@ RS1035 | | Do not use APIs banned for analyzers | RS1036 | | Specify analyzer banned API enforcement setting | RS1037 | | Add "CompilationEnd" custom tag to compilation end diagnostic descriptor | RS1039 | | This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' | +RS1040 | | This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' | diff --git a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs index 57c8a1eec1..e24cf624dc 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers; +using Microsoft.CodeAnalysis.Testing; using Xunit; using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers.CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer, @@ -11,12 +13,36 @@ namespace Microsoft.CodeAnalysis.Analyzers.UnitTests.MetaAnalyzers public sealed class SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests { [Theory] - [InlineData("GlobalStatementSyntax")] - [InlineData("IncompleteMemberSyntax")] + [InlineData("AccessorListSyntax")] + [InlineData("AwaitExpressionSyntax")] + [InlineData("ForStatementSyntax")] + [InlineData("GenericNameSyntax")] + [InlineData("ParameterListSyntax")] + [InlineData("LockStatementSyntax")] + public Task Diagnostic(string type) + { + var code = $@" +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +public class Test {{ + public void M(SemanticModel semanticModel, {type} syntax) {{ + var x = {{|#0:semanticModel.GetDeclaredSymbol(syntax)|}}; + }} +}}"; + + return new VerifyCS.Test + { + TestCode = code, + ExpectedDiagnostics = { new DiagnosticResult(CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.DiagnosticDescriptor).WithLocation(0).WithArguments(type) } + }.RunAsync(); + } + + [Theory] [InlineData("BaseFieldDeclarationSyntax")] [InlineData("FieldDeclarationSyntax")] [InlineData("EventFieldDeclarationSyntax")] - public Task Diagnostic(string type) + public Task Field_Diagnostic(string type) { var code = $@" using Microsoft.CodeAnalysis; @@ -24,16 +50,23 @@ public Task Diagnostic(string type) public class Test {{ public void M(SemanticModel semanticModel, {type} syntax) {{ - var x = [|semanticModel.GetDeclaredSymbol(syntax)|]; + var x = {{|#0:semanticModel.GetDeclaredSymbol(syntax)|}}; }} }}"; - return VerifyCS.VerifyAnalyzerAsync(code); + return new VerifyCS.Test + { + TestCode = code, + ExpectedDiagnostics = { new DiagnosticResult(CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.FieldDiagnosticDescriptor).WithLocation(0).WithArguments(type) } + }.RunAsync(); } [Theory] [InlineData("SyntaxNode")] [InlineData("TypeDeclarationSyntax")] + [InlineData("ClassDeclarationSyntax")] + [InlineData("EnumMemberDeclarationSyntax")] + [InlineData("NamespaceDeclarationSyntax")] public Task NoDiagnostic(string type) { var code = $@" diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md index 26c9c1b9bb..118c7c6d88 100644 --- a/src/NetAnalyzers/RulesMissingDocumentation.md +++ b/src/NetAnalyzers/RulesMissingDocumentation.md @@ -6,7 +6,6 @@ CA1510 | | Use ArgumentException throw helper | CA1512 | | Use ArgumentOutOfRangeException throw helper | CA1513 | | Use ObjectDisposedException throw helper | -CA1514 | | Avoid redundant length argument | CA1515 | | Consider making public types internal | CA1856 | | Incorrect usage of ConstantExpected attribute | CA1857 | | A constant is expected for the parameter | diff --git a/src/Utilities/Compiler/WellKnownTypeNames.cs b/src/Utilities/Compiler/WellKnownTypeNames.cs index 691842d65f..e0b85d116e 100644 --- a/src/Utilities/Compiler/WellKnownTypeNames.cs +++ b/src/Utilities/Compiler/WellKnownTypeNames.cs @@ -37,8 +37,6 @@ internal static class WellKnownTypeNames public const string MicrosoftCodeAnalysisCSharpCSharpExtensions = "Microsoft.CodeAnalysis.CSharp.CSharpExtensions"; public const string MicrosoftCodeAnalysisCSharpExtensions = "Microsoft.CodeAnalysis.CSharpExtensions"; public const string MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.BaseFieldDeclarationSyntax"; - public const string MicrosoftCodeAnalysisCSharpSyntaxGlobalStatementSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.GlobalStatementSyntax"; - public const string MicrosoftCodeAnalysisCSharpSyntaxIncompleteMemberSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.IncompleteMemberSyntax"; public const string MicrosoftCodeAnalysisDiagnostic = "Microsoft.CodeAnalysis.Diagnostic"; public const string MicrosoftCodeAnalysisDiagnosticDescriptor = "Microsoft.CodeAnalysis.DiagnosticDescriptor"; public const string MicrosoftCodeAnalysisDiagnosticsAnalysisContext = "Microsoft.CodeAnalysis.Diagnostics.AnalysisContext"; @@ -65,6 +63,7 @@ internal static class WellKnownTypeNames public const string MicrosoftCodeAnalysisModelExtensions = "Microsoft.CodeAnalysis.ModelExtensions"; public const string MicrosoftCodeAnalysisSharedCollectionsTemporaryArrayExtensions = "Microsoft.CodeAnalysis.Shared.Collections.TemporaryArrayExtensions"; public const string MicrosoftCodeAnalysisSymbolKind = "Microsoft.CodeAnalysis.SymbolKind"; + public const string MicrosoftCodeAnalysisSyntaxNode = "Microsoft.CodeAnalysis.SyntaxNode"; public const string MicrosoftCodeAnalysisVisualBasicExtensions = "Microsoft.CodeAnalysis.VisualBasicExtensions"; public const string MicrosoftCodeAnalysisVisualBasicVisualBasicCompilation = "Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation"; public const string MicrosoftCodeAnalysisVisualBasicVisualBasicExtensions = "Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions"; From 28a372ce631fa3ec74183992617a119bf673cc37 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 17 Oct 2023 12:58:44 +0200 Subject: [PATCH 19/30] Do not raise CA1065 when in delegate --- ...NotRaiseExceptionsInUnexpectedLocations.cs | 26 ++++++++++++- ...iseExceptionsInUnexpectedLocationsTests.cs | 39 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs index 36b38ea1c4..1a5690a951 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs @@ -84,7 +84,7 @@ public override void Initialize(AnalysisContext context) // Find out if this given method is one of the interesting categories of methods. // For example, certain Equals methods or certain accessors etc. - MethodCategory methodCategory = methodCategories.FirstOrDefault(l => l.IsMatch(methodSymbol, compilation)); + MethodCategory? methodCategory = methodCategories.FirstOrDefault(l => l.IsMatch(methodSymbol, compilation)); if (methodCategory == null) { return; @@ -94,8 +94,14 @@ public override void Initialize(AnalysisContext context) // Throw statements. operationBlockContext.RegisterOperationAction(operationContext => { + var throwOperation = (IThrowOperation)operationContext.Operation; + if (ThrowOperationOccursInDelegate(throwOperation)) + { + return; + } + // Get ThrowOperation's ExceptionType - if (((IThrowOperation)operationContext.Operation).GetThrownExceptionType() is INamedTypeSymbol thrownExceptionType && thrownExceptionType.DerivesFrom(exceptionType)) + if (throwOperation.GetThrownExceptionType() is INamedTypeSymbol thrownExceptionType && thrownExceptionType.DerivesFrom(exceptionType)) { // If no exceptions are allowed or if the thrown exceptions is not an allowed one.. if (methodCategory.AllowedExceptions.IsEmpty || !methodCategory.AllowedExceptions.Any(n => thrownExceptionType.IsAssignableTo(n, compilation))) @@ -109,6 +115,22 @@ public override void Initialize(AnalysisContext context) }); } + private static bool ThrowOperationOccursInDelegate(IThrowOperation throwOperation) + { + var throwParent = throwOperation.Parent; + while (throwParent is not null) + { + if (throwParent is IDelegateCreationOperation) + { + return true; + } + + throwParent = throwParent.Parent; + } + + return false; + } + /// /// This object describes a class of methods where exception throwing statements should be analyzed. /// diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocationsTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocationsTests.cs index 18fca105b5..4c8d2c9ef3 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocationsTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocationsTests.cs @@ -573,6 +573,45 @@ End Class await VerifyVB.VerifyAnalyzerAsync(code, GetBasicNoExceptionsResultAt(6, 9, "Finalize", "Exception")); } + + [Fact, WorkItem(6963, "https://github.com/dotnet/roslyn-analyzers/issues/6963")] + public Task Lambda_NoDiagnostic() + { + const string code = """ + using System; + + public class ShouldNotViolate + { + static readonly Action a; + + static ShouldNotViolate() + { + a = () => throw new DivideByZeroException(); + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } + + [Fact, WorkItem(6963, "https://github.com/dotnet/roslyn-analyzers/issues/6963")] + public Task VB_Lambda_NoDiagnostic() + { + const string code = """ + Imports System + + Public Class ShouldNotViolate + Shared ReadOnly a As Action + + Shared Sub New() + a = Sub () Throw New DivideByZeroException() + End Sub + End Class + """; + + return VerifyVB.VerifyAnalyzerAsync(code); + } + #endregion #region Operator tests From 5b1a52b195e6f69245c7648a85b050e6be425a8b Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 17 Oct 2023 13:02:34 +0200 Subject: [PATCH 20/30] Add newline --- .../CSharp/AnalyzerReleases.Unshipped.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md index 1e4fb7afae..adf1e316cc 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/AnalyzerReleases.Unshipped.md @@ -5,4 +5,4 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- RS1039 | MicrosoftCodeAnalysisCorrectness | Warning | SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer -RS1040 | MicrosoftCodeAnalysisCorrectness | Warning | CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer \ No newline at end of file +RS1040 | MicrosoftCodeAnalysisCorrectness | Warning | CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer From 42825d9347b3a338227f7c92e488b2c74c6eca2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Wed, 18 Oct 2023 12:05:54 +0200 Subject: [PATCH 21/30] Replace explicit richCodeNavigationEnvironment in azure-pipelines-richnav.yml This is managed by the arcade defaults, we should be using the "internal" environment as requested by the RichNav team. --- azure-pipelines-richnav.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/azure-pipelines-richnav.yml b/azure-pipelines-richnav.yml index b310c305aa..c988f20fd9 100644 --- a/azure-pipelines-richnav.yml +++ b/azure-pipelines-richnav.yml @@ -10,7 +10,6 @@ stages: - template: /eng/common/templates/jobs/jobs.yml parameters: enableRichCodeNavigation: true - richCodeNavigationEnvironment: "production" richCodeNavigationLanguage: "csharp" jobs: - job: Debug_Build From fe9e6340b1f0ffd9568feb68bd190e6b6f66551a Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 20 Oct 2023 11:28:32 +0300 Subject: [PATCH 22/30] Adjust source generator verifier for broader usability --- .../Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs b/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs index 62948431a8..1392c321f8 100644 --- a/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs +++ b/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs @@ -15,6 +15,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; @@ -90,7 +91,7 @@ protected override ParseOptions CreateParseOptions() expectedNames.Add(Path.GetFileName(tree.FilePath)); } - var currentTestPrefix = $"{typeof(ResxGeneratorTests).Assembly.GetName().Name}.Resources.{ResourceName}."; + var currentTestPrefix = $"{Assembly.GetExecutingAssembly().GetName().Name}.Resources.{ResourceName}."; foreach (var name in GetType().Assembly.GetManifestResourceNames()) { if (!name.StartsWith(currentTestPrefix, StringComparison.Ordinal)) @@ -109,7 +110,7 @@ protected override ParseOptions CreateParseOptions() public Test AddGeneratedSources() { - var expectedPrefix = $"{typeof(ResxGeneratorTests).Assembly.GetName().Name}.Resources.{ResourceName}."; + var expectedPrefix = $"{Assembly.GetExecutingAssembly().GetName().Name}.Resources.{ResourceName}."; foreach (var resourceName in typeof(Test).Assembly.GetManifestResourceNames()) { if (!resourceName.StartsWith(expectedPrefix, StringComparison.Ordinal)) @@ -117,10 +118,10 @@ public Test AddGeneratedSources() continue; } - using var resourceStream = typeof(ResxGeneratorTests).Assembly.GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException(); + using var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException(); using var reader = new StreamReader(resourceStream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4096, leaveOpen: true); var name = resourceName.Substring(expectedPrefix.Length); - TestState.GeneratedSources.Add((typeof(CSharpResxGenerator), name, SourceText.From(reader.ReadToEnd(), Encoding.UTF8, SourceHashAlgorithm.Sha256))); + TestState.GeneratedSources.Add((typeof(TSourceGenerator), name, SourceText.From(reader.ReadToEnd(), Encoding.UTF8, SourceHashAlgorithm.Sha256))); } return this; From 6f0cb188b0851635ba5afa111f3251f23afedc75 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 20 Oct 2023 11:30:13 +0300 Subject: [PATCH 23/30] Update one more --- .../Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs b/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs index 1392c321f8..c4d76e8e4e 100644 --- a/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs +++ b/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs @@ -111,7 +111,7 @@ protected override ParseOptions CreateParseOptions() public Test AddGeneratedSources() { var expectedPrefix = $"{Assembly.GetExecutingAssembly().GetName().Name}.Resources.{ResourceName}."; - foreach (var resourceName in typeof(Test).Assembly.GetManifestResourceNames()) + foreach (var resourceName in Assembly.GetExecutingAssembly().GetManifestResourceNames()) { if (!resourceName.StartsWith(expectedPrefix, StringComparison.Ordinal)) { From efd7c16bfe1b3a9ebcd91ffd6df14062987587ae Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 20 Oct 2023 11:51:33 +0300 Subject: [PATCH 24/30] Remove unused using --- .../Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs b/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs index c4d76e8e4e..f09a5835b5 100644 --- a/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs +++ b/src/Microsoft.CodeAnalysis.ResxSourceGenerator/Microsoft.CodeAnalysis.ResxSourceGenerator.UnitTests/Verifiers/CSharpSourceGeneratorVerifier`1+Test.cs @@ -22,7 +22,6 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Testing; -using Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Testing.Verifiers; using Microsoft.CodeAnalysis.Text; From 6e2f18acc363e0484cb96327bbced7344d157642 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 20 Oct 2023 14:28:27 -0500 Subject: [PATCH 25/30] Remove special case MicrosoftCodeAnalysisVersionForBannedApiAnalyzersTests --- eng/Versions.props | 1 - ...alysis.BannedApiAnalyzers.UnitTests.csproj | 4 +- ...strictedInternalsVisibleToAnalyzerTests.cs | 47 ++++++++++++------- .../UnitTests/SymbolIsBannedAnalyzerTests.cs | 12 +++++ 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 27a6d9ad2c..07043a53b1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -64,7 +64,6 @@ 3.11.0 1.2.1 3.11.0 - 3.11.0 3.11.0 3.11.0 4.0.1 diff --git a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/Microsoft.CodeAnalysis.BannedApiAnalyzers.UnitTests.csproj b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/Microsoft.CodeAnalysis.BannedApiAnalyzers.UnitTests.csproj index 6381e3f419..3449f60633 100644 --- a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/Microsoft.CodeAnalysis.BannedApiAnalyzers.UnitTests.csproj +++ b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/Microsoft.CodeAnalysis.BannedApiAnalyzers.UnitTests.csproj @@ -4,9 +4,7 @@ $(NetCurrent) true true - - $(MicrosoftCodeAnalysisVersionForBannedApiAnalyzersTests) + $(MicrosoftCodeAnalysisVersionForTests) diff --git a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/RestrictedInternalsVisibleToAnalyzerTests.cs b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/RestrictedInternalsVisibleToAnalyzerTests.cs index cf1373ebac..68fa91d5bd 100644 --- a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/RestrictedInternalsVisibleToAnalyzerTests.cs +++ b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/RestrictedInternalsVisibleToAnalyzerTests.cs @@ -1039,21 +1039,21 @@ public C1(object o) { } }"; var apiConsumerSource = @" -[{|#0:N1.C1|}(typeof({|#1:N1.C1|}))] +[{|#16:{|#0:N1.C1|}(typeof({|#1:N1.C1|}))|}] class C2 { - [{|#2:N1.C1|}(typeof({|#3:N1.C1|}))] + [{|#17:{|#2:N1.C1|}(typeof({|#3:N1.C1|}))|}] private readonly int field; - [{|#4:N1.C1|}(typeof({|#5:N1.C1|}))] - private int Property { [{|#6:N1.C1|}(typeof({|#7:N1.C1|}))] get; } + [{|#18:{|#4:N1.C1|}(typeof({|#5:N1.C1|}))|}] + private int Property { [{|#19:{|#6:N1.C1|}(typeof({|#7:N1.C1|}))|}] get; } - [{|#8:N1.C1|}(typeof({|#9:N1.C1|}))] + [{|#20:{|#8:N1.C1|}(typeof({|#9:N1.C1|}))|}] private event System.EventHandler X; - [{|#10:N1.C1|}(typeof({|#11:N1.C1|}))] - [return: {|#12:N1.C1|}(typeof({|#13:N1.C1|}))] - int M([{|#14:N1.C1|}(typeof({|#15:N1.C1|}))]object c) + [{|#21:{|#10:N1.C1|}(typeof({|#11:N1.C1|}))|}] + [return: {|#22:{|#12:N1.C1|}(typeof({|#13:N1.C1|}))|}] + int M([{|#23:{|#14:N1.C1|}(typeof({|#15:N1.C1|}))|}]object c) { return 0; } @@ -1075,7 +1075,15 @@ await VerifyCSharpAsync(apiProviderSource, apiConsumerSource, GetCSharpResultAt(12, "N1.C1", "N2"), GetCSharpResultAt(13, "N1.C1", "N2"), GetCSharpResultAt(14, "N1.C1", "N2"), - GetCSharpResultAt(15, "N1.C1", "N2") + GetCSharpResultAt(15, "N1.C1", "N2"), + GetCSharpResultAt(16, "N1.C1.C1", "N2"), + GetCSharpResultAt(17, "N1.C1.C1", "N2"), + GetCSharpResultAt(18, "N1.C1.C1", "N2"), + GetCSharpResultAt(19, "N1.C1.C1", "N2"), + GetCSharpResultAt(20, "N1.C1.C1", "N2"), + GetCSharpResultAt(21, "N1.C1.C1", "N2"), + GetCSharpResultAt(22, "N1.C1.C1", "N2"), + GetCSharpResultAt(23, "N1.C1.C1", "N2") ); } @@ -1095,19 +1103,19 @@ End Class End Namespace"; var apiConsumerSource = @" -<{|#0:N1.C1|}(GetType({|#1:N1.C1|}))> +<{|#14:{|#0:N1.C1|}(GetType({|#1:N1.C1|}))|}> Class C2 - <{|#2:N1.C1|}(GetType({|#3:N1.C1|}))> + <{|#15:{|#2:N1.C1|}(GetType({|#3:N1.C1|}))|}> Private ReadOnly field As Integer - <{|#4:N1.C1|}(GetType({|#5:N1.C1|}))> + <{|#16:{|#4:N1.C1|}(GetType({|#5:N1.C1|}))|}> Private ReadOnly Property [Property] As Integer - <{|#6:N1.C1|}(GetType({|#7:N1.C1|}))> + <{|#17:{|#6:N1.C1|}(GetType({|#7:N1.C1|}))|}> Private Event X As System.EventHandler - <{|#8:N1.C1|}(GetType({|#9:N1.C1|}))> - Private Function M(<{|#10:N1.C1|}(GetType({|#11:N1.C1|}))> ByVal c As Object) As <{|#12:N1.C1|}(GetType({|#13:N1.C1|}))> Integer + <{|#18:{|#8:N1.C1|}(GetType({|#9:N1.C1|}))|}> + Private Function M(<{|#19:{|#10:N1.C1|}(GetType({|#11:N1.C1|}))|}> ByVal c As Object) As <{|#20:{|#12:N1.C1|}(GetType({|#13:N1.C1|}))|}> Integer Return 0 End Function End Class"; @@ -1126,7 +1134,14 @@ await VerifyBasicAsync(apiProviderSource, apiConsumerSource, GetBasicResultAt(10, "N1.C1", "N2"), GetBasicResultAt(11, "N1.C1", "N2"), GetBasicResultAt(12, "N1.C1", "N2"), - GetBasicResultAt(13, "N1.C1", "N2") + GetBasicResultAt(13, "N1.C1", "N2"), + GetBasicResultAt(14, "N1.C1.New", "N2"), + GetBasicResultAt(15, "N1.C1.New", "N2"), + GetBasicResultAt(16, "N1.C1.New", "N2"), + GetBasicResultAt(17, "N1.C1.New", "N2"), + GetBasicResultAt(18, "N1.C1.New", "N2"), + GetBasicResultAt(19, "N1.C1.New", "N2"), + GetBasicResultAt(20, "N1.C1.New", "N2") ); } diff --git a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/SymbolIsBannedAnalyzerTests.cs b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/SymbolIsBannedAnalyzerTests.cs index d667f00e16..65362884b8 100644 --- a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/SymbolIsBannedAnalyzerTests.cs +++ b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/UnitTests/SymbolIsBannedAnalyzerTests.cs @@ -966,6 +966,7 @@ class D : C { } var bannedText = @"T:BannedAttribute"; await VerifyCSharpAnalyzerAsync(source, bannedText, + GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -987,6 +988,7 @@ class C var bannedText = @"T:BannedAttribute"; await VerifyCSharpAnalyzerAsync(source, bannedText, + GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -1005,6 +1007,7 @@ class BannedAttribute : Attribute { } var bannedText = @"T:BannedAttribute"; await VerifyCSharpAnalyzerAsync(source, bannedText, + GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -1023,6 +1026,7 @@ class BannedAttribute : Attribute { } var bannedText = @"T:BannedAttribute"; await VerifyCSharpAnalyzerAsync(source, bannedText, + GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -1093,11 +1097,13 @@ class D {} await VerifyCSharpAnalyzerAsync( source, bannedText1, + GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute.BannedAttribute()", ""), GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute.BannedAttribute()", "")); await VerifyCSharpAnalyzerAsync( source, bannedText2, + GetCSharpResultAt(1, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute.BannedAttribute(int)", ""), GetCSharpResultAt(1, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute.BannedAttribute(int)", "")); } @@ -1812,6 +1818,7 @@ End Class var bannedText = @"T:BannedAttribute"; await VerifyBasicAnalyzerAsync(source, bannedText, + GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -1834,6 +1841,7 @@ End Class var bannedText = @"T:BannedAttribute"; await VerifyBasicAnalyzerAsync(source, bannedText, + GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -1854,6 +1862,7 @@ End Class var bannedText = @"T:BannedAttribute"; await VerifyBasicAnalyzerAsync(source, bannedText, + GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -1874,6 +1883,7 @@ End Class var bannedText = @"T:BannedAttribute"; await VerifyBasicAnalyzerAsync(source, bannedText, + GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", ""), GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "BannedAttribute", "")); } @@ -1940,11 +1950,13 @@ End Class await VerifyBasicAnalyzerAsync( source, bannedText1, + GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "Public Sub New()", ""), GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "Public Sub New()", "")); await VerifyBasicAnalyzerAsync( source, bannedText2, + GetBasicResultAt(1, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "Public Sub New(Banned As Integer)", ""), GetBasicResultAt(1, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "Public Sub New(Banned As Integer)", "")); } From 1f8488e7d293d1e0fc2461af5a5c924d395d7792 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 20 Oct 2023 14:38:07 -0500 Subject: [PATCH 26/30] Remove special case MicrosoftCodeAnalysisVersionForPerfSensitiveAnalyzersTests --- eng/Versions.props | 1 - .../Core/ExplicitAllocationAnalyzer.cs | 7 +++++++ ...Analysis.PerformanceSensitiveAnalyzers.UnitTests.csproj | 4 +--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 07043a53b1..05e93a2192 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -65,7 +65,6 @@ 1.2.1 3.11.0 3.11.0 - 3.11.0 4.0.1 3.11.0 3.11.0 diff --git a/src/PerformanceSensitiveAnalyzers/Core/ExplicitAllocationAnalyzer.cs b/src/PerformanceSensitiveAnalyzers/Core/ExplicitAllocationAnalyzer.cs index 534581bd13..99c62aa68f 100644 --- a/src/PerformanceSensitiveAnalyzers/Core/ExplicitAllocationAnalyzer.cs +++ b/src/PerformanceSensitiveAnalyzers/Core/ExplicitAllocationAnalyzer.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; +using Analyzer.Utilities.Lightup; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; @@ -89,6 +90,12 @@ protected override void AnalyzeNode(OperationAnalysisContext context, in Perform if (context.Operation is IObjectCreationOperation or ITypeParameterObjectCreationOperation) { + if (context.Operation.Parent?.Kind == OperationKindEx.Attribute) + { + // Don't report attribute usage as creating a new instance + return; + } + if (context.Operation.Type?.IsReferenceType == true) { context.ReportDiagnostic(context.Operation.CreateDiagnostic(ObjectCreationRule, EmptyMessageArgs)); diff --git a/src/PerformanceSensitiveAnalyzers/UnitTests/Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.csproj b/src/PerformanceSensitiveAnalyzers/UnitTests/Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.csproj index a99d6341b6..b4bbfc860e 100644 --- a/src/PerformanceSensitiveAnalyzers/UnitTests/Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.csproj +++ b/src/PerformanceSensitiveAnalyzers/UnitTests/Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.UnitTests.csproj @@ -9,9 +9,7 @@ $(NoWarn);CA2007 true - - $(MicrosoftCodeAnalysisVersionForPerfSensitiveAnalyzersTests) + $(MicrosoftCodeAnalysisVersionForTests) From 71f054010c2ad2f6ffd8a977addf3e931cb0de04 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Wed, 25 Oct 2023 17:52:28 +0200 Subject: [PATCH 27/30] Apply PR comments --- ...tDeclaredSymbolAlwaysReturnsNullAnalyzer.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs index 6fd1aa6086..ee05499325 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs @@ -38,6 +38,8 @@ public sealed class CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyze helpLinkUri: null, customTags: WellKnownDiagnosticTagsExtensions.Telemetry); + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptor, FieldDiagnosticDescriptor); + public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); @@ -50,7 +52,7 @@ public override void Initialize(AnalysisContext context) || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisModelExtensions, out var modelExtensions) || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax, out var baseFieldDeclaration) || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisSyntaxNode, out var syntaxNode) - || (getDeclaredSymbolMethod = modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault() as IMethodSymbol) is null) + || (getDeclaredSymbolMethod = (IMethodSymbol?)modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault(m => m is IMethodSymbol { Parameters.Length: >= 2 })) is null) { return; } @@ -69,29 +71,21 @@ private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodS var invocation = (IInvocationOperation)context.Operation; if (SymbolEqualityComparer.Default.Equals(invocation.TargetMethod, getDeclaredSymbolMethod)) { - var syntaxNodeDerivingType = invocation.Arguments[1].Value.WalkDownConversion().Type; + var syntaxNodeDerivingType = invocation.Arguments.GetArgumentForParameterAtIndex(1).Value.WalkDownConversion().Type; if (syntaxNodeDerivingType is null || syntaxNodeDerivingType.Equals(syntaxNodeType)) { return; } - Diagnostic? diagnostic = null; if (syntaxNodeDerivingType.DerivesFrom(baseFieldDeclarationType)) { - diagnostic = invocation.CreateDiagnostic(FieldDiagnosticDescriptor, syntaxNodeDerivingType.Name); + context.ReportDiagnostic(invocation.CreateDiagnostic(FieldDiagnosticDescriptor, syntaxNodeDerivingType.Name)); } else if (allowedTypes.All(type => !syntaxNodeDerivingType.DerivesFrom(type, baseTypesOnly: true, checkTypeParameterConstraints: false))) { - diagnostic = invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeDerivingType.Name); - } - - if (diagnostic is not null) - { - context.ReportDiagnostic(diagnostic); + context.ReportDiagnostic(invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeDerivingType.Name)); } } } - - public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptor, FieldDiagnosticDescriptor); } } \ No newline at end of file From da0b5d409a8b70dd5ed8536ec65a62c510d555a5 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Wed, 25 Oct 2023 18:01:36 +0200 Subject: [PATCH 28/30] Fix analyzer description. --- .../Core/CodeAnalysisDiagnosticsResources.resx | 2 +- .../Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf | 4 ++-- .../Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf | 4 ++-- .../Microsoft.CodeAnalysis.Analyzers.md | 2 +- .../Microsoft.CodeAnalysis.Analyzers.sarif | 2 +- 16 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx index e5ee9451e4..1830b9b2dd 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx @@ -572,7 +572,7 @@ Compiler extensions should be implemented in assemblies with compiler-provided references - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. A call to 'SemanticModel.GetDeclaredSymbol({0})' will always return 'null' diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf index 2de74967db..0a264fe937 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf index 1e6fd9932e..b86e6ab84d 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf index edc7945de6..34f2ce69cd 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf index 8744cff59f..c108dd1294 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf index c685f4bbd4..bd6996bcf2 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf index c2e3ff5057..58fd2d49dd 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf index c2a965346c..27af5b0939 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf index 458bfbd183..5ccc97b52c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf index e3ad15a9ef..da901cff9c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf index 936f61a9c3..8d6bb7762b 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf index f04be9091c..100aaf61bf 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf index a8e66576e4..b7ab8b58be 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf index f0a53f7c28..abb58a39b1 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf @@ -408,8 +408,8 @@ - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. - Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. + Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md index 758b5278b2..c93a971ec6 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.md @@ -474,7 +474,7 @@ Types which implement compiler extension points should not be declared in assemb ## RS1039: This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null' -Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'. +Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'. |Item|Value| |-|-| diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif index f4e68012a4..b5341da80c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif +++ b/src/Microsoft.CodeAnalysis.Analyzers/Microsoft.CodeAnalysis.Analyzers.sarif @@ -872,7 +872,7 @@ "RS1039": { "id": "RS1039", "shortDescription": "This call to 'SemanticModel.GetDeclaredSymbol()' will always return 'null'", - "fullDescription": "Calling 'SemanticModel.GetDeclaredSymbol' with an argument of type 'GlobalStatementSyntax', 'IncompleteMemberSyntax' or a type inheriting from 'BaseFieldDeclarationSyntax' will always return 'null'.", + "fullDescription": "Calling 'SemanticModel.GetDeclaredSymbol' with on certain types inheriting from 'SyntaxNode', for example 'GlobalStatementSyntax' and 'IncompleteMemberSyntax' will always return 'null'.", "defaultLevel": "warning", "properties": { "category": "MicrosoftCodeAnalysisCorrectness", From 6b82e4eb9ef7431e0b8b52f8acba272c9238eba3 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Sun, 29 Oct 2023 11:42:37 +0100 Subject: [PATCH 29/30] Don't emit CA1849 for nameof expressions --- .../Runtime/UseAsyncMethodInAsyncContext.cs | 6 +++++- .../UseAsyncMethodInAsyncContextTests.cs | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContext.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContext.cs index 5a575c277e..d3af695bee 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContext.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContext.cs @@ -137,7 +137,11 @@ public override void Initialize(AnalysisContext context) } else { - InspectAndReportBlockingMemberAccess(context, ((IPropertyReferenceOperation)context.Operation).Property, syncBlockingSymbols, SymbolKind.Property); + var propertyReferenceOperation = (IPropertyReferenceOperation)context.Operation; + if (propertyReferenceOperation.Parent is not INameOfOperation) + { + InspectAndReportBlockingMemberAccess(context, propertyReferenceOperation.Property, syncBlockingSymbols, SymbolKind.Property); + } } } }, OperationKind.Invocation, OperationKind.PropertyReference); diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContextTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContextTests.cs index e9db9ffbcf..f808388f7d 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContextTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/UseAsyncMethodInAsyncContextTests.cs @@ -1322,6 +1322,27 @@ public async Task RunAsync(IDbContextFactory factory) { }.RunAsync(); } + [Theory] + [InlineData("Task.Result")] + [InlineData("ValueTask.Result")] + [WorkItem(6993, "https://github.com/dotnet/roslyn-analyzers/issues/6993")] + public Task WhenUsingNameOf_NoDiagnostic(string taskExpression) + { + var code = $$""" + using System.Threading.Tasks; + + class Test + { + public async Task Foo() + { + await Task.CompletedTask; + return nameof({{taskExpression}}); + } + } + """; + return VerifyCS.VerifyAnalyzerAsync(code); + } + private static async Task CreateCSTestAndRunAsync(string testCS) { var csTestVerify = new VerifyCS.Test From 88a1407d8377e56c6a32607fd1131ed6c67325cf Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 30 Oct 2023 12:08:22 +0100 Subject: [PATCH 30/30] Apply PR comments --- ...oNotRaiseExceptionsInUnexpectedLocations.cs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs index 1a5690a951..8a52badbb8 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs @@ -95,7 +95,7 @@ public override void Initialize(AnalysisContext context) operationBlockContext.RegisterOperationAction(operationContext => { var throwOperation = (IThrowOperation)operationContext.Operation; - if (ThrowOperationOccursInDelegate(throwOperation)) + if (throwOperation.TryGetContainingAnonymousFunctionOrLocalFunction() is not null) { return; } @@ -115,22 +115,6 @@ public override void Initialize(AnalysisContext context) }); } - private static bool ThrowOperationOccursInDelegate(IThrowOperation throwOperation) - { - var throwParent = throwOperation.Parent; - while (throwParent is not null) - { - if (throwParent is IDelegateCreationOperation) - { - return true; - } - - throwParent = throwParent.Parent; - } - - return false; - } - /// /// This object describes a class of methods where exception throwing statements should be analyzed. ///