1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2017 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.whitespace; | |
21 | ||
22 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
23 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
24 | import com.puppycrawl.tools.checkstyle.utils.CommonUtils; | |
25 | ||
26 | /** | |
27 | * <p> | |
28 | * Checks that non-whitespace characters are separated by no more than one | |
29 | * whitespace. Separating characters by tabs or multiple spaces will be | |
30 | * reported. Currently the check doesn't permit horizontal alignment. To inspect | |
31 | * whitespaces before and after comments, set the property | |
32 | * <b>validateComments</b> to true. | |
33 | * </p> | |
34 | * | |
35 | * <p> | |
36 | * Setting <b>validateComments</b> to false will ignore cases like: | |
37 | * </p> | |
38 | * | |
39 | * <pre> | |
40 | * int i; // Multiple whitespaces before comment tokens will be ignored. | |
41 | * private void foo(int /* whitespaces before and after block-comments will be | |
42 | * ignored */ i) { | |
43 | * </pre> | |
44 | * | |
45 | * <p> | |
46 | * Sometimes, users like to space similar items on different lines to the same | |
47 | * column position for easier reading. This feature isn't supported by this | |
48 | * check, so both braces in the following case will be reported as violations. | |
49 | * </p> | |
50 | * | |
51 | * <pre> | |
52 | * public long toNanos(long d) { return d; } // 2 violations | |
53 | * public long toMicros(long d) { return d / (C1 / C0); } | |
54 | * </pre> | |
55 | * | |
56 | * <p> | |
57 | * Check have following options: | |
58 | * </p> | |
59 | * | |
60 | * <ul> | |
61 | * <li>validateComments - Boolean when set to {@code true}, whitespaces | |
62 | * surrounding comments will be ignored. Default value is {@code false}.</li> | |
63 | * </ul> | |
64 | * | |
65 | * <p> | |
66 | * To configure the check: | |
67 | * </p> | |
68 | * | |
69 | * <pre> | |
70 | * <module name="SingleSpaceSeparator"/> | |
71 | * </pre> | |
72 | * | |
73 | * <p> | |
74 | * To configure the check so that it validates comments: | |
75 | * </p> | |
76 | * | |
77 | * <pre> | |
78 | * <module name="SingleSpaceSeparator"> | |
79 | * <property name="validateComments" value="true"/> | |
80 | * </module> | |
81 | * </pre> | |
82 | * | |
83 | * @author Robert Whitebit | |
84 | * @author Richard Veach | |
85 | */ | |
86 | public class SingleSpaceSeparatorCheck extends AbstractCheck { | |
87 | /** | |
88 | * A key is pointing to the warning message text in "messages.properties" | |
89 | * file. | |
90 | */ | |
91 | public static final String MSG_KEY = "single.space.separator"; | |
92 | ||
93 | /** Indicates if whitespaces surrounding comments will be ignored. */ | |
94 | private boolean validateComments; | |
95 | ||
96 | /** | |
97 | * Sets whether or not to validate surrounding whitespaces at comments. | |
98 | * | |
99 | * @param validateComments {@code true} to validate surrounding whitespaces at comments. | |
100 | */ | |
101 | public void setValidateComments(boolean validateComments) { | |
102 | this.validateComments = validateComments; | |
103 | } | |
104 | ||
105 | @Override | |
106 | public int[] getDefaultTokens() { | |
107 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/SingleSpaceSeparatorCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CommonUtils.EMPTY_INT_ARRAY; |
108 | } | |
109 | ||
110 | @Override | |
111 | public int[] getAcceptableTokens() { | |
112 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/SingleSpaceSeparatorCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getDefaultTokens(); |
113 | } | |
114 | ||
115 | @Override | |
116 | public int[] getRequiredTokens() { | |
117 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/SingleSpaceSeparatorCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getDefaultTokens(); |
118 | } | |
119 | ||
120 | // -@cs[SimpleAccessorNameNotation] Overrides method from base class. | |
121 | // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166 | |
122 | @Override | |
123 | public boolean isCommentNodesRequired() { | |
124 |
1
1. isCommentNodesRequired : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return validateComments; |
125 | } | |
126 | ||
127 | @Override | |
128 | public void beginTree(DetailAST rootAST) { | |
129 |
1
1. beginTree : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/SingleSpaceSeparatorCheck::visitEachToken → KILLED |
visitEachToken(rootAST); |
130 | } | |
131 | ||
132 | /** | |
133 | * Examines every sibling and child of {@code node} for violations. | |
134 | * | |
135 | * @param node The node to start examining. | |
136 | */ | |
137 | private void visitEachToken(DetailAST node) { | |
138 | DetailAST sibling = node; | |
139 | ||
140 |
1
1. visitEachToken : negated conditional → KILLED |
while (sibling != null) { |
141 |
1
1. visitEachToken : Replaced integer subtraction with addition → KILLED |
final int columnNo = sibling.getColumnNo() - 1; |
142 | ||
143 | // in such expression: "j =123", placed at the start of the string index of the second | |
144 | // space character will be: 2 = 0(j) + 1(whitespace) + 1(whitespace). It is a minimal | |
145 | // possible index for the second whitespace between non-whitespace characters. | |
146 | final int minSecondWhitespaceColumnNo = 2; | |
147 | ||
148 |
2
1. visitEachToken : changed conditional boundary → KILLED 2. visitEachToken : negated conditional → KILLED |
if (columnNo >= minSecondWhitespaceColumnNo |
149 |
2
1. visitEachToken : Replaced integer subtraction with addition → KILLED 2. visitEachToken : negated conditional → KILLED |
&& !isTextSeparatedCorrectlyFromPrevious(getLine(sibling.getLineNo() - 1), |
150 | columnNo)) { | |
151 |
1
1. visitEachToken : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/SingleSpaceSeparatorCheck::log → KILLED |
log(sibling.getLineNo(), columnNo, MSG_KEY); |
152 | } | |
153 |
2
1. visitEachToken : changed conditional boundary → KILLED 2. visitEachToken : negated conditional → KILLED |
if (sibling.getChildCount() >= 1) { |
154 |
1
1. visitEachToken : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/SingleSpaceSeparatorCheck::visitEachToken → KILLED |
visitEachToken(sibling.getFirstChild()); |
155 | } | |
156 | ||
157 | sibling = sibling.getNextSibling(); | |
158 | } | |
159 | } | |
160 | ||
161 | /** | |
162 | * Checks if characters in {@code line} at and around {@code columnNo} has | |
163 | * the correct number of spaces. to return {@code true} the following | |
164 | * conditions must be met:<br /> | |
165 | * - the character at {@code columnNo} is the first in the line.<br /> | |
166 | * - the character at {@code columnNo} is not separated by whitespaces from | |
167 | * the previous non-whitespace character. <br /> | |
168 | * - the character at {@code columnNo} is separated by only one whitespace | |
169 | * from the previous non-whitespace character.<br /> | |
170 | * - {@link #validateComments} is disabled and the previous text is the | |
171 | * end of a block comment. | |
172 | * | |
173 | * @param line The line in the file to examine. | |
174 | * @param columnNo The column position in the {@code line} to examine. | |
175 | * @return {@code true} if the text at {@code columnNo} is separated | |
176 | * correctly from the previous token. | |
177 | */ | |
178 | private boolean isTextSeparatedCorrectlyFromPrevious(String line, int columnNo) { | |
179 |
2
1. isTextSeparatedCorrectlyFromPrevious : negated conditional → KILLED 2. isTextSeparatedCorrectlyFromPrevious : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isSingleSpace(line, columnNo) |
180 |
1
1. isTextSeparatedCorrectlyFromPrevious : negated conditional → KILLED |
|| !isWhitespace(line, columnNo) |
181 |
2
1. isTextSeparatedCorrectlyFromPrevious : negated conditional → KILLED 2. isTextSeparatedCorrectlyFromPrevious : negated conditional → KILLED |
|| isFirstInLine(line, columnNo) |
182 |
1
1. isTextSeparatedCorrectlyFromPrevious : negated conditional → KILLED |
|| !validateComments && isBlockCommentEnd(line, columnNo); |
183 | } | |
184 | ||
185 | /** | |
186 | * Checks if the {@code line} at {@code columnNo} is a single space, and not | |
187 | * preceded by another space. | |
188 | * | |
189 | * @param line The line in the file to examine. | |
190 | * @param columnNo The column position in the {@code line} to examine. | |
191 | * @return {@code true} if the character at {@code columnNo} is a space, and | |
192 | * not preceded by another space. | |
193 | */ | |
194 | private static boolean isSingleSpace(String line, int columnNo) { | |
195 |
2
1. isSingleSpace : negated conditional → KILLED 2. isSingleSpace : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return !isPrecededByMultipleWhitespaces(line, columnNo) |
196 |
1
1. isSingleSpace : negated conditional → KILLED |
&& isSpace(line, columnNo); |
197 | } | |
198 | ||
199 | /** | |
200 | * Checks if the {@code line} at {@code columnNo} is a space. | |
201 | * | |
202 | * @param line The line in the file to examine. | |
203 | * @param columnNo The column position in the {@code line} to examine. | |
204 | * @return {@code true} if the character at {@code columnNo} is a space. | |
205 | */ | |
206 | private static boolean isSpace(String line, int columnNo) { | |
207 |
2
1. isSpace : negated conditional → KILLED 2. isSpace : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return line.charAt(columnNo) == ' '; |
208 | } | |
209 | ||
210 | /** | |
211 | * Checks if the {@code line} at {@code columnNo} is preceded by at least 2 | |
212 | * whitespaces. | |
213 | * | |
214 | * @param line The line in the file to examine. | |
215 | * @param columnNo The column position in the {@code line} to examine. | |
216 | * @return {@code true} if there are at least 2 whitespace characters before | |
217 | * {@code columnNo}. | |
218 | */ | |
219 | private static boolean isPrecededByMultipleWhitespaces(String line, int columnNo) { | |
220 |
3
1. isPrecededByMultipleWhitespaces : Replaced integer subtraction with addition → KILLED 2. isPrecededByMultipleWhitespaces : negated conditional → KILLED 3. isPrecededByMultipleWhitespaces : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return Character.isWhitespace(line.charAt(columnNo)) |
221 |
1
1. isPrecededByMultipleWhitespaces : negated conditional → KILLED |
&& Character.isWhitespace(line.charAt(columnNo - 1)); |
222 | } | |
223 | ||
224 | /** | |
225 | * Checks if the {@code line} at {@code columnNo} is a whitespace character. | |
226 | * | |
227 | * @param line The line in the file to examine. | |
228 | * @param columnNo The column position in the {@code line} to examine. | |
229 | * @return {@code true} if the character at {@code columnNo} is a | |
230 | * whitespace. | |
231 | */ | |
232 | private static boolean isWhitespace(String line, int columnNo) { | |
233 |
1
1. isWhitespace : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return Character.isWhitespace(line.charAt(columnNo)); |
234 | } | |
235 | ||
236 | /** | |
237 | * Checks if the {@code line} up to and including {@code columnNo} is all | |
238 | * non-whitespace text encountered. | |
239 | * | |
240 | * @param line The line in the file to examine. | |
241 | * @param columnNo The column position in the {@code line} to examine. | |
242 | * @return {@code true} if the column position is the first non-whitespace | |
243 | * text on the {@code line}. | |
244 | */ | |
245 | private static boolean isFirstInLine(String line, int columnNo) { | |
246 |
1
1. isFirstInLine : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return CommonUtils.isBlank(line.substring(0, columnNo)); |
247 | } | |
248 | ||
249 | /** | |
250 | * Checks if the {@code line} at {@code columnNo} is the end of a comment, | |
251 | * '*/'. | |
252 | * | |
253 | * @param line The line in the file to examine. | |
254 | * @param columnNo The column position in the {@code line} to examine. | |
255 | * @return {@code true} if the previous text is a end comment block. | |
256 | */ | |
257 | private static boolean isBlockCommentEnd(String line, int columnNo) { | |
258 |
1
1. isBlockCommentEnd : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return line.substring(0, columnNo).trim().endsWith("*/"); |
259 | } | |
260 | } | |
Mutations | ||
107 |
1.1 |
|
112 |
1.1 |
|
117 |
1.1 |
|
124 |
1.1 |
|
129 |
1.1 |
|
140 |
1.1 |
|
141 |
1.1 |
|
148 |
1.1 2.2 |
|
149 |
1.1 2.2 |
|
151 |
1.1 |
|
153 |
1.1 2.2 |
|
154 |
1.1 |
|
179 |
1.1 2.2 |
|
180 |
1.1 |
|
181 |
1.1 2.2 |
|
182 |
1.1 |
|
195 |
1.1 2.2 |
|
196 |
1.1 |
|
207 |
1.1 2.2 |
|
220 |
1.1 2.2 3.3 |
|
221 |
1.1 |
|
233 |
1.1 |
|
246 |
1.1 |
|
258 |
1.1 |