@@ -133,13 +133,23 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
133133 var onNewLine = true ;
134134 var pipelineAsts = ast . FindAll ( testAst => testAst is PipelineAst && ( testAst as PipelineAst ) . PipelineElements . Count > 1 , true ) . ToList ( ) ;
135135 // Sort by end position so that inner (nested) pipelines appear before outer ones.
136- // This is required by MatchingPipelineAstEnd, whose early-break optimization
137- // would otherwise skip nested pipelines that end before their outer pipeline.
136+ // Preserve this order when selecting the first matching pipeline on each line.
138137 pipelineAsts . Sort ( ( a , b ) =>
139138 {
140139 int lineCmp = a . Extent . EndScriptPosition . LineNumber . CompareTo ( b . Extent . EndScriptPosition . LineNumber ) ;
141140 return lineCmp != 0 ? lineCmp : a . Extent . EndScriptPosition . ColumnNumber . CompareTo ( b . Extent . EndScriptPosition . ColumnNumber ) ;
142141 } ) ;
142+ var pipelineEndsByLine = new Dictionary < int , List < Ast > > ( ) ;
143+ foreach ( var pipeline in pipelineAsts )
144+ {
145+ int endLine = pipeline . Extent . EndScriptPosition . LineNumber ;
146+ if ( ! pipelineEndsByLine . TryGetValue ( endLine , out var pipelinesOnLine ) )
147+ {
148+ pipelinesOnLine = new List < Ast > ( ) ;
149+ pipelineEndsByLine . Add ( endLine , pipelinesOnLine ) ;
150+ }
151+ pipelinesOnLine . Add ( pipeline ) ;
152+ }
143153 // Track pipeline indentation increases per PipelineAst instead of as a single
144154 // flat counter. A flat counter caused all accumulated pipeline indentation to be
145155 // subtracted when *any* pipeline ended, instead of only the contribution from
@@ -306,7 +316,7 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
306316 if ( pipelineIndentationStyle == PipelineIndentationStyle . None ) { continue ; }
307317
308318 // Check if the current token matches the end of a PipelineAst
309- PipelineAst matchingPipeLineAstEnd = MatchingPipelineAstEnd ( pipelineAsts , token ) ;
319+ PipelineAst matchingPipeLineAstEnd = MatchingPipelineAstEnd ( pipelineEndsByLine , token ) ;
310320 if ( matchingPipeLineAstEnd == null )
311321 {
312322 continue ;
@@ -493,24 +503,22 @@ private static CommandBaseAst LastPipeOnFirstLineWithPipeUsage(PipelineAst pipel
493503 return lastPipeOnFirstLineWithPipeUsage ;
494504 }
495505
496- private static PipelineAst MatchingPipelineAstEnd ( List < Ast > pipelineAsts , Token token )
506+ private static PipelineAst MatchingPipelineAstEnd ( Dictionary < int , List < Ast > > pipelineEndsByLine , Token token )
497507 {
498- PipelineAst matchingPipeLineAstEnd = null ;
499- for ( int i = 0 ; i < pipelineAsts . Count ; i ++ )
508+ if ( ! pipelineEndsByLine . TryGetValue ( token . Extent . EndScriptPosition . LineNumber , out var pipelineAsts ) )
500509 {
501- if ( pipelineAsts [ i ] . Extent . EndScriptPosition . LineNumber > token . Extent . EndScriptPosition . LineNumber )
502- {
503- break ;
504- }
510+ return null ;
511+ }
505512
513+ for ( int i = 0 ; i < pipelineAsts . Count ; i ++ )
514+ {
506515 if ( PositionIsEqual ( pipelineAsts [ i ] . Extent . EndScriptPosition , token . Extent . EndScriptPosition ) )
507516 {
508- matchingPipeLineAstEnd = pipelineAsts [ i ] as PipelineAst ;
509- break ;
517+ return pipelineAsts [ i ] as PipelineAst ;
510518 }
511519 }
512520
513- return matchingPipeLineAstEnd ;
521+ return null ;
514522 }
515523
516524 /// <summary>
0 commit comments