Separate catch formal from method formal
This commit is contained in:
@ -2980,10 +2980,28 @@ void CatchClause() :
|
||||
{}
|
||||
{
|
||||
"catch"
|
||||
"(" FormalParameter() ")"
|
||||
"(" CatchParameter() ")"
|
||||
Block()
|
||||
}
|
||||
|
||||
|
||||
void CatchParameter() :
|
||||
{boolean isFinal = false;}
|
||||
{
|
||||
isFinal=LocalVarModifierList() UnionType() VariableDeclaratorId()
|
||||
}
|
||||
|
||||
// Special type for catch formal parameters
|
||||
// Eg `IOException | ParseException`
|
||||
void UnionType() #UnionType(isUnion):
|
||||
{boolean isUnion=false;}
|
||||
{
|
||||
// Annotations of the first class type belong to the
|
||||
// catch parameter (the variable) because of syntactic ambiguity
|
||||
// This is similar to how a local var type works.
|
||||
ClassOrInterfaceType() ( "|" {isUnion=true; checkForBadMultipleExceptionsCatching();} AnnotatedClassOrInterfaceType() )*
|
||||
}
|
||||
|
||||
void FinallyClause() :
|
||||
{}
|
||||
{
|
||||
|
@ -49,15 +49,28 @@ public final class ASTCatchClause extends AbstractJavaNode {
|
||||
* @return True if this node is a multi-catch statement
|
||||
*/
|
||||
public boolean isMulticatchStatement() {
|
||||
return getCaughtExceptionTypeNodes().size() > 1; // the list is parsed multiple times...
|
||||
return getFormal().isMultiCatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@linkplain ASTCatchParameter CatchParameter} node.
|
||||
*/
|
||||
public ASTCatchParameter getFormal() {
|
||||
return (ASTCatchParameter) jjtGetChild(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the declared variable.
|
||||
*/
|
||||
public ASTVariableDeclaratorId getVariableId() {
|
||||
return getFormal().getVariableId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Block node of this catch branch.
|
||||
*/
|
||||
public ASTBlock getBlock() {
|
||||
return getFirstChildOfType(ASTBlock.class);
|
||||
return (ASTBlock) getLastChild();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +80,7 @@ public final class ASTCatchClause extends AbstractJavaNode {
|
||||
*/
|
||||
public List<ASTType> getCaughtExceptionTypeNodes() {
|
||||
// maybe cache the list
|
||||
return getFirstChildOfType(ASTFormalParameter.class).findChildrenOfType(ASTType.class);
|
||||
return getFormal().getTypeNode().asList();
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +102,7 @@ public final class ASTCatchClause extends AbstractJavaNode {
|
||||
* Returns exception name caught by this catch block.
|
||||
*/
|
||||
public String getExceptionName() {
|
||||
return getFirstDescendantOfType(ASTVariableDeclaratorId.class).getImage();
|
||||
return getVariableId().getVariableName();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
|
||||
/**
|
||||
* Formal parameter of a {@linkplain ASTCatchStatement catch statement}.
|
||||
* The type node may be a {@link ASTUnionType union type}, which represents
|
||||
* multi-catch clauses.
|
||||
*
|
||||
* TODO warning suppression
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* CatchParameter ::= ( "final" | {@link ASTAnnotation Annotation} )* {@link ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public class ASTCatchParameter extends AbstractJavaTypeNode implements Annotatable {
|
||||
|
||||
private boolean isFinal;
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTCatchParameter(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
ASTCatchParameter(JavaParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
public boolean isFinal() {
|
||||
return isFinal;
|
||||
}
|
||||
|
||||
void setFinal(boolean f) {
|
||||
isFinal = f;
|
||||
}
|
||||
|
||||
|
||||
@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 declarator ID of this catch parameter.
|
||||
*/
|
||||
public ASTVariableDeclaratorId getVariableId() {
|
||||
return (ASTVariableDeclaratorId) getLastChild();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type node of this formal parameter. This may be
|
||||
* a {@linkplain ASTUnionType union type}.
|
||||
*/
|
||||
public ASTType getTypeNode() {
|
||||
return getFirstChildOfType(ASTType.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a multi-catch node.
|
||||
*/
|
||||
public boolean isMultiCatch() {
|
||||
return getTypeNode() instanceof ASTUnionType;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
@ -24,7 +25,7 @@ import java.util.Iterator;
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTIntersectionType extends AbstractJavaTypeNode implements ASTReferenceType, Iterable<ASTType> {
|
||||
public final class ASTIntersectionType extends AbstractJavaTypeNode implements ASTReferenceType, JSingleChildNode<ASTType>, Iterable<ASTType> {
|
||||
|
||||
ASTIntersectionType(int id) {
|
||||
super(id);
|
||||
@ -43,6 +44,18 @@ public final class ASTIntersectionType extends AbstractJavaTypeNode implements A
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ASTType> asList() {
|
||||
return findChildrenOfType(ASTType.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ASTType jjtGetChild(int index) {
|
||||
return (ASTType) super.jjtGetChild(index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -5,6 +5,7 @@
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A list of resources in a {@linkplain ASTTryStatement try-with-resources}.
|
||||
@ -15,7 +16,7 @@ import java.util.Iterator;
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTResourceList extends AbstractJavaNode implements Iterable<ASTResource> {
|
||||
public final class ASTResourceList extends AbstractJavaNode implements Iterable<ASTResource>, JSingleChildNode<ASTResource> {
|
||||
|
||||
private boolean trailingSemi;
|
||||
|
||||
@ -38,6 +39,11 @@ public final class ASTResourceList extends AbstractJavaNode implements Iterable<
|
||||
visitor.visit(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTResource jjtGetChild(int index) {
|
||||
return (ASTResource) super.jjtGetChild(index);
|
||||
}
|
||||
|
||||
void setTrailingSemi() {
|
||||
this.trailingSemi = true;
|
||||
}
|
||||
@ -54,4 +60,9 @@ public final class ASTResourceList extends AbstractJavaNode implements Iterable<
|
||||
public Iterator<ASTResource> iterator() {
|
||||
return children(ASTResource.class).iterator();
|
||||
}
|
||||
|
||||
public List<ASTResource> asList() {
|
||||
return findChildrenOfType(ASTResource.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.internal.util.IteratorUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Try statement node.
|
||||
@ -57,13 +55,13 @@ public final class ASTTryStatement extends AbstractStatement {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ASTResourceList getResourceList() {
|
||||
public ASTResourceList getResourceListNode() {
|
||||
return AstImplUtil.getChildAs(this, 0, ASTResourceList.class);
|
||||
}
|
||||
|
||||
public List<ASTResource> getResources() {
|
||||
ASTResourceList list = getResourceList();
|
||||
return list == null ? Collections.emptyList() : IteratorUtil.toList(list.iterator());
|
||||
ASTResourceList list = getResourceListNode();
|
||||
return list == null ? Collections.emptyList() : list.asList();
|
||||
}
|
||||
|
||||
|
||||
@ -88,6 +86,7 @@ public final class ASTTryStatement extends AbstractStatement {
|
||||
*
|
||||
* @return The finally statement, or null if there is none
|
||||
*/
|
||||
@Nullable
|
||||
public ASTFinallyClause getFinallyClause() {
|
||||
return getFirstChildOfType(ASTFinallyClause.class);
|
||||
}
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.annotation.Experimental;
|
||||
@ -71,6 +74,17 @@ public interface ASTType extends TypeNode, Annotatable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a read-only list of the components of this type.
|
||||
* Returns a singleton containing this type if this is neither
|
||||
* a {@linkplain ASTUnionType union type} or a {@linkplain ASTIntersectionType intersection type}.
|
||||
* In those cases, returns the list of components.
|
||||
*/
|
||||
default List<ASTType> asList() {
|
||||
return Collections.singletonList(this);
|
||||
}
|
||||
|
||||
|
||||
default boolean isClassOrInterfaceType() {
|
||||
return this instanceof ASTClassOrInterfaceType;
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Represents the type node of a multi-catch statement. This node is used
|
||||
* to make the grammar of {@link ASTCatchStatement CatchStatement} more
|
||||
* straightforward. Note though, that the Java type system does not feature
|
||||
* union types per se. The type of this node is defined as the least upper-bound
|
||||
* of all its components.
|
||||
*
|
||||
* <pre class="grammar">
|
||||
*
|
||||
* UnionType ::= {@link ASTClassOrInterfaceType ClassType} ("|" {@link ASTClassOrInterfaceType ClassType})+
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public final class ASTUnionType extends AbstractJavaTypeNode implements ASTReferenceType, JSingleChildNode<ASTClassOrInterfaceType>, Iterable<ASTClassOrInterfaceType> {
|
||||
|
||||
ASTUnionType(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
ASTUnionType(JavaParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getTypeImage() {
|
||||
// TODO
|
||||
return iterator().next().getTypeImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ASTType> asList() {
|
||||
return findChildrenOfType(ASTType.class);
|
||||
}
|
||||
|
||||
@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<ASTClassOrInterfaceType> iterator() {
|
||||
return new NodeChildrenIterator<>(this, ASTClassOrInterfaceType.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTClassOrInterfaceType jjtGetChild(int index) {
|
||||
return (ASTClassOrInterfaceType) super.jjtGetChild(index);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user