@@ -14,8 +14,10 @@ namespace StyleCop.Analyzers.OrderingRules
1414 using Microsoft . CodeAnalysis ;
1515 using Microsoft . CodeAnalysis . CodeActions ;
1616 using Microsoft . CodeAnalysis . CodeFixes ;
17+ using Microsoft . CodeAnalysis . CSharp ;
1718 using Microsoft . CodeAnalysis . CSharp . Syntax ;
1819 using StyleCop . Analyzers . Helpers ;
20+ using StyleCop . Analyzers . Lightup ;
1921 using static StyleCop . Analyzers . OrderingRules . ModifierOrderHelper ;
2022
2123 /// <summary>
@@ -55,31 +57,45 @@ private static async Task<Document> GetTransformedDocumentAsync(Document documen
5557 {
5658 var syntaxRoot = await document . GetSyntaxRootAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
5759
58- var memberDeclaration = syntaxRoot . FindNode ( diagnostic . Location . SourceSpan ) . FirstAncestorOrSelf < MemberDeclarationSyntax > ( ) ;
59- if ( memberDeclaration == null )
60+ var memberOrLocalFunction = syntaxRoot . FindNode ( diagnostic . Location . SourceSpan ) . FirstAncestorOrSelf < CSharpSyntaxNode > ( static node => node is MemberDeclarationSyntax || LocalFunctionStatementSyntaxWrapper . IsInstance ( node ) ) ;
61+ if ( memberOrLocalFunction == null )
6062 {
6163 return document ;
6264 }
6365
64- var modifierTokenToFix = memberDeclaration . FindToken ( diagnostic . Location . SourceSpan . Start ) ;
66+ var modifierTokenToFix = memberOrLocalFunction . FindToken ( diagnostic . Location . SourceSpan . Start ) ;
6567 if ( GetModifierType ( modifierTokenToFix ) == ModifierType . None )
6668 {
6769 return document ;
6870 }
6971
70- var newModifierList = PartiallySortModifiers ( memberDeclaration . GetModifiers ( ) , modifierTokenToFix ) ;
71- syntaxRoot = UpdateSyntaxRoot ( memberDeclaration , newModifierList , syntaxRoot ) ;
72+ if ( memberOrLocalFunction is MemberDeclarationSyntax memberDeclaration )
73+ {
74+ var newModifierList = PartiallySortModifiers ( memberDeclaration . GetModifiers ( ) , modifierTokenToFix ) ;
75+ syntaxRoot = UpdateSyntaxRoot ( memberDeclaration , newModifierList , syntaxRoot ) ;
76+ }
77+ else
78+ {
79+ var localFunctionStatement = ( LocalFunctionStatementSyntaxWrapper ) memberOrLocalFunction ;
80+ var newModifierList = PartiallySortModifiers ( localFunctionStatement . Modifiers , modifierTokenToFix ) ;
81+ syntaxRoot = UpdateSyntaxRoot ( localFunctionStatement , newModifierList , syntaxRoot ) ;
82+ }
7283
7384 return document . WithSyntaxRoot ( syntaxRoot ) ;
7485 }
7586
7687 private static SyntaxNode UpdateSyntaxRoot ( MemberDeclarationSyntax memberDeclaration , SyntaxTokenList newModifiers , SyntaxNode syntaxRoot )
7788 {
78- var newDeclaration = memberDeclaration . WithModifiers ( newModifiers ) ;
79-
89+ var newDeclaration = DeclarationModifiersHelper . WithModifiers ( memberDeclaration , newModifiers ) ;
8090 return syntaxRoot . ReplaceNode ( memberDeclaration , newDeclaration ) ;
8191 }
8292
93+ private static SyntaxNode UpdateSyntaxRoot ( LocalFunctionStatementSyntaxWrapper localFunctionStatement , SyntaxTokenList newModifiers , SyntaxNode syntaxRoot )
94+ {
95+ var newDeclaration = localFunctionStatement . WithModifiers ( newModifiers ) ;
96+ return syntaxRoot . ReplaceNode ( localFunctionStatement , newDeclaration ) ;
97+ }
98+
8399 /// <summary>
84100 /// Sorts the complete modifier list to fix all issues.
85101 /// The trivia will be maintained positionally.
@@ -175,31 +191,40 @@ protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fi
175191
176192 // because all modifiers can be fixed in one run, we
177193 // only need to store each declaration once
178- var trackedDiagnosticMembers = new HashSet < MemberDeclarationSyntax > ( ) ;
194+ var trackedDiagnosticMembers = new HashSet < CSharpSyntaxNode > ( ) ;
179195 foreach ( var diagnostic in diagnostics )
180196 {
181- var memberDeclaration = syntaxRoot . FindNode ( diagnostic . Location . SourceSpan ) . FirstAncestorOrSelf < MemberDeclarationSyntax > ( ) ;
182- if ( memberDeclaration == null )
197+ var memberOrLocalFunction = syntaxRoot . FindNode ( diagnostic . Location . SourceSpan ) . FirstAncestorOrSelf < CSharpSyntaxNode > ( static node => node is MemberDeclarationSyntax || LocalFunctionStatementSyntaxWrapper . IsInstance ( node ) ) ;
198+ if ( memberOrLocalFunction == null )
183199 {
184200 continue ;
185201 }
186202
187- var modifierToken = memberDeclaration . FindToken ( diagnostic . Location . SourceSpan . Start ) ;
203+ var modifierToken = memberOrLocalFunction . FindToken ( diagnostic . Location . SourceSpan . Start ) ;
188204 if ( GetModifierType ( modifierToken ) == ModifierType . None )
189205 {
190206 continue ;
191207 }
192208
193- trackedDiagnosticMembers . Add ( memberDeclaration ) ;
209+ trackedDiagnosticMembers . Add ( memberOrLocalFunction ) ;
194210 }
195211
196212 syntaxRoot = syntaxRoot . TrackNodes ( trackedDiagnosticMembers ) ;
197213
198214 foreach ( var member in trackedDiagnosticMembers )
199215 {
200- var memberDeclaration = syntaxRoot . GetCurrentNode ( member ) ;
201- var newModifierList = FullySortModifiers ( memberDeclaration . GetModifiers ( ) ) ;
202- syntaxRoot = UpdateSyntaxRoot ( memberDeclaration , newModifierList , syntaxRoot ) ;
216+ var currentMember = syntaxRoot . GetCurrentNode ( member ) ;
217+ if ( currentMember is MemberDeclarationSyntax memberDeclaration )
218+ {
219+ var newModifierList = FullySortModifiers ( memberDeclaration . GetModifiers ( ) ) ;
220+ syntaxRoot = UpdateSyntaxRoot ( memberDeclaration , newModifierList , syntaxRoot ) ;
221+ }
222+ else
223+ {
224+ var localFunctionStatement = ( LocalFunctionStatementSyntaxWrapper ) currentMember ;
225+ var newModifierList = FullySortModifiers ( localFunctionStatement . Modifiers ) ;
226+ syntaxRoot = UpdateSyntaxRoot ( localFunctionStatement , newModifierList , syntaxRoot ) ;
227+ }
203228 }
204229
205230 return syntaxRoot ;
0 commit comments