Issue #903: Skip type annotations from validation of ModifierOrderCheck
This commit is contained in:
parent
0fe6a55348
commit
4c3a5dcdd0
|
|
@ -154,8 +154,10 @@ public class ModifierOrderCheck
|
|||
&& offendingModifier == null) {
|
||||
|
||||
if (modifier.getType() == TokenTypes.ANNOTATION) {
|
||||
//Annotation not at start of modifiers, bad
|
||||
offendingModifier = modifier;
|
||||
if (!isAnnotationOnType(modifier)) {
|
||||
//Annotation not at start of modifiers, bad
|
||||
offendingModifier = modifier;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -193,4 +195,20 @@ public class ModifierOrderCheck
|
|||
while (modifierIterator.hasNext() && modifier.getType() == TokenTypes.ANNOTATION);
|
||||
return modifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether annotation on type takes place.
|
||||
* @param modifier modifier token.
|
||||
* @return true if annotation on type takes place.
|
||||
*/
|
||||
private static boolean isAnnotationOnType(DetailAST modifier) {
|
||||
boolean annotationOnType = false;
|
||||
final DetailAST modifiers = modifier.getParent();
|
||||
final int definitionTokenType = modifiers.getParent().getType();
|
||||
if (definitionTokenType == TokenTypes.VARIABLE_DEF
|
||||
|| definitionTokenType == TokenTypes.PARAMETER_DEF) {
|
||||
annotationOnType = true;
|
||||
}
|
||||
return annotationOnType;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,4 +110,15 @@ public class ModifierOrderCheckTest
|
|||
Assert.assertNotSame(unexpectedArray, actual);
|
||||
Assert.assertNotNull(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipTypeAnnotations() throws Exception {
|
||||
// Type Annotations are avaliable only in Java 8
|
||||
// We skip type annotations from validation
|
||||
// See https://github.com/checkstyle/checkstyle/issues/903#issuecomment-172228013
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(ModifierOrderCheck.class);
|
||||
final String[] expected = ArrayUtils.EMPTY_STRING_ARRAY;
|
||||
verify(checkConfig, getNonCompilablePath("InputTypeAnnotations.java"), expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
//Compilable with Java8
|
||||
package com.puppycrawl.tools.checkstyle.checks.modifier;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class InputTypeAnnotations {
|
||||
|
||||
// Simple type definitions with type annotations
|
||||
private @TypeAnnotation String hello = "Hello, World!";
|
||||
private @TypeAnnotation final String jdk = "JDK8";
|
||||
@TypeAnnotation private String projectName = "Checkstyle";
|
||||
|
||||
// We can use type Annotations with generic type arguments
|
||||
private Map.@TypeAnnotation Entry entry;
|
||||
// Type annotations can also be applied to nested types
|
||||
private List<@TypeAnnotation String> strings;
|
||||
|
||||
// Constructors with type annotations
|
||||
{
|
||||
new @TypeAnnotation Object();
|
||||
}
|
||||
|
||||
static {
|
||||
new @TypeAnnotation Object();
|
||||
}
|
||||
|
||||
public void foo1() {
|
||||
new @TypeAnnotation Object();
|
||||
}
|
||||
|
||||
// Type annotations work with nested (non static) class constructors too
|
||||
public void foo2() {
|
||||
InputTypeAnnotations myObject = new InputTypeAnnotations();
|
||||
myObject.new @TypeAnnotation Nested();
|
||||
}
|
||||
|
||||
// Type casts
|
||||
public void foo3() {
|
||||
String myString = (@TypeAnnotation String) new Object();
|
||||
|
||||
}
|
||||
|
||||
// Type annotations with method arguments
|
||||
private void foo4(final @TypeAnnotation String parameterName) { }
|
||||
|
||||
// Inheritance
|
||||
class MySerializableClass<T> implements @TypeAnnotation Serializable { }
|
||||
|
||||
// Nested type annotations
|
||||
Map<@TypeAnnotation String, @TypeAnnotation List<@TypeAnnotation String>> documents;
|
||||
|
||||
// Apply type annotations to intersection types
|
||||
public <E extends @TypeAnnotation Comparator<E> & @TypeAnnotation Comparable> void foo5() { }
|
||||
|
||||
// Including parameter bounds and wildcard bounds
|
||||
class Folder<F extends @TypeAnnotation File> { }
|
||||
Collection<? super @TypeAnnotation File> c;
|
||||
List<@TypeAnnotation ? extends Comparable<T>> unchangeable;
|
||||
|
||||
// Throwing exceptions
|
||||
void foo6() throws @TypeAnnotation IOException { }
|
||||
|
||||
// Type annotations in instanceof statements
|
||||
public void foo7() {
|
||||
boolean isNonNull = "string" instanceof @TypeAnnotation String;
|
||||
|
||||
}
|
||||
|
||||
class Nested { }
|
||||
|
||||
class T { }
|
||||
}
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER,
|
||||
ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
|
||||
@interface TypeAnnotation {
|
||||
}
|
||||
|
|
@ -66,6 +66,12 @@
|
|||
<code>strictfp</code>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
ATTENTION: We skip <a href="https://blogs.oracle.com/java-platform-group/entry/java_8_s_new_type">
|
||||
type annotations</a> from validation.
|
||||
</p>
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Examples">
|
||||
|
|
|
|||
Loading…
Reference in New Issue