@@ -3,37 +3,124 @@ package checkstyle.checks.whitespace;
33@ignore (" base class line based whitespace checks" )
44class LineCheckBase extends Check {
55
6- var quotesRE : EReg ;
7- var multilineStartRE : EReg ;
8- var escapeRE : EReg ;
9- var multilineStringStart : Bool ;
6+ var currentState : RangeType ;
7+ var skipOverInitialQuote : Bool ;
8+
9+ var commentStartRE : EReg ;
10+ var commentBlockEndRE : EReg ;
11+ var stringStartRE : EReg ;
12+ var stringInterpolatedEndRE : EReg ;
13+ var stringLiteralEndRE : EReg ;
1014
1115 public function new () {
1216 super (LINE );
13- quotesRE = ~/ ('| ")/ ;
14- multilineStartRE = null ;
15- escapeRE = null ;
16- multilineStringStart = false ;
17+
18+ commentStartRE = ~/ \/ ([\/ *] )/ ;
19+ commentBlockEndRE = ~/ \*\/ / ;
20+ stringStartRE = ~/ ['"] / ;
21+ stringInterpolatedEndRE = ~/ (? <!\\ )'/ ;
22+ stringLiteralEndRE = ~/ (? <!\\ )"/ ;
1723 }
1824
1925 override public function run (checker : Checker ): Array <CheckMessage > {
20- multilineStringStart = false ;
26+ currentState = TEXT ;
27+ skipOverInitialQuote = false ;
2128 return super .run (checker );
2229 }
2330
24- function isMultineString (line : String ): Bool {
25- if (! multilineStringStart && quotesRE .match (line )) {
26- var matched = quotesRE .matched (0 );
27- var matchedRight = quotesRE .matchedRight ();
28- multilineStartRE = new EReg (matched , " " );
29- escapeRE = new EReg (" \\ " + matched , " " );
30- multilineStringStart = ! multilineStartRE .match (matchedRight ) && ! escapeRE .match (matchedRight );
31+ function getRanges (line : String ): Array <Range > {
32+ var ranges = [];
33+ var currentStart = 0 ;
34+ while (currentStart < line .length ) {
35+ currentStart = switch (currentState ) {
36+ case TEXT : handleTextState (line , ranges , currentStart );
37+ case COMMENT (isBlock ): handleCommentState (line , ranges , currentStart , isBlock );
38+ case STRING (isInterpolated ): handleStringState (line , ranges , currentStart , isInterpolated );
39+ };
40+ }
41+ if (line .length == 0 ) ranges .push ({ type : currentState , start : 0 , end : 0 });
42+ return ranges ;
43+ }
44+
45+ function handleTextState (line : String , ranges : Array <Range >, currentStart : Int ): Int {
46+ var foundCommentStart = commentStartRE .matchSub (line , currentStart );
47+ var commentStart = foundCommentStart ? commentStartRE .matchedPos ().pos : line .length ;
48+ var foundStringStart = stringStartRE .matchSub (line , currentStart );
49+ var stringStart = foundStringStart ? stringStartRE .matchedPos ().pos : line .length ;
50+
51+ if (foundCommentStart && commentStart < stringStart ) {
52+ if (commentStart > currentStart ) {
53+ ranges .push ({ type : currentState , start : currentStart , end : commentStart });
54+ }
55+
56+ currentState = COMMENT (commentStartRE .matched (1 ) == " *" );
57+ return commentStart ;
58+ }
59+ else if (foundStringStart && stringStart < commentStart ) {
60+ if (stringStart > currentStart ) {
61+ ranges .push ({ type : currentState , start : currentStart , end : stringStart });
62+ }
63+
64+ skipOverInitialQuote = true ;
65+ currentState = STRING (stringStartRE .matched (0 ) == " '" );
66+ return stringStart ;
67+ }
68+ else {
69+ ranges .push ({ type : currentState , start : currentStart , end : line .length });
70+
71+ return line .length ;
72+ }
73+ }
74+
75+ function handleCommentState (line : String , ranges : Array <Range >, currentStart : Int , isBlock : Bool ): Int {
76+ if (isBlock && commentBlockEndRE .matchSub (line , currentStart )) {
77+ var commentEnd = commentBlockEndRE .matchedPos ().pos + 2 ;
78+ ranges .push ({ type : currentState , start : currentStart , end : commentEnd });
79+
80+ currentState = TEXT ;
81+ return commentEnd ;
82+ }
83+ else {
84+ ranges .push ({ type : currentState , start : currentStart , end : line .length });
85+
86+ if (! isBlock ) currentState = TEXT ;
87+ return line .length ;
88+ }
89+ }
90+
91+ function handleStringState (line : String , ranges : Array <Range >, currentStart : Int , isInterpolated : Bool ): Int {
92+ var adjustedStart = currentStart + (skipOverInitialQuote ? 1 : 0 );
93+ skipOverInitialQuote = false ;
94+ if (isInterpolated && stringInterpolatedEndRE .matchSub (line , adjustedStart )) {
95+ var stringEnd = stringInterpolatedEndRE .matchedPos ().pos + 1 ;
96+ ranges .push ({ type : currentState , start : currentStart , end : stringEnd });
97+
98+ currentState = TEXT ;
99+ return stringEnd ;
100+ }
101+ else if (! isInterpolated && stringLiteralEndRE .matchSub (line , adjustedStart )) {
102+ var stringEnd = stringLiteralEndRE .matchedPos ().pos + 1 ;
103+ ranges .push ({ type : currentState , start : currentStart , end : stringEnd });
104+
105+ currentState = TEXT ;
106+ return stringEnd ;
31107 }
32- else if ( multilineStringStart && multilineStartRE != null && multilineStartRE . match ( line ) && ! escapeRE . match ( line )) {
33- multilineStringStart = false ;
34- multilineStartRE = null ;
35- escapeRE = null ;
108+ else {
109+ ranges . push ({ type : currentState , start : currentStart , end : line . length }) ;
110+
111+ return line . length ;
36112 }
37- return multilineStringStart ;
38113 }
114+ }
115+
116+ enum RangeType {
117+ TEXT ;
118+ COMMENT (isBlock : Bool );
119+ STRING (isInterpolated : Bool );
120+ }
121+
122+ typedef Range = {
123+ var type : RangeType ;
124+ var start : Int ;
125+ var end : Int ;
39126}
0 commit comments