Unify repr of annotations
This commit is contained in:
@ -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,83 @@
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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("\\.");
|
||||
public String getSimpleName() {
|
||||
String[] split = getAnnotationName().split("\\.");
|
||||
return split[split.length - 1];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* 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() {
|
||||
|
@ -15,8 +15,11 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
*
|
||||
* @see ASTSingleMemberAnnotation
|
||||
* @see ASTNormalAnnotation
|
||||
*
|
||||
* @deprecated Replaced with {@link ASTAnnotation}
|
||||
*/
|
||||
public final class ASTMarkerAnnotation extends AbstractJavaTypeNode implements ASTAnnotation {
|
||||
@Deprecated
|
||||
public final class ASTMarkerAnnotation extends AbstractJavaTypeNode {
|
||||
|
||||
ASTMarkerAnnotation(int id) {
|
||||
super(id);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,11 @@ import java.util.Iterator;
|
||||
*
|
||||
* @see ASTSingleMemberAnnotation
|
||||
* @see ASTMarkerAnnotation
|
||||
* @deprecated Replaced with {@link ASTAnnotation}
|
||||
*/
|
||||
public final class ASTNormalAnnotation extends AbstractJavaTypeNode implements ASTAnnotation, Iterable<ASTMemberValuePair> {
|
||||
@Deprecated
|
||||
public final class ASTNormalAnnotation extends AbstractJavaTypeNode implements Iterable<ASTMemberValuePair> {
|
||||
|
||||
ASTNormalAnnotation(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
@ -15,8 +15,11 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
*
|
||||
* @see ASTMarkerAnnotation
|
||||
* @see ASTNormalAnnotation
|
||||
* @deprecated Replaced with {@link ASTAnnotation}
|
||||
*/
|
||||
public final class ASTSingleMemberAnnotation extends AbstractJavaTypeNode implements ASTAnnotation {
|
||||
@Deprecated
|
||||
public final class ASTSingleMemberAnnotation extends AbstractJavaTypeNode {
|
||||
|
||||
ASTSingleMemberAnnotation(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
@ -5,8 +5,6 @@
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
@ -30,11 +28,6 @@ public final class ASTTypeParameter extends AbstractJavaTypeNode implements Anno
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return children(ASTAnnotation.class).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the type variable introduced by this declaration.
|
||||
*/
|
||||
|
@ -11,6 +11,8 @@ 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 +33,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,25 +15,6 @@ 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);
|
||||
}
|
||||
|
||||
// TODO delegation
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -125,6 +125,7 @@ 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);
|
||||
|
@ -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,7 @@ package net.sourceforge.pmd.lang.java.rule.design;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||
@ -17,9 +17,10 @@ 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.ast.TypeNode;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractLombokAwareRule;
|
||||
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
|
||||
|
||||
public class UseUtilityClassRule extends AbstractLombokAwareRule {
|
||||
|
||||
@ -99,29 +100,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((Predicate<TypeNode>) 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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -56,11 +56,11 @@ class ASTCastExpressionTest : ParserTestSpec({
|
||||
castExpr {
|
||||
it::getCastType shouldBe child<ASTIntersectionType> {
|
||||
|
||||
it::getDeclaredAnnotations shouldBe emptyList()
|
||||
it::declaredAnnotationsList shouldBe emptyList()
|
||||
|
||||
classType("Foo") {
|
||||
// annotations nest on the inner node
|
||||
it::getDeclaredAnnotations shouldBe listOf(annotation("F"))
|
||||
it::declaredAnnotationsList shouldBe listOf(annotation("F"))
|
||||
}
|
||||
|
||||
classType("Bar")
|
||||
@ -76,15 +76,15 @@ class ASTCastExpressionTest : ParserTestSpec({
|
||||
castExpr {
|
||||
it::getCastType shouldBe child<ASTIntersectionType> {
|
||||
|
||||
it::getDeclaredAnnotations shouldBe emptyList()
|
||||
it::declaredAnnotationsList shouldBe emptyList()
|
||||
|
||||
classType("Foo") {
|
||||
// annotations nest on the inner node
|
||||
it::getDeclaredAnnotations shouldBe listOf(annotation("F"))
|
||||
it::declaredAnnotationsList shouldBe listOf(annotation("F"))
|
||||
}
|
||||
|
||||
classType("Bar") {
|
||||
it::getDeclaredAnnotations shouldBe listOf(annotation("B"), annotation("C"))
|
||||
it::declaredAnnotationsList shouldBe listOf(annotation("B"), annotation("C"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,3 +140,6 @@ class ASTCastExpressionTest : ParserTestSpec({
|
||||
|
||||
|
||||
})
|
||||
|
||||
val Annotatable.declaredAnnotationsList: List<ASTAnnotation>
|
||||
get() = declaredAnnotations.toList()
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast
|
||||
|
||||
import io.kotlintest.shouldBe
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBe
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType.PrimitiveType
|
||||
|
||||
@ -52,7 +53,7 @@ class ASTConstructorDeclarationTest : ParserTestSpec({
|
||||
}
|
||||
}
|
||||
|
||||
it::toList shouldBe listOf(
|
||||
it.toList() shouldBe listOf(
|
||||
child {
|
||||
localVarModifiers { }
|
||||
primitiveType(PrimitiveType.INT)
|
||||
|
@ -102,7 +102,7 @@ class ASTEnumConstantTest : ParserTestSpec({
|
||||
val c = it
|
||||
|
||||
it::getModifiers shouldBe modifiers {
|
||||
c::getDeclaredAnnotations shouldBe listOf(annotation("C"))
|
||||
c::declaredAnnotationsList shouldBe listOf(annotation("C"))
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +118,7 @@ class ASTEnumConstantTest : ParserTestSpec({
|
||||
val c = it
|
||||
|
||||
it::getModifiers shouldBe modifiers {
|
||||
c::getDeclaredAnnotations shouldBe listOf(annotation("A"), annotation("a"))
|
||||
c::declaredAnnotationsList shouldBe listOf(annotation("A"), annotation("a"))
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.sourceforge.pmd.lang.java.ast
|
||||
|
||||
import io.kotlintest.should
|
||||
import io.kotlintest.shouldBe
|
||||
import io.kotlintest.shouldNot
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBe
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType.PrimitiveType
|
||||
@ -399,7 +400,7 @@ class ASTMethodDeclarationTest : ParserTestSpec({
|
||||
it::getResultType shouldBe voidResult()
|
||||
|
||||
it::getFormalParameters shouldBe formalsList(0) {
|
||||
it::toList shouldBe emptyList()
|
||||
it.toList() shouldBe emptyList()
|
||||
|
||||
it::getReceiverParameter shouldBe child {
|
||||
classType("Foo") {
|
||||
@ -434,7 +435,7 @@ class ASTMethodDeclarationTest : ParserTestSpec({
|
||||
}
|
||||
}
|
||||
|
||||
it::toList shouldBe listOf(
|
||||
it.toList() shouldBe listOf(
|
||||
child {
|
||||
localVarModifiers { }
|
||||
primitiveType(PrimitiveType.INT)
|
||||
|
@ -472,8 +472,14 @@ fun TreeNodeWrapper<Node, *>.ambiguousName(image: String, contents: NodeSpec<AST
|
||||
|
||||
fun TreeNodeWrapper<Node, *>.memberValuePair(name: String, contents: ValuedNodeSpec<ASTMemberValuePair, ASTMemberValue>) =
|
||||
child<ASTMemberValuePair> {
|
||||
it::getMemberName shouldBe name
|
||||
it::getMemberValue shouldBe contents()
|
||||
it::getName shouldBe name
|
||||
it::getValue shouldBe contents()
|
||||
}
|
||||
|
||||
fun TreeNodeWrapper<Node, *>.shorthandMemberValue(contents: ValuedNodeSpec<ASTMemberValuePair, ASTMemberValue>) =
|
||||
memberValuePair("value") {
|
||||
it::isShorthand shouldBe true
|
||||
contents()
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user