From 45651cf1236a6aa2c4aeb723c7b49a664d63baa4 Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 23 Sep 2020 16:58:35 +0100 Subject: [PATCH 1/5] Java: PrintAst: Add a synthetic node for the initialisers of for statements --- java/ql/src/semmle/code/java/PrintAst.qll | 31 ++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index a3f4807661d..b26db2704ee 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -113,6 +113,7 @@ 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 TAnnotationsNode(Annotatable ann) { shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann) } or @@ -248,7 +249,11 @@ final class ExprStmtNode extends ElementNode { override PrintAstNode getChild(int childIndex) { exists(Element el | result.(ElementNode).getElement() = el | el.(Expr).isNthChildOf(element, childIndex) and - not partOfAnnotation(element) + not partOfAnnotation(element) and + not ( + element instanceof ForStmt and + childIndex <= 0 + ) or el.(Stmt).isNthChildOf(element, childIndex) or @@ -271,6 +276,9 @@ final class ExprStmtNode extends ElementNode { childIndex = -2 and el = element.(LocalVariableDeclExpr).getVariable() ) + or + childIndex = 0 and + result.(ForInitNode).getForStmt() = element } } @@ -432,6 +440,27 @@ 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 node representing the annotations of an `Annotatable`. * Only rendered if there is at least one annotation. From 1f9960762425b676b64a9a150ded4015a6ff9606 Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 23 Sep 2020 17:11:20 +0100 Subject: [PATCH 2/5] Java: PrintAst: Improve test --- java/ql/test/library-tests/printAst/A.java | 6 ++ .../library-tests/printAst/PrintAst.expected | 77 +++++++++++++------ 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/java/ql/test/library-tests/printAst/A.java b/java/ql/test/library-tests/printAst/A.java index b0eeb9276a1..c3176cc14f3 100644 --- a/java/ql/test/library-tests/printAst/A.java +++ b/java/ql/test/library-tests/printAst/A.java @@ -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; } diff --git a/java/ql/test/library-tests/printAst/PrintAst.expected b/java/ql/test/library-tests/printAst/PrintAst.expected index b23ed34ea82..c8f22de6950 100644 --- a/java/ql/test/library-tests/printAst/PrintAst.expected +++ b/java/ql/test/library-tests/printAst/PrintAst.expected @@ -31,26 +31,59 @@ 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" From 3e960c1e0bdac2062fbe047152acc9d73f75f30c Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 23 Sep 2020 17:53:30 +0100 Subject: [PATCH 3/5] Java: PrintAst: Refactor exceptions to the usual AST of expressions and statements using dispatch --- java/ql/src/semmle/code/java/PrintAst.qll | 132 +++++++++++++++------- 1 file changed, 90 insertions(+), 42 deletions(-) diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index b26db2704ee..08b108c8e47 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -222,6 +222,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 @@ -229,53 +247,83 @@ private predicate partOfAnnotation(Expr e) { partOfAnnotation(e.getParent()) } -private Expr getAnAnnotationChild(Expr e) { - partOfAnnotation(e) and - ( - result = e.(Annotation).getValue(_) - or - result = e.(ArrayInit).getAnInit() - or - result = e.(ArrayInit).(Annotatable).getAnAnnotation() - ) +/** + * 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 = element.(ArrayInit).getAnInit() + or + 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) and - not ( - element instanceof ForStmt and - childIndex <= 0 - ) - 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 @@ -448,7 +496,7 @@ final class ForInitNode extends PrintAstNode, TForInitNode { ForInitNode() { this = TForInitNode(fs) } - override string toString() { result = "(For Initializers) "} + override string toString() { result = "(For Initializers) " } override ElementNode getChild(int childIndex) { childIndex >= 0 and @@ -458,7 +506,7 @@ final class ForInitNode extends PrintAstNode, TForInitNode { /** * Gets the underlying `ForStmt`. */ - ForStmt getForStmt() {result = fs} + ForStmt getForStmt() { result = fs } } /** From 9c8a4682377ea2a65985552531754e27ebfda030 Mon Sep 17 00:00:00 2001 From: Joe Date: Thu, 24 Sep 2020 12:12:28 +0100 Subject: [PATCH 4/5] Java: PrintAst: Add synthetic nodes for other declarations --- java/ql/src/semmle/code/java/PrintAst.qll | 67 +++++++++++++++++++ .../java7/MultiCatch/PrintAst.expected | 23 ++++--- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index 08b108c8e47..ca1daf6c2a4 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -114,6 +114,9 @@ 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 LocalVarDeclParent + } or TAnnotationsNode(Annotatable ann) { shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann) } or @@ -330,6 +333,46 @@ final class ForStmtNode extends ExprStmtNode { } } +/** + * An element that can be the parent of a `LocalVariableDeclExpr` for which we want + * to use a synthetic node to hold the variable declaration and its `TypeAccess`. + */ +private class LocalVarDeclParent extends ExprOrStmt { + LocalVarDeclParent() { + 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 a `LocalVariableDeclExpr` for which we + * want to use a synthetic node to variable declaration and its type access. + * + * Excludes: + * - `LocalVariableDeclStmt` because a synthetic node isn't needed + * - `ForStmt` becasue a different synthetic node is already used + */ +final class LocalVarDeclParentNode extends ExprStmtNode { + LocalVarDeclParent lvdp; + + LocalVarDeclParentNode() { 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() + } +} + /** * A node representing a `Callable`, such as method declaration. */ @@ -509,6 +552,30 @@ final class ForInitNode extends PrintAstNode, TForInitNode { 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 = "(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. diff --git a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected index 8b8fe959628..98172ceff75 100644 --- a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected +++ b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected @@ -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: (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: (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: (Local Variable Declaration) +# 40| 0: [TypeAccess] Exception +# 40| 1: [LocalVariableDeclExpr] e # 41| 1: [BlockStmt] stmt From 5256c0ba39caba0b2939c5626e2edc3f7e9dc92b Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 25 Sep 2020 11:19:13 +0100 Subject: [PATCH 5/5] Java: Improve PrintAst tests and rename things Add tests for `EnhcancedForStmt`s and `InstanceOfExpr`s. Rename LocalVarDeclParent to SingleLocalVarDeclParent --- java/ql/src/semmle/code/java/PrintAst.qll | 35 ++++++++--------- .../java7/MultiCatch/PrintAst.expected | 6 +-- java/ql/test/library-tests/printAst/A.java | 16 ++++++++ .../library-tests/printAst/PrintAst.expected | 38 +++++++++++++++++++ java/ql/test/library-tests/printAst/options | 1 + 5 files changed, 74 insertions(+), 22 deletions(-) create mode 100644 java/ql/test/library-tests/printAst/options diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index ca1daf6c2a4..4e219603024 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -115,7 +115,7 @@ 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 LocalVarDeclParent + shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent } or TAnnotationsNode(Annotatable ann) { shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann) @@ -266,13 +266,11 @@ final class AnnotationPartNode extends ExprStmtNode { } private Expr getAnAnnotationChild() { - ( - result = element.(Annotation).getValue(_) - or - result = element.(ArrayInit).getAnInit() - or - result = element.(ArrayInit).(Annotatable).getAnAnnotation() - ) + result = element.(Annotation).getValue(_) + or + result = element.(ArrayInit).getAnInit() + or + result = element.(ArrayInit).(Annotatable).getAnAnnotation() } } @@ -334,11 +332,11 @@ final class ForStmtNode extends ExprStmtNode { } /** - * An element that can be the parent of a `LocalVariableDeclExpr` for which we want + * 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 LocalVarDeclParent extends ExprOrStmt { - LocalVarDeclParent() { +private class SingleLocalVarDeclParent extends ExprOrStmt { + SingleLocalVarDeclParent() { this instanceof EnhancedForStmt or this instanceof CatchClause or this.(InstanceOfExpr).isPattern() @@ -352,17 +350,16 @@ private class LocalVarDeclParent extends ExprOrStmt { } /** - * A node representing an element that can be the parent of a `LocalVariableDeclExpr` for which we + * 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` because a synthetic node isn't needed - * - `ForStmt` becasue a different synthetic node is already used + * 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 LocalVarDeclParentNode extends ExprStmtNode { - LocalVarDeclParent lvdp; +final class SingleLocalVarDeclParentNode extends ExprStmtNode { + SingleLocalVarDeclParent lvdp; - LocalVarDeclParentNode() { lvdp = element } + SingleLocalVarDeclParentNode() { lvdp = element } override PrintAstNode getChild(int childIndex) { result = super.getChild(childIndex) and @@ -560,7 +557,7 @@ final class LocalVarDeclSynthNode extends PrintAstNode, TLocalVarDeclNode { LocalVarDeclSynthNode() { this = TLocalVarDeclNode(lvde) } - override string toString() { result = "(Local Variable Declaration)" } + override string toString() { result = "(Single Local Variable Declaration)" } override ElementNode getChild(int childIndex) { childIndex = 0 and diff --git a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected index 98172ceff75..bba3b450e3e 100644 --- a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected +++ b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected @@ -21,7 +21,7 @@ MultiCatch.java: # 14| 0: [ClassInstanceExpr] new SQLException(...) # 14| -3: [TypeAccess] SQLException # 15| 0: [CatchClause] stmt -#-----| 0: (Local Variable Declaration) +#-----| 0: (Single Local Variable Declaration) # 15| 0: [UnionTypeAccess] ...|... # 15| 0: [TypeAccess] IOException # 15| 1: [TypeAccess] SQLException @@ -56,7 +56,7 @@ MultiCatch.java: # 30| 0: [ClassInstanceExpr] new Exception(...) # 30| -3: [TypeAccess] Exception # 31| 0: [CatchClause] stmt -#-----| 0: (Local Variable Declaration) +#-----| 0: (Single Local Variable Declaration) # 31| 0: [UnionTypeAccess] ...|... # 31| 0: [TypeAccess] IOException # 31| 1: [TypeAccess] SQLException @@ -71,7 +71,7 @@ MultiCatch.java: # 39| 0: [ClassInstanceExpr] new IOException(...) # 39| -3: [TypeAccess] IOException # 40| 0: [CatchClause] stmt -#-----| 0: (Local Variable Declaration) +#-----| 0: (Single Local Variable Declaration) # 40| 0: [TypeAccess] Exception # 40| 1: [LocalVariableDeclExpr] e # 41| 1: [BlockStmt] stmt diff --git a/java/ql/test/library-tests/printAst/A.java b/java/ql/test/library-tests/printAst/A.java index c3176cc14f3..38319c64706 100644 --- a/java/ql/test/library-tests/printAst/A.java +++ b/java/ql/test/library-tests/printAst/A.java @@ -40,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; + } + } } \ No newline at end of file diff --git a/java/ql/test/library-tests/printAst/PrintAst.expected b/java/ql/test/library-tests/printAst/PrintAst.expected index c8f22de6950..922acc4011a 100644 --- a/java/ql/test/library-tests/printAst/PrintAst.expected +++ b/java/ql/test/library-tests/printAst/PrintAst.expected @@ -87,3 +87,41 @@ A.java: # 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 diff --git a/java/ql/test/library-tests/printAst/options b/java/ql/test/library-tests/printAst/options new file mode 100644 index 00000000000..266b0eadc5e --- /dev/null +++ b/java/ql/test/library-tests/printAst/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args --enable-preview -source 14 -target 14