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