@@ -22,7 +22,7 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
2222#endif
2323 public class UseConsistentWhitespace : ConfigurableRule
2424 {
25- private enum ErrorKind { Brace , Paren , Operator , SeparatorComma , SeparatorSemi } ;
25+ private enum ErrorKind { BeforeOpeningBrace , Paren , Operator , SeparatorComma , SeparatorSemi , AfterOpeningBrace , BeforeClosingBrace , BeforePipe , AfterPipe } ;
2626 private const int whiteSpaceSize = 1 ;
2727 private const string whiteSpace = " " ;
2828 private readonly SortedSet < TokenKind > openParenKeywordWhitelist = new SortedSet < TokenKind > ( )
@@ -41,6 +41,12 @@ private List<Func<TokenOperations, IEnumerable<DiagnosticRecord>>> violationFind
4141 [ ConfigurableRuleProperty ( defaultValue : true ) ]
4242 public bool CheckOpenBrace { get ; protected set ; }
4343
44+ [ ConfigurableRuleProperty ( defaultValue : true ) ]
45+ public bool CheckInnerBrace { get ; protected set ; }
46+
47+ [ ConfigurableRuleProperty ( defaultValue : true ) ]
48+ public bool CheckPipe { get ; protected set ; }
49+
4450 [ ConfigurableRuleProperty ( defaultValue : true ) ]
4551 public bool CheckOpenParen { get ; protected set ; }
4652
@@ -58,6 +64,16 @@ public override void ConfigureRule(IDictionary<string, object> paramValueMap)
5864 violationFinders . Add ( FindOpenBraceViolations ) ;
5965 }
6066
67+ if ( CheckInnerBrace )
68+ {
69+ violationFinders . Add ( FindInnerBraceViolations ) ;
70+ }
71+
72+ if ( CheckPipe )
73+ {
74+ violationFinders . Add ( FindPipeViolations ) ;
75+ }
76+
6177 if ( CheckOpenParen )
6278 {
6379 violationFinders . Add ( FindOpenParenViolations ) ;
@@ -171,10 +187,18 @@ private string GetError(ErrorKind kind)
171187 {
172188 switch ( kind )
173189 {
174- case ErrorKind . Brace :
175- return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorBeforeBrace ) ;
190+ case ErrorKind . BeforeOpeningBrace :
191+ return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorBeforeOpeningBrace ) ;
192+ case ErrorKind . AfterOpeningBrace :
193+ return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorAfterOpeningBrace ) ;
194+ case ErrorKind . BeforeClosingBrace :
195+ return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorBeforeClosingInnerBrace ) ;
176196 case ErrorKind . Operator :
177197 return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorOperator ) ;
198+ case ErrorKind . BeforePipe :
199+ return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorSpaceBeforePipe ) ;
200+ case ErrorKind . AfterPipe :
201+ return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorSpaceAfterPipe ) ;
178202 case ErrorKind . SeparatorComma :
179203 return string . Format ( CultureInfo . CurrentCulture , Strings . UseConsistentWhitespaceErrorSeparatorComma ) ;
180204 case ErrorKind . SeparatorSemi :
@@ -200,7 +224,7 @@ private IEnumerable<DiagnosticRecord> FindOpenBraceViolations(TokenOperations to
200224 if ( ! IsPreviousTokenApartByWhitespace ( lcurly ) )
201225 {
202226 yield return new DiagnosticRecord (
203- GetError ( ErrorKind . Brace ) ,
227+ GetError ( ErrorKind . BeforeOpeningBrace ) ,
204228 lcurly . Value . Extent ,
205229 GetName ( ) ,
206230 GetDiagnosticSeverity ( ) ,
@@ -211,6 +235,111 @@ private IEnumerable<DiagnosticRecord> FindOpenBraceViolations(TokenOperations to
211235 }
212236 }
213237
238+ private IEnumerable < DiagnosticRecord > FindInnerBraceViolations ( TokenOperations tokenOperations )
239+ {
240+ foreach ( var lCurly in tokenOperations . GetTokenNodes ( TokenKind . LCurly ) )
241+ {
242+ if ( lCurly . Next == null
243+ || ! IsPreviousTokenOnSameLine ( lCurly )
244+ || lCurly . Next . Value . Kind == TokenKind . NewLine
245+ || lCurly . Next . Value . Kind == TokenKind . LineContinuation
246+ )
247+ {
248+ continue ;
249+ }
250+
251+ if ( ! IsNextTokenApartByWhitespace ( lCurly ) )
252+ {
253+ yield return new DiagnosticRecord (
254+ GetError ( ErrorKind . AfterOpeningBrace ) ,
255+ lCurly . Value . Extent ,
256+ GetName ( ) ,
257+ GetDiagnosticSeverity ( ) ,
258+ tokenOperations . Ast . Extent . File ,
259+ null ,
260+ GetCorrections ( lCurly . Previous . Value , lCurly . Value , lCurly . Next . Value , true , false ) . ToList ( ) ) ;
261+ }
262+ }
263+
264+ foreach ( var rCurly in tokenOperations . GetTokenNodes ( TokenKind . RCurly ) )
265+ {
266+ if ( rCurly . Previous == null
267+ || ! IsPreviousTokenOnSameLine ( rCurly )
268+ || rCurly . Previous . Value . Kind == TokenKind . LCurly
269+ || rCurly . Previous . Value . Kind == TokenKind . NewLine
270+ || rCurly . Previous . Value . Kind == TokenKind . LineContinuation
271+ )
272+ {
273+ continue ;
274+ }
275+
276+ if ( ! IsPreviousTokenApartByWhitespace ( rCurly ) )
277+ {
278+ yield return new DiagnosticRecord (
279+ GetError ( ErrorKind . BeforeClosingBrace ) ,
280+ rCurly . Value . Extent ,
281+ GetName ( ) ,
282+ GetDiagnosticSeverity ( ) ,
283+ tokenOperations . Ast . Extent . File ,
284+ null ,
285+ GetCorrections ( rCurly . Previous . Value , rCurly . Value , rCurly . Next . Value , false , true ) . ToList ( ) ) ;
286+ }
287+ }
288+ }
289+
290+ private IEnumerable < DiagnosticRecord > FindPipeViolations ( TokenOperations tokenOperations )
291+ {
292+ foreach ( var pipe in tokenOperations . GetTokenNodes ( TokenKind . Pipe ) )
293+ {
294+ if ( pipe . Next == null
295+ || ! IsPreviousTokenOnSameLine ( pipe )
296+ || pipe . Next . Value . Kind == TokenKind . Pipe
297+ || pipe . Next . Value . Kind == TokenKind . NewLine
298+ || pipe . Next . Value . Kind == TokenKind . LineContinuation
299+ )
300+ {
301+ continue ;
302+ }
303+
304+ if ( ! IsNextTokenApartByWhitespace ( pipe ) )
305+ {
306+ yield return new DiagnosticRecord (
307+ GetError ( ErrorKind . AfterPipe ) ,
308+ pipe . Value . Extent ,
309+ GetName ( ) ,
310+ GetDiagnosticSeverity ( ) ,
311+ tokenOperations . Ast . Extent . File ,
312+ null ,
313+ GetCorrections ( pipe . Previous . Value , pipe . Value , pipe . Next . Value , true , false ) . ToList ( ) ) ;
314+ }
315+ }
316+
317+ foreach ( var pipe in tokenOperations . GetTokenNodes ( TokenKind . Pipe ) )
318+ {
319+ if ( pipe . Previous == null
320+ || ! IsPreviousTokenOnSameLine ( pipe )
321+ || pipe . Previous . Value . Kind == TokenKind . Pipe
322+ || pipe . Previous . Value . Kind == TokenKind . NewLine
323+ || pipe . Previous . Value . Kind == TokenKind . LineContinuation
324+ )
325+ {
326+ continue ;
327+ }
328+
329+ if ( ! IsPreviousTokenApartByWhitespace ( pipe ) )
330+ {
331+ yield return new DiagnosticRecord (
332+ GetError ( ErrorKind . BeforePipe ) ,
333+ pipe . Value . Extent ,
334+ GetName ( ) ,
335+ GetDiagnosticSeverity ( ) ,
336+ tokenOperations . Ast . Extent . File ,
337+ null ,
338+ GetCorrections ( pipe . Previous . Value , pipe . Value , pipe . Next . Value , false , true ) . ToList ( ) ) ;
339+ }
340+ }
341+ }
342+
214343 private IEnumerable < DiagnosticRecord > FindOpenParenViolations ( TokenOperations tokenOperations )
215344 {
216345 foreach ( var lparen in tokenOperations . GetTokenNodes ( TokenKind . LParen ) )
@@ -291,6 +420,12 @@ private bool IsPreviousTokenApartByWhitespace(LinkedListNode<Token> tokenNode)
291420 ( tokenNode . Value . Extent . StartColumnNumber - tokenNode . Previous . Value . Extent . EndColumnNumber ) ;
292421 }
293422
423+ private bool IsNextTokenApartByWhitespace ( LinkedListNode < Token > tokenNode )
424+ {
425+ return whiteSpaceSize ==
426+ ( tokenNode . Next . Value . Extent . StartColumnNumber - tokenNode . Value . Extent . EndColumnNumber ) ;
427+ }
428+
294429 private bool IsPreviousTokenOnSameLineAndApartByWhitespace ( LinkedListNode < Token > tokenNode )
295430 {
296431 return IsPreviousTokenOnSameLine ( tokenNode ) && IsPreviousTokenApartByWhitespace ( tokenNode ) ;
@@ -342,8 +477,9 @@ private List<CorrectionExtent> GetCorrections(
342477 Token prevToken ,
343478 Token token ,
344479 Token nextToken ,
345- bool hasWhitespaceBefore ,
346- bool hasWhitespaceAfter )
480+ bool hasWhitespaceBefore , // if this is false, then the returned correction extent will add a whitespace before the token
481+ bool hasWhitespaceAfter // if this is false, then the returned correction extent will add a whitespace after the token
482+ )
347483 {
348484 var sb = new StringBuilder ( ) ;
349485 IScriptExtent e1 = token . Extent ;
0 commit comments