From 4a7d283e6a9c58d02121efac41a1ce9a1161bb87 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 14 Feb 2020 16:58:39 -0800 Subject: [PATCH 1/9] Implement analyzer and fix verifiers --- eng/Versions.props | 4 +- .../CSharpCodeFixVerifier`2+Test.cs | 73 +++++++++++++++++++ .../CodeActions/CSharpCodeFixVerifier`2.cs | 56 ++++++++++++++ .../CodeActions/OptionsCollection.cs | 43 +++++++++++ .../VisualBasicCodeFixVerifier`2+Test.cs | 51 +++++++++++++ .../VisualBasicCodeFixVerifier`2.cs | 56 ++++++++++++++ .../Roslyn.Services.Test.Utilities.csproj | 2 + 7 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs create mode 100644 src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs create mode 100644 src/EditorFeatures/TestUtilities/CodeActions/OptionsCollection.cs create mode 100644 src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs create mode 100644 src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs diff --git a/eng/Versions.props b/eng/Versions.props index 12cffd628b7f5..106d12fb72c13 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -28,7 +28,7 @@ 3.0.0-beta2.20059.3+77df2220 3.3.1 - 1.0.1-beta1.20067.1 + 1.0.1-beta1.20114.4 3.5.0-beta3-20078-04 16.4.248 5.0.0-alpha1.19409.1 @@ -97,7 +97,7 @@ 15.8.27812-alpha 1.1.20180503.2 16.0.198-g52de9c2988 - 15.5.23 + 15.6.36 $(VisualStudioEditorPackagesVersion) 16.0.29431.108 16.4.1091102-preview diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs new file mode 100644 index 0000000000000..986765afc1974 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions +{ + public static partial class CSharpCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + public class Test : CSharpCodeFixTest + { + private static readonly ImmutableDictionary NullableWarnings = GetNullableWarningsFromCompiler(); + + public Test() + { + MarkupOptions = Testing.MarkupOptions.UseFirstDescriptor; + + SolutionTransforms.Add((solution, projectId) => + { + var parseOptions = (CSharpParseOptions)solution.GetProject(projectId).ParseOptions; + solution = solution.WithProjectParseOptions(projectId, parseOptions.WithLanguageVersion(LanguageVersion)); + + var compilationOptions = solution.GetProject(projectId).CompilationOptions; + compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(compilationOptions.SpecificDiagnosticOptions.SetItems(NullableWarnings)); + solution = solution.WithProjectCompilationOptions(projectId, compilationOptions); + + var options = solution.Options; + foreach (var (key, value) in Options) + { + options = options.WithChangedOption(key, value); + } + + solution = solution.WithOptions(options); + + return solution; + }); + } + + private static ImmutableDictionary GetNullableWarningsFromCompiler() + { + string[] args = { "/warnaserror:nullable" }; + var commandLineArguments = CSharpCommandLineParser.Default.Parse(args, baseDirectory: Environment.CurrentDirectory, sdkDirectory: Environment.CurrentDirectory); + var nullableWarnings = commandLineArguments.CompilationOptions.SpecificDiagnosticOptions; + + // Workaround for https://github.com/dotnet/roslyn/issues/41610 + nullableWarnings = nullableWarnings + .SetItem("CS8632", ReportDiagnostic.Error) + .SetItem("CS8669", ReportDiagnostic.Error); + + return nullableWarnings; + } + + public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.CSharp8; + + public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.CSharp); + + protected override AnalyzerOptions GetAnalyzerOptions(Project project) + { + return new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution); + } + } + } +} diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs new file mode 100644 index 0000000000000..8956322ddc413 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions +{ + public static partial class CSharpCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + public static DiagnosticResult Diagnostic() + => CSharpCodeFixVerifier.Diagnostic(); + + public static DiagnosticResult Diagnostic(string diagnosticId) + => CSharpCodeFixVerifier.Diagnostic(diagnosticId); + + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) + => CSharpCodeFixVerifier.Diagnostic(descriptor); + + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test + { + TestCode = source, + }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(); + } + + public static async Task VerifyCodeFixAsync(string source, string fixedSource) + => await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + + public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) + => await VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + + public static async Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource) + { + var test = new Test + { + TestCode = source, + FixedCode = fixedSource, + }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(); + } + } +} diff --git a/src/EditorFeatures/TestUtilities/CodeActions/OptionsCollection.cs b/src/EditorFeatures/TestUtilities/CodeActions/OptionsCollection.cs new file mode 100644 index 0000000000000..99ac6de7263a2 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/OptionsCollection.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions +{ + public sealed class OptionsCollection : IEnumerable> + { + private readonly Dictionary _options = new Dictionary(); + private readonly string _languageName; + + public OptionsCollection(string languageName) + { + _languageName = languageName; + } + + public void Add(Option option, T value) + => _options.Add(new OptionKey(option), value); + + public void Add(Option> option, T value, NotificationOption notification) + => _options.Add(new OptionKey(option), new CodeStyleOption(value, notification)); + + public void Add(PerLanguageOption option, T value) + => _options.Add(new OptionKey(option, _languageName), value); + + public void Add(PerLanguageOption> option, T value) + => Add(option, value, option.DefaultValue.Notification); + + public void Add(PerLanguageOption> option, T value, NotificationOption notification) + => _options.Add(new OptionKey(option, _languageName), new CodeStyleOption(value, notification)); + + public IEnumerator> GetEnumerator() + => _options.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + } +} diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs new file mode 100644 index 0000000000000..017f1780800a7 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic; +using Microsoft.CodeAnalysis.VisualBasic.Testing; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions +{ + public static partial class VisualBasicCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + public class Test : VisualBasicCodeFixTest + { + public Test() + { + MarkupOptions = Testing.MarkupOptions.UseFirstDescriptor; + + SolutionTransforms.Add((solution, projectId) => + { + var parseOptions = (VisualBasicParseOptions)solution.GetProject(projectId).ParseOptions; + solution = solution.WithProjectParseOptions(projectId, parseOptions.WithLanguageVersion(LanguageVersion)); + + var options = solution.Options; + foreach (var (key, value) in Options) + { + options = options.WithChangedOption(key, value); + } + + solution = solution.WithOptions(options); + + return solution; + }); + } + + public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.VisualBasic16; + + public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.CSharp); + + protected override AnalyzerOptions GetAnalyzerOptions(Project project) + { + return new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution); + } + } + } +} diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs new file mode 100644 index 0000000000000..d1941b9ec9a5c --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions +{ + public static partial class VisualBasicCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + public static DiagnosticResult Diagnostic() + => VisualBasicCodeFixVerifier.Diagnostic(); + + public static DiagnosticResult Diagnostic(string diagnosticId) + => VisualBasicCodeFixVerifier.Diagnostic(diagnosticId); + + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) + => VisualBasicCodeFixVerifier.Diagnostic(descriptor); + + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test + { + TestCode = source, + }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(); + } + + public static async Task VerifyCodeFixAsync(string source, string fixedSource) + => await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + + public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) + => await VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + + public static async Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource) + { + var test = new Test + { + TestCode = source, + FixedCode = fixedSource, + }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(); + } + } +} diff --git a/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj b/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj index 9b15252cf1be4..1e0ea1173fd2a 100644 --- a/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj +++ b/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj @@ -57,6 +57,8 @@ + + From 6495e6fe547a2f25b6c3e2df54ce5a00bc4b48b5 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 14 Feb 2020 17:01:14 -0800 Subject: [PATCH 2/9] Convert AddAccessibilityModifiersTests to the new test library --- .../AddAccessibilityModifiersTests.cs | 311 +++++++++++++++--- 1 file changed, 257 insertions(+), 54 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index 526e07bc16666..f4e6fb65ff1ff 100644 --- a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -2,16 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; using Xunit; +using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< + Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers.CSharpAddAccessibilityModifiersDiagnosticAnalyzer, + Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers.CSharpAddAccessibilityModifiersCodeFixProvider>; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddAccessibilityModifiers { @@ -20,56 +22,58 @@ public partial class AddAccessibilityModifiersTests : AbstractCSharpDiagnosticPr internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) => (new CSharpAddAccessibilityModifiersDiagnosticAnalyzer(), new CSharpAddAccessibilityModifiersCodeFixProvider()); - private IDictionary OmitDefaultModifiers => - OptionsSet(SingleOption(CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault, NotificationOption.Suggestion)); - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestAllConstructs() { - await TestInRegularAndScriptAsync( -@" + await new VerifyCS.Test + { + TestState = + { + Sources = + { + @" namespace Outer { namespace Inner1.Inner2 { - class {|FixAllInDocument:C|} + class [|C|] { - class NestedClass { } + class [|NestedClass|] { } - struct NestedStruct { } + struct [|NestedStruct|] { } - int f1; - int f2, f3; + int [|f1|]; + int [|f2|], f3; public int f4; - event Action e1, e2; + event Action [|e1|], e2; public event Action e3; - event Action e4 { add { } remove { } } + event Action [|e4|] { add { } remove { } } public event Action e5 { add { } remove { } } event Action I.e6 { add { } remote { } } static C() { } - C() { } + [|C|]() { } public C(int i) { } ~C() { } - void M1() { } + void [|M1|]() { } public void M2() { } void I.M3() { } partial void M4() { } - int P1 { get; } + int [|P1|] { get; } public int P2 { get; } int I.P3 { get; } - int this[int i] { get; } + int [|this|][int i] { get; } public int this[string s] { get; } int I.this[bool b] { get; } } - interface I + interface [|I|] { event Action e6; void M3(); @@ -77,20 +81,63 @@ interface I int this[bool b] { get; } } - delegate void D(); + delegate void [|D|](); - enum E + enum [|E|] { EMember } } }", -@" + }, + ExpectedDiagnostics = + { + // Test0.cs(16,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(16, 19, 16, 25).WithArguments("Action"), + // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), + // Test0.cs(19,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(19, 19, 19, 25).WithArguments("Action"), + // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), + // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), + // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), + // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors + DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), + // Test0.cs(21,41): error CS1055: An add or remove accessor expected + DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), + // Test0.cs(31,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(31, 18, 31, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), + // Test0.cs(32,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface + DiagnosticResult.CompilerError("CS0751").WithSpan(32, 26, 32, 28), + // Test0.cs(32,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' + DiagnosticResult.CompilerError("CS0759").WithSpan(32, 26, 32, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), + // Test0.cs(36,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(36, 17, 36, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), + // Test0.cs(38,31): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(38, 31, 38, 34).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), + // Test0.cs(39,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(39, 41, 39, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), + // Test0.cs(40,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(40, 17, 40, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), + // Test0.cs(40,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(40, 34, 40, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), + // Test0.cs(45,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(45, 19, 45, 25).WithArguments("Action"), + }, + }, + FixedState = + { + Sources = + { + @" namespace Outer { namespace Inner1.Inner2 { - internal class {|FixAllInDocument:C|} + internal class C { private class NestedClass { } @@ -143,13 +190,53 @@ internal enum E EMember } } -}"); +}", + }, + ExpectedDiagnostics = + { + // Test0.cs(16,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(16, 27, 16, 33).WithArguments("Action"), + // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), + // Test0.cs(19,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(19, 27, 19, 33).WithArguments("Action"), + // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), + // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), + // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), + // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors + DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), + // Test0.cs(21,41): error CS1055: An add or remove accessor expected + DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), + // Test0.cs(32,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(32, 18, 32, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), + // Test0.cs(33,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface + DiagnosticResult.CompilerError("CS0751").WithSpan(33, 26, 33, 28), + // Test0.cs(33,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' + DiagnosticResult.CompilerError("CS0759").WithSpan(33, 26, 33, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), + // Test0.cs(37,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(37, 17, 37, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), + // Test0.cs(39,39): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(39, 39, 39, 42).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), + // Test0.cs(40,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(40, 41, 40, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), + // Test0.cs(41,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(41, 17, 41, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), + // Test0.cs(41,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(41, 34, 41, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), + // Test0.cs(46,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(46, 19, 46, 25).WithArguments("Action"), + }, + }, + }.RunAsync(); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestRefStructs() { - await TestInRegularAndScriptAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" namespace Test { ref struct [|S1|] { } @@ -163,7 +250,7 @@ internal ref struct S1 { } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestReadOnlyStructs() { - await TestInRegularAndScriptAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" namespace Test { readonly struct [|S1|] { } @@ -177,51 +264,56 @@ internal readonly struct S1 { } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestAllConstructsWithOmit() { - await TestInRegularAndScriptAsync( -@" + await new VerifyCS.Test + { + TestState = + { + Sources = + { + @" namespace Outer { namespace Inner1.Inner2 { - internal class {|FixAllInDocument:C|} + internal class [|C|] { - private class NestedClass { } + private class [|NestedClass|] { } - private struct NestedStruct { } + private struct [|NestedStruct|] { } - private int f1; - private int f2, f3; + private int [|f1|]; + private int [|f2|], f3; public int f4; - private event Action e1, e2; + private event Action [|e1|], e2; public event Action e3; - private event Action e4 { add { } remove { } } + private event Action [|e4|] { add { } remove { } } public event Action e5 { add { } remove { } } event Action I.e6 { add { } remote { } } static C() { } - private C() { } + private [|C|]() { } public C(int i) { } ~C() { } - private void M1() { } + private void [|M1|]() { } public void M2() { } void I.M3() { } partial void M4() { } - private int P1 { get; } + private int [|P1|] { get; } public int P2 { get; } int I.P3 { get; } - private int this[int i] { get; } + private int [|this|][int i] { get; } public int this[string s] { get; } int I.this[bool b] { get; } } - internal interface I + internal interface [|I|] { event Action e6; void M3(); @@ -229,20 +321,63 @@ internal interface I int this[bool b] { get; } } - internal delegate void D(); + internal delegate void [|D|](); - internal enum E + internal enum [|E|] { EMember } } }", -@" + }, + ExpectedDiagnostics = + { + // Test0.cs(16,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(16, 27, 16, 33).WithArguments("Action"), + // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), + // Test0.cs(19,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(19, 27, 19, 33).WithArguments("Action"), + // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), + // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), + // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), + // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors + DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), + // Test0.cs(21,41): error CS1055: An add or remove accessor expected + DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), + // Test0.cs(32,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(32, 18, 32, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), + // Test0.cs(33,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface + DiagnosticResult.CompilerError("CS0751").WithSpan(33, 26, 33, 28), + // Test0.cs(33,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' + DiagnosticResult.CompilerError("CS0759").WithSpan(33, 26, 33, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), + // Test0.cs(37,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(37, 17, 37, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), + // Test0.cs(39,39): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(39, 39, 39, 42).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), + // Test0.cs(40,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(40, 41, 40, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), + // Test0.cs(41,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(41, 17, 41, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), + // Test0.cs(41,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(41, 34, 41, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), + // Test0.cs(46,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(46, 19, 46, 25).WithArguments("Action"), + }, + }, + FixedState = + { + Sources = + { + @" namespace Outer { namespace Inner1.Inner2 { - class {|FixAllInDocument:C|} + class C { class NestedClass { } @@ -295,43 +430,111 @@ enum E EMember } } -}", options: OmitDefaultModifiers); +}", + }, + ExpectedDiagnostics = + { + // Test0.cs(16,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(16, 19, 16, 25).WithArguments("Action"), + // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), + // Test0.cs(19,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(19, 19, 19, 25).WithArguments("Action"), + // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), + // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), + // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), + // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors + DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), + // Test0.cs(21,41): error CS1055: An add or remove accessor expected + DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), + // Test0.cs(32,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(32, 18, 32, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), + // Test0.cs(33,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface + DiagnosticResult.CompilerError("CS0751").WithSpan(33, 26, 33, 28), + // Test0.cs(33,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' + DiagnosticResult.CompilerError("CS0759").WithSpan(33, 26, 33, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), + // Test0.cs(37,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(37, 17, 37, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), + // Test0.cs(39,31): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(39, 31, 39, 34).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), + // Test0.cs(40,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(40, 41, 40, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), + // Test0.cs(41,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' + DiagnosticResult.CompilerError("CS0540").WithSpan(41, 17, 41, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), + // Test0.cs(41,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial + DiagnosticResult.CompilerError("CS0501").WithSpan(41, 34, 41, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), + // Test0.cs(46,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) + DiagnosticResult.CompilerError("CS0246").WithSpan(46, 19, 46, 25).WithArguments("Action"), + }, + }, + Options = + { + { CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + }, + }.RunAsync(); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestRefStructsWithOmit() { - await TestInRegularAndScriptAsync(@" + await new VerifyCS.Test + { + TestCode = @" namespace Test { internal ref struct [|S1|] { } -}", @" +}", + FixedCode = @" namespace Test { ref struct S1 { } -}", options: OmitDefaultModifiers); +}", + Options = + { + { CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + }, + }.RunAsync(); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestReadOnlyStructsWithOmit() { - await TestInRegularAndScriptAsync(@" + await new VerifyCS.Test + { + TestCode = @" namespace Test { internal readonly struct [|S1|] { } -}", @" +}", + FixedCode = @" namespace Test { readonly struct S1 { } -}", options: OmitDefaultModifiers); +}", + Options = + { + { CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + }, + }.RunAsync(); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestClassOutsideNamespace() { - await TestInRegularAndScriptAsync(@" -internal class [|C1|] { }", @" -class C1 { }", options: OmitDefaultModifiers); + await new VerifyCS.Test + { + TestCode = @" +internal class [|C1|] { }", + FixedCode = @" +class C1 { }", + Options = + { + { CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + }, + }.RunAsync(); } } } From ec82406ce3f0344d95516767e042cd4856e8d8e3 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 14 Feb 2020 17:38:09 -0800 Subject: [PATCH 3/9] Fix compile errors in test code --- .../AddAccessibilityModifiersTests.cs | 201 +++--------------- 1 file changed, 28 insertions(+), 173 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index f4e6fb65ff1ff..78856d6c85072 100644 --- a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; -using Microsoft.CodeAnalysis.Testing; using Xunit; using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers.CSharpAddAccessibilityModifiersDiagnosticAnalyzer, @@ -31,12 +30,12 @@ public async Task TestAllConstructs() { Sources = { - @" + @"using System; namespace Outer { namespace Inner1.Inner2 { - class [|C|] + partial class [|C|] : I { class [|NestedClass|] { } @@ -51,7 +50,7 @@ struct [|NestedStruct|] { } event Action [|e4|] { add { } remove { } } public event Action e5 { add { } remove { } } - event Action I.e6 { add { } remote { } } + event Action I.e6 { add { } remove { } } static C() { } [|C|]() { } @@ -62,15 +61,16 @@ public C(int i) { } void [|M1|]() { } public void M2() { } void I.M3() { } + partial void M4(); partial void M4() { } int [|P1|] { get; } public int P2 { get; } int I.P3 { get; } - int [|this|][int i] { get; } - public int this[string s] { get; } - int I.this[bool b] { get; } + int [|this|][int i] => throw null; + public int this[string s] => throw null; + int I.this[bool b] => throw null; } interface [|I|] @@ -90,54 +90,17 @@ enum [|E|] } }", }, - ExpectedDiagnostics = - { - // Test0.cs(16,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(16, 19, 16, 25).WithArguments("Action"), - // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), - // Test0.cs(19,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(19, 19, 19, 25).WithArguments("Action"), - // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), - // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), - // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), - // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors - DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), - // Test0.cs(21,41): error CS1055: An add or remove accessor expected - DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), - // Test0.cs(31,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(31, 18, 31, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), - // Test0.cs(32,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface - DiagnosticResult.CompilerError("CS0751").WithSpan(32, 26, 32, 28), - // Test0.cs(32,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' - DiagnosticResult.CompilerError("CS0759").WithSpan(32, 26, 32, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), - // Test0.cs(36,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(36, 17, 36, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), - // Test0.cs(38,31): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(38, 31, 38, 34).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), - // Test0.cs(39,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(39, 41, 39, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), - // Test0.cs(40,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(40, 17, 40, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), - // Test0.cs(40,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(40, 34, 40, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), - // Test0.cs(45,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(45, 19, 45, 25).WithArguments("Action"), - }, }, FixedState = { Sources = { - @" + @"using System; namespace Outer { namespace Inner1.Inner2 { - internal class C + internal partial class C : I { private class NestedClass { } @@ -152,7 +115,7 @@ private struct NestedStruct { } private event Action e4 { add { } remove { } } public event Action e5 { add { } remove { } } - event Action I.e6 { add { } remote { } } + event Action I.e6 { add { } remove { } } static C() { } @@ -164,15 +127,16 @@ public C(int i) { } private void M1() { } public void M2() { } void I.M3() { } + partial void M4(); partial void M4() { } private int P1 { get; } public int P2 { get; } int I.P3 { get; } - private int this[int i] { get; } - public int this[string s] { get; } - int I.this[bool b] { get; } + private int this[int i] => throw null; + public int this[string s] => throw null; + int I.this[bool b] => throw null; } internal interface I @@ -192,43 +156,6 @@ internal enum E } }", }, - ExpectedDiagnostics = - { - // Test0.cs(16,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(16, 27, 16, 33).WithArguments("Action"), - // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), - // Test0.cs(19,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(19, 27, 19, 33).WithArguments("Action"), - // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), - // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), - // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), - // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors - DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), - // Test0.cs(21,41): error CS1055: An add or remove accessor expected - DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), - // Test0.cs(32,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(32, 18, 32, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), - // Test0.cs(33,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface - DiagnosticResult.CompilerError("CS0751").WithSpan(33, 26, 33, 28), - // Test0.cs(33,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' - DiagnosticResult.CompilerError("CS0759").WithSpan(33, 26, 33, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), - // Test0.cs(37,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(37, 17, 37, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), - // Test0.cs(39,39): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(39, 39, 39, 42).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), - // Test0.cs(40,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(40, 41, 40, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), - // Test0.cs(41,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(41, 17, 41, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), - // Test0.cs(41,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(41, 34, 41, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), - // Test0.cs(46,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(46, 19, 46, 25).WithArguments("Action"), - }, }, }.RunAsync(); } @@ -270,12 +197,12 @@ public async Task TestAllConstructsWithOmit() { Sources = { - @" + @"using System; namespace Outer { namespace Inner1.Inner2 { - internal class [|C|] + internal partial class [|C|] : I { private class [|NestedClass|] { } @@ -290,7 +217,7 @@ private struct [|NestedStruct|] { } private event Action [|e4|] { add { } remove { } } public event Action e5 { add { } remove { } } - event Action I.e6 { add { } remote { } } + event Action I.e6 { add { } remove { } } static C() { } @@ -302,15 +229,16 @@ public C(int i) { } private void [|M1|]() { } public void M2() { } void I.M3() { } + partial void M4(); partial void M4() { } private int [|P1|] { get; } public int P2 { get; } int I.P3 { get; } - private int [|this|][int i] { get; } - public int this[string s] { get; } - int I.this[bool b] { get; } + private int [|this|][int i] => throw null; + public int this[string s] => throw null; + int I.this[bool b] => throw null; } internal interface [|I|] @@ -330,54 +258,17 @@ internal enum [|E|] } }", }, - ExpectedDiagnostics = - { - // Test0.cs(16,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(16, 27, 16, 33).WithArguments("Action"), - // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), - // Test0.cs(19,27): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(19, 27, 19, 33).WithArguments("Action"), - // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), - // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), - // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), - // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors - DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), - // Test0.cs(21,41): error CS1055: An add or remove accessor expected - DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), - // Test0.cs(32,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(32, 18, 32, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), - // Test0.cs(33,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface - DiagnosticResult.CompilerError("CS0751").WithSpan(33, 26, 33, 28), - // Test0.cs(33,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' - DiagnosticResult.CompilerError("CS0759").WithSpan(33, 26, 33, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), - // Test0.cs(37,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(37, 17, 37, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), - // Test0.cs(39,39): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(39, 39, 39, 42).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), - // Test0.cs(40,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(40, 41, 40, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), - // Test0.cs(41,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(41, 17, 41, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), - // Test0.cs(41,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(41, 34, 41, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), - // Test0.cs(46,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(46, 19, 46, 25).WithArguments("Action"), - }, }, FixedState = { Sources = { - @" + @"using System; namespace Outer { namespace Inner1.Inner2 { - class C + partial class C : I { class NestedClass { } @@ -392,7 +283,7 @@ struct NestedStruct { } event Action e4 { add { } remove { } } public event Action e5 { add { } remove { } } - event Action I.e6 { add { } remote { } } + event Action I.e6 { add { } remove { } } static C() { } @@ -404,15 +295,16 @@ public C(int i) { } void M1() { } public void M2() { } void I.M3() { } + partial void M4(); partial void M4() { } int P1 { get; } public int P2 { get; } int I.P3 { get; } - int this[int i] { get; } - public int this[string s] { get; } - int I.this[bool b] { get; } + int this[int i] => throw null; + public int this[string s] => throw null; + int I.this[bool b] => throw null; } interface I @@ -432,43 +324,6 @@ enum E } }", }, - ExpectedDiagnostics = - { - // Test0.cs(16,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(16, 19, 16, 25).WithArguments("Action"), - // Test0.cs(17,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(17, 26, 17, 32).WithArguments("Action"), - // Test0.cs(19,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(19, 19, 19, 25).WithArguments("Action"), - // Test0.cs(20,26): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(20, 26, 20, 32).WithArguments("Action"), - // Test0.cs(21,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(21, 19, 21, 25).WithArguments("Action"), - // Test0.cs(21,26): error CS0540: 'C.I.e6': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(21, 26, 21, 27).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6", "Outer.Inner1.Inner2.I"), - // Test0.cs(21,28): error CS0065: 'C.I.e6': event property must have both add and remove accessors - DiagnosticResult.CompilerError("CS0065").WithSpan(21, 28, 21, 30).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.e6"), - // Test0.cs(21,41): error CS1055: An add or remove accessor expected - DiagnosticResult.CompilerError("CS1055").WithSpan(21, 41, 21, 47), - // Test0.cs(32,18): error CS0540: 'C.I.M3()': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(32, 18, 32, 19).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.M3()", "Outer.Inner1.Inner2.I"), - // Test0.cs(33,26): error CS0751: A partial method must be declared within a partial class, partial struct, or partial interface - DiagnosticResult.CompilerError("CS0751").WithSpan(33, 26, 33, 28), - // Test0.cs(33,26): error CS0759: No defining declaration found for implementing declaration of partial method 'C.M4()' - DiagnosticResult.CompilerError("CS0759").WithSpan(33, 26, 33, 28).WithArguments("Outer.Inner1.Inner2.C.M4()"), - // Test0.cs(37,17): error CS0540: 'C.I.P3': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(37, 17, 37, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.P3", "Outer.Inner1.Inner2.I"), - // Test0.cs(39,31): error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(39, 31, 39, 34).WithArguments("Outer.Inner1.Inner2.C.this[int].get"), - // Test0.cs(40,41): error CS0501: 'C.this[string].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(40, 41, 40, 44).WithArguments("Outer.Inner1.Inner2.C.this[string].get"), - // Test0.cs(41,17): error CS0540: 'C.I.this[bool]': containing type does not implement interface 'I' - DiagnosticResult.CompilerError("CS0540").WithSpan(41, 17, 41, 18).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool]", "Outer.Inner1.Inner2.I"), - // Test0.cs(41,34): error CS0501: 'C.I.this[bool].get' must declare a body because it is not marked abstract, extern, or partial - DiagnosticResult.CompilerError("CS0501").WithSpan(41, 34, 41, 37).WithArguments("Outer.Inner1.Inner2.C.Outer.Inner1.Inner2.I.this[bool].get"), - // Test0.cs(46,19): error CS0246: The type or namespace name 'Action' could not be found (are you missing a using directive or an assembly reference?) - DiagnosticResult.CompilerError("CS0246").WithSpan(46, 19, 46, 25).WithArguments("Action"), - }, }, Options = { From f4aa583c39225d42740895dbe1de83bbe79517b2 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 15 Feb 2020 13:02:27 -0800 Subject: [PATCH 4/9] Use simple verification API --- .../AddAccessibilityModifiersTests.cs | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index 78856d6c85072..04dc2d75f432d 100644 --- a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -24,13 +24,8 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestAllConstructs() { - await new VerifyCS.Test - { - TestState = - { - Sources = - { - @"using System; + await VerifyCS.VerifyCodeFixAsync( + @"using System; namespace Outer { namespace Inner1.Inner2 @@ -89,13 +84,7 @@ enum [|E|] } } }", - }, - }, - FixedState = - { - Sources = - { - @"using System; + @"using System; namespace Outer { namespace Inner1.Inner2 @@ -154,10 +143,7 @@ internal enum E EMember } } -}", - }, - }, - }.RunAsync(); +}"); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] From da9a24d196de795ca430d678c326aa535abd61c1 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 15 Feb 2020 13:03:19 -0800 Subject: [PATCH 5/9] Verify standard analyzer properties --- .../AddAccessibilityModifiersTests.cs | 4 + .../CodeActions/CSharpCodeFixVerifier`2.cs | 3 + .../CodeActions/CodeFixVerifierHelper.cs | 77 +++++++++++++++++++ .../VisualBasicCodeFixVerifier`2.cs | 3 + 4 files changed, 87 insertions(+) create mode 100644 src/EditorFeatures/TestUtilities/CodeActions/CodeFixVerifierHelper.cs diff --git a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index 04dc2d75f432d..163bfdda9676f 100644 --- a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -21,6 +21,10 @@ public partial class AddAccessibilityModifiersTests : AbstractCSharpDiagnosticPr internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) => (new CSharpAddAccessibilityModifiersDiagnosticAnalyzer(), new CSharpAddAccessibilityModifiersCodeFixProvider()); + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] + public void TestStandardProperties() + => VerifyCS.VerifyStandardProperties(); + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestAllConstructs() { diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs index 8956322ddc413..bde9807f6c391 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs @@ -24,6 +24,9 @@ public static DiagnosticResult Diagnostic(string diagnosticId) public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => CSharpCodeFixVerifier.Diagnostic(descriptor); + public static void VerifyStandardProperties(bool verifyHelpLink = false) + => CodeFixVerifierHelper.VerifyStandardProperties(new TAnalyzer(), verifyHelpLink); + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) { var test = new Test diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CodeFixVerifierHelper.cs b/src/EditorFeatures/TestUtilities/CodeActions/CodeFixVerifierHelper.cs new file mode 100644 index 0000000000000..922759fd1a997 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/CodeFixVerifierHelper.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using Microsoft.CodeAnalysis.Diagnostics; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions +{ + internal static class CodeFixVerifierHelper + { + public static void VerifyStandardProperties(DiagnosticAnalyzer analyzer, bool verifyHelpLink = false) + { + VerifyMessageTitle(analyzer); + VerifyMessageDescription(analyzer); + + if (verifyHelpLink) + { + VerifyMessageHelpLinkUri(analyzer); + } + } + + private static void VerifyMessageTitle(DiagnosticAnalyzer analyzer) + { + foreach (var descriptor in analyzer.SupportedDiagnostics) + { + if (descriptor.CustomTags.Contains(WellKnownDiagnosticTags.NotConfigurable)) + { + // The title only displayed for rule configuration + continue; + } + + Assert.NotEqual("", descriptor.Title?.ToString() ?? ""); + } + } + + private static void VerifyMessageDescription(DiagnosticAnalyzer analyzer) + { + foreach (var descriptor in analyzer.SupportedDiagnostics) + { + if (ShouldSkipMessageDescriptionVerification(descriptor)) + { + continue; + } + + Assert.NotEqual("", descriptor.MessageFormat?.ToString() ?? ""); + } + + return; + + // Local function + static bool ShouldSkipMessageDescriptionVerification(DiagnosticDescriptor descriptor) + { + if (descriptor.CustomTags.Contains(WellKnownDiagnosticTags.NotConfigurable)) + { + if (!descriptor.IsEnabledByDefault || descriptor.DefaultSeverity == DiagnosticSeverity.Hidden) + { + // The message only displayed if either enabled and not hidden, or configurable + return true; + } + } + + return false; + } + } + + private static void VerifyMessageHelpLinkUri(DiagnosticAnalyzer analyzer) + { + foreach (var descriptor in analyzer.SupportedDiagnostics) + { + Assert.NotEqual("", descriptor.HelpLinkUri ?? ""); + } + } + } +} diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs index d1941b9ec9a5c..e1d0b58803095 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs @@ -24,6 +24,9 @@ public static DiagnosticResult Diagnostic(string diagnosticId) public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => VisualBasicCodeFixVerifier.Diagnostic(descriptor); + public static void VerifyStandardProperties(bool verifyHelpLink = false) + => CodeFixVerifierHelper.VerifyStandardProperties(new TAnalyzer(), verifyHelpLink); + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) { var test = new Test From a94edd9023c21dcbbb4a9d5bbfcda435c3b422fe Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 15 Feb 2020 13:03:53 -0800 Subject: [PATCH 6/9] Remove unnecessary use of AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest --- .../AddAccessibilityModifiersTests.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index 163bfdda9676f..20376ba845d19 100644 --- a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -3,11 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeStyle; -using Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier< @@ -16,11 +12,8 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddAccessibilityModifiers { - public partial class AddAccessibilityModifiersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + public class AddAccessibilityModifiersTests { - internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) - => (new CSharpAddAccessibilityModifiersDiagnosticAnalyzer(), new CSharpAddAccessibilityModifiersCodeFixProvider()); - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public void TestStandardProperties() => VerifyCS.VerifyStandardProperties(); From d199c5ec0e38ca96d26bb93823f95bf48db13aa1 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 15 Feb 2020 13:17:42 -0800 Subject: [PATCH 7/9] Fix incorrect language name for OptionsCollection --- .../CodeActions/VisualBasicCodeFixVerifier`2+Test.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs index 017f1780800a7..71c9005b2fb91 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs @@ -40,7 +40,7 @@ public Test() public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.VisualBasic16; - public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.CSharp); + public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.VisualBasic); protected override AnalyzerOptions GetAnalyzerOptions(Project project) { From ee754f97371c1369e3e5f4c1b8760011a62ea981 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 15 Feb 2020 13:18:08 -0800 Subject: [PATCH 8/9] Update field name to match the expected code style --- .../TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs index 986765afc1974..1d9ca675728dc 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs @@ -19,7 +19,7 @@ public static partial class CSharpCodeFixVerifier { public class Test : CSharpCodeFixTest { - private static readonly ImmutableDictionary NullableWarnings = GetNullableWarningsFromCompiler(); + private static readonly ImmutableDictionary s_nullableWarnings = GetNullableWarningsFromCompiler(); public Test() { @@ -31,7 +31,7 @@ public Test() solution = solution.WithProjectParseOptions(projectId, parseOptions.WithLanguageVersion(LanguageVersion)); var compilationOptions = solution.GetProject(projectId).CompilationOptions; - compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(compilationOptions.SpecificDiagnosticOptions.SetItems(NullableWarnings)); + compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(compilationOptions.SpecificDiagnosticOptions.SetItems(s_nullableWarnings)); solution = solution.WithProjectCompilationOptions(projectId, compilationOptions); var options = solution.Options; From 69cb96361bc9fb1a6ad283fe98e4279a1bf3844b Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 15 Feb 2020 13:18:24 -0800 Subject: [PATCH 9/9] Added documentation for test helpers --- .../CodeActions/CSharpCodeFixVerifier`2+Test.cs | 15 +++++++++++++++ .../CodeActions/CSharpCodeFixVerifier`2.cs | 15 +++++++++++++++ .../VisualBasicCodeFixVerifier`2+Test.cs | 8 ++++++++ .../CodeActions/VisualBasicCodeFixVerifier`2.cs | 15 +++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs index 1d9ca675728dc..b2e46bba43ec0 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs @@ -19,6 +19,13 @@ public static partial class CSharpCodeFixVerifier { public class Test : CSharpCodeFixTest { + /// + /// By default, the compiler reports diagnostics for nullable reference types at + /// , and the analyzer test framework defaults to only validating + /// diagnostics at . This map contains all compiler diagnostic IDs + /// related to nullability mapped to , which is then used to enable all + /// of these warnings for default validation during analyzer and code fix tests. + /// private static readonly ImmutableDictionary s_nullableWarnings = GetNullableWarningsFromCompiler(); public Test() @@ -60,8 +67,16 @@ private static ImmutableDictionary GetNullableWarnings return nullableWarnings; } + /// + /// Gets or sets the language version to use for the test. The default value is + /// . + /// public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.CSharp8; + /// + /// Gets a collection of options to apply to for testing. Values may be added + /// using a collection initializer. + /// public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.CSharp); protected override AnalyzerOptions GetAnalyzerOptions(Project project) diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs index bde9807f6c391..630e6df217b49 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs @@ -15,18 +15,30 @@ public static partial class CSharpCodeFixVerifier where TAnalyzer : DiagnosticAnalyzer, new() where TCodeFix : CodeFixProvider, new() { + /// public static DiagnosticResult Diagnostic() => CSharpCodeFixVerifier.Diagnostic(); + /// public static DiagnosticResult Diagnostic(string diagnosticId) => CSharpCodeFixVerifier.Diagnostic(diagnosticId); + /// public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => CSharpCodeFixVerifier.Diagnostic(descriptor); + /// + /// Verify standard properties of . + /// + /// + /// This validation method is largely specific to dotnet/roslyn scenarios. + /// + /// to verify + /// property of supported diagnostics; otherwise, to skip this validation. public static void VerifyStandardProperties(bool verifyHelpLink = false) => CodeFixVerifierHelper.VerifyStandardProperties(new TAnalyzer(), verifyHelpLink); + /// public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) { var test = new Test @@ -38,12 +50,15 @@ public static async Task VerifyAnalyzerAsync(string source, params DiagnosticRes await test.RunAsync(); } + /// public static async Task VerifyCodeFixAsync(string source, string fixedSource) => await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + /// public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) => await VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + /// public static async Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource) { var test = new Test diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs index 71c9005b2fb91..030264a2764d7 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs @@ -38,8 +38,16 @@ public Test() }); } + /// + /// Gets or sets the language version to use for the test. The default value is + /// . + /// public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.VisualBasic16; + /// + /// Gets a collection of options to apply to for testing. Values may be added + /// using a collection initializer. + /// public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.VisualBasic); protected override AnalyzerOptions GetAnalyzerOptions(Project project) diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs index e1d0b58803095..47a3848eacf67 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs @@ -15,18 +15,30 @@ public static partial class VisualBasicCodeFixVerifier where TAnalyzer : DiagnosticAnalyzer, new() where TCodeFix : CodeFixProvider, new() { + /// public static DiagnosticResult Diagnostic() => VisualBasicCodeFixVerifier.Diagnostic(); + /// public static DiagnosticResult Diagnostic(string diagnosticId) => VisualBasicCodeFixVerifier.Diagnostic(diagnosticId); + /// public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => VisualBasicCodeFixVerifier.Diagnostic(descriptor); + /// + /// Verify standard properties of . + /// + /// + /// This validation method is largely specific to dotnet/roslyn scenarios. + /// + /// to verify + /// property of supported diagnostics; otherwise, to skip this validation. public static void VerifyStandardProperties(bool verifyHelpLink = false) => CodeFixVerifierHelper.VerifyStandardProperties(new TAnalyzer(), verifyHelpLink); + /// public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) { var test = new Test @@ -38,12 +50,15 @@ public static async Task VerifyAnalyzerAsync(string source, params DiagnosticRes await test.RunAsync(); } + /// public static async Task VerifyCodeFixAsync(string source, string fixedSource) => await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + /// public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) => await VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + /// public static async Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource) { var test = new Test