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