Skip to content

Commit

Permalink
Issue #11736: Support qualified annotation names for MissingJavadocTy…
Browse files Browse the repository at this point in the history
…peCheck
  • Loading branch information
stoyanK7 committed Jul 3, 2022
1 parent a6b980f commit 66c557a
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 10 deletions.
Expand Up @@ -123,20 +123,88 @@ public static boolean containsAnnotation(DetailAST ast, Set<String> annotations)

if (!annotations.isEmpty()) {
final DetailAST firstMatchingAnnotation = findFirstAnnotation(ast, annotationNode -> {
DetailAST identNode = annotationNode.findFirstToken(TokenTypes.IDENT);
if (identNode == null) {
identNode = annotationNode.findFirstToken(TokenTypes.DOT)
.findFirstToken(TokenTypes.IDENT);
}

return annotations.contains(identNode.getText());
return doesAnnotationMatch(annotationNode, annotations);
});
result = firstMatchingAnnotation != null;
}

return result;
}

/**
* Checks if annotation is found in the set of provided annotations.
*
* @param annotations A collection of annotations to look through.
* @param annotationNode Annotation to look for.
* @return {@code true} if the annotation is contained in the set.
*/
private static boolean doesAnnotationMatch(DetailAST annotationNode, Set<String> annotations) {
final DetailAST identNode = annotationNode.findFirstToken(TokenTypes.IDENT);
final String annotationString;

// If no `IDENT` is found, then we have a `DOT` -> more than 1 qualifier
if (identNode == null) {
final DetailAST dotNode = annotationNode.findFirstToken(TokenTypes.DOT);
annotationString = convertAnnotationNameToString(dotNode);
}
else {
annotationString = identNode.getText();
}

boolean annotationsMatch = false;

for (String annotation : annotations) {
if (annotation.equals(annotationString)) {
annotationsMatch = true;
break;
}
}

return annotationsMatch;
}

/**
* Converts (qualified) annotation name to string.
*
* <p>
* For example:
* </p>
* <pre>
* &#64;org.example.MyAnn -&gt; "org.example.MyAnn"
* &#64;MyAnn -&gt; "MyAnn"
* </pre>
*
* @param rootDotNode The root DOT node of the (qualified) annotation.
* @return Annotation name as string.
*/
private static String convertAnnotationNameToString(DetailAST rootDotNode) {
final StringBuilder result = new StringBuilder();
final StringBuilder temp = new StringBuilder();
final char dot = '.';
DetailAST currDotNode = rootDotNode;

while (currDotNode != null) {
if (currDotNode.findFirstToken(TokenTypes.DOT) == null) {
temp.append(currDotNode.getFirstChild().getText());
if (currDotNode.getChildCount() > 1) {
temp.append(dot);
temp.append(currDotNode.getLastChild().getText());
}
}
else {
temp.append(currDotNode.findFirstToken(TokenTypes.IDENT).getText());
}
if (result.length() != 0) {
temp.append(dot);
}
currDotNode = currDotNode.findFirstToken(TokenTypes.DOT);
result.insert(0, temp);
temp.setLength(0);
}

return result.toString();
}

/**
* Checks if the AST is annotated with {@code Override} or
* {@code java.lang.Override} annotation.
Expand Down
Expand Up @@ -291,4 +291,45 @@ public void testInterfaceMemberScopeIsPublic() throws Exception {
expected);
}

@Test
public void testFullyQualifiedAnnotation1() throws Exception {
final String[] expected = {
"16:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
"19:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
"22:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
};
verifyWithInlineConfigParser(
getPath("InputMissingJavadocTypeFullyQualifiedAnnotation1.java"), expected);
}

@Test
public void testFullyQualifiedAnnotation2() throws Exception {
final String[] expected = {
"19:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
"22:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
};
verifyWithInlineConfigParser(
getPath("InputMissingJavadocTypeFullyQualifiedAnnotation2.java"), expected);
}

@Test
public void testFullyQualifiedAnnotation3() throws Exception {
final String[] expected = {
"16:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
"22:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
};
verifyWithInlineConfigParser(
getPath("InputMissingJavadocTypeFullyQualifiedAnnotation3.java"), expected);
}

@Test
public void testFullyQualifiedAnnotation4() throws Exception {
final String[] expected = {
"17:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
"20:5: " + getCheckMessage(MSG_JAVADOC_MISSING),
};
verifyWithInlineConfigParser(
getPath("InputMissingJavadocTypeFullyQualifiedAnnotation4.java"), expected);
}

}
Expand Up @@ -28,9 +28,6 @@ public void allowed1() {}
@ThisIsOkToo
public void allowed2() {}

@com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadocmethod.ThisIsOk
public void allowed3() {}

@Override
public void method() {}
}
Expand Down
@@ -0,0 +1,25 @@
/*
MissingJavadocType
scope = (default)public
excludeScope = (default)null
skipAnnotations = (default)Generated
tokens = INTERFACE_DEF
*/

package com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype;

public class InputMissingJavadocTypeFullyQualifiedAnnotation1 {
public @interface SomeAnnotation { }

@SomeAnnotation // violation
public interface A { }

@InputMissingJavadocTypeFullyQualifiedAnnotation1.SomeAnnotation // violation
public interface B { }

@com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype. // violation
InputMissingJavadocTypeFullyQualifiedAnnotation1.SomeAnnotation
public interface C { }
}
@@ -0,0 +1,25 @@
/*
MissingJavadocType
scope = (default)public
excludeScope = (default)null
skipAnnotations = SomeAnnotation
tokens = INTERFACE_DEF
*/

package com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype;

public class InputMissingJavadocTypeFullyQualifiedAnnotation2 {
public @interface SomeAnnotation { }

@SomeAnnotation // ok
public interface A { }

@InputMissingJavadocTypeFullyQualifiedAnnotation2.SomeAnnotation // violation
public interface B { }

@com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype. // violation
InputMissingJavadocTypeFullyQualifiedAnnotation2.SomeAnnotation
public interface C { }
}
@@ -0,0 +1,25 @@
/*
MissingJavadocType
scope = (default)public
excludeScope = (default)null
skipAnnotations = InputMissingJavadocTypeFullyQualifiedAnnotation3.SomeAnnotation
tokens = INTERFACE_DEF
*/

package com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype;

public class InputMissingJavadocTypeFullyQualifiedAnnotation3 {
public @interface SomeAnnotation { }

@SomeAnnotation // violation
public interface A { }

@InputMissingJavadocTypeFullyQualifiedAnnotation3.SomeAnnotation // ok
public interface B { }

@com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype. // violation
InputMissingJavadocTypeFullyQualifiedAnnotation3.SomeAnnotation
public interface C { }
}
@@ -0,0 +1,26 @@
/*
MissingJavadocType
scope = (default)public
excludeScope = (default)null
skipAnnotations = com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype.\
InputMissingJavadocTypeFullyQualifiedAnnotation4.SomeAnnotation
tokens = INTERFACE_DEF
*/

package com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype;

public class InputMissingJavadocTypeFullyQualifiedAnnotation4 {
public @interface SomeAnnotation { }

@SomeAnnotation // violation
public interface A { }

@InputMissingJavadocTypeFullyQualifiedAnnotation4.SomeAnnotation // violation
public interface B { }

@com.puppycrawl.tools.checkstyle.checks.javadoc.missingjavadoctype. // ok
InputMissingJavadocTypeFullyQualifiedAnnotation4.SomeAnnotation
public interface C { }
}

0 comments on commit 66c557a

Please sign in to comment.