Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #6440: AnnotationLocation: named parameters must be considered parameters #6444

Merged
merged 1 commit into from Feb 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -53,6 +53,7 @@ public void testAnnotation() throws Exception {
"78: " + getCheckMessage(clazz, msgLocation, "MyAnnotation2", "11", "8"),
"81: " + getCheckMessage(clazz, msgLocation, "MyAnnotation2", "10", "8"),
"90: " + getCheckMessage(clazz, msgLocation, "MyAnnotation2", "1", "0"),
"93: " + getCheckMessage(clazz, msgLocationAlone, "MyAnnotationWithParam"),
};

final String filePath = getPath("InputAnnotationLocation.java");
Expand Down
Expand Up @@ -90,6 +90,8 @@ void foo2() {}
@MyAnnotation2 //warn
class Foo {}

@MyAnnotationWithParam(value = "bar") class Bar {} //warn

@interface MyAnnotation1 {}

@interface MyAnnotation2 {}
Expand Down
Expand Up @@ -24,6 +24,7 @@
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
import com.puppycrawl.tools.checkstyle.utils.TokenUtil;

/**
* Check location of annotation on language elements.
Expand Down Expand Up @@ -302,7 +303,10 @@ else if (annotation.getColumnNo() != correctIndentation && !hasNodeBefore(annota
* @return true if the annotation has parameters.
*/
private static boolean isParameterized(DetailAST annotation) {
return annotation.findFirstToken(TokenTypes.EXPR) != null;
return TokenUtil.findFirstTokenByPredicate(annotation, ast -> {
return ast.getType() == TokenTypes.EXPR
|| ast.getType() == TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR;
}).isPresent();
}

/**
Expand Down
Expand Up @@ -59,6 +59,7 @@ public void testIncorrect() throws Exception {
final String[] expected = {
"6: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnn"),
"11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"14: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 8, 4),
"25: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 8, 4),
"29: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
Expand All @@ -68,13 +69,17 @@ public void testIncorrect() throws Exception {
"37: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation3", 6, 4),
"38: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation4", 10, 4),
"41: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"45: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"48: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 12, 8),
"56: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"61: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 12, 8),
"65: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 12, 8),
"70: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 7, 4),
"73: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"75: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"85: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 11, 8),
"88: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 10, 8),
"91: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"98: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 0, 3),
};
verify(checkConfig, getPath("InputAnnotationLocationIncorrect.java"), expected);
Expand All @@ -88,6 +93,7 @@ public void testIncorrectAllTokens() throws Exception {
final String[] expected = {
"6: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnn"),
"11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"14: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 8, 4),
"25: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 8, 4),
"29: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
Expand All @@ -97,13 +103,17 @@ public void testIncorrectAllTokens() throws Exception {
"37: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation3", 6, 4),
"38: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation4", 10, 4),
"41: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"45: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"48: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 12, 8),
"56: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"61: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 12, 8),
"65: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 12, 8),
"70: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 7, 4),
"73: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"75: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"85: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 11, 8),
"88: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 10, 8),
"91: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
"98: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation2", 0, 3),
"100: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation2"),
};
Expand Down Expand Up @@ -193,4 +203,45 @@ public void testAnnotationInForEachLoopParameterAndVariableDef() throws Exceptio
verify(checkConfig, getPath("InputAnnotationLocationDeprecatedAndCustom.java"), expected);
}

@Test
public void testAnnotationMultiple() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(AnnotationLocationCheck.class);
checkConfig.addAttribute("allowSamelineMultipleAnnotations", "true");
checkConfig.addAttribute("allowSamelineSingleParameterlessAnnotation", "false");
checkConfig.addAttribute("allowSamelineParameterizedAnnotation", "false");
final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
verify(checkConfig, getPath("InputAnnotationLocationMultiple.java"), expected);
}

@Test
public void testAnnotationParameterized() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(AnnotationLocationCheck.class);
checkConfig.addAttribute("allowSamelineMultipleAnnotations", "false");
checkConfig.addAttribute("allowSamelineSingleParameterlessAnnotation", "false");
checkConfig.addAttribute("allowSamelineParameterizedAnnotation", "true");
final String[] expected = {
"15: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
"17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
"23: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
"25: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
};
verify(checkConfig, getPath("InputAnnotationLocationParameterized.java"), expected);
}

@Test
public void testAnnotationSingleParameterless() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(AnnotationLocationCheck.class);
checkConfig.addAttribute("allowSamelineMultipleAnnotations", "false");
checkConfig.addAttribute("allowSamelineSingleParameterlessAnnotation", "true");
checkConfig.addAttribute("allowSamelineParameterizedAnnotation", "false");
final String[] expected = {
"17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
"19: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
"21: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
"23: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
"25: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
};
verify(checkConfig, getPath("InputAnnotationLocationSingleParameterless.java"), expected);
}

}
Expand Up @@ -11,7 +11,7 @@ class InputAnnotationLocationIncorrect
@MyAnnotation2 @MyAnnotation1(value = "")
public int a;

@MyAnnotation1(value = "") public int b;
@MyAnnotation1(value = "") public int b; //warn

@MyAnnotation2
@MyAnnotation1 //warn
Expand Down Expand Up @@ -42,7 +42,7 @@ class InnerClass
(value = "")
public int a;

@MyAnnotation1(value = "") public int b;
@MyAnnotation1(value = "") public int b; //warn

@MyAnnotation2
@MyAnnotation1 //warn
Expand All @@ -53,7 +53,7 @@ class InnerClass
public int d;

@MyAnnotation2
@MyAnnotation1(value = "") public InnerClass()
@MyAnnotation1(value = "") public InnerClass() //warn
{
// comment
}
Expand All @@ -72,7 +72,7 @@ void foo2() {}
{
@MyAnnotation2 @MyAnnotation1(value = "") public int a;

@MyAnnotation1(value = "") public int b;
@MyAnnotation1(value = "") public int b; //warn

@MyAnnotation2
@MyAnnotation1(value = "")
Expand All @@ -88,7 +88,7 @@ void foo2() {}
@MyAnnotation2 //warn
void foo2() {}

@MyAnnotation1(value = "") void foo42() {}
@MyAnnotation1(value = "") void foo42() {} //warn
};

}
Expand Down
@@ -0,0 +1,36 @@
package com.puppycrawl.tools.checkstyle.checks.annotation.annotationlocation;

import java.lang.annotation.Repeatable;

/**
* This test-input is intended to be checked using following configuration:
*
* allowSamelineSingleParameterlessAnnotation = false
* allowSamelineParameterizedAnnotation = false
* allowSamelineMultipleAnnotations = true
*/
Copy link
Member

Choose a reason for hiding this comment

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

Can we have some warnings in this file ?

Copy link
Member Author

Choose a reason for hiding this comment

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

No. with allowSamelineMultipleAnnotations = true both allowSamelineSingleParameterlessAnnotation and allowSamelineParameterizedAnnotation has no effect. Actually, this means that any combination of annotations is allowed.

However, it is possible to catch a violation by using annotations on different lines.
This one: https://github.com/checkstyle/checkstyle/blob/master/src/main/java/com/puppycrawl/tools/checkstyle/checks/annotation/AnnotationLocationCheck.java#L292
But this is a different case and should be covered by another set of tests.


class InputAnnotationLocationMultiple {

@Annotation void singleParameterless() {}

@Annotation @Annotation void multipleParameterless() {}

@Annotation("") void parameterized() {}

@Annotation(value = "") void namedParameterized() {}

@Annotation @Annotation("") @Annotation(value = "") void multiple() {}

@Annotation("") @Annotation(value = "") void multipleParametrized() {}

@Repeatable(Annotations.class)
@interface Annotation {
String value() default "";
}

@interface Annotations {
Annotation[] value();
}

}
@@ -0,0 +1,36 @@
package com.puppycrawl.tools.checkstyle.checks.annotation.annotationlocation;

import java.lang.annotation.Repeatable;

/**
* This test-input is intended to be checked using following configuration:
*
* allowSamelineSingleParameterlessAnnotation = false
* allowSamelineParameterizedAnnotation = true
* allowSamelineMultipleAnnotations = false
*/

class InputAnnotationLocationParameterized {

@Annotation void singleParameterless() {} //warn

@Annotation @Annotation void multipleParameterless() {} //warn

@Annotation("") void parameterized() {}

@Annotation(value = "") void namedParameterized() {}

@Annotation @Annotation("") @Annotation(value = "") void multiple() {} //warn

@Annotation("") @Annotation(value = "") void multipleParametrized() {} //warn

@Repeatable(Annotations.class)
@interface Annotation {
String value() default "";
}

@interface Annotations {
Annotation[] value();
}

}
@@ -0,0 +1,36 @@
package com.puppycrawl.tools.checkstyle.checks.annotation.annotationlocation;

import java.lang.annotation.Repeatable;

/**
* This test-input is intended to be checked using following configuration:
*
* allowSamelineSingleParameterlessAnnotation = true
* allowSamelineParameterizedAnnotation = false
* allowSamelineMultipleAnnotations = false
*/

class InputAnnotationLocationSingleParameterless {

@Annotation void singleParameterless() {}

@Annotation @Annotation void multipleParameterless() {} //warn

@Annotation("") void parameterized() {} //warn

@Annotation(value = "") void namedParameterized() {} //warn

@Annotation @Annotation("") @Annotation(value = "") void multiple() {} //warn

@Annotation("") @Annotation(value = "") void multipleParametrized() {} //warn

@Repeatable(Annotations.class)
@interface Annotation {
String value() default "";
}

@interface Annotations {
Annotation[] value();
}

}