mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
Merge pull request #4339 from joefarebrother/printAST-java-var-decls
Java: Add synthetic nodes for `LocalVariableDeclExpr`s in the AST view
This commit is contained in:
@@ -113,6 +113,10 @@ private predicate locationSortKeys(Element ast, string file, int line, int colum
|
||||
*/
|
||||
private newtype TPrintAstNode =
|
||||
TElementNode(Element el) { shouldPrint(el, _) } or
|
||||
TForInitNode(ForStmt fs) { shouldPrint(fs, _) and exists(fs.getAnInit()) } or
|
||||
TLocalVarDeclNode(LocalVariableDeclExpr lvde) {
|
||||
shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent
|
||||
} or
|
||||
TAnnotationsNode(Annotatable ann) {
|
||||
shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann)
|
||||
} or
|
||||
@@ -221,6 +225,24 @@ abstract class ElementNode extends PrintAstNode, TElementNode {
|
||||
final Element getElement() { result = element }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing an `Expr` or a `Stmt`.
|
||||
*/
|
||||
class ExprStmtNode extends ElementNode {
|
||||
ExprStmtNode() { element instanceof ExprOrStmt }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(Element el | result.(ElementNode).getElement() = el |
|
||||
el.(Expr).isNthChildOf(element, childIndex)
|
||||
or
|
||||
el.(Stmt).isNthChildOf(element, childIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given expression is part of an annotation.
|
||||
*/
|
||||
private predicate partOfAnnotation(Expr e) {
|
||||
e instanceof Annotation
|
||||
or
|
||||
@@ -228,49 +250,123 @@ private predicate partOfAnnotation(Expr e) {
|
||||
partOfAnnotation(e.getParent())
|
||||
}
|
||||
|
||||
private Expr getAnAnnotationChild(Expr e) {
|
||||
partOfAnnotation(e) and
|
||||
(
|
||||
result = e.(Annotation).getValue(_)
|
||||
/**
|
||||
* A node representing an `Expr` that is part of an annotation.
|
||||
*/
|
||||
final class AnnotationPartNode extends ExprStmtNode {
|
||||
AnnotationPartNode() { partOfAnnotation(element) }
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
result.getElement() =
|
||||
rank[childIndex](Element ch, string file, int line, int column |
|
||||
ch = getAnAnnotationChild() and locationSortKeys(ch, file, line, column)
|
||||
|
|
||||
ch order by file, line, column
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getAnAnnotationChild() {
|
||||
result = element.(Annotation).getValue(_)
|
||||
or
|
||||
result = e.(ArrayInit).getAnInit()
|
||||
result = element.(ArrayInit).getAnInit()
|
||||
or
|
||||
result = e.(ArrayInit).(Annotatable).getAnAnnotation()
|
||||
)
|
||||
result = element.(ArrayInit).(Annotatable).getAnAnnotation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An node representing an `Expr` or a `Stmt`.
|
||||
* A node representing a `LocalVariableDeclExpr`.
|
||||
*/
|
||||
final class ExprStmtNode extends ElementNode {
|
||||
ExprStmtNode() { element instanceof ExprOrStmt }
|
||||
final class LocalVarDeclExprNode extends ExprStmtNode {
|
||||
LocalVarDeclExprNode() { element instanceof LocalVariableDeclExpr }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(Element el | result.(ElementNode).getElement() = el |
|
||||
el.(Expr).isNthChildOf(element, childIndex) and
|
||||
not partOfAnnotation(element)
|
||||
or
|
||||
el.(Stmt).isNthChildOf(element, childIndex)
|
||||
or
|
||||
childIndex = -4 and
|
||||
el = element.(ClassInstanceExpr).getAnonymousClass()
|
||||
or
|
||||
childIndex = 0 and
|
||||
el = element.(LocalClassDeclStmt).getLocalClass()
|
||||
or
|
||||
partOfAnnotation(element) and
|
||||
el =
|
||||
rank[childIndex](Element ch, string file, int line, int column |
|
||||
ch = getAnAnnotationChild(element) and locationSortKeys(ch, file, line, column)
|
||||
|
|
||||
ch order by file, line, column
|
||||
)
|
||||
)
|
||||
result = super.getChild(childIndex)
|
||||
or
|
||||
exists(Element el | result.(AnnotationsNode).getAnnotated() = el |
|
||||
childIndex = -2 and
|
||||
el = element.(LocalVariableDeclExpr).getVariable()
|
||||
)
|
||||
childIndex = -2 and
|
||||
result.(AnnotationsNode).getAnnotated() = element.(LocalVariableDeclExpr).getVariable()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `ClassInstanceExpr`.
|
||||
*/
|
||||
final class ClassInstanceExprNode extends ExprStmtNode {
|
||||
ClassInstanceExprNode() { element instanceof ClassInstanceExpr }
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
result = super.getChild(childIndex)
|
||||
or
|
||||
childIndex = -4 and
|
||||
result.getElement() = element.(ClassInstanceExpr).getAnonymousClass()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `LocalClassDeclStmt`.
|
||||
*/
|
||||
final class LocalClassDeclStmtNode extends ExprStmtNode {
|
||||
LocalClassDeclStmtNode() { element instanceof LocalClassDeclStmt }
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
result = super.getChild(childIndex)
|
||||
or
|
||||
childIndex = 0 and
|
||||
result.getElement() = element.(LocalClassDeclStmt).getLocalClass()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `ForStmt`.
|
||||
*/
|
||||
final class ForStmtNode extends ExprStmtNode {
|
||||
ForStmtNode() { element instanceof ForStmt }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
childIndex >= 1 and
|
||||
result = super.getChild(childIndex)
|
||||
or
|
||||
childIndex = 0 and
|
||||
result.(ForInitNode).getForStmt() = element
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An element that can be the parent of up to one `LocalVariableDeclExpr` for which we want
|
||||
* to use a synthetic node to hold the variable declaration and its `TypeAccess`.
|
||||
*/
|
||||
private class SingleLocalVarDeclParent extends ExprOrStmt {
|
||||
SingleLocalVarDeclParent() {
|
||||
this instanceof EnhancedForStmt or
|
||||
this instanceof CatchClause or
|
||||
this.(InstanceOfExpr).isPattern()
|
||||
}
|
||||
|
||||
/** Gets the variable declaration that this element contains */
|
||||
LocalVariableDeclExpr getVariable() { result.getParent() = this }
|
||||
|
||||
/** Gets the type access of the variable */
|
||||
Expr getTypeAccess() { result = getVariable().getTypeAccess() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing an element that can be the parent of up to one `LocalVariableDeclExpr` for which we
|
||||
* want to use a synthetic node to variable declaration and its type access.
|
||||
*
|
||||
* Excludes `LocalVariableDeclStmt` and `ForStmt`, as they can hold multiple declarations.
|
||||
* For these cases, either a synthetic node is not necassary or a different synthetic node is used.
|
||||
*/
|
||||
final class SingleLocalVarDeclParentNode extends ExprStmtNode {
|
||||
SingleLocalVarDeclParent lvdp;
|
||||
|
||||
SingleLocalVarDeclParentNode() { lvdp = element }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
result = super.getChild(childIndex) and
|
||||
not result.(ElementNode).getElement() = [lvdp.getVariable(), lvdp.getTypeAccess()]
|
||||
or
|
||||
childIndex = lvdp.getVariable().getIndex() and
|
||||
result.(LocalVarDeclSynthNode).getVariable() = lvdp.getVariable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +528,51 @@ final class TypeVariableNode extends ElementNode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing the initializers of a `ForStmt`.
|
||||
*/
|
||||
final class ForInitNode extends PrintAstNode, TForInitNode {
|
||||
ForStmt fs;
|
||||
|
||||
ForInitNode() { this = TForInitNode(fs) }
|
||||
|
||||
override string toString() { result = "(For Initializers) " }
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
childIndex >= 0 and
|
||||
result.getElement().(Expr).isNthChildOf(fs, -childIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying `ForStmt`.
|
||||
*/
|
||||
ForStmt getForStmt() { result = fs }
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthetic node holding a `LocalVariableDeclExpr` and its type access.
|
||||
*/
|
||||
final class LocalVarDeclSynthNode extends PrintAstNode, TLocalVarDeclNode {
|
||||
LocalVariableDeclExpr lvde;
|
||||
|
||||
LocalVarDeclSynthNode() { this = TLocalVarDeclNode(lvde) }
|
||||
|
||||
override string toString() { result = "(Single Local Variable Declaration)" }
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.getElement() = lvde.getTypeAccess()
|
||||
or
|
||||
childIndex = 1 and
|
||||
result.getElement() = lvde
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying `LocalVariableDeclExpr`
|
||||
*/
|
||||
LocalVariableDeclExpr getVariable() { result = lvde }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing the annotations of an `Annotatable`.
|
||||
* Only rendered if there is at least one annotation.
|
||||
|
||||
@@ -21,10 +21,11 @@ MultiCatch.java:
|
||||
# 14| 0: [ClassInstanceExpr] new SQLException(...)
|
||||
# 14| -3: [TypeAccess] SQLException
|
||||
# 15| 0: [CatchClause] stmt
|
||||
# 15| -1: [UnionTypeAccess] ...|...
|
||||
# 15| 0: [TypeAccess] IOException
|
||||
# 15| 1: [TypeAccess] SQLException
|
||||
# 15| 0: [LocalVariableDeclExpr] e
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 15| 0: [UnionTypeAccess] ...|...
|
||||
# 15| 0: [TypeAccess] IOException
|
||||
# 15| 1: [TypeAccess] SQLException
|
||||
# 15| 1: [LocalVariableDeclExpr] e
|
||||
# 16| 1: [BlockStmt] stmt
|
||||
# 17| 0: [ExprStmt] stmt
|
||||
# 17| 0: [MethodAccess] printStackTrace(...)
|
||||
@@ -55,10 +56,11 @@ MultiCatch.java:
|
||||
# 30| 0: [ClassInstanceExpr] new Exception(...)
|
||||
# 30| -3: [TypeAccess] Exception
|
||||
# 31| 0: [CatchClause] stmt
|
||||
# 31| -1: [UnionTypeAccess] ...|...
|
||||
# 31| 0: [TypeAccess] IOException
|
||||
# 31| 1: [TypeAccess] SQLException
|
||||
# 31| 0: [LocalVariableDeclExpr] e
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 31| 0: [UnionTypeAccess] ...|...
|
||||
# 31| 0: [TypeAccess] IOException
|
||||
# 31| 1: [TypeAccess] SQLException
|
||||
# 31| 1: [LocalVariableDeclExpr] e
|
||||
# 32| 1: [BlockStmt] stmt
|
||||
# 35| 4: [Method] ordinaryCatch
|
||||
# 35| 3: [TypeAccess] void
|
||||
@@ -69,6 +71,7 @@ MultiCatch.java:
|
||||
# 39| 0: [ClassInstanceExpr] new IOException(...)
|
||||
# 39| -3: [TypeAccess] IOException
|
||||
# 40| 0: [CatchClause] stmt
|
||||
# 40| -1: [TypeAccess] Exception
|
||||
# 40| 0: [LocalVariableDeclExpr] e
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 40| 0: [TypeAccess] Exception
|
||||
# 40| 1: [LocalVariableDeclExpr] e
|
||||
# 41| 1: [BlockStmt] stmt
|
||||
|
||||
@@ -18,6 +18,12 @@ class A {
|
||||
/** Does something */
|
||||
@Deprecated
|
||||
static int doSomething(@SuppressWarnings("all") String text) {
|
||||
int i=0, j=1;
|
||||
|
||||
for(i=0, j=1; i<3; i++) {}
|
||||
|
||||
for(int m=0, n=1; m<3; m++) {}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -34,4 +40,20 @@ class A {
|
||||
@Ann2(7)
|
||||
})
|
||||
String doSomethingElse() { return "c"; }
|
||||
|
||||
void varDecls(Object[] things) {
|
||||
try {
|
||||
for(Object thing : things) {
|
||||
if (thing instanceof Integer) {
|
||||
return;
|
||||
}
|
||||
if (thing instanceof String s) {
|
||||
throw new RuntimeException(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RuntimeException rte) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,26 +31,97 @@ A.java:
|
||||
# 20| 1: [StringLiteral] "all"
|
||||
# 20| 0: [TypeAccess] String
|
||||
# 20| 5: [BlockStmt] stmt
|
||||
# 21| 0: [ReturnStmt] stmt
|
||||
# 21| 0: [IntegerLiteral] 0
|
||||
# 24| 6: [FieldDeclaration] int counter, ...;
|
||||
# 24| -1: [TypeAccess] int
|
||||
# 24| 0: [IntegerLiteral] 1
|
||||
# 26| 7: [BlockStmt] stmt
|
||||
# 27| 0: [ExprStmt] stmt
|
||||
# 27| 0: [AssignExpr] ...=...
|
||||
# 27| 0: [VarAccess] counter
|
||||
# 27| 1: [MethodAccess] doSomething(...)
|
||||
# 27| 0: [StringLiteral] "hi"
|
||||
# 36| 8: [Method] doSomethingElse
|
||||
# 21| 0: [LocalVariableDeclStmt] stmt
|
||||
# 21| 0: [TypeAccess] int
|
||||
# 21| 1: [LocalVariableDeclExpr] i
|
||||
# 21| 0: [IntegerLiteral] 0
|
||||
# 21| 2: [LocalVariableDeclExpr] j
|
||||
# 21| 0: [IntegerLiteral] 1
|
||||
# 23| 1: [ForStmt] stmt
|
||||
#-----| 0: (For Initializers)
|
||||
# 23| 1: [AssignExpr] ...=...
|
||||
# 23| 0: [VarAccess] i
|
||||
# 23| 1: [IntegerLiteral] 0
|
||||
# 23| 2: [AssignExpr] ...=...
|
||||
# 23| 0: [VarAccess] j
|
||||
# 23| 1: [IntegerLiteral] 1
|
||||
# 23| 1: [LTExpr] ... < ...
|
||||
# 23| 0: [VarAccess] i
|
||||
# 23| 1: [IntegerLiteral] 3
|
||||
# 23| 2: [BlockStmt] stmt
|
||||
# 23| 3: [PostIncExpr] ...++
|
||||
# 23| 0: [VarAccess] i
|
||||
# 25| 2: [ForStmt] stmt
|
||||
#-----| 0: (For Initializers)
|
||||
# 25| 0: [TypeAccess] int
|
||||
# 25| 1: [LocalVariableDeclExpr] m
|
||||
# 25| 0: [IntegerLiteral] 0
|
||||
# 25| 2: [LocalVariableDeclExpr] n
|
||||
# 25| 0: [IntegerLiteral] 1
|
||||
# 25| 1: [LTExpr] ... < ...
|
||||
# 25| 0: [VarAccess] m
|
||||
# 25| 1: [IntegerLiteral] 3
|
||||
# 25| 2: [BlockStmt] stmt
|
||||
# 25| 3: [PostIncExpr] ...++
|
||||
# 25| 0: [VarAccess] m
|
||||
# 27| 3: [ReturnStmt] stmt
|
||||
# 27| 0: [IntegerLiteral] 0
|
||||
# 30| 6: [FieldDeclaration] int counter, ...;
|
||||
# 30| -1: [TypeAccess] int
|
||||
# 30| 0: [IntegerLiteral] 1
|
||||
# 32| 7: [BlockStmt] stmt
|
||||
# 33| 0: [ExprStmt] stmt
|
||||
# 33| 0: [AssignExpr] ...=...
|
||||
# 33| 0: [VarAccess] counter
|
||||
# 33| 1: [MethodAccess] doSomething(...)
|
||||
# 33| 0: [StringLiteral] "hi"
|
||||
# 42| 8: [Method] doSomethingElse
|
||||
#-----| 1: (Annotations)
|
||||
# 30| 1: [Annotation] Ann1
|
||||
# 31| 1: [StringLiteral] "a"
|
||||
# 32| 2: [ArrayInit] {...}
|
||||
# 33| 1: [Annotation] Ann2
|
||||
# 34| 2: [Annotation] Ann2
|
||||
# 34| 1: [IntegerLiteral] 7
|
||||
# 36| 3: [TypeAccess] String
|
||||
# 36| 5: [BlockStmt] stmt
|
||||
# 36| 0: [ReturnStmt] stmt
|
||||
# 36| 0: [StringLiteral] "c"
|
||||
# 36| 1: [Annotation] Ann1
|
||||
# 37| 1: [StringLiteral] "a"
|
||||
# 38| 2: [ArrayInit] {...}
|
||||
# 39| 1: [Annotation] Ann2
|
||||
# 40| 2: [Annotation] Ann2
|
||||
# 40| 1: [IntegerLiteral] 7
|
||||
# 42| 3: [TypeAccess] String
|
||||
# 42| 5: [BlockStmt] stmt
|
||||
# 42| 0: [ReturnStmt] stmt
|
||||
# 42| 0: [StringLiteral] "c"
|
||||
# 44| 9: [Method] varDecls
|
||||
# 44| 3: [TypeAccess] void
|
||||
#-----| 4: (Parameters)
|
||||
# 44| 0: [Parameter] things
|
||||
# 44| 0: [ArrayTypeAccess] ...[]
|
||||
# 44| 0: [TypeAccess] Object
|
||||
# 44| 5: [BlockStmt] stmt
|
||||
# 45| 0: [TryStmt] stmt
|
||||
# 45| -1: [BlockStmt] stmt
|
||||
# 46| 0: [EnhancedForStmt] stmt
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 46| 0: [TypeAccess] Object
|
||||
# 46| 1: [LocalVariableDeclExpr] thing
|
||||
# 46| 1: [VarAccess] things
|
||||
# 46| 2: [BlockStmt] stmt
|
||||
# 47| 0: [IfStmt] stmt
|
||||
# 47| 0: [InstanceOfExpr] ...instanceof...
|
||||
# 47| 0: [VarAccess] thing
|
||||
# 47| 1: [TypeAccess] Integer
|
||||
# 47| 1: [BlockStmt] stmt
|
||||
# 48| 0: [ReturnStmt] stmt
|
||||
# 50| 1: [IfStmt] stmt
|
||||
# 50| 0: [InstanceOfExpr] ...instanceof...
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 50| 0: [TypeAccess] String
|
||||
# 50| 1: [LocalVariableDeclExpr] s
|
||||
# 50| 0: [VarAccess] thing
|
||||
# 50| 1: [BlockStmt] stmt
|
||||
# 51| 0: [ThrowStmt] stmt
|
||||
# 51| 0: [ClassInstanceExpr] new RuntimeException(...)
|
||||
# 51| -3: [TypeAccess] RuntimeException
|
||||
# 51| 0: [VarAccess] s
|
||||
# 55| 0: [CatchClause] stmt
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 55| 0: [TypeAccess] RuntimeException
|
||||
# 55| 1: [LocalVariableDeclExpr] rte
|
||||
# 55| 1: [BlockStmt] stmt
|
||||
# 56| 0: [ReturnStmt] stmt
|
||||
|
||||
1
java/ql/test/library-tests/printAst/options
Normal file
1
java/ql/test/library-tests/printAst/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args --enable-preview -source 14 -target 14
|
||||
Reference in New Issue
Block a user