33
44namespace StyleCop . Analyzers . Helpers
55{
6- using System ;
76 using System . Collections . Concurrent ;
87 using System . Collections . Generic ;
98 using System . Collections . Immutable ;
109 using System . Linq ;
11- using System . Reflection ;
1210 using System . Threading ;
1311 using System . Threading . Tasks ;
1412 using Microsoft . CodeAnalysis ;
1513 using Microsoft . CodeAnalysis . CodeFixes ;
1614 using Microsoft . CodeAnalysis . Diagnostics ;
17- using Microsoft . CodeAnalysis . Text ;
1815
1916 internal static class FixAllContextHelper
2017 {
21- private static readonly ImmutableDictionary < string , ImmutableArray < Type > > DiagnosticAnalyzers = GetAllAnalyzers ( ) ;
22-
23- private static readonly Func < CompilationWithAnalyzers , SyntaxTree , CancellationToken , Task < ImmutableArray < Diagnostic > > > GetAnalyzerSyntaxDiagnosticsAsync ;
24- private static readonly Func < CompilationWithAnalyzers , SemanticModel , TextSpan ? , CancellationToken , Task < ImmutableArray < Diagnostic > > > GetAnalyzerSemanticDiagnosticsAsync ;
25- private static readonly Func < CompilationWithAnalyzers , ImmutableArray < DiagnosticAnalyzer > , CancellationToken , Task < ImmutableArray < Diagnostic > > > GetAnalyzerCompilationDiagnosticsAsync ;
26-
27- static FixAllContextHelper ( )
28- {
29- Version roslynVersion = typeof ( AdditionalText ) . GetTypeInfo ( ) . Assembly . GetName ( ) . Version ;
30- bool avoidGetAnalyzerDiagnosticsAsync = roslynVersion >= new Version ( 1 , 1 , 0 , 0 ) && roslynVersion < new Version ( 1 , 2 , 0 , 0 ) ;
31- if ( avoidGetAnalyzerDiagnosticsAsync )
32- {
33- var methodInfo = typeof ( CompilationWithAnalyzers ) . GetRuntimeMethod ( nameof ( GetAnalyzerSyntaxDiagnosticsAsync ) , new [ ] { typeof ( SyntaxTree ) , typeof ( CancellationToken ) } ) ;
34- GetAnalyzerSyntaxDiagnosticsAsync = ( Func < CompilationWithAnalyzers , SyntaxTree , CancellationToken , Task < ImmutableArray < Diagnostic > > > ) methodInfo ? . CreateDelegate ( typeof ( Func < CompilationWithAnalyzers , SyntaxTree , CancellationToken , Task < ImmutableArray < Diagnostic > > > ) ) ;
35-
36- methodInfo = typeof ( CompilationWithAnalyzers ) . GetRuntimeMethod ( nameof ( GetAnalyzerSemanticDiagnosticsAsync ) , new [ ] { typeof ( SemanticModel ) , typeof ( TextSpan ? ) , typeof ( CancellationToken ) } ) ;
37- GetAnalyzerSemanticDiagnosticsAsync = ( Func < CompilationWithAnalyzers , SemanticModel , TextSpan ? , CancellationToken , Task < ImmutableArray < Diagnostic > > > ) methodInfo ? . CreateDelegate ( typeof ( Func < CompilationWithAnalyzers , SemanticModel , TextSpan ? , CancellationToken , Task < ImmutableArray < Diagnostic > > > ) ) ;
38-
39- methodInfo = typeof ( CompilationWithAnalyzers ) . GetRuntimeMethod ( nameof ( GetAnalyzerCompilationDiagnosticsAsync ) , new [ ] { typeof ( ImmutableArray < DiagnosticAnalyzer > ) , typeof ( CancellationToken ) } ) ;
40- GetAnalyzerCompilationDiagnosticsAsync = ( Func < CompilationWithAnalyzers , ImmutableArray < DiagnosticAnalyzer > , CancellationToken , Task < ImmutableArray < Diagnostic > > > ) methodInfo ? . CreateDelegate ( typeof ( Func < CompilationWithAnalyzers , ImmutableArray < DiagnosticAnalyzer > , CancellationToken , Task < ImmutableArray < Diagnostic > > > ) ) ;
41- }
42- }
43-
4418 public static async Task < ImmutableDictionary < Document , ImmutableArray < Diagnostic > > > GetDocumentDiagnosticsToFixAsync ( FixAllContext fixAllContext )
4519 {
4620 var allDiagnostics = ImmutableArray < Diagnostic > . Empty ;
@@ -132,87 +106,7 @@ public static async Task<ImmutableDictionary<Project, ImmutableArray<Diagnostic>
132106
133107 public static async Task < ImmutableArray < Diagnostic > > GetAllDiagnosticsAsync ( Compilation compilation , CompilationWithAnalyzers compilationWithAnalyzers , ImmutableArray < DiagnosticAnalyzer > analyzers , IEnumerable < Document > documents , bool includeCompilerDiagnostics , CancellationToken cancellationToken )
134108 {
135- if ( GetAnalyzerSyntaxDiagnosticsAsync == null || GetAnalyzerSemanticDiagnosticsAsync == null )
136- {
137- // In everything except Roslyn 1.1, we use GetAllDiagnosticsAsync and return the result.
138- var allDiagnostics = await compilationWithAnalyzers . GetAllDiagnosticsAsync ( ) . ConfigureAwait ( false ) ;
139- return allDiagnostics ;
140- }
141-
142- compilationWithAnalyzers . Compilation . GetDeclarationDiagnostics ( cancellationToken ) ;
143-
144- // Note that the following loop to obtain syntax and semantic diagnostics for each document cannot operate
145- // on parallel due to our use of a single CompilationWithAnalyzers instance.
146- var diagnostics = ImmutableArray . CreateBuilder < Diagnostic > ( ) ;
147- foreach ( var document in documents )
148- {
149- var syntaxTree = await document . GetSyntaxTreeAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
150- var syntaxDiagnostics = await GetAnalyzerSyntaxDiagnosticsAsync ( compilationWithAnalyzers , syntaxTree , cancellationToken ) . ConfigureAwait ( false ) ;
151- diagnostics . AddRange ( syntaxDiagnostics ) ;
152-
153- var semanticModel = await document . GetSemanticModelAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
154- var semanticDiagnostics = await GetAnalyzerSemanticDiagnosticsAsync ( compilationWithAnalyzers , semanticModel , default ( TextSpan ? ) , cancellationToken ) . ConfigureAwait ( false ) ;
155- diagnostics . AddRange ( semanticDiagnostics ) ;
156- }
157-
158- foreach ( var analyzer in analyzers )
159- {
160- diagnostics . AddRange ( await GetAnalyzerCompilationDiagnosticsAsync ( compilationWithAnalyzers , ImmutableArray . Create ( analyzer ) , cancellationToken ) . ConfigureAwait ( false ) ) ;
161- }
162-
163- if ( includeCompilerDiagnostics )
164- {
165- // This is the special handling for cases where code fixes operate on warnings produced by the C#
166- // compiler, as opposed to being created by specific analyzers.
167- var compilerDiagnostics = compilation . GetDiagnostics ( cancellationToken ) ;
168- diagnostics . AddRange ( compilerDiagnostics ) ;
169- }
170-
171- return diagnostics . ToImmutable ( ) ;
172- }
173-
174- private static ImmutableDictionary < string , ImmutableArray < Type > > GetAllAnalyzers ( )
175- {
176- Assembly assembly = typeof ( NoCodeFixAttribute ) . GetTypeInfo ( ) . Assembly ;
177-
178- var diagnosticAnalyzerType = typeof ( DiagnosticAnalyzer ) ;
179-
180- var analyzers = ImmutableDictionary . CreateBuilder < string , ImmutableArray < Type > > ( ) ;
181-
182- foreach ( var type in assembly . DefinedTypes )
183- {
184- if ( type . IsSubclassOf ( diagnosticAnalyzerType ) && ! type . IsAbstract )
185- {
186- Type analyzerType = type . AsType ( ) ;
187- DiagnosticAnalyzer analyzer = ( DiagnosticAnalyzer ) Activator . CreateInstance ( analyzerType ) ;
188- foreach ( var descriptor in analyzer . SupportedDiagnostics )
189- {
190- ImmutableArray < Type > types ;
191- if ( analyzers . TryGetValue ( descriptor . Id , out types ) )
192- {
193- types = types . Add ( analyzerType ) ;
194- }
195- else
196- {
197- types = ImmutableArray . Create ( analyzerType ) ;
198- }
199-
200- analyzers [ descriptor . Id ] = types ;
201- }
202- }
203- }
204-
205- return analyzers . ToImmutable ( ) ;
206- }
207-
208- private static ImmutableArray < DiagnosticAnalyzer > GetDiagnosticAnalyzersForContext ( FixAllContext fixAllContext )
209- {
210- return DiagnosticAnalyzers
211- . Where ( x => fixAllContext . DiagnosticIds . Contains ( x . Key ) )
212- . SelectMany ( x => x . Value )
213- . Distinct ( )
214- . Select ( type => ( DiagnosticAnalyzer ) Activator . CreateInstance ( type ) )
215- . ToImmutableArray ( ) ;
109+ return await compilationWithAnalyzers . GetAllDiagnosticsAsync ( ) . ConfigureAwait ( false ) ;
216110 }
217111
218112 /// <summary>
@@ -225,32 +119,7 @@ private static ImmutableArray<DiagnosticAnalyzer> GetDiagnosticAnalyzersForConte
225119 /// successfully, the <see cref="Task{TResult}.Result"/> will contain the requested diagnostics.</returns>
226120 private static async Task < ImmutableArray < Diagnostic > > GetAllDiagnosticsAsync ( FixAllContext fixAllContext , Project project )
227121 {
228- if ( GetAnalyzerSyntaxDiagnosticsAsync == null || GetAnalyzerSemanticDiagnosticsAsync == null )
229- {
230- return await fixAllContext . GetAllDiagnosticsAsync ( project ) . ConfigureAwait ( false ) ;
231- }
232-
233- /*
234- * The rest of this method is workaround code for issues with Roslyn 1.1...
235- */
236-
237- var analyzers = GetDiagnosticAnalyzersForContext ( fixAllContext ) ;
238-
239- // Most code fixes in this project operate on diagnostics reported by analyzers in this project. However, a
240- // few code fixes also operate on standard warnings produced by the C# compiler. Special handling is
241- // required for the latter case since these warnings are not considered "analyzer diagnostics".
242- bool includeCompilerDiagnostics = fixAllContext . DiagnosticIds . Any ( x => x . StartsWith ( "CS" , StringComparison . Ordinal ) ) ;
243-
244- // Use a single CompilationWithAnalyzers for the entire operation. This allows us to use the
245- // GetDeclarationDiagnostics workaround for dotnet/roslyn#7446 a single time, rather than once per document.
246- var compilation = await project . GetCompilationAsync ( fixAllContext . CancellationToken ) . ConfigureAwait ( false ) ;
247- var compilationWithAnalyzers = compilation . WithAnalyzers ( analyzers , project . AnalyzerOptions , fixAllContext . CancellationToken ) ;
248- ImmutableArray < Diagnostic > diagnostics = await GetAllDiagnosticsAsync ( compilation , compilationWithAnalyzers , analyzers , project . Documents , includeCompilerDiagnostics , fixAllContext . CancellationToken ) . ConfigureAwait ( false ) ;
249-
250- // Make sure to filter the results to the set requested for the Fix All operation, since analyzers can
251- // report diagnostics with different IDs.
252- diagnostics = diagnostics . RemoveAll ( x => ! fixAllContext . DiagnosticIds . Contains ( x . Id ) ) ;
253- return diagnostics ;
122+ return await fixAllContext . GetAllDiagnosticsAsync ( project ) . ConfigureAwait ( false ) ;
254123 }
255124
256125 private static async Task < ImmutableDictionary < Document , ImmutableArray < Diagnostic > > > GetDocumentDiagnosticsToFixAsync (
0 commit comments