Skip to content

Commit db46934

Browse files
author
Kapil Borle
authored
Merge pull request #702 from PowerShell/kapilmb/use-whitespace-rule
Add rule to check for consistent whitespace style
2 parents 0f4c3aa + 96b1a60 commit db46934

10 files changed

+787
-9
lines changed

Engine/Generic/CorrectionExtent.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,22 @@ public CorrectionExtent(
111111
ThrowIfInvalidArguments();
112112
}
113113

114+
public CorrectionExtent(
115+
IScriptExtent violationExtent,
116+
string replacementText,
117+
string filePath,
118+
string description)
119+
: this(
120+
violationExtent.StartLineNumber,
121+
violationExtent.EndLineNumber,
122+
violationExtent.StartColumnNumber,
123+
violationExtent.EndColumnNumber,
124+
replacementText,
125+
filePath,
126+
description)
127+
{
114128

129+
}
115130

116131
private void ThrowIfInvalidArguments()
117132
{

Engine/Settings/CodeFormatting.psd1

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
IncludeRules = @(
33
'PSPlaceOpenBrace',
44
'PSPlaceCloseBrace',
5-
'PSUseConsistentIndentation'
5+
'PSUseConsistentIndentation',
6+
'PSUseWhitespace'
67
)
78

89
Rules = @{
@@ -20,5 +21,14 @@
2021
Enable = $true
2122
IndentationSize = 4
2223
}
24+
25+
PSUseWhitespace = @{
26+
Enable = $true
27+
CheckOpenBrace = $true
28+
CheckOpenParen = $true
29+
CheckOperator = $true
30+
CheckSeparator = $true
31+
}
32+
2333
}
2434
}

Engine/TokenOperations.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer
2222
public class TokenOperations
2323
{
2424
private readonly Token[] tokens;
25+
private LinkedList<Token> tokensLL;
2526
private readonly Ast ast;
2627

28+
public Ast Ast { get { return ast; } }
29+
2730
/// <summary>
2831
/// Initializes the fields of the TokenOperations class.
2932
/// </summary>
@@ -43,6 +46,7 @@ public TokenOperations(Token[] tokens, Ast ast)
4346

4447
this.tokens = tokens;
4548
this.ast = ast;
49+
this.tokensLL = new LinkedList<Token>(this.tokens);
4650
}
4751

4852
/// <summary>
@@ -105,5 +109,55 @@ private IEnumerable<Token> GetBraceInCommandElement(TokenKind tokenKind)
105109
}
106110
}
107111
}
112+
113+
public IEnumerable<LinkedListNode<Token>> GetTokenNodes(TokenKind kind)
114+
{
115+
return GetTokenNodes((token) => token.Kind == kind);
116+
}
117+
118+
public IEnumerable<LinkedListNode<Token>> GetTokenNodes(Func<Token, bool> predicate)
119+
{
120+
var token = tokensLL.First;
121+
while (token != null)
122+
{
123+
if (predicate(token.Value))
124+
{
125+
yield return token;
126+
}
127+
token = token.Next;
128+
}
129+
}
130+
131+
private IEnumerable<Tuple<Token, int>> GetTokenAndPrecedingWhitespace(TokenKind kind)
132+
{
133+
var lCurlyTokens = GetTokenNodes(TokenKind.LCurly);
134+
foreach (var item in lCurlyTokens)
135+
{
136+
if (item.Previous == null
137+
|| !OnSameLine(item.Previous.Value, item.Value))
138+
{
139+
continue;
140+
}
141+
142+
yield return new Tuple<Token, int>(
143+
item.Value,
144+
item.Value.Extent.StartColumnNumber - item.Previous.Value.Extent.EndColumnNumber);
145+
}
146+
}
147+
148+
public IEnumerable<Tuple<Token, int>> GetOpenBracesWithWhiteSpacesBefore()
149+
{
150+
return GetTokenAndPrecedingWhitespace(TokenKind.LCurly);
151+
}
152+
153+
public IEnumerable<Tuple<Token, int>> GetOpenParensWithWhiteSpacesBefore()
154+
{
155+
return GetTokenAndPrecedingWhitespace(TokenKind.LParen);
156+
}
157+
158+
private bool OnSameLine(Token token1, Token token2)
159+
{
160+
return token1.Extent.StartLineNumber == token2.Extent.EndLineNumber;
161+
}
108162
}
109163
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# UseConsistentWhitespace
2+
**Severity Level: Warning**
3+
4+
## Description
5+
This rule enforces consistent brace, parenthesis, binary operator, assignment operator and separator styles. For more information please see the [Parameters](#parameters) section.
6+
7+
**Note**: This rule is not enabled by default. The user needs to enable it through settings.
8+
9+
## Configuration
10+
```powershell
11+
Rules = @{
12+
PSUseConsistentWhitespace = @{
13+
Enable = $true
14+
CheckOpenBrace = $true
15+
CheckOpenParen = $true
16+
CheckOperator = $true
17+
CheckSeparator = $true
18+
}
19+
}
20+
```
21+
22+
### Parameters
23+
24+
#### Enable: bool (Default value is `$false`)
25+
Enable or disable the rule during ScriptAnalyzer invocation.
26+
27+
#### CheckOpenBrace: bool (Default value is `$true`)
28+
Checks if there is a space between a keyword and its corresponding open brace. E.g. `foo { }`.
29+
30+
#### CheckOpenParen: bool (Default value is `$true`)
31+
Checks if there is space between a keyword and its corresponding open parenthesis. E.g. `if (true)`.
32+
33+
#### CheckOperator: bool (Default value is `$true`)
34+
Checks if a binary operator is surrounded on both sides by a space. E.g. `$x = 1`.
35+
36+
#### CheckSeparator: bool (Default value is `$true`)
37+
Checks if a comma or a semicolon is followed by a space. E.g. `@(1, 2, 3)` or `@{a = 1; b = 2}`.

Rules/ScriptAnalyzerBuiltinRules.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
<Compile Include="PlaceOpenBrace.cs" />
121121
<Compile Include="PlaceCloseBrace.cs" />
122122
<Compile Include="UseConsistentIndentation.cs" />
123+
<Compile Include="UseConsistentWhitespace.cs" />
123124
</ItemGroup>
124125
<ItemGroup>
125126
<ProjectReference Include="..\Engine\ScriptAnalyzerEngine.csproj">

Rules/Strings.resx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,4 +915,28 @@
915915
<data name="UseConsistentIndentationError" xml:space="preserve">
916916
<value>Indentation not consistent</value>
917917
</data>
918+
<data name="UseConsistentWhitespaceName" xml:space="preserve">
919+
<value>UseConsistentWhitespace</value>
920+
</data>
921+
<data name="UseConsistentWhitespaceCommonName" xml:space="preserve">
922+
<value>Use whitespaces</value>
923+
</data>
924+
<data name="UseConsistentWhitespaceDescription" xml:space="preserve">
925+
<value>Check for whitespace between keyword and open paren/curly, around assigment operator ('='), around arithmetic operators and after separators (',' and ';')</value>
926+
</data>
927+
<data name="UseConsistentWhitespaceErrorBeforeBrace" xml:space="preserve">
928+
<value>Use space before open brace.</value>
929+
</data>
930+
<data name="UseConsistentWhitespaceErrorBeforeParen" xml:space="preserve">
931+
<value>Use space before open parenthesis.</value>
932+
</data>
933+
<data name="UseConsistentWhitespaceErrorOperator" xml:space="preserve">
934+
<value>Use space before and after binary and assignment operators.</value>
935+
</data>
936+
<data name="UseConsistentWhitespaceErrorSeparatorComma" xml:space="preserve">
937+
<value>Use space after a comma.</value>
938+
</data>
939+
<data name="UseConsistentWhitespaceErrorSeparatorSemi" xml:space="preserve">
940+
<value>Use space after a semicolon.</value>
941+
</data>
918942
</root>

0 commit comments

Comments
 (0)