1 ///////////////////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3 // Copyright (C) 2001-2024 the original author or authors.
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ///////////////////////////////////////////////////////////////////////////////////////////////
19
20 package com.puppycrawl.tools.checkstyle.checks.annotation;
21
22 import com.puppycrawl.tools.checkstyle.StatelessCheck;
23 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
24 import com.puppycrawl.tools.checkstyle.api.DetailAST;
25 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
26 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
27 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
28
29 /**
30 * <div>
31 * Checks that annotations are located on the same line with their targets.
32 * Verifying with this check is not good practice, but it is using by some style guides.
33 * </div>
34 *
35 * <ul>
36 * <li>
37 * Property {@code tokens} - tokens to check
38 * Type is {@code java.lang.String[]}.
39 * Validation type is {@code tokenSet}.
40 * Default value is:
41 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CLASS_DEF">
42 * CLASS_DEF</a>,
43 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#INTERFACE_DEF">
44 * INTERFACE_DEF</a>,
45 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ENUM_DEF">
46 * ENUM_DEF</a>,
47 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#METHOD_DEF">
48 * METHOD_DEF</a>,
49 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CTOR_DEF">
50 * CTOR_DEF</a>,
51 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#VARIABLE_DEF">
52 * VARIABLE_DEF</a>,
53 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#RECORD_DEF">
54 * RECORD_DEF</a>,
55 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#COMPACT_CTOR_DEF">
56 * COMPACT_CTOR_DEF</a>.
57 * </li>
58 * </ul>
59 *
60 * <p>
61 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker}
62 * </p>
63 *
64 * <p>
65 * Violation Message Keys:
66 * </p>
67 * <ul>
68 * <li>
69 * {@code annotation.same.line}
70 * </li>
71 * </ul>
72 *
73 * @since 8.2
74 */
75 @StatelessCheck
76 public class AnnotationOnSameLineCheck extends AbstractCheck {
77
78 /** A key is pointing to the warning message text in "messages.properties" file. */
79 public static final String MSG_KEY_ANNOTATION_ON_SAME_LINE = "annotation.same.line";
80
81 @Override
82 public int[] getDefaultTokens() {
83 return new int[] {
84 TokenTypes.CLASS_DEF,
85 TokenTypes.INTERFACE_DEF,
86 TokenTypes.ENUM_DEF,
87 TokenTypes.METHOD_DEF,
88 TokenTypes.CTOR_DEF,
89 TokenTypes.VARIABLE_DEF,
90 TokenTypes.RECORD_DEF,
91 TokenTypes.COMPACT_CTOR_DEF,
92 };
93 }
94
95 @Override
96 public int[] getAcceptableTokens() {
97 return new int[] {
98 TokenTypes.CLASS_DEF,
99 TokenTypes.INTERFACE_DEF,
100 TokenTypes.ENUM_DEF,
101 TokenTypes.METHOD_DEF,
102 TokenTypes.CTOR_DEF,
103 TokenTypes.VARIABLE_DEF,
104 TokenTypes.PARAMETER_DEF,
105 TokenTypes.ANNOTATION_DEF,
106 TokenTypes.TYPECAST,
107 TokenTypes.LITERAL_THROWS,
108 TokenTypes.IMPLEMENTS_CLAUSE,
109 TokenTypes.TYPE_ARGUMENT,
110 TokenTypes.LITERAL_NEW,
111 TokenTypes.DOT,
112 TokenTypes.ANNOTATION_FIELD_DEF,
113 TokenTypes.RECORD_DEF,
114 TokenTypes.COMPACT_CTOR_DEF,
115 };
116 }
117
118 @Override
119 public int[] getRequiredTokens() {
120 return CommonUtil.EMPTY_INT_ARRAY;
121 }
122
123 @Override
124 public void visitToken(DetailAST ast) {
125 DetailAST nodeWithAnnotations = ast;
126 if (ast.getType() == TokenTypes.TYPECAST) {
127 nodeWithAnnotations = ast.findFirstToken(TokenTypes.TYPE);
128 }
129 DetailAST modifiersNode = nodeWithAnnotations.findFirstToken(TokenTypes.MODIFIERS);
130 if (modifiersNode == null) {
131 modifiersNode = nodeWithAnnotations.findFirstToken(TokenTypes.ANNOTATIONS);
132 }
133 if (modifiersNode != null) {
134 for (DetailAST annotationNode = modifiersNode.getFirstChild();
135 annotationNode != null;
136 annotationNode = annotationNode.getNextSibling()) {
137 if (annotationNode.getType() == TokenTypes.ANNOTATION
138 && !TokenUtil.areOnSameLine(annotationNode, getNextNode(annotationNode))) {
139 log(annotationNode, MSG_KEY_ANNOTATION_ON_SAME_LINE,
140 getAnnotationName(annotationNode));
141 }
142 }
143 }
144 }
145
146 /**
147 * Finds next node of ast tree.
148 *
149 * @param node current node
150 * @return node that is next to given
151 */
152 private static DetailAST getNextNode(DetailAST node) {
153 DetailAST nextNode = node.getNextSibling();
154 if (nextNode == null) {
155 nextNode = node.getParent().getNextSibling();
156 }
157 return nextNode;
158 }
159
160 /**
161 * Returns the name of the given annotation.
162 *
163 * @param annotation annotation node.
164 * @return annotation name.
165 */
166 private static String getAnnotationName(DetailAST annotation) {
167 DetailAST identNode = annotation.findFirstToken(TokenTypes.IDENT);
168 if (identNode == null) {
169 identNode = annotation.findFirstToken(TokenTypes.DOT).getLastChild();
170 }
171 return identNode.getText();
172 }
173
174 }