@@ -29,12 +29,14 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
2929 class UseConsistentIndentation : IScriptRule
3030 {
3131 private readonly int unitsPerIndentationLevel ;
32+ private enum IndentationKind { Space , Tab } ;
33+ private IndentationKind indentationKind ;
3234
3335 UseConsistentIndentation ( )
3436 {
35- // TODO Add a parameter for indentation kind {Tab, Space}
3637 // TODO make this configurable
37- unitsPerIndentationLevel = 4 ;
38+ indentationKind = IndentationKind . Space ;
39+ unitsPerIndentationLevel = indentationKind == IndentationKind . Space ? 4 : 1 ;
3840 }
3941
4042 /// <summary>
@@ -52,26 +54,20 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
5254
5355 var tokens = Helper . Instance . Tokens ;
5456 var diagnosticRecords = new List < DiagnosticRecord > ( ) ;
55- var openBracePosStack = new Stack < int > ( ) ;
57+ var indentationLevel = 0 ;
5658 bool onNewLine = true ;
5759 for ( int k = 0 ; k < tokens . Length ; k ++ )
5860 {
5961 var token = tokens [ k ] ;
60- var curIndentationLevel = GetIndentationLevel ( openBracePosStack ) ;
61- var curIndentation = GetIndentation ( curIndentationLevel ) ;
6262 switch ( token . Kind )
6363 {
6464 case TokenKind . LCurly :
65- AddViolation ( token , curIndentationLevel , diagnosticRecords , ref onNewLine ) ;
66- openBracePosStack . Push ( k ) ;
65+ AddViolation ( token , indentationLevel ++ , diagnosticRecords , ref onNewLine ) ;
6766 break ;
6867
6968 case TokenKind . RCurly :
70- if ( openBracePosStack . Count > 0 )
71- {
72- openBracePosStack . Pop ( ) ;
73- }
74- AddViolation ( token , GetIndentationLevel ( openBracePosStack ) , diagnosticRecords , ref onNewLine ) ;
69+ indentationLevel = ClipNegative ( indentationLevel - 1 ) ;
70+ AddViolation ( token , indentationLevel , diagnosticRecords , ref onNewLine ) ;
7571 break ;
7672
7773 case TokenKind . NewLine :
@@ -83,7 +79,7 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
8379 // we add this redundant check
8480 if ( onNewLine )
8581 {
86- AddViolation ( token , curIndentationLevel , diagnosticRecords , ref onNewLine ) ;
82+ AddViolation ( token , indentationLevel , diagnosticRecords , ref onNewLine ) ;
8783 }
8884 break ;
8985 }
@@ -94,14 +90,14 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
9490
9591 private void AddViolation (
9692 Token token ,
97- int curIndentationLevel ,
93+ int expectedIndentationLevel ,
9894 List < DiagnosticRecord > diagnosticRecords ,
9995 ref bool onNewLine )
10096 {
10197 if ( onNewLine )
10298 {
10399 onNewLine = false ;
104- if ( token . Extent . StartColumnNumber - 1 != GetIndentation ( curIndentationLevel ) )
100+ if ( token . Extent . StartColumnNumber - 1 != GetIndentation ( expectedIndentationLevel ) )
105101 {
106102 var fileName = token . Extent . File ;
107103 var extent = token . Extent ;
@@ -124,11 +120,30 @@ private void AddViolation(
124120 GetDiagnosticSeverity ( ) ,
125121 fileName ,
126122 null ,
127- null ) ) ;
123+ GetSuggestedCorrections ( token , expectedIndentationLevel ) ) ) ;
128124 }
129125 }
130126 }
131127
128+ private List < CorrectionExtent > GetSuggestedCorrections (
129+ Token token ,
130+ int indentationLevel )
131+ {
132+ // TODO Add another constructor for correction extent that takes extent
133+ // TODO handle param block
134+ // TODO handle multiline commands
135+
136+ var corrections = new List < CorrectionExtent > ( ) ;
137+ corrections . Add ( new CorrectionExtent (
138+ token . Extent . StartLineNumber ,
139+ token . Extent . EndLineNumber ,
140+ 1 ,
141+ token . Extent . EndColumnNumber ,
142+ GetIndentationString ( indentationLevel ) + token . Extent . Text ,
143+ token . Extent . File ) ) ;
144+ return corrections ;
145+ }
146+
132147 private static int ClipNegative ( int x )
133148 {
134149 return x > 0 ? x : 0 ;
@@ -144,9 +159,14 @@ private int GetIndentation(int indentationLevel)
144159 return indentationLevel * this . unitsPerIndentationLevel ;
145160 }
146161
147- private int GetIndentationLevel ( Stack < int > openBracePosStack )
162+ private char GetIndentationChar ( )
163+ {
164+ return indentationKind == IndentationKind . Space ? ' ' : '\t ' ;
165+ }
166+
167+ private string GetIndentationString ( int indentationLevel )
148168 {
149- return openBracePosStack . Count ;
169+ return new string ( GetIndentationChar ( ) , GetIndentation ( indentationLevel ) ) ;
150170 }
151171
152172 /// <summary>
0 commit comments