Skip to content

Commit

Permalink
Issue checkstyle#3238: Java 8 Grammar: annotations on arrays and varargs
Browse files Browse the repository at this point in the history
  • Loading branch information
esilkensen committed Jan 20, 2020
1 parent dd95725 commit cfc4404
Show file tree
Hide file tree
Showing 8 changed files with 604 additions and 402 deletions.
Expand Up @@ -170,8 +170,7 @@ public void setAllowLineBreaks(boolean allowLineBreaks) {
public void visitToken(DetailAST ast) {
final DetailAST whitespaceFollowedAst = getWhitespaceFollowedNode(ast);

if (whitespaceFollowedAst.getNextSibling() == null
|| whitespaceFollowedAst.getNextSibling().getType() != TokenTypes.ANNOTATIONS) {
if (shouldCheckWhitespaceAfter(whitespaceFollowedAst)) {
final int whitespaceColumnNo = getPositionAfter(whitespaceFollowedAst);
final int whitespaceLineNo = whitespaceFollowedAst.getLineNo();

Expand Down Expand Up @@ -206,6 +205,27 @@ private static DetailAST getWhitespaceFollowedNode(DetailAST ast) {
return whitespaceFollowedAst;
}

/**
* Returns whether whitespace after a visited node should be checked. For example, whitespace
* is not allowed between a type and an array declarator (returns true), except when there is
* an annotation in between the type and array declarator (returns false).
* @param ast the visited node
* @return true if whitespace after ast should be checked
*/
private static boolean shouldCheckWhitespaceAfter(DetailAST ast) {
boolean checkWhitespace = true;
if (ast.getNextSibling() != null) {
final DetailAST sibling = ast.getNextSibling();
if (sibling.getType() == TokenTypes.ANNOTATIONS) {
checkWhitespace = false;
}
else if (sibling.getType() == TokenTypes.ARRAY_DECLARATOR) {
checkWhitespace = sibling.getFirstChild().getType() != TokenTypes.ANNOTATIONS;
}
}
return checkWhitespace;
}

/**
* Gets position after token (place of possible redundant whitespace).
* @param ast Node representing token.
Expand Down
23 changes: 17 additions & 6 deletions src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java.g
Expand Up @@ -257,6 +257,14 @@ typeSpec[boolean addImagNode]
| builtInTypeSpec[addImagNode]
;
// A type specification for a variable length parameter is a type name with
// possible brackets afterwards that can end with annotations.
variableLengthParameterTypeSpec
: (classOrInterfaceType[false] | builtInType)
({LA(1) == AT}? annotations | )
(lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK ({LA(1) == AT}? annotations | ))*
;
// A class type specification is a class type with either:
// - possible brackets afterwards
// (which would make it an array type).
Expand Down Expand Up @@ -387,8 +395,8 @@ builtInTypeSpec[boolean addImagNode]
// A type name. which is either a (possibly qualified and parameterized)
// class name or a primitive (builtin) type
type
: classOrInterfaceType[false]
| builtInType
: ({LA(1) == AT}? annotations | )
(classOrInterfaceType[false] | builtInType)
;

/** A declaration is the creation of a reference or primitive-type variable
Expand Down Expand Up @@ -893,9 +901,11 @@ variableDeclarator![AST mods, AST t]
{#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v);}
;
declaratorBrackets[AST typ]
: {#declaratorBrackets=typ;}
(lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK)*
declaratorBrackets![AST typ]
: ({LA(1) == AT}? an:annotations | ) lb:LBRACK {#lb.setType(ARRAY_DECLARATOR);} rb:RBRACK
db:declaratorBrackets[#(lb, typ, an, rb)]
{#declaratorBrackets = #db;}
| {#declaratorBrackets = typ;}
;
varInitializer
Expand Down Expand Up @@ -969,7 +979,7 @@ parameterDeclarationList
;
variableLengthParameterDeclaration!
: pm:parameterModifier t:typeSpec[false] td:ELLIPSIS IDENT
: pm:parameterModifier t:variableLengthParameterTypeSpec td:ELLIPSIS IDENT
pd:declaratorBrackets[#t]
{#variableLengthParameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
pm, #([TYPE,"TYPE"],pd), td, IDENT);}
Expand Down Expand Up @@ -1592,6 +1602,7 @@ newArrayDeclarator
warnWhenFollowAmbig = false;
}
:
({LA(1) == AT}? annotations | )
lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
(expression)?
RBRACK
Expand Down
Expand Up @@ -132,4 +132,13 @@ public void testAnnotationInTypeParameters()
verify(checkConfig, getPath("InputAnnotations11.java"), expected);
}

@Test
public void testAnnotationOnVarargs()
throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(MemberNameCheck.class);
final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
verify(checkConfig, getPath("InputAnnotations12.java"), expected);
}

}
Expand Up @@ -9,6 +9,9 @@ public void testWithAnnotationInMiddle1(final char @AnnotationAfterTest [] a) {}
public void testWithAnnotationInMiddle2(final char@AnnotationAfterTest [] a) {}//Correct
public void testWithAnnotationInMiddle3(final char @AnnotationAfterTest[] a) {}//Correct
public void testWithAnnotationInMiddle4(final char@AnnotationAfterTest[]a) {}//Correct
public @AnnotationAfterTest String @AnnotationAfterTest [] testWithAnnotationInMiddle5() {
return new @AnnotationAfterTest String @AnnotationAfterTest [3];//Correct
}

@Target(ElementType.TYPE_USE)
@interface AnnotationAfterTest {
Expand Down
Expand Up @@ -25,6 +25,8 @@ public static <T> void m2(T @Nullable [] array) {}
public void m3() throws NullPointerException, @Nullable ArrayIndexOutOfBoundsException {}
public void m4(InputRegressionJava8Class1 this) {}
public void m5(@Nullable InputRegressionJava8Class1 this) {}
public void m6(@Nullable String @Nullable ... vararg) {}
public String m7() @Nullable [] @Nullable [] { return null; }

{
List<String> vlist = new ArrayList<String>();
Expand All @@ -44,6 +46,9 @@ public void instructions() {
Map.@Nullable Entry e;
String str = (@Nullable String) "";
(new Inner3()).<@Nullable String>m();
Object arr = new @Nullable String @Nullable [3];
for (String a @Nullable [] : m7()) {}
Object arr2 = new @Nullable int[3];

// method reference
IntBinaryOperator ibo = Math::max;
Expand Down

0 comments on commit cfc4404

Please sign in to comment.