@@ -37,6 +37,7 @@ public class SolutionReader
3737 private Compilation analyzerCompilation ;
3838 private Compilation codeFixCompilation ;
3939 private ITypeSymbol booleanType ;
40+ private Type batchFixerType ;
4041
4142 private SolutionReader ( )
4243 {
@@ -99,7 +100,6 @@ public async Task<ImmutableList<StyleCopDiagnostic>> GetDiagnosticsAsync()
99100 }
100101
101102 string shortName = match . Groups [ "name" ] . Value ;
102- CodeFixStatus codeFixStatus ;
103103 string noCodeFixReason = null ;
104104
105105 // Check if this syntax tree represents a diagnostic
@@ -130,7 +130,7 @@ public async Task<ImmutableList<StyleCopDiagnostic>> GetDiagnosticsAsync()
130130
131131 foreach ( var descriptorInfo in descriptorInfos )
132132 {
133- codeFixStatus = this . HasCodeFix ( descriptorInfo . Id , classSymbol , out noCodeFixReason ) ;
133+ var ( codeFixStatus , fixAllStatus ) = this . GetCodeFixAndFixAllStatus ( descriptorInfo . Id , classSymbol , out noCodeFixReason ) ;
134134 string status = this . GetStatus ( classSymbol , syntaxRoot , semanticModel , descriptorInfo ) ;
135135 if ( descriptorInfo . CustomTags . Contains ( WellKnownDiagnosticTags . NotConfigurable ) )
136136 {
@@ -147,6 +147,7 @@ public async Task<ImmutableList<StyleCopDiagnostic>> GetDiagnosticsAsync()
147147 Title = descriptorInfo . Title . ToString ( ) ,
148148 HelpLink = descriptorInfo . HelpLinkUri ,
149149 CodeFixStatus = codeFixStatus ,
150+ FixAllStatus = fixAllStatus ,
150151 NoCodeFixReason = noCodeFixReason ,
151152 } ;
152153 diagnostics . Add ( diagnostic ) ;
@@ -192,6 +193,8 @@ private async Task InitializeAsync()
192193 this . noCodeFixAttributeTypeSymbol = this . analyzerCompilation . GetTypeByMetadataName ( "StyleCop.Analyzers.NoCodeFixAttribute" ) ;
193194 this . diagnosticAnalyzerTypeSymbol = this . analyzerCompilation . GetTypeByMetadataName ( typeof ( DiagnosticAnalyzer ) . FullName ) ;
194195
196+ this . batchFixerType = this . codeFixAssembly . GetType ( "StyleCop.Analyzers.Helpers.CustomBatchFixAllProvider" ) ;
197+
195198 this . InitializeCodeFixTypes ( ) ;
196199 }
197200
@@ -284,18 +287,22 @@ private IEnumerable<DiagnosticDescriptor> GetDescriptor(INamedTypeSymbol classSy
284287 return analyzer . SupportedDiagnostics ;
285288 }
286289
287- private CodeFixStatus HasCodeFix ( string diagnosticId , INamedTypeSymbol classSymbol , out string noCodeFixReason )
290+ private ( CodeFixStatus , FixAllStatus ) GetCodeFixAndFixAllStatus ( string diagnosticId , INamedTypeSymbol classSymbol , out string noCodeFixReason )
288291 {
289- CodeFixStatus status ;
292+ CodeFixStatus codeFixStatus ;
293+ FixAllStatus fixAllStatus ;
290294
291295 noCodeFixReason = null ;
292296
293- var noCodeFixAttribute = classSymbol . GetAttributes ( ) . SingleOrDefault ( x => x . AttributeClass == this . noCodeFixAttributeTypeSymbol ) ;
297+ var noCodeFixAttribute = classSymbol
298+ . GetAttributes ( )
299+ . SingleOrDefault ( x => x . AttributeClass == this . noCodeFixAttributeTypeSymbol ) ;
294300
295301 bool hasCodeFix = noCodeFixAttribute == null ;
296302 if ( ! hasCodeFix )
297303 {
298- status = CodeFixStatus . NotImplemented ;
304+ codeFixStatus = CodeFixStatus . NotImplemented ;
305+ fixAllStatus = FixAllStatus . None ;
299306 if ( noCodeFixAttribute . ConstructorArguments . Length > 0 )
300307 {
301308 noCodeFixReason = noCodeFixAttribute . ConstructorArguments [ 0 ] . Value as string ;
@@ -304,12 +311,45 @@ private CodeFixStatus HasCodeFix(string diagnosticId, INamedTypeSymbol classSymb
304311 else
305312 {
306313 // Check if the code fix actually exists
307- hasCodeFix = this . CodeFixProviders . Any ( x => x . FixableDiagnosticIds . Contains ( diagnosticId ) ) ;
314+ var codeFixes = this . CodeFixProviders
315+ . Where ( x => x . FixableDiagnosticIds . Contains ( diagnosticId ) )
316+ . Select ( x => this . IsBatchFixer ( x ) )
317+ . Where ( x => x != null )
318+ . Select ( x => ( bool ) x ) . ToArray ( ) ;
319+
320+ hasCodeFix = codeFixes . Length > 0 ;
321+
322+ codeFixStatus = hasCodeFix ? CodeFixStatus . Implemented : CodeFixStatus . NotYetImplemented ;
308323
309- status = hasCodeFix ? CodeFixStatus . Implemented : CodeFixStatus . NotYetImplemented ;
324+ if ( codeFixes . Any ( x => x ) )
325+ {
326+ fixAllStatus = FixAllStatus . BatchFixer ;
327+ }
328+ else if ( codeFixes . Length > 0 )
329+ {
330+ fixAllStatus = FixAllStatus . CustomImplementation ;
331+ }
332+ else
333+ {
334+ fixAllStatus = FixAllStatus . None ;
335+ }
310336 }
311337
312- return status ;
338+ return ( codeFixStatus , fixAllStatus ) ;
339+ }
340+
341+ private bool ? IsBatchFixer ( CodeFixProvider provider )
342+ {
343+ var fixAllProvider = provider . GetFixAllProvider ( ) ;
344+
345+ if ( fixAllProvider == null )
346+ {
347+ return null ;
348+ }
349+ else
350+ {
351+ return fixAllProvider . GetType ( ) == this . batchFixerType ;
352+ }
313353 }
314354
315355 private bool InheritsFrom ( INamedTypeSymbol declaration , INamedTypeSymbol possibleBaseType )
0 commit comments