@@ -134,6 +134,13 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
134134 var onNewLine = true ;
135135 var pipelineAsts = ast . FindAll ( testAst => testAst is PipelineAst && ( testAst as PipelineAst ) . PipelineElements . Count > 1 , true ) . ToList ( ) ;
136136 int minimumPipelineAstIndex = 0 ;
137+ /*
138+ When an LParen and LBrace are on the same line, it can lead to too much de-indentation.
139+ In order to prevent the RParen code from de-indenting too much, we keep a stack of when we skipped the indentation
140+ caused by tokens that require a closing RParen (which are LParen, AtParen and DollarParen).
141+ */
142+ var lParenSkippedIndentation = new Stack < bool > ( ) ;
143+
137144 for ( int tokenIndex = 0 ; tokenIndex < tokens . Length ; tokenIndex ++ )
138145 {
139146 var token = tokens [ tokenIndex ] ;
@@ -146,10 +153,27 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
146153 switch ( token . Kind )
147154 {
148155 case TokenKind . AtCurly :
149- case TokenKind . AtParen :
150- case TokenKind . LParen :
151156 case TokenKind . LCurly :
157+ AddViolation ( token , indentationLevel ++ , diagnosticRecords , ref onNewLine ) ;
158+ break ;
159+
152160 case TokenKind . DollarParen :
161+ case TokenKind . AtParen :
162+ lParenSkippedIndentation . Push ( false ) ;
163+ AddViolation ( token , indentationLevel ++ , diagnosticRecords , ref onNewLine ) ;
164+ break ;
165+
166+ case TokenKind . LParen :
167+ // When a line starts with a parenthesis and it is not the last non-comment token of that line,
168+ // then indentation does not need to be increased.
169+ if ( ( tokenIndex == 0 || tokens [ tokenIndex - 1 ] . Kind == TokenKind . NewLine ) &&
170+ NextTokenIgnoringComments ( tokens , tokenIndex ) ? . Kind != TokenKind . NewLine )
171+ {
172+ onNewLine = false ;
173+ lParenSkippedIndentation . Push ( true ) ;
174+ break ;
175+ }
176+ lParenSkippedIndentation . Push ( false ) ;
153177 AddViolation ( token , indentationLevel ++ , diagnosticRecords , ref onNewLine ) ;
154178 break ;
155179
@@ -181,6 +205,20 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
181205 break ;
182206
183207 case TokenKind . RParen :
208+ bool matchingLParenIncreasedIndentation = false ;
209+ if ( lParenSkippedIndentation . Count > 0 )
210+ {
211+ matchingLParenIncreasedIndentation = lParenSkippedIndentation . Pop ( ) ;
212+ }
213+ if ( matchingLParenIncreasedIndentation )
214+ {
215+ onNewLine = false ;
216+ break ;
217+ }
218+ indentationLevel = ClipNegative ( indentationLevel - 1 ) ;
219+ AddViolation ( token , indentationLevel , diagnosticRecords , ref onNewLine ) ;
220+ break ;
221+
184222 case TokenKind . RCurly :
185223 indentationLevel = ClipNegative ( indentationLevel - 1 ) ;
186224 AddViolation ( token , indentationLevel , diagnosticRecords , ref onNewLine ) ;
@@ -259,6 +297,29 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
259297 return diagnosticRecords ;
260298 }
261299
300+ private static Token NextTokenIgnoringComments ( Token [ ] tokens , int startIndex )
301+ {
302+ if ( startIndex >= tokens . Length - 1 )
303+ {
304+ return null ;
305+ }
306+
307+ for ( int i = startIndex + 1 ; i < tokens . Length ; i ++ )
308+ {
309+ switch ( tokens [ i ] . Kind )
310+ {
311+ case TokenKind . Comment :
312+ continue ;
313+
314+ default :
315+ return tokens [ i ] ;
316+ }
317+ }
318+
319+ // We've run out of tokens
320+ return null ;
321+ }
322+
262323 private static bool PipelineIsFollowedByNewlineOrLineContinuation ( Token [ ] tokens , int startIndex )
263324 {
264325 if ( startIndex >= tokens . Length - 1 )
0 commit comments