Skip to content

Commit 735c860

Browse files
author
Kapil Borle
committed
Pass rule argument to PlaceOpenBrace rule
1 parent 0fc42d6 commit 735c860

2 files changed

Lines changed: 145 additions & 13 deletions

File tree

Rules/PlaceOpenBrace.cs

Lines changed: 114 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
using System.Globalization;
1717
using System.Linq;
1818
using System.Management.Automation.Language;
19+
using System.Text;
1920
using Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic;
21+
using System.Reflection;
2022

2123
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
2224
{
@@ -28,6 +30,42 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
2830
#endif
2931
class PlaceOpenBrace : IScriptRule
3032
{
33+
private class RuleArguments
34+
{
35+
public bool OnSameLine { get; set; } = true;
36+
37+
public static RuleArguments Create(Dictionary<string, object> arguments)
38+
{
39+
try
40+
{
41+
var ruleArguments = new RuleArguments();
42+
var properties = ruleArguments.GetType().GetProperties();
43+
foreach (var property in properties)
44+
{
45+
if (arguments.ContainsKey(property.Name))
46+
{
47+
var type = property.PropertyType;
48+
var obj = arguments[property.Name];
49+
property.SetValue(ruleArguments, System.Convert.ChangeType(obj, Type.GetTypeCode(type)));
50+
}
51+
}
52+
53+
return ruleArguments;
54+
}
55+
catch
56+
{
57+
return new RuleArguments(); // return arguments with defaults
58+
}
59+
}
60+
}
61+
62+
private RuleArguments ruleArgs;
63+
64+
public PlaceOpenBrace()
65+
{
66+
ruleArgs = RuleArguments.Create(Helper.Instance.GetRuleArguments(this.GetName()));
67+
}
68+
3169
/// <summary>
3270
/// Analyzes the given ast to find the [violation]
3371
/// </summary>
@@ -46,26 +84,90 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
4684
// * on-new-line
4785
// * new-line-after
4886
// * no-empty-line-after
49-
// * stick-a-space-before
5087

5188
var tokens = Helper.Instance.Tokens;
52-
for (int k = 2; k < tokens.Length; k++)
89+
if (ruleArgs.OnSameLine)
90+
{
91+
for (int k = 2; k < tokens.Length; k++)
92+
{
93+
if (tokens[k].Kind == TokenKind.LCurly
94+
&& tokens[k - 1].Kind == TokenKind.NewLine)
95+
{
96+
yield return new DiagnosticRecord(
97+
GetError(),
98+
tokens[k].Extent,
99+
GetName(),
100+
GetDiagnosticSeverity(),
101+
fileName,
102+
null,
103+
GetSuggestedCorrections(tokens[k - 2], tokens[k], fileName));
104+
}
105+
}
106+
}
107+
else
53108
{
54-
if (tokens[k].Kind == TokenKind.LCurly
55-
&& tokens[k - 1].Kind == TokenKind.NewLine)
109+
for (int k = 1; k < tokens.Length; k++)
56110
{
57-
yield return new DiagnosticRecord(
58-
GetError(),
59-
tokens[k].Extent,
60-
GetName(),
61-
GetDiagnosticSeverity(),
62-
fileName,
63-
null,
64-
GetSuggestedCorrections(tokens[k - 2], tokens[k], fileName));
111+
if (tokens[k].Kind == TokenKind.LCurly
112+
&& tokens[k - 1].Kind != TokenKind.NewLine)
113+
{
114+
yield return new DiagnosticRecord(
115+
GetError(),
116+
tokens[k].Extent,
117+
GetName(),
118+
GetDiagnosticSeverity(),
119+
fileName,
120+
null,
121+
GetSuggestedCorrectionsForNotOneSameLine(tokens, k - 1, k, fileName));
122+
}
65123
}
66124
}
67125
}
68126

127+
private List<CorrectionExtent> GetSuggestedCorrectionsForNotOneSameLine(
128+
Token[] tokens,
129+
int prevTokenPos,
130+
int closeBraceTokenPos,
131+
string fileName)
132+
{
133+
var corrections = new List<CorrectionExtent>();
134+
var prevToken = tokens[prevTokenPos];
135+
var closeBraceToken = tokens[closeBraceTokenPos];
136+
corrections.Add(
137+
new CorrectionExtent(
138+
prevToken.Extent.StartLineNumber,
139+
closeBraceToken.Extent.EndLineNumber,
140+
prevToken.Extent.StartColumnNumber,
141+
closeBraceToken.Extent.EndColumnNumber,
142+
(new StringBuilder())
143+
.Append(prevToken.Text)
144+
.AppendLine()
145+
.Append(GetIndentation(tokens, closeBraceTokenPos))
146+
.Append(closeBraceToken.Text)
147+
.ToString(),
148+
fileName));
149+
return corrections;
150+
}
151+
152+
private string GetIndentation(Token[] tokens, int refTokenPos)
153+
{
154+
return new String(' ', GetStartColumnNumberOfTokenLine(tokens, refTokenPos) - 1);
155+
}
156+
157+
private int GetStartColumnNumberOfTokenLine(Token[] tokens, int refTokenPos)
158+
{
159+
var refToken = tokens[refTokenPos];
160+
for (int k = refTokenPos - 1; k >= 0; k--)
161+
{
162+
if (tokens[k].Extent.StartLineNumber != refToken.Extent.StartLineNumber)
163+
{
164+
return tokens[k].Extent.StartColumnNumber;
165+
}
166+
}
167+
168+
return refToken.Extent.StartColumnNumber;
169+
}
170+
69171
private List<CorrectionExtent> GetSuggestedCorrections(Token precedingExpression, Token lCurly, string fileName)
70172
{
71173
var corrections = new List<CorrectionExtent>();

Tests/Rules/PlaceOpenBrace.tests.ps1

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
$ruleName = "PSPlaceOpenBrace"
33

44
Describe "PlaceOpenBrace on same line" {
5-
Context "When a open brace is on a new line" {
5+
Context "When an open brace must be on the same line" {
66
BeforeAll{
77
$def = @'
88
function foo ($param1)
@@ -21,4 +21,34 @@ function foo ($param1)
2121
$violations[0].Extent.Text | Should Be '{'
2222
}
2323
}
24+
25+
Context "When an open brace must be on a new line" {
26+
BeforeAll{
27+
$def = @'
28+
function foo ($param1) {
29+
30+
}
31+
'@
32+
$params = @{
33+
ScriptDefinition = $def
34+
IncludeRule = $ruleName
35+
Settings = @{
36+
rules = @{
37+
PSPlaceOpenBrace = @{
38+
OnSameLine = $false
39+
}
40+
}
41+
}
42+
}
43+
$violations = Invoke-ScriptAnalyzer @params
44+
}
45+
46+
It "Should find a violation" {
47+
$violations.Count | Should Be 1
48+
}
49+
50+
It "Should mark only the open brace" {
51+
$violations[0].Extent.Text | Should Be '{'
52+
}
53+
}
2454
}

0 commit comments

Comments
 (0)