From f69b6eef7afc464dc1db4e1043bad2f73643d9cc Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 10 Jul 2021 22:52:54 +0200 Subject: [PATCH] Java: Clarify that `Annotatable` predicates consider inherited annotations Additionally changes `hasAnnotation()` to consider inherited annotations for consistency. --- java/ql/lib/semmle/code/java/Annotation.qll | 24 ++++++++++++++++----- java/ql/lib/semmle/code/java/PrintAst.qll | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll index 31773b44035..f4419406e45 100644 --- a/java/ql/lib/semmle/code/java/Annotation.qll +++ b/java/ql/lib/semmle/code/java/Annotation.qll @@ -166,19 +166,33 @@ 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. */ + predicate hasAnnotation() { exists(getAnAnnotation()) } - /** Holds if this element has the specified annotation. */ + /** Holds if this element has a declared annotation, excluding inherited annotations. */ + predicate hasDeclaredAnnotation() { exists(getADeclaredAnnotation()) } + + /** + * Holds if this element has the specified annotation, including inherited + * annotations. + */ 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. + */ + // This predicate is overridden by Class to consider inherited annotations cached - Annotation getAnAnnotation() { result.getAnnotatedElement() = this } + Annotation getAnAnnotation() { result = getADeclaredAnnotation() } + + /** + * Gets an annotation that is declared on this element, excluding inherited annotations. + */ + Annotation getADeclaredAnnotation() { result.getAnnotatedElement() = this } /** * Holds if this or any enclosing `Annotatable` has a `@SuppressWarnings("")` diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index 9d88550faa3..b2937d67940 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -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