Rework AccessNode

Introduce a ModifierList node, that ranges
 over the modifiers of a declaration (including
annotations).

This is a combination of a few old commits:

Figure out modifiers

Fix tests

Remove AccessTypeNode

Document

Remove specific methods

Fix symboltable test

Fix tests

Rename to JModifier

Fix copypaste default/abstract

Improve doc

Test anon classes

Remove useless impl

Static modifier should not be present on toplevel classes

Simplify impl

Add visibility enum

Port some tests

Fix test ranges

Fix modifier ordering

Cleanup

Fix unnecessary modifier rule

Rename to use plural

Improve visibility doc

Simplify some things

Checkstyle

Remove some usages of typekind

Fix missing import

Remove irrelevant method

REmove some duplication

Replace AccessNode with ModifierOwner

Rename to AccessNode to reduce diff

Remove changes to rules

Add convenience methods

Make VariableDeclaratorId a ModifierOwner

Fix variable name decl

Make enum constant an implicit AccessNode

Fix compil

Checkstyle

Cleanup

Deprecate TypeKind

Cleanup

Remove TypeKind

Revert "Remove TypeKind"

This reverts commit 222c169c3401a01507726f339ae9f9b2b20dc69a.

Fix doc

Fix UnnecessaryModifierRule

Use special node instead of ModifierSet

Remove useless tests

Fix tests WIP

Work should be resumed when #2211 is merged into java-grammar

Fix some tests

Doc
This commit is contained in:
Clément Fournier
2019-07-01 15:55:14 +02:00
parent 01ef998d17
commit 3191ef360d
73 changed files with 1459 additions and 1509 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ import net.sourceforge.pmd.lang.java.ast.MethodLikeNode.MethodLikeKind;
* enclosing type is an annotation.
*/
@Deprecated
public final class ASTAnnotationMethodDeclaration extends AbstractJavaAccessNode {
public final class ASTAnnotationMethodDeclaration extends AbstractJavaNode implements AccessNode {
ASTAnnotationMethodDeclaration(int id) {
super(id);

View File

@ -4,27 +4,19 @@
package net.sourceforge.pmd.lang.java.ast;
import java.util.List;
/**
* The declaration of an annotation type.
*
* <p>Note that in constrast to interface types, no {@linkplain ASTExtendsList extends clause}
* <p>Note that in contrast to interface types, no {@linkplain ASTExtendsList extends clause}
* is permitted, and an annotation type cannot be generic.
*
* <pre class="grammar">
*
* AnnotationTypeDeclaration ::= AnnotationTypeModifier*
* AnnotationTypeDeclaration ::= {@link ASTModifierList ModifierList}
* "@" "interface"
* &lt;IDENTIFIER&gt;
* {@link ASTAnnotationTypeBody AnnotationTypeBody}
*
*
*
* AnnotationTypeModifier ::= "public" | "private" | "protected"
* | "abstract" | "static"
* | {@linkplain ASTAnnotation Annotation}
*
* </pre>
*
*/
@ -52,10 +44,9 @@ public final class ASTAnnotationTypeDeclaration extends AbstractAnyTypeDeclarati
return TypeKind.ANNOTATION;
}
@Override
public List<ASTAnyTypeBodyDeclaration> getDeclarations() {
return getFirstChildOfType(ASTAnnotationTypeBody.class)
.findChildrenOfType(ASTAnyTypeBodyDeclaration.class);
public boolean isInterface() {
return true;
}
}

View File

@ -4,23 +4,19 @@
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName;
/**
* An anonymous class declaration. This can occur in a {@linkplain ASTConstructorCall class instance creation expression}
* An anonymous class declaration. This can occur in a {@linkplain ASTConstructorCall class instance creation
* expression}
* or in an {@linkplain ASTEnumConstant enum constant declaration}.
*
*
* <pre class="grammar">
*
* AnonymousClassDeclaration ::= {@link ASTClassOrInterfaceBody}
* AnonymousClassDeclaration ::= {@link ASTModifierList EmptyModifierList} {@link ASTClassOrInterfaceBody}
*
* </pre>
*/
public final class ASTAnonymousClassDeclaration extends AbstractJavaTypeNode implements JavaQualifiableNode {
private JavaTypeQualifiedName qualifiedName;
public final class ASTAnonymousClassDeclaration extends AbstractAnyTypeDeclaration {
ASTAnonymousClassDeclaration(int id) {
@ -34,6 +30,11 @@ public final class ASTAnonymousClassDeclaration extends AbstractJavaTypeNode imp
}
@Override
public Visibility getVisibility() {
return Visibility.V_ANONYMOUS;
}
@Override
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
@ -45,27 +46,8 @@ public final class ASTAnonymousClassDeclaration extends AbstractJavaTypeNode imp
visitor.visit(this, data);
}
/**
* Returns the body of the anonymous class.
*/
public ASTClassOrInterfaceBody getBody() {
return (ASTClassOrInterfaceBody) getChild(0);
}
/**
* Returns the qualified name of the anonymous class
* declared by this node.
*/
@Override
public JavaTypeQualifiedName getQualifiedName() {
return qualifiedName;
public TypeKind getTypeKind() {
return TypeKind.CLASS;
}
public void setQualifiedName(JavaTypeQualifiedName qname) {
this.qualifiedName = qname;
}
}

View File

@ -4,22 +4,32 @@
package net.sourceforge.pmd.lang.java.ast;
import static net.sourceforge.pmd.lang.java.ast.JModifier.ABSTRACT;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
import net.sourceforge.pmd.lang.ast.NodeStream;
import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil;
import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName;
/**
* Groups enum, class, annotation and interface declarations.
*
* @author Clément Fournier
* Groups enum, class, annotation and interface declarations under a common
* supertype.
*/
public interface ASTAnyTypeDeclaration extends TypeNode, JavaQualifiableNode, AccessNode, JavaNode {
public interface ASTAnyTypeDeclaration extends TypeNode, JavaQualifiableNode, AccessNode, FinalizableNode {
/**
* @deprecated Use {@link #getBinaryName()}
*/
@Override
@Deprecated
JavaTypeQualifiedName getQualifiedName();
/**
@ -47,6 +57,15 @@ public interface ASTAnyTypeDeclaration extends TypeNode, JavaQualifiableNode, Ac
// @NotNull
String getBinaryName();
/**
* Returns true if this is an abstract type. Interfaces and annotations
* types are implicitly abstract.
*/
@Override
default boolean isAbstract() {
return hasModifiers(ABSTRACT);
}
/**
* Finds the type kind of this declaration.
@ -59,21 +78,31 @@ public interface ASTAnyTypeDeclaration extends TypeNode, JavaQualifiableNode, Ac
TypeKind getTypeKind();
/**
* Returns the enum constants declared by this enum. If this is not
* an enum declaration, returns an empty stream.
*/
default NodeStream<ASTEnumConstant> getEnumConstants() {
return getFirstChildOfType(ASTEnumBody.class).children(ASTEnumConstant.class);
}
/**
* Retrieves the member declarations (fields, methods, classes, etc.) from the body of this type declaration.
*
* @return The member declarations declared in this type declaration
*/
List<ASTAnyTypeBodyDeclaration> getDeclarations();
default List<ASTAnyTypeBodyDeclaration> getDeclarations() {
return getBody().children(ASTAnyTypeBodyDeclaration.class).toList();
}
/**
* @deprecated Use {@link #getBinaryName()}
* Returns the body of this type declaration.
*/
@Override
@Deprecated
JavaTypeQualifiedName getQualifiedName();
default ASTTypeBody getBody() {
return (ASTTypeBody) getLastChild();
}
default List<ASTTypeParameter> getTypeParameters() {
ASTTypeParameters parameters = getFirstChildOfType(ASTTypeParameters.class);
@ -85,22 +114,65 @@ public interface ASTAnyTypeDeclaration extends TypeNode, JavaQualifiableNode, Ac
}
/**
* Returns true if this type declaration is nested inside an interface, class or annotation.
* Returns true if this type declaration is nested inside an interface,
* class or annotation.
*/
default boolean isNested() {
return getParent() instanceof ASTClassOrInterfaceBodyDeclaration
|| getParent() instanceof ASTAnnotationTypeMemberDeclaration;
return getParent() instanceof ASTAnyTypeBodyDeclaration;
}
/**
* Returns true if this is a local class declaration.
* Returns true if the class is declared inside a block other
* than the body of another class, or the top level. Anonymous
* classes are not considered local. Only class declarations
* can be local. Local classes cannot be static.
*/
default boolean isLocal() {
return getParent() instanceof ASTLocalClassStatement;
}
/**
* Returns true if this type is declared at the top-level of a file.
*/
default boolean isTopLevel() {
return getParent() instanceof ASTTypeDeclaration;
}
/**
* Returns true if this is an {@linkplain ASTAnonymousClassDeclaration anonymous class declaration}.
*/
default boolean isAnonymous() {
return this instanceof ASTAnonymousClassDeclaration;
}
/**
* Returns true if this is an {@linkplain ASTEnumDeclaration enum class declaration}.
*/
default boolean isEnum() {
return this instanceof ASTEnumDeclaration;
}
/**
* Returns true if this is an interface type declaration (including
* annotation types). This is consistent with {@link Class#isInterface()}.
*/
default boolean isInterface() {
return false;
}
/** Returns true if this is an {@linkplain ASTAnnotationTypeDeclaration annotation type declaration}. */
default boolean isAnnotation() {
return this instanceof ASTAnnotationTypeDeclaration;
}
/**
* The kind of type this node declares.
*
@ -125,27 +197,7 @@ public interface ASTAnyTypeDeclaration extends TypeNode, JavaQualifiableNode, Ac
*/
@Deprecated
enum TypeKind {
CLASS, INTERFACE, ENUM, ANNOTATION;
public String getPrintableName() {
return name().toLowerCase(Locale.ROOT);
}
public static TypeKind ofClass(Class<?> clazz) {
if (clazz.isInterface()) {
return INTERFACE;
} else if (clazz.isEnum()) {
return ENUM;
} else if (clazz.isAnnotation()) {
return ANNOTATION;
} else {
return CLASS;
}
}
CLASS, INTERFACE, ENUM, ANNOTATION
}
}

View File

@ -13,11 +13,13 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*
* <pre class="grammar">
*
* CatchParameter ::= ( "final" | {@link ASTAnnotation Annotation} )* {@link ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
* CatchParameter ::= {@link ASTModifierList LocalVarModifierList} {@link ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
*
* </pre>
*/
public final class ASTCatchParameter extends AbstractJavaAccessNode implements InternalInterfaces.VariableIdOwner {
public final class ASTCatchParameter extends AbstractJavaNode
implements InternalInterfaces.VariableIdOwner,
FinalizableNode {
ASTCatchParameter(int id) {
super(id);

View File

@ -17,18 +17,13 @@ import net.sourceforge.pmd.util.CollectionUtil;
*
* <pre class="grammar">
*
* ClassOrInterfaceDeclaration ::= ClassModifier*
* ClassOrInterfaceDeclaration ::= {@link ASTModifierList ModifierList}
* ( "class" | "interface" )
* &lt;IDENTIFIER&gt;
* {@linkplain ASTTypeParameters TypeParameters}?
* {@linkplain ASTExtendsList ExtendsList}?
* {@linkplain ASTImplementsList ImplementsList}?
* {@linkplain ASTClassOrInterfaceBody ClassOrInterfaceBody}
*
*
* ClassModifier ::= "public" | "private" | "protected"
* | "final" | "abstract" | "static" | "strictfp"
* | {@linkplain ASTAnnotation Annotation}
* {@link ASTTypeParameters TypeParameters}?
* {@link ASTExtendsList ExtendsList}?
* {@link ASTImplementsList ImplementsList}?
* {@link ASTClassOrInterfaceBody ClassOrInterfaceBody}
*
* </pre>
*/
@ -45,16 +40,12 @@ public final class ASTClassOrInterfaceDeclaration extends AbstractAnyTypeDeclara
return visitor.visit(this, data);
}
@Override
public boolean isPackagePrivate() {
return super.isPackagePrivate() && !isLocal();
}
@Override
public <T> void jjtAccept(SideEffectingVisitor<T> visitor, T data) {
visitor.visit(this, data);
}
@Override
public boolean isInterface() {
return this.isInterface;
}
@ -69,13 +60,6 @@ public final class ASTClassOrInterfaceDeclaration extends AbstractAnyTypeDeclara
}
@Override
public List<ASTAnyTypeBodyDeclaration> getDeclarations() {
return getFirstChildOfType(ASTClassOrInterfaceBody.class)
.findChildrenOfType(ASTAnyTypeBodyDeclaration.class);
}
/**
* Returns the superclass type node if this node is a class
* declaration and explicitly declares an {@code extends}

View File

@ -12,18 +12,13 @@ import org.checkerframework.checker.nullness.qual.NonNull;
*
* <pre class="grammar">
*
* ConstructorDeclaration ::= ConstructorModifier*
* ConstructorDeclaration ::= {@link ASTModifierList ModifierList}
* {@link ASTTypeParameters TypeParameters}?
* &lt;IDENTIFIER&gt;
* {@link ASTFormalParameters FormalParameters}
* ({@link ASTThrowsList ThrowsList})?
* {@link ASTBlock Block}
*
*
* ConstructorModifier ::= "public" | "private" | "protected"
* | {@linkplain ASTAnnotation Annotation}
*
*
* </pre>
*/
public final class ASTConstructorDeclaration extends AbstractMethodOrConstructorDeclaration {

View File

@ -11,15 +11,15 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*
* <pre class="grammar">
*
* EnumConstant ::= {@link ASTAnnotation Annotation}* {@link ASTVariableDeclaratorId VariableDeclaratorId} {@linkplain ASTArgumentList ArgumentList}? {@linkplain ASTAnonymousClassDeclaration AnonymousClassDeclaration}?
* EnumConstant ::= {@link ASTModifierList AnnotationList} {@link ASTVariableDeclaratorId VariableDeclaratorId} {@linkplain ASTArgumentList ArgumentList}? {@linkplain ASTAnonymousClassDeclaration AnonymousClassDeclaration}?
*
* </pre>
*/
public final class ASTEnumConstant extends AbstractJavaNode
implements Annotatable,
AccessNode,
InternalInterfaces.VariableIdOwner {
ASTEnumConstant(int id) {
super(id);
}

View File

@ -4,8 +4,6 @@
package net.sourceforge.pmd.lang.java.ast;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
/**
@ -18,18 +16,12 @@ import net.sourceforge.pmd.lang.ast.Node;
*
* <pre class="grammar">
*
* EnumDeclaration ::= EnumModifier*
* EnumDeclaration ::= {@link ASTModifierList ModifierList}
* "enum"
* &lt;IDENTIFIER&gt;
* {@linkplain ASTImplementsList ImplementsList}?
* {@link ASTEnumBody EnumBody}
*
*
*
* EnumModifier ::= "public" | "private" | "protected"
* | "strictfp" | "static"
* | {@linkplain ASTAnnotation Annotation}
*
* </pre>
*/
public final class ASTEnumDeclaration extends AbstractAnyTypeDeclaration {
@ -56,16 +48,8 @@ public final class ASTEnumDeclaration extends AbstractAnyTypeDeclaration {
return TypeKind.ENUM;
}
/**
* Returns the enum constants declared by this enum.
*/
public List<ASTEnumConstant> getConstants() {
return getFirstChildOfType(ASTEnumBody.class).findChildrenOfType(ASTEnumConstant.class);
}
@Override
public List<ASTAnyTypeBodyDeclaration> getDeclarations() {
return getFirstChildOfType(ASTEnumBody.class)
.findChildrenOfType(ASTAnyTypeBodyDeclaration.class);
public ASTEnumBody getBody() {
return (ASTEnumBody) getLastChild();
}
}

View File

@ -15,31 +15,21 @@ import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSignature;
* types (see {@link ASTVariableDeclaratorId#getType()}). The nodes
* corresponding to the declared variables are accessible through {@link #iterator()}.
*
* <p>{@link AccessNode} methods take into account the syntactic context of the
* declaration, e.g. {@link #isPublic()} will always return true if the field is
* declared inside an interface, regardless of whether the {@code public} modifier
* was specified or not. If you want to know whether the modifier was explicitly
* stated, use e.g {@link #isSyntacticallyPublic()}.
*
* <pre class="grammar">
*
* FieldDeclaration ::= FieldModifier* {@linkplain ASTType Type} {@linkplain ASTVariableDeclarator VariableDeclarator} ( "," {@linkplain ASTVariableDeclarator VariableDeclarator} )* ";"
*
* FieldModifier ::= "public" | "static" | "protected" | "private"
* | "final" | "transient" | "volatile"
* | {@linkplain ASTAnnotation Annotation}
* FieldDeclaration ::= {@link ASTModifierList ModifierList} {@linkplain ASTType Type} {@linkplain ASTVariableDeclarator VariableDeclarator} ( "," {@linkplain ASTVariableDeclarator VariableDeclarator} )* ";"
*
* </pre>
*/
public final class ASTFieldDeclaration extends AbstractJavaAccessNode
public final class ASTFieldDeclaration extends AbstractJavaNode
implements SignedNode<ASTFieldDeclaration>,
Iterable<ASTVariableDeclaratorId>,
LeftRecursiveNode,
AccessNode,
InternalInterfaces.MultiVariableIdOwner {
private JavaFieldSignature signature;
ASTFieldDeclaration(int id) {
super(id);
}
@ -55,86 +45,6 @@ public final class ASTFieldDeclaration extends AbstractJavaAccessNode
visitor.visit(this, data);
}
public boolean isSyntacticallyPublic() {
return super.isPublic();
}
@Override
public boolean isPublic() {
if (isAnnotationMember() || isInterfaceMember()) {
return true;
}
return super.isPublic();
}
public boolean isSyntacticallyStatic() {
return super.isStatic();
}
@Override
public boolean isStatic() {
if (isAnnotationMember() || isInterfaceMember()) {
return true;
}
return super.isStatic();
}
public boolean isSyntacticallyFinal() {
return super.isFinal();
}
@Override
public boolean isFinal() {
if (isAnnotationMember() || isInterfaceMember()) {
return true;
}
return super.isFinal();
}
@Override
public boolean isPrivate() {
if (isAnnotationMember() || isInterfaceMember()) {
return false;
}
return super.isPrivate();
}
@Override
public boolean isPackagePrivate() {
if (isAnnotationMember() || isInterfaceMember()) {
return false;
}
return super.isPackagePrivate();
}
@Override
public boolean isProtected() {
if (isAnnotationMember() || isInterfaceMember()) {
return false;
}
return super.isProtected();
}
public boolean isAnnotationMember() {
return getNthParent(2) instanceof ASTAnnotationTypeBody;
}
public boolean isInterfaceMember() {
if (getNthParent(2) instanceof ASTEnumBody) {
return false;
}
ASTClassOrInterfaceBody classOrInterfaceBody = getFirstParentOfType(ASTClassOrInterfaceBody.class);
if (classOrInterfaceBody == null || classOrInterfaceBody.isAnonymousInnerClass()) {
return false;
}
if (classOrInterfaceBody.getParent() instanceof ASTClassOrInterfaceDeclaration) {
ASTClassOrInterfaceDeclaration n = (ASTClassOrInterfaceDeclaration) classOrInterfaceBody.getParent();
return n.isInterface();
}
return false;
}
/**
* Gets the variable name of this field. This method searches the first
* VariableDeclartorId node and returns its image or <code>null</code> if

View File

@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.ast;
import org.checkerframework.checker.nullness.qual.NonNull;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.java.ast.InternalInterfaces.VariableIdOwner;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
@ -19,13 +20,14 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin
*
* <pre class="grammar">
*
* FormalParameter ::= ( "final" | {@link ASTAnnotation Annotation} )* {@link ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
* FormalParameter ::= {@link ASTModifierList LocalVarModifierList} {@link ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
*
* </pre>
*/
public final class ASTFormalParameter extends AbstractJavaAccessTypeNode
implements Annotatable,
InternalInterfaces.VariableIdOwner {
public final class ASTFormalParameter extends AbstractJavaTypeNode
implements FinalizableNode,
Annotatable,
VariableIdOwner {
@InternalApi
@Deprecated
@ -33,6 +35,12 @@ public final class ASTFormalParameter extends AbstractJavaAccessTypeNode
super(id);
}
@Override
public Visibility getVisibility() {
return Visibility.V_LOCAL;
}
/**
* Returns true if this node is a varargs parameter. Then, the type
* node is an {@link ASTArrayType ArrayType}, and its last dimension

View File

@ -35,7 +35,7 @@ import net.sourceforge.pmd.lang.java.ast.InternalInterfaces.BinaryExpressionLike
* <img src="doc-files/binaryExpr_60x.svg" />
* </figure>
*/
public final class ASTInfixExpression extends AbstractJavaExpr implements LeftRecursiveNode, BinaryExpressionLike, AtLeastOneChild {
public final class ASTInfixExpression extends AbstractJavaExpr implements BinaryExpressionLike, AtLeastOneChild {
private BinaryOp operator;

View File

@ -7,7 +7,7 @@ package net.sourceforge.pmd.lang.java.ast;
import org.checkerframework.checker.nullness.qual.Nullable;
import net.sourceforge.pmd.lang.ast.NodeStream;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
import net.sourceforge.pmd.lang.java.qname.JavaOperationQualifiedName;
/**
@ -20,10 +20,9 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin
*
* </pre>
*/
public final class ASTLambdaExpression extends AbstractMethodLikeNode implements ASTExpression {
public final class ASTLambdaExpression extends AbstractJavaExpr implements ASTExpression, MethodLikeNode {
private JavaTypeDefinition typeDefinition;
private int parenDepth;
private JavaOperationQualifiedName qualifiedName;
ASTLambdaExpression(int id) {
super(id);
@ -43,9 +42,11 @@ public final class ASTLambdaExpression extends AbstractMethodLikeNode implements
return !isBlockBody();
}
/**
* Returns the body of this lambda if it is a block.
*/
@Nullable
public ASTBlock getBlockBody() {
return NodeStream.of(getLastChild()).filterIs(ASTBlock.class).first();
}
@ -53,40 +54,12 @@ public final class ASTLambdaExpression extends AbstractMethodLikeNode implements
/**
* Returns the body of this lambda if it is an expression.
*/
@Nullable
public ASTExpression getExpressionBody() {
return NodeStream.of(getLastChild()).filterIs(ASTExpression.class).first();
}
// TODO MethodLikeNode should be removed, and this class extend AbstractJavaExpr
void bumpParenDepth() {
parenDepth++;
}
@Override
public int getParenthesisDepth() {
return parenDepth;
}
@Override
@Nullable
public Class<?> getType() {
return typeDefinition == null ? null : typeDefinition.getType();
}
@Override
@Nullable
public JavaTypeDefinition getTypeDefinition() {
return typeDefinition;
}
void setTypeDefinition(JavaTypeDefinition typeDefinition) {
this.typeDefinition = typeDefinition;
}
@Override
public boolean isFindBoundary() {
@ -106,6 +79,15 @@ public final class ASTLambdaExpression extends AbstractMethodLikeNode implements
}
@Override
public JavaOperationQualifiedName getQualifiedName() {
return qualifiedName;
}
void setQualifiedName(JavaOperationQualifiedName qualifiedName) {
this.qualifiedName = qualifiedName;
}
@Override
public MethodLikeKind getKind() {
return MethodLikeKind.LAMBDA;

View File

@ -15,30 +15,19 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin
*
* <pre class="grammar">
*
* LambdaParameter ::= ( "final" | {@link ASTAnnotation Annotation} )* ( "var" | {@link ASTType Type} ) {@link ASTVariableDeclaratorId VariableDeclaratorId}
* | {@link ASTVariableDeclaratorId VariableDeclaratorId}
* LambdaParameter ::= {@link ASTModifierList LocalVarModifierList} ( "var" | {@link ASTType Type} ) {@link ASTVariableDeclaratorId VariableDeclaratorId}
* | {@link ASTModifierList EmptyModifierList} {@link ASTVariableDeclaratorId VariableDeclaratorId}
*
* </pre>
*/
public final class ASTLambdaParameter extends AbstractJavaTypeNode
implements InternalInterfaces.VariableIdOwner {
private boolean isFinal;
implements InternalInterfaces.VariableIdOwner,
FinalizableNode {
ASTLambdaParameter(int id) {
super(id);
}
void setFinal(boolean aFinal) {
isFinal = aFinal;
}
public boolean isFinal() {
return isFinal;
}
/**
* If true, this formal parameter represents one without explicit types.
* This can appear as part of a lambda expression with java11 using "var".

View File

@ -15,14 +15,15 @@ package net.sourceforge.pmd.lang.java.ast;
*
* <pre class="grammar">
*
* LocalVariableDeclaration ::= ( "final" | {@linkplain ASTAnnotation Annotation} )* {@linkplain ASTType Type} {@linkplain ASTVariableDeclarator VariableDeclarator} ( "," {@linkplain ASTVariableDeclarator VariableDeclarator} )*
* LocalVariableDeclaration ::= {@link ASTModifierList LocalVarModifierList} {@linkplain ASTType Type} {@linkplain ASTVariableDeclarator VariableDeclarator} ( "," {@linkplain ASTVariableDeclarator VariableDeclarator} )*
*
* </pre>
*/
// TODO extend AbstractStatement
public final class ASTLocalVariableDeclaration extends AbstractJavaAccessNode
public final class ASTLocalVariableDeclaration extends AbstractJavaNode
implements Iterable<ASTVariableDeclaratorId>,
ASTStatement,
FinalizableNode,
InternalInterfaces.MultiVariableIdOwner {
ASTLocalVariableDeclaration(int id) {
@ -40,16 +41,9 @@ public final class ASTLocalVariableDeclaration extends AbstractJavaAccessNode
visitor.visit(this, data);
}
/**
* Returns true if the local variables declared by this statement
* are final.
*/
@Override
@SuppressWarnings("PMD.UselessOverridingMethod")
public boolean isFinal() {
// TODO unimplement AccessNode, this causes compilation errors because of our current symbol table
return super.isFinal();
public Visibility getVisibility() {
return Visibility.V_LOCAL;
}
/**

View File

@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.java.ast;
import org.checkerframework.checker.nullness.qual.Nullable;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.dfa.DFAGraphMethod;
@ -26,7 +25,7 @@ import net.sourceforge.pmd.lang.dfa.DFAGraphMethod;
*
* <pre class="grammar">
*
* MethodDeclaration ::= MethodModifier*
* MethodDeclaration ::= {@link ASTModifierList ModifierList}
* {@link ASTTypeParameters TypeParameters}?
* {@link ASTResultType ResultType}
* &lt;IDENTIFIER&gt;
@ -35,11 +34,6 @@ import net.sourceforge.pmd.lang.dfa.DFAGraphMethod;
* {@link ASTThrowsList ThrowsList}?
* ({@link ASTBlock Block} | ";" )
*
*
* MethodModifier ::= "public" | "private" | "protected" | "static"
* | "final" | "abstract" | "native"
* | {@linkplain ASTAnnotation Annotation}
*
* </pre>
*/
public final class ASTMethodDeclaration extends AbstractMethodOrConstructorDeclaration implements DFAGraphMethod {
@ -81,67 +75,10 @@ public final class ASTMethodDeclaration extends AbstractMethodOrConstructorDecla
}
/**
* Returns true if this method is explicitly modified by
* the {@code public} modifier.
*/
public boolean isSyntacticallyPublic() {
return super.isPublic();
}
/**
* Returns true if this method is explicitly modified by
* the {@code abstract} modifier.
*/
public boolean isSyntacticallyAbstract() {
return super.isAbstract();
}
/**
* Returns true if this method has public visibility.
* Non-private interface members are implicitly public,
* whether they declare the {@code public} modifier or
* not.
*/
@Override
public boolean isPublic() {
// interface methods are public by default, but could be private since java9
return isInterfaceMember() && !isPrivate() || super.isPublic();
}
/**
* Returns true if this method is abstract, so doesn't
* declare a body. Interface members are
* implicitly abstract, whether they declare the
* {@code abstract} modifier or not. Default interface
* methods are not abstract though, consistently with the
* standard reflection API.
*/
@Override
public boolean isAbstract() {
return isInterfaceMember() && !isDefault() || super.isAbstract();
}
/**
* Returns true if this method declaration is a member of an interface type.
*/
public boolean isInterfaceMember() {
// for a real class/interface the 3rd parent is a ClassOrInterfaceDeclaration,
// for anonymous classes, the parent is e.g. a AllocationExpression
Node potentialTypeDeclaration = getNthParent(3);
return potentialTypeDeclaration instanceof ASTClassOrInterfaceDeclaration
&& ((ASTClassOrInterfaceDeclaration) potentialTypeDeclaration).isInterface()
|| potentialTypeDeclaration instanceof ASTAnnotationTypeDeclaration;
}
/**
* Returns true if the result type of this method is {@code void}.
*
* TODO remove, just as simple to write getResultType().isVoid()
*/
public boolean isVoid() {
return getResultType().isVoid();

View File

@ -26,7 +26,7 @@ import net.sourceforge.pmd.lang.java.qname.JavaOperationQualifiedName;
* @see MethodLikeNode
* @since 5.8.1
*/
public interface ASTMethodOrConstructorDeclaration extends MethodLikeNode, SignedNode<ASTMethodOrConstructorDeclaration> {
public interface ASTMethodOrConstructorDeclaration extends MethodLikeNode, AccessNode, SignedNode<ASTMethodOrConstructorDeclaration> {
/**
@ -41,6 +41,21 @@ public interface ASTMethodOrConstructorDeclaration extends MethodLikeNode, Signe
JavaOperationSignature getSignature();
/**
* Returns true if this method is abstract, so doesn't
* declare a body. Interface members are
* implicitly abstract, whether they declare the
* {@code abstract} modifier or not. Default interface
* methods are not abstract though, consistently with the
* standard reflection API.
*/
// TODO is this relevant?
@Override
default boolean isAbstract() {
return hasModifiers(JModifier.ABSTRACT);
}
/**
* Returns the formal parameters node of this method or constructor.
*/

View File

@ -0,0 +1,246 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import static net.sourceforge.pmd.lang.java.ast.JModifier.ABSTRACT;
import static net.sourceforge.pmd.lang.java.ast.JModifier.DEFAULT;
import static net.sourceforge.pmd.lang.java.ast.JModifier.FINAL;
import static net.sourceforge.pmd.lang.java.ast.JModifier.PRIVATE;
import static net.sourceforge.pmd.lang.java.ast.JModifier.PUBLIC;
import static net.sourceforge.pmd.lang.java.ast.JModifier.STATIC;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
/**
* List of modifiers of a declaration.
*
* <p>This class keeps track of two modifier sets: the {@linkplain #getExplicitModifiers() explicit}
* one, which is the modifiers that appeared in the source, and the
* {@linkplain #getEffectiveModifiers() effective} one, which includes
* modifiers implicitly given by the context of the node.
*
* <pre class="grammar">
*
*
*
* ModifierList ::= Modifier*
*
* Modifier ::= "public" | "private" | "protected"
* | "final" | "abstract" | "static" | "strictfp"
* | "synchronized" | "native" | "default"
* | "volatile" | "transient"
* | {@linkplain ASTAnnotation Annotation}
*
*
* LocalVarModifierList ::= ( "final" | {@link ASTAnnotation Annotation} )*
*
* AnnotationList ::= {@link ASTAnnotation Annotation}*
*
* EmptyModifierList ::= ()
*
* </pre>
*/
public final class ASTModifierList extends AbstractJavaNode {
/** Might as well share it. */
static final Set<JModifier> JUST_FINAL = Collections.singleton(FINAL);
private Set<JModifier> explicitModifiers;
private Set<JModifier> effectiveModifiers;
ASTModifierList(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);
}
void setDeclaredModifiers(Set<JModifier> explicit) {
this.explicitModifiers = explicit;
}
/**
* Returns the set of modifiers written out in the source explicitly.
* The returned set is unmodifiable.
*/
public Set<JModifier> getExplicitModifiers() {
assert explicitModifiers != null : "Parser should have set the explicit modifiers";
return Collections.unmodifiableSet(explicitModifiers);
}
/**
* Returns the {@linkplain #getExplicitModifiers() declared modifiers},
* plus the modifiers that are implicitly bestowed by the context or
* the type of this declaration. E.g. an interface is implicitly abstract,
* while an interface field is implicitly static.
* The returned set is unmodifiable.
*/
public Set<JModifier> getEffectiveModifiers() {
assert explicitModifiers != null : "Parser should have set the explicit modifiers";
if (effectiveModifiers == null) {
EnumSet<JModifier> mods =
explicitModifiers.isEmpty()
? EnumSet.noneOf(JModifier.class)
: EnumSet.copyOf(explicitModifiers);
getOwner().jjtAccept(EffectiveModifierVisitor.INSTANCE, mods);
this.effectiveModifiers = Collections.unmodifiableSet(mods);
}
return effectiveModifiers;
}
public JavaNode getOwner() {
return getParent(); // TODO
}
/**
* Returns true if the effective modifiers contain all of the mentioned
* modifiers.
*
* @param mod1 First mod
* @param mods Other mods
*/
public boolean hasAll(JModifier mod1, JModifier... mods) {
Set<JModifier> actual = getEffectiveModifiers();
return actual.contains(mod1) && (mods.length == 0 || actual.containsAll(Arrays.asList(mods)));
}
/**
* Returns true if the explicit modifiers contain all of the mentioned
* modifiers.
*
* @param mod1 First mod
* @param mods Other mods
*/
public boolean hasAllExplicitly(JModifier mod1, JModifier... mods) {
Set<JModifier> actual = getExplicitModifiers();
return actual.contains(mod1) && (mods.length == 0 || actual.containsAll(Arrays.asList(mods)));
}
/**
* Returns true if the effective modifiers contain any of the mentioned
* modifiers.
*
* @param mod1 First mod
* @param mods Other mods
*/
public boolean hasAny(JModifier mod1, JModifier... mods) {
Set<JModifier> actual = getEffectiveModifiers();
return actual.contains(mod1) || Arrays.stream(mods).anyMatch(actual::contains);
}
/**
* Returns true if the explicit modifiers contain any of the mentioned
* modifiers.
*
* @param mod1 First mod
* @param mods Other mods
*/
public boolean hasAnyExplicitly(JModifier mod1, JModifier... mods) {
Set<JModifier> actual = getExplicitModifiers();
return actual.contains(mod1) || Arrays.stream(mods).anyMatch(actual::contains);
}
/**
* Populates effective modifiers from the declared ones.
*/
private static class EffectiveModifierVisitor extends SideEffectingVisitorAdapter<Set<JModifier>> {
private static final EffectiveModifierVisitor INSTANCE = new EffectiveModifierVisitor();
// TODO strictfp modifier is also implicitly given to descendants
@Override
public void visit(ASTAnyTypeDeclaration node, Set<JModifier> effective) {
if (node.getEnclosingType().isInterface()) {
effective.add(PUBLIC);
effective.add(STATIC);
}
if (node.isInterface() || node.isAnnotation()) {
effective.add(ABSTRACT);
if (!node.isTopLevel()) {
effective.add(STATIC);
}
} else if (node instanceof ASTEnumDeclaration && !node.isTopLevel()) {
effective.add(STATIC);
}
if (node instanceof ASTEnumDeclaration
&& node.getEnumConstants().none(ASTEnumConstant::isAnonymousClass)) {
effective.add(FINAL);
}
}
@Override
public void visit(ASTFieldDeclaration node, Set<JModifier> effective) {
if (node.getEnclosingType().isInterface()) {
effective.add(PUBLIC);
effective.add(STATIC);
effective.add(FINAL);
}
}
@Override
public void visit(ASTLocalVariableDeclaration node, Set<JModifier> effective) {
// resources are implicitly final
if (node.getParent() instanceof ASTResource) {
effective.add(FINAL);
}
}
@Override
public void visit(ASTEnumConstant node, Set<JModifier> effective) {
effective.add(PUBLIC);
effective.add(STATIC);
effective.add(FINAL);
}
@Override
public void visit(ASTAnonymousClassDeclaration node, Set<JModifier> effective) {
// TODO add static modifier in static context
}
@Override
public void visit(ASTMethodDeclaration node, Set<JModifier> effective) {
if (node.getEnclosingType().isInterface()) {
Set<JModifier> declared = node.getModifiers().explicitModifiers;
if (!declared.contains(PRIVATE)) {
effective.add(PUBLIC);
}
if (!declared.contains(DEFAULT) && !declared.contains(STATIC)) {
effective.add(ABSTRACT);
}
}
}
}
}

View File

@ -12,7 +12,7 @@ package net.sourceforge.pmd.lang.java.ast;
*
* <pre class="grammar">
*
* PackageDeclaration ::= "package" Name ";"
* PackageDeclaration ::= {@link ASTModifierList AnnotationList} "package" Name ";"
*
* </pre>
*

View File

@ -5,6 +5,8 @@
package net.sourceforge.pmd.lang.java.ast;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@ -28,6 +30,10 @@ 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.

View File

@ -43,7 +43,7 @@ import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
*
*/
// @formatter:on
public final class ASTVariableDeclaratorId extends AbstractJavaTypeNode {
public final class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements AccessNode {
private VariableNameDeclaration nameDeclaration;
@ -90,6 +90,19 @@ public final class ASTVariableDeclaratorId extends AbstractJavaTypeNode {
return children(ASTArrayDimensions.class).first();
}
@Override
public ASTModifierList getModifiers() {
// delegates modifiers
return getModifierOwnerParent().getModifiers();
}
private AccessNode getModifierOwnerParent() {
JavaNode parent = getParent();
if (parent instanceof ASTVariableDeclarator) {
return (AccessNode) parent.getParent();
}
return (AccessNode) parent;
}
/**
* Returns true if the declared variable has an array type.
@ -163,6 +176,7 @@ public final class ASTVariableDeclaratorId extends AbstractJavaTypeNode {
* Doesn't account for the "effectively-final" nuance. Resource
* declarations are implicitly final.
*/
@Override
public boolean isFinal() {
if (isResourceDeclaration()) {
// this is implicit even if "final" is not explicitly declared.

View File

@ -4,7 +4,6 @@
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
@ -12,9 +11,10 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin
/**
* Abstract class for type declarations nodes.
*/
abstract class AbstractAnyTypeDeclaration extends AbstractJavaAccessTypeNode implements ASTAnyTypeDeclaration, LeftRecursiveNode {
abstract class AbstractAnyTypeDeclaration extends AbstractJavaNode implements ASTAnyTypeDeclaration, LeftRecursiveNode {
private JavaTypeQualifiedName qualifiedName;
private JavaTypeDefinition typeDefinition;
AbstractAnyTypeDeclaration(int i) {
@ -33,53 +33,8 @@ abstract class AbstractAnyTypeDeclaration extends AbstractJavaAccessTypeNode imp
}
@Override
public String getSimpleName() {
return getImage();
}
@Override
public boolean isFindBoundary() {
return isNested() || isLocal();
}
/**
* Returns true if the enclosing type of this type declaration
* is any of the given kinds. If this declaration is a top-level
* declaration, returns false. This won't consider anonymous classes
* until #905 is tackled. TODO 7.0.0
*
* @param kinds Kinds to test
*/
// TODO 7.0.0 move that up to ASTAnyTypeDeclaration
public final boolean enclosingTypeIsA(TypeKind... kinds) {
ASTAnyTypeDeclaration parent = getEnclosingTypeDeclaration();
if (parent == null) {
return false;
}
for (TypeKind k : kinds) {
if (parent.getTypeKind() == k) {
return true;
}
}
return false;
}
/**
* Returns the enclosing type of this type, if it is nested.
* Otherwise returns null. This won't consider anonymous classes
* until #905 is tackled. TODO 7.0.0
*/
public final ASTAnyTypeDeclaration getEnclosingTypeDeclaration() {
if (!isNested()) {
return null;
}
Node parent = getNthParent(3);
return parent instanceof ASTAnyTypeDeclaration ? (ASTAnyTypeDeclaration) parent : null;
public Visibility getVisibility() {
return isLocal() ? Visibility.V_LOCAL : ASTAnyTypeDeclaration.super.getVisibility();
}
@Override
@ -91,5 +46,14 @@ abstract class AbstractAnyTypeDeclaration extends AbstractJavaAccessTypeNode imp
this.qualifiedName = qualifiedName;
this.typeDefinition = JavaTypeDefinition.forClass(qualifiedName.getType());
}
void setTypeDefinition(JavaTypeDefinition typeDefinition) {
this.typeDefinition = typeDefinition;
}
@Override
public JavaTypeDefinition getTypeDefinition() {
return typeDefinition;
}
}

View File

@ -1,114 +0,0 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
abstract class AbstractJavaAccessNode extends AbstractJavaNode implements AccessNode {
private int modifiers;
AbstractJavaAccessNode(int i) {
super(i);
}
@Override
public int getModifiers() {
return this.modifiers;
}
void setModifiers(int modifiers) {
this.modifiers = modifiers;
}
@Override
public boolean isPublic() {
return isModifier(PUBLIC);
}
@Override
public boolean isProtected() {
return isModifier(PROTECTED);
}
@Override
public boolean isPrivate() {
return isModifier(PRIVATE);
}
@Override
public boolean isAbstract() {
return isModifier(ABSTRACT);
}
@Override
public boolean isStatic() {
return isModifier(STATIC);
}
@Override
public boolean isFinal() {
return isModifier(FINAL);
}
void setFinal(boolean enable) {
setModifier(enable, FINAL);
}
@Override
public boolean isSynchronized() {
return isModifier(SYNCHRONIZED);
}
@Override
public boolean isNative() {
return isModifier(NATIVE);
}
@Override
public boolean isTransient() {
return isModifier(TRANSIENT);
}
@Override
public boolean isVolatile() {
return isModifier(VOLATILE);
}
@Override
public boolean isStrictfp() {
return isModifier(STRICTFP);
}
@Override
public boolean isDefault() {
return isModifier(DEFAULT);
}
private boolean isModifier(int mask) {
return (modifiers & mask) == mask;
}
void setModifier(boolean enable, int mask) {
if (enable) {
this.modifiers |= mask;
} else {
this.modifiers &= ~mask;
}
}
@Override
public boolean isPackagePrivate() {
return !isPrivate() && !isPublic() && !isProtected();
}
}

View File

@ -1,37 +0,0 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
abstract class AbstractJavaAccessTypeNode extends AbstractJavaAccessNode implements TypeNode {
/**
* Type definition, used to get the type of the node.
*/
protected JavaTypeDefinition typeDefinition;
AbstractJavaAccessTypeNode(int i) {
super(i);
}
@Override
public Class<?> getType() {
if (typeDefinition != null) {
return typeDefinition.getType();
}
return null;
}
@Override
public JavaTypeDefinition getTypeDefinition() {
return typeDefinition;
}
void setTypeDefinition(JavaTypeDefinition typeDefinition) {
this.typeDefinition = typeDefinition;
}
}

View File

@ -1,30 +0,0 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.java.qname.JavaOperationQualifiedName;
abstract class AbstractMethodLikeNode extends AbstractJavaAccessNode implements MethodLikeNode {
private JavaOperationQualifiedName qualifiedName;
AbstractMethodLikeNode(int i) {
super(i);
}
void setQualifiedName(JavaOperationQualifiedName qualifiedName) {
this.qualifiedName = qualifiedName;
}
@Override
@Deprecated
public JavaOperationQualifiedName getQualifiedName() {
return qualifiedName;
}
}

View File

@ -5,12 +5,13 @@
package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature;
import net.sourceforge.pmd.lang.java.qname.JavaOperationQualifiedName;
abstract class AbstractMethodOrConstructorDeclaration extends AbstractMethodLikeNode implements ASTMethodOrConstructorDeclaration, LeftRecursiveNode {
abstract class AbstractMethodOrConstructorDeclaration extends AbstractJavaNode implements ASTMethodOrConstructorDeclaration, LeftRecursiveNode, AccessNode {
private JavaOperationSignature signature;
private JavaOperationQualifiedName qualifiedName;
AbstractMethodOrConstructorDeclaration(int i) {
super(i);
@ -25,4 +26,17 @@ abstract class AbstractMethodOrConstructorDeclaration extends AbstractMethodLike
return signature;
}
void setQualifiedName(JavaOperationQualifiedName qualifiedName) {
this.qualifiedName = qualifiedName;
}
@Override
public JavaOperationQualifiedName getQualifiedName() {
return qualifiedName;
}
}

View File

@ -1,70 +1,250 @@
/**
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
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;
/**
* This interface captures Java access modifiers.
* A node that owns a {@linkplain ASTModifierList modifier list}.
*
* <p>{@link AccessNode} methods take into account the syntactic context of the
* declaration, e.g. {@link #isPublic()} will always return true for a field
* declared inside an interface, regardless of whether the {@code public}
* modifier was specified explicitly or not. If you want to know whether
* the modifier was explicitly stated, use {@link #hasExplicitModifiers(JModifier, JModifier...)}.
*
* TODO make modifiers accessible from XPath
* * Ideally we'd have two attributes, eg @EffectiveModifiers and @ExplicitModifiers,
* which would each return a sequence, eg ("public", "static", "final")
* * Ideally we'd have a way to add attributes that are not necessarily
* getters on the node. It makes no sense in the Java API to expose
* those getters on the node, it's more orthogonal to query getModifiers() directly.
*
* TODO rename to ModifierOwner, kept out from PR to reduce diff
*/
public interface AccessNode extends Annotatable {
int PUBLIC = 0x0001;
int PROTECTED = 0x0002;
int PRIVATE = 0x0004;
int ABSTRACT = 0x0008;
int STATIC = 0x0010;
int FINAL = 0x0020;
int SYNCHRONIZED = 0x0040;
int NATIVE = 0x0080;
int TRANSIENT = 0x0100;
int VOLATILE = 0x0200;
int STRICTFP = 0x1000;
int DEFAULT = 0x2000;
@Override
default List<ASTAnnotation> getDeclaredAnnotations() {
return getModifiers().children(ASTAnnotation.class).toList();
}
int getModifiers();
/**
* Returns the node representing the modifier list of this node.
*/
@NonNull
default ASTModifierList getModifiers() {
return children(ASTModifierList.class).firstOrThrow();
}
boolean isPublic();
/**
* Returns the visibility corresponding to the {@link ASTModifierList#getEffectiveModifiers() effective modifiers}.
* Eg a public method will have visibility {@link Visibility#V_PUBLIC public},
* a local class will have visibility {@link Visibility#V_LOCAL local}.
* There cannot be any conflict with {@link #hasModifiers(JModifier, JModifier...)}} on
* well-formed code (e.g. for any {@code n}, {@code (n.getVisibility() == V_PROTECTED) ==
* n.hasModifiers(PROTECTED)})
*
* <p>TODO a public method of a private class can be considered to be private
* we could probably add another method later on that takes this into account
*/
default Visibility getVisibility() {
Set<JModifier> effective = getModifiers().getEffectiveModifiers();
if (effective.contains(JModifier.PUBLIC)) {
return Visibility.V_PUBLIC;
} else if (effective.contains(JModifier.PROTECTED)) {
return Visibility.V_PROTECTED;
} else if (effective.contains(JModifier.PRIVATE)) {
return Visibility.V_PRIVATE;
} else {
return Visibility.V_PACKAGE;
}
}
boolean isProtected();
/**
* Returns true if this node has <i>all</i> the given modifiers
* either explicitly written or inferred through context.
*/
default boolean hasModifiers(JModifier mod1, JModifier... mod) {
return getModifiers().hasAll(mod1, mod);
}
boolean isPrivate();
/**
* Returns true if this node has <i>all</i> the given modifiers
* explicitly written in the source.
*/
default boolean hasExplicitModifiers(JModifier mod1, JModifier... mod) {
return getModifiers().hasAllExplicitly(mod1, mod);
}
boolean isAbstract();
// TODO remove all those, kept only for compatibility with rules
// these are about effective modifiers
boolean isStatic();
@Deprecated
default boolean isFinal() {
return hasModifiers(JModifier.FINAL);
}
boolean isFinal();
@Deprecated
default boolean isAbstract() {
return hasModifiers(JModifier.ABSTRACT);
}
boolean isSynchronized();
@Deprecated
default boolean isStrictfp() {
return hasModifiers(STRICTFP);
}
boolean isNative();
@Deprecated
default boolean isSynchronized() {
return hasModifiers(JModifier.SYNCHRONIZED);
}
boolean isTransient();
@Deprecated
default boolean isNative() {
return hasModifiers(JModifier.NATIVE);
}
boolean isVolatile();
@Deprecated
default boolean isStatic() {
return hasModifiers(JModifier.STATIC);
}
boolean isStrictfp();
@Deprecated
default boolean isVolatile() {
return hasModifiers(JModifier.VOLATILE);
}
boolean isPackagePrivate();
@Deprecated
default boolean isTransient() {
return hasModifiers(JModifier.TRANSIENT);
}
boolean isDefault();
// these are about visibility
@Deprecated
default boolean isPrivate() {
return getVisibility() == Visibility.V_PRIVATE;
}
@Deprecated
default boolean isPublic() {
return getVisibility() == Visibility.V_PUBLIC;
}
@Deprecated
default boolean isProtected() {
return getVisibility() == Visibility.V_PROTECTED;
}
@Deprecated
default boolean isPackagePrivate() {
return getVisibility() == Visibility.V_PACKAGE;
}
// these are about explicit modifiers
@Deprecated
default boolean isSyntacticallyAbstract() {
return hasExplicitModifiers(JModifier.ABSTRACT);
}
@Deprecated
default boolean isSyntacticallyPublic() {
return hasExplicitModifiers(JModifier.PUBLIC);
}
@Deprecated
default boolean isSyntacticallyStatic() {
return hasExplicitModifiers(JModifier.STATIC);
}
@Deprecated
default boolean isSyntacticallyFinal() {
return hasExplicitModifiers(JModifier.FINAL);
}
/**
* Represents the visibility of a declaration.
*
* <p>The ordering of the constants encodes a "contains" relationship,
* ie, given two visibilities {@code v1} and {@code v2}, {@code v1 < v2}
* means that {@code v2} is strictly more permissive than {@code v1}.
*/
enum Visibility {
// Note: constants are prefixed with "V_" to avoid conflicts with JModifier
/** Special visibility of anonymous classes, even more restricted than local. */
V_ANONYMOUS("anonymous"),
/** Confined to a local scope, eg method parameters, local variables, local classes. */
V_LOCAL("local"),
/** File-private. Corresponds to modifier {@link JModifier#PRIVATE}. */
V_PRIVATE("private"),
/** Package-private. */
V_PACKAGE("package"),
/** Package-private + visible to subclasses. Corresponds to modifier {@link JModifier#PROTECTED}. */
V_PROTECTED("protected"),
/** Visible everywhere. Corresponds to modifier {@link JModifier#PUBLIC}. */
V_PUBLIC("public");
private final String myName;
Visibility(String name) {
this.myName = name;
}
@Override
public String toString() {
return myName;
}
/**
* Returns true if this visibility is greater than or equal to
* the parameter.
*/
public boolean isAtLeast(Visibility other) {
return this.compareTo(other) >= 0;
}
/**
* Returns true if this visibility is strictly lower than the
* parameter.
*/
public boolean isAtMost(Visibility other) {
return this.compareTo(other) < 0;
}
}
}

View File

@ -0,0 +1,21 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
/**
* Package private, though the method is public.
*/
interface FinalizableNode extends AccessNode {
/**
* Returns true if this variable, method or class is final (even implicitly).
*/
@Override
default boolean isFinal() {
return hasModifiers(JModifier.FINAL);
}
}

View File

@ -40,25 +40,23 @@ public final class InternalApiBridge {
((AbstractJavaNode) node).comment(comment);
}
public static void setModifier(AccessNode node, int modifier) {
((AbstractJavaAccessNode) node).setModifier(true, modifier);
}
public static void setQname(ASTAnyTypeDeclaration declaration, JavaTypeQualifiedName qualifiedName) {
((AbstractAnyTypeDeclaration) declaration).setQualifiedName(qualifiedName);
}
public static void setQname(MethodLikeNode node, JavaOperationQualifiedName qualifiedName) {
((AbstractMethodLikeNode) node).setQualifiedName(qualifiedName);
if (node instanceof ASTLambdaExpression) {
((ASTLambdaExpression) node).setQualifiedName(qualifiedName);
} else if (node instanceof AbstractMethodOrConstructorDeclaration) {
((AbstractMethodOrConstructorDeclaration) node).setQualifiedName(qualifiedName);
}
}
public static void setTypeDefinition(TypeNode node, JavaTypeDefinition definition) {
if (node instanceof AbstractJavaTypeNode) {
((AbstractJavaTypeNode) node).setTypeDefinition(definition);
} else if (node instanceof AbstractJavaAccessTypeNode) {
((AbstractJavaAccessTypeNode) node).setTypeDefinition(definition);
} else if (node instanceof ASTLambdaExpression) {
((ASTLambdaExpression) node).setTypeDefinition(definition);
} else if (node instanceof AbstractAnyTypeDeclaration) {
((AbstractAnyTypeDeclaration) node).setTypeDefinition(definition);
}
}

Some files were not shown because too many files have changed in this diff Show More