22
22
import java .util .Collections ;
23
23
import java .util .List ;
24
24
import java .util .stream .Collectors ;
25
+ import java .util .stream .IntStream ;
25
26
import org .sonar .check .Rule ;
26
27
import org .sonar .plugins .communitydelphi .api .ast .CompoundStatementNode ;
27
28
import org .sonar .plugins .communitydelphi .api .ast .DelphiNode ;
@@ -59,45 +60,34 @@ public DelphiCheckContext visit(RoutineImplementationNode routine, DelphiCheckCo
59
60
60
61
private static List <QuickFix > getQuickFixes (
61
62
DelphiNode violationNode , DelphiCheckContext context ) {
62
- DelphiNode statement = violationNode ;
63
+ DelphiNode violationStatement = violationNode ;
63
64
DelphiNode parent = violationNode .getParent ();
64
65
while (!(parent instanceof StatementListNode )) {
65
- statement = parent ;
66
+ violationStatement = parent ;
66
67
parent = parent .getParent ();
67
68
if (parent == null ) {
68
69
return Collections .emptyList ();
69
70
}
70
71
}
71
72
StatementListNode statementListNode = (StatementListNode ) parent ;
72
- int statementIndex = statementListNode .getStatements ().indexOf (statement );
73
+ int statementIndex = statementListNode .getStatements ().indexOf (violationStatement );
73
74
74
- int startLine = statement .getBeginLine ();
75
- int startCol = statement .getBeginColumn ();
76
- int endLine = statement .getEndLine ();
77
- int endCol = statement .getEndColumn ();
75
+ int startLine = violationStatement .getBeginLine ();
76
+ int startCol = violationStatement .getBeginColumn ();
77
+
78
+ DelphiToken lastStatementToken = getLastStatementToken (statementListNode , violationStatement );
79
+ int endLine = lastStatementToken .getEndLine ();
80
+ int endCol = lastStatementToken .getEndColumn ();
78
81
79
82
if (statementListNode .getStatements ().size () > statementIndex + 1 ) {
80
- int tokenIndex = statement .getLastToken ().getIndex () + 1 ;
81
- final List <DelphiTokenType > skipTokenTypes =
82
- List .of (DelphiTokenType .SEMICOLON , DelphiTokenType .WHITESPACE );
83
- while (skipTokenTypes .contains (context .getTokens ().get (tokenIndex ).getType ())) {
84
- tokenIndex ++;
85
- }
86
- DelphiToken statementNode = context .getTokens ().get (tokenIndex );
87
- endLine = statementNode .getBeginLine ();
88
- endCol = statementNode .getBeginColumn ();
83
+ DelphiToken lastDeletableToken = nextNonWhitespaceToken (context , lastStatementToken , true );
84
+ endLine = lastDeletableToken .getBeginLine ();
85
+ endCol = lastDeletableToken .getBeginColumn ();
89
86
} else if (statementIndex > 0 ) {
90
- int tokenIndex = statement .getLastToken ().getIndex () - 1 ;
91
- while (context .getTokens ().get (tokenIndex ).getType () == DelphiTokenType .WHITESPACE ) {
92
- tokenIndex --;
93
- }
94
- DelphiToken statementNode = context .getTokens ().get (tokenIndex );
95
- startLine = statementNode .getEndLine ();
96
- startCol = statementNode .getEndColumn ();
97
- } else {
98
- DelphiNode lastToken = getLastStatementToken (statementListNode , statement );
99
- endLine = lastToken .getEndLine ();
100
- endCol = lastToken .getEndColumn ();
87
+ DelphiToken lastDeletableToken =
88
+ nextNonWhitespaceToken (context , violationStatement .getFirstToken (), false );
89
+ startLine = lastDeletableToken .getEndLine ();
90
+ startCol = lastDeletableToken .getEndColumn ();
101
91
}
102
92
103
93
return List .of (
@@ -106,17 +96,39 @@ private static List<QuickFix> getQuickFixes(
106
96
QuickFixEdit .delete (FilePosition .from (startLine , startCol , endLine , endCol ))));
107
97
}
108
98
99
+ private static DelphiToken nextNonWhitespaceToken (
100
+ DelphiCheckContext context , DelphiToken startingToken , boolean forward ) {
101
+ int step = forward ? 1 : -1 ;
102
+ int contextIndex = getContextIndex (context , startingToken );
103
+ if (contextIndex == -1 ) {
104
+ return startingToken ;
105
+ }
106
+
107
+ do {
108
+ contextIndex += step ;
109
+ } while (context .getTokens ().get (contextIndex ).getType () == DelphiTokenType .WHITESPACE );
110
+ return context .getTokens ().get (contextIndex );
111
+ }
112
+
109
113
private static boolean isSemicolon (DelphiNode node ) {
110
114
return node .getChildren ().isEmpty () && node .getToken ().getType () == DelphiTokenType .SEMICOLON ;
111
115
}
112
116
113
- private static DelphiNode getLastStatementToken (
117
+ private static int getContextIndex (DelphiCheckContext context , DelphiToken token ) {
118
+ return IntStream .range (0 , context .getTokens ().size ())
119
+ .filter (tokenIndex -> context .getTokens ().get (tokenIndex ).getIndex () == token .getIndex ())
120
+ .findFirst ()
121
+ .orElse (-1 );
122
+ }
123
+
124
+ private static DelphiToken getLastStatementToken (
114
125
StatementListNode statementListNode , DelphiNode node ) {
115
126
return statementListNode .getChildren ().stream ()
116
127
.skip (node .getChildIndex () + 1L )
117
128
.takeWhile (RedundantInheritedCheck ::isSemicolon )
118
129
.reduce ((first , second ) -> second )
119
- .orElse (node );
130
+ .orElse (node )
131
+ .getLastToken ();
120
132
}
121
133
122
134
private static List <DelphiNode > findViolations (RoutineImplementationNode routine ) {
0 commit comments