-
Notifications
You must be signed in to change notification settings - Fork 257
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add diagnostic and code fix verification helpers
- Loading branch information
Showing
11 changed files
with
1,757 additions
and
7 deletions.
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
...es/CSharp/ConvertToConditional/ConvertToConditional.Test/ConvertToConditional.Test.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace Roslyn.UnitTestFramework | ||
{ | ||
public static class CodeFixVerifier<TAnalyzer, TCodeFix> | ||
where TAnalyzer : DiagnosticAnalyzer, new() | ||
where TCodeFix : CodeFixProvider, new() | ||
{ | ||
public static DiagnosticResult[] EmptyDiagnosticResults | ||
=> DiagnosticVerifier<TAnalyzer>.EmptyDiagnosticResults; | ||
|
||
public static DiagnosticResult Diagnostic(string diagnosticId = null) | ||
=> DiagnosticVerifier<TAnalyzer>.Diagnostic(diagnosticId); | ||
|
||
public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) | ||
=> DiagnosticVerifier<TAnalyzer>.Diagnostic(descriptor); | ||
|
||
public static DiagnosticResult CompilerError(string errorIdentifier) | ||
=> DiagnosticVerifier<TAnalyzer>.CompilerError(errorIdentifier); | ||
|
||
public static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult expected, CancellationToken cancellationToken) | ||
=> DiagnosticVerifier<TAnalyzer>.VerifyCSharpDiagnosticAsync(source, expected, cancellationToken); | ||
|
||
public static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[] expected, CancellationToken cancellationToken) | ||
=> DiagnosticVerifier<TAnalyzer>.VerifyCSharpDiagnosticAsync(source, expected, cancellationToken); | ||
|
||
public static Task VerifyCSharpFixAsync(string source, DiagnosticResult expected, string fixedSource, CancellationToken cancellationToken) | ||
=> VerifyCSharpFixAsync(source, new[] { expected }, fixedSource, cancellationToken); | ||
|
||
public static Task VerifyCSharpFixAsync(string source, DiagnosticResult[] expected, string fixedSource, CancellationToken cancellationToken) | ||
{ | ||
CSharpTest test = new CSharpTest | ||
{ | ||
TestCode = source, | ||
FixedCode = fixedSource, | ||
}; | ||
|
||
test.ExpectedDiagnostics.AddRange(expected); | ||
return test.RunAsync(cancellationToken); | ||
} | ||
|
||
public class CSharpTest : DiagnosticVerifier<TAnalyzer>.CSharpTest | ||
{ | ||
protected override IEnumerable<CodeFixProvider> GetCodeFixProviders() | ||
=> new[] { new TCodeFix() }; | ||
} | ||
|
||
public class VisualBasicTest : DiagnosticVerifier<TAnalyzer>.VisualBasicTest | ||
{ | ||
protected override IEnumerable<CodeFixProvider> GetCodeFixProviders() | ||
=> new[] { new TCodeFix() }; | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
samples/Shared/UnitTestFramework/CustomDiagnosticVerifier`1.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace Roslyn.UnitTestFramework | ||
{ | ||
public static class CustomDiagnosticVerifier<TAnalyzer> | ||
where TAnalyzer : DiagnosticAnalyzer, new() | ||
{ | ||
public static DiagnosticResult[] EmptyDiagnosticResults | ||
=> DiagnosticVerifier<TAnalyzer>.EmptyDiagnosticResults; | ||
|
||
public static DiagnosticResult Diagnostic(string diagnosticId = null) | ||
=> DiagnosticVerifier<TAnalyzer>.Diagnostic(diagnosticId); | ||
|
||
public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) | ||
=> DiagnosticVerifier<TAnalyzer>.Diagnostic(descriptor); | ||
|
||
public static DiagnosticResult CompilerError(string errorIdentifier) | ||
=> DiagnosticVerifier<TAnalyzer>.CompilerError(errorIdentifier); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Collections.Immutable; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace Roslyn.UnitTestFramework | ||
{ | ||
/// <summary> | ||
/// Structure that stores information about a <see cref="Diagnostic"/> appearing in a source. | ||
/// </summary> | ||
public struct DiagnosticResult | ||
{ | ||
private const string DefaultPath = "Test0.cs"; | ||
|
||
private static readonly object[] EmptyArguments = new object[0]; | ||
|
||
private ImmutableArray<FileLinePositionSpan> _spans; | ||
private string _message; | ||
|
||
public DiagnosticResult(string id, DiagnosticSeverity severity) | ||
: this() | ||
{ | ||
Id = id; | ||
Severity = severity; | ||
} | ||
|
||
public DiagnosticResult(DiagnosticDescriptor descriptor) | ||
: this() | ||
{ | ||
Id = descriptor.Id; | ||
Severity = descriptor.DefaultSeverity; | ||
MessageFormat = descriptor.MessageFormat; | ||
} | ||
|
||
public ImmutableArray<FileLinePositionSpan> Spans | ||
{ | ||
get | ||
{ | ||
return _spans.IsDefault ? ImmutableArray<FileLinePositionSpan>.Empty : _spans; | ||
} | ||
} | ||
|
||
public DiagnosticSeverity Severity | ||
{ | ||
get; | ||
private set; | ||
} | ||
|
||
public string Id | ||
{ | ||
get; | ||
private set; | ||
} | ||
|
||
public string Message | ||
{ | ||
get | ||
{ | ||
if (_message != null) | ||
{ | ||
return _message; | ||
} | ||
|
||
if (MessageFormat != null) | ||
{ | ||
return string.Format(MessageFormat.ToString(), MessageArguments ?? EmptyArguments); | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
|
||
public LocalizableString MessageFormat | ||
{ | ||
get; | ||
private set; | ||
} | ||
|
||
public object[] MessageArguments | ||
{ | ||
get; | ||
private set; | ||
} | ||
|
||
public bool HasLocation | ||
{ | ||
get | ||
{ | ||
return (_spans != null) && (_spans.Length > 0); | ||
} | ||
} | ||
|
||
public DiagnosticResult WithSeverity(DiagnosticSeverity severity) | ||
{ | ||
DiagnosticResult result = this; | ||
result.Severity = severity; | ||
return result; | ||
} | ||
|
||
public DiagnosticResult WithArguments(params object[] arguments) | ||
{ | ||
DiagnosticResult result = this; | ||
result.MessageArguments = arguments; | ||
return result; | ||
} | ||
|
||
public DiagnosticResult WithMessage(string message) | ||
{ | ||
DiagnosticResult result = this; | ||
result._message = message; | ||
return result; | ||
} | ||
|
||
public DiagnosticResult WithMessageFormat(LocalizableString messageFormat) | ||
{ | ||
DiagnosticResult result = this; | ||
result.MessageFormat = messageFormat; | ||
return result; | ||
} | ||
|
||
public DiagnosticResult WithLocation(int line, int column) | ||
{ | ||
return WithLocation(DefaultPath, line, column); | ||
} | ||
|
||
public DiagnosticResult WithLocation(string path, int line, int column) | ||
{ | ||
LinePosition linePosition = new LinePosition(line, column); | ||
|
||
return AppendSpan(new FileLinePositionSpan(path, linePosition, linePosition)); | ||
} | ||
|
||
public DiagnosticResult WithSpan(int startLine, int startColumn, int endLine, int endColumn) | ||
{ | ||
return WithSpan(DefaultPath, startLine, startColumn, endLine, endColumn); | ||
} | ||
|
||
public DiagnosticResult WithSpan(string path, int startLine, int startColumn, int endLine, int endColumn) | ||
{ | ||
return AppendSpan(new FileLinePositionSpan(path, new LinePosition(startLine, startColumn), new LinePosition(endLine, endColumn))); | ||
} | ||
|
||
public DiagnosticResult WithLineOffset(int offset) | ||
{ | ||
DiagnosticResult result = this; | ||
ImmutableArray<FileLinePositionSpan>.Builder spansBuilder = result._spans.ToBuilder(); | ||
for (int i = 0; i < result._spans.Length; i++) | ||
{ | ||
LinePosition newStartLinePosition = new LinePosition(result._spans[i].StartLinePosition.Line + offset, result._spans[i].StartLinePosition.Character); | ||
LinePosition newEndLinePosition = new LinePosition(result._spans[i].EndLinePosition.Line + offset, result._spans[i].EndLinePosition.Character); | ||
|
||
spansBuilder[i] = new FileLinePositionSpan(result._spans[i].Path, newStartLinePosition, newEndLinePosition); | ||
} | ||
|
||
result._spans = spansBuilder.MoveToImmutable(); | ||
return result; | ||
} | ||
|
||
private DiagnosticResult AppendSpan(FileLinePositionSpan span) | ||
{ | ||
ImmutableArray<FileLinePositionSpan> newSpans = _spans.Add(span); | ||
|
||
// clone the object, so that the fluent syntax will work on immutable objects. | ||
return new DiagnosticResult | ||
{ | ||
Id = Id, | ||
_message = _message, | ||
MessageFormat = MessageFormat, | ||
MessageArguments = MessageArguments, | ||
Severity = Severity, | ||
_spans = newSpans, | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace Roslyn.UnitTestFramework | ||
{ | ||
public static class DiagnosticVerifier<TAnalyzer> | ||
where TAnalyzer : DiagnosticAnalyzer, new() | ||
{ | ||
public static DiagnosticResult[] EmptyDiagnosticResults { get; } = { }; | ||
|
||
public static DiagnosticResult Diagnostic(string diagnosticId = null) | ||
{ | ||
TAnalyzer analyzer = new TAnalyzer(); | ||
ImmutableArray<DiagnosticDescriptor> supportedDiagnostics = analyzer.SupportedDiagnostics; | ||
if (diagnosticId is null) | ||
{ | ||
return Diagnostic(supportedDiagnostics.Single()); | ||
} | ||
else | ||
{ | ||
return Diagnostic(supportedDiagnostics.Single(i => i.Id == diagnosticId)); | ||
} | ||
} | ||
|
||
public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) | ||
{ | ||
return new DiagnosticResult(descriptor); | ||
} | ||
|
||
public static DiagnosticResult CompilerError(string errorIdentifier) | ||
{ | ||
return new DiagnosticResult(errorIdentifier, DiagnosticSeverity.Error); | ||
} | ||
|
||
public static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult expected, CancellationToken cancellationToken) | ||
=> VerifyCSharpDiagnosticAsync(source, new[] { expected }, cancellationToken); | ||
|
||
public static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult[] expected, CancellationToken cancellationToken) | ||
{ | ||
CSharpTest test = new CSharpTest | ||
{ | ||
TestCode = source, | ||
}; | ||
|
||
test.ExpectedDiagnostics.AddRange(expected); | ||
return test.RunAsync(cancellationToken); | ||
} | ||
|
||
public class CSharpTest : GenericAnalyzerTest | ||
{ | ||
public override string Language => LanguageNames.CSharp; | ||
|
||
protected override IEnumerable<DiagnosticAnalyzer> GetDiagnosticAnalyzers() | ||
=> new[] { new TAnalyzer() }; | ||
|
||
protected override IEnumerable<CodeFixProvider> GetCodeFixProviders() | ||
=> Enumerable.Empty<CodeFixProvider>(); | ||
} | ||
|
||
public class VisualBasicTest : GenericAnalyzerTest | ||
{ | ||
public override string Language => LanguageNames.VisualBasic; | ||
|
||
protected override IEnumerable<DiagnosticAnalyzer> GetDiagnosticAnalyzers() | ||
=> new[] { new TAnalyzer() }; | ||
|
||
protected override IEnumerable<CodeFixProvider> GetCodeFixProviders() | ||
=> Enumerable.Empty<CodeFixProvider>(); | ||
} | ||
} | ||
} |
Oops, something went wrong.