1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.indentation;
21
22 import java.util.ArrayDeque;
23 import java.util.Deque;
24 import java.util.Locale;
25
26 import com.puppycrawl.tools.checkstyle.StatelessCheck;
27 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
28 import com.puppycrawl.tools.checkstyle.api.DetailAST;
29 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
30 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
31 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
32
33
34
35
36
37
38
39
40
41
42
43
44 @StatelessCheck
45 public class CommentsIndentationCheck extends AbstractCheck {
46
47
48
49
50 public static final String MSG_KEY_SINGLE = "comments.indentation.single";
51
52
53
54
55 public static final String MSG_KEY_BLOCK = "comments.indentation.block";
56
57 @Override
58 public int[] getDefaultTokens() {
59 return new int[] {
60 TokenTypes.SINGLE_LINE_COMMENT,
61 TokenTypes.BLOCK_COMMENT_BEGIN,
62 };
63 }
64
65 @Override
66 public int[] getAcceptableTokens() {
67 return new int[] {
68 TokenTypes.SINGLE_LINE_COMMENT,
69 TokenTypes.BLOCK_COMMENT_BEGIN,
70 };
71 }
72
73 @Override
74 public int[] getRequiredTokens() {
75 return CommonUtil.EMPTY_INT_ARRAY;
76 }
77
78 @Override
79 public boolean isCommentNodesRequired() {
80 return true;
81 }
82
83 @Override
84 public void visitToken(DetailAST commentAst) {
85 switch (commentAst.getType()) {
86 case TokenTypes.SINGLE_LINE_COMMENT, TokenTypes.BLOCK_COMMENT_BEGIN ->
87 visitComment(commentAst);
88
89 default -> {
90 final String exceptionMsg = "Unexpected token type: " + commentAst.getText();
91 throw new IllegalArgumentException(exceptionMsg);
92 }
93 }
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 private void visitComment(DetailAST comment) {
111 if (!isTrailingComment(comment)) {
112 final DetailAST prevStmt = getPreviousStatement(comment);
113 final DetailAST nextStmt = getNextStmt(comment);
114
115 if (isInEmptyCaseBlock(prevStmt, nextStmt)) {
116 handleCommentInEmptyCaseBlock(prevStmt, comment, nextStmt);
117 }
118 else if (isFallThroughComment(prevStmt, nextStmt)) {
119 handleFallThroughComment(prevStmt, comment, nextStmt);
120 }
121 else if (isInEmptyCodeBlock(prevStmt, nextStmt)) {
122 handleCommentInEmptyCodeBlock(comment, nextStmt);
123 }
124 else if (isCommentAtTheEndOfTheCodeBlock(nextStmt)) {
125 handleCommentAtTheEndOfTheCodeBlock(prevStmt, comment, nextStmt);
126 }
127 else if (nextStmt != null && !areSameLevelIndented(comment, nextStmt, nextStmt)
128 && !areInSameMethodCallWithSameIndent(comment)) {
129 log(comment, getMessageKey(comment), nextStmt.getLineNo(),
130 comment.getColumnNo(), nextStmt.getColumnNo());
131 }
132 }
133 }
134
135
136
137
138
139
140
141 private static DetailAST getNextStmt(DetailAST comment) {
142 DetailAST nextStmt = comment.getNextSibling();
143 while (nextStmt != null
144 && isComment(nextStmt)
145 && comment.getColumnNo() != nextStmt.getColumnNo()) {
146 nextStmt = nextStmt.getNextSibling();
147 }
148 return nextStmt;
149 }
150
151
152
153
154
155
156
157 private DetailAST getPreviousStatement(DetailAST comment) {
158 final DetailAST prevStatement;
159 if (isDistributedPreviousStatement(comment)) {
160 prevStatement = getDistributedPreviousStatement(comment);
161 }
162 else {
163 prevStatement = getOneLinePreviousStatement(comment);
164 }
165 return prevStatement;
166 }
167
168
169
170
171
172
173
174 private boolean isDistributedPreviousStatement(DetailAST comment) {
175 final DetailAST previousSibling = comment.getPreviousSibling();
176 return isDistributedExpression(comment)
177 || isDistributedReturnStatement(previousSibling)
178 || isDistributedThrowStatement(previousSibling);
179 }
180
181
182
183
184
185
186
187
188 private boolean isDistributedExpression(DetailAST comment) {
189 DetailAST previousSibling = comment.getPreviousSibling();
190 while (previousSibling != null && isComment(previousSibling)) {
191 previousSibling = previousSibling.getPreviousSibling();
192 }
193 boolean isDistributed = false;
194 if (previousSibling != null) {
195 if (previousSibling.getType() == TokenTypes.SEMI
196 && isOnPreviousLineIgnoringComments(comment, previousSibling)) {
197 DetailAST currentToken = previousSibling.getPreviousSibling();
198 while (currentToken.getFirstChild() != null) {
199 currentToken = currentToken.getFirstChild();
200 }
201 if (!TokenUtil.areOnSameLine(previousSibling, currentToken)) {
202 isDistributed = true;
203 }
204 }
205 else {
206 isDistributed = isStatementWithPossibleCurlies(previousSibling);
207 }
208 }
209 return isDistributed;
210 }
211
212
213
214
215
216
217
218 private static boolean isStatementWithPossibleCurlies(DetailAST previousSibling) {
219 return previousSibling.getType() == TokenTypes.LITERAL_IF
220 || previousSibling.getType() == TokenTypes.LITERAL_TRY
221 || previousSibling.getType() == TokenTypes.LITERAL_FOR
222 || previousSibling.getType() == TokenTypes.LITERAL_DO
223 || previousSibling.getType() == TokenTypes.LITERAL_WHILE
224 || previousSibling.getType() == TokenTypes.LITERAL_SWITCH
225 || isDefinition(previousSibling);
226 }
227
228
229
230
231
232
233
234 private static boolean isDefinition(DetailAST previousSibling) {
235 return TokenUtil.isTypeDeclaration(previousSibling.getType())
236 || previousSibling.getType() == TokenTypes.METHOD_DEF;
237 }
238
239
240
241
242
243
244
245 private static boolean isDistributedReturnStatement(DetailAST commentPreviousSibling) {
246 boolean isDistributed = false;
247 if (commentPreviousSibling != null
248 && commentPreviousSibling.getType() == TokenTypes.LITERAL_RETURN) {
249 final DetailAST firstChild = commentPreviousSibling.getFirstChild();
250 final DetailAST nextSibling = firstChild.getNextSibling();
251 if (nextSibling != null) {
252 isDistributed = true;
253 }
254 }
255 return isDistributed;
256 }
257
258
259
260
261
262
263
264 private static boolean isDistributedThrowStatement(DetailAST commentPreviousSibling) {
265 boolean isDistributed = false;
266 if (commentPreviousSibling != null
267 && commentPreviousSibling.getType() == TokenTypes.LITERAL_THROW) {
268 final DetailAST firstChild = commentPreviousSibling.getFirstChild();
269 final DetailAST nextSibling = firstChild.getNextSibling();
270 if (!TokenUtil.areOnSameLine(nextSibling, commentPreviousSibling)) {
271 isDistributed = true;
272 }
273 }
274 return isDistributed;
275 }
276
277
278
279
280
281
282
283 private static DetailAST getDistributedPreviousStatement(DetailAST comment) {
284 DetailAST currentToken = comment.getPreviousSibling();
285 while (isComment(currentToken)) {
286 currentToken = currentToken.getPreviousSibling();
287 }
288 final DetailAST previousStatement;
289 if (currentToken.getType() == TokenTypes.SEMI) {
290 currentToken = currentToken.getPreviousSibling();
291 while (currentToken.getFirstChild() != null) {
292 if (isComment(currentToken)) {
293 currentToken = currentToken.getNextSibling();
294 }
295 else {
296 currentToken = currentToken.getFirstChild();
297 }
298 }
299 previousStatement = currentToken;
300 }
301 else {
302 previousStatement = currentToken;
303 }
304 return previousStatement;
305 }
306
307
308
309
310
311
312
313
314 private static boolean isInEmptyCaseBlock(DetailAST prevStmt, DetailAST nextStmt) {
315 return prevStmt != null
316 && nextStmt != null
317 && (prevStmt.getType() == TokenTypes.LITERAL_CASE
318 || prevStmt.getType() == TokenTypes.CASE_GROUP)
319 && (nextStmt.getType() == TokenTypes.LITERAL_CASE
320 || nextStmt.getType() == TokenTypes.LITERAL_DEFAULT);
321 }
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344 private static boolean isFallThroughComment(DetailAST prevStmt, DetailAST nextStmt) {
345 return prevStmt != null
346 && nextStmt != null
347 && prevStmt.getType() != TokenTypes.LITERAL_CASE
348 && (nextStmt.getType() == TokenTypes.LITERAL_CASE
349 || nextStmt.getType() == TokenTypes.LITERAL_DEFAULT);
350 }
351
352
353
354
355
356
357
358 private static boolean isCommentAtTheEndOfTheCodeBlock(DetailAST nextStmt) {
359 return nextStmt != null
360 && nextStmt.getType() == TokenTypes.RCURLY;
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380 private static boolean isInEmptyCodeBlock(DetailAST prevStmt, DetailAST nextStmt) {
381 return prevStmt != null
382 && nextStmt != null
383 && (prevStmt.getType() == TokenTypes.SLIST
384 || prevStmt.getType() == TokenTypes.LCURLY
385 || prevStmt.getType() == TokenTypes.ARRAY_INIT
386 || prevStmt.getType() == TokenTypes.OBJBLOCK)
387 && nextStmt.getType() == TokenTypes.RCURLY;
388 }
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412 private void handleCommentInEmptyCaseBlock(DetailAST prevStmt, DetailAST comment,
413 DetailAST nextStmt) {
414 if (comment.getColumnNo() < prevStmt.getColumnNo()
415 || comment.getColumnNo() < nextStmt.getColumnNo()) {
416 logMultilineIndentation(prevStmt, comment, nextStmt);
417 }
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456 private void handleFallThroughComment(DetailAST prevStmt, DetailAST comment,
457 DetailAST nextStmt) {
458 if (!areSameLevelIndented(comment, prevStmt, nextStmt)) {
459 logMultilineIndentation(prevStmt, comment, nextStmt);
460 }
461 }
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481 private void handleCommentAtTheEndOfTheCodeBlock(DetailAST prevStmt, DetailAST comment,
482 DetailAST nextStmt) {
483 if (prevStmt != null) {
484 if (prevStmt.getType() == TokenTypes.LITERAL_CASE
485 || prevStmt.getType() == TokenTypes.CASE_GROUP
486 || prevStmt.getType() == TokenTypes.LITERAL_DEFAULT) {
487 if (comment.getColumnNo() < nextStmt.getColumnNo()) {
488 log(comment, getMessageKey(comment), nextStmt.getLineNo(),
489 comment.getColumnNo(), nextStmt.getColumnNo());
490 }
491 }
492 else if (isCommentForMultiblock(nextStmt)) {
493 if (!areSameLevelIndented(comment, prevStmt, nextStmt)) {
494 logMultilineIndentation(prevStmt, comment, nextStmt);
495 }
496 }
497 else if (!areSameLevelIndented(comment, prevStmt, prevStmt)) {
498 final int prevStmtLineNo = prevStmt.getLineNo();
499 log(comment, getMessageKey(comment), prevStmtLineNo,
500 comment.getColumnNo(), getLineStart(prevStmtLineNo));
501 }
502 }
503 }
504
505
506
507
508
509
510
511
512 private static boolean isCommentForMultiblock(DetailAST endBlockStmt) {
513 final DetailAST nextBlock = endBlockStmt.getParent().getNextSibling();
514 final int endBlockLineNo = endBlockStmt.getLineNo();
515 final DetailAST catchAst = endBlockStmt.getParent().getParent();
516 final DetailAST finallyAst = catchAst.getNextSibling();
517 return nextBlock != null && nextBlock.getLineNo() == endBlockLineNo
518 || finallyAst != null
519 && catchAst.getType() == TokenTypes.LITERAL_CATCH
520 && finallyAst.getLineNo() == endBlockLineNo;
521 }
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542 private void handleCommentInEmptyCodeBlock(DetailAST comment, DetailAST nextStmt) {
543 if (comment.getColumnNo() < nextStmt.getColumnNo()) {
544 log(comment, getMessageKey(comment), nextStmt.getLineNo(),
545 comment.getColumnNo(), nextStmt.getColumnNo());
546 }
547 }
548
549
550
551
552
553
554
555
556
557
558 private DetailAST getOneLinePreviousStatement(DetailAST comment) {
559 DetailAST root = comment.getParent();
560 while (root != null && !isBlockStart(root)) {
561 root = root.getParent();
562 }
563
564 final Deque<DetailAST> stack = new ArrayDeque<>();
565 DetailAST previousStatement = null;
566 while (root != null || !stack.isEmpty()) {
567 if (!stack.isEmpty()) {
568 root = stack.pop();
569 }
570 while (root != null) {
571 previousStatement = findPreviousStatement(comment, root);
572 if (previousStatement != null) {
573 root = null;
574 stack.clear();
575 break;
576 }
577 if (root.getNextSibling() != null) {
578 stack.push(root.getNextSibling());
579 }
580 root = root.getFirstChild();
581 }
582 }
583 return previousStatement;
584 }
585
586
587
588
589
590
591
592 private static boolean isComment(DetailAST ast) {
593 final int astType = ast.getType();
594 return astType == TokenTypes.SINGLE_LINE_COMMENT
595 || astType == TokenTypes.BLOCK_COMMENT_BEGIN
596 || astType == TokenTypes.COMMENT_CONTENT
597 || astType == TokenTypes.BLOCK_COMMENT_END;
598 }
599
600
601
602
603
604
605
606 private static boolean isBlockStart(DetailAST root) {
607 return root.getType() == TokenTypes.SLIST
608 || root.getType() == TokenTypes.OBJBLOCK
609 || root.getType() == TokenTypes.ARRAY_INIT
610 || root.getType() == TokenTypes.CASE_GROUP;
611 }
612
613
614
615
616
617
618
619
620
621 private DetailAST findPreviousStatement(DetailAST comment, DetailAST root) {
622 DetailAST previousStatement = null;
623 if (root.getLineNo() >= comment.getLineNo()) {
624
625
626 previousStatement = getPrevStatementFromSwitchBlock(comment);
627 }
628 final DetailAST tokenWhichBeginsTheLine;
629 if (root.getType() == TokenTypes.EXPR
630 && root.getFirstChild().getFirstChild() != null) {
631 if (root.getFirstChild().getType() == TokenTypes.LITERAL_NEW) {
632 tokenWhichBeginsTheLine = root.getFirstChild();
633 }
634 else {
635 tokenWhichBeginsTheLine = findTokenWhichBeginsTheLine(root);
636 }
637 }
638 else if (root.getType() == TokenTypes.PLUS) {
639 tokenWhichBeginsTheLine = root.getFirstChild();
640 }
641 else {
642 tokenWhichBeginsTheLine = root;
643 }
644 if (tokenWhichBeginsTheLine != null
645 && !isComment(tokenWhichBeginsTheLine)
646 && isOnPreviousLineIgnoringComments(comment, tokenWhichBeginsTheLine)) {
647 previousStatement = tokenWhichBeginsTheLine;
648 }
649 return previousStatement;
650 }
651
652
653
654
655
656
657
658 private static DetailAST findTokenWhichBeginsTheLine(DetailAST root) {
659 final DetailAST tokenWhichBeginsTheLine;
660 if (isUsingOfObjectReferenceToInvokeMethod(root)) {
661 tokenWhichBeginsTheLine = findStartTokenOfMethodCallChain(root);
662 }
663 else {
664 tokenWhichBeginsTheLine = root.getFirstChild().findFirstToken(TokenTypes.IDENT);
665 }
666 return tokenWhichBeginsTheLine;
667 }
668
669
670
671
672
673
674
675 private static boolean isUsingOfObjectReferenceToInvokeMethod(DetailAST root) {
676 return root.getFirstChild().getFirstChild().getFirstChild() != null
677 && root.getFirstChild().getFirstChild().getFirstChild().getNextSibling() != null;
678 }
679
680
681
682
683
684
685
686 private static DetailAST findStartTokenOfMethodCallChain(DetailAST root) {
687 DetailAST startOfMethodCallChain = root;
688 while (startOfMethodCallChain.getFirstChild() != null
689 && TokenUtil.areOnSameLine(startOfMethodCallChain.getFirstChild(), root)) {
690 startOfMethodCallChain = startOfMethodCallChain.getFirstChild();
691 }
692 if (startOfMethodCallChain.getFirstChild() != null) {
693 startOfMethodCallChain = startOfMethodCallChain.getFirstChild().getNextSibling();
694 }
695 return startOfMethodCallChain;
696 }
697
698
699
700
701
702
703
704
705
706
707 private boolean isOnPreviousLineIgnoringComments(DetailAST currentStatement,
708 DetailAST checkedStatement) {
709 DetailAST nextToken = getNextToken(checkedStatement);
710 int distanceAim = 1;
711 if (nextToken != null && isComment(nextToken)) {
712 distanceAim += countEmptyLines(checkedStatement, currentStatement);
713 }
714
715 while (nextToken != null && nextToken != currentStatement && isComment(nextToken)) {
716 if (nextToken.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) {
717 distanceAim += nextToken.getLastChild().getLineNo() - nextToken.getLineNo();
718 }
719 distanceAim++;
720 nextToken = nextToken.getNextSibling();
721 }
722 return currentStatement.getLineNo() - checkedStatement.getLineNo() == distanceAim;
723 }
724
725
726
727
728
729
730
731 private DetailAST getNextToken(DetailAST checkedStatement) {
732 DetailAST nextToken;
733 if (checkedStatement.getType() == TokenTypes.SLIST
734 || checkedStatement.getType() == TokenTypes.ARRAY_INIT
735 || checkedStatement.getType() == TokenTypes.CASE_GROUP) {
736 nextToken = checkedStatement.getFirstChild();
737 }
738 else {
739 nextToken = checkedStatement.getNextSibling();
740 }
741 if (nextToken != null && isComment(nextToken) && isTrailingComment(nextToken)) {
742 nextToken = nextToken.getNextSibling();
743 }
744 return nextToken;
745 }
746
747
748
749
750
751
752
753
754 private int countEmptyLines(DetailAST startStatement, DetailAST endStatement) {
755 int emptyLinesNumber = 0;
756 final String[] lines = getLines();
757 final int endLineNo = endStatement.getLineNo();
758 for (int lineNo = startStatement.getLineNo(); lineNo < endLineNo; lineNo++) {
759 if (CommonUtil.isBlank(lines[lineNo])) {
760 emptyLinesNumber++;
761 }
762 }
763 return emptyLinesNumber;
764 }
765
766
767
768
769
770
771
772
773 private void logMultilineIndentation(DetailAST prevStmt, DetailAST comment,
774 DetailAST nextStmt) {
775 final String multilineNoTemplate = "%d, %d";
776 log(comment, getMessageKey(comment),
777 String.format(Locale.getDefault(), multilineNoTemplate, prevStmt.getLineNo(),
778 nextStmt.getLineNo()), comment.getColumnNo(),
779 String.format(Locale.getDefault(), multilineNoTemplate,
780 getLineStart(prevStmt.getLineNo()), getLineStart(nextStmt.getLineNo())));
781 }
782
783
784
785
786
787
788
789 private static String getMessageKey(DetailAST comment) {
790 final String msgKey;
791 if (comment.getType() == TokenTypes.SINGLE_LINE_COMMENT) {
792 msgKey = MSG_KEY_SINGLE;
793 }
794 else {
795 msgKey = MSG_KEY_BLOCK;
796 }
797 return msgKey;
798 }
799
800
801
802
803
804
805
806 private static DetailAST getPrevStatementFromSwitchBlock(DetailAST comment) {
807 final DetailAST prevStmt;
808 final DetailAST parentStatement = comment.getParent();
809 if (parentStatement.getType() == TokenTypes.CASE_GROUP) {
810 prevStmt = getPrevStatementWhenCommentIsUnderCase(parentStatement);
811 }
812 else {
813 prevStmt = getPrevCaseToken(parentStatement);
814 }
815 return prevStmt;
816 }
817
818
819
820
821
822
823
824 private static DetailAST getPrevStatementWhenCommentIsUnderCase(DetailAST parentStatement) {
825 DetailAST prevStmt = null;
826 final DetailAST prevBlock = parentStatement.getPreviousSibling();
827 if (prevBlock.getLastChild() != null) {
828 DetailAST blockBody = prevBlock.getLastChild().getLastChild();
829 if (blockBody.getType() == TokenTypes.SEMI) {
830 blockBody = blockBody.getPreviousSibling();
831 }
832 if (blockBody.getType() == TokenTypes.EXPR) {
833 if (isUsingOfObjectReferenceToInvokeMethod(blockBody)) {
834 prevStmt = findStartTokenOfMethodCallChain(blockBody);
835 }
836 else {
837 prevStmt = blockBody.getFirstChild().getFirstChild();
838 }
839 }
840 else {
841 if (blockBody.getType() == TokenTypes.SLIST) {
842 prevStmt = blockBody.getParent().getParent();
843 }
844 else {
845 prevStmt = blockBody;
846 }
847 }
848 if (isComment(prevStmt)) {
849 prevStmt = prevStmt.getNextSibling();
850 }
851 }
852 return prevStmt;
853 }
854
855
856
857
858
859
860
861 private static DetailAST getPrevCaseToken(DetailAST parentStatement) {
862 final DetailAST prevCaseToken;
863 final DetailAST parentBlock = parentStatement.getParent();
864 if (parentBlock.getParent().getPreviousSibling() != null
865 && parentBlock.getParent().getPreviousSibling().getType()
866 == TokenTypes.LITERAL_CASE) {
867 prevCaseToken = parentBlock.getParent().getPreviousSibling();
868 }
869 else {
870 prevCaseToken = null;
871 }
872 return prevCaseToken;
873 }
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897 private boolean areSameLevelIndented(DetailAST comment, DetailAST prevStmt,
898 DetailAST nextStmt) {
899 return comment.getColumnNo() == getLineStart(nextStmt.getLineNo())
900 || comment.getColumnNo() == getLineStart(prevStmt.getLineNo());
901 }
902
903
904
905
906
907
908
909 private int getLineStart(int lineNo) {
910 final char[] line = getLines()[lineNo - 1].toCharArray();
911 int lineStart = 0;
912 while (Character.isWhitespace(line[lineStart])) {
913 lineStart++;
914 }
915 return lineStart;
916 }
917
918
919
920
921
922
923
924 private boolean isTrailingComment(DetailAST comment) {
925 final boolean isTrailingComment;
926 if (comment.getType() == TokenTypes.SINGLE_LINE_COMMENT) {
927 isTrailingComment = isTrailingSingleLineComment(comment);
928 }
929 else {
930 isTrailingComment = isTrailingBlockComment(comment);
931 }
932 return isTrailingComment;
933 }
934
935
936
937
938
939
940
941
942
943
944
945
946
947 private boolean isTrailingSingleLineComment(DetailAST singleLineComment) {
948 final String targetSourceLine = getLine(singleLineComment.getLineNo() - 1);
949 final int commentColumnNo = singleLineComment.getColumnNo();
950 return !CommonUtil.hasWhitespaceBefore(commentColumnNo, targetSourceLine);
951 }
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966 private boolean isTrailingBlockComment(DetailAST blockComment) {
967 final String commentLine = getLine(blockComment.getLineNo() - 1);
968 final int commentColumnNo = blockComment.getColumnNo();
969 final DetailAST nextSibling = blockComment.getNextSibling();
970 return !CommonUtil.hasWhitespaceBefore(commentColumnNo, commentLine)
971 || nextSibling != null && TokenUtil.areOnSameLine(nextSibling, blockComment);
972 }
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993 private static boolean areInSameMethodCallWithSameIndent(DetailAST comment) {
994 return comment.getParent().getType() == TokenTypes.METHOD_CALL
995 && comment.getColumnNo()
996 == getFirstExpressionNodeFromMethodCall(comment.getParent()).getColumnNo();
997 }
998
999
1000
1001
1002
1003
1004
1005 private static DetailAST getFirstExpressionNodeFromMethodCall(DetailAST methodCall) {
1006
1007 return methodCall.findFirstToken(TokenTypes.ELIST);
1008 }
1009
1010 }