@@ -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