Fix AST type annots

This commit is contained in:
Clément Fournier committed 2022-11-29 15:18:16 +01:00
1 parent c8f2a8db14
commit 42cbc84b11
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;
}
}
@@ -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());
}
};
@@ -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);
}
@@ -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
@@ -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,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());
}