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/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index 526e07bc16666..20376ba845d19 100644 --- a/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/EditorFeatures/CSharpTest/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -2,74 +2,70 @@ // 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 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 { - public partial class AddAccessibilityModifiersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + public class AddAccessibilityModifiersTests { - 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 void TestStandardProperties() + => VerifyCS.VerifyStandardProperties(); [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestAllConstructs() { - await TestInRegularAndScriptAsync( -@" + await VerifyCS.VerifyCodeFixAsync( + @"using System; namespace Outer { namespace Inner1.Inner2 { - class {|FixAllInDocument:C|} + partial class [|C|] : I { - 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 { } } + event Action I.e6 { add { } remove { } } static C() { } - C() { } + [|C|]() { } public C(int i) { } ~C() { } - void M1() { } + void [|M1|]() { } public void M2() { } void I.M3() { } + partial void M4(); partial void M4() { } - int P1 { get; } + 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 + interface [|I|] { event Action e6; void M3(); @@ -77,20 +73,20 @@ interface I int this[bool b] { get; } } - delegate void D(); + delegate void [|D|](); - enum E + enum [|E|] { EMember } } }", -@" + @"using System; namespace Outer { namespace Inner1.Inner2 { - internal class {|FixAllInDocument:C|} + internal partial class C : I { private class NestedClass { } @@ -105,7 +101,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() { } @@ -117,15 +113,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 @@ -149,7 +146,7 @@ internal enum E [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestRefStructs() { - await TestInRegularAndScriptAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" namespace Test { ref struct [|S1|] { } @@ -163,7 +160,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 +174,57 @@ internal readonly struct S1 { } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] public async Task TestAllConstructsWithOmit() { - await TestInRegularAndScriptAsync( -@" + await new VerifyCS.Test + { + TestState = + { + Sources = + { + @"using System; namespace Outer { namespace Inner1.Inner2 { - internal class {|FixAllInDocument:C|} + internal partial class [|C|] : I { - 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 { } } + event Action I.e6 { add { } remove { } } 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(); 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; } - 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 + internal interface [|I|] { event Action e6; void M3(); @@ -229,20 +232,26 @@ internal interface I int this[bool b] { get; } } - internal delegate void D(); + internal delegate void [|D|](); - internal enum E + internal enum [|E|] { EMember } } }", -@" + }, + }, + FixedState = + { + Sources = + { + @"using System; namespace Outer { namespace Inner1.Inner2 { - class {|FixAllInDocument:C|} + partial class C : I { class NestedClass { } @@ -257,7 +266,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() { } @@ -269,15 +278,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 @@ -295,43 +305,74 @@ enum E EMember } } -}", options: OmitDefaultModifiers); +}", + }, + }, + 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(); } } } 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..b2e46bba43ec0 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs @@ -0,0 +1,88 @@ +// 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 + { + /// + /// 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() + { + 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(s_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; + } + + /// + /// 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) + { + 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..630e6df217b49 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs @@ -0,0 +1,74 @@ +// 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); + + /// + /// 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 + { + 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/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/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..030264a2764d7 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs @@ -0,0 +1,59 @@ +// 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; + }); + } + + /// + /// 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) + { + 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..47a3848eacf67 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs @@ -0,0 +1,74 @@ +// 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); + + /// + /// 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 + { + 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 @@ + +