From 6c7227cd2cbd6746fa11472038d5f7736fabeedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 16:35:59 +0100 Subject: [PATCH 01/14] preparation of unit test --- .../IncludeDiagnosticsMentionedByCodeFixTests.cs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs new file mode 100644 index 000000000..dfd3b359b --- /dev/null +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs @@ -0,0 +1,7 @@ +namespace Microsoft.CodeAnalysis.Testing +{ + public class IncludeDiagnosticsMentiondByCodeFixTests + { + + } +} From 1c78beaba6e42b39257fdab878437fa44170512a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 16:36:18 +0100 Subject: [PATCH 02/14] preparation of unit test --- ...cludeDiagnosticsMentionedByCodeFixTests.cs | 88 ++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs index dfd3b359b..11f65745a 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs @@ -1,7 +1,89 @@ -namespace Microsoft.CodeAnalysis.Testing +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Composition; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Text; +using Xunit; + +namespace Microsoft.CodeAnalysis.Testing { - public class IncludeDiagnosticsMentiondByCodeFixTests + public class IncludeDiagnosticsMentionedByCodeFixTests { - + private class Verify : CodeFixVerifier, DefaultVerifier> + where TCodeFix : CodeFixProvider, new() + { + } + + [ExportCodeFixProvider(LanguageNames.CSharp)] + [PartNotDiscoverable] + internal class SomeCodeFix : CodeFixProvider + { + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + foreach (var diagnostic in context.Diagnostics) + { + context.RegisterCodeFix( + CodeAction.Create( + nameof(SomeCodeFix), + cancellationToken => CreateChangedDocument(context.Document, diagnostic.Location.SourceSpan, + cancellationToken), + nameof(SomeCodeFix)), + diagnostic); + } + + return Task.CompletedTask; + } + + private async Task CreateChangedDocument( + Document document, + TextSpan sourceSpan, + CancellationToken cancellationToken) + { + var tree = await document.GetSyntaxTreeAsync(cancellationToken); + var root = await tree.GetRootAsync(cancellationToken); + var node = root.FindNode(sourceSpan); + return document.WithSyntaxRoot(root.RemoveNode(node, SyntaxRemoveOptions.AddElasticMarker)); + } + + public override ImmutableArray FixableDiagnosticIds => new[] { "CS0169" }.ToImmutableArray(); + } + + /// + /// Verifies that a test case with automatically include compiler diagnostics which are part of the the provided codefix + /// + /// A representing the asynchronous unit test. + [Fact] + [WorkItem(419, "https://github.com/dotnet/roslyn-sdk/issues/419")] + public async Task VerifySimpleSyntaxWorks() + { + var before = @" +using System; + +namespace ConsoleApp1 +{ + public class TestClass + { + private int someField; + + public void SomeMethod(){} + } +}"; + + var after = @" +using System; + +namespace ConsoleApp1 +{ + public class TestClass + { + public void SomeMethod(){} + } +}"; + await Verify.VerifyCodeFixAsync(before, DiagnosticResult.CompilerWarning("CS0169"), after); + } } } From edbb39240cb28c6a94d0095a06143e7a127eb0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 16:54:26 +0100 Subject: [PATCH 03/14] unit test to verify changes --- .../IncludeDiagnosticsMentionedByCodeFixTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs index 11f65745a..aff43612d 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs @@ -83,6 +83,7 @@ public class TestClass public void SomeMethod(){} } }"; + await Verify.VerifyCodeFixAsync(before, DiagnosticResult.CompilerWarning("CS0169"), after); } } From 989775d29d619b39abb13bb604eb69ce347dedd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 22:17:04 +0100 Subject: [PATCH 04/14] Manual API updates + modifications to cover reason for issue 419 --- .../AnalyzerTest`1.cs | 8 ++++++++ .../PublicAPI.Unshipped.txt | 1 + .../CodeFixTest`1.cs | 8 ++++++++ .../PublicAPI.Unshipped.txt | 1 + ...IncludeDiagnosticsMentionedByCodeFixTests.cs | 17 ++++++++++------- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index b7aff52f0..5a3d26733 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -791,6 +791,7 @@ protected async Task> GetSortedDiagnosticsAsync(Solut bool IsIncludedDiagnostic(Diagnostic diagnostic) { return !IsCompilerDiagnostic(diagnostic) + || IsDiagnosticHandled(diagnostic) || IsCompilerDiagnosticIncluded(diagnostic); } @@ -822,6 +823,13 @@ bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic) } } + /// + /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false + /// + /// the diagnostic which is subject to filter processes. + /// return true to exclude a diagnostic, false to leave it up to internal logic. + protected internal virtual bool IsDiagnosticHandled(Diagnostic diagnostic) => false; + /// /// Gets the effective analyzer options for a project. The default implementation returns /// . diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt index 5a684f004..2fa7d52cd 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt @@ -251,6 +251,7 @@ virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.CreateWorkspace() virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultFilePath.get -> string virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultFilePathPrefix.get -> string virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultTestProjectName.get -> string +virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.IsDiagnosticHandled(Microsoft.CodeAnalysis.Diagnostic diagnostic) -> bool virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetAnalyzerOptions(Microsoft.CodeAnalysis.Project project) -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetDefaultDiagnostic(Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer[] analyzers) -> Microsoft.CodeAnalysis.DiagnosticDescriptor virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.RunAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs index 82865ff60..020237cfc 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs @@ -169,6 +169,14 @@ protected CodeFixTest() /// The to be used. protected abstract IEnumerable GetCodeFixProviders(); + /// + protected override bool IsDiagnosticHandled(Diagnostic diagnostic) + { + var codeFixProviders = GetCodeFixProviders(); + return codeFixProviders + .Any(provider => provider.FixableDiagnosticIds.Any(fixerDiagnosticId => string.Equals(fixerDiagnosticId, diagnostic.Id, StringComparison.OrdinalIgnoreCase))); + } + public override async Task RunAsync(CancellationToken cancellationToken = default) { Verify.NotEmpty($"{nameof(TestState)}.{nameof(SolutionState.Sources)}", TestState.Sources); diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt index 48689e241..bf51ebf28 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt @@ -27,6 +27,7 @@ Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider.EmptyCodeFixProvider() -> void abstract Microsoft.CodeAnalysis.Testing.CodeFixTest.GetCodeFixProviders() -> System.Collections.Generic.IEnumerable abstract Microsoft.CodeAnalysis.Testing.CodeFixTest.SyntaxKindType.get -> System.Type +override Microsoft.CodeAnalysis.Testing.CodeFixTest.IsDiagnosticHandled(Microsoft.CodeAnalysis.Diagnostic diagnostic) -> bool override Microsoft.CodeAnalysis.Testing.CodeFixTest.RunAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task override Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider.FixableDiagnosticIds.get -> System.Collections.Immutable.ImmutableArray override Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider.RegisterCodeFixesAsync(Microsoft.CodeAnalysis.CodeFixes.CodeFixContext context) -> System.Threading.Tasks.Task diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs index aff43612d..67a02fb98 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs @@ -2,10 +2,12 @@ using System.Collections.Immutable; using System.Composition; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; using Xunit; @@ -29,8 +31,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( nameof(SomeCodeFix), - cancellationToken => CreateChangedDocument(context.Document, diagnostic.Location.SourceSpan, - cancellationToken), + cancellationToken => CreateChangedDocument(context.Document, diagnostic.Location.SourceSpan, cancellationToken), nameof(SomeCodeFix)), diagnostic); } @@ -46,7 +47,8 @@ private async Task CreateChangedDocument( var tree = await document.GetSyntaxTreeAsync(cancellationToken); var root = await tree.GetRootAsync(cancellationToken); var node = root.FindNode(sourceSpan); - return document.WithSyntaxRoot(root.RemoveNode(node, SyntaxRemoveOptions.AddElasticMarker)); + var targetNode = node.AncestorsAndSelf().OfType().FirstOrDefault(); + return document.WithSyntaxRoot(root.RemoveNode(targetNode, SyntaxRemoveOptions.AddElasticMarker)); } public override ImmutableArray FixableDiagnosticIds => new[] { "CS0169" }.ToImmutableArray(); @@ -67,9 +69,9 @@ namespace ConsoleApp1 { public class TestClass { - private int someField; + private int someField; - public void SomeMethod(){} + public void SomeMethod(){} } }"; @@ -80,11 +82,12 @@ namespace ConsoleApp1 { public class TestClass { - public void SomeMethod(){} + public void SomeMethod(){} } }"; - await Verify.VerifyCodeFixAsync(before, DiagnosticResult.CompilerWarning("CS0169"), after); + var diagnostic = DiagnosticResult.CompilerWarning("CS0169").WithSpan(8, 21, 8, 30).WithArguments("ConsoleApp1.TestClass.someField"); + await Verify.VerifyCodeFixAsync(before, diagnostic, after); } } } From 4bb06c238a35a64c7741aa2145ce53fa16f3a584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 22:30:09 +0100 Subject: [PATCH 05/14] RS1016 handling --- .../IncludeDiagnosticsMentionedByCodeFixTests.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs index 67a02fb98..c5fc6707b 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing.UnitTests/IncludeDiagnosticsMentionedByCodeFixTests.cs @@ -24,6 +24,12 @@ private class Verify : CodeFixVerifier + public override FixAllProvider GetFixAllProvider() + { + return WellKnownFixAllProviders.BatchFixer; + } + public override Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) From 89e83500ec83ef86d0b6c3d3e0704ef7bb6fc81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 22:46:56 +0100 Subject: [PATCH 06/14] updates from codereview --- .../Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index 5a3d26733..c5ca1e3bc 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -828,7 +828,7 @@ bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic) /// /// the diagnostic which is subject to filter processes. /// return true to exclude a diagnostic, false to leave it up to internal logic. - protected internal virtual bool IsDiagnosticHandled(Diagnostic diagnostic) => false; + protected virtual bool IsDiagnosticHandled(Diagnostic diagnostic) => false; /// /// Gets the effective analyzer options for a project. The default implementation returns From dcb50f536fe15ece48a6bdfe8fa4651592194614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 23:12:09 +0100 Subject: [PATCH 07/14] Changes according to code review --- .../AnalyzerTest`1.cs | 51 +++++++++---------- .../PublicAPI.Unshipped.txt | 2 +- .../CodeFixTest`1.cs | 18 +++++-- .../PublicAPI.Unshipped.txt | 2 +- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index c5ca1e3bc..ea12fef09 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -786,50 +786,49 @@ protected async Task> GetSortedDiagnosticsAsync(Solut var results = SortDistinctDiagnostics(diagnostics); return results.ToImmutableArray(); + } - // Local function - bool IsIncludedDiagnostic(Diagnostic diagnostic) - { - return !IsCompilerDiagnostic(diagnostic) - || IsDiagnosticHandled(diagnostic) - || IsCompilerDiagnosticIncluded(diagnostic); - } + /// + /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false + /// + /// the diagnostic which is subject to filter processes. + /// return true to exclude a diagnostic, false to leave it up to internal logic. + protected virtual bool IsDiagnosticHandled(Diagnostic diagnostic) => false; + + protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, + CompilerDiagnostics compilerDiagnostics) + { + return IsCompilerDiagnostic(diagnostic) + || IsCompilerDiagnosticIncluded(); static bool IsCompilerDiagnostic(Diagnostic diagnostic) { return diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Compiler); } - bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic) + bool IsCompilerDiagnosticIncluded() { switch (compilerDiagnostics) { - case CompilerDiagnostics.None: - default: - return false; + case CompilerDiagnostics.None: + default: + return false; - case CompilerDiagnostics.Errors: - return diagnostic.Severity >= DiagnosticSeverity.Error; + case CompilerDiagnostics.Errors: + return diagnostic.Severity >= DiagnosticSeverity.Error; - case CompilerDiagnostics.Warnings: - return diagnostic.Severity >= DiagnosticSeverity.Warning; + case CompilerDiagnostics.Warnings: + return diagnostic.Severity >= DiagnosticSeverity.Warning; - case CompilerDiagnostics.Suggestions: - return diagnostic.Severity >= DiagnosticSeverity.Info; + case CompilerDiagnostics.Suggestions: + return diagnostic.Severity >= DiagnosticSeverity.Info; - case CompilerDiagnostics.All: - return true; + case CompilerDiagnostics.All: + return true; } } } - /// - /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false - /// - /// the diagnostic which is subject to filter processes. - /// return true to exclude a diagnostic, false to leave it up to internal logic. - protected virtual bool IsDiagnosticHandled(Diagnostic diagnostic) => false; - /// /// Gets the effective analyzer options for a project. The default implementation returns /// . diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt index 2fa7d52cd..a03633c6d 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt @@ -251,7 +251,7 @@ virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.CreateWorkspace() virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultFilePath.get -> string virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultFilePathPrefix.get -> string virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultTestProjectName.get -> string -virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.IsDiagnosticHandled(Microsoft.CodeAnalysis.Diagnostic diagnostic) -> bool +virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.IsCompilerDiagnosticIncluded(Microsoft.CodeAnalysis.Diagnostic diagnostic, Microsoft.CodeAnalysis.Testing.CompilerDiagnostics compilerDiagnostics) -> bool virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetAnalyzerOptions(Microsoft.CodeAnalysis.Project project) -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetDefaultDiagnostic(Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer[] analyzers) -> Microsoft.CodeAnalysis.DiagnosticDescriptor virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.RunAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs index 020237cfc..9a251146b 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs @@ -170,11 +170,21 @@ protected CodeFixTest() protected abstract IEnumerable GetCodeFixProviders(); /// - protected override bool IsDiagnosticHandled(Diagnostic diagnostic) + protected override bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) { - var codeFixProviders = GetCodeFixProviders(); - return codeFixProviders - .Any(provider => provider.FixableDiagnosticIds.Any(fixerDiagnosticId => string.Equals(fixerDiagnosticId, diagnostic.Id, StringComparison.OrdinalIgnoreCase))); + if (base.IsCompilerDiagnosticIncluded(diagnostic, compilerDiagnostics)) + { + return true; + } + + return CodeFixProvidersHandleDiagnostic(diagnostic); + + bool CodeFixProvidersHandleDiagnostic(Diagnostic localDiagnostic) + { + var codeFixProviders = GetCodeFixProviders(); + return codeFixProviders + .Any(provider => provider.FixableDiagnosticIds.Any(fixerDiagnosticId => string.Equals(fixerDiagnosticId, localDiagnostic.Id, StringComparison.OrdinalIgnoreCase))); + } } public override async Task RunAsync(CancellationToken cancellationToken = default) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt index bf51ebf28..01d4c78b0 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/PublicAPI.Unshipped.txt @@ -27,7 +27,7 @@ Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider.EmptyCodeFixProvider() -> void abstract Microsoft.CodeAnalysis.Testing.CodeFixTest.GetCodeFixProviders() -> System.Collections.Generic.IEnumerable abstract Microsoft.CodeAnalysis.Testing.CodeFixTest.SyntaxKindType.get -> System.Type -override Microsoft.CodeAnalysis.Testing.CodeFixTest.IsDiagnosticHandled(Microsoft.CodeAnalysis.Diagnostic diagnostic) -> bool +override Microsoft.CodeAnalysis.Testing.CodeFixTest.IsCompilerDiagnosticIncluded(Microsoft.CodeAnalysis.Diagnostic diagnostic, Microsoft.CodeAnalysis.Testing.CompilerDiagnostics compilerDiagnostics) -> bool override Microsoft.CodeAnalysis.Testing.CodeFixTest.RunAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task override Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider.FixableDiagnosticIds.get -> System.Collections.Immutable.ImmutableArray override Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider.RegisterCodeFixesAsync(Microsoft.CodeAnalysis.CodeFixes.CodeFixContext context) -> System.Threading.Tasks.Task From 23f9a08b2fff3df6f6a96e13e8e1d1a49ea8b019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 16 Jan 2020 23:31:07 +0100 Subject: [PATCH 08/14] cleanup --- .../AnalyzerTest`1.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index ea12fef09..af5ebea07 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -781,7 +781,8 @@ protected async Task> GetSortedDiagnosticsAsync(Solut var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, GetAnalyzerOptions(project), cancellationToken); var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync().ConfigureAwait(false); - diagnostics.AddRange(allDiagnostics.Where(IsIncludedDiagnostic)); + + diagnostics.AddRange(allDiagnostics.Where(diagnostic => IsCompilerDiagnosticIncluded(diagnostic, CompilerDiagnostics))); } var results = SortDistinctDiagnostics(diagnostics); @@ -792,11 +793,9 @@ protected async Task> GetSortedDiagnosticsAsync(Solut /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false /// /// the diagnostic which is subject to filter processes. + /// level of diagnostic used to filter compiler diagnostics /// return true to exclude a diagnostic, false to leave it up to internal logic. - protected virtual bool IsDiagnosticHandled(Diagnostic diagnostic) => false; - - protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, - CompilerDiagnostics compilerDiagnostics) + protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) { return IsCompilerDiagnostic(diagnostic) || IsCompilerDiagnosticIncluded(); From 13e137445b357cdf5adc61896b7ef4ff1777b63a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 17 Jan 2020 00:01:39 +0100 Subject: [PATCH 09/14] unit test fixes --- .../AnalyzerTest`1.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index af5ebea07..bcb70c95f 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -782,7 +782,7 @@ protected async Task> GetSortedDiagnosticsAsync(Solut var compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, GetAnalyzerOptions(project), cancellationToken); var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync().ConfigureAwait(false); - diagnostics.AddRange(allDiagnostics.Where(diagnostic => IsCompilerDiagnosticIncluded(diagnostic, CompilerDiagnostics))); + diagnostics.AddRange(allDiagnostics.Where(diagnostic => IsCompilerDiagnosticIncluded(diagnostic, compilerDiagnostics))); } var results = SortDistinctDiagnostics(diagnostics); @@ -797,15 +797,15 @@ protected async Task> GetSortedDiagnosticsAsync(Solut /// return true to exclude a diagnostic, false to leave it up to internal logic. protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) { - return IsCompilerDiagnostic(diagnostic) - || IsCompilerDiagnosticIncluded(); + return !IsCompilerDiagnostic(diagnostic) + || IsCompilerDiagnosticIncluded(diagnostic, compilerDiagnostics); static bool IsCompilerDiagnostic(Diagnostic diagnostic) { return diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Compiler); } - bool IsCompilerDiagnosticIncluded() + static bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) { switch (compilerDiagnostics) { From c0e721ca75de7051a2a8634a8663c09555bb56ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 17 Jan 2020 00:28:00 +0100 Subject: [PATCH 10/14] Update src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs Co-Authored-By: Sam Harwell --- .../Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index bcb70c95f..50bc16311 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -792,7 +792,7 @@ protected async Task> GetSortedDiagnosticsAsync(Solut /// /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false /// - /// the diagnostic which is subject to filter processes. + /// The compiler diagnostic. /// level of diagnostic used to filter compiler diagnostics /// return true to exclude a diagnostic, false to leave it up to internal logic. protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) From 80f220bdf6878aa4e429e711fc7f2d94f51cc0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 17 Jan 2020 00:28:17 +0100 Subject: [PATCH 11/14] Update src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs Co-Authored-By: Sam Harwell --- .../Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index 50bc16311..c92822ab2 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -793,7 +793,7 @@ protected async Task> GetSortedDiagnosticsAsync(Solut /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false /// /// The compiler diagnostic. - /// level of diagnostic used to filter compiler diagnostics + /// The compiler diagnostic level in effect for the test. /// return true to exclude a diagnostic, false to leave it up to internal logic. protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) { From c9d5c3c02fc70cc7df828016ccd237657df72370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 17 Jan 2020 00:28:41 +0100 Subject: [PATCH 12/14] Update src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs Co-Authored-By: Sam Harwell --- .../Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index c92822ab2..55f290c3b 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -794,7 +794,7 @@ protected async Task> GetSortedDiagnosticsAsync(Solut /// /// The compiler diagnostic. /// The compiler diagnostic level in effect for the test. - /// return true to exclude a diagnostic, false to leave it up to internal logic. + /// to include the diagnostic for validation; otherwise, to exclude a diagnostic. protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) { return !IsCompilerDiagnostic(diagnostic) From de64475fc77c952067ac3609319dd89a0f7ce48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 17 Jan 2020 00:30:39 +0100 Subject: [PATCH 13/14] Update src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs Co-Authored-By: Sam Harwell --- .../Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index 55f290c3b..cf1921365 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -790,7 +790,7 @@ protected async Task> GetSortedDiagnosticsAsync(Solut } /// - /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false + /// Determines if a compiler diagnostic should be included for diagnostic validation. The default implementation includes all diagnostics at a severity level indicated by . /// /// The compiler diagnostic. /// The compiler diagnostic level in effect for the test. From 1c4cf6a50bc5f7bb761c3114ae790d25836ac8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 17 Jan 2020 18:05:53 +0100 Subject: [PATCH 14/14] push remaining changes --- .../AnalyzerTest`1.cs | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index bcb70c95f..978f59c71 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -782,13 +782,18 @@ protected async Task> GetSortedDiagnosticsAsync(Solut var compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, GetAnalyzerOptions(project), cancellationToken); var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync().ConfigureAwait(false); - diagnostics.AddRange(allDiagnostics.Where(diagnostic => IsCompilerDiagnosticIncluded(diagnostic, compilerDiagnostics))); + diagnostics.AddRange(allDiagnostics.Where(diagnostic => !IsCompilerDiagnostic(diagnostic) || IsCompilerDiagnosticIncluded(diagnostic, compilerDiagnostics))); } var results = SortDistinctDiagnostics(diagnostics); return results.ToImmutableArray(); } + private static bool IsCompilerDiagnostic(Diagnostic diagnostic) + { + return diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Compiler); + } + /// /// Extension point to allow inheriting classes to include diagnostics which would otherwise be filtered. The default implementation returns false /// @@ -797,34 +802,23 @@ protected async Task> GetSortedDiagnosticsAsync(Solut /// return true to exclude a diagnostic, false to leave it up to internal logic. protected virtual bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) { - return !IsCompilerDiagnostic(diagnostic) - || IsCompilerDiagnosticIncluded(diagnostic, compilerDiagnostics); - - static bool IsCompilerDiagnostic(Diagnostic diagnostic) - { - return diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Compiler); - } - - static bool IsCompilerDiagnosticIncluded(Diagnostic diagnostic, CompilerDiagnostics compilerDiagnostics) + switch (compilerDiagnostics) { - switch (compilerDiagnostics) - { - case CompilerDiagnostics.None: - default: - return false; + case CompilerDiagnostics.None: + default: + return false; - case CompilerDiagnostics.Errors: - return diagnostic.Severity >= DiagnosticSeverity.Error; + case CompilerDiagnostics.Errors: + return diagnostic.Severity >= DiagnosticSeverity.Error; - case CompilerDiagnostics.Warnings: - return diagnostic.Severity >= DiagnosticSeverity.Warning; + case CompilerDiagnostics.Warnings: + return diagnostic.Severity >= DiagnosticSeverity.Warning; - case CompilerDiagnostics.Suggestions: - return diagnostic.Severity >= DiagnosticSeverity.Info; + case CompilerDiagnostics.Suggestions: + return diagnostic.Severity >= DiagnosticSeverity.Info; - case CompilerDiagnostics.All: - return true; - } + case CompilerDiagnostics.All: + return true; } }