@@ -10,11 +10,12 @@ namespace Rubberduck.SmartIndenter
10
10
internal class AbsoluteCodeLine
11
11
{
12
12
private const string StupidLineEnding = ": _" ;
13
- private const string StringPlaceholder = "\a " ;
14
- private static readonly Regex StringLiteralRegex = new Regex ( "\" (?:[^\" ]+|\" \" )*\" " ) ;
15
- private static readonly Regex StringReplaceRegex = new Regex ( StringPlaceholder ) ;
13
+ private const char StringPlaceholder = '\a ' ;
14
+ private const char BracketPlaceholder = '\x2 ';
15
+ private static readonly Regex StringReplaceRegex = new Regex ( StringPlaceholder . ToString ( CultureInfo . InvariantCulture ) ) ;
16
+ private static readonly Regex BracketReplaceRegex = new Regex ( BracketPlaceholder . ToString ( CultureInfo . InvariantCulture ) ) ;
16
17
private static readonly Regex LineNumberRegex = new Regex ( @"^(?<number>\d+)\s+(?<code>.*)" , RegexOptions . ExplicitCapture ) ;
17
- private static readonly Regex EndOfLineCommentRegex = new Regex ( @"^(?!(Rem\s)|('))(?<code>. *)(\s(?<comment>'.*))$" , RegexOptions . ExplicitCapture ) ;
18
+ private static readonly Regex EndOfLineCommentRegex = new Regex ( @"^(?!(Rem\s)|('))(?<code>[^'] *)(\s(?<comment>'.*))$" , RegexOptions . ExplicitCapture ) ;
18
19
private static readonly Regex ProcedureStartRegex = new Regex ( @"^(Public\s|Private\s|Friend\s)?(Static\s)?(Sub|Function|Property\s(Let|Get|Set))\s" ) ;
19
20
private static readonly Regex ProcedureStartIgnoreRegex = new Regex ( @"^[LR]?Set\s|^Let\s|^(Public|Private)\sDeclare\s(Function|Sub)" ) ;
20
21
private static readonly Regex ProcedureEndRegex = new Regex ( @"^End\s(Sub|Function|Property)" ) ;
@@ -31,9 +32,10 @@ internal class AbsoluteCodeLine
31
32
private uint _lineNumber ;
32
33
private bool _numbered ;
33
34
private string _code ;
34
- private bool _stupidLineEnding ;
35
+ private readonly bool _stupidLineEnding ;
35
36
private readonly string [ ] _segments ;
36
37
private List < string > _strings ;
38
+ private List < string > _brackets ;
37
39
38
40
public AbsoluteCodeLine ( string code , IIndenterSettings settings )
39
41
{
@@ -51,23 +53,69 @@ public AbsoluteCodeLine(string code, IIndenterSettings settings)
51
53
52
54
Original = code ;
53
55
54
- ExtractStringLiterals ( ) ;
56
+ ExtractStringLiteralsAndBrackets ( ) ;
55
57
ExtractLineNumber ( ) ;
56
58
ExtractEndOfLineComment ( ) ;
57
-
59
+ _code = Regex . Replace ( _code , StringPlaceholder + "+" , StringPlaceholder . ToString ( CultureInfo . InvariantCulture ) ) ;
60
+ _code = Regex . Replace ( _code , BracketPlaceholder + "+" , BracketPlaceholder . ToString ( CultureInfo . InvariantCulture ) ) . Trim ( ) ;
58
61
_segments = _code . Split ( new [ ] { ": " } , StringSplitOptions . None ) ;
59
62
}
60
63
61
- private void ExtractStringLiterals ( )
64
+ //TODO: This should be a class.
65
+ private void ExtractStringLiteralsAndBrackets ( )
62
66
{
63
67
_strings = new List < string > ( ) ;
64
- var matches = StringLiteralRegex . Matches ( _code ) ;
65
- if ( matches . Count == 0 ) return ;
66
- foreach ( var match in matches )
68
+ _brackets = new List < string > ( ) ;
69
+
70
+ var chars = _code . ToCharArray ( ) ;
71
+ var quoted = false ;
72
+ var bracketed = false ;
73
+ var ins = 0 ;
74
+ var strpos = 0 ;
75
+ var brkpos = 0 ;
76
+ for ( var c = 0 ; c < chars . Length ; c ++ )
67
77
{
68
- _strings . Add ( match . ToString ( ) ) ;
78
+ if ( chars [ c ] == '"' && ! bracketed )
79
+ {
80
+ if ( ! quoted )
81
+ {
82
+ strpos = c ;
83
+ quoted = true ;
84
+ continue ;
85
+ }
86
+ if ( c + 1 < chars . Length && chars [ c ] == '"' )
87
+ {
88
+ c ++ ;
89
+ }
90
+ quoted = false ;
91
+ _strings . Add ( new string ( chars . Skip ( strpos ) . Take ( c - strpos ) . ToArray ( ) ) ) ;
92
+ for ( var e = strpos ; e < c ; e ++ )
93
+ {
94
+ chars [ e ] = StringPlaceholder ;
95
+ }
96
+ }
97
+ else if ( ! quoted && ! bracketed && chars [ c ] == '[' )
98
+ {
99
+ bracketed = true ;
100
+ brkpos = c ;
101
+ ins ++ ;
102
+ }
103
+ else if ( ! quoted && bracketed && chars [ c ] == ']' )
104
+ {
105
+ ins -- ;
106
+ if ( ins != 0 )
107
+ {
108
+ continue ;
109
+ }
110
+ bracketed = false ;
111
+ _brackets . Add ( new string ( chars . Skip ( brkpos ) . Take ( c - brkpos ) . ToArray ( ) ) ) ;
112
+ for ( var e = brkpos ; e < c ; e ++ )
113
+ {
114
+ chars [ e ] = BracketPlaceholder ;
115
+ }
116
+ }
69
117
}
70
- _code = StringLiteralRegex . Replace ( _code , StringPlaceholder ) ;
118
+ _code = new string ( chars ) ;
71
119
}
72
120
73
121
private void ExtractLineNumber ( )
@@ -77,12 +125,9 @@ private void ExtractLineNumber()
77
125
{
78
126
_numbered = true ;
79
127
_lineNumber = Convert . ToUInt32 ( match . Groups [ "number" ] . Value ) ;
80
- _code = match . Groups [ "code" ] . Value . Trim ( ) ;
81
- }
82
- else
83
- {
84
- _code = _code . Trim ( ) ;
128
+ _code = match . Groups [ "code" ] . Value ;
85
129
}
130
+ _code = _code . Trim ( ) ;
86
131
}
87
132
88
133
private void ExtractEndOfLineComment ( )
@@ -98,7 +143,24 @@ private void ExtractEndOfLineComment()
98
143
}
99
144
100
145
public string Original { get ; private set ; }
101
-
146
+
147
+ public string Escaped
148
+ {
149
+ get
150
+ {
151
+ var output = Original ;
152
+ foreach ( var item in _strings )
153
+ {
154
+ output = output . Replace ( item , new string ( StringPlaceholder , item . Length ) ) ;
155
+ }
156
+ foreach ( var item in _brackets )
157
+ {
158
+ output = output . Replace ( item , new string ( BracketPlaceholder , item . Length ) ) ;
159
+ }
160
+ return output ;
161
+ }
162
+ }
163
+
102
164
public string EndOfLineComment { get ; private set ; }
103
165
104
166
public IEnumerable < string > Segments
@@ -146,7 +208,7 @@ public bool HasContinuation
146
208
147
209
public bool IsPrecompilerDirective
148
210
{
149
- get { return Original . TrimStart ( ) . StartsWith ( "#" ) ; }
211
+ get { return _code . TrimStart ( ) . StartsWith ( "#" ) ; }
150
212
}
151
213
152
214
public bool IsBareDebugStatement
@@ -248,6 +310,10 @@ public string Indent(int indents, bool atProcStart, bool absolute = false)
248
310
{
249
311
code = _strings . Aggregate ( code , ( current , literal ) => StringReplaceRegex . Replace ( current , literal , 1 ) ) ;
250
312
}
313
+ if ( _brackets . Any ( ) )
314
+ {
315
+ code = _brackets . Aggregate ( code , ( current , expr ) => BracketReplaceRegex . Replace ( current , expr , 1 ) ) ;
316
+ }
251
317
252
318
code = string . Join ( string . Empty , number , new string ( ' ' , gap ) , code ) ;
253
319
if ( string . IsNullOrEmpty ( EndOfLineComment ) )
@@ -283,10 +349,20 @@ public override string ToString()
283
349
}
284
350
285
351
private void AlignDims ( int postition )
286
- {
352
+ {
353
+ if ( _segments [ 0 ] . Trim ( ) . StartsWith ( "As " ) )
354
+ {
355
+ _segments [ 0 ] = string . Format ( "{0}{1}" , new String ( ' ' , _settings . AlignDimColumn - postition - 1 ) , _segments [ 0 ] . Trim ( ) ) ;
356
+ return ;
357
+ }
287
358
var alignTokens = _segments [ 0 ] . Split ( new [ ] { " As " } , StringSplitOptions . None ) ;
359
+ if ( alignTokens . Length <= 1 )
360
+ {
361
+ return ;
362
+ }
288
363
var gap = Math . Max ( _settings . AlignDimColumn - postition - alignTokens [ 0 ] . Length - 2 , 0 ) ;
289
- _segments [ 0 ] = string . Format ( "{0}{1} As {2}" , alignTokens [ 0 ] . Trim ( ) , new string ( ' ' , gap ) , string . Join ( " As " , alignTokens . Skip ( 1 ) ) ) ;
364
+ _segments [ 0 ] = string . Format ( "{0}{1} As {2}" , alignTokens [ 0 ] . Trim ( ) , new string ( ' ' , gap ) ,
365
+ string . Join ( " As " , alignTokens . Skip ( 1 ) ) ) ;
290
366
}
291
367
}
292
368
}
0 commit comments