From 3dfab766865d97c438a900f8eef0012f49e4c918 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 6 Apr 2023 02:01:29 -0700 Subject: [PATCH 1/9] Deprecate CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed public API Fixes #67592 Details in above issue description --- .../Diagnostics/DiagnosticAnalyzerTests.cs | 25 --- .../CompilationWithAnalyzersTests.cs | 8 - .../DiagnosticLocalizationTests.cs | 8 +- .../DiagnosticAnalyzer/AnalyzerDriver.cs | 2 +- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 173 ++++++------------ .../DiagnosticAnalyzer/AnalyzerManager.cs | 16 +- .../CompilationWithAnalyzers.cs | 17 +- .../Core/Diagnostics/DiagnosticExtensions.cs | 8 - .../Diagnostics/DiagnosticAnalyzerTests.vb | 18 -- 9 files changed, 74 insertions(+), 201 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs index 7b6435b8e7ecc..f0ce2d079a6d6 100644 --- a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs @@ -516,31 +516,6 @@ public override void Initialize(AnalysisContext context) } } - [Fact] - public void TestDisabledAnalyzers() - { - var fullyDisabledAnalyzer = new FullyDisabledAnalyzer(); - var partiallyDisabledAnalyzer = new PartiallyDisabledAnalyzer(); - - var options = TestOptions.ReleaseDll; - Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); - Assert.False(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); - - var specificDiagOptions = new Dictionary(); - specificDiagOptions.Add(FullyDisabledAnalyzer.desc1.Id, ReportDiagnostic.Warn); - specificDiagOptions.Add(PartiallyDisabledAnalyzer.desc2.Id, ReportDiagnostic.Suppress); - - options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions); - Assert.False(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); - Assert.True(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); - - // Verify not configurable disabled diagnostic cannot be enabled, and hence cannot affect IsDiagnosticAnalyzerSuppressed computation. - specificDiagOptions = new Dictionary(); - specificDiagOptions.Add(FullyDisabledAnalyzer.desc3.Id, ReportDiagnostic.Warn); - options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions); - Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); - } - [Fact, WorkItem(1008059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1008059")] public void TestCodeBlockAnalyzersForNoExecutableCode() { diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs index 764b282bf749b..dfcd5a6805410 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs @@ -68,13 +68,5 @@ public void GetAnalyzerTelemetry() var analyzerTelemetry = compWithAnalyzers.GetAnalyzerTelemetryInfoAsync(analyzer, CancellationToken.None).Result; Assert.Equal(0, analyzerTelemetry.SymbolActionsCount); } - - [Fact] - public void TestIsDiagnosticAnalyzerSuppressedWithExceptionInSupportedDiagnostics() - { - // Verify IsDiagnosticAnalyzerSuppressed does not throw an exception when 'onAnalyzerException' is null. - var analyzer = new AnalyzerThatThrowsInSupportedDiagnostics(); - _ = CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, s_dllWithMaxWarningLevel, onAnalyzerException: null); - } } } diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs index 57e9087a82dcd..283acc2d19899 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs @@ -303,7 +303,13 @@ private static void TestDescriptorIsExceptionSafeCore(DiagnosticDescriptor descr Action onAnalyzerException = (ex, a, diag, ct) => exceptionDiagnostics.Add(diag); var analyzerManager = new AnalyzerManager(analyzer); - var analyzerExecutor = AnalyzerExecutor.CreateForSupportedDiagnostics(onAnalyzerException, analyzerManager); + var compilation = CSharp.CSharpCompilation.Create("test"); + var analyzerExecutor = AnalyzerExecutor.Create(compilation, AnalyzerOptions.Empty, + addNonCategorizedDiagnostic: null, onAnalyzerException, analyzerExceptionFilter: null, + isCompilerAnalyzer: _ => false, analyzerManager, shouldSkipAnalysisOnGeneratedCode: _ => false, + shouldSuppressGeneratedCodeDiagnostic: (_, _, _, _) => false, isGeneratedCodeLocation: (_, _) => false, + isAnalyzerSuppressedForTree: (_, _, _) => false, getAnalyzerGate: _ => null, + getSemanticModel: tree => compilation.GetSemanticModel(tree, ignoreAccessibility: true)); var descriptors = analyzerManager.GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor); Assert.Equal(1, descriptors.Length); diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index 808729b009480..275e2dae90d8c 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -2289,7 +2289,7 @@ internal static bool IsDiagnosticAnalyzerSuppressed( CompilationOptions options, AnalyzerManager analyzerManager, AnalyzerExecutor analyzerExecutor, - AnalysisScope? analysisScope, + AnalysisScope analysisScope, SeverityFilter severityFilter) { return analyzerManager.IsDiagnosticAnalyzerSuppressed(analyzer, options, s_IsCompilerAnalyzerFunc, analyzerExecutor, analysisScope, severityFilter); diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index 8253721fab79b..dd80d4d6a0b4e 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -31,29 +31,25 @@ internal partial class AnalyzerExecutor internal const string AnalyzerExceptionDiagnosticId = "AD0001"; internal const string AnalyzerDriverExceptionDiagnosticId = "AD0002"; - private readonly Compilation? _compilation; - private readonly AnalyzerOptions? _analyzerOptions; private readonly Action? _addNonCategorizedDiagnostic; private readonly Action? _addCategorizedLocalDiagnostic; private readonly Action? _addCategorizedNonLocalDiagnostic; private readonly Action? _addSuppression; - private readonly Action _onAnalyzerException; private readonly Func? _analyzerExceptionFilter; private readonly AnalyzerManager _analyzerManager; - private readonly Func? _isCompilerAnalyzer; - private readonly Func? _getAnalyzerGate; - private readonly Func? _getSemanticModel; + private readonly Func _isCompilerAnalyzer; + private readonly Func _getAnalyzerGate; + private readonly Func _getSemanticModel; private readonly Func _shouldSkipAnalysisOnGeneratedCode; private readonly Func _shouldSuppressGeneratedCodeDiagnostic; private readonly Func _isGeneratedCodeLocation; - private readonly Func? _isAnalyzerSuppressedForTree; + private readonly Func _isAnalyzerSuppressedForTree; /// /// The values in this map convert to using . /// private readonly ConcurrentDictionary>? _analyzerExecutionTimeMap; private readonly CompilationAnalysisValueProviderFactory _compilationAnalysisValueProviderFactory; - private readonly CancellationToken _cancellationToken; private Func? _lazyGetControlFlowGraph; @@ -64,7 +60,6 @@ private Func GetControlFlowGraph private bool IsAnalyzerSuppressedForTree(DiagnosticAnalyzer analyzer, SyntaxTree tree) { - Debug.Assert(_isAnalyzerSuppressedForTree != null); return _isAnalyzerSuppressedForTree(analyzer, tree, Compilation.Options.SyntaxTreeOptionsProvider); } @@ -132,66 +127,30 @@ public static AnalyzerExecutor Create( addSuppression, cancellationToken); } - /// - /// Creates to fetch . - /// - /// - /// Optional delegate which is invoked when an analyzer throws an exception. - /// Delegate can do custom tasks such as report the given analyzer exception diagnostic, report a non-fatal watson for the exception, etc. - /// - /// Analyzer manager to fetch supported diagnostics. - /// Cancellation token. - public static AnalyzerExecutor CreateForSupportedDiagnostics( - Action? onAnalyzerException, - AnalyzerManager analyzerManager, - CancellationToken cancellationToken = default) - { - onAnalyzerException ??= (ex, analyzer, diagnostic, cancellationToken) => { }; - return new AnalyzerExecutor( - compilation: null, - analyzerOptions: null, - addNonCategorizedDiagnosticOpt: null, - isCompilerAnalyzer: null, - shouldSkipAnalysisOnGeneratedCode: _ => false, - shouldSuppressGeneratedCodeDiagnostic: (diagnostic, analyzer, compilation, ct) => false, - isGeneratedCodeLocation: (_1, _2) => false, - isAnalyzerSuppressedForTree: null, - getAnalyzerGate: null, - getSemanticModel: null, - onAnalyzerException: onAnalyzerException, - analyzerExceptionFilter: null, - analyzerManager: analyzerManager, - analyzerExecutionTimeMap: null, - addCategorizedLocalDiagnostic: null, - addCategorizedNonLocalDiagnostic: null, - addSuppression: null, - cancellationToken: cancellationToken); - } - private AnalyzerExecutor( - Compilation? compilation, - AnalyzerOptions? analyzerOptions, + Compilation compilation, + AnalyzerOptions analyzerOptions, Action? addNonCategorizedDiagnosticOpt, Action onAnalyzerException, Func? analyzerExceptionFilter, - Func? isCompilerAnalyzer, + Func isCompilerAnalyzer, AnalyzerManager analyzerManager, Func shouldSkipAnalysisOnGeneratedCode, Func shouldSuppressGeneratedCodeDiagnostic, Func isGeneratedCodeLocation, - Func? isAnalyzerSuppressedForTree, - Func? getAnalyzerGate, - Func? getSemanticModel, + Func isAnalyzerSuppressedForTree, + Func getAnalyzerGate, + Func getSemanticModel, ConcurrentDictionary>? analyzerExecutionTimeMap, Action? addCategorizedLocalDiagnostic, Action? addCategorizedNonLocalDiagnostic, Action? addSuppression, CancellationToken cancellationToken) { - _compilation = compilation; - _analyzerOptions = analyzerOptions; + Compilation = compilation; + AnalyzerOptions = analyzerOptions; _addNonCategorizedDiagnostic = addNonCategorizedDiagnosticOpt; - _onAnalyzerException = onAnalyzerException; + OnAnalyzerException = onAnalyzerException; _analyzerExceptionFilter = analyzerExceptionFilter; _isCompilerAnalyzer = isCompilerAnalyzer; _analyzerManager = analyzerManager; @@ -205,52 +164,32 @@ private AnalyzerExecutor( _addCategorizedLocalDiagnostic = addCategorizedLocalDiagnostic; _addCategorizedNonLocalDiagnostic = addCategorizedNonLocalDiagnostic; _addSuppression = addSuppression; - _cancellationToken = cancellationToken; + CancellationToken = cancellationToken; _compilationAnalysisValueProviderFactory = new CompilationAnalysisValueProviderFactory(); } + // TODO: Remove this method. Tracked by https://github.com/dotnet/roslyn/issues/67670. public AnalyzerExecutor WithCancellationToken(CancellationToken cancellationToken) { - if (cancellationToken == _cancellationToken) + if (cancellationToken == CancellationToken) { return this; } - return new AnalyzerExecutor(_compilation, _analyzerOptions, _addNonCategorizedDiagnostic, _onAnalyzerException, _analyzerExceptionFilter, + return new AnalyzerExecutor(Compilation, AnalyzerOptions, _addNonCategorizedDiagnostic, OnAnalyzerException, _analyzerExceptionFilter, _isCompilerAnalyzer, _analyzerManager, _shouldSkipAnalysisOnGeneratedCode, _shouldSuppressGeneratedCodeDiagnostic, _isGeneratedCodeLocation, _isAnalyzerSuppressedForTree, _getAnalyzerGate, _getSemanticModel, _analyzerExecutionTimeMap, _addCategorizedLocalDiagnostic, _addCategorizedNonLocalDiagnostic, _addSuppression, cancellationToken); } - internal bool TryGetCompilationAndAnalyzerOptions( - [NotNullWhen(true)] out Compilation? compilation, - [NotNullWhen(true)] out AnalyzerOptions? analyzerOptions) - { - (compilation, analyzerOptions) = (_compilation, _analyzerOptions); - return compilation != null && analyzerOptions != null; - } + internal Compilation Compilation { get; } - internal Compilation Compilation - { - get - { - Debug.Assert(_compilation != null); - return _compilation; - } - } - - internal AnalyzerOptions AnalyzerOptions - { - get - { - Debug.Assert(_analyzerOptions != null); - return _analyzerOptions; - } - } + internal AnalyzerOptions AnalyzerOptions { get; } - internal CancellationToken CancellationToken => _cancellationToken; - internal Action OnAnalyzerException => _onAnalyzerException; + // TODO: Remove this property. Tracked by https://github.com/dotnet/roslyn/issues/67670. + internal CancellationToken CancellationToken { get; } + internal Action OnAnalyzerException { get; } internal ImmutableDictionary AnalyzerExecutionTimes { get @@ -290,10 +229,10 @@ public void ExecuteCompilationStartActions(ImmutableArray isSupportedSuppression = supportedSuppressions.Contains; Action action = suppressor.ReportSuppressions; var context = new SuppressionAnalysisContext(Compilation, AnalyzerOptions, - reportedDiagnostics, _addSuppression, isSupportedSuppression, _getSemanticModel, _cancellationToken); + reportedDiagnostics, _addSuppression, isSupportedSuppression, _getSemanticModel, CancellationToken); ExecuteAndCatchIfThrows( suppressor, @@ -389,11 +328,11 @@ public void ExecuteCompilationActions( foreach (var endAction in compilationActions) { - _cancellationToken.ThrowIfCancellationRequested(); + CancellationToken.ThrowIfCancellationRequested(); var context = new CompilationAnalysisContext( Compilation, AnalyzerOptions, addDiagnostic, - isSupportedDiagnostic, _compilationAnalysisValueProviderFactory, _cancellationToken); + isSupportedDiagnostic, _compilationAnalysisValueProviderFactory, CancellationToken); ExecuteAndCatchIfThrows( endAction.Analyzer, @@ -438,10 +377,10 @@ public void ExecuteSymbolActions( if (kinds.Contains(symbol.Kind)) { - _cancellationToken.ThrowIfCancellationRequested(); + CancellationToken.ThrowIfCancellationRequested(); var context = new SymbolAnalysisContext(symbol, Compilation, AnalyzerOptions, addDiagnostic, - isSupportedDiagnostic, isGeneratedCodeSymbol, _cancellationToken); + isSupportedDiagnostic, isGeneratedCodeSymbol, CancellationToken); ExecuteAndCatchIfThrows( symbolAction.Analyzer, @@ -526,10 +465,10 @@ private void ExecuteSymbolEndActionsCore( { var action = symbolAction.Action; - _cancellationToken.ThrowIfCancellationRequested(); + CancellationToken.ThrowIfCancellationRequested(); var context = new SymbolAnalysisContext(symbol, Compilation, AnalyzerOptions, addDiagnostic, - isSupportedDiagnostic, isGeneratedCode, _cancellationToken); + isSupportedDiagnostic, isGeneratedCode, CancellationToken); ExecuteAndCatchIfThrows( symbolAction.Analyzer, @@ -568,10 +507,10 @@ public void ExecuteSemanticModelActions( foreach (var semanticModelAction in semanticModelActions) { - _cancellationToken.ThrowIfCancellationRequested(); + CancellationToken.ThrowIfCancellationRequested(); var context = new SemanticModelAnalysisContext(semanticModel, AnalyzerOptions, diagReporter.AddDiagnosticAction, - isSupportedDiagnostic, analysisScope.FilterSpanOpt, isGeneratedCode, _cancellationToken); + isSupportedDiagnostic, analysisScope.FilterSpanOpt, isGeneratedCode, CancellationToken); // Catch Exception from action. ExecuteAndCatchIfThrows( @@ -612,9 +551,9 @@ public void ExecuteSyntaxTreeActions( foreach (var syntaxTreeAction in syntaxTreeActions) { - _cancellationToken.ThrowIfCancellationRequested(); + CancellationToken.ThrowIfCancellationRequested(); - var context = new SyntaxTreeAnalysisContext(tree, AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, Compilation, isGeneratedCode, _cancellationToken); + var context = new SyntaxTreeAnalysisContext(tree, AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, Compilation, isGeneratedCode, CancellationToken); // Catch Exception from action. ExecuteAndCatchIfThrows( @@ -646,9 +585,9 @@ public void ExecuteAdditionalFileActions( using var _ = PooledDelegates.GetPooledFunction((d, arg) => arg.self.IsSupportedDiagnostic(arg.analyzer, d), (self: this, analyzer), out Func isSupportedDiagnostic); foreach (var additionalFileAction in additionalFileActions) { - _cancellationToken.ThrowIfCancellationRequested(); + CancellationToken.ThrowIfCancellationRequested(); - var context = new AdditionalFileAnalysisContext(additionalFile, AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, Compilation, _cancellationToken); + var context = new AdditionalFileAnalysisContext(additionalFile, AnalyzerOptions, diagReporter.AddDiagnosticAction, isSupportedDiagnostic, Compilation, CancellationToken); // Catch Exception from action. ExecuteAndCatchIfThrows( @@ -675,7 +614,7 @@ private void ExecuteSyntaxNodeAction( Debug.Assert(!IsAnalyzerSuppressedForTree(syntaxNodeAction.Analyzer, node.SyntaxTree)); var syntaxNodeContext = new SyntaxNodeAnalysisContext(node, containingSymbol, semanticModel, AnalyzerOptions, addDiagnostic, - isSupportedDiagnostic, isGeneratedCode, _cancellationToken); + isSupportedDiagnostic, isGeneratedCode, CancellationToken); ExecuteAndCatchIfThrows( syntaxNodeAction.Analyzer, @@ -697,7 +636,7 @@ private void ExecuteOperationAction( Debug.Assert(!IsAnalyzerSuppressedForTree(operationAction.Analyzer, semanticModel.SyntaxTree)); var operationContext = new OperationAnalysisContext(operation, containingSymbol, semanticModel.Compilation, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, isGeneratedCode, _cancellationToken); + AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, isGeneratedCode, CancellationToken); ExecuteAndCatchIfThrows( operationAction.Analyzer, data => data.action(data.context), @@ -815,7 +754,7 @@ private void ExecuteBlockActionsCore; var codeBlockScope = new HostCodeBlockStartAnalysisScope(); var blockStartContext = new AnalyzerCodeBlockStartAnalysisContext(startAction.Analyzer, - codeBlockScope, declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, isGeneratedCode, _cancellationToken); + codeBlockScope, declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, isGeneratedCode, CancellationToken); // Catch Exception from the start action. ExecuteAndCatchIfThrows( @@ -837,7 +776,7 @@ private void ExecuteBlockActionsCore( var codeBlockAction = blockAction as CodeBlockAnalyzerAction; if (codeBlockAction != null) { - var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, isGeneratedCode, _cancellationToken); + var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, isGeneratedCode, CancellationToken); ExecuteAndCatchIfThrows( codeBlockAction.Analyzer, @@ -917,7 +856,7 @@ private void ExecuteBlockActions( if (operationBlockAction != null) { var context = new OperationBlockAnalysisContext(operationBlocks, declaredSymbol, semanticModel.Compilation, - AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, isGeneratedCode, _cancellationToken); + AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, GetControlFlowGraph, isGeneratedCode, CancellationToken); ExecuteAndCatchIfThrows( operationBlockAction.Analyzer, @@ -1180,7 +1119,7 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A { try { - _cancellationToken.ThrowIfCancellationRequested(); + CancellationToken.ThrowIfCancellationRequested(); analyze(argument); } catch (Exception e) when (ExceptionFilter(e)) @@ -1189,7 +1128,7 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A var diagnostic = CreateAnalyzerExceptionDiagnostic(analyzer, e, info); try { - _onAnalyzerException(e, analyzer, diagnostic, _cancellationToken); + OnAnalyzerException(e, analyzer, diagnostic, CancellationToken); } catch (Exception) { @@ -1200,7 +1139,7 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A internal bool ExceptionFilter(Exception ex) { - if ((ex as OperationCanceledException)?.CancellationToken == _cancellationToken) + if ((ex as OperationCanceledException)?.CancellationToken == CancellationToken) { return false; } @@ -1347,7 +1286,7 @@ private bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diagn private Action GetAddDiagnostic(ISymbol contextSymbol, ImmutableArray cachedDeclaringReferences, DiagnosticAnalyzer analyzer, Func getTopMostNodeForAnalysis) { return GetAddDiagnostic(contextSymbol, cachedDeclaringReferences, Compilation, analyzer, _addNonCategorizedDiagnostic, - _addCategorizedLocalDiagnostic, _addCategorizedNonLocalDiagnostic, getTopMostNodeForAnalysis, _shouldSuppressGeneratedCodeDiagnostic, _cancellationToken); + _addCategorizedLocalDiagnostic, _addCategorizedNonLocalDiagnostic, getTopMostNodeForAnalysis, _shouldSuppressGeneratedCodeDiagnostic, CancellationToken); } private static Action GetAddDiagnostic( @@ -1403,7 +1342,7 @@ private Action GetAddCompilationDiagnostic(DiagnosticAnalyzer analyz { return diagnostic => { - if (_shouldSuppressGeneratedCodeDiagnostic(diagnostic, analyzer, Compilation, _cancellationToken)) + if (_shouldSuppressGeneratedCodeDiagnostic(diagnostic, analyzer, Compilation, CancellationToken)) { return; } @@ -1411,11 +1350,11 @@ private Action GetAddCompilationDiagnostic(DiagnosticAnalyzer analyz if (_addCategorizedNonLocalDiagnostic == null) { Debug.Assert(_addNonCategorizedDiagnostic != null); - _addNonCategorizedDiagnostic(diagnostic, _cancellationToken); + _addNonCategorizedDiagnostic(diagnostic, CancellationToken); return; } - _addCategorizedNonLocalDiagnostic(diagnostic, analyzer, _cancellationToken); + _addCategorizedNonLocalDiagnostic(diagnostic, analyzer, CancellationToken); }; } @@ -1423,21 +1362,21 @@ private AnalyzerDiagnosticReporter GetAddSemanticDiagnostic(SyntaxTree tree, Dia { return AnalyzerDiagnosticReporter.GetInstance(new SourceOrAdditionalFile(tree), span: null, Compilation, analyzer, isSyntaxDiagnostic: false, _addNonCategorizedDiagnostic, _addCategorizedLocalDiagnostic, _addCategorizedNonLocalDiagnostic, - _shouldSuppressGeneratedCodeDiagnostic, _cancellationToken); + _shouldSuppressGeneratedCodeDiagnostic, CancellationToken); } private AnalyzerDiagnosticReporter GetAddSemanticDiagnostic(SyntaxTree tree, TextSpan? span, DiagnosticAnalyzer analyzer) { return AnalyzerDiagnosticReporter.GetInstance(new SourceOrAdditionalFile(tree), span, Compilation, analyzer, isSyntaxDiagnostic: false, _addNonCategorizedDiagnostic, _addCategorizedLocalDiagnostic, _addCategorizedNonLocalDiagnostic, - _shouldSuppressGeneratedCodeDiagnostic, _cancellationToken); + _shouldSuppressGeneratedCodeDiagnostic, CancellationToken); } private AnalyzerDiagnosticReporter GetAddSyntaxDiagnostic(SourceOrAdditionalFile file, DiagnosticAnalyzer analyzer) { return AnalyzerDiagnosticReporter.GetInstance(file, span: null, Compilation, analyzer, isSyntaxDiagnostic: true, _addNonCategorizedDiagnostic, _addCategorizedLocalDiagnostic, _addCategorizedNonLocalDiagnostic, - _shouldSuppressGeneratedCodeDiagnostic, _cancellationToken); + _shouldSuppressGeneratedCodeDiagnostic, CancellationToken); } private bool ShouldExecuteNode(SyntaxNode node, DiagnosticAnalyzer analyzer) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs index dbb187a225afa..5dea86bc89c36 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs @@ -294,7 +294,7 @@ internal bool IsDiagnosticAnalyzerSuppressed( CompilationOptions options, Func isCompilerAnalyzer, AnalyzerExecutor analyzerExecutor, - AnalysisScope? analysisScope, + AnalysisScope analysisScope, SeverityFilter severityFilter) { if (isCompilerAnalyzer(analyzer)) @@ -305,7 +305,6 @@ internal bool IsDiagnosticAnalyzerSuppressed( var supportedDiagnostics = GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor); var diagnosticOptions = options.SpecificDiagnosticOptions; - analyzerExecutor.TryGetCompilationAndAnalyzerOptions(out var compilation, out var analyzerOptions); foreach (var diag in supportedDiagnostics) { @@ -349,7 +348,7 @@ internal bool IsDiagnosticAnalyzerSuppressed( // Editorconfig user settings override compilation wide settings. if (isSuppressed && - isEnabledWithAnalyzerConfigOptions(diag, severityFilter, compilation, analyzerOptions, analysisScope, analyzerExecutor.CancellationToken)) + isEnabledWithAnalyzerConfigOptions(diag, severityFilter, analyzerExecutor.Compilation, analyzerExecutor.AnalyzerOptions, analysisScope, analyzerExecutor.CancellationToken)) { isSuppressed = false; } @@ -376,15 +375,14 @@ internal bool IsDiagnosticAnalyzerSuppressed( static bool isEnabledWithAnalyzerConfigOptions( DiagnosticDescriptor descriptor, SeverityFilter severityFilter, - Compilation? compilation, - AnalyzerOptions? analyzerOptions, - AnalysisScope? analysisScope, + Compilation compilation, + AnalyzerOptions analyzerOptions, + AnalysisScope analysisScope, CancellationToken cancellationToken) { - if (compilation != null && compilation.Options.SyntaxTreeOptionsProvider is { } treeOptions) + if (compilation.Options.SyntaxTreeOptionsProvider is { } treeOptions) { - var trees = analysisScope?.SyntaxTrees ?? compilation.SyntaxTrees; - foreach (var tree in trees) + foreach (var tree in analysisScope.SyntaxTrees) { // Check if diagnostic is enabled by SyntaxTree.DiagnosticOptions or Bulk configuration from AnalyzerConfigOptions. if (treeOptions.TryGetDiagnosticValue(tree, descriptor.Id, cancellationToken, out var configuredValue) || diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs index 753f6f6ce2ac7..90b3f6f9ab270 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs @@ -1066,25 +1066,14 @@ private static IEnumerable GetEffectiveDiagnosticsImpl(ImmutableArra /// /// Optional delegate which is invoked when an analyzer throws an exception. /// Delegate can do custom tasks such as report the given analyzer exception diagnostic, report a non-fatal watson for the exception, etc. - /// + /// + [Obsolete("This API is no longer supported. See https://github.com/dotnet/roslyn/issues/67592 for details")] public static bool IsDiagnosticAnalyzerSuppressed( DiagnosticAnalyzer analyzer, CompilationOptions options, Action? onAnalyzerException = null) { - VerifyAnalyzerArgumentForStaticApis(analyzer); - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - var analyzerManager = new AnalyzerManager(analyzer); - - Action? wrappedOnAnalyzerException = - onAnalyzerException == null ? null : (ex, analyzer, diagnostic, _) => onAnalyzerException(ex, analyzer, diagnostic); - var analyzerExecutor = AnalyzerExecutor.CreateForSupportedDiagnostics(wrappedOnAnalyzerException, analyzerManager); - return AnalyzerDriver.IsDiagnosticAnalyzerSuppressed(analyzer, options, analyzerManager, analyzerExecutor, analysisScope: null, severityFilter: SeverityFilter.None); + return false; } /// diff --git a/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs b/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs index ed78cb663d927..2b80f555cb286 100644 --- a/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs +++ b/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs @@ -341,14 +341,6 @@ public static IEnumerable GetEffectiveDiagnostics(this Compilation c return CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, compilation); } - /// - /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options. - /// - public static bool IsDiagnosticAnalyzerSuppressed(this DiagnosticAnalyzer analyzer, CompilationOptions options) - { - return CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, options); - } - public static TCompilation VerifyEmitDiagnostics(this TCompilation c, EmitOptions options, params DiagnosticDescription[] expected) where TCompilation : Compilation { diff --git a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb index ea1f007c6443d..f0d7d15a752af 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb @@ -241,24 +241,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics End Sub End Class - - Public Sub TestDisabledAnalyzers() - Dim FullyDisabledAnalyzer = New FullyDisabledAnalyzer() - Dim PartiallyDisabledAnalyzer = New PartiallyDisabledAnalyzer() - - Dim options = TestOptions.ReleaseDll - Assert.True(FullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) - Assert.False(PartiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) - - Dim specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() - specificDiagOptions.Add(FullyDisabledAnalyzer.desc1.Id, ReportDiagnostic.Warn) - specificDiagOptions.Add(PartiallyDisabledAnalyzer.desc2.Id, ReportDiagnostic.Suppress) - - options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) - Assert.False(FullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) - Assert.True(PartiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) - End Sub - Public Class ModuleStatementAnalyzer Inherits DiagnosticAnalyzer From d1afd657ea3e10b74cd4aa6a80c46b8eb245b3ef Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 6 Apr 2023 02:05:07 -0700 Subject: [PATCH 2/9] Remove redundant asserts --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index dd80d4d6a0b4e..535ab7798391b 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -287,7 +287,6 @@ public void ExecuteSymbolStartActions( public void ExecuteSuppressionAction(DiagnosticSuppressor suppressor, ImmutableArray reportedDiagnostics) { Debug.Assert(_addSuppression != null); - Debug.Assert(_getSemanticModel != null); if (reportedDiagnostics.IsEmpty) { @@ -1091,7 +1090,7 @@ internal void ExecuteAndCatchIfThrows(DiagnosticAnalyzer analyzer, Action< timer = SharedStopwatch.StartNew(); } - var gate = _getAnalyzerGate?.Invoke(analyzer); + var gate = _getAnalyzerGate(analyzer); if (gate != null) { lock (gate) @@ -1272,8 +1271,6 @@ internal static bool AreEquivalentAnalyzerExceptionDiagnostics(Diagnostic except private bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diagnostic) { - Debug.Assert(_isCompilerAnalyzer != null); - if (diagnostic is DiagnosticWithInfo) { // Compiler diagnostic From be75fe00c31ece8b25c9f81b1781c7bc5194dd6a Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 6 Apr 2023 04:59:00 -0700 Subject: [PATCH 3/9] Fix tests --- .../CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs index 283acc2d19899..4ca6c1da01603 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs @@ -305,7 +305,7 @@ private static void TestDescriptorIsExceptionSafeCore(DiagnosticDescriptor descr var analyzerManager = new AnalyzerManager(analyzer); var compilation = CSharp.CSharpCompilation.Create("test"); var analyzerExecutor = AnalyzerExecutor.Create(compilation, AnalyzerOptions.Empty, - addNonCategorizedDiagnostic: null, onAnalyzerException, analyzerExceptionFilter: null, + addNonCategorizedDiagnostic: (_, _) => { }, onAnalyzerException, analyzerExceptionFilter: null, isCompilerAnalyzer: _ => false, analyzerManager, shouldSkipAnalysisOnGeneratedCode: _ => false, shouldSuppressGeneratedCodeDiagnostic: (_, _, _, _) => false, isGeneratedCodeLocation: (_, _) => false, isAnalyzerSuppressedForTree: (_, _, _) => false, getAnalyzerGate: _ => null, From a8ba0dbb6f4a48c7fdebca630dc1dfbd0caff97d Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 14 Apr 2023 04:09:25 -0700 Subject: [PATCH 4/9] Refactor code to restore functionality and tests for IsDiagnosticAnalyzerSuppressed API --- .../Diagnostics/DiagnosticAnalyzerTests.cs | 27 +++++++ .../CompilationWithAnalyzersTests.cs | 10 +++ .../DiagnosticAnalyzer/AnalyzerDriver.cs | 2 +- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 4 +- .../DiagnosticAnalyzer/AnalyzerManager.cs | 77 +++++++++++-------- .../CompilationWithAnalyzers.cs | 8 +- .../Core/Diagnostics/DiagnosticExtensions.cs | 9 +++ .../Diagnostics/DiagnosticAnalyzerTests.vb | 20 +++++ 8 files changed, 122 insertions(+), 35 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs index f0ce2d079a6d6..bf83129a225fa 100644 --- a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs @@ -516,6 +516,33 @@ public override void Initialize(AnalysisContext context) } } +#pragma warning disable CS0618 // Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete + [Fact] + public void TestDisabledAnalyzers() + { + var fullyDisabledAnalyzer = new FullyDisabledAnalyzer(); + var partiallyDisabledAnalyzer = new PartiallyDisabledAnalyzer(); + + var options = TestOptions.ReleaseDll; + Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); + Assert.False(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); + + var specificDiagOptions = new Dictionary(); + specificDiagOptions.Add(FullyDisabledAnalyzer.desc1.Id, ReportDiagnostic.Warn); + specificDiagOptions.Add(PartiallyDisabledAnalyzer.desc2.Id, ReportDiagnostic.Suppress); + + options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions); + Assert.False(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); + Assert.True(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); + + // Verify not configurable disabled diagnostic cannot be enabled, and hence cannot affect IsDiagnosticAnalyzerSuppressed computation. + specificDiagOptions = new Dictionary(); + specificDiagOptions.Add(FullyDisabledAnalyzer.desc3.Id, ReportDiagnostic.Warn); + options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions); + Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); + } +#pragma warning restore CS0618 // Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete + [Fact, WorkItem(1008059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1008059")] public void TestCodeBlockAnalyzersForNoExecutableCode() { diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs index dfcd5a6805410..7b26923137f48 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs @@ -68,5 +68,15 @@ public void GetAnalyzerTelemetry() var analyzerTelemetry = compWithAnalyzers.GetAnalyzerTelemetryInfoAsync(analyzer, CancellationToken.None).Result; Assert.Equal(0, analyzerTelemetry.SymbolActionsCount); } + + [Fact] + public void TestIsDiagnosticAnalyzerSuppressedWithExceptionInSupportedDiagnostics() + { + // Verify IsDiagnosticAnalyzerSuppressed does not throw an exception when 'onAnalyzerException' is null. + var analyzer = new AnalyzerThatThrowsInSupportedDiagnostics(); +#pragma warning disable CS0618 // Type or member is obsolete + _ = CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, s_dllWithMaxWarningLevel, onAnalyzerException: null); +#pragma warning restore CS0618 // Type or member is obsolete + } } } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index ad6a5980c6644..a1e13aa833585 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -2297,7 +2297,7 @@ internal static bool IsDiagnosticAnalyzerSuppressed( return analyzerManager.IsDiagnosticAnalyzerSuppressed(analyzer, options, s_IsCompilerAnalyzerFunc, analyzerExecutor, analysisScope, severityFilter, cancellationToken); } - private static bool IsCompilerAnalyzer(DiagnosticAnalyzer analyzer) => analyzer is CompilerDiagnosticAnalyzer; + internal static bool IsCompilerAnalyzer(DiagnosticAnalyzer analyzer) => analyzer is CompilerDiagnosticAnalyzer; public void Dispose() { diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index dc45104e3556e..a5d54c9f6534e 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -43,7 +43,7 @@ internal partial class AnalyzerExecutor private readonly Func _shouldSkipAnalysisOnGeneratedCode; private readonly Func _shouldSuppressGeneratedCodeDiagnostic; private readonly Func _isGeneratedCodeLocation; - private readonly Func _isAnalyzerSuppressedForTree; + private readonly Func _isAnalyzerSuppressedForTree; /// /// The values in this map convert to using . @@ -861,7 +861,7 @@ private void ExecuteBlockActions( var codeBlockAction = blockAction as CodeBlockAnalyzerAction; if (codeBlockAction != null) { - var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, isGeneratedCode, _cancellationToken); + var context = new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, AnalyzerOptions, addDiagnostic, isSupportedDiagnostic, isGeneratedCode, cancellationToken); ExecuteAndCatchIfThrows( codeBlockAction.Analyzer, diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs index 1d5ab157abd34..ba42f747e9c56 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs @@ -296,6 +296,50 @@ internal bool IsDiagnosticAnalyzerSuppressed( AnalysisScope analysisScope, SeverityFilter severityFilter, CancellationToken cancellationToken) + { + Func> getSupportedDiagnosticDescriptors = + (analyzer, cancellationToken) => GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, cancellationToken); + + Func> getSupportedSuppressionDescriptors = + (suppressor, cancellationToken) => GetSupportedSuppressionDescriptors(suppressor, analyzerExecutor, cancellationToken); + + return IsDiagnosticAnalyzerSuppressed(analyzer, options, isCompilerAnalyzer, severityFilter, + isEnabledWithAnalyzerConfigOptions, getSupportedDiagnosticDescriptors, getSupportedSuppressionDescriptors, cancellationToken); + + bool isEnabledWithAnalyzerConfigOptions(DiagnosticDescriptor descriptor) + { + if (analyzerExecutor.Compilation.Options.SyntaxTreeOptionsProvider is { } treeOptions) + { + foreach (var tree in analysisScope.SyntaxTrees) + { + // Check if diagnostic is enabled by SyntaxTree.DiagnosticOptions or Bulk configuration from AnalyzerConfigOptions. + if (treeOptions.TryGetDiagnosticValue(tree, descriptor.Id, cancellationToken, out var configuredValue) || + analyzerExecutor.AnalyzerOptions.TryGetSeverityFromBulkConfiguration(tree, analyzerExecutor.Compilation, descriptor, cancellationToken, out configuredValue)) + { + if (configuredValue != ReportDiagnostic.Suppress && !severityFilter.Contains(configuredValue)) + { + return true; + } + } + } + } + + return false; + } + } + + /// + /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options. + /// + internal static bool IsDiagnosticAnalyzerSuppressed( + DiagnosticAnalyzer analyzer, + CompilationOptions options, + Func isCompilerAnalyzer, + SeverityFilter severityFilter, + Func isEnabledWithAnalyzerConfigOptions, + Func> getSupportedDiagnosticDescriptors, + Func> getSupportedSuppressionDescriptors, + CancellationToken cancellationToken) { if (isCompilerAnalyzer(analyzer)) { @@ -303,7 +347,7 @@ internal bool IsDiagnosticAnalyzerSuppressed( return false; } - var supportedDiagnostics = GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, cancellationToken); + var supportedDiagnostics = getSupportedDiagnosticDescriptors(analyzer, cancellationToken); var diagnosticOptions = options.SpecificDiagnosticOptions; foreach (var diag in supportedDiagnostics) @@ -348,7 +392,7 @@ internal bool IsDiagnosticAnalyzerSuppressed( // Editorconfig user settings override compilation wide settings. if (isSuppressed && - isEnabledWithAnalyzerConfigOptions(diag, severityFilter, compilation, analyzerOptions, analysisScope, cancellationToken)) + isEnabledWithAnalyzerConfigOptions(diag)) { isSuppressed = false; } @@ -361,7 +405,7 @@ internal bool IsDiagnosticAnalyzerSuppressed( if (analyzer is DiagnosticSuppressor suppressor) { - foreach (var suppressionDescriptor in GetSupportedSuppressionDescriptors(suppressor, analyzerExecutor, cancellationToken)) + foreach (var suppressionDescriptor in getSupportedSuppressionDescriptors(suppressor, cancellationToken)) { if (!suppressionDescriptor.IsDisabled(options)) { @@ -371,33 +415,6 @@ internal bool IsDiagnosticAnalyzerSuppressed( } return true; - - static bool isEnabledWithAnalyzerConfigOptions( - DiagnosticDescriptor descriptor, - SeverityFilter severityFilter, - Compilation compilation, - AnalyzerOptions analyzerOptions, - AnalysisScope analysisScope, - CancellationToken cancellationToken) - { - if (compilation.Options.SyntaxTreeOptionsProvider is { } treeOptions) - { - foreach (var tree in analysisScope.SyntaxTrees) - { - // Check if diagnostic is enabled by SyntaxTree.DiagnosticOptions or Bulk configuration from AnalyzerConfigOptions. - if (treeOptions.TryGetDiagnosticValue(tree, descriptor.Id, cancellationToken, out var configuredValue) || - analyzerOptions.TryGetSeverityFromBulkConfiguration(tree, compilation, descriptor, cancellationToken, out configuredValue)) - { - if (configuredValue != ReportDiagnostic.Suppress && !severityFilter.Contains(configuredValue)) - { - return true; - } - } - } - } - - return false; - } } internal static bool HasCompilerOrNotConfigurableTag(ImmutableArray customTags) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs index dc13776dc1754..73b5abc91066a 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs @@ -1084,8 +1084,12 @@ public static bool IsDiagnosticAnalyzerSuppressed( Action? wrappedOnAnalyzerException = onAnalyzerException == null ? null : (ex, analyzer, diagnostic, _) => onAnalyzerException(ex, analyzer, diagnostic); - var analyzerExecutor = AnalyzerExecutor.CreateForSupportedDiagnostics(wrappedOnAnalyzerException, analyzerManager); - return AnalyzerDriver.IsDiagnosticAnalyzerSuppressed(analyzer, options, analyzerManager, analyzerExecutor, analysisScope: null, severityFilter: SeverityFilter.None, CancellationToken.None); + return AnalyzerManager.IsDiagnosticAnalyzerSuppressed(analyzer, options, + IsCompilerAnalyzer, severityFilter: SeverityFilter.None, + isEnabledWithAnalyzerConfigOptions: _ => false, + getSupportedDiagnosticDescriptors: (analyzer, _) => analyzer.SupportedDiagnostics, + getSupportedSuppressionDescriptors: (suppressor, _) => suppressor.SupportedSuppressions, + CancellationToken.None); ; } /// diff --git a/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs b/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs index 6c890dabc1dc2..75b0e0e80653f 100644 --- a/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs +++ b/src/Compilers/Test/Core/Diagnostics/DiagnosticExtensions.cs @@ -341,6 +341,15 @@ public static IEnumerable GetEffectiveDiagnostics(this Compilation c return CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, compilation); } + /// + /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options. + /// + [Obsolete("This API is no longer supported. See https://github.com/dotnet/roslyn/issues/67592 for details")] + public static bool IsDiagnosticAnalyzerSuppressed(this DiagnosticAnalyzer analyzer, CompilationOptions options) + { + return CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, options); + } + public static TCompilation VerifyEmitDiagnostics(this TCompilation c, EmitOptions options, params DiagnosticDescription[] expected) where TCompilation : Compilation { diff --git a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb index f0d7d15a752af..8e727de98be68 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb @@ -241,6 +241,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics End Sub End Class +#Disable Warning BC40000 ' Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete + + Public Sub TestDisabledAnalyzers() + Dim fullyDisabledAnalyzer = New FullyDisabledAnalyzer() + Dim partiallyDisabledAnalyzer = New PartiallyDisabledAnalyzer() + + Dim options = TestOptions.ReleaseDll + Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + Assert.False(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + + Dim specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() + specificDiagOptions.Add(FullyDisabledAnalyzer.desc1.Id, ReportDiagnostic.Warn) + specificDiagOptions.Add(PartiallyDisabledAnalyzer.desc2.Id, ReportDiagnostic.Suppress) + + options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) + Assert.False(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + Assert.True(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) + End Sub +#Enable Warning BC40000 ' Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete + Public Class ModuleStatementAnalyzer Inherits DiagnosticAnalyzer From 52c69096453ef7fa926e1d672ac8bac9fc40940a Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 14 Apr 2023 04:37:21 -0700 Subject: [PATCH 5/9] Refactor to fix test validating analyzer exception --- .../DiagnosticLocalizationTests.cs | 4 +- .../DiagnosticAnalyzer/AnalyzerExecutor.cs | 50 ++++++++++++------- .../DiagnosticAnalyzer/AnalyzerManager.cs | 17 +++---- .../CompilationWithAnalyzers.cs | 39 ++++++++++++--- 4 files changed, 74 insertions(+), 36 deletions(-) diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs index 7d0b4fbe31281..9764d5519b5cf 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/DiagnosticLocalizationTests.cs @@ -307,8 +307,8 @@ private static void TestDescriptorIsExceptionSafeCore(DiagnosticDescriptor descr var analyzerExecutor = AnalyzerExecutor.Create(compilation, AnalyzerOptions.Empty, addNonCategorizedDiagnostic: (_, _) => { }, onAnalyzerException, analyzerExceptionFilter: null, isCompilerAnalyzer: _ => false, analyzerManager, shouldSkipAnalysisOnGeneratedCode: _ => false, - shouldSuppressGeneratedCodeDiagnostic: (_, _, _, _) => false, isGeneratedCodeLocation: (_, _) => false, - isAnalyzerSuppressedForTree: (_, _, _) => false, getAnalyzerGate: _ => null, + shouldSuppressGeneratedCodeDiagnostic: (_, _, _, _) => false, isGeneratedCodeLocation: (_, _, _) => false, + isAnalyzerSuppressedForTree: (_, _, _, _) => false, getAnalyzerGate: _ => null, getSemanticModel: tree => compilation.GetSemanticModel(tree, ignoreAccessibility: true)); var descriptors = analyzerManager.GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, CancellationToken.None); diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index a5d54c9f6534e..e847da08a51be 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -1147,34 +1147,50 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A cancellationToken.ThrowIfCancellationRequested(); analyze(argument); } - catch (Exception e) when (ExceptionFilter(e, cancellationToken)) + catch (Exception ex) { - // Diagnostic for analyzer exception. - var diagnostic = CreateAnalyzerExceptionDiagnostic(analyzer, e, info); - try - { - OnAnalyzerException(e, analyzer, diagnostic, cancellationToken); - } - catch (Exception) - { - // Ignore exceptions from exception handlers. - } + HandleAnalyzerException(ex, analyzer, info, OnAnalyzerException, _analyzerExceptionFilter, cancellationToken); } } - internal bool ExceptionFilter(Exception ex, CancellationToken cancellationToken) + internal static void HandleAnalyzerException( + Exception exception, + DiagnosticAnalyzer analyzer, + AnalysisContextInfo? info, + Action onAnalyzerException, + Func? analyzerExceptionFilter, + CancellationToken cancellationToken) { - if ((ex as OperationCanceledException)?.CancellationToken == cancellationToken) + if (!ExceptionFilter(exception, analyzerExceptionFilter, cancellationToken)) { - return false; + throw exception; } - if (_analyzerExceptionFilter != null) + // Diagnostic for analyzer exception. + var diagnostic = CreateAnalyzerExceptionDiagnostic(analyzer, exception, info); + try + { + onAnalyzerException(exception, analyzer, diagnostic, cancellationToken); + } + catch (Exception) { - return _analyzerExceptionFilter(ex); + // Ignore exceptions from exception handlers. } - return true; + static bool ExceptionFilter(Exception ex, Func? analyzerExceptionFilter, CancellationToken cancellationToken) + { + if ((ex as OperationCanceledException)?.CancellationToken == cancellationToken) + { + return false; + } + + if (analyzerExceptionFilter != null) + { + return analyzerExceptionFilter(ex); + } + + return true; + } } internal static Diagnostic CreateAnalyzerExceptionDiagnostic(DiagnosticAnalyzer analyzer, Exception e, AnalysisContextInfo? info = null) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs index ba42f747e9c56..d8ed74f140798 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.cs @@ -297,11 +297,10 @@ internal bool IsDiagnosticAnalyzerSuppressed( SeverityFilter severityFilter, CancellationToken cancellationToken) { - Func> getSupportedDiagnosticDescriptors = - (analyzer, cancellationToken) => GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, cancellationToken); - - Func> getSupportedSuppressionDescriptors = - (suppressor, cancellationToken) => GetSupportedSuppressionDescriptors(suppressor, analyzerExecutor, cancellationToken); + Func> getSupportedDiagnosticDescriptors = + analyzer => GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor, cancellationToken); + Func> getSupportedSuppressionDescriptors = + suppressor => GetSupportedSuppressionDescriptors(suppressor, analyzerExecutor, cancellationToken); return IsDiagnosticAnalyzerSuppressed(analyzer, options, isCompilerAnalyzer, severityFilter, isEnabledWithAnalyzerConfigOptions, getSupportedDiagnosticDescriptors, getSupportedSuppressionDescriptors, cancellationToken); @@ -337,8 +336,8 @@ internal static bool IsDiagnosticAnalyzerSuppressed( Func isCompilerAnalyzer, SeverityFilter severityFilter, Func isEnabledWithAnalyzerConfigOptions, - Func> getSupportedDiagnosticDescriptors, - Func> getSupportedSuppressionDescriptors, + Func> getSupportedDiagnosticDescriptors, + Func> getSupportedSuppressionDescriptors, CancellationToken cancellationToken) { if (isCompilerAnalyzer(analyzer)) @@ -347,7 +346,7 @@ internal static bool IsDiagnosticAnalyzerSuppressed( return false; } - var supportedDiagnostics = getSupportedDiagnosticDescriptors(analyzer, cancellationToken); + var supportedDiagnostics = getSupportedDiagnosticDescriptors(analyzer); var diagnosticOptions = options.SpecificDiagnosticOptions; foreach (var diag in supportedDiagnostics) @@ -405,7 +404,7 @@ internal static bool IsDiagnosticAnalyzerSuppressed( if (analyzer is DiagnosticSuppressor suppressor) { - foreach (var suppressionDescriptor in getSupportedSuppressionDescriptors(suppressor, cancellationToken)) + foreach (var suppressionDescriptor in getSupportedSuppressionDescriptors(suppressor)) { if (!suppressionDescriptor.IsDisabled(options)) { diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs index 73b5abc91066a..e7783dc1d9724 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs @@ -1082,14 +1082,37 @@ public static bool IsDiagnosticAnalyzerSuppressed( var analyzerManager = new AnalyzerManager(analyzer); - Action? wrappedOnAnalyzerException = - onAnalyzerException == null ? null : (ex, analyzer, diagnostic, _) => onAnalyzerException(ex, analyzer, diagnostic); - return AnalyzerManager.IsDiagnosticAnalyzerSuppressed(analyzer, options, - IsCompilerAnalyzer, severityFilter: SeverityFilter.None, - isEnabledWithAnalyzerConfigOptions: _ => false, - getSupportedDiagnosticDescriptors: (analyzer, _) => analyzer.SupportedDiagnostics, - getSupportedSuppressionDescriptors: (suppressor, _) => suppressor.SupportedSuppressions, - CancellationToken.None); ; + Action wrappedOnAnalyzerException = + (ex, analyzer, diagnostic, _) => onAnalyzerException?.Invoke(ex, analyzer, diagnostic); + + Func> getSupportedDiagnosticDescriptors = analyzer => + { + try + { + return analyzer.SupportedDiagnostics; + } + catch (Exception ex) + { + AnalyzerExecutor.HandleAnalyzerException(ex, analyzer, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None); + return ImmutableArray.Empty; + } + }; + + Func> getSupportedSuppressionDescriptors = suppressor => + { + try + { + return suppressor.SupportedSuppressions; + } + catch (Exception ex) + { + AnalyzerExecutor.HandleAnalyzerException(ex, analyzer, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None); + return ImmutableArray.Empty; + } + }; + + return AnalyzerManager.IsDiagnosticAnalyzerSuppressed(analyzer, options, IsCompilerAnalyzer, severityFilter: SeverityFilter.None, + isEnabledWithAnalyzerConfigOptions: _ => false, getSupportedDiagnosticDescriptors, getSupportedSuppressionDescriptors, CancellationToken.None); ; } /// From ed91b0777cb19417528c154b15907ff3d4bbb739 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 14 Apr 2023 04:41:57 -0700 Subject: [PATCH 6/9] Fix typo --- .../Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs index e7783dc1d9724..dbc6e42940996 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs @@ -1106,7 +1106,7 @@ public static bool IsDiagnosticAnalyzerSuppressed( } catch (Exception ex) { - AnalyzerExecutor.HandleAnalyzerException(ex, analyzer, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None); + AnalyzerExecutor.HandleAnalyzerException(ex, suppressor, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None); return ImmutableArray.Empty; } }; From f4810e36018721c5ae53d4a0f64a0f8c45b4e899 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Wed, 3 May 2023 10:31:55 +0530 Subject: [PATCH 7/9] Address feedback from Chuck --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs | 9 +++++---- .../DiagnosticAnalyzer/CompilationWithAnalyzers.cs | 6 ++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs index e847da08a51be..4e4301f24eb3a 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs @@ -1147,13 +1147,12 @@ private void ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, A cancellationToken.ThrowIfCancellationRequested(); analyze(argument); } - catch (Exception ex) + catch (Exception ex) when (HandleAnalyzerException(ex, analyzer, info, OnAnalyzerException, _analyzerExceptionFilter, cancellationToken)) { - HandleAnalyzerException(ex, analyzer, info, OnAnalyzerException, _analyzerExceptionFilter, cancellationToken); } } - internal static void HandleAnalyzerException( + internal static bool HandleAnalyzerException( Exception exception, DiagnosticAnalyzer analyzer, AnalysisContextInfo? info, @@ -1163,7 +1162,7 @@ internal static void HandleAnalyzerException( { if (!ExceptionFilter(exception, analyzerExceptionFilter, cancellationToken)) { - throw exception; + return false; } // Diagnostic for analyzer exception. @@ -1177,6 +1176,8 @@ internal static void HandleAnalyzerException( // Ignore exceptions from exception handlers. } + return true; + static bool ExceptionFilter(Exception ex, Func? analyzerExceptionFilter, CancellationToken cancellationToken) { if ((ex as OperationCanceledException)?.CancellationToken == cancellationToken) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs index dbc6e42940996..7ddc28bf1af62 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/CompilationWithAnalyzers.cs @@ -1091,9 +1091,8 @@ public static bool IsDiagnosticAnalyzerSuppressed( { return analyzer.SupportedDiagnostics; } - catch (Exception ex) + catch (Exception ex) when (AnalyzerExecutor.HandleAnalyzerException(ex, analyzer, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None)) { - AnalyzerExecutor.HandleAnalyzerException(ex, analyzer, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None); return ImmutableArray.Empty; } }; @@ -1104,9 +1103,8 @@ public static bool IsDiagnosticAnalyzerSuppressed( { return suppressor.SupportedSuppressions; } - catch (Exception ex) + catch (Exception ex) when (AnalyzerExecutor.HandleAnalyzerException(ex, suppressor, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None)) { - AnalyzerExecutor.HandleAnalyzerException(ex, suppressor, info: null, wrappedOnAnalyzerException, analyzerExceptionFilter: null, CancellationToken.None); return ImmutableArray.Empty; } }; From a92b060bcc15fcc26837a93a52c007b0e8fc7a91 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Wed, 3 May 2023 10:35:41 +0530 Subject: [PATCH 8/9] Address feedback from Sam --- .../CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs | 4 +--- .../Diagnostics/CompilationWithAnalyzersTests.cs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs index bf83129a225fa..06a5b1001bb45 100644 --- a/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Diagnostics/DiagnosticAnalyzerTests.cs @@ -516,8 +516,7 @@ public override void Initialize(AnalysisContext context) } } -#pragma warning disable CS0618 // Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete - [Fact] + [Fact, Obsolete(message: "IsDiagnosticAnalyzerSuppressed is an obsolete public API")] public void TestDisabledAnalyzers() { var fullyDisabledAnalyzer = new FullyDisabledAnalyzer(); @@ -541,7 +540,6 @@ public void TestDisabledAnalyzers() options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions); Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)); } -#pragma warning restore CS0618 // Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete [Fact, WorkItem(1008059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1008059")] public void TestCodeBlockAnalyzersForNoExecutableCode() diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs index 7b26923137f48..995ddab41fdf6 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/CompilationWithAnalyzersTests.cs @@ -69,14 +69,12 @@ public void GetAnalyzerTelemetry() Assert.Equal(0, analyzerTelemetry.SymbolActionsCount); } - [Fact] + [Fact, Obsolete(message: "IsDiagnosticAnalyzerSuppressed is an obsolete public API")] public void TestIsDiagnosticAnalyzerSuppressedWithExceptionInSupportedDiagnostics() { // Verify IsDiagnosticAnalyzerSuppressed does not throw an exception when 'onAnalyzerException' is null. var analyzer = new AnalyzerThatThrowsInSupportedDiagnostics(); -#pragma warning disable CS0618 // Type or member is obsolete _ = CompilationWithAnalyzers.IsDiagnosticAnalyzerSuppressed(analyzer, s_dllWithMaxWarningLevel, onAnalyzerException: null); -#pragma warning restore CS0618 // Type or member is obsolete } } } From 5aa26e90f04609927d44fb6d724c819402ba82a8 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Wed, 3 May 2023 10:41:32 +0530 Subject: [PATCH 9/9] Also update VB test --- .../Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb index 8e727de98be68..24721c44d70ba 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb @@ -241,8 +241,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics End Sub End Class -#Disable Warning BC40000 ' Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete - + Public Sub TestDisabledAnalyzers() Dim fullyDisabledAnalyzer = New FullyDisabledAnalyzer() Dim partiallyDisabledAnalyzer = New PartiallyDisabledAnalyzer() @@ -259,7 +258,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics Assert.False(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) Assert.True(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) End Sub -#Enable Warning BC40000 ' Type or member is obsolete - IsDiagnosticAnalyzerSuppressed is obsolete Public Class ModuleStatementAnalyzer Inherits DiagnosticAnalyzer