1
2
3
4
5 package com.qulice.checkstyle;
6
7 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
8 import com.puppycrawl.tools.checkstyle.api.DetailAST;
9 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
10 import java.util.ArrayList;
11 import java.util.List;
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public final class StringLiteralsConcatenationCheck extends AbstractCheck {
37
38
39
40
41 public StringLiteralsConcatenationCheck() {
42
43 }
44
45 @Override
46 public int[] getDefaultTokens() {
47 return new int[] {TokenTypes.OBJBLOCK};
48 }
49
50 @Override
51 public int[] getAcceptableTokens() {
52 return this.getDefaultTokens();
53 }
54
55 @Override
56 public int[] getRequiredTokens() {
57 return this.getDefaultTokens();
58 }
59
60 @Override
61 public void visitToken(final DetailAST ast) {
62 final List<DetailAST> pluses = this.findChildAstsOfType(
63 ast,
64 TokenTypes.PLUS,
65 TokenTypes.PLUS_ASSIGN
66 );
67 for (final DetailAST plus : pluses) {
68 if (this.hasStringLiteralOperand(plus)) {
69 this.log(plus, "Concatenation of string literals prohibited");
70 }
71 }
72 }
73
74 private List<DetailAST> findChildAstsOfType(final DetailAST tree,
75 final int... types) {
76 final List<DetailAST> children = new ArrayList<>(0);
77 DetailAST child = tree.getFirstChild();
78 while (child != null) {
79 if (StringLiteralsConcatenationCheck.isOfType(child, types)) {
80 children.add(child);
81 } else {
82 children.addAll(this.findChildAstsOfType(child, types));
83 }
84 child = child.getNextSibling();
85 }
86 return children;
87 }
88
89 private boolean hasStringLiteralOperand(final DetailAST node) {
90 boolean found = false;
91 DetailAST child = node.getFirstChild();
92 while (child != null) {
93 final int type = child.getType();
94 if (type == TokenTypes.STRING_LITERAL) {
95 found = true;
96 break;
97 }
98 if ((type == TokenTypes.PLUS || type == TokenTypes.PLUS_ASSIGN)
99 && this.hasStringLiteralOperand(child)) {
100 found = true;
101 break;
102 }
103 child = child.getNextSibling();
104 }
105 return found;
106 }
107
108 private static boolean isOfType(final DetailAST ast, final int... types) {
109 boolean yes = false;
110 for (final int type : types) {
111 if (ast.getType() == type) {
112 yes = true;
113 break;
114 }
115 }
116 return yes;
117 }
118 }