Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/checkstyle-checks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
LITERAL_YIELD, LITERAL_CASE, LITERAL_WHEN, ANNOTATIONS"/>
LITERAL_YIELD, LITERAL_CASE, LITERAL_WHEN, ANNOTATIONS, TYPE"/>
</module>
<module name="WhitespaceAround"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public int[] getAcceptableTokens() {
TokenTypes.LAMBDA,
TokenTypes.LITERAL_WHEN,
TokenTypes.ANNOTATIONS,
TokenTypes.TYPE,
};
}

Expand All @@ -119,6 +120,9 @@ public void visitToken(DetailAST ast) {
log(targetAST, MSG_WS_TYPECAST);
}
}
else if (ast.getType() == TokenTypes.TYPE) {
visitType(ast);
}
else if (ast.getType() == TokenTypes.ANNOTATIONS) {
if (ast.getFirstChild() != null) {
DetailAST targetAST = ast.getFirstChild().getLastChild();
Expand Down Expand Up @@ -158,9 +162,75 @@ private static boolean isFollowedByWhitespace(DetailAST targetAST, int... line)

followedByWhitespace = codePoint == ';'
|| codePoint == ')'
|| codePoint == ','
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One problem is that this change has an impact on other tokens (not only on TYPE), because the method is shared.

|| Character.isWhitespace(codePoint);
}
return followedByWhitespace;
}

/**
* Performs a whitespace check on a {@code TokenTypes.TYPE} token by locating the
* rightmost token of the {@code TokenTypes.TYPE} expression and verifying that it
* is followed by a whitespace character when appropriate. If the check fails, a log
* message is recorded. The rightmost token may be {@code null} when
* the {@code TokenTypes.TYPE} node has no meaningful trailing token to validate.
*
* @param typeAst AST node of type {@code TokenTypes.TYPE}
*/
private void visitType(DetailAST typeAst) {
final DetailAST targetAst = getTypeRightmostToken(typeAst);
if (targetAst != null) {
final int[] line = getLineCodePoints(targetAst.getLineNo() - 1);
if (!isFollowedByWhitespace(targetAst, line)) {
final Object[] args = {targetAst.getText()};
log(targetAst, MSG_WS_NOT_FOLLOWED, args);
}
}
}

/**
* Determines the appropriate AST node representing the end of a TYPE token.
* Used to locate the final token of a type expression for whitespace checks.
* Depending on context, this may be an ellipsis token, the deepest child of
* the type node, or {@code null} if the type is already the rightmost element
* and has no relevant token following it.
*
* @param typeAst AST node of type {@code TokenTypes.TYPE}
* @return the rightmost AST token relevant to the TYPE, or {@code null}
* if no applicable token is found
*/
private static DetailAST getTypeRightmostToken(DetailAST typeAst) {
final int parentType = typeAst.getParent().getType();
DetailAST targetAst = null;
if (parentType == TokenTypes.PARAMETER_DEF
|| parentType == TokenTypes.RECORD_COMPONENT_DEF) {
final DetailAST sibling = typeAst.getNextSibling();
if (sibling.getType() == TokenTypes.ELLIPSIS) {
targetAst = sibling;
}
else if (typeAst.hasChildren()) {
targetAst = getDeepestLastChild(typeAst);
}
}
else if (parentType != TokenTypes.RECORD_PATTERN_DEF) {
targetAst = getDeepestLastChild(typeAst);
}
return targetAst;
}

/**
* Finds the deepest descendant of the given AST by repeatedly
* following the last child until a leaf node is reached.
*
* @param ast AST node from which to start the search.
* @return the deepest last child AST node.
*/
private static DetailAST getDeepestLastChild(DetailAST ast) {
DetailAST current = ast;
while (current.getLastChild() != null) {
current = current.getLastChild();
}
return current;
}

}
2 changes: 1 addition & 1 deletion src/main/resources/google_checks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
LITERAL_YIELD, LITERAL_CASE, LITERAL_WHEN, ANNOTATIONS"/>
LITERAL_YIELD, LITERAL_CASE, LITERAL_WHEN, ANNOTATIONS, TYPE"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
Expand Down
2 changes: 2 additions & 0 deletions src/site/xdoc/checks/whitespace/whitespaceafter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
LITERAL_WHEN</a>
, <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ANNOTATIONS">
ANNOTATIONS</a>
, <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#TYPE">
TYPE</a>
.
</td>
<td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,4 +413,32 @@ public void testWhitespaceAfterAnnotationInPackageFile2() throws Exception {
verifyWithInlineConfigParser(
getPath("example2/package-info.java"), expected);
}

@Test
public void testWhitespaceAfterType() throws Exception {
final String[] expected = {
"11:9: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"13:11: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"15:13: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"20:13: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"21:40: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, ">"),
"23:39: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, ">"),
"25:28: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"27:40: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, ">"),
"29:27: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "..."),
"31:32: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"31:67: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, ">"),
"38:42: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, ">"),
"48:34: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, ">"),
"50:22: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"56:18: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "]"),
"58:17: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "..."),
"62:28: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "..."),
"64:5: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "int"),
};
verifyWithInlineConfigParser(
getPath("InputWhitespaceAfterType.java"),
expected
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
WhitespaceAfter
tokens = TYPE


*/

package com.puppycrawl.tools.checkstyle.checks.whitespace.whitespaceafter;

public class InputWhitespaceAfterType {
int[]arrayBad; // violation '']' is not followed by whitespace'
int[] arrayOk;
int[][]matrixBad; // violation '']' is not followed by whitespace'
int[][] matrixOk;
int[][][]cubeBad; // violation '']' is not followed by whitespace'
int[][][] cubeOk;
int[]
arrayNewlineOk;
int[
]arrayNewlineBad; // violation '']' is not followed by whitespace'
java.util.Map.Entry<String, Integer>entryBad; // violation ''>' is not followed by whitespace'
java.util.Map.Entry<String, Integer> entryOk;
java.util.List<java.util.Set<Byte>>listSetBad; // violation ''>' is not followed by whitespace'
java.util.List<java.util.Set<Byte>> listSetOk;
java.util.List<String>[]arrayOfListStringBad; // violation '']' is not followed by whitespace'
java.util.List<String>[] arrayOfListStringOk;
void paramBad(java.util.List<String>param) {} // violation ''>' is not followed by whitespace'
void paramOk(java.util.List<String> param) {}
void varargsBad(String...args) {} // violation ''...' is not followed by whitespace'
void varargsOk(String... args) {}
void multipleParamsBad(int[]arr, java.util.Map<String, Integer>map) {}
// 2 violations above:
// '']' is not followed by whitespace'
// ''>' is not followed by whitespace'
void multiParamsOk(int[] arr, java.util.Map<String, Integer> map) {}
void instanceOf() {
Object o = java.util.List.of("x");
if (o instanceof java.util.List<?>bad) { } // violation ''>' is not followed by whitespace'
if (o instanceof java.util.List<?> ok) { }
}
int switches(Object o) {
record Point(int x, int y) {}
switch (o) {
case Point(int x, int y) when !(x >= 0 && y >= 0) -> {}
default -> {}
}
return switch (o) {
case java.util.List<?>bad -> 1; // violation ''>' is not followed by whitespace'
case java.util.SequencedCollection<?> ok -> 2;
case int[]bad -> 3; // violation '']' is not followed by whitespace'
case byte[] ok -> 4;
default -> 5;
};
}
java.util.function.Predicate<int[]> p1 =
(int[]bad) -> true; // violation '']' is not followed by whitespace'
java.util.function.Predicate<int[]> p2 =
(int...bad) -> true; // violation ''...' is not followed by whitespace'
java.util.function.Predicate<int[]> p3 = (int[] ok) -> true;
java.util.function.BiFunction<Integer, Integer, Integer> ok = (a, b) -> a + b;
boolean returnInstanceof(Object o) { return o instanceof Enum; }
record recordBad(String...s) {} // violation ''...' is not followed by whitespace'
record recordGood(String... s) {}
int/*<TargetElement>*/commentBad; // violation ''int' is not followed by whitespace'
int /*<TargetElement>*/ commentOk2;
int cStyleArrOk[];
int cStyleMatrixOk[][];
void cStyleArrayDeclarationOk(char ch[], int a) {}
}
Loading