Filter annotations that apply to type use
This commit is contained in:
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())) {
|
||||
|
||||
+6
@@ -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();
|
||||
|
||||
+6
@@ -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();
|
||||
|
||||
+6
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user