mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Merge pull request #6246 from Marcono1234/marcono1234/annotation-improvements
Java: Improve and add predicates and classes for annotations
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The predicate `Annotation.getAValue()` has been deprecated because it might lead to obtaining the value of the wrong annotation element by accident. `getValue(string)` (or one of the value type specific predicates) should be used to explicitly specify the name of the annotation element.
|
||||
* The predicate `Annotation.getAValue(string)` has been renamed to `getAnArrayValue(string)`.
|
||||
* The predicate `SuppressWarningsAnnotation.getASuppressedWarningLiteral()` has been deprecated because it unnecessarily restricts the result type; `getASuppressedWarning()` should be used instead.
|
||||
* The predicates `TargetAnnotation.getATargetExpression()` and `RetentionAnnotation.getRetentionPolicyExpression()` have been deprecated because getting the enum constant read expression is rarely useful, instead the corresponding predicates for getting the name of the referenced enum constants should be used.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* The predicates of the CodeQL class `Annotation` have been improved:
|
||||
* Convenience value type specific predicates have been added, such as `getEnumConstantValue(string)` or `getStringValue(string)`.
|
||||
* Convenience predicates for elements with array values have been added, such as `getAnEnumConstantArrayValue(string)`. While the behavior of the existing predicates has not changed, usage of them should be reviewed (or replaced with the newly added predicate) to make sure they work correctly for elements with array values.
|
||||
* Some internal CodeQL usage of the `Annotation` predicates has been adjusted and corrected; this might affect the results of some queries.
|
||||
* New predicates have been added to the CodeQL class `Annotatable` to support getting declared and associated annotations. As part of that, `hasAnnotation()` has been changed to also consider inherited annotations, to be consistent with `hasAnnotation(string, string)` and `getAnAnnotation()`. The newly added predicate `hasDeclaredAnnotation()` can be used as replacement for the old functionality.
|
||||
* New predicates have been added to the CodeQL class `AnnotationType` to simplify getting information about usage of JDK meta-annotations, such as `@Retention`.
|
||||
@@ -44,12 +44,100 @@ class Annotation extends @annotation, Expr {
|
||||
result = this.getType().getAnnotationElement(name)
|
||||
}
|
||||
|
||||
/** Gets a value of an annotation element. */
|
||||
Expr getAValue() { filteredAnnotValue(this, _, result) }
|
||||
/**
|
||||
* DEPRECATED: Getting the value of _any_ annotation element is error-prone because
|
||||
* it could lead to selecting the value of the wrong element by accident (for example
|
||||
* when an annotation type is extended in the future). Prefer the predicate `getValue(string)`
|
||||
* and explicitly specify the element name. Use `getValue(_)` if it is really desired to
|
||||
* get the value of any element.
|
||||
*
|
||||
* Gets a value of an annotation element. This includes default values in case
|
||||
* no explicit value is specified. For elements with an array value type this
|
||||
* might have an `ArrayInit` as result. To properly handle array values, prefer
|
||||
* the predicate `getAnArrayValue`.
|
||||
*/
|
||||
deprecated Expr getAValue() { filteredAnnotValue(this, _, result) }
|
||||
|
||||
/** Gets the value of the annotation element with the specified `name`. */
|
||||
/**
|
||||
* Gets the value of the annotation element with the specified `name`.
|
||||
* This includes default values in case no explicit value is specified.
|
||||
* For elements with an array value type this might get an `ArrayInit` instance.
|
||||
* To properly handle array values, prefer the predicate `getAnArrayValue`.
|
||||
*/
|
||||
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
|
||||
* case no explicit value is specified.
|
||||
*
|
||||
* If the element value type is an enum type array, use `getAnEnumConstantArrayValue`.
|
||||
*/
|
||||
EnumConstant getEnumConstantValue(string name) {
|
||||
result = this.getNonArrayValue(name).(FieldRead).getField()
|
||||
}
|
||||
|
||||
/**
|
||||
* If the value type of the annotation element with the specified `name` is `String`,
|
||||
* gets the string value used for that element. This includes default values in case no
|
||||
* explicit value is specified.
|
||||
*
|
||||
* If the element value type is a string array, use `getAStringArrayValue`.
|
||||
*/
|
||||
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.getNonArrayValue(name).(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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.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"])
|
||||
}
|
||||
|
||||
/**
|
||||
* If the value type of the annotation element with the specified `name` is `boolean`,
|
||||
* gets the boolean value used for that element. This includes default values in case
|
||||
* no explicit value is specified.
|
||||
*/
|
||||
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.getNonArrayValue(name).(CompileTimeConstantExpr).getBooleanValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* If the value type of the annotation element with the specified `name` is `java.lang.Class`,
|
||||
* gets the type referred to by that `Class`. This includes default values in case no explicit
|
||||
* value is specified.
|
||||
*
|
||||
* If the element value type is a `Class` array, use `getATypeArrayValue`.
|
||||
*/
|
||||
Type getTypeValue(string name) {
|
||||
result = this.getNonArrayValue(name).(TypeLiteral).getReferencedType()
|
||||
}
|
||||
|
||||
/** Gets the element being annotated. */
|
||||
Element getTarget() { result = this.getAnnotatedElement() }
|
||||
|
||||
@@ -60,16 +148,83 @@ class Annotation extends @annotation, Expr {
|
||||
|
||||
/**
|
||||
* Gets a value of the annotation element with the specified `name`, which must be declared as an array
|
||||
* type.
|
||||
* type. This includes default values in case no explicit value is specified.
|
||||
*
|
||||
* If the annotation element is defined with an array initializer, then the returned value will
|
||||
* be one of the elements of that array. Otherwise, the returned value will be the single
|
||||
* expression defined for the value.
|
||||
* 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.
|
||||
*/
|
||||
Expr getAValue(string name) {
|
||||
Expr getAnArrayValue(string name) { result = this.getArrayValue(name, _) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Predicate has been renamed to `getAnArrayValue`
|
||||
*/
|
||||
deprecated Expr getAValue(string name) { result = this.getAnArrayValue(name) }
|
||||
|
||||
/**
|
||||
* Gets a value of the annotation element with the specified `name`, which must be declared as an enum
|
||||
* type array. 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.
|
||||
*/
|
||||
EnumConstant getAnEnumConstantArrayValue(string name) {
|
||||
result = this.getAnArrayValue(name).(FieldRead).getField()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value of the annotation element with the specified `name`, which must be declared as a string
|
||||
* array. 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.
|
||||
*/
|
||||
string getAStringArrayValue(string name) {
|
||||
result = this.getAnArrayValue(name).(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value of the annotation element with the specified `name`, which must be declared as an `int`
|
||||
* 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() and
|
||||
// Verify that type is integral; ignore floating point elements with IntegerLiteral as value
|
||||
this.getAnnotationElement(name).getType().hasName(["byte[]", "short[]", "int[]", "char[]"])
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value of the annotation element with the specified `name`, which must be declared as a `Class`
|
||||
* array. 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.
|
||||
*/
|
||||
Type getATypeArrayValue(string name) {
|
||||
result = this.getAnArrayValue(name).(TypeLiteral).getReferencedType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value at a given index of the annotation element with the specified `name`, which must be
|
||||
* 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, 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).getAnInit() else result = value
|
||||
if value instanceof ArrayInit
|
||||
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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -99,19 +254,86 @@ 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. */
|
||||
predicate hasAnnotation() { exists(Annotation a | a.getAnnotatedElement() = this) }
|
||||
/**
|
||||
* 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 the specified annotation. */
|
||||
/**
|
||||
* 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. The retention policy of the annotation type is not considered.
|
||||
*/
|
||||
predicate hasAnnotation(string package, string name) {
|
||||
exists(AnnotationType at | at = this.getAnAnnotation().getType() |
|
||||
at.nestedName() = name and at.getPackage().getName() = package
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an annotation that applies to this 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() { result.getAnnotatedElement() = this }
|
||||
Annotation getAnAnnotation() {
|
||||
// This predicate is overridden by Class to consider inherited annotations
|
||||
result = this.getADeclaredAnnotation()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 }
|
||||
|
||||
/** Gets an _indirect_ (= repeated) annotation. */
|
||||
private Annotation getAnIndirectAnnotation() {
|
||||
// 'indirect' as defined by https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/AnnotatedElement.html
|
||||
exists(AnnotationType t, Annotation containerAnn |
|
||||
t = result.getType() and
|
||||
containerAnn = this.getADeclaredAnnotation() and
|
||||
containerAnn.getType() = t.getContainingAnnotationType()
|
||||
|
|
||||
result = containerAnn.getAnArrayValue("value")
|
||||
)
|
||||
}
|
||||
|
||||
private Annotation getADeclaredAssociatedAnnotation(AnnotationType t) {
|
||||
// Direct or indirect annotation
|
||||
result.getType() = t and
|
||||
result = [this.getADeclaredAnnotation(), this.getAnIndirectAnnotation()]
|
||||
}
|
||||
|
||||
private Annotation getAnAssociatedAnnotation(AnnotationType t) {
|
||||
// 'associated' as defined by https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/AnnotatedElement.html
|
||||
if exists(this.getADeclaredAssociatedAnnotation(t))
|
||||
then result = this.getADeclaredAssociatedAnnotation(t)
|
||||
else (
|
||||
// Only if neither a direct nor an indirect annotation is present look for an inherited one
|
||||
t.isInherited() and
|
||||
// @Inherited only works for classes; cast to Annotatable is necessary because predicate is private
|
||||
result = this.(Class).getASupertype().(Class).(Annotatable).getAnAssociatedAnnotation(t)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an annotation _associated_ with this element, that is:
|
||||
* - An annotation directly present on this element, or
|
||||
* - 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(_) }
|
||||
|
||||
/**
|
||||
* Holds if this or any enclosing `Annotatable` has a `@SuppressWarnings("<category>")`
|
||||
@@ -128,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)
|
||||
}
|
||||
}
|
||||
@@ -146,10 +373,79 @@ class AnnotationType extends Interface {
|
||||
|
||||
/** Holds if this annotation type is annotated with the meta-annotation `@Inherited`. */
|
||||
predicate isInherited() {
|
||||
exists(Annotation ann |
|
||||
ann.getAnnotatedElement() = this and
|
||||
ann.getType().hasQualifiedName("java.lang.annotation", "Inherited")
|
||||
)
|
||||
this.getADeclaredAnnotation().getType().hasQualifiedName("java.lang.annotation", "Inherited")
|
||||
}
|
||||
|
||||
/** Holds if this annotation type is annotated with the meta-annotation `@Documented`. */
|
||||
predicate isDocumented() {
|
||||
this.getADeclaredAnnotation().getType().hasQualifiedName("java.lang.annotation", "Documented")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the retention policy of this annotation type, that is, the name of one of the
|
||||
* enum constants of `java.lang.annotation.RetentionPolicy`. If this annotation type
|
||||
* has no `@Retention` annotation, the result is `CLASS`.
|
||||
*/
|
||||
string getRetentionPolicy() {
|
||||
if this.getADeclaredAnnotation() instanceof RetentionAnnotation
|
||||
then result = this.getADeclaredAnnotation().(RetentionAnnotation).getRetentionPolicy()
|
||||
else
|
||||
// If not explicitly specified retention is CLASS
|
||||
result = "CLASS"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the element type is a possible target for this annotation type.
|
||||
* The `elementType` is the name of one of the `java.lang.annotation.ElementType`
|
||||
* enum constants.
|
||||
*
|
||||
* If this annotation type has no `@Target` annotation, it is considered to be applicable
|
||||
* in all declaration contexts. This matches the behavior of the latest Java versions
|
||||
* but differs from the behavior of older Java versions. This predicate must only be
|
||||
* called with names of `ElementType` enum constants; for other values it might hold
|
||||
* erroneously.
|
||||
*/
|
||||
bindingset[elementType]
|
||||
predicate isATargetType(string elementType) {
|
||||
/*
|
||||
* Note: Cannot use a predicate with string as result because annotation type without
|
||||
* explicit @Target can be applied in all declaration contexts, requiring to hardcode
|
||||
* element types here; then the results could become outdated if this predicate is not
|
||||
* updated for future JDK versions, or it could have irritating results, e.g. RECORD_COMPONENT
|
||||
* for a database created for Java 8.
|
||||
*
|
||||
* Could in theory read java.lang.annotation.ElementType constants from database, but might
|
||||
* be brittle in case ElementType is not present in the database for whatever reason.
|
||||
*/
|
||||
|
||||
if this.getADeclaredAnnotation() instanceof TargetAnnotation
|
||||
then elementType = this.getADeclaredAnnotation().(TargetAnnotation).getATargetElementType()
|
||||
else
|
||||
/*
|
||||
* Behavior for missing @Target annotation changed between Java versions. In older Java
|
||||
* versions it allowed usage in most (but not all) declaration contexts. Then for Java 14
|
||||
* JDK-8231435 changed it to allow usage in all declaration and type contexts. In Java 17
|
||||
* it was changed by JDK-8261610 to only allow usage in all declaration contexts, but not
|
||||
* in type contexts anymore. However, during these changes javac did not always comply with
|
||||
* the specification, see for example JDK-8254023.
|
||||
*
|
||||
* For simplicity pretend the latest behavior defined by the JLS applied in all versions;
|
||||
* that means any declaration context is allowed, but type contexts (represented by TYPE_USE,
|
||||
* see JLS 17 section 9.6.4.1) are not allowed.
|
||||
*/
|
||||
|
||||
elementType != "TYPE_USE"
|
||||
}
|
||||
|
||||
/** Holds if this annotation type is annotated with the meta-annotation `@Repeatable`. */
|
||||
predicate isRepeatable() { this.getADeclaredAnnotation() instanceof RepeatableAnnotation }
|
||||
|
||||
/**
|
||||
* If this annotation type is annotated with the meta-annotation `@Repeatable`,
|
||||
* gets the annotation type which acts as _containing annotation type_.
|
||||
*/
|
||||
AnnotationType getContainingAnnotationType() {
|
||||
result = this.getADeclaredAnnotation().(RepeatableAnnotation).getContainingType()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,8 @@ predicate depends(RefType t, RefType dep) {
|
||||
a.getAnnotatedElement().(Member).getDeclaringType() = t
|
||||
|
|
||||
usesType(a.getType(), dep) or
|
||||
usesType(a.getAValue().getType(), dep)
|
||||
usesType(a.getValue(_).getType(), dep) or
|
||||
usesType(a.getAnArrayValue(_).getType(), dep)
|
||||
)
|
||||
or
|
||||
// the type accessed in an `instanceof` expression in `t`.
|
||||
|
||||
@@ -90,7 +90,7 @@ predicate numDepends(RefType t, RefType dep, int value) {
|
||||
|
|
||||
elem = a and usesType(a.getType(), dep)
|
||||
or
|
||||
elem = a.getAValue() and
|
||||
elem = [a.getValue(_), a.getAnArrayValue(_)] and
|
||||
elem.getFile().getExtension() = "java" and
|
||||
usesType(elem.(Expr).getType(), dep)
|
||||
)
|
||||
|
||||
@@ -18,14 +18,16 @@ class OverrideAnnotation extends Annotation {
|
||||
class SuppressWarningsAnnotation extends Annotation {
|
||||
SuppressWarningsAnnotation() { this.getType().hasQualifiedName("java.lang", "SuppressWarnings") }
|
||||
|
||||
/** Gets the `StringLiteral` of a warning suppressed by this annotation. */
|
||||
StringLiteral getASuppressedWarningLiteral() {
|
||||
result = this.getAValue() or
|
||||
result = this.getAValue().(ArrayInit).getAnInit()
|
||||
}
|
||||
/**
|
||||
* DEPRECATED: This predicate restricts the results to `StringLiteral`; prefer `getASuppressedWarning()`
|
||||
* to get the name of a suppressed warning.
|
||||
*
|
||||
* Gets the `StringLiteral` of a warning suppressed by this annotation.
|
||||
*/
|
||||
deprecated StringLiteral getASuppressedWarningLiteral() { result = this.getAnArrayValue("value") }
|
||||
|
||||
/** Gets the name of a warning suppressed by this annotation. */
|
||||
string getASuppressedWarning() { result = this.getASuppressedWarningLiteral().getValue() }
|
||||
string getASuppressedWarning() { result = this.getAStringArrayValue("value") }
|
||||
}
|
||||
|
||||
/** A `@Target` annotation. */
|
||||
@@ -33,18 +35,15 @@ class TargetAnnotation extends Annotation {
|
||||
TargetAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Target") }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Getting the field access expression is rarely useful. Use `getATargetElementType()`
|
||||
* to get the name of the target element.
|
||||
*
|
||||
* Gets a target expression within this annotation.
|
||||
*
|
||||
* For example, the field access `ElementType.FIELD` is a target expression in
|
||||
* `@Target({ElementType.FIELD, ElementType.METHOD})`.
|
||||
*/
|
||||
Expr getATargetExpression() {
|
||||
not result instanceof ArrayInit and
|
||||
(
|
||||
result = this.getAValue() or
|
||||
result = this.getAValue().(ArrayInit).getAnInit()
|
||||
)
|
||||
}
|
||||
deprecated Expr getATargetExpression() { result = this.getAnArrayValue("value") }
|
||||
|
||||
/**
|
||||
* Gets the name of a target element type.
|
||||
@@ -52,14 +51,7 @@ class TargetAnnotation extends Annotation {
|
||||
* For example, `METHOD` is the name of a target element type in
|
||||
* `@Target({ElementType.FIELD, ElementType.METHOD})`.
|
||||
*/
|
||||
string getATargetElementType() {
|
||||
exists(EnumConstant ec |
|
||||
ec = this.getATargetExpression().(VarAccess).getVariable() and
|
||||
ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "ElementType")
|
||||
|
|
||||
result = ec.getName()
|
||||
)
|
||||
}
|
||||
string getATargetElementType() { result = this.getAnEnumConstantArrayValue("value").getName() }
|
||||
}
|
||||
|
||||
/** A `@Retention` annotation. */
|
||||
@@ -67,12 +59,15 @@ class RetentionAnnotation extends Annotation {
|
||||
RetentionAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Retention") }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Getting the field access expression is rarely useful. Use `getRetentionPolicy()`
|
||||
* to get the name of the retention policy.
|
||||
*
|
||||
* Gets the retention policy expression within this annotation.
|
||||
*
|
||||
* For example, the field access `RetentionPolicy.RUNTIME` is the
|
||||
* retention policy expression in `@Retention(RetentionPolicy.RUNTIME)`.
|
||||
*/
|
||||
Expr getRetentionPolicyExpression() { result = this.getValue("value") }
|
||||
deprecated Expr getRetentionPolicyExpression() { result = this.getValue("value") }
|
||||
|
||||
/**
|
||||
* Gets the name of the retention policy of this annotation.
|
||||
@@ -80,14 +75,18 @@ class RetentionAnnotation extends Annotation {
|
||||
* For example, `RUNTIME` is the name of the retention policy
|
||||
* in `@Retention(RetentionPolicy.RUNTIME)`.
|
||||
*/
|
||||
string getRetentionPolicy() {
|
||||
exists(EnumConstant ec |
|
||||
ec = this.getRetentionPolicyExpression().(VarAccess).getVariable() and
|
||||
ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "RetentionPolicy")
|
||||
|
|
||||
result = ec.getName()
|
||||
)
|
||||
}
|
||||
string getRetentionPolicy() { result = this.getEnumConstantValue("value").getName() }
|
||||
}
|
||||
|
||||
/** A `@Repeatable` annotation. */
|
||||
class RepeatableAnnotation extends Annotation {
|
||||
RepeatableAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Repeatable") }
|
||||
|
||||
/**
|
||||
* Gets the annotation type which acts as _containing type_, grouping multiple
|
||||
* repeatable annotations together.
|
||||
*/
|
||||
AnnotationType getContainingType() { result = this.getTypeValue("value") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,11 +118,7 @@ abstract class NonReflectiveAnnotation extends Annotation { }
|
||||
|
||||
library class StandardNonReflectiveAnnotation extends NonReflectiveAnnotation {
|
||||
StandardNonReflectiveAnnotation() {
|
||||
exists(AnnotationType anntp | anntp = this.getType() |
|
||||
anntp.hasQualifiedName("java.lang", "Override") or
|
||||
anntp.hasQualifiedName("java.lang", "Deprecated") or
|
||||
anntp.hasQualifiedName("java.lang", "SuppressWarnings") or
|
||||
anntp.hasQualifiedName("java.lang", "SafeVarargs")
|
||||
)
|
||||
this.getType()
|
||||
.hasQualifiedName("java.lang", ["Override", "Deprecated", "SuppressWarnings", "SafeVarargs"])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ private newtype TPrintAstNode =
|
||||
shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent
|
||||
} or
|
||||
TAnnotationsNode(Annotatable ann) {
|
||||
shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann)
|
||||
shouldPrint(ann, _) and ann.hasDeclaredAnnotation() and not partOfAnnotation(ann)
|
||||
} or
|
||||
TParametersNode(Callable c) { shouldPrint(c, _) and not c.hasNoParameters() } or
|
||||
TBaseTypesNode(ClassOrInterface ty) { shouldPrint(ty, _) } or
|
||||
|
||||
@@ -161,15 +161,13 @@ class TestNGTestMethod extends Method {
|
||||
exists(TestNGTestAnnotation testAnnotation |
|
||||
testAnnotation = this.getAnAnnotation() and
|
||||
// The data provider must have the same name as the referenced data provider
|
||||
result.getDataProviderName() =
|
||||
testAnnotation.getValue("dataProvider").(StringLiteral).getValue()
|
||||
result.getDataProviderName() = testAnnotation.getStringValue("dataProvider")
|
||||
|
|
||||
// Either the data provider should be on the current class, or a supertype
|
||||
this.getDeclaringType().getAnAncestor() = result.getDeclaringType()
|
||||
or
|
||||
// Or the data provider class should be declared
|
||||
result.getDeclaringType() =
|
||||
testAnnotation.getValue("dataProviderClass").(TypeLiteral).getReferencedType()
|
||||
result.getDeclaringType() = testAnnotation.getTypeValue("dataProviderClass")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -227,9 +225,7 @@ class TestNGListenersAnnotation extends TestNGAnnotation {
|
||||
/**
|
||||
* Gets a listener defined in this annotation.
|
||||
*/
|
||||
TestNGListenerImpl getAListener() {
|
||||
result = this.getAValue("value").(TypeLiteral).getReferencedType()
|
||||
}
|
||||
TestNGListenerImpl getAListener() { result = this.getATypeArrayValue("value") }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,7 +60,7 @@ class JaxbType extends Class {
|
||||
this.getAnAnnotation() = a and
|
||||
a.getType().(JaxbAnnotationType).hasName("XmlAccessorType")
|
||||
|
|
||||
result.getAnAccess() = a.getValue("value")
|
||||
result = a.getEnumConstantValue("value")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -64,5 +64,5 @@ class RunWithAnnotation extends Annotation {
|
||||
/**
|
||||
* Gets the runner that will be used.
|
||||
*/
|
||||
Type getRunner() { result = this.getValue("value").(TypeLiteral).getReferencedType() }
|
||||
Type getRunner() { result = this.getTypeValue("value") }
|
||||
}
|
||||
|
||||
@@ -296,11 +296,7 @@ class JaxRSProducesAnnotation extends JaxRSAnnotation {
|
||||
/**
|
||||
* Gets a declared content type that can be produced by this resource.
|
||||
*/
|
||||
Expr getADeclaredContentTypeExpr() {
|
||||
result = this.getAValue() and not result instanceof ArrayInit
|
||||
or
|
||||
result = this.getAValue().(ArrayInit).getAnInit()
|
||||
}
|
||||
Expr getADeclaredContentTypeExpr() { result = this.getAnArrayValue("value") }
|
||||
}
|
||||
|
||||
/** An `@Consumes` annotation that describes content types can be consumed by this resource. */
|
||||
|
||||
@@ -85,9 +85,7 @@ class IbatisSqlOperationAnnotation extends Annotation {
|
||||
/**
|
||||
* Gets this annotation's SQL statement string.
|
||||
*/
|
||||
string getSqlValue() {
|
||||
result = this.getAValue("value").(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
string getSqlValue() { result = this.getAStringArrayValue("value") }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,12 +33,12 @@ class PersistentEntity extends RefType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the access type for this entity as defined by a `@javax.persistence.Access` annotation, if any.
|
||||
* Gets the access type for this entity as defined by a `@javax.persistence.Access` annotation,
|
||||
* if any, in lower case.
|
||||
*/
|
||||
string getAccessTypeFromAnnotation() {
|
||||
exists(AccessAnnotation accessType | accessType = this.getAnAnnotation() |
|
||||
result =
|
||||
accessType.getValue("value").(FieldRead).getField().(EnumConstant).getName().toLowerCase()
|
||||
result = accessType.getEnumConstantValue("value").getName().toLowerCase()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,9 +311,7 @@ class SpringQualifierDefinitionAnnotation extends Annotation {
|
||||
/**
|
||||
* Gets the value of the qualifier field for this qualifier.
|
||||
*/
|
||||
string getQualifierValue() {
|
||||
result = this.getValue("value").(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
string getQualifierValue() { result = this.getStringValue("value") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,9 +323,7 @@ class SpringQualifierAnnotation extends Annotation {
|
||||
/**
|
||||
* Gets the value of the qualifier field for this qualifier.
|
||||
*/
|
||||
string getQualifierValue() {
|
||||
result = this.getValue("value").(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
string getQualifierValue() { result = this.getStringValue("value") }
|
||||
|
||||
/**
|
||||
* Gets the bean definition in an XML file that this qualifier resolves to, if any.
|
||||
@@ -350,9 +346,7 @@ class SpringResourceAnnotation extends Annotation {
|
||||
/**
|
||||
* Gets the specified name value, if any.
|
||||
*/
|
||||
string getNameValue() {
|
||||
result = this.getValue("name").(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
string getNameValue() { result = this.getStringValue("name") }
|
||||
|
||||
/**
|
||||
* Gets the bean definition in an XML file that the resource resolves to, if any.
|
||||
|
||||
@@ -40,16 +40,10 @@ class SpringComponentScan extends Annotation {
|
||||
*/
|
||||
string getBasePackages() {
|
||||
// "value" and "basePackages" are synonymous, and are simple strings
|
||||
result = this.getAValue("basePackages").(StringLiteral).getValue()
|
||||
result = this.getAStringArrayValue(["basePackages", "value"])
|
||||
or
|
||||
result = this.getAValue("value").(StringLiteral).getValue()
|
||||
or
|
||||
exists(TypeLiteral typeLiteral |
|
||||
// Base package classes are type literals whose package should be considered a base package.
|
||||
typeLiteral = this.getAValue("basePackageClasses")
|
||||
|
|
||||
result = typeLiteral.getReferencedType().(RefType).getPackage().getName()
|
||||
)
|
||||
// Base package classes are type literals whose package should be considered a base package.
|
||||
result = this.getATypeArrayValue("basePackageClasses").(RefType).getPackage().getName()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,8 +138,7 @@ class SpringComponent extends RefType {
|
||||
if exists(this.getComponentAnnotation().getValue("value"))
|
||||
then
|
||||
// If the name has been specified in the component annotation, use that.
|
||||
result =
|
||||
this.getComponentAnnotation().getValue("value").(CompileTimeConstantExpr).getStringValue()
|
||||
result = this.getComponentAnnotation().getStringValue("value")
|
||||
else
|
||||
// Otherwise use the name of the class, with the initial letter lower cased.
|
||||
exists(string name | name = this.getName() |
|
||||
@@ -204,7 +197,7 @@ class SpringComponent extends RefType {
|
||||
.getType()
|
||||
.hasQualifiedName("org.springframework.context.annotation", "Profile")
|
||||
|
|
||||
result = profileAnnotation.getAValue("value").(StringLiteral).getValue()
|
||||
result = profileAnnotation.getAStringArrayValue("value")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,9 +154,7 @@ class SpringRequestMappingMethod extends SpringControllerMethod {
|
||||
}
|
||||
|
||||
/** Gets the "value" @RequestMapping annotation value, if present. */
|
||||
string getValue() {
|
||||
result = requestMappingAnnotation.getValue("value").(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
string getValue() { result = requestMappingAnnotation.getStringValue("value") }
|
||||
|
||||
/** Holds if this is considered an `@ResponseBody` method. */
|
||||
predicate isResponseBody() {
|
||||
|
||||
@@ -34,5 +34,5 @@ class StrutsActionsAnnotation extends StrutsAnnotation {
|
||||
/**
|
||||
* Gets an Action annotation contained in this Actions annotation.
|
||||
*/
|
||||
StrutsActionAnnotation getAnAction() { result = this.getAValue("value") }
|
||||
StrutsActionAnnotation getAnAction() { result = this.getAnArrayValue("value") }
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class SuppressionAnnotation extends SuppressWarningsAnnotation {
|
||||
string text;
|
||||
|
||||
SuppressionAnnotation() {
|
||||
text = this.getASuppressedWarningLiteral().getValue() and
|
||||
text = this.getASuppressedWarning() and
|
||||
exists(getAnnotationText(text))
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,5 @@ where
|
||||
m.getNumberOfParameters() = 1 and
|
||||
c.getArgument(0).getType() = p and
|
||||
p.getATypeArgument() = t and
|
||||
not exists(RetentionAnnotation a |
|
||||
t.getAnAnnotation() = a and
|
||||
a.getAValue().(VarAccess).getVariable().hasName("RUNTIME")
|
||||
)
|
||||
t.getRetentionPolicy() != "RUNTIME"
|
||||
select c, "Call to isAnnotationPresent where no annotation has the RUNTIME retention policy."
|
||||
|
||||
@@ -47,8 +47,8 @@ class SpringControllerRequestMappingGetMethod extends SpringControllerGetMethod
|
||||
.getType()
|
||||
.hasQualifiedName("org.springframework.web.bind.annotation", "RequestMapping") and
|
||||
(
|
||||
this.getAnAnnotation().getValue("method").(VarAccess).getVariable().getName() = "GET" or
|
||||
this.getAnAnnotation().getValue("method").(ArrayInit).getSize() = 0 //Java code example: @RequestMapping(value = "test")
|
||||
this.getAnAnnotation().getAnEnumConstantArrayValue("method").getName() = "GET" or
|
||||
not exists(this.getAnAnnotation().getAnArrayValue("method")) //Java code example: @RequestMapping(value = "test")
|
||||
) and
|
||||
not this.getAParamType().getName() = "MultipartFile"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ from Field f, Annotation ann, Expr value, Expr valueChild
|
||||
where
|
||||
f.getDeclaringType().fromSource() and
|
||||
ann = f.getAnAnnotation() and
|
||||
value = ann.getAValue() and
|
||||
value = ann.getValue(_) and
|
||||
valueChild.getParent() = value
|
||||
select f, ann, value, valueChild
|
||||
|
||||
101
java/ql/test/library-tests/annotations/Annotatable.expected
Normal file
101
java/ql/test/library-tests/annotations/Annotatable.expected
Normal 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 |
|
||||
192
java/ql/test/library-tests/annotations/Annotatable.java
Normal file
192
java/ql/test/library-tests/annotations/Annotatable.java
Normal 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 {}
|
||||
}
|
||||
34
java/ql/test/library-tests/annotations/Annotatable.ql
Normal file
34
java/ql/test/library-tests/annotations/Annotatable.ql
Normal 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()
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
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 | {...} |
|
||||
| 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:105:28:105:54 | CustomAnnotation | value | AnnotationValues.java:105:46:105:53 | "single" |
|
||||
| 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:105:28:105:54 | 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 | CustomAnnotation |
|
||||
| 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 |
|
||||
37
java/ql/test/library-tests/annotations/Annotation-values.ql
Normal file
37
java/ql/test/library-tests/annotations/Annotation-values.ql
Normal 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) }
|
||||
@@ -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 |
|
||||
54
java/ql/test/library-tests/annotations/AnnotationType.java
Normal file
54
java/ql/test/library-tests/annotations/AnnotationType.java
Normal 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 {}
|
||||
}
|
||||
46
java/ql/test/library-tests/annotations/AnnotationType.ql
Normal file
46
java/ql/test/library-tests/annotations/AnnotationType.ql
Normal 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()
|
||||
}
|
||||
124
java/ql/test/library-tests/annotations/AnnotationValues.java
Normal file
124
java/ql/test/library-tests/annotations/AnnotationValues.java
Normal 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;
|
||||
}
|
||||
1
java/ql/test/library-tests/annotations/options
Normal file
1
java/ql/test/library-tests/annotations/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -source 16 -target 16
|
||||
Reference in New Issue
Block a user