未验证 提交 fea95d79 编写于 作者: S Sam Harwell 提交者: GitHub

Merge pull request #41717 from sharwell/testing-library

Begin transition to Microsoft.CodeAnalysis.Testing
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<!-- Versions used by several individual references below --> <!-- Versions used by several individual references below -->
<RoslynDiagnosticsNugetPackageVersion>3.0.0-beta2.20059.3+77df2220</RoslynDiagnosticsNugetPackageVersion> <RoslynDiagnosticsNugetPackageVersion>3.0.0-beta2.20059.3+77df2220</RoslynDiagnosticsNugetPackageVersion>
<CodeStyleLayerCodeAnalysisVersion>3.3.1</CodeStyleLayerCodeAnalysisVersion> <CodeStyleLayerCodeAnalysisVersion>3.3.1</CodeStyleLayerCodeAnalysisVersion>
<MicrosoftCodeAnalysisTestingVersion>1.0.1-beta1.20067.1</MicrosoftCodeAnalysisTestingVersion> <MicrosoftCodeAnalysisTestingVersion>1.0.1-beta1.20114.4</MicrosoftCodeAnalysisTestingVersion>
<CodeStyleAnalyzerVersion>3.5.0-beta3-20078-04</CodeStyleAnalyzerVersion> <CodeStyleAnalyzerVersion>3.5.0-beta3-20078-04</CodeStyleAnalyzerVersion>
<VisualStudioEditorPackagesVersion>16.4.248</VisualStudioEditorPackagesVersion> <VisualStudioEditorPackagesVersion>16.4.248</VisualStudioEditorPackagesVersion>
<ILToolsPackageVersion>5.0.0-alpha1.19409.1</ILToolsPackageVersion> <ILToolsPackageVersion>5.0.0-alpha1.19409.1</ILToolsPackageVersion>
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
<MicrosoftVisualStudioCodeAnalysisSdkUIVersion>15.8.27812-alpha</MicrosoftVisualStudioCodeAnalysisSdkUIVersion> <MicrosoftVisualStudioCodeAnalysisSdkUIVersion>15.8.27812-alpha</MicrosoftVisualStudioCodeAnalysisSdkUIVersion>
<MicrosoftVisualStudioCodingConventionsVersion>1.1.20180503.2</MicrosoftVisualStudioCodingConventionsVersion> <MicrosoftVisualStudioCodingConventionsVersion>1.1.20180503.2</MicrosoftVisualStudioCodingConventionsVersion>
<MicrosoftVisualStudioComponentModelHostVersion>16.0.198-g52de9c2988</MicrosoftVisualStudioComponentModelHostVersion> <MicrosoftVisualStudioComponentModelHostVersion>16.0.198-g52de9c2988</MicrosoftVisualStudioComponentModelHostVersion>
<MicrosoftVisualStudioCompositionVersion>15.5.23</MicrosoftVisualStudioCompositionVersion> <MicrosoftVisualStudioCompositionVersion>15.6.36</MicrosoftVisualStudioCompositionVersion>
<MicrosoftVisualStudioCoreUtilityVersion>$(VisualStudioEditorPackagesVersion)</MicrosoftVisualStudioCoreUtilityVersion> <MicrosoftVisualStudioCoreUtilityVersion>$(VisualStudioEditorPackagesVersion)</MicrosoftVisualStudioCoreUtilityVersion>
<MicrosoftVisualStudioDebuggerUIInterfacesVersion>16.0.29431.108</MicrosoftVisualStudioDebuggerUIInterfacesVersion> <MicrosoftVisualStudioDebuggerUIInterfacesVersion>16.0.29431.108</MicrosoftVisualStudioDebuggerUIInterfacesVersion>
<MicrosoftVisualStudioDebuggerEngineimplementationVersion>16.4.1091102-preview</MicrosoftVisualStudioDebuggerEngineimplementationVersion> <MicrosoftVisualStudioDebuggerEngineimplementationVersion>16.4.1091102-preview</MicrosoftVisualStudioDebuggerEngineimplementationVersion>
......
...@@ -2,74 +2,70 @@ ...@@ -2,74 +2,70 @@
// The .NET Foundation licenses this file to you under the MIT license. // The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle; 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.Test.Utilities;
using Xunit; 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 namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddAccessibilityModifiers
{ {
public partial class AddAccessibilityModifiersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest public class AddAccessibilityModifiersTests
{ {
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
=> (new CSharpAddAccessibilityModifiersDiagnosticAnalyzer(), new CSharpAddAccessibilityModifiersCodeFixProvider()); public void TestStandardProperties()
=> VerifyCS.VerifyStandardProperties();
private IDictionary<OptionKey, object> OmitDefaultModifiers =>
OptionsSet(SingleOption(CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault, NotificationOption.Suggestion));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestAllConstructs() public async Task TestAllConstructs()
{ {
await TestInRegularAndScriptAsync( await VerifyCS.VerifyCodeFixAsync(
@" @"using System;
namespace Outer namespace Outer
{ {
namespace Inner1.Inner2 namespace Inner1.Inner2
{ {
class {|FixAllInDocument:C|} partial class [|C|] : I
{ {
class NestedClass { } class [|NestedClass|] { }
struct NestedStruct { } struct [|NestedStruct|] { }
int f1; int [|f1|];
int f2, f3; int [|f2|], f3;
public int f4; public int f4;
event Action e1, e2; event Action [|e1|], e2;
public event Action e3; public event Action e3;
event Action e4 { add { } remove { } } event Action [|e4|] { add { } remove { } }
public event Action e5 { add { } remove { } } public event Action e5 { add { } remove { } }
event Action I.e6 { add { } remote { } } event Action I.e6 { add { } remove { } }
static C() { } static C() { }
C() { } [|C|]() { }
public C(int i) { } public C(int i) { }
~C() { } ~C() { }
void M1() { } void [|M1|]() { }
public void M2() { } public void M2() { }
void I.M3() { } void I.M3() { }
partial void M4();
partial void M4() { } partial void M4() { }
int P1 { get; } int [|P1|] { get; }
public int P2 { get; } public int P2 { get; }
int I.P3 { get; } int I.P3 { get; }
int this[int i] { get; } int [|this|][int i] => throw null;
public int this[string s] { get; } public int this[string s] => throw null;
int I.this[bool b] { get; } int I.this[bool b] => throw null;
} }
interface I interface [|I|]
{ {
event Action e6; event Action e6;
void M3(); void M3();
...@@ -77,20 +73,20 @@ interface I ...@@ -77,20 +73,20 @@ interface I
int this[bool b] { get; } int this[bool b] { get; }
} }
delegate void D(); delegate void [|D|]();
enum E enum [|E|]
{ {
EMember EMember
} }
} }
}", }",
@" @"using System;
namespace Outer namespace Outer
{ {
namespace Inner1.Inner2 namespace Inner1.Inner2
{ {
internal class {|FixAllInDocument:C|} internal partial class C : I
{ {
private class NestedClass { } private class NestedClass { }
...@@ -105,7 +101,7 @@ private struct NestedStruct { } ...@@ -105,7 +101,7 @@ private struct NestedStruct { }
private event Action e4 { add { } remove { } } private event Action e4 { add { } remove { } }
public event Action e5 { add { } remove { } } public event Action e5 { add { } remove { } }
event Action I.e6 { add { } remote { } } event Action I.e6 { add { } remove { } }
static C() { } static C() { }
...@@ -117,15 +113,16 @@ private struct NestedStruct { } ...@@ -117,15 +113,16 @@ private struct NestedStruct { }
private void M1() { } private void M1() { }
public void M2() { } public void M2() { }
void I.M3() { } void I.M3() { }
partial void M4();
partial void M4() { } partial void M4() { }
private int P1 { get; } private int P1 { get; }
public int P2 { get; } public int P2 { get; }
int I.P3 { get; } int I.P3 { get; }
private int this[int i] { get; } private int this[int i] => throw null;
public int this[string s] { get; } public int this[string s] => throw null;
int I.this[bool b] { get; } int I.this[bool b] => throw null;
} }
internal interface I internal interface I
...@@ -149,7 +146,7 @@ internal enum E ...@@ -149,7 +146,7 @@ internal enum E
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestRefStructs() public async Task TestRefStructs()
{ {
await TestInRegularAndScriptAsync(@" await VerifyCS.VerifyCodeFixAsync(@"
namespace Test namespace Test
{ {
ref struct [|S1|] { } ref struct [|S1|] { }
...@@ -163,7 +160,7 @@ namespace Test ...@@ -163,7 +160,7 @@ namespace Test
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestReadOnlyStructs() public async Task TestReadOnlyStructs()
{ {
await TestInRegularAndScriptAsync(@" await VerifyCS.VerifyCodeFixAsync(@"
namespace Test namespace Test
{ {
readonly struct [|S1|] { } readonly struct [|S1|] { }
...@@ -177,51 +174,57 @@ namespace Test ...@@ -177,51 +174,57 @@ namespace Test
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestAllConstructsWithOmit() public async Task TestAllConstructsWithOmit()
{ {
await TestInRegularAndScriptAsync( await new VerifyCS.Test
@" {
TestState =
{
Sources =
{
@"using System;
namespace Outer namespace Outer
{ {
namespace Inner1.Inner2 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 [|f1|];
private int f2, f3; private int [|f2|], f3;
public int f4; public int f4;
private event Action e1, e2; private event Action [|e1|], e2;
public event Action e3; public event Action e3;
private event Action e4 { add { } remove { } } private event Action [|e4|] { add { } remove { } }
public event Action e5 { add { } remove { } } public event Action e5 { add { } remove { } }
event Action I.e6 { add { } remote { } } event Action I.e6 { add { } remove { } }
static C() { } static C() { }
private C() { } private [|C|]() { }
public C(int i) { } public C(int i) { }
~C() { } ~C() { }
private void M1() { } private void [|M1|]() { }
public void M2() { } public void M2() { }
void I.M3() { } void I.M3() { }
partial void M4();
partial void M4() { } partial void M4() { }
private int P1 { get; } private int [|P1|] { get; }
public int P2 { get; } public int P2 { get; }
int I.P3 { get; } int I.P3 { get; }
private int this[int i] { get; } private int [|this|][int i] => throw null;
public int this[string s] { get; } public int this[string s] => throw null;
int I.this[bool b] { get; } int I.this[bool b] => throw null;
} }
internal interface I internal interface [|I|]
{ {
event Action e6; event Action e6;
void M3(); void M3();
...@@ -229,20 +232,26 @@ internal interface I ...@@ -229,20 +232,26 @@ internal interface I
int this[bool b] { get; } int this[bool b] { get; }
} }
internal delegate void D(); internal delegate void [|D|]();
internal enum E internal enum [|E|]
{ {
EMember EMember
} }
} }
}", }",
@" },
},
FixedState =
{
Sources =
{
@"using System;
namespace Outer namespace Outer
{ {
namespace Inner1.Inner2 namespace Inner1.Inner2
{ {
class {|FixAllInDocument:C|} partial class C : I
{ {
class NestedClass { } class NestedClass { }
...@@ -257,7 +266,7 @@ struct NestedStruct { } ...@@ -257,7 +266,7 @@ struct NestedStruct { }
event Action e4 { add { } remove { } } event Action e4 { add { } remove { } }
public event Action e5 { add { } remove { } } public event Action e5 { add { } remove { } }
event Action I.e6 { add { } remote { } } event Action I.e6 { add { } remove { } }
static C() { } static C() { }
...@@ -269,15 +278,16 @@ struct NestedStruct { } ...@@ -269,15 +278,16 @@ struct NestedStruct { }
void M1() { } void M1() { }
public void M2() { } public void M2() { }
void I.M3() { } void I.M3() { }
partial void M4();
partial void M4() { } partial void M4() { }
int P1 { get; } int P1 { get; }
public int P2 { get; } public int P2 { get; }
int I.P3 { get; } int I.P3 { get; }
int this[int i] { get; } int this[int i] => throw null;
public int this[string s] { get; } public int this[string s] => throw null;
int I.this[bool b] { get; } int I.this[bool b] => throw null;
} }
interface I interface I
...@@ -295,43 +305,74 @@ enum E ...@@ -295,43 +305,74 @@ enum E
EMember EMember
} }
} }
}", options: OmitDefaultModifiers); }",
},
},
Options =
{
{ CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault },
},
}.RunAsync();
} }
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestRefStructsWithOmit() public async Task TestRefStructsWithOmit()
{ {
await TestInRegularAndScriptAsync(@" await new VerifyCS.Test
{
TestCode = @"
namespace Test namespace Test
{ {
internal ref struct [|S1|] { } internal ref struct [|S1|] { }
}", @" }",
FixedCode = @"
namespace Test namespace Test
{ {
ref struct S1 { } ref struct S1 { }
}", options: OmitDefaultModifiers); }",
Options =
{
{ CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault },
},
}.RunAsync();
} }
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestReadOnlyStructsWithOmit() public async Task TestReadOnlyStructsWithOmit()
{ {
await TestInRegularAndScriptAsync(@" await new VerifyCS.Test
{
TestCode = @"
namespace Test namespace Test
{ {
internal readonly struct [|S1|] { } internal readonly struct [|S1|] { }
}", @" }",
FixedCode = @"
namespace Test namespace Test
{ {
readonly struct S1 { } readonly struct S1 { }
}", options: OmitDefaultModifiers); }",
Options =
{
{ CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault },
},
}.RunAsync();
} }
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddAccessibilityModifiers)]
public async Task TestClassOutsideNamespace() public async Task TestClassOutsideNamespace()
{ {
await TestInRegularAndScriptAsync(@" await new VerifyCS.Test
internal class [|C1|] { }", @" {
class C1 { }", options: OmitDefaultModifiers); TestCode = @"
internal class [|C1|] { }",
FixedCode = @"
class C1 { }",
Options =
{
{ CodeStyleOptions.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault },
},
}.RunAsync();
} }
} }
} }
// 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<TAnalyzer, TCodeFix>
where TAnalyzer : DiagnosticAnalyzer, new()
where TCodeFix : CodeFixProvider, new()
{
public class Test : CSharpCodeFixTest<TAnalyzer, TCodeFix, XUnitVerifier>
{
/// <summary>
/// By default, the compiler reports diagnostics for nullable reference types at
/// <see cref="DiagnosticSeverity.Warning"/>, and the analyzer test framework defaults to only validating
/// diagnostics at <see cref="DiagnosticSeverity.Error"/>. This map contains all compiler diagnostic IDs
/// related to nullability mapped to <see cref="ReportDiagnostic.Error"/>, which is then used to enable all
/// of these warnings for default validation during analyzer and code fix tests.
/// </summary>
private static readonly ImmutableDictionary<string, ReportDiagnostic> 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<string, ReportDiagnostic> 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;
}
/// <summary>
/// Gets or sets the language version to use for the test. The default value is
/// <see cref="LanguageVersion.CSharp8"/>.
/// </summary>
public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.CSharp8;
/// <summary>
/// Gets a collection of options to apply to <see cref="Solution.Options"/> for testing. Values may be added
/// using a collection initializer.
/// </summary>
public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.CSharp);
protected override AnalyzerOptions GetAnalyzerOptions(Project project)
{
return new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution);
}
}
}
}
// 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<TAnalyzer, TCodeFix>
where TAnalyzer : DiagnosticAnalyzer, new()
where TCodeFix : CodeFixProvider, new()
{
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic()"/>
public static DiagnosticResult Diagnostic()
=> CSharpCodeFixVerifier<TAnalyzer, TCodeFix, XUnitVerifier>.Diagnostic();
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic(string)"/>
public static DiagnosticResult Diagnostic(string diagnosticId)
=> CSharpCodeFixVerifier<TAnalyzer, TCodeFix, XUnitVerifier>.Diagnostic(diagnosticId);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic(DiagnosticDescriptor)"/>
public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
=> CSharpCodeFixVerifier<TAnalyzer, TCodeFix, XUnitVerifier>.Diagnostic(descriptor);
/// <summary>
/// Verify standard properties of <typeparamref name="TAnalyzer"/>.
/// </summary>
/// <remarks>
/// This validation method is largely specific to dotnet/roslyn scenarios.
/// </remarks>
/// <param name="verifyHelpLink"><see langword="true"/> to verify <see cref="DiagnosticDescriptor.HelpLinkUri"/>
/// property of supported diagnostics; otherwise, <see langword="false"/> to skip this validation.</param>
public static void VerifyStandardProperties(bool verifyHelpLink = false)
=> CodeFixVerifierHelper.VerifyStandardProperties(new TAnalyzer(), verifyHelpLink);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyAnalyzerAsync(string, DiagnosticResult[])"/>
public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected)
{
var test = new Test
{
TestCode = source,
};
test.ExpectedDiagnostics.AddRange(expected);
await test.RunAsync();
}
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, string)"/>
public static async Task VerifyCodeFixAsync(string source, string fixedSource)
=> await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, DiagnosticResult, string)"/>
public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource)
=> await VerifyCodeFixAsync(source, new[] { expected }, fixedSource);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, DiagnosticResult[], string)"/>
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();
}
}
}
// 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 ?? "");
}
}
}
}
// 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<KeyValuePair<OptionKey, object>>
{
private readonly Dictionary<OptionKey, object> _options = new Dictionary<OptionKey, object>();
private readonly string _languageName;
public OptionsCollection(string languageName)
{
_languageName = languageName;
}
public void Add<T>(Option<T> option, T value)
=> _options.Add(new OptionKey(option), value);
public void Add<T>(Option<CodeStyleOption<T>> option, T value, NotificationOption notification)
=> _options.Add(new OptionKey(option), new CodeStyleOption<T>(value, notification));
public void Add<T>(PerLanguageOption<T> option, T value)
=> _options.Add(new OptionKey(option, _languageName), value);
public void Add<T>(PerLanguageOption<CodeStyleOption<T>> option, T value)
=> Add(option, value, option.DefaultValue.Notification);
public void Add<T>(PerLanguageOption<CodeStyleOption<T>> option, T value, NotificationOption notification)
=> _options.Add(new OptionKey(option, _languageName), new CodeStyleOption<T>(value, notification));
public IEnumerator<KeyValuePair<OptionKey, object>> GetEnumerator()
=> _options.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
}
}
// 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<TAnalyzer, TCodeFix>
where TAnalyzer : DiagnosticAnalyzer, new()
where TCodeFix : CodeFixProvider, new()
{
public class Test : VisualBasicCodeFixTest<TAnalyzer, TCodeFix, XUnitVerifier>
{
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;
});
}
/// <summary>
/// Gets or sets the language version to use for the test. The default value is
/// <see cref="LanguageVersion.VisualBasic16"/>.
/// </summary>
public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.VisualBasic16;
/// <summary>
/// Gets a collection of options to apply to <see cref="Solution.Options"/> for testing. Values may be added
/// using a collection initializer.
/// </summary>
public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.VisualBasic);
protected override AnalyzerOptions GetAnalyzerOptions(Project project)
{
return new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution);
}
}
}
}
// 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<TAnalyzer, TCodeFix>
where TAnalyzer : DiagnosticAnalyzer, new()
where TCodeFix : CodeFixProvider, new()
{
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic()"/>
public static DiagnosticResult Diagnostic()
=> VisualBasicCodeFixVerifier<TAnalyzer, TCodeFix, XUnitVerifier>.Diagnostic();
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic(string)"/>
public static DiagnosticResult Diagnostic(string diagnosticId)
=> VisualBasicCodeFixVerifier<TAnalyzer, TCodeFix, XUnitVerifier>.Diagnostic(diagnosticId);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic(DiagnosticDescriptor)"/>
public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
=> VisualBasicCodeFixVerifier<TAnalyzer, TCodeFix, XUnitVerifier>.Diagnostic(descriptor);
/// <summary>
/// Verify standard properties of <typeparamref name="TAnalyzer"/>.
/// </summary>
/// <remarks>
/// This validation method is largely specific to dotnet/roslyn scenarios.
/// </remarks>
/// <param name="verifyHelpLink"><see langword="true"/> to verify <see cref="DiagnosticDescriptor.HelpLinkUri"/>
/// property of supported diagnostics; otherwise, <see langword="false"/> to skip this validation.</param>
public static void VerifyStandardProperties(bool verifyHelpLink = false)
=> CodeFixVerifierHelper.VerifyStandardProperties(new TAnalyzer(), verifyHelpLink);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyAnalyzerAsync(string, DiagnosticResult[])"/>
public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected)
{
var test = new Test
{
TestCode = source,
};
test.ExpectedDiagnostics.AddRange(expected);
await test.RunAsync();
}
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, string)"/>
public static async Task VerifyCodeFixAsync(string source, string fixedSource)
=> await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, DiagnosticResult, string)"/>
public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource)
=> await VerifyCodeFixAsync(source, new[] { expected }, fixedSource);
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, DiagnosticResult[], string)"/>
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();
}
}
}
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
<PackageReference Include="Microsoft.VisualStudio.Utilities" Version="$(MicrosoftVisualStudioUtilitiesVersion)" /> <PackageReference Include="Microsoft.VisualStudio.Utilities" Version="$(MicrosoftVisualStudioUtilitiesVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="$(MicrosoftVisualStudioValidationVersion)" /> <PackageReference Include="Microsoft.VisualStudio.Validation" Version="$(MicrosoftVisualStudioValidationVersion)" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(SystemThreadingTasksDataflowVersion)" /> <PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(SystemThreadingTasksDataflowVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="$(MicrosoftCodeAnalysisCSharpCodeFixTestingXUnitVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.CodeFix.Testing.XUnit" Version="$(MicrosoftCodeAnalysisVisualBasicCodeFixTestingXUnitVersion)" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\..\VisualStudio\Core\Def\Implementation\Remote\JsonRpcConnection.cs"> <Compile Include="..\..\VisualStudio\Core\Def\Implementation\Remote\JsonRpcConnection.cs">
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册