From 1917528babb41f1153fdbd895931f3c85f65cf91 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Mon, 31 Jul 2023 21:06:35 +0200 Subject: [PATCH 1/2] Ignore obsolete methods for CA2016 --- ...CancellationTokenToInvocations.Analyzer.cs | 21 +++++++++++------- ...wardCancellationTokenToInvocationsTests.cs | 22 +++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs index e20bb81a26..5f3c4d32f3 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs @@ -68,14 +68,16 @@ public override void Initialize(AnalysisContext context) private void AnalyzeCompilationStart(CompilationStartAnalysisContext context) { - if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingCancellationToken, out INamedTypeSymbol? cancellationTokenType)) + var typeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); + if (!typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingCancellationToken, out INamedTypeSymbol? cancellationTokenType) + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemObsoleteAttribute, out INamedTypeSymbol? obsoleteAttribute)) { return; } // We don't care if these symbols are not defined in our compilation. They are used to special case the Task <-> ValueTask logic - context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask1, out INamedTypeSymbol? genericTask); - context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksValueTask1, out INamedTypeSymbol? genericValueTask); + typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask1, out INamedTypeSymbol? genericTask); + typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksValueTask1, out INamedTypeSymbol? genericValueTask); context.RegisterOperationAction(context => { @@ -93,6 +95,7 @@ private void AnalyzeCompilationStart(CompilationStartAnalysisContext context) cancellationTokenType, genericTask, genericValueTask, + obsoleteAttribute, out int shouldFix, out string? cancellationTokenArgumentName, out string? invocationTokenParameterName)) @@ -125,6 +128,7 @@ private bool ShouldDiagnose( INamedTypeSymbol cancellationTokenType, INamedTypeSymbol? genericTask, INamedTypeSymbol? genericValueTask, + INamedTypeSymbol obsoleteAttribute, out int shouldFix, [NotNullWhen(returnValue: true)] out string? ancestorTokenParameterName, out string? invocationTokenParameterName) { shouldFix = 1; @@ -152,7 +156,7 @@ private bool ShouldDiagnose( } } // or an overload that takes a ct at the end - else if (MethodHasCancellationTokenOverload(compilation, method, cancellationTokenType, genericTask, genericValueTask, out overload)) + else if (MethodHasCancellationTokenOverload(compilation, method, cancellationTokenType, genericTask, genericValueTask, obsoleteAttribute, out overload)) { if (ArgumentsImplicitOrNamed(cancellationTokenType, invocation.Arguments)) { @@ -334,13 +338,14 @@ private static bool MethodHasCancellationTokenOverload( ITypeSymbol cancellationTokenType, INamedTypeSymbol? genericTask, INamedTypeSymbol? genericValueTask, + INamedTypeSymbol obsoleteAttribute, [NotNullWhen(returnValue: true)] out IMethodSymbol? overload) { overload = method.ContainingType - .GetMembers(method.Name) - .OfType() - .FirstOrDefault(methodToCompare => - HasSameParametersPlusCancellationToken(compilation, cancellationTokenType, genericTask, genericValueTask, method, methodToCompare)); + .GetMembers(method.Name) + .OfType() + .FirstOrDefault(methodToCompare => !methodToCompare.HasAttribute(obsoleteAttribute) + && HasSameParametersPlusCancellationToken(compilation, cancellationTokenType, genericTask, genericValueTask, method, methodToCompare)); return overload != null; diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocationsTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocationsTests.cs index de0b3e43fa..cd89401402 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocationsTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocationsTests.cs @@ -478,6 +478,28 @@ static void M1(string s, CancellationToken cancellationToken, __arglist) await VerifyCS.VerifyCodeFixAsync(source, source); } + [Fact] + [WorkItem(6819, "https://github.com/dotnet/roslyn-analyzers/issues/6819")] + public Task ObsoleteOverload() + { + return VerifyCS.VerifyAnalyzerAsync(@" +using System; +using System.Threading; + +class Test +{ + public void Main(CancellationToken token) + { + Run(); + } + + public void Run() {} + + [Obsolete] + public void Run(CancellationToken token) {} +}"); + } + #endregion #region Diagnostics with no fix = C# From 0e7bef2c23b2e60f6bfac307505b6caca5fd5b52 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 1 Aug 2023 11:11:15 +0200 Subject: [PATCH 2/2] Fix build --- .../Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs | 2 +- src/NetAnalyzers/RulesMissingDocumentation.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs index 5f3c4d32f3..0bd93e4ca0 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ForwardCancellationTokenToInvocations.Analyzer.cs @@ -344,7 +344,7 @@ private static bool MethodHasCancellationTokenOverload( overload = method.ContainingType .GetMembers(method.Name) .OfType() - .FirstOrDefault(methodToCompare => !methodToCompare.HasAttribute(obsoleteAttribute) + .FirstOrDefault(methodToCompare => !methodToCompare.HasAnyAttribute(obsoleteAttribute) && HasSameParametersPlusCancellationToken(compilation, cancellationTokenType, genericTask, genericValueTask, method, methodToCompare)); return overload != 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\ |