Filter annotations that apply to type use

This commit is contained in:
Clément Fournier committed 2022-11-29 17:43:58 +01:00
1 parent 41bc5ac309
commit b90e46a449
7 files changed
+85 -5

No files matched your search

@@ -261,16 +261,17 @@ final class TypesFromAst {
}
private static PSet<SymAnnot> getTypeAnnotations(ASTType type) {
PSet<SymAnnot> annotsOnTypes = getSymbolicAnnotations(type);
PSet<SymAnnot> annotsOnType = 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;
for (SymAnnot parentAnnot : parentAnnots) {
if (parentAnnot.appliesToTypeUse()) {
annotsOnType = annotsOnType.plus(parentAnnot);
}
}
return annotsOnTypes.plusAll(parentAnnots);
}
return annotsOnTypes;
return annotsOnType;
}
}
@@ -5,6 +5,7 @@
package net.sourceforge.pmd.lang.java.symbols;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
@@ -87,6 +88,11 @@ final class AnnotWrapper implements SymAnnot {
return annotationClass.getSimpleName();
}
@Override
public boolean appliesToTypeUse() {
return annotationClassSymbol.annotationAppliesTo(ElementType.TYPE_USE);
}
@Override
public boolean equals(Object o) {
return SymbolEquality.ANNOTATION.equals(this, o);
@@ -5,8 +5,10 @@
package net.sourceforge.pmd.lang.java.symbols;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.List;
@@ -17,6 +19,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue.SymAnnot;
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue.SymEnum;
import net.sourceforge.pmd.lang.java.types.JArrayType;
import net.sourceforge.pmd.lang.java.types.JClassType;
@@ -247,6 +250,22 @@ public interface JClassSymbol extends JTypeDeclSymbol,
.orElse(RetentionPolicy.CLASS);
}
/**
* Return whether annotations of this annotation type apply to the
* given construct, as per the {@link Target} annotation. Return
* false if this is not an annotation.
*/
default boolean annotationAppliesTo(ElementType elementType) {
if (!isAnnotation()) {
return false;
}
SymAnnot target = getDeclaredAnnotation(Target.class);
if (target == null) {
return false;
}
return target.attributeContains("value", elementType).isTrue();
}
// todo isSealed + getPermittedSubclasses
// (isNonSealed is not so useful I think)
@@ -200,6 +200,30 @@ public interface SymbolicValue {
}
}
/**
* Returns YES if the annotation has the attribute set to the
* given value. Returns NO if it is set to another value.
* Returns UNKNOWN if the attribute does not exist or is
* unresolved.
*/
default OptionalBool attributeContains(String attrName, Object attrValue) {
SymbolicValue attr = getAttribute(attrName);
if (attr == null) {
return OptionalBool.UNKNOWN;
}
if (attr instanceof SymArray) {
// todo what if the value is an array itself
return OptionalBool.definitely(((SymArray) attr).elements.stream().anyMatch(it -> it.valueEquals(attrValue)));
}
if (attrValue instanceof SymbolicValue) {
return OptionalBool.definitely(attr.equals(attrValue));
} else {
return OptionalBool.definitely(attr.valueEquals(attrValue));
}
}
boolean appliesToTypeUse();
}
/**
@@ -278,6 +302,18 @@ public interface SymbolicValue {
return length;
}
public boolean containsValue(Object value) {
if (primArray != null) {
// todo I don't know how to code that
} else if (elements != null) {
if (value instanceof SymbolicValue) {
return elements.stream().anyMatch(it -> it.equals(value));
}
return elements.stream().anyMatch(it -> it.valueEquals(value));
}
return false;
}
@Override
public boolean valueEquals(Object o) {
if (!o.getClass().isArray() || !isOkComponentType(o.getClass().getComponentType())) {
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.java.symbols.internal;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.Set;
@@ -56,6 +57,11 @@ public class FakeSymAnnot implements SymAnnot {
return annotationClass.getAnnotationRetention();
}
@Override
public boolean appliesToTypeUse() {
return annotationClass.annotationAppliesTo(ElementType.TYPE_USE);
}
@Override
public String toString() {
return "@" + annotationClass.getCanonicalName();
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.java.symbols.internal.asm;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashMap;
@@ -76,6 +77,11 @@ final class SymbolicAnnotationImpl implements SymAnnot {
: RetentionPolicy.CLASS;
}
@Override
public boolean appliesToTypeUse() {
return typeStub.annotationAppliesTo(ElementType.TYPE_USE);
}
@Override
public String getBinaryName() {
return typeStub.getBinaryName();
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.java.symbols.internal.ast;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -59,6 +60,11 @@ class AstSymbolicAnnot implements SymbolicValue.SymAnnot {
return retention;
}
@Override
public boolean appliesToTypeUse() {
return node.getTypeMirror().getSymbol().annotationAppliesTo(ElementType.TYPE_USE);
}
@Override
public @NonNull String getBinaryName() {
return node.getTypeMirror().getSymbol().getBinaryName();