Skip to content

Commit 3b38a95

Browse files
committed
Add custom verifiers to the test project
1 parent f03ffa4 commit 3b38a95

30 files changed

+860
-4
lines changed

src/VisualStudio.Roslyn.SDK/Roslyn.SDK/ProjectTemplates/CSharp/Diagnostic/Test/Test.vstemplate

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@
1919
<TemplateContent>
2020
<Project TargetFileName="$safeprojectname$.csproj" File="Test.csproj" ReplaceParameters="true">
2121
<ProjectItem ReplaceParameters="true" TargetFileName="$saferootidentifiername$UnitTests.cs">UnitTests.cs</ProjectItem>
22+
23+
<!-- File names are shortened to avoid PathTooLongException on project creation... -->
24+
<ProjectItem ReplaceParameters="true" TargetFileName="CSharpAnalyzerVerifier`1.cs">Verifiers\CSAnalyzerVerifier`1.cs</ProjectItem>
25+
<ProjectItem ReplaceParameters="true" TargetFileName="CSharpAnalyzerVerifier`1+Test.cs">Verifiers\CSAnalyzerVerifier`1+Test.cs</ProjectItem>
26+
<ProjectItem ReplaceParameters="true" TargetFileName="CSharpCodeFixVerifier`2.cs">Verifiers\CSCodeFixVerifier`2.cs</ProjectItem>
27+
<ProjectItem ReplaceParameters="true" TargetFileName="CSharpCodeFixVerifier`2+Test.cs">Verifiers\CSCodeFixVerifier`2+Test.cs</ProjectItem>
28+
<ProjectItem ReplaceParameters="true" TargetFileName="CSharpCodeRefactoringVerifier`1.cs">Verifiers\CSRefactoringVerifier`1.cs</ProjectItem>
29+
<ProjectItem ReplaceParameters="true" TargetFileName="CSharpCodeRefactoringVerifier`1+Test.cs">Verifiers\CSRefactoringVerifier`1+Test.cs</ProjectItem>
30+
<ProjectItem ReplaceParameters="true" TargetFileName="CSharpVerifierHelper.cs">Verifiers\CSVerifierHelper.cs</ProjectItem>
31+
<ProjectItem ReplaceParameters="true" TargetFileName="VisualBasicAnalyzerVerifier`1.cs">Verifiers\VBAnalyzerVerifier`1.cs</ProjectItem>
32+
<ProjectItem ReplaceParameters="true" TargetFileName="VisualBasicAnalyzerVerifier`1+Test.cs">Verifiers\VBAnalyzerVerifier`1+Test.cs</ProjectItem>
33+
<ProjectItem ReplaceParameters="true" TargetFileName="VisualBasicCodeFixVerifier`2.cs">Verifiers\VBCodeFixVerifier`2.cs</ProjectItem>
34+
<ProjectItem ReplaceParameters="true" TargetFileName="VisualBasicCodeFixVerifier`2+Test.cs">Verifiers\VBCodeFixVerifier`2+Test.cs</ProjectItem>
35+
<ProjectItem ReplaceParameters="true" TargetFileName="VisualBasicCodeRefactoringVerifier`1.cs">Verifiers\VBRefactoringVerifier`1.cs</ProjectItem>
36+
<ProjectItem ReplaceParameters="true" TargetFileName="VisualBasicCodeRefactoringVerifier`1+Test.cs">Verifiers\VBRefactoringVerifier`1+Test.cs</ProjectItem>
2237
</Project>
2338
</TemplateContent>
2439
<WizardExtension>

src/VisualStudio.Roslyn.SDK/Roslyn.SDK/ProjectTemplates/CSharp/Diagnostic/Test/UnitTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
22
using System.Threading.Tasks;
3-
using VerifyCS = Microsoft.CodeAnalysis.CSharp.Testing.MSTest.CodeFixVerifier<
3+
using VerifyCS = $safeprojectname$.CSharpCodeFixVerifier<
44
$saferootprojectname$.$saferootidentifiername$Analyzer,
55
$saferootprojectname$.CSharp$saferootidentifiername$CodeFixProvider>;
6-
using VerifyVB = Microsoft.CodeAnalysis.VisualBasic.Testing.MSTest.CodeFixVerifier<
6+
using VerifyVB = $safeprojectname$.VisualBasicCodeFixVerifier<
77
$saferootprojectname$.$saferootidentifiername$Analyzer,
88
$saferootprojectname$.VisualBasic$saferootidentifiername$CodeFixProvider>;
99

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.CodeAnalysis.CSharp.Testing;
2+
using Microsoft.CodeAnalysis.Diagnostics;
3+
using Microsoft.CodeAnalysis.Testing.Verifiers;
4+
5+
namespace $safeprojectname$
6+
{
7+
public static partial class CSharpAnalyzerVerifier<TAnalyzer>
8+
where TAnalyzer : DiagnosticAnalyzer, new()
9+
{
10+
public class Test : CSharpAnalyzerTest<TAnalyzer, MSTestVerifier>
11+
{
12+
public Test()
13+
{
14+
SolutionTransforms.Add((solution, projectId) =>
15+
{
16+
var compilationOptions = solution.GetProject(projectId).CompilationOptions;
17+
compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(
18+
compilationOptions.SpecificDiagnosticOptions.SetItems(CSharpVerifierHelper.NullableWarnings));
19+
solution = solution.WithProjectCompilationOptions(projectId, compilationOptions);
20+
21+
return solution;
22+
});
23+
}
24+
}
25+
}
26+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Microsoft.CodeAnalysis;
4+
using Microsoft.CodeAnalysis.CSharp.Testing;
5+
using Microsoft.CodeAnalysis.Diagnostics;
6+
using Microsoft.CodeAnalysis.Testing;
7+
using Microsoft.CodeAnalysis.Testing.Verifiers;
8+
9+
namespace $safeprojectname$
10+
{
11+
public static partial class CSharpAnalyzerVerifier<TAnalyzer>
12+
where TAnalyzer : DiagnosticAnalyzer, new()
13+
{
14+
/// <inheritdoc cref="AnalyzerVerifier{TAnalyzer, TTest, TVerifier}.Diagnostic()"/>
15+
public static DiagnosticResult Diagnostic()
16+
=> CSharpAnalyzerVerifier<TAnalyzer, MSTestVerifier>.Diagnostic();
17+
18+
/// <inheritdoc cref="AnalyzerVerifier{TAnalyzer, TTest, TVerifier}.Diagnostic(string)"/>
19+
public static DiagnosticResult Diagnostic(string diagnosticId)
20+
=> CSharpAnalyzerVerifier<TAnalyzer, MSTestVerifier>.Diagnostic(diagnosticId);
21+
22+
/// <inheritdoc cref="AnalyzerVerifier{TAnalyzer, TTest, TVerifier}.Diagnostic(DiagnosticDescriptor)"/>
23+
public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
24+
=> CSharpAnalyzerVerifier<TAnalyzer, MSTestVerifier>.Diagnostic(descriptor);
25+
26+
/// <inheritdoc cref="AnalyzerVerifier{TAnalyzer, TTest, TVerifier}.VerifyAnalyzerAsync(string, DiagnosticResult[])"/>
27+
public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected)
28+
{
29+
var test = new Test
30+
{
31+
TestCode = source,
32+
};
33+
34+
test.ExpectedDiagnostics.AddRange(expected);
35+
await test.RunAsync(CancellationToken.None);
36+
}
37+
}
38+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Microsoft.CodeAnalysis.CodeFixes;
2+
using Microsoft.CodeAnalysis.CSharp.Testing;
3+
using Microsoft.CodeAnalysis.Diagnostics;
4+
using Microsoft.CodeAnalysis.Testing.Verifiers;
5+
6+
namespace $safeprojectname$
7+
{
8+
public static partial class CSharpCodeFixVerifier<TAnalyzer, TCodeFix>
9+
where TAnalyzer : DiagnosticAnalyzer, new()
10+
where TCodeFix : CodeFixProvider, new()
11+
{
12+
public class Test : CSharpCodeFixTest<TAnalyzer, TCodeFix, MSTestVerifier>
13+
{
14+
public Test()
15+
{
16+
SolutionTransforms.Add((solution, projectId) =>
17+
{
18+
var compilationOptions = solution.GetProject(projectId).CompilationOptions;
19+
compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(
20+
compilationOptions.SpecificDiagnosticOptions.SetItems(CSharpVerifierHelper.NullableWarnings));
21+
solution = solution.WithProjectCompilationOptions(projectId, compilationOptions);
22+
23+
return solution;
24+
});
25+
}
26+
}
27+
}
28+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Microsoft.CodeAnalysis;
4+
using Microsoft.CodeAnalysis.CodeFixes;
5+
using Microsoft.CodeAnalysis.CSharp.Testing;
6+
using Microsoft.CodeAnalysis.Diagnostics;
7+
using Microsoft.CodeAnalysis.Testing;
8+
using Microsoft.CodeAnalysis.Testing.Verifiers;
9+
10+
namespace $safeprojectname$
11+
{
12+
public static partial class CSharpCodeFixVerifier<TAnalyzer, TCodeFix>
13+
where TAnalyzer : DiagnosticAnalyzer, new()
14+
where TCodeFix : CodeFixProvider, new()
15+
{
16+
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic()"/>
17+
public static DiagnosticResult Diagnostic()
18+
=> CSharpCodeFixVerifier<TAnalyzer, TCodeFix, MSTestVerifier>.Diagnostic();
19+
20+
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic(string)"/>
21+
public static DiagnosticResult Diagnostic(string diagnosticId)
22+
=> CSharpCodeFixVerifier<TAnalyzer, TCodeFix, MSTestVerifier>.Diagnostic(diagnosticId);
23+
24+
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.Diagnostic(DiagnosticDescriptor)"/>
25+
public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
26+
=> CSharpCodeFixVerifier<TAnalyzer, TCodeFix, MSTestVerifier>.Diagnostic(descriptor);
27+
28+
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyAnalyzerAsync(string, DiagnosticResult[])"/>
29+
public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected)
30+
{
31+
var test = new Test
32+
{
33+
TestCode = source,
34+
};
35+
36+
test.ExpectedDiagnostics.AddRange(expected);
37+
await test.RunAsync(CancellationToken.None);
38+
}
39+
40+
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, string)"/>
41+
public static async Task VerifyCodeFixAsync(string source, string fixedSource)
42+
=> await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource);
43+
44+
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, DiagnosticResult, string)"/>
45+
public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource)
46+
=> await VerifyCodeFixAsync(source, new[] { expected }, fixedSource);
47+
48+
/// <inheritdoc cref="CodeFixVerifier{TAnalyzer, TCodeFix, TTest, TVerifier}.VerifyCodeFixAsync(string, DiagnosticResult[], string)"/>
49+
public static async Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource)
50+
{
51+
var test = new Test
52+
{
53+
TestCode = source,
54+
FixedCode = fixedSource,
55+
};
56+
57+
test.ExpectedDiagnostics.AddRange(expected);
58+
await test.RunAsync(CancellationToken.None);
59+
}
60+
}
61+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.CodeAnalysis.CodeRefactorings;
2+
using Microsoft.CodeAnalysis.CSharp.Testing;
3+
using Microsoft.CodeAnalysis.Testing.Verifiers;
4+
5+
namespace $safeprojectname$
6+
{
7+
public static partial class CSharpCodeRefactoringVerifier<TCodeRefactoring>
8+
where TCodeRefactoring : CodeRefactoringProvider, new()
9+
{
10+
public class Test : CSharpCodeRefactoringTest<TCodeRefactoring, MSTestVerifier>
11+
{
12+
public Test()
13+
{
14+
SolutionTransforms.Add((solution, projectId) =>
15+
{
16+
var compilationOptions = solution.GetProject(projectId).CompilationOptions;
17+
compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(
18+
compilationOptions.SpecificDiagnosticOptions.SetItems(CSharpVerifierHelper.NullableWarnings));
19+
solution = solution.WithProjectCompilationOptions(projectId, compilationOptions);
20+
21+
return solution;
22+
});
23+
}
24+
}
25+
}
26+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Microsoft.CodeAnalysis.CodeRefactorings;
4+
using Microsoft.CodeAnalysis.Testing;
5+
6+
namespace $safeprojectname$
7+
{
8+
public static partial class CSharpCodeRefactoringVerifier<TCodeRefactoring>
9+
where TCodeRefactoring : CodeRefactoringProvider, new()
10+
{
11+
/// <inheritdoc cref="CodeRefactoringVerifier{TCodeRefactoring, TTest, TVerifier}.VerifyRefactoringAsync(string, string)"/>
12+
public static async Task VerifyRefactoringAsync(string source, string fixedSource)
13+
{
14+
await VerifyRefactoringAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource);
15+
}
16+
17+
/// <inheritdoc cref="CodeRefactoringVerifier{TCodeRefactoring, TTest, TVerifier}.VerifyRefactoringAsync(string, DiagnosticResult, string)"/>
18+
public static async Task VerifyRefactoringAsync(string source, DiagnosticResult expected, string fixedSource)
19+
{
20+
await VerifyRefactoringAsync(source, new[] { expected }, fixedSource);
21+
}
22+
23+
/// <inheritdoc cref="CodeRefactoringVerifier{TCodeRefactoring, TTest, TVerifier}.VerifyRefactoringAsync(string, DiagnosticResult[], string)"/>
24+
public static async Task VerifyRefactoringAsync(string source, DiagnosticResult[] expected, string fixedSource)
25+
{
26+
var test = new Test
27+
{
28+
TestCode = source,
29+
FixedCode = fixedSource,
30+
};
31+
32+
test.ExpectedDiagnostics.AddRange(expected);
33+
await test.RunAsync(CancellationToken.None);
34+
}
35+
}
36+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Collections.Immutable;
3+
using Microsoft.CodeAnalysis;
4+
using Microsoft.CodeAnalysis.CSharp;
5+
6+
namespace $safeprojectname$
7+
{
8+
internal static class CSharpVerifierHelper
9+
{
10+
/// <summary>
11+
/// By default, the compiler reports diagnostics for nullable reference types at
12+
/// <see cref="DiagnosticSeverity.Warning"/>, and the analyzer test framework defaults to only validating
13+
/// diagnostics at <see cref="DiagnosticSeverity.Error"/>. This map contains all compiler diagnostic IDs
14+
/// related to nullability mapped to <see cref="ReportDiagnostic.Error"/>, which is then used to enable all
15+
/// of these warnings for default validation during analyzer and code fix tests.
16+
/// </summary>
17+
internal static ImmutableDictionary<string, ReportDiagnostic> NullableWarnings { get; } = GetNullableWarningsFromCompiler();
18+
19+
private static ImmutableDictionary<string, ReportDiagnostic> GetNullableWarningsFromCompiler()
20+
{
21+
string[] args = { "/warnaserror:nullable" };
22+
var commandLineArguments = CSharpCommandLineParser.Default.Parse(args, baseDirectory: Environment.CurrentDirectory, sdkDirectory: Environment.CurrentDirectory);
23+
var nullableWarnings = commandLineArguments.CompilationOptions.SpecificDiagnosticOptions;
24+
25+
// Workaround for https://github.com/dotnet/roslyn/issues/41610
26+
nullableWarnings = nullableWarnings
27+
.SetItem("CS8632", ReportDiagnostic.Error)
28+
.SetItem("CS8669", ReportDiagnostic.Error);
29+
30+
return nullableWarnings;
31+
}
32+
}
33+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Microsoft.CodeAnalysis.Diagnostics;
2+
using Microsoft.CodeAnalysis.Testing.Verifiers;
3+
using Microsoft.CodeAnalysis.VisualBasic.Testing;
4+
5+
namespace $safeprojectname$
6+
{
7+
public static partial class VisualBasicAnalyzerVerifier<TAnalyzer>
8+
where TAnalyzer : DiagnosticAnalyzer, new()
9+
{
10+
public class Test : VisualBasicAnalyzerTest<TAnalyzer, MSTestVerifier>
11+
{
12+
public Test()
13+
{
14+
}
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)