2222import java .util .Collections ;
2323import java .util .List ;
2424import java .util .stream .Collectors ;
25+ import java .util .stream .IntStream ;
2526import org .sonar .check .Rule ;
2627import org .sonar .plugins .communitydelphi .api .ast .CompoundStatementNode ;
2728import org .sonar .plugins .communitydelphi .api .ast .DelphiNode ;
@@ -59,45 +60,34 @@ public DelphiCheckContext visit(RoutineImplementationNode routine, DelphiCheckCo
5960
6061 private static List <QuickFix > getQuickFixes (
6162 DelphiNode violationNode , DelphiCheckContext context ) {
62- DelphiNode statement = violationNode ;
63+ DelphiNode violationStatement = violationNode ;
6364 DelphiNode parent = violationNode .getParent ();
6465 while (!(parent instanceof StatementListNode )) {
65- statement = parent ;
66+ violationStatement = parent ;
6667 parent = parent .getParent ();
6768 if (parent == null ) {
6869 return Collections .emptyList ();
6970 }
7071 }
7172 StatementListNode statementListNode = (StatementListNode ) parent ;
72- int statementIndex = statementListNode .getStatements ().indexOf (statement );
73+ int statementIndex = statementListNode .getStatements ().indexOf (violationStatement );
7374
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 ();
7881
7982 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 ();
8986 } 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 ();
10191 }
10292
10393 return List .of (
@@ -106,17 +96,39 @@ private static List<QuickFix> getQuickFixes(
10696 QuickFixEdit .delete (FilePosition .from (startLine , startCol , endLine , endCol ))));
10797 }
10898
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+
109113 private static boolean isSemicolon (DelphiNode node ) {
110114 return node .getChildren ().isEmpty () && node .getToken ().getType () == DelphiTokenType .SEMICOLON ;
111115 }
112116
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 (
114125 StatementListNode statementListNode , DelphiNode node ) {
115126 return statementListNode .getChildren ().stream ()
116127 .skip (node .getChildIndex () + 1L )
117128 .takeWhile (RedundantInheritedCheck ::isSemicolon )
118129 .reduce ((first , second ) -> second )
119- .orElse (node );
130+ .orElse (node )
131+ .getLastToken ();
120132 }
121133
122134 private static List <DelphiNode > findViolations (RoutineImplementationNode routine ) {
0 commit comments