Java: Add annotation tests

This commit is contained in:
Marcono1234
2022-04-02 18:53:29 +02:00
committed by Chris Smowton
parent 8c9bdeb3be
commit 37b18914ac
11 changed files with 867 additions and 17 deletions

View File

@@ -66,6 +66,16 @@ class Annotation extends @annotation, Expr {
*/
Expr getValue(string name) { filteredAnnotValue(this, this.getAnnotationElement(name), result) }
/**
* Gets the value of the annotation element, if its type is not an array.
* This guarantees that for consistency even elements of type array with a
* single value have no result, to prevent accidental error-prone usage.
*/
private Expr getNonArrayValue(string name) {
result = this.getValue(name) and
not this.getAnnotationElement(name).getType() instanceof Array
}
/**
* If the value type of the annotation element with the specified `name` is an enum type,
* gets the enum constant used as value for that element. This includes default values in
@@ -74,7 +84,7 @@ class Annotation extends @annotation, Expr {
* If the element value type is an enum type array, use `getAnEnumConstantArrayValue`.
*/
EnumConstant getEnumConstantValue(string name) {
result = this.getValue(name).(FieldRead).getField()
result = this.getNonArrayValue(name).(FieldRead).getField()
}
/**
@@ -87,20 +97,23 @@ class Annotation extends @annotation, Expr {
string getStringValue(string name) {
// Uses CompileTimeConstantExpr instead of StringLiteral because this can for example
// be a read from a final variable as well.
result = this.getValue(name).(CompileTimeConstantExpr).getStringValue()
result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getStringValue()
}
/**
* If the value type of the annotation element with the specified `name` is `int`,
* gets the int value used for that element. This includes default values in case no
* explicit value is specified.
* If the value type of the annotation element with the specified `name` is `int` or
* a smaller integral type or `char`, gets the int value used for that element.
* This includes default values in case no explicit value is specified.
*
* If the element value type is an `int` array, use `getAnIntArrayValue`.
* If the element value type is an `int` array or an array of a smaller integral
* type or `char`, use `getAnIntArrayValue`.
*/
int getIntValue(string name) {
// Uses CompileTimeConstantExpr instead of IntegerLiteral because this can for example
// be a read from a final variable as well.
result = this.getValue(name).(CompileTimeConstantExpr).getIntValue()
result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getIntValue() and
// Verify that type is integral; ignore floating point elements with IntegerLiteral as value
this.getAnnotationElement(name).getType().hasName(["byte", "short", "int", "char"])
}
/**
@@ -111,7 +124,7 @@ class Annotation extends @annotation, Expr {
boolean getBooleanValue(string name) {
// Uses CompileTimeConstantExpr instead of BooleanLiteral because this can for example
// be a read from a final variable as well.
result = this.getValue(name).(CompileTimeConstantExpr).getBooleanValue()
result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getBooleanValue()
}
/**
@@ -121,7 +134,9 @@ class Annotation extends @annotation, Expr {
*
* If the element value type is a `Class` array, use `getATypeArrayValue`.
*/
Type getTypeValue(string name) { result = this.getValue(name).(TypeLiteral).getReferencedType() }
Type getTypeValue(string name) {
result = this.getNonArrayValue(name).(TypeLiteral).getReferencedType()
}
/** Gets the element being annotated. */
Element getTarget() { result = this.getAnnotatedElement() }
@@ -169,13 +184,16 @@ class Annotation extends @annotation, Expr {
/**
* Gets a value of the annotation element with the specified `name`, which must be declared as an `int`
* array. This includes default values in case no explicit value is specified.
* array or an array of a smaller integral type or `char`. This includes default values in case no
* explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the result will be one of the
* elements of that array. Otherwise, the result will be the single expression used as value.
*/
int getAnIntArrayValue(string name) {
result = this.getAnArrayValue(name).(CompileTimeConstantExpr).getIntValue()
result = this.getAnArrayValue(name).(CompileTimeConstantExpr).getIntValue() and
// Verify that type is integral; ignore floating point elements with IntegerLiteral as value
this.getAnnotationElement(name).getType().hasName(["byte[]", "short[]", "int[]", "char[]"])
}
/**
@@ -194,14 +212,16 @@ class Annotation extends @annotation, Expr {
* declared as an array type. This includes default values in case no explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the result will be the element
* at the given index of that array. Otherwise, the result will be the single expression defined for
* the value and the `index` will be 0.
* at the given index of that array, starting at 0. Otherwise, the result will be the single expression
* defined for the value and the `index` will be 0.
*/
Expr getArrayValue(string name, int index) {
this.getType().getAnnotationElement(name).getType() instanceof Array and
exists(Expr value | value = this.getValue(name) |
if value instanceof ArrayInit
then result = value.(ArrayInit).getInit(index)
then
// TODO: Currently reports incorrect index values in some cases, see https://github.com/github/codeql/issues/8645
result = value.(ArrayInit).getInit(index)
else (
index = 0 and result = value
)
@@ -234,15 +254,21 @@ private predicate sourceAnnotValue(Annotation a, Method m, Expr val) {
/** An abstract representation of language elements that can be annotated. */
class Annotatable extends Element {
/** Holds if this element has an annotation, including inherited annotations. */
/**
* Holds if this element has an annotation, including inherited annotations.
* The retention policy of the annotation type is not considered.
*/
predicate hasAnnotation() { exists(this.getAnAnnotation()) }
/** Holds if this element has a declared annotation, excluding inherited annotations. */
/**
* Holds if this element has a declared annotation, excluding inherited annotations.
* The retention policy of the annotation type is not considered.
*/
predicate hasDeclaredAnnotation() { exists(this.getADeclaredAnnotation()) }
/**
* Holds if this element has the specified annotation, including inherited
* annotations.
* annotations. The retention policy of the annotation type is not considered.
*/
predicate hasAnnotation(string package, string name) {
exists(AnnotationType at | at = this.getAnAnnotation().getType() |
@@ -254,6 +280,7 @@ class Annotatable extends Element {
* Gets an annotation that applies to this element, including inherited annotations.
* The results only include _direct_ annotations; _indirect_ annotations, that is
* repeated annotations in an (implicit) container annotation, are not included.
* The retention policy of the annotation type is not considered.
*/
cached
Annotation getAnAnnotation() {
@@ -263,6 +290,7 @@ class Annotatable extends Element {
/**
* Gets an annotation that is declared on this element, excluding inherited annotations.
* The retention policy of the annotation type is not considered.
*/
Annotation getADeclaredAnnotation() { result.getAnnotatedElement() = this }
@@ -302,6 +330,8 @@ class Annotatable extends Element {
* - An annotation indirectly present on this element (in the form of a repeated annotation), or
* - If an annotation of a type is neither directly nor indirectly present
* the result is an associated inherited annotation (recursively)
*
* The retention policy of the annotation type is not considered.
*/
Annotation getAnAssociatedAnnotation() { result = this.getAnAssociatedAnnotation(_) }
@@ -320,6 +350,11 @@ class Annotatable extends Element {
or
this.(NestedClass).getEnclosingType().suppressesWarningsAbout(category)
or
this.(LocalClassOrInterface)
.getLocalTypeDeclStmt()
.getEnclosingCallable()
.suppressesWarningsAbout(category)
or
this.(LocalVariableDecl).getCallable().suppressesWarningsAbout(category)
}
}

View File

@@ -0,0 +1,101 @@
declaredAnnotation
| Annotatable.java:8:16:8:40 | CustomInheritedAnnotation | Annotatable.java:7:5:7:14 | Inherited |
| Annotatable.java:14:11:14:22 | WithDeclared | Annotatable.java:12:5:12:21 | CustomAnnotation |
| Annotatable.java:14:11:14:22 | WithDeclared | Annotatable.java:13:5:13:38 | CustomInheritedAnnotation |
| Annotatable.java:17:14:17:31 | methodWithDeclared | Annotatable.java:16:9:16:49 | CustomInheritedAnnotation |
| Annotatable.java:22:14:22:31 | methodWithDeclared | Annotatable.java:21:9:21:17 | Override |
| Annotatable.java:30:11:30:41 | SubclassDeclaringSameAnnotation | Annotatable.java:29:5:29:37 | CustomInheritedAnnotation |
| Annotatable.java:35:15:35:35 | InterfaceWithDeclared | Annotatable.java:34:5:34:38 | CustomInheritedAnnotation |
| Annotatable.java:47:16:47:35 | RepeatableAnnotation | Annotatable.java:46:5:46:42 | Repeatable |
| Annotatable.java:52:16:52:43 | InheritedContainerAnnotation | Annotatable.java:51:5:51:14 | Inherited |
| Annotatable.java:58:16:58:44 | InheritedRepeatableAnnotation | Annotatable.java:56:5:56:14 | Inherited |
| Annotatable.java:58:16:58:44 | InheritedRepeatableAnnotation | Annotatable.java:57:5:57:51 | Repeatable |
| Annotatable.java:63:16:63:44 | InheritedContainerAnnotation2 | Annotatable.java:62:5:62:14 | Inherited |
| Annotatable.java:71:16:71:47 | NonInheritedRepeatableAnnotation | Annotatable.java:70:5:70:52 | Repeatable |
| Annotatable.java:78:11:78:30 | WithAssociatedSingle | Annotatable.java:75:5:75:33 | RepeatableAnnotation |
| Annotatable.java:78:11:78:30 | WithAssociatedSingle | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation |
| Annotatable.java:78:11:78:30 | WithAssociatedSingle | Annotatable.java:77:5:77:45 | NonInheritedRepeatableAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | ContainerAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 |
| Annotatable.java:92:11:92:44 | SubclassOfSingleWithEmptyContainer | Annotatable.java:90:5:90:37 | InheritedContainerAnnotation |
| Annotatable.java:92:11:92:44 | SubclassOfSingleWithEmptyContainer | Annotatable.java:91:5:91:38 | InheritedContainerAnnotation2 |
| Annotatable.java:98:15:98:37 | InterfaceWithAssociated | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | ContainerAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 |
| Annotatable.java:116:14:116:39 | methodWithAssociatedSingle | Annotatable.java:115:9:115:53 | InheritedRepeatableAnnotation |
| Annotatable.java:121:14:121:33 | methodWithAssociated | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation |
| Annotatable.java:126:14:126:39 | methodWithAssociatedSingle | Annotatable.java:125:9:125:17 | Override |
| Annotatable.java:129:14:129:33 | methodWithAssociated | Annotatable.java:128:9:128:17 | Override |
| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.java:135:5:135:34 | RepeatableAnnotation |
| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.java:136:5:136:43 | InheritedRepeatableAnnotation |
| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.java:137:5:137:46 | NonInheritedRepeatableAnnotation |
| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.java:142:5:142:37 | InheritedContainerAnnotation |
| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.java:143:5:143:38 | InheritedContainerAnnotation2 |
| Annotatable.java:150:35:153:5 | {...} | Annotatable.java:151:9:151:53 | InheritedRepeatableAnnotation |
| Annotatable.java:150:35:153:5 | {...} | Annotatable.java:152:9:152:53 | InheritedRepeatableAnnotation |
| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:148:5:148:44 | InheritedRepeatableAnnotation |
| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:150:5:153:6 | InheritedContainerAnnotation |
| Annotatable.java:160:16:160:41 | NestedAnnotationContainer1 | Annotatable.java:159:5:159:14 | Inherited |
| Annotatable.java:166:16:166:32 | NestedAnnotation1 | Annotatable.java:164:5:164:14 | Inherited |
| Annotatable.java:166:16:166:32 | NestedAnnotation1 | Annotatable.java:165:5:165:49 | Repeatable |
| Annotatable.java:172:16:172:32 | NestedAnnotation2 | Annotatable.java:170:5:170:14 | Inherited |
| Annotatable.java:172:16:172:32 | NestedAnnotation2 | Annotatable.java:171:5:171:40 | Repeatable |
| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 |
| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.java:177:5:177:27 | NestedAnnotation2 |
| Annotatable.java:189:11:189:48 | WithNestedAssociatedExplicitContainers | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 |
annotationAdditional
| Annotatable.java:20:11:20:18 | Subclass | Annotatable.java:13:5:13:38 | CustomInheritedAnnotation |
| Annotatable.java:26:11:26:21 | SubSubclass | Annotatable.java:13:5:13:38 | CustomInheritedAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation |
| Annotatable.java:92:11:92:44 | SubclassOfSingleWithEmptyContainer | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation |
| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation |
| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 |
| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation |
| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 |
| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation |
| Annotatable.java:138:11:138:28 | SubclassWithSingle | Annotatable.class:0:0:0:0 | InheritedContainerAnnotation2 |
| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:148:5:148:44 | InheritedRepeatableAnnotation |
| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:150:5:153:6 | InheritedContainerAnnotation |
| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 |
| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.java:177:5:177:27 | NestedAnnotation2 |
| Annotatable.java:191:11:191:56 | WithNestedAssociatedExplicitContainersSubclass | Annotatable.class:0:0:0:0 | NestedAnnotationContainer1 |
bugAnnotationAdditional
associatedAnnotationAdditional
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation |
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation |
| Annotatable.java:98:15:98:37 | InterfaceWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:98:15:98:37 | InterfaceWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | NonInheritedRepeatableAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation |
| Annotatable.java:113:11:113:32 | WithAssociatedMultiple | Annotatable.class:0:0:0:0 | RepeatableAnnotation |
| Annotatable.java:121:14:121:33 | methodWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:121:14:121:33 | methodWithAssociated | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:124:11:124:32 | WithAssociatedSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:133:11:133:35 | WithAssociatedSubSubclass | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:144:11:144:46 | SubclassOfMultipleWithEmptyContainer | Annotatable.class:0:0:0:0 | InheritedRepeatableAnnotation |
| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:151:9:151:53 | InheritedRepeatableAnnotation |
| Annotatable.java:154:11:154:45 | ExplicitContainerAndSingleContained | Annotatable.java:152:9:152:53 | InheritedRepeatableAnnotation |
| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:151:9:151:53 | InheritedRepeatableAnnotation |
| Annotatable.java:156:11:156:35 | ExplicitContainerSubclass | Annotatable.java:152:9:152:53 | InheritedRepeatableAnnotation |
| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
| Annotatable.java:182:11:182:30 | WithNestedAssociated | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
| Annotatable.java:184:11:184:38 | WithNestedAssociatedSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
| Annotatable.java:189:11:189:48 | WithNestedAssociatedExplicitContainers | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
| Annotatable.java:189:11:189:48 | WithNestedAssociatedExplicitContainers | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
| Annotatable.java:191:11:191:56 | WithNestedAssociatedExplicitContainersSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
| Annotatable.java:191:11:191:56 | WithNestedAssociatedExplicitContainersSubclass | Annotatable.class:0:0:0:0 | NestedAnnotation1 |
associatedAnnotationNotInherited
| Annotatable.java:86:11:86:30 | SubclassWithMultiple | Annotatable.java:76:5:76:42 | InheritedRepeatableAnnotation |

View File

@@ -0,0 +1,192 @@
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
class Annotatable {
@interface CustomAnnotation {}
@Inherited
@interface CustomInheritedAnnotation {
String value();
}
@CustomAnnotation
@CustomInheritedAnnotation("base")
class WithDeclared {
// Annotations on methods are not inherited
@CustomInheritedAnnotation("base-method")
void methodWithDeclared() {}
}
class Subclass extends WithDeclared {
@Override
void methodWithDeclared() {}
}
// Inheritance from super-superclass
class SubSubclass extends Subclass {}
// Prevents inheriting annotation of same type
@CustomInheritedAnnotation("sub")
class SubclassDeclaringSameAnnotation extends WithDeclared {}
// Annotations on interfaces are not inherited
@CustomInheritedAnnotation("base")
interface InterfaceWithDeclared {}
interface ExtendingInterface extends InterfaceWithDeclared {}
class ImplementingInterface implements InterfaceWithDeclared {}
@interface ContainerAnnotation {
RepeatableAnnotation[] value();
}
@Repeatable(ContainerAnnotation.class)
@interface RepeatableAnnotation {
String value();
}
@Inherited
@interface InheritedContainerAnnotation {
InheritedRepeatableAnnotation[] value();
}
@Inherited
@Repeatable(InheritedContainerAnnotation.class)
@interface InheritedRepeatableAnnotation {
String value();
}
@Inherited
@interface InheritedContainerAnnotation2 {
NonInheritedRepeatableAnnotation[] value();
}
// Container is marked as @Inherited, but this annotation type is not
// This is allowed, but means that associated annotations will not be inherited,
// see java.lang.reflect.AnnotatedElement documentation
@Repeatable(InheritedContainerAnnotation2.class)
@interface NonInheritedRepeatableAnnotation {
String value();
}
@RepeatableAnnotation("base")
@InheritedRepeatableAnnotation("base")
@NonInheritedRepeatableAnnotation("base")
class WithAssociatedSingle {}
@RepeatableAnnotation("sub-1")
@RepeatableAnnotation("sub-2")
@InheritedRepeatableAnnotation("sub-1")
@InheritedRepeatableAnnotation("sub-2")
@NonInheritedRepeatableAnnotation("sub-1")
@NonInheritedRepeatableAnnotation("sub-2")
class SubclassWithMultiple extends WithAssociatedSingle {}
// Empty container annotations have no effect; annotations are inherited from superclass
@InheritedContainerAnnotation({})
@InheritedContainerAnnotation2({})
class SubclassOfSingleWithEmptyContainer extends WithAssociatedSingle {}
// Annotations on interfaces are not inherited
@InheritedRepeatableAnnotation("base-1")
@InheritedRepeatableAnnotation("base-2")
interface InterfaceWithAssociated {}
interface ExtendingInterfaceWithAssociated extends InterfaceWithAssociated {}
class ImplementingInterfaceWithAssociated implements InterfaceWithAssociated {}
@RepeatableAnnotation("base-1")
@RepeatableAnnotation("base-2")
@InheritedRepeatableAnnotation("base-1")
@InheritedRepeatableAnnotation("base-2")
// These annotations are not inherited, but their (implicit) container annotation
// is inherited
@NonInheritedRepeatableAnnotation("base-1")
@NonInheritedRepeatableAnnotation("base-2")
class WithAssociatedMultiple {
// Annotations on methods are not inherited
@InheritedRepeatableAnnotation("base-method")
void methodWithAssociatedSingle() {}
// Annotations on methods are not inherited
@InheritedRepeatableAnnotation("base-method-1")
@InheritedRepeatableAnnotation("base-method-2")
void methodWithAssociated() {}
}
class WithAssociatedSubclass extends WithAssociatedMultiple {
@Override
void methodWithAssociatedSingle() {}
@Override
void methodWithAssociated() {}
}
// Inheritance from super-superclass
class WithAssociatedSubSubclass extends WithAssociatedSubclass {}
@RepeatableAnnotation("sub-1")
@InheritedRepeatableAnnotation("sub-1")
@NonInheritedRepeatableAnnotation("sub-1")
class SubclassWithSingle extends WithAssociatedMultiple {}
// Empty container annotations have no effect; associated annotations are inherited from superclass
@InheritedContainerAnnotation({})
@InheritedContainerAnnotation2({})
class SubclassOfMultipleWithEmptyContainer extends WithAssociatedMultiple {}
// This annotation exists on its own without a container
@InheritedRepeatableAnnotation("single")
// TODO: Has currently spurious results for ArrayInit due to https://github.com/github/codeql/issues/8647
@InheritedContainerAnnotation({
@InheritedRepeatableAnnotation("container-1"),
@InheritedRepeatableAnnotation("container-2")
})
class ExplicitContainerAndSingleContained {}
class ExplicitContainerSubclass extends ExplicitContainerAndSingleContained {}
@Inherited
@interface NestedAnnotationContainer1 {
NestedAnnotation1[] value();
}
@Inherited
@Repeatable(NestedAnnotationContainer1.class)
@interface NestedAnnotation1 {
NestedAnnotation2[] value();
}
@Inherited
@Repeatable(NestedAnnotation1.class)
@interface NestedAnnotation2 {
String value();
}
// This annotation exists on its own without a container
@NestedAnnotation2("1")
// But these are nested inside an implicit @NestedAnnotationContainer1
// Nested repeated annotations (@NestedAnnotation2) are not considered associated
@NestedAnnotation1({@NestedAnnotation2("1-1"), @NestedAnnotation2("1-2")})
@NestedAnnotation1({@NestedAnnotation2("2-1"), @NestedAnnotation2("2-2")})
class WithNestedAssociated {}
class WithNestedAssociatedSubclass extends WithNestedAssociated {}
// Nested repeated annotations (@NestedAnnotation2) are not considered associated
@NestedAnnotation1({@NestedAnnotation2("1-1"), @NestedAnnotation2("1-2")})
@NestedAnnotation1({@NestedAnnotation2("2-1"), @NestedAnnotation2("2-2")})
class WithNestedAssociatedExplicitContainers {}
class WithNestedAssociatedExplicitContainersSubclass extends WithNestedAssociatedExplicitContainers {}
}

View File

@@ -0,0 +1,34 @@
import java
class RelevantAnnotatable extends Annotatable {
RelevantAnnotatable() {
getCompilationUnit().hasName("Annotatable") and getCompilationUnit().fromSource()
}
}
query Annotation declaredAnnotation(RelevantAnnotatable a) { result = a.getADeclaredAnnotation() }
/** Note: Only has the annotations as result which are not also considered _declared_. */
query Annotation annotationAdditional(RelevantAnnotatable a) {
result = a.getAnAnnotation() and not result = a.getADeclaredAnnotation()
}
/** Sanity check to verify that `getADeclaredAnnotation()` is a subset of `getAnAnnotation()` */
query Annotation bugAnnotationAdditional(RelevantAnnotatable a) {
result = a.getADeclaredAnnotation() and not result = a.getAnAnnotation()
}
/** Note: Only has the annotations as result which are not part of `getAnAnnotation()`. */
query Annotation associatedAnnotationAdditional(RelevantAnnotatable a) {
result = a.getAnAssociatedAnnotation() and not result = a.getAnAnnotation()
}
/**
* Covers all results of `getAnAssociatedAnnotation()` which are not also a result of `getAnAnnotation()`.
* This should only be the case for a base class using an inheritable annotation `A` and a subclass which
* has an annotation `CA` of the container type of `A`. In that case `A` is not considered _associated_
* and the _indirect_ annotations from `CA` are considered instead.
*/
query Annotation associatedAnnotationNotInherited(RelevantAnnotatable a) {
result = a.getAnAnnotation() and not result = a.getAnAssociatedAnnotation()
}

View File

@@ -0,0 +1,213 @@
value
| AnnotationValues.java:39:5:39:17 | SingleValues | annotationValue | AnnotationValues.class:0:0:0:0 | CustomAnnotation |
| AnnotationValues.java:39:5:39:17 | SingleValues | booleanValue | AnnotationValues.class:0:0:0:0 | false |
| AnnotationValues.java:39:5:39:17 | SingleValues | byteValue | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:39:5:39:17 | SingleValues | charValue | AnnotationValues.class:0:0:0:0 | \uffff |
| AnnotationValues.java:39:5:39:17 | SingleValues | classValue | AnnotationValues.class:0:0:0:0 | AnnotationValues.class |
| AnnotationValues.java:39:5:39:17 | SingleValues | doubleValue | AnnotationValues.class:0:0:0:0 | -1.0 |
| AnnotationValues.java:39:5:39:17 | SingleValues | enumValue | AnnotationValues.class:0:0:0:0 | DEFAULT |
| AnnotationValues.java:39:5:39:17 | SingleValues | floatValue | AnnotationValues.class:0:0:0:0 | -1.0 |
| AnnotationValues.java:39:5:39:17 | SingleValues | intValue | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:39:5:39:17 | SingleValues | longValue | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:39:5:39:17 | SingleValues | shortValue | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:39:5:39:17 | SingleValues | stringValue | AnnotationValues.class:0:0:0:0 | "\u0000" |
| AnnotationValues.java:42:5:55:5 | SingleValues | annotationValue | AnnotationValues.java:54:27:54:53 | CustomAnnotation |
| AnnotationValues.java:42:5:55:5 | SingleValues | booleanValue | AnnotationValues.java:49:24:49:27 | true |
| AnnotationValues.java:42:5:55:5 | SingleValues | byteValue | AnnotationValues.java:43:21:43:21 | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | charValue | AnnotationValues.java:50:21:50:21 | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | classValue | AnnotationValues.java:52:22:52:39 | SingleValues.class |
| AnnotationValues.java:42:5:55:5 | SingleValues | doubleValue | AnnotationValues.java:48:23:48:23 | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | enumValue | AnnotationValues.java:53:21:53:32 | CustomEnum.A |
| AnnotationValues.java:42:5:55:5 | SingleValues | floatValue | AnnotationValues.java:47:22:47:22 | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | intValue | AnnotationValues.java:45:20:45:20 | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | longValue | AnnotationValues.java:46:21:46:21 | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | shortValue | AnnotationValues.java:44:22:44:22 | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | stringValue | AnnotationValues.java:51:23:51:25 | "a" |
| AnnotationValues.java:54:27:54:53 | CustomAnnotation | value | AnnotationValues.java:54:45:54:52 | "single" |
| AnnotationValues.java:58:5:71:5 | SingleValues | annotationValue | AnnotationValues.java:70:27:70:53 | CustomAnnotation |
| AnnotationValues.java:58:5:71:5 | SingleValues | booleanValue | AnnotationValues.java:65:24:65:30 | BOOLEAN |
| AnnotationValues.java:58:5:71:5 | SingleValues | byteValue | AnnotationValues.java:59:21:59:24 | BYTE |
| AnnotationValues.java:58:5:71:5 | SingleValues | charValue | AnnotationValues.java:66:21:66:24 | CHAR |
| AnnotationValues.java:58:5:71:5 | SingleValues | classValue | AnnotationValues.java:68:22:68:39 | SingleValues.class |
| AnnotationValues.java:58:5:71:5 | SingleValues | doubleValue | AnnotationValues.java:64:23:64:28 | DOUBLE |
| AnnotationValues.java:58:5:71:5 | SingleValues | enumValue | AnnotationValues.java:69:21:69:32 | CustomEnum.A |
| AnnotationValues.java:58:5:71:5 | SingleValues | floatValue | AnnotationValues.java:63:22:63:26 | FLOAT |
| AnnotationValues.java:58:5:71:5 | SingleValues | intValue | AnnotationValues.java:61:20:61:22 | INT |
| AnnotationValues.java:58:5:71:5 | SingleValues | longValue | AnnotationValues.java:62:21:62:24 | LONG |
| AnnotationValues.java:58:5:71:5 | SingleValues | shortValue | AnnotationValues.java:60:22:60:26 | SHORT |
| AnnotationValues.java:58:5:71:5 | SingleValues | stringValue | AnnotationValues.java:67:23:67:28 | STRING |
| AnnotationValues.java:70:27:70:53 | CustomAnnotation | value | AnnotationValues.java:70:45:70:52 | "single" |
| AnnotationValues.java:90:5:90:16 | ArrayValues | annotationValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | booleanValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | byteValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | charValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | classValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | doubleValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | enumValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | floatValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | intValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | longValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | shortValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:90:5:90:16 | ArrayValues | stringValues | AnnotationValues.class:0:0:0:0 | {...} |
| AnnotationValues.java:93:5:106:5 | ArrayValues | annotationValues | AnnotationValues.java:105:28:105:54 | (no string representation) |
| AnnotationValues.java:93:5:106:5 | ArrayValues | booleanValues | AnnotationValues.java:100:25:100:28 | true |
| AnnotationValues.java:93:5:106:5 | ArrayValues | byteValues | AnnotationValues.java:94:22:94:22 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | charValues | AnnotationValues.java:101:22:101:24 | 'a' |
| AnnotationValues.java:93:5:106:5 | ArrayValues | classValues | AnnotationValues.java:103:23:103:39 | ArrayValues.class |
| AnnotationValues.java:93:5:106:5 | ArrayValues | doubleValues | AnnotationValues.java:99:24:99:24 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | enumValues | AnnotationValues.java:104:22:104:33 | CustomEnum.A |
| AnnotationValues.java:93:5:106:5 | ArrayValues | floatValues | AnnotationValues.java:98:23:98:23 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | intValues | AnnotationValues.java:96:21:96:21 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | longValues | AnnotationValues.java:97:22:97:22 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | shortValues | AnnotationValues.java:95:23:95:23 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | stringValues | AnnotationValues.java:102:24:102:26 | "a" |
| AnnotationValues.java:109:5:122:5 | ArrayValues | annotationValues | AnnotationValues.java:121:28:121:84 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | AnnotationValues.java:116:25:116:40 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | AnnotationValues.java:110:22:110:30 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | AnnotationValues.java:117:22:117:32 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | AnnotationValues.java:119:23:119:61 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | AnnotationValues.java:115:24:115:34 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | AnnotationValues.java:120:22:120:49 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | AnnotationValues.java:114:23:114:32 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | AnnotationValues.java:112:21:112:28 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | AnnotationValues.java:113:22:113:30 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | AnnotationValues.java:111:23:111:32 | {...} |
| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | AnnotationValues.java:118:24:118:33 | {...} |
| AnnotationValues.java:121:29:121:54 | CustomAnnotation | value | AnnotationValues.java:121:47:121:53 | "first" |
| AnnotationValues.java:121:57:121:83 | CustomAnnotation | value | AnnotationValues.java:121:75:121:82 | "second" |
enumConstantValue
| AnnotationValues.java:39:5:39:17 | SingleValues | enumValue | AnnotationValues.java:14:9:14:15 | DEFAULT |
| AnnotationValues.java:42:5:55:5 | SingleValues | enumValue | AnnotationValues.java:15:9:15:9 | A |
| AnnotationValues.java:58:5:71:5 | SingleValues | enumValue | AnnotationValues.java:15:9:15:9 | A |
stringValue
| AnnotationValues.java:39:5:39:17 | SingleValues | stringValue | \u0000 |
| AnnotationValues.java:42:5:55:5 | SingleValues | stringValue | a |
| AnnotationValues.java:54:27:54:53 | CustomAnnotation | value | single |
| AnnotationValues.java:58:5:71:5 | SingleValues | stringValue | b |
| AnnotationValues.java:70:27:70:53 | CustomAnnotation | value | single |
| AnnotationValues.java:121:29:121:54 | CustomAnnotation | value | first |
| AnnotationValues.java:121:57:121:83 | CustomAnnotation | value | second |
intValue
| AnnotationValues.java:39:5:39:17 | SingleValues | byteValue | -1 |
| AnnotationValues.java:39:5:39:17 | SingleValues | charValue | 65535 |
| AnnotationValues.java:39:5:39:17 | SingleValues | intValue | -1 |
| AnnotationValues.java:39:5:39:17 | SingleValues | shortValue | -1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | byteValue | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | charValue | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | intValue | 1 |
| AnnotationValues.java:42:5:55:5 | SingleValues | shortValue | 1 |
| AnnotationValues.java:58:5:71:5 | SingleValues | byteValue | 2 |
| AnnotationValues.java:58:5:71:5 | SingleValues | charValue | 98 |
| AnnotationValues.java:58:5:71:5 | SingleValues | intValue | 2 |
| AnnotationValues.java:58:5:71:5 | SingleValues | shortValue | 2 |
booleanValue
| AnnotationValues.java:39:5:39:17 | SingleValues | booleanValue | false |
| AnnotationValues.java:42:5:55:5 | SingleValues | booleanValue | true |
| AnnotationValues.java:58:5:71:5 | SingleValues | booleanValue | true |
typeValue
| AnnotationValues.java:39:5:39:17 | SingleValues | classValue | AnnotationValues.java:1:7:1:22 | AnnotationValues |
| AnnotationValues.java:42:5:55:5 | SingleValues | classValue | AnnotationValues.java:23:16:23:27 | SingleValues |
| AnnotationValues.java:58:5:71:5 | SingleValues | classValue | AnnotationValues.java:23:16:23:27 | SingleValues |
arrayValue
| AnnotationValues.java:90:5:90:16 | ArrayValues | annotationValues | 0 | AnnotationValues.class:0:0:0:0 | CustomAnnotation |
| AnnotationValues.java:90:5:90:16 | ArrayValues | booleanValues | 0 | AnnotationValues.class:0:0:0:0 | false |
| AnnotationValues.java:90:5:90:16 | ArrayValues | byteValues | 0 | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | charValues | 0 | AnnotationValues.class:0:0:0:0 | \uffff |
| AnnotationValues.java:90:5:90:16 | ArrayValues | classValues | 0 | AnnotationValues.class:0:0:0:0 | AnnotationValues.class |
| AnnotationValues.java:90:5:90:16 | ArrayValues | doubleValues | 0 | AnnotationValues.class:0:0:0:0 | -1.0 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | enumValues | 0 | AnnotationValues.class:0:0:0:0 | DEFAULT |
| AnnotationValues.java:90:5:90:16 | ArrayValues | floatValues | 0 | AnnotationValues.class:0:0:0:0 | -1.0 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | intValues | 0 | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | longValues | 0 | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | shortValues | 0 | AnnotationValues.class:0:0:0:0 | -1 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | stringValues | 0 | AnnotationValues.class:0:0:0:0 | "\u0000" |
| AnnotationValues.java:93:5:106:5 | ArrayValues | annotationValues | 0 | AnnotationValues.java:105:28:105:54 | (no string representation) |
| AnnotationValues.java:93:5:106:5 | ArrayValues | booleanValues | 0 | AnnotationValues.java:100:25:100:28 | true |
| AnnotationValues.java:93:5:106:5 | ArrayValues | byteValues | 0 | AnnotationValues.java:94:22:94:22 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | charValues | 0 | AnnotationValues.java:101:22:101:24 | 'a' |
| AnnotationValues.java:93:5:106:5 | ArrayValues | classValues | 0 | AnnotationValues.java:103:23:103:39 | ArrayValues.class |
| AnnotationValues.java:93:5:106:5 | ArrayValues | doubleValues | 0 | AnnotationValues.java:99:24:99:24 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | enumValues | 0 | AnnotationValues.java:104:22:104:33 | CustomEnum.A |
| AnnotationValues.java:93:5:106:5 | ArrayValues | floatValues | 0 | AnnotationValues.java:98:23:98:23 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | intValues | 0 | AnnotationValues.java:96:21:96:21 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | longValues | 0 | AnnotationValues.java:97:22:97:22 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | shortValues | 0 | AnnotationValues.java:95:23:95:23 | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | stringValues | 0 | AnnotationValues.java:102:24:102:26 | "a" |
| AnnotationValues.java:109:5:122:5 | ArrayValues | annotationValues | 0 | AnnotationValues.java:121:29:121:54 | CustomAnnotation |
| AnnotationValues.java:109:5:122:5 | ArrayValues | annotationValues | 1 | AnnotationValues.java:121:57:121:83 | CustomAnnotation |
| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | 0 | AnnotationValues.class:0:0:0:0 | false |
| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | 1 | AnnotationValues.class:0:0:0:0 | true |
| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | -1 | AnnotationValues.java:116:26:116:30 | false |
| AnnotationValues.java:109:5:122:5 | ArrayValues | booleanValues | -2 | AnnotationValues.java:116:33:116:39 | BOOLEAN |
| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 0 | AnnotationValues.class:0:0:0:0 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 1 | AnnotationValues.class:0:0:0:0 | 2 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | -1 | AnnotationValues.java:110:23:110:23 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | -2 | AnnotationValues.java:110:26:110:29 | BYTE |
| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 0 | AnnotationValues.class:0:0:0:0 | a |
| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 1 | AnnotationValues.class:0:0:0:0 | b |
| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | -1 | AnnotationValues.java:117:23:117:25 | 'a' |
| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | -2 | AnnotationValues.java:117:28:117:31 | CHAR |
| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | 0 | AnnotationValues.class:0:0:0:0 | SingleValues.class |
| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | 1 | AnnotationValues.class:0:0:0:0 | ArrayValues.class |
| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | -1 | AnnotationValues.java:119:24:119:41 | SingleValues.class |
| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | -2 | AnnotationValues.java:119:44:119:60 | ArrayValues.class |
| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | 0 | AnnotationValues.class:0:0:0:0 | 1.0 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | 1 | AnnotationValues.class:0:0:0:0 | 2.0 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | -1 | AnnotationValues.java:115:25:115:25 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | doubleValues | -2 | AnnotationValues.java:115:28:115:33 | DOUBLE |
| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | 0 | AnnotationValues.class:0:0:0:0 | A |
| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | 1 | AnnotationValues.class:0:0:0:0 | B |
| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | -1 | AnnotationValues.java:120:23:120:34 | CustomEnum.A |
| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | -2 | AnnotationValues.java:120:37:120:48 | CustomEnum.B |
| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | 0 | AnnotationValues.class:0:0:0:0 | 1.0 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | 1 | AnnotationValues.class:0:0:0:0 | 2.0 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | -1 | AnnotationValues.java:114:24:114:24 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | floatValues | -2 | AnnotationValues.java:114:27:114:31 | FLOAT |
| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 0 | AnnotationValues.class:0:0:0:0 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 1 | AnnotationValues.class:0:0:0:0 | 2 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | -1 | AnnotationValues.java:112:22:112:22 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | -2 | AnnotationValues.java:112:25:112:27 | INT |
| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | 0 | AnnotationValues.class:0:0:0:0 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | 1 | AnnotationValues.class:0:0:0:0 | 2 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | -1 | AnnotationValues.java:113:23:113:23 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | longValues | -2 | AnnotationValues.java:113:26:113:29 | LONG |
| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 0 | AnnotationValues.class:0:0:0:0 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 1 | AnnotationValues.class:0:0:0:0 | 2 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | -1 | AnnotationValues.java:111:24:111:24 | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | -2 | AnnotationValues.java:111:27:111:31 | SHORT |
| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | 0 | AnnotationValues.class:0:0:0:0 | "a" |
| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | 1 | AnnotationValues.class:0:0:0:0 | "b" |
| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | -1 | AnnotationValues.java:118:25:118:27 | "a" |
| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | -2 | AnnotationValues.java:118:30:118:32 | "b" |
enumConstantArrayValue
| AnnotationValues.java:90:5:90:16 | ArrayValues | enumValues | AnnotationValues.java:14:9:14:15 | DEFAULT |
| AnnotationValues.java:93:5:106:5 | ArrayValues | enumValues | AnnotationValues.java:15:9:15:9 | A |
| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | AnnotationValues.java:15:9:15:9 | A |
| AnnotationValues.java:109:5:122:5 | ArrayValues | enumValues | AnnotationValues.java:16:9:16:9 | B |
stringArrayValue
| AnnotationValues.java:90:5:90:16 | ArrayValues | stringValues | \u0000 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | stringValues | a |
| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | a |
| AnnotationValues.java:109:5:122:5 | ArrayValues | stringValues | b |
intArrayValue
| AnnotationValues.java:90:5:90:16 | ArrayValues | byteValues | -1 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | charValues | 65535 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | intValues | -1 |
| AnnotationValues.java:90:5:90:16 | ArrayValues | shortValues | -1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | byteValues | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | charValues | 97 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | intValues | 1 |
| AnnotationValues.java:93:5:106:5 | ArrayValues | shortValues | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | byteValues | 2 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 97 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | charValues | 98 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | intValues | 2 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 1 |
| AnnotationValues.java:109:5:122:5 | ArrayValues | shortValues | 2 |
typeArrayValue
| AnnotationValues.java:90:5:90:16 | ArrayValues | classValues | AnnotationValues.java:1:7:1:22 | AnnotationValues |
| AnnotationValues.java:93:5:106:5 | ArrayValues | classValues | AnnotationValues.java:74:16:74:26 | ArrayValues |
| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | AnnotationValues.java:23:16:23:27 | SingleValues |
| AnnotationValues.java:109:5:122:5 | ArrayValues | classValues | AnnotationValues.java:74:16:74:26 | ArrayValues |

View File

@@ -0,0 +1,37 @@
import java
class RelevantAnnotation extends Annotation {
RelevantAnnotation() {
getCompilationUnit().hasName("AnnotationValues") and getCompilationUnit().fromSource()
}
}
query Expr value(RelevantAnnotation a, string name) { result = a.getValue(name) }
query EnumConstant enumConstantValue(RelevantAnnotation a, string name) {
result = a.getEnumConstantValue(name)
}
query string stringValue(RelevantAnnotation a, string name) { result = a.getStringValue(name) }
query int intValue(RelevantAnnotation a, string name) { result = a.getIntValue(name) }
query boolean booleanValue(RelevantAnnotation a, string name) { result = a.getBooleanValue(name) }
query Type typeValue(RelevantAnnotation a, string name) { result = a.getTypeValue(name) }
query Expr arrayValue(RelevantAnnotation a, string name, int index) {
result = a.getArrayValue(name, index)
}
query EnumConstant enumConstantArrayValue(RelevantAnnotation a, string name) {
result = a.getAnEnumConstantArrayValue(name)
}
query string stringArrayValue(RelevantAnnotation a, string name) {
result = a.getAStringArrayValue(name)
}
query int intArrayValue(RelevantAnnotation a, string name) { result = a.getAnIntArrayValue(name) }
query Type typeArrayValue(RelevantAnnotation a, string name) { result = a.getATypeArrayValue(name) }

View File

@@ -0,0 +1,13 @@
annotationType
| AnnotationType.java:11:16:11:34 | InheritedAnnotation | inherited | <any-target> | CLASS |
| AnnotationType.java:14:16:14:35 | DocumentedAnnotation | documented | <any-target> | CLASS |
| AnnotationType.java:16:16:16:34 | ContainerAnnotation | | <any-target> | CLASS |
| AnnotationType.java:21:16:21:35 | RepeatableAnnotation | repeatable | <any-target> | CLASS |
| AnnotationType.java:25:16:25:26 | EmptyTarget | | | CLASS |
| AnnotationType.java:28:16:28:27 | SingleTarget | | ANNOTATION_TYPE | CLASS |
| AnnotationType.java:43:16:43:25 | AllTargets | | ANNOTATION_TYPE,CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,MODULE,PACKAGE,PARAMETER,RECORD_COMPONENT,TYPE_PARAMETER,TYPE_USE | CLASS |
| AnnotationType.java:47:16:47:29 | ClassRetention | | <any-target> | CLASS |
| AnnotationType.java:50:16:50:31 | RuntimeRetention | | <any-target> | RUNTIME |
| AnnotationType.java:53:16:53:30 | SourceRetention | | <any-target> | SOURCE |
containingAnnotationType
| AnnotationType.java:21:16:21:35 | RepeatableAnnotation | AnnotationType.java:16:16:16:34 | ContainerAnnotation |

View File

@@ -0,0 +1,54 @@
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
class AnnotationType {
@Inherited
@interface InheritedAnnotation {}
@Documented
@interface DocumentedAnnotation {}
@interface ContainerAnnotation {
RepeatableAnnotation[] value();
}
@Repeatable(ContainerAnnotation.class)
@interface RepeatableAnnotation {}
@Target({})
@interface EmptyTarget {}
@Target(ElementType.ANNOTATION_TYPE)
@interface SingleTarget {}
@Target({
ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.LOCAL_VARIABLE,
ElementType.METHOD,
ElementType.MODULE,
ElementType.PACKAGE,
ElementType.PARAMETER,
ElementType.RECORD_COMPONENT,
ElementType.TYPE_PARAMETER,
ElementType.TYPE_USE
})
@interface AllTargets {}
@Retention(RetentionPolicy.CLASS)
@interface ClassRetention {}
@Retention(RetentionPolicy.RUNTIME)
@interface RuntimeRetention {}
@Retention(RetentionPolicy.SOURCE)
@interface SourceRetention {}
}

View File

@@ -0,0 +1,46 @@
import java
class RelevantAnnotationType extends AnnotationType {
RelevantAnnotationType() { getCompilationUnit().hasName("AnnotationType") }
}
query predicate annotationType(
RelevantAnnotationType t, string flagsString, string targets, string retentionPolicy
) {
flagsString =
concat(string s |
t.isInherited() and s = "inherited"
or
t.isDocumented() and s = "documented"
or
t.isRepeatable() and s = "repeatable"
|
s, "," order by s
) and
(
// Workaround to test if no explicit @Target is specified; in that case any string except
// TYPE_USE, which represents type contexts, is considered a target because it might be
// added to ElementType in a future JDK version
if t.isATargetType("<any-target>")
then
if t.isATargetType("TYPE_USE")
then targets = "BUG: Includes TYPE_USE"
else targets = "<any-target>"
else
targets =
concat(string s |
exists(EnumConstant elementType |
elementType.getDeclaringType().hasQualifiedName("java.lang.annotation", "ElementType") and
s = elementType.getName() and
t.isATargetType(s)
)
|
s, "," order by s
)
) and
retentionPolicy = t.getRetentionPolicy()
}
query AnnotationType containingAnnotationType(RelevantAnnotationType t) {
result = t.getContainingAnnotationType()
}

View File

@@ -0,0 +1,124 @@
class AnnotationValues {
private static final byte BYTE = 2;
private static final short SHORT = 2;
private static final int INT = 2;
private static final long LONG = 2;
private static final float FLOAT = 2;
private static final double DOUBLE = 2;
private static final boolean BOOLEAN = true;
private static final char CHAR = 'b';
private static final String STRING = "b";
enum CustomEnum {
DEFAULT,
A,
B
}
@interface CustomAnnotation {
String value();
}
@interface SingleValues {
byte byteValue() default -1;
short shortValue() default -1;
int intValue() default -1;
long longValue() default -1;
float floatValue() default -1;
double doubleValue() default -1;
boolean booleanValue() default false;
char charValue() default '\uFFFF';
String stringValue() default "\0";
Class<?> classValue() default AnnotationValues.class;
CustomEnum enumValue() default CustomEnum.DEFAULT;
CustomAnnotation annotationValue() default @CustomAnnotation("default");
}
@SingleValues
private int singleValuesDefault;
@SingleValues(
byteValue = 1,
shortValue = 1,
intValue = 1,
longValue = 1,
floatValue = 1,
doubleValue = 1,
booleanValue = true,
charValue = 1,
stringValue = "a",
classValue = SingleValues.class,
enumValue = CustomEnum.A,
annotationValue = @CustomAnnotation("single")
)
private int singleValues;
@SingleValues(
byteValue = BYTE,
shortValue = SHORT,
intValue = INT,
longValue = LONG,
floatValue = FLOAT,
doubleValue = DOUBLE,
booleanValue = BOOLEAN,
charValue = CHAR,
stringValue = STRING,
classValue = SingleValues.class,
enumValue = CustomEnum.A,
annotationValue = @CustomAnnotation("single")
)
private int singleValuesConstants;
@interface ArrayValues {
byte[] byteValues() default -1;
short[] shortValues() default -1;
int[] intValues() default -1;
long[] longValues() default -1;
float[] floatValues() default -1;
double[] doubleValues() default -1;
boolean[] booleanValues() default false;
char[] charValues() default '\uFFFF';
String[] stringValues() default "\0";
Class<?>[] classValues() default AnnotationValues.class;
CustomEnum[] enumValues() default CustomEnum.DEFAULT;
CustomAnnotation[] annotationValues() default @CustomAnnotation("default");
}
@ArrayValues
private int arrayValuesDefault;
@ArrayValues(
byteValues = 1,
shortValues = 1,
intValues = 1,
longValues = 1,
floatValues = 1,
doubleValues = 1,
booleanValues = true,
charValues = 'a',
stringValues = "a",
classValues = ArrayValues.class,
enumValues = CustomEnum.A,
annotationValues = @CustomAnnotation("single")
)
private int arrayValuesSingleExpr;
@ArrayValues(
byteValues = {1, BYTE},
shortValues = {1, SHORT},
intValues = {1, INT},
longValues = {1, LONG},
floatValues = {1, FLOAT},
doubleValues = {1, DOUBLE},
booleanValues = {false, BOOLEAN},
charValues = {'a', CHAR},
stringValues = {"a", "b"},
classValues = {SingleValues.class, ArrayValues.class},
enumValues = {CustomEnum.A, CustomEnum.B},
annotationValues = {@CustomAnnotation("first"), @CustomAnnotation("second")}
)
private int arrayValues;
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -source 16 -target 16