Fix AST type annots
This commit is contained in:
9 files changed
+60
-40
No files matched your search
@@ -24,7 +24,7 @@ public final class ASTArrayType extends AbstractJavaTypeNode implements ASTRefer
|
||||
|
||||
@Override
|
||||
public NodeStream<ASTAnnotation> getDeclaredAnnotations() {
|
||||
return getDimensions().getLastChild().getDeclaredAnnotations();
|
||||
return getDimensions().getFirstChild().getDeclaredAnnotations();
|
||||
}
|
||||
|
||||
public ASTArrayDimensions getDimensions() {
|
||||
|
||||
@@ -19,7 +19,6 @@ import net.sourceforge.pmd.lang.java.symbols.JClassSymbol;
|
||||
import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol;
|
||||
import net.sourceforge.pmd.lang.java.symbols.JTypeParameterSymbol;
|
||||
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue.SymAnnot;
|
||||
import net.sourceforge.pmd.lang.java.symbols.internal.ast.SymbolResolutionPass;
|
||||
import net.sourceforge.pmd.lang.java.symbols.table.internal.JavaResolvers;
|
||||
import net.sourceforge.pmd.lang.java.types.JClassType;
|
||||
import net.sourceforge.pmd.lang.java.types.JTypeMirror;
|
||||
@@ -71,7 +70,7 @@ final class TypesFromAst {
|
||||
} else {
|
||||
isUpperBound = wild.hasUpperBound();
|
||||
}
|
||||
return ts.wildcard(isUpperBound, bound).withAnnotations(getSymbolicAnnotations(node));
|
||||
return ts.wildcard(isUpperBound, bound).withAnnotations(getTypeAnnotations(node));
|
||||
|
||||
|
||||
} else if (node instanceof ASTIntersectionType) {
|
||||
@@ -88,13 +87,20 @@ final class TypesFromAst {
|
||||
}
|
||||
} else if (node instanceof ASTArrayType) {
|
||||
|
||||
JTypeMirror eltType = fromAst(ts, lexicalSubst, ((ASTArrayType) node).getElementType());
|
||||
JTypeMirror t = fromAst(ts, lexicalSubst, ((ASTArrayType) node).getElementType());
|
||||
ASTArrayDimensions dimensions = ((ASTArrayType) node).getDimensions();
|
||||
// we have to iterate in reverse
|
||||
for (int i = dimensions.size() - 1; i >= 0; i--) {
|
||||
ASTArrayTypeDim dim = dimensions.get(i);
|
||||
PSet<SymAnnot> annots = getSymbolicAnnotations(dim);
|
||||
t = ts.arrayType(t).withAnnotations(annots);
|
||||
}
|
||||
|
||||
return ts.arrayType(eltType, node.getArrayDepth()); //todo type annotations
|
||||
return t;
|
||||
|
||||
} else if (node instanceof ASTPrimitiveType) {
|
||||
|
||||
return ts.getPrimitive(((ASTPrimitiveType) node).getKind()).withAnnotations(getSymbolicAnnotations(node));
|
||||
return ts.getPrimitive(((ASTPrimitiveType) node).getKind()).withAnnotations(getTypeAnnotations(node));
|
||||
|
||||
} else if (node instanceof ASTAmbiguousName) {
|
||||
|
||||
@@ -236,12 +242,35 @@ final class TypesFromAst {
|
||||
return !Modifier.isStatic(reference.getModifiers());
|
||||
}
|
||||
|
||||
private static PSet<SymAnnot> getTypeAnnotations(ASTType type) {
|
||||
PSet<SymAnnot> baseAnnots = getSymbolicAnnotations(type);
|
||||
JavaNode parent = type.getParent();
|
||||
if (!(parent instanceof ASTType) && parent instanceof Annotatable) {
|
||||
return baseAnnots.plusAll(getSymbolicAnnotations((Annotatable) parent));
|
||||
/**
|
||||
* Returns the variable declaration or field or formal, etc, that
|
||||
* may give additional type annotations to the given type.
|
||||
*/
|
||||
private static @Nullable Annotatable getEnclosingAnnotationGiver(JavaNode node) {
|
||||
JavaNode parent = node.getParent();
|
||||
if (node.getIndexInParent() == 0 && parent instanceof ASTClassOrInterfaceType) {
|
||||
// this is an enclosing type
|
||||
return getEnclosingAnnotationGiver(parent);
|
||||
} else if (node.getIndexInParent() == 0 && parent instanceof ASTArrayType) {
|
||||
// the element type of an array type
|
||||
return getEnclosingAnnotationGiver(parent);
|
||||
} else if (!(parent instanceof ASTType) && parent instanceof Annotatable) {
|
||||
return (Annotatable) parent;
|
||||
}
|
||||
return baseAnnots;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PSet<SymAnnot> getTypeAnnotations(ASTType type) {
|
||||
PSet<SymAnnot> annotsOnTypes = getSymbolicAnnotations(type);
|
||||
Annotatable parent = getEnclosingAnnotationGiver(type);
|
||||
if (parent != null) {
|
||||
// todo parent annots should be filtered by target TYPE_USE
|
||||
PSet<SymAnnot> parentAnnots = getSymbolicAnnotations(parent);
|
||||
if (annotsOnTypes.isEmpty()) {
|
||||
return parentAnnots;
|
||||
}
|
||||
return annotsOnTypes.plusAll(parentAnnots);
|
||||
}
|
||||
return annotsOnTypes;
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -144,7 +144,7 @@ public final class SymbolEquality {
|
||||
public static final EqAndHash<SymAnnot> ANNOTATION = new EqAndHash<SymAnnot>() {
|
||||
@Override
|
||||
public int hash(SymAnnot t1) {
|
||||
return Objects.hash(t1.getBinaryName(), t1.getAttributeNames());
|
||||
return Objects.hash(t1.getBinaryName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,8 +153,7 @@ public final class SymbolEquality {
|
||||
return false;
|
||||
}
|
||||
SymAnnot f2 = (SymAnnot) o;
|
||||
return f1.getBinaryName().equals(f2.getBinaryName())
|
||||
&& f1.getAttributeNames().equals(f2.getAttributeNames());
|
||||
return f1.getBinaryName().equals(f2.getBinaryName());
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
+2
-5
@@ -30,18 +30,15 @@ abstract class AbstractAstExecSymbol<T extends ASTMethodOrConstructorDeclaration
|
||||
|
||||
private final JClassSymbol owner;
|
||||
private final List<JFormalParamSymbol> formals;
|
||||
private final PSet<SymAnnot> declaredAnnotations;
|
||||
|
||||
protected AbstractAstExecSymbol(T node, AstSymFactory factory, JClassSymbol owner) {
|
||||
super(node, factory);
|
||||
this.owner = owner;
|
||||
|
||||
formals = CollectionUtil.map(
|
||||
this.formals = CollectionUtil.map(
|
||||
node.getFormalParameters(),
|
||||
p -> new AstFormalParamSym(p.getVarId(), factory, this)
|
||||
);
|
||||
|
||||
this.declaredAnnotations = SymbolResolutionPass.getSymbolicAnnotations(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,7 +62,7 @@ abstract class AbstractAstExecSymbol<T extends ASTMethodOrConstructorDeclaration
|
||||
|
||||
@Override
|
||||
public PSet<SymAnnot> getDeclaredAnnotations() {
|
||||
return declaredAnnotations;
|
||||
return SymbolResolutionPass.getSymbolicAnnotations(node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-5
@@ -22,12 +22,8 @@ abstract class AbstractAstVariableSym
|
||||
extends AbstractAstBackedSymbol<ASTVariableDeclaratorId>
|
||||
implements JVariableSymbol {
|
||||
|
||||
private final PSet<SymAnnot> declaredAnnotations;
|
||||
|
||||
AbstractAstVariableSym(ASTVariableDeclaratorId node, AstSymFactory factory) {
|
||||
super(node, factory);
|
||||
|
||||
this.declaredAnnotations = SymbolResolutionPass.getSymbolicAnnotations(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,7 +38,7 @@ abstract class AbstractAstVariableSym
|
||||
|
||||
@Override
|
||||
public PSet<SymAnnot> getDeclaredAnnotations() {
|
||||
return declaredAnnotations;
|
||||
return SymbolResolutionPass.getSymbolicAnnotations(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-3
@@ -56,7 +56,6 @@ final class AstClassSym
|
||||
private final List<JConstructorSymbol> declaredCtors;
|
||||
private final List<JFieldSymbol> declaredFields;
|
||||
private final List<JFieldSymbol> enumConstants; // subset of declaredFields
|
||||
private final PSet<SymAnnot> declaredAnnotations;
|
||||
|
||||
AstClassSym(ASTAnyTypeDeclaration node,
|
||||
AstSymFactory factory,
|
||||
@@ -144,7 +143,6 @@ final class AstClassSym
|
||||
this.declaredCtors = Collections.unmodifiableList(myCtors);
|
||||
this.declaredFields = Collections.unmodifiableList(myFields);
|
||||
this.enumConstants = CollectionUtil.makeUnmodifiableAndNonNull(enumConstants);
|
||||
this.declaredAnnotations = SymbolResolutionPass.getSymbolicAnnotations(node);
|
||||
}
|
||||
|
||||
private List<JFieldSymbol> mapComponentsToMutableList(AstSymFactory factory, ASTRecordComponentList components) {
|
||||
@@ -219,7 +217,7 @@ final class AstClassSym
|
||||
|
||||
@Override
|
||||
public PSet<SymAnnot> getDeclaredAnnotations() {
|
||||
return declaredAnnotations;
|
||||
return SymbolResolutionPass.getSymbolicAnnotations(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,7 +47,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTNumericLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPattern;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPatternExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTStringLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSuperExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression;
|
||||
@@ -192,11 +191,6 @@ public final class LazyTypeResolver extends JavaVisitorBase<TypingContext, @NonN
|
||||
return ts.NO_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JTypeMirror visit(ASTPrimitiveType node, TypingContext ctx) {
|
||||
return ts.getPrimitive(node.getKind());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JTypeMirror visit(ASTVariableDeclaratorId node, TypingContext ctx) {
|
||||
boolean isTypeInferred = node.isTypeInferred();
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.symbols;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.pcollections.PSet;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
|
||||
@@ -45,7 +44,7 @@ public class SymbolParsingTest extends AbstractSymbolTest {
|
||||
ASTVariableDeclarator variableDeclarator = method.tryGetNode().descendants(ASTVariableDeclarator.class).first();
|
||||
JVariableSymbol localSym = variableDeclarator.getSymbolTable().variables().resolveFirst("local").getSymbol();
|
||||
|
||||
List<SymAnnot> declaredAnnotations = localSym.getDeclaredAnnotations();
|
||||
PSet<SymAnnot> declaredAnnotations = localSym.getDeclaredAnnotations();
|
||||
|
||||
Assert.assertEquals(1, declaredAnnotations.size());
|
||||
Assert.assertNotNull(localSym.getDeclaredAnnotation(LocalVarAnnotation.class));
|
||||
|
||||
+11
-3
@@ -11,11 +11,9 @@ import static net.sourceforge.pmd.lang.java.symbols.internal.TypeAnnotTestUtil.b
|
||||
import static net.sourceforge.pmd.lang.java.symbols.internal.TypeAnnotTestUtil.getFieldType;
|
||||
import static net.sourceforge.pmd.util.CollectionUtil.emptyList;
|
||||
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
@@ -61,6 +59,17 @@ public class TypeAnnotReflectionTest {
|
||||
@EnumSource
|
||||
public void testArrayTypeAnnotsOnFields(SymImplementation impl) {
|
||||
|
||||
/*
|
||||
|
||||
@A int[] annotOnArrayComponent;
|
||||
int @A [] annotOnArrayDimension;
|
||||
// this annotates the int[]
|
||||
int[] @A @B [] twoAnnotsOnOuterArrayDim;
|
||||
int @A [][] annotOnInnerArrayDim;
|
||||
int @A(1) [] @A(2) [] annotsOnBothArrayDims;
|
||||
|
||||
*/
|
||||
|
||||
JClassType sym = impl.getDeclaration(ts, ClassWithTypeAnnotationsInside.class);
|
||||
|
||||
{
|
||||
@@ -79,7 +88,6 @@ public class TypeAnnotReflectionTest {
|
||||
// int[] @A @B []
|
||||
JArrayType t = (JArrayType) getFieldType(sym, "twoAnnotsOnOuterArrayDim");
|
||||
assertHasTypeAnnots(t, emptyList());
|
||||
assertThat(t.getComponentType(), Matchers.isA(JArrayType.class));
|
||||
assertHasTypeAnnots(t.getComponentType(), aAndBAnnot);
|
||||
assertHasTypeAnnots(t.getElementType(), emptyList());
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user