Skip to content
This repository was archived by the owner on Apr 8, 2019. It is now read-only.

Commit b49b767

Browse files
committed
Update test framework to support testing code fixes in multiple files
1 parent 0897c00 commit b49b767

File tree

2 files changed

+179
-64
lines changed

2 files changed

+179
-64
lines changed

PublicApiAnalyzer/PublicApiAnalyzer.Test/Helpers/CodeFixVerifier.Helper.cs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace TestHelper
1212
using Microsoft.CodeAnalysis.CodeActions;
1313
using Microsoft.CodeAnalysis.Formatting;
1414
using Microsoft.CodeAnalysis.Simplification;
15+
using Microsoft.CodeAnalysis.Text;
1516

1617
/// <summary>
1718
/// Diagnostic Producer class with extra methods dealing with applying code fixes.
@@ -23,16 +24,16 @@ public abstract partial class CodeFixVerifier : DiagnosticVerifier
2324
/// Apply the inputted <see cref="CodeAction"/> to the inputted document.
2425
/// Meant to be used to apply code fixes.
2526
/// </summary>
26-
/// <param name="document">The <see cref="Document"/> to apply the fix on</param>
27+
/// <param name="project">The <see cref="Project"/> to apply the fix on</param>
2728
/// <param name="codeAction">A <see cref="CodeAction"/> that will be applied to the
28-
/// <paramref name="document"/>.</param>
29+
/// <paramref name="project"/>.</param>
2930
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
30-
/// <returns>A <see cref="Document"/> with the changes from the <see cref="CodeAction"/>.</returns>
31-
private static async Task<Document> ApplyFixAsync(Document document, CodeAction codeAction, CancellationToken cancellationToken)
31+
/// <returns>A <see cref="Project"/> with the changes from the <see cref="CodeAction"/>.</returns>
32+
private static async Task<Project> ApplyFixAsync(Project project, CodeAction codeAction, CancellationToken cancellationToken)
3233
{
3334
var operations = await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false);
3435
var solution = operations.OfType<ApplyChangesOperation>().Single().ChangedSolution;
35-
return solution.GetDocument(document.Id);
36+
return solution.GetProject(project.Id);
3637
}
3738

3839
/// <summary>
@@ -75,13 +76,20 @@ private static IEnumerable<Diagnostic> GetNewDiagnostics(IEnumerable<Diagnostic>
7576
/// <summary>
7677
/// Get the existing compiler diagnostics on the input document.
7778
/// </summary>
78-
/// <param name="document">The <see cref="Document"/> to run the compiler diagnostic analyzers on.</param>
79+
/// <param name="project">The <see cref="Project"/> to run the compiler diagnostic analyzers on.</param>
7980
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
8081
/// <returns>The compiler diagnostics that were found in the code.</returns>
81-
private static async Task<ImmutableArray<Diagnostic>> GetCompilerDiagnosticsAsync(Document document, CancellationToken cancellationToken)
82+
private static async Task<ImmutableArray<Diagnostic>> GetCompilerDiagnosticsAsync(Project project, CancellationToken cancellationToken)
8283
{
83-
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
84-
return semanticModel.GetDiagnostics(cancellationToken: cancellationToken);
84+
var allDiagnostics = ImmutableArray.Create<Diagnostic>();
85+
86+
foreach (var document in project.Documents)
87+
{
88+
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
89+
allDiagnostics = allDiagnostics.AddRange(semanticModel.GetDiagnostics(cancellationToken: cancellationToken));
90+
}
91+
92+
return allDiagnostics;
8593
}
8694

8795
/// <summary>
@@ -97,5 +105,49 @@ private static async Task<string> GetStringFromDocumentAsync(Document document,
97105
var sourceText = await formatted.GetTextAsync(cancellationToken).ConfigureAwait(false);
98106
return sourceText.ToString();
99107
}
108+
109+
/// <summary>
110+
/// Implements a workaround for issue #936, force re-parsing to get the same sort of syntax tree as the original document.
111+
/// </summary>
112+
/// <param name="project">The project to update.</param>
113+
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
114+
/// <returns>The updated <see cref="Project"/>.</returns>
115+
private static async Task<Project> RecreateProjectDocumentsAsync(Project project, CancellationToken cancellationToken)
116+
{
117+
foreach (var documentId in project.DocumentIds)
118+
{
119+
var document = project.GetDocument(documentId);
120+
document = await RecreateDocumentAsync(document, cancellationToken).ConfigureAwait(false);
121+
project = document.Project;
122+
}
123+
124+
return project;
125+
}
126+
127+
private static async Task<Document> RecreateDocumentAsync(Document document, CancellationToken cancellationToken)
128+
{
129+
var newText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
130+
newText = newText.WithChanges(new TextChange(new TextSpan(0, 0), " "));
131+
newText = newText.WithChanges(new TextChange(new TextSpan(0, 1), string.Empty));
132+
return document.WithText(newText);
133+
}
134+
135+
/// <summary>
136+
/// Formats the whitespace in all documents of the specified <see cref="Project"/>.
137+
/// </summary>
138+
/// <param name="project">The project to update.</param>
139+
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
140+
/// <returns>The updated <see cref="Project"/>.</returns>
141+
private static async Task<Project> ReformatProjectDocumentsAsync(Project project, CancellationToken cancellationToken)
142+
{
143+
foreach (var documentId in project.DocumentIds)
144+
{
145+
var document = project.GetDocument(documentId);
146+
document = await Formatter.FormatAsync(document, Formatter.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);
147+
project = document.Project;
148+
}
149+
150+
return project;
151+
}
100152
}
101153
}

0 commit comments

Comments
 (0)