Merge branch 'pr-2282' into java-grammar
[java] Use single node for annotations
This commit is contained in:
@ -138,6 +138,20 @@ public final class StringUtil {
|
||||
return col;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the substring following the last occurrence of the
|
||||
* given character. If the character doesn't occur, returns
|
||||
* the whole string. This contrasts with {@link StringUtils#substringAfterLast(String, String)},
|
||||
* which returns the empty string in that case.
|
||||
*
|
||||
* @param str String to cut
|
||||
* @param c Delimiter
|
||||
*/
|
||||
public static String substringAfterLast(String str, int c) {
|
||||
int i = str.lastIndexOf(c);
|
||||
return i < 0 ? str : str.substring(i + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a double to a percentage, keeping {@code numDecimal} decimal places.
|
||||
*
|
||||
|
@ -2282,47 +2282,32 @@ void RSIGNEDSHIFT() #void:
|
||||
|
||||
/* Annotation syntax follows. */
|
||||
|
||||
void Annotation() #void:
|
||||
void Annotation():
|
||||
{}
|
||||
{
|
||||
LOOKAHEAD( "@" VoidName() "(" ( <IDENTIFIER> "=" | ")" ))
|
||||
NormalAnnotation()
|
||||
|
|
||||
LOOKAHEAD( "@" VoidName() "(" )
|
||||
SingleMemberAnnotation()
|
||||
|
|
||||
MarkerAnnotation()
|
||||
"@" jjtThis.name=VoidName() [ AnnotationMemberList() ]
|
||||
}
|
||||
|
||||
void AnnotationBase(Node n) #void:
|
||||
{String name = null;}
|
||||
{
|
||||
"@" name=VoidName() {n.setImage(name);}
|
||||
}
|
||||
|
||||
void NormalAnnotation():
|
||||
void AnnotationMemberList():
|
||||
{}
|
||||
{
|
||||
AnnotationBase(jjtThis) "(" [ MemberValuePairs() ] ")"
|
||||
"("
|
||||
( LOOKAHEAD(<IDENTIFIER> "=")
|
||||
MemberValuePair() ( "," MemberValuePair() )*
|
||||
| [ ShorthandAnnotationValue() ]
|
||||
)
|
||||
")"
|
||||
}
|
||||
|
||||
void MarkerAnnotation():
|
||||
{}
|
||||
void ShorthandAnnotationValue() #MemberValuePair:
|
||||
{
|
||||
AnnotationBase(jjtThis)
|
||||
jjtThis.setImage("value");
|
||||
jjtThis.setShorthand();
|
||||
}
|
||||
{
|
||||
MemberValue()
|
||||
}
|
||||
|
||||
void SingleMemberAnnotation():
|
||||
{}
|
||||
{
|
||||
AnnotationBase(jjtThis) "(" MemberValue() ")"
|
||||
}
|
||||
|
||||
void MemberValuePairs() #void:
|
||||
{}
|
||||
{
|
||||
MemberValuePair() ( "," MemberValuePair() )*
|
||||
}
|
||||
|
||||
void MemberValuePair():
|
||||
{}
|
||||
@ -2334,11 +2319,8 @@ void MemberValue() #void:
|
||||
{}
|
||||
{
|
||||
Annotation()
|
||||
|
|
||||
MemberValueArrayInitializer()
|
||||
|
|
||||
// Constant expression
|
||||
ConditionalExpression()
|
||||
| MemberValueArrayInitializer()
|
||||
| ConditionalExpression() // Constant expression
|
||||
}
|
||||
|
||||
void MemberValueArrayInitializer():
|
||||
@ -2471,12 +2453,8 @@ String VoidName() #void:
|
||||
JavaccToken t;
|
||||
}
|
||||
{
|
||||
t=<IDENTIFIER>
|
||||
{
|
||||
s.append(t.getImage());
|
||||
}
|
||||
( LOOKAHEAD(2) "." t=<IDENTIFIER>
|
||||
{s.append('.').append(t.getImage());}
|
||||
t=<IDENTIFIER> { s.append(t.getImage()); }
|
||||
( LOOKAHEAD(2) "." t=<IDENTIFIER> {s.append('.').append(t.getImage());}
|
||||
)*
|
||||
{return s.toString();}
|
||||
}
|
||||
|
@ -4,38 +4,82 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Represents an annotation. This node has three specific syntactic variants,
|
||||
* represented by nodes that implement this interface.
|
||||
* Represents an annotation.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* Annotation ::= {@linkplain ASTNormalAnnotation NormalAnnotation}
|
||||
* | {@linkplain ASTSingleMemberAnnotation SingleMemberAnnotation}
|
||||
* | {@linkplain ASTMarkerAnnotation MarkerAnnotation}
|
||||
* Annotation ::= "@" Name {@link ASTAnnotationMemberList AnnotationMemberList}?
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public interface ASTAnnotation extends TypeNode, ASTMemberValue {
|
||||
public final class ASTAnnotation extends AbstractJavaTypeNode implements TypeNode, ASTMemberValue, Iterable<ASTMemberValuePair> {
|
||||
|
||||
String name;
|
||||
|
||||
ASTAnnotation(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the annotation as it is used,
|
||||
* eg {@code java.lang.Override} or {@code Override}.
|
||||
*/
|
||||
default String getAnnotationName() {
|
||||
return getImage();
|
||||
public String getAnnotationName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String getImage() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simple name of the annotation.
|
||||
*/
|
||||
default String getSimpleName() {
|
||||
String[] split = getImage().split("\\.");
|
||||
return split[split.length - 1];
|
||||
public String getSimpleName() {
|
||||
return StringUtil.substringAfterLast(getImage(), '.');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* Returns the list of members, or null if there is none.
|
||||
*/
|
||||
public @Nullable ASTAnnotationMemberList getMemberList() {
|
||||
return children().first(ASTAnnotationMemberList.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stream of explicit members for this annotation.
|
||||
*/
|
||||
public NodeStream<ASTMemberValuePair> getMembers() {
|
||||
return children(ASTAnnotationMemberList.class).children(ASTMemberValuePair.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<ASTMemberValuePair> iterator() {
|
||||
return children(ASTMemberValuePair.class).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
|
||||
/**
|
||||
* Represents the list of {@link ASTMemberValuePair member-value pairs}
|
||||
* in an {@link ASTAnnotation annotation}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* AnnotationMemberList ::= "(" {@link ASTMemberValuePair MemberValuePair} ( "," {@link ASTMemberValuePair MemberValuePair} )* ")"
|
||||
* | "(" {@link ASTMemberValuePair ValueShorthand} ")"
|
||||
* | "(" ")"
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTAnnotationMemberList extends AbstractJavaNode implements Iterable<ASTMemberValuePair> {
|
||||
|
||||
ASTAnnotationMemberList(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ASTAnnotation getParent() {
|
||||
return (ASTAnnotation) super.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public NodeStream<ASTMemberValuePair> children() {
|
||||
return (NodeStream<ASTMemberValuePair>) super.children();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ASTMemberValuePair> iterator() {
|
||||
return children().iterator();
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.List;
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
|
||||
/**
|
||||
* Represents an array type.
|
||||
@ -23,11 +23,8 @@ public final class ASTArrayType extends AbstractJavaTypeNode implements ASTRefer
|
||||
|
||||
|
||||
@Override
|
||||
public List<ASTAnnotation> getDeclaredAnnotations() {
|
||||
// an array type's annotations are on its dimensions
|
||||
// any annotations found before the element type apply to the
|
||||
// element type
|
||||
return ((ASTArrayTypeDim) getDimensions().getLastChild()).getDeclaredAnnotations();
|
||||
public NodeStream<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return getDimensions().getLastChild().getDeclaredAnnotations();
|
||||
}
|
||||
|
||||
public ASTArrayDimensions getDimensions() {
|
||||
|
@ -1,38 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
/**
|
||||
* Represents an annotation with no declared member, e.g. {@code @Override}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* MarkerAnnotation ::= "@" Name
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see ASTSingleMemberAnnotation
|
||||
* @see ASTNormalAnnotation
|
||||
*/
|
||||
public final class ASTMarkerAnnotation extends AbstractJavaTypeNode implements ASTAnnotation {
|
||||
|
||||
ASTMarkerAnnotation(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
/**
|
||||
* Represents the value of a member of an annotation.
|
||||
* This can appear in a {@linkplain ASTMemberValuePair member-value pair},
|
||||
* in a {@linkplain ASTSingleMemberAnnotation single-member annotation},
|
||||
* or in the {@linkplain ASTDefaultValue default clause} of an annotation
|
||||
* method.
|
||||
*
|
||||
|
@ -5,38 +5,54 @@
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
/**
|
||||
* Represents a single member-value pair in a {@linkplain ASTNormalAnnotation NormalAnnotation}.
|
||||
* Represents a single pair of member name to value in an annotation.
|
||||
* This node also represents the shorthand syntax, see {@link #isShorthand()}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* MemberValuePair ::= <IDENTIFIER> "=" {@linkplain ASTMemberValue MemberValue}
|
||||
* MemberValuePair ::= <IDENTIFIER> "=" {@linkplain ASTMemberValue MemberValue}
|
||||
*
|
||||
* ValueShorthand ::= {@linkplain ASTMemberValue MemberValue}
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTMemberValuePair extends AbstractJavaNode {
|
||||
|
||||
private boolean isShorthand;
|
||||
|
||||
ASTMemberValuePair(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the member set by this pair.
|
||||
* This returns {@code "value"} if this is a shorthand declaration.
|
||||
*/
|
||||
public String getMemberName() {
|
||||
public String getName() {
|
||||
return getImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a shorthand for the {@code value} attribute.
|
||||
* For example, {@code @A("v")} has exactly the same structure as
|
||||
* {@code @A(value = "v")}, except this attribute returns true for
|
||||
* the first one only.
|
||||
*/
|
||||
public boolean isShorthand() {
|
||||
return isShorthand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the member set by this pair.
|
||||
*/
|
||||
public ASTMemberValue getMemberValue() {
|
||||
public ASTMemberValue getValue() {
|
||||
return (ASTMemberValue) getChild(0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ASTNormalAnnotation getParent() {
|
||||
return (ASTNormalAnnotation) super.getParent();
|
||||
public ASTAnnotationMemberList getParent() {
|
||||
return (ASTAnnotationMemberList) super.getParent();
|
||||
}
|
||||
|
||||
|
||||
@ -50,4 +66,8 @@ public final class ASTMemberValuePair extends AbstractJavaNode {
|
||||
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
void setShorthand() {
|
||||
this.isShorthand = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a list of member values in an {@linkplain ASTNormalAnnotation annotation}.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* MemberValuePairs ::= {@linkplain ASTMemberValuePair MemberValuePair} ( "," {@linkplain ASTMemberValuePair MemberValuePair} )*
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @deprecated Removed from the tree, added no info
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ASTMemberValuePairs extends AbstractJavaNode implements Iterable<ASTMemberValuePair> {
|
||||
|
||||
ASTMemberValuePairs(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ASTMemberValuePair getChild(int index) {
|
||||
return (ASTMemberValuePair) super.getChild(index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ASTNormalAnnotation getParent() {
|
||||
return (ASTNormalAnnotation) super.getParent();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<ASTMemberValuePair> iterator() {
|
||||
return children(ASTMemberValuePair.class).iterator();
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Represents an annotation that with a parenthesized list
|
||||
* of key-value pairs (possibly empty).
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* NormalAnnotation ::= "@" Name "(" ( {@linkplain ASTMemberValuePair MemberValuePair} ( "," {@linkplain ASTMemberValuePair MemberValuePair} )* )? ")"
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see ASTSingleMemberAnnotation
|
||||
* @see ASTMarkerAnnotation
|
||||
*/
|
||||
public final class ASTNormalAnnotation extends AbstractJavaTypeNode implements ASTAnnotation, Iterable<ASTMemberValuePair> {
|
||||
ASTNormalAnnotation(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<ASTMemberValuePair> iterator() {
|
||||
return children(ASTMemberValuePair.class).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
/**
|
||||
* Represents an annotation using the shorthand syntax for the default member.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* SingleMemberAnnotation ::= "@" Name "(" {@linkplain ASTMemberValue MemberValue} ")"
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see ASTMarkerAnnotation
|
||||
* @see ASTNormalAnnotation
|
||||
*/
|
||||
public final class ASTSingleMemberAnnotation extends AbstractJavaTypeNode implements ASTAnnotation {
|
||||
ASTSingleMemberAnnotation(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of the default member
|
||||
* set by this annotation.
|
||||
*/
|
||||
public ASTMemberValue getMemberValue() {
|
||||
return (ASTMemberValue) getChild(0);
|
||||
}
|
||||
|
||||
}
|
@ -5,8 +5,6 @@
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.symbols.JTypeParameterSymbol;
|
||||
@ -32,11 +30,6 @@ public final class ASTTypeParameter extends AbstractTypedSymbolDeclarator<JTypeP
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return children(ASTAnnotation.class).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the type variable introduced by this declaration.
|
||||
*/
|
||||
|
@ -6,11 +6,12 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import static net.sourceforge.pmd.lang.java.ast.JModifier.STRICTFP;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
|
||||
/**
|
||||
* A node that owns a {@linkplain ASTModifierList modifier list}.
|
||||
*
|
||||
@ -31,10 +32,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
*/
|
||||
public interface AccessNode extends Annotatable {
|
||||
|
||||
|
||||
@Override
|
||||
default List<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return getModifiers().children(ASTAnnotation.class).toList();
|
||||
default NodeStream<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return getModifiers().children(ASTAnnotation.class);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,11 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.NodeStream;
|
||||
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
|
||||
|
||||
/**
|
||||
@ -24,54 +22,25 @@ public interface Annotatable extends JavaNode {
|
||||
/**
|
||||
* Returns all annotations present on this node.
|
||||
*/
|
||||
default List<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return this.findChildrenOfType(ASTAnnotation.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the annotation with the given qualified name if it is present,
|
||||
* otherwise returns null. The argument should be a qualified name, though
|
||||
* this method will find also usages of an annotation that use the simple
|
||||
* name if it is in scope.
|
||||
*
|
||||
* <p>E.g. {@code getAnnotation("java.lang.Override")} will find both
|
||||
* {@code @java.lang.Override} and {@code @Override}.
|
||||
*/
|
||||
@Nullable
|
||||
default ASTAnnotation getAnnotation(String annotQualifiedName) {
|
||||
// TODO use node streams
|
||||
List<ASTAnnotation> annotations = getDeclaredAnnotations();
|
||||
for (ASTAnnotation annotation : annotations) {
|
||||
if (TypeHelper.isA(annotation, annotQualifiedName)) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if any annotation in the given collection is present,
|
||||
* using {@link #isAnnotationPresent(String)}, otherwise false.
|
||||
*/
|
||||
default boolean isAnyAnnotationPresent(Collection<String> annotQualifiedNames) {
|
||||
// TODO use node streams
|
||||
for (String annotQualifiedName : annotQualifiedNames) {
|
||||
if (isAnnotationPresent(annotQualifiedName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default NodeStream<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return children(ASTAnnotation.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if an annotation with the given qualified name is
|
||||
* applied to this node. In this case, {@link #getAnnotation(String)}
|
||||
* will not return null.
|
||||
* applied to this node.
|
||||
*/
|
||||
default boolean isAnnotationPresent(String annotQualifiedName) {
|
||||
return getAnnotation(annotQualifiedName) != null;
|
||||
return getDeclaredAnnotations().any(t -> TypeHelper.isA(t, annotQualifiedName));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if an annotation with the given type is
|
||||
* applied to this node.
|
||||
*/
|
||||
default boolean isAnnotationPresent(Class<?> type) {
|
||||
return getDeclaredAnnotations().any((Predicate<TypeNode>) t -> TypeHelper.subclasses(t, type));
|
||||
}
|
||||
}
|
||||
|
@ -25,24 +25,6 @@ import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
public class JavaParserVisitorAdapter implements JavaParserVisitor {
|
||||
|
||||
|
||||
public Object visit(ASTAnnotation node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMarkerAnnotation node, Object data) {
|
||||
return visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTSingleMemberAnnotation node, Object data) {
|
||||
return visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTNormalAnnotation node, Object data) {
|
||||
return visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
public Object visit(ASTType node, Object data) {
|
||||
return visit((JavaNode) node, data);
|
||||
|
@ -15,44 +15,22 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
public class SideEffectingVisitorAdapter<T> implements SideEffectingVisitor<T> {
|
||||
|
||||
|
||||
public void visit(ASTAnnotation node, T data) {
|
||||
visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ASTSingleMemberAnnotation node, T data) {
|
||||
visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ASTNormalAnnotation node, T data) {
|
||||
visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ASTMarkerAnnotation node, T data) {
|
||||
visit((ASTAnnotation) node, data);
|
||||
}
|
||||
|
||||
|
||||
public void visit(ASTMethodOrConstructorDeclaration node, T data) {
|
||||
visit((JavaNode) node, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visit(ASTMethodDeclaration node, T data) {
|
||||
visit((ASTMethodOrConstructorDeclaration) node, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visit(ASTConstructorDeclaration node, T data) {
|
||||
visit((ASTMethodOrConstructorDeclaration) node, data);
|
||||
}
|
||||
|
||||
|
||||
// TODO delegation
|
||||
|
||||
|
||||
public void visit(ASTAnyTypeDeclaration node, T data) {
|
||||
visit((JavaNode) node, data);
|
||||
}
|
||||
|
@ -38,6 +38,6 @@ public abstract class AbstractIgnoredAnnotationRule extends AbstractJavaRule {
|
||||
* @return <code>true</code> if the annotation has been found, otherwise <code>false</code>
|
||||
*/
|
||||
protected boolean hasIgnoredAnnotation(Annotatable node) {
|
||||
return node.isAnyAnnotationPresent(getProperty(ignoredAnnotationsDescriptor));
|
||||
return getProperty(ignoredAnnotationsDescriptor).stream().anyMatch(node::isAnnotationPresent);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import net.sourceforge.pmd.lang.java.JavaLanguageModule;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAdditiveExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAndExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTArguments;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
@ -106,9 +105,6 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse
|
||||
// FIXME those are not in sync with JavaParserVisitorAdapter
|
||||
// See #1786
|
||||
|
||||
public Object visit(ASTAnnotation node, Object data) {
|
||||
return JavaParserVisitor.super.visit(node, data);
|
||||
}
|
||||
|
||||
public Object visit(ASTExpression node, Object data) {
|
||||
return JavaParserVisitor.super.visit(node, data);
|
||||
|
@ -136,6 +136,6 @@ public class AbstractLombokAwareRule extends AbstractIgnoredAnnotationRule {
|
||||
* @return <code>true</code> if a lombok annotation has been found
|
||||
*/
|
||||
protected boolean hasLombokAnnotation(Annotatable node) {
|
||||
return node.isAnyAnnotationPresent(LOMBOK_ANNOTATIONS);
|
||||
return LOMBOK_ANNOTATIONS.stream().anyMatch(node::isAnnotationPresent);
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMemberValuePair;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTNormalAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
|
||||
@ -41,7 +39,7 @@ public class JUnitTestsShouldIncludeAssertRule extends AbstractJUnitRule {
|
||||
@Override
|
||||
public Object visit(ASTMethodDeclaration method, Object data) {
|
||||
if (isJUnitMethod(method, data)) {
|
||||
if (!isExpectAnnotated(method.getParent())) {
|
||||
if (!isExpectAnnotated(method)) {
|
||||
Map<String, VariableNameDeclaration> variables = getVariables(method);
|
||||
|
||||
Scope classScope = method.getScope().getParent();
|
||||
@ -98,10 +96,9 @@ public class JUnitTestsShouldIncludeAssertRule extends AbstractJUnitRule {
|
||||
|
||||
for (Map.Entry<NameDeclaration, List<NameOccurrence>> entry : decls.entrySet()) {
|
||||
Node parent = entry.getKey().getNode().getParent().getParent().getParent();
|
||||
if (parent.hasDescendantOfType(ASTMarkerAnnotation.class)
|
||||
&& parent.getFirstChildOfType(ASTFieldDeclaration.class) != null) {
|
||||
String annot = parent.getFirstDescendantOfType(ASTMarkerAnnotation.class).getChild(0).getImage();
|
||||
if (!"Rule".equals(annot) && !"org.junit.Rule".equals(annot)) {
|
||||
if (parent.getFirstChildOfType(ASTFieldDeclaration.class) != null) {
|
||||
ASTAnnotation annot = parent.getFirstDescendantOfType(ASTAnnotation.class);
|
||||
if (annot == null || !TypeHelper.isA(annot, "org.junit.Rule")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -118,20 +115,12 @@ public class JUnitTestsShouldIncludeAssertRule extends AbstractJUnitRule {
|
||||
/**
|
||||
* Tells if the node contains a Test annotation with an expected exception.
|
||||
*/
|
||||
private boolean isExpectAnnotated(Node methodParent) {
|
||||
List<ASTNormalAnnotation> annotations = methodParent.findDescendantsOfType(ASTNormalAnnotation.class);
|
||||
for (ASTNormalAnnotation annotation : annotations) {
|
||||
ASTName name = annotation.getFirstChildOfType(ASTName.class);
|
||||
if (name != null && TypeHelper.isA(name, JUNIT4_CLASS_NAME)) {
|
||||
List<ASTMemberValuePair> memberValues = annotation.findDescendantsOfType(ASTMemberValuePair.class);
|
||||
for (ASTMemberValuePair pair : memberValues) {
|
||||
if ("expected".equals(pair.getImage())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
private boolean isExpectAnnotated(ASTMethodDeclaration method) {
|
||||
return method.getDeclaredAnnotations()
|
||||
.filter(it -> TypeHelper.isA(it, JUNIT4_CLASS_NAME))
|
||||
.flatMap(ASTAnnotation::getMembers)
|
||||
.any(it -> "expected".equals(it.getName()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,14 +5,12 @@
|
||||
package net.sourceforge.pmd.lang.java.rule.bestpractices;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTResultType;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaNode;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
import net.sourceforge.pmd.util.CollectionUtil;
|
||||
|
||||
@ -44,17 +42,8 @@ public class LooseCouplingRule extends AbstractJavaRule {
|
||||
return data;
|
||||
}
|
||||
|
||||
private boolean methodHasOverride(Node node) {
|
||||
ASTClassOrInterfaceBodyDeclaration method = node.getFirstParentOfType(ASTClassOrInterfaceBodyDeclaration.class);
|
||||
if (method != null && method.getNumChildren() > 0 && method.getChild(0) instanceof ASTAnnotation) {
|
||||
ASTMarkerAnnotation marker = method.getFirstDescendantOfType(ASTMarkerAnnotation.class);
|
||||
if (marker != null && marker.getFirstChildOfType(ASTName.class) != null) {
|
||||
ASTName name = marker.getFirstChildOfType(ASTName.class);
|
||||
if (name.getType() == Override.class) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
private boolean methodHasOverride(JavaNode node) {
|
||||
ASTMethodDeclaration method = node.ancestors(ASTMethodDeclaration.class).first();
|
||||
return method != null && method.isAnnotationPresent(Override.class);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import java.util.Stack;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant;
|
||||
@ -213,11 +212,9 @@ public class MissingOverrideRule extends AbstractJavaRule {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
for (ASTAnnotation annot : node.getDeclaredAnnotations()) {
|
||||
if (Override.class.equals(annot.getType())) {
|
||||
// we assume the compiler has already checked it, so it's correct
|
||||
return super.visit(node, data);
|
||||
}
|
||||
if (node.isAnnotationPresent(Override.class)) {
|
||||
// we assume the compiler has already checked it, so it's correct
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -18,10 +18,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTThrowsList;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
@ -125,17 +123,6 @@ public class UnusedFormalParameterRule extends AbstractJavaRule {
|
||||
}
|
||||
|
||||
private boolean hasOverrideAnnotation(ASTMethodDeclaration node) {
|
||||
int childIndex = node.getIndexInParent();
|
||||
for (int i = 0; i < childIndex; i++) {
|
||||
Node previousSibling = node.getParent().getChild(i);
|
||||
List<ASTMarkerAnnotation> annotations = previousSibling.findDescendantsOfType(ASTMarkerAnnotation.class);
|
||||
for (ASTMarkerAnnotation annotation : annotations) {
|
||||
ASTName name = annotation.getFirstChildOfType(ASTName.class);
|
||||
if (name != null && (name.hasImageEqualTo("Override") || name.hasImageEqualTo("java.lang.Override"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return node.isAnnotationPresent(Override.class);
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public class MethodNamingConventionsRule extends AbstractNamingConventionRule<AS
|
||||
@Override
|
||||
public Object visit(ASTMethodDeclaration node, Object data) {
|
||||
|
||||
if (node.isAnnotationPresent("java.lang.Override")) {
|
||||
if (node.isAnnotationPresent(Override.class)) {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.design;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
@ -17,9 +16,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMemberValuePair;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTResultType;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractLombokAwareRule;
|
||||
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
|
||||
|
||||
public class UseUtilityClassRule extends AbstractLombokAwareRule {
|
||||
|
||||
@ -99,29 +98,16 @@ public class UseUtilityClassRule extends AbstractLombokAwareRule {
|
||||
|
||||
private boolean hasLombokNoArgsConstructor(ASTClassOrInterfaceDeclaration parent) {
|
||||
// check if there's a lombok no arg private constructor, if so skip the rest of the rules
|
||||
ASTAnnotation annotation = parent.getAnnotation("lombok.NoArgsConstructor");
|
||||
|
||||
if (annotation != null) {
|
||||
|
||||
List<ASTMemberValuePair> memberValuePairs = annotation.findDescendantsOfType(ASTMemberValuePair.class);
|
||||
|
||||
for (ASTMemberValuePair memberValuePair : memberValuePairs) {
|
||||
// to set the access level of a constructor in lombok, you set the access property on the annotation
|
||||
if ("access".equals(memberValuePair.getImage())) {
|
||||
List<ASTName> names = memberValuePair.findDescendantsOfType(ASTName.class);
|
||||
|
||||
for (ASTName name : names) {
|
||||
// check to see if the value of the member value pair ends PRIVATE. This is from the AccessLevel enum in Lombok
|
||||
if (name.getImage().endsWith("PRIVATE")) {
|
||||
// if the constructor is found and the accesslevel is private no need to check anything else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return parent.getDeclaredAnnotations()
|
||||
.filter(t -> TypeHelper.isA(t, "lombok.NoArgsConstructor"))
|
||||
.flatMap(ASTAnnotation::getMembers)
|
||||
// to set the access level of a constructor in lombok, you set the access property on the annotation
|
||||
.filterMatching(ASTMemberValuePair::getName, "access")
|
||||
.map(ASTMemberValuePair::getValue)
|
||||
// This is from the AccessLevel enum in Lombok
|
||||
// if the constructor is found and the accesslevel is private no need to check anything else
|
||||
.any(it -> it.getImage().equals("PRIVATE"));
|
||||
}
|
||||
|
||||
private Node skipAnnotations(Node p) {
|
||||
|
@ -10,7 +10,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTArguments;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTBlock;
|
||||
@ -19,7 +18,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
@ -31,6 +29,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTResultType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTStatement;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
|
||||
|
||||
@ -175,20 +174,8 @@ public class UselessOverridingMethodRule extends AbstractJavaRule {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
if (!ignoreAnnotations) {
|
||||
ASTClassOrInterfaceBodyDeclaration parent = (ASTClassOrInterfaceBodyDeclaration) node.getParent();
|
||||
for (int i = 0; i < parent.getNumChildren(); i++) {
|
||||
Node n = parent.getChild(i);
|
||||
if (n instanceof ASTAnnotation) {
|
||||
if (n.getChild(0) instanceof ASTMarkerAnnotation) {
|
||||
// @Override is ignored
|
||||
if ("Override".equals(((ASTName) n.getChild(0).getChild(0)).getImage())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return super.visit(node, data);
|
||||
}
|
||||
}
|
||||
if (!ignoreAnnotations && node.getDeclaredAnnotations().any(it -> !TypeHelper.isExactlyA(it, Override.class.getName()))) {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
if (arguments.getNumChildren() == 0) {
|
||||
|
@ -19,9 +19,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.AccessNode;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaNode;
|
||||
import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature;
|
||||
@ -178,13 +176,7 @@ public class CommentRequiredRule extends AbstractCommentRule {
|
||||
|
||||
|
||||
private boolean isAnnotatedOverride(ASTMethodDeclaration decl) {
|
||||
List<ASTMarkerAnnotation> annotations = decl.getParent().findDescendantsOfType(ASTMarkerAnnotation.class);
|
||||
for (ASTMarkerAnnotation ann : annotations) { // TODO consider making a method to get the annotations of a method
|
||||
if (ann.getFirstChildOfType(ASTName.class).getImage().equals("Override")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return decl.isAnnotationPresent(Override.class);
|
||||
}
|
||||
|
||||
|
||||
|
@ -104,12 +104,7 @@ final class AnnotationSuppressionUtil {
|
||||
}
|
||||
|
||||
private static boolean hasSuppressWarningsAnnotationFor(final Annotatable node, Rule rule) {
|
||||
for (ASTAnnotation a : node.getDeclaredAnnotations()) {
|
||||
if (annotationSuppresses(a, rule)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return node.getDeclaredAnnotations().any(it -> annotationSuppresses(it, rule));
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,9 +6,9 @@ package net.sourceforge.pmd.lang.java.ast
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBe
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaVersion.Companion.Earliest
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaVersion.Companion.Latest
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaVersion.J1_3
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaVersion.J1_5
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaVersion.Companion.Latest
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
@ -30,16 +30,20 @@ class ASTAnnotationTest : ParserTestSpec({
|
||||
inContext(AnnotationParsingCtx) {
|
||||
|
||||
"@F" should parseAs {
|
||||
child<ASTMarkerAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
it::getMemberList shouldBe null
|
||||
}
|
||||
}
|
||||
|
||||
"@java.lang.Override" should parseAs {
|
||||
child<ASTMarkerAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "java.lang.Override"
|
||||
it::getSimpleName shouldBe "Override"
|
||||
|
||||
it::getMemberList shouldBe null
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,45 +55,63 @@ class ASTAnnotationTest : ParserTestSpec({
|
||||
inContext(AnnotationParsingCtx) {
|
||||
|
||||
"@F(\"ohio\")" should parseAs {
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
it::getMemberValue shouldBe stringLit("\"ohio\"")
|
||||
it::getMemberList shouldBe child {
|
||||
shorthandMemberValue {
|
||||
stringLit("\"ohio\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"@org.F({java.lang.Math.PI})" should parseAs {
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "org.F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
it::getMemberValue shouldBe child<ASTMemberValueArrayInitializer> {
|
||||
child<ASTFieldAccess> {
|
||||
it::getFieldName shouldBe "PI"
|
||||
ambiguousName("java.lang.Math")
|
||||
it::getMemberList shouldBe child {
|
||||
shorthandMemberValue {
|
||||
child<ASTMemberValueArrayInitializer> {
|
||||
child<ASTFieldAccess> {
|
||||
it::getFieldName shouldBe "PI"
|
||||
ambiguousName("java.lang.Math")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"@org.F({@Aha, @Oh})" should parseAs {
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "org.F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
it::getMemberValue shouldBe child<ASTMemberValueArrayInitializer> {
|
||||
annotation("Aha")
|
||||
annotation("Oh")
|
||||
|
||||
it::getMemberList shouldBe child {
|
||||
shorthandMemberValue {
|
||||
child<ASTMemberValueArrayInitializer> {
|
||||
annotation("Aha")
|
||||
annotation("Oh")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"@org.F(@Oh)" should parseAs {
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "org.F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
it::getMemberValue shouldBe annotation("Oh")
|
||||
|
||||
it::getMemberList shouldBe child {
|
||||
shorthandMemberValue {
|
||||
annotation("Oh")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,44 +123,37 @@ class ASTAnnotationTest : ParserTestSpec({
|
||||
inContext(AnnotationParsingCtx) {
|
||||
|
||||
"@F(a=\"ohio\")" should parseAs {
|
||||
child<ASTNormalAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
memberValuePair("a") {
|
||||
stringLit("\"ohio\"")
|
||||
|
||||
it::getMemberList shouldBe child {
|
||||
memberValuePair("a") {
|
||||
stringLit("\"ohio\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"@org.F(a={java.lang.Math.PI}, b=2)" should parseAs {
|
||||
child<ASTNormalAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
it::getAnnotationName shouldBe "org.F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
memberValuePair("a") {
|
||||
child<ASTMemberValueArrayInitializer> {
|
||||
child<ASTFieldAccess> {
|
||||
it::getFieldName shouldBe "PI"
|
||||
ambiguousName("java.lang.Math")
|
||||
|
||||
it::getMemberList shouldBe child {
|
||||
memberValuePair("a") {
|
||||
child<ASTMemberValueArrayInitializer> {
|
||||
fieldAccess("PI") {
|
||||
ambiguousName("java.lang.Math")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memberValuePair("b") {
|
||||
number()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"@org.F({@Aha, @Oh})" should parseAs {
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
it::getAnnotationName shouldBe "org.F"
|
||||
it::getSimpleName shouldBe "F"
|
||||
|
||||
it::getMemberValue shouldBe child<ASTMemberValueArrayInitializer> {
|
||||
annotation("Aha")
|
||||
annotation("Oh")
|
||||
memberValuePair("b") {
|
||||
number()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,28 +161,45 @@ class ASTAnnotationTest : ParserTestSpec({
|
||||
|
||||
"""
|
||||
@TestAnnotation({@SuppressWarnings({}),
|
||||
@SuppressWarnings({"Beware the ides of March.",}),
|
||||
@SuppressWarnings(value = {"Beware the ides of March.",}),
|
||||
@SuppressWarnings({"Look both ways", "Before Crossing",}), })
|
||||
""" should parseAs {
|
||||
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
child<ASTAnnotation> {
|
||||
|
||||
it::getMemberValue shouldBe child<ASTMemberValueArrayInitializer> {
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
it::getMemberList shouldBe child {
|
||||
|
||||
it::getMemberValue shouldBe child<ASTMemberValueArrayInitializer> {}
|
||||
}
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
shorthandMemberValue {
|
||||
|
||||
it::getMemberValue shouldBe child<ASTMemberValueArrayInitializer> {
|
||||
stringLit("\"Beware the ides of March.\"")
|
||||
}
|
||||
}
|
||||
child<ASTSingleMemberAnnotation> {
|
||||
child<ASTMemberValueArrayInitializer> {
|
||||
annotation {
|
||||
|
||||
it::getMemberValue shouldBe child<ASTMemberValueArrayInitializer> {
|
||||
stringLit("\"Look both ways\"")
|
||||
stringLit("\"Before Crossing\"")
|
||||
it::getMemberList shouldBe child {
|
||||
shorthandMemberValue {
|
||||
child<ASTMemberValueArrayInitializer> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
annotation {
|
||||
it::getMemberList shouldBe child {
|
||||
memberValuePair("value") {
|
||||
it::isShorthand shouldBe false
|
||||
child<ASTMemberValueArrayInitializer> {
|
||||
stringLit("\"Beware the ides of March.\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
annotation {
|
||||
it::getMemberList shouldBe child {
|
||||
shorthandMemberValue {
|
||||
child<ASTMemberValueArrayInitializer> {
|
||||
stringLit("\"Look both ways\"")
|
||||
stringLit("\"Before Crossing\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ class ASTArrayTypeTest : ParserTestSpec({
|
||||
arrayType {
|
||||
it::getElementType shouldBe classType("ArrayTypes")
|
||||
|
||||
it::getDeclaredAnnotations shouldBe fromChild<ASTArrayDimensions, List<ASTAnnotation>> {
|
||||
it::declaredAnnotationsList shouldBe fromChild<ASTArrayDimensions, List<ASTAnnotation>> {
|
||||
|
||||
arrayDim { }
|
||||
arrayDim { }
|
||||
@ -44,7 +44,7 @@ class ASTArrayTypeTest : ParserTestSpec({
|
||||
|
||||
val lst = listOf(annotation("A"))
|
||||
|
||||
it::getDeclaredAnnotations shouldBe lst
|
||||
it::declaredAnnotationsList shouldBe lst
|
||||
|
||||
lst
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user