mirror of
https://github.com/github/codeql.git
synced 2026-05-05 13:45:19 +02:00
Merge pull request #16023 from smowton/smowton/feature/jdk22-support
Java: support Java 22 language features
This commit is contained in:
@@ -49,6 +49,15 @@ predicate gapInChildren(Element e, int i) {
|
||||
not e instanceof Annotation and
|
||||
// Pattern case statements legitimately have a TypeAccess (-2) and a pattern (0) but not a rule (-1)
|
||||
not (i = -1 and e instanceof PatternCase and not e.(PatternCase).isRule()) and
|
||||
// Pattern case statements can have a gap at -3 when they have more than one pattern but no guard.
|
||||
not (
|
||||
i = -3 and count(e.(PatternCase).getAPattern()) > 1 and not exists(e.(PatternCase).getGuard())
|
||||
) and
|
||||
// Pattern case statements may have some missing type accesses, depending on the nature of the direct child
|
||||
not (
|
||||
(i = -2 or i < -4) and
|
||||
e instanceof PatternCase
|
||||
) and
|
||||
// Instanceof with a record pattern is not expected to have a type access in position 1
|
||||
not (i = 1 and e.(InstanceOfExpr).getPattern() instanceof RecordPatternExpr) and
|
||||
// RecordPatternExpr extracts type-accesses only for its LocalVariableDeclExpr children
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The Java extractor and QL libraries now support Java 22, including support for anonymous variables, lambda parameters and patterns.
|
||||
* Pattern cases with multiple patterns and that fall through to or from other pattern cases are now supported. The `PatternCase` class gains the new `getPatternAtIndex` and `getAPattern` predicates, and deprecates `getPattern`.
|
||||
@@ -489,14 +489,14 @@ private module ControlFlowGraphImpl {
|
||||
private Stmt getSwitchStatement(SwitchBlock switch, int i) { result.isNthChildOf(switch, i) }
|
||||
|
||||
/**
|
||||
* Holds if `last` is the last node in a pattern case `pc`'s succeeding bind-and-test operation,
|
||||
* Holds if `last` is the last node in any of pattern case `pc`'s succeeding bind-and-test operations,
|
||||
* immediately before either falling through to execute successor statements or execute a rule body
|
||||
* if present. `completion` is the completion kind of the last operation.
|
||||
*/
|
||||
private predicate lastPatternCaseMatchingOp(
|
||||
PatternCase pc, ControlFlowNode last, Completion completion
|
||||
) {
|
||||
last(pc.getPattern(), last, completion) and
|
||||
last(pc.getAPattern(), last, completion) and
|
||||
completion = NormalCompletion() and
|
||||
not exists(pc.getGuard())
|
||||
or
|
||||
@@ -776,6 +776,18 @@ private module ControlFlowGraphImpl {
|
||||
last(try.getFinally(), last, NormalCompletion())
|
||||
}
|
||||
|
||||
private predicate isNextNormalSwitchStmt(SwitchBlock switch, Stmt pred, Stmt succ) {
|
||||
exists(int i, Stmt immediateSucc |
|
||||
getSwitchStatement(switch, i) = pred and
|
||||
getSwitchStatement(switch, i + 1) = immediateSucc and
|
||||
(
|
||||
if immediateSucc instanceof PatternCase
|
||||
then isNextNormalSwitchStmt(switch, immediateSucc, succ)
|
||||
else succ = immediateSucc
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind `last` to a cfg node nested inside `n` (or, indeed, `n` itself) such
|
||||
* that `last` may be the last node during an execution of `n` and finish
|
||||
@@ -927,9 +939,15 @@ private module ControlFlowGraphImpl {
|
||||
completion != anonymousBreakCompletion() and
|
||||
not completion instanceof NormalOrBooleanCompletion
|
||||
or
|
||||
// if the last case completes normally, then so does the switch
|
||||
last(switch.getStmt(strictcount(switch.getAStmt()) - 1), last, NormalCompletion()) and
|
||||
completion = NormalCompletion()
|
||||
// if a statement without a non-pattern-case successor completes normally (or for a pattern case
|
||||
// the guard succeeds) then the switch completes normally.
|
||||
exists(Stmt lastNormalStmt, Completion stmtCompletion |
|
||||
lastNormalStmt = getSwitchStatement(switch, _) and
|
||||
not isNextNormalSwitchStmt(switch, lastNormalStmt, _) and
|
||||
last(lastNormalStmt, last, stmtCompletion) and
|
||||
(stmtCompletion = NormalCompletion() or stmtCompletion = BooleanCompletion(true, _)) and
|
||||
completion = NormalCompletion()
|
||||
)
|
||||
or
|
||||
// if no default case exists, then normal completion of the expression may terminate the switch
|
||||
// Note this can't happen if there are pattern cases or a null literal, as
|
||||
@@ -973,9 +991,9 @@ private module ControlFlowGraphImpl {
|
||||
)
|
||||
or
|
||||
// A pattern case statement can complete:
|
||||
// * On failure of its type test (boolean false)
|
||||
// * On failure of its final type test (boolean false)
|
||||
// * On failure of its guard test if any (boolean false)
|
||||
// * On completion of its variable declarations, if it is not a rule and has no guard (normal completion)
|
||||
// * On completion of one of its pattern variable declarations, if it is not a rule and has no guard (normal completion)
|
||||
// * On success of its guard test, if it is not a rule (boolean true)
|
||||
// (the latter two cases are accounted for by lastPatternCaseMatchingOp)
|
||||
exists(PatternCase pc | n = pc |
|
||||
@@ -1315,9 +1333,13 @@ private module ControlFlowGraphImpl {
|
||||
// Note this includes non-rule case statements and the successful pattern match successor
|
||||
// of a non-rule pattern case statement. Rule case statements do not complete normally
|
||||
// (they always break or yield).
|
||||
exists(int i |
|
||||
last(getSwitchStatement(switch, i), n, completion) and
|
||||
result = first(getSwitchStatement(switch, i + 1)) and
|
||||
// Exception: falling through into a pattern case statement (which necessarily does not
|
||||
// declare any named variables) must skip one or more such statements, otherwise we would
|
||||
// incorrectly apply their type test and/or guard.
|
||||
exists(Stmt pred, Stmt succ |
|
||||
isNextNormalSwitchStmt(switch, pred, succ) and
|
||||
last(pred, n, completion) and
|
||||
result = first(succ) and
|
||||
(completion = NormalCompletion() or completion = BooleanCompletion(true, _))
|
||||
)
|
||||
or
|
||||
@@ -1328,16 +1350,19 @@ private module ControlFlowGraphImpl {
|
||||
)
|
||||
or
|
||||
// Pattern cases have internal edges:
|
||||
// * Type test success -true-> variable declarations
|
||||
// * Type test success -true-> one of the possible sets of variable declarations
|
||||
// n.b. for unnamed patterns (e.g. case A _, B _) this means that *one* of the
|
||||
// type tests has succeeded. There aren't enough nodes in the AST to describe
|
||||
// a sequential test in detail, so CFG consumers have to watch out for this case.
|
||||
// * Variable declarations -normal-> guard evaluation
|
||||
// * Variable declarations -normal-> rule execution (when there is no guard)
|
||||
// * Guard success -true-> rule execution
|
||||
exists(PatternCase pc |
|
||||
n = pc and
|
||||
completion = basicBooleanCompletion(true) and
|
||||
result = first(pc.getPattern())
|
||||
result = first(pc.getAPattern())
|
||||
or
|
||||
last(pc.getPattern(), n, completion) and
|
||||
last(pc.getAPattern(), n, completion) and
|
||||
completion = NormalCompletion() and
|
||||
result = first(pc.getGuard())
|
||||
or
|
||||
|
||||
@@ -84,7 +84,7 @@ predicate depends(RefType t, RefType dep) {
|
||||
or
|
||||
// A type accessed in a pattern-switch case statement in `t`.
|
||||
exists(PatternCase pc | t = pc.getEnclosingCallable().getDeclaringType() |
|
||||
usesType(pc.getPattern().getAChildExpr*().getType(), dep)
|
||||
usesType(pc.getAPattern().getAChildExpr*().getType(), dep)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ predicate numDepends(RefType t, RefType dep, int value) {
|
||||
or
|
||||
// the type accessed in a pattern-switch case statement in `t`.
|
||||
exists(PatternCase pc | elem = pc and t = pc.getEnclosingCallable().getDeclaringType() |
|
||||
usesType(pc.getPattern().getAChildExpr*().getType(), dep)
|
||||
usesType(pc.getAPattern().getAChildExpr*().getType(), dep)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1590,7 +1590,9 @@ class InstanceOfExpr extends Expr, @instanceofexpr {
|
||||
* Note that this won't get anything when record pattern matching is used-- for more general patterns,
|
||||
* use `getPattern`.
|
||||
*/
|
||||
LocalVariableDeclExpr getLocalVariableDeclExpr() { result = this.getPattern().asBindingPattern() }
|
||||
LocalVariableDeclExpr getLocalVariableDeclExpr() {
|
||||
result = this.getPattern().asBindingOrUnnamedPattern()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the access to the type on the right-hand side of the `instanceof` operator.
|
||||
@@ -1681,7 +1683,10 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
|
||||
or
|
||||
exists(InstanceOfExpr ioe | this.getParent() = ioe | result.isNthChildOf(ioe, 1))
|
||||
or
|
||||
exists(PatternCase pc | this.getParent() = pc | result.isNthChildOf(pc, -2))
|
||||
exists(PatternCase pc, int index, int typeAccessIdx | this.isNthChildOf(pc, index) |
|
||||
(if index = 0 then typeAccessIdx = -2 else typeAccessIdx = (-3 - index)) and
|
||||
result.isNthChildOf(pc, typeAccessIdx)
|
||||
)
|
||||
or
|
||||
exists(RecordPatternExpr rpe, int index |
|
||||
this.isNthChildOf(rpe, index) and result.isNthChildOf(rpe, -(index + 1))
|
||||
@@ -1691,6 +1696,9 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
|
||||
/** Gets the name of the variable declared by this local variable declaration expression. */
|
||||
string getName() { result = this.getVariable().getName() }
|
||||
|
||||
/** Holds if this is an anonymous local variable, `_` */
|
||||
predicate isAnonymous() { this.getName() = "" }
|
||||
|
||||
/**
|
||||
* Gets the switch statement or expression whose pattern declares this identifier, if any.
|
||||
*/
|
||||
@@ -1700,7 +1708,7 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
|
||||
or
|
||||
pc = result.(SwitchExpr).getAPatternCase()
|
||||
|
|
||||
this = pc.getPattern().getAChildExpr*()
|
||||
this = pc.getAPattern().getAChildExpr*()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1739,17 +1747,17 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
|
||||
or
|
||||
exists(SwitchStmt switch |
|
||||
result = switch.getExpr() and
|
||||
this = switch.getAPatternCase().getPattern().asBindingPattern()
|
||||
this = switch.getAPatternCase().getAPattern().asBindingOrUnnamedPattern()
|
||||
)
|
||||
or
|
||||
exists(SwitchExpr switch |
|
||||
result = switch.getExpr() and
|
||||
this = switch.getAPatternCase().getPattern().asBindingPattern()
|
||||
this = switch.getAPatternCase().getAPattern().asBindingOrUnnamedPattern()
|
||||
)
|
||||
or
|
||||
exists(InstanceOfExpr ioe |
|
||||
result = ioe.getExpr() and
|
||||
this = ioe.getPattern().asBindingPattern()
|
||||
this = ioe.getPattern().asBindingOrUnnamedPattern()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1763,7 +1771,9 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this expression. */
|
||||
override string toString() { result = this.getName() }
|
||||
override string toString() {
|
||||
if this.getName() = "" then result = "<anonymous local variable>" else result = this.getName()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalVariableDeclExpr" }
|
||||
}
|
||||
@@ -2671,9 +2681,9 @@ class NotNullExpr extends UnaryExpr, @notnullexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A binding or record pattern.
|
||||
* A binding, unnamed or record pattern.
|
||||
*
|
||||
* Note binding patterns are represented as `LocalVariableDeclExpr`s.
|
||||
* Note binding and unnamed patterns are represented as `LocalVariableDeclExpr`s.
|
||||
*/
|
||||
class PatternExpr extends Expr {
|
||||
PatternExpr() {
|
||||
@@ -2686,9 +2696,14 @@ class PatternExpr extends Expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this pattern cast to a binding pattern.
|
||||
* Gets this pattern cast to a binding or unnamed pattern.
|
||||
*/
|
||||
LocalVariableDeclExpr asBindingPattern() { result = this }
|
||||
LocalVariableDeclExpr asBindingOrUnnamedPattern() { result = this }
|
||||
|
||||
/**
|
||||
* DEPRECATED: alias for `asBindingOrUnnamedPattern`.
|
||||
*/
|
||||
deprecated LocalVariableDeclExpr asBindingPattern() { result = this.asBindingOrUnnamedPattern() }
|
||||
|
||||
/**
|
||||
* Gets this pattern cast to a record pattern.
|
||||
@@ -2724,4 +2739,14 @@ class RecordPatternExpr extends Expr, @recordpatternexpr {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this record pattern declares any identifiers (i.e., at least one leaf declaration is named).
|
||||
*/
|
||||
predicate declaresAnyIdentifiers() {
|
||||
exists(PatternExpr subPattern | subPattern = this.getSubPattern(_) |
|
||||
subPattern.asRecordPattern().declaresAnyIdentifiers() or
|
||||
not subPattern.asBindingOrUnnamedPattern().isAnonymous()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ private class PpInstanceOfExpr extends PpAst, InstanceOfExpr {
|
||||
i = 3 and result = " " and this.getPattern() instanceof LocalVariableDeclExpr
|
||||
or
|
||||
i = 4 and
|
||||
result = this.getPattern().asBindingPattern().getName()
|
||||
result = this.getPattern().asBindingOrUnnamedPattern().getName()
|
||||
}
|
||||
|
||||
override PpAst getChild(int i) {
|
||||
@@ -400,7 +400,8 @@ private class PpInstanceOfExpr extends PpAst, InstanceOfExpr {
|
||||
|
||||
private class PpLocalVariableDeclExpr extends PpAst, LocalVariableDeclExpr {
|
||||
override string getPart(int i) {
|
||||
i = 0 and result = this.getName()
|
||||
i = 0 and
|
||||
(if this.isAnonymous() then result = "_" else result = this.getName())
|
||||
or
|
||||
i = 1 and result = " = " and exists(this.getInit())
|
||||
}
|
||||
@@ -782,28 +783,54 @@ private class PpSwitchCase extends PpAst, SwitchCase {
|
||||
}
|
||||
|
||||
private class PpPatternCase extends PpAst, PatternCase {
|
||||
private predicate isAnonymousPattern(int n) {
|
||||
this.getPattern(n).asBindingOrUnnamedPattern().isAnonymous()
|
||||
}
|
||||
|
||||
override string getPart(int i) {
|
||||
i = 0 and result = "case "
|
||||
exists(int n, int base | exists(this.getPattern(n)) and base = n * 4 |
|
||||
i = base and
|
||||
(if n = 0 then result = "case " else result = ", ")
|
||||
or
|
||||
i = base + 2 and
|
||||
this.getPattern(n) instanceof LocalVariableDeclExpr and
|
||||
(
|
||||
exists(this.getPattern(n).asBindingOrUnnamedPattern().getTypeAccess())
|
||||
or
|
||||
not this.isAnonymousPattern(n)
|
||||
) and
|
||||
result = " "
|
||||
or
|
||||
i = base + 3 and
|
||||
(
|
||||
if this.isAnonymousPattern(n)
|
||||
then result = "_"
|
||||
else result = this.getPattern(n).asBindingOrUnnamedPattern().getName()
|
||||
)
|
||||
)
|
||||
or
|
||||
i = 2 and this.getPattern() instanceof LocalVariableDeclExpr and result = " "
|
||||
or
|
||||
i = 3 and result = this.getPattern().asBindingPattern().getName()
|
||||
or
|
||||
i = 4 and result = ":" and not this.isRule()
|
||||
or
|
||||
i = 4 and result = " -> " and this.isRule()
|
||||
or
|
||||
i = 6 and result = ";" and exists(this.getRuleExpression())
|
||||
exists(int base | base = (max(int n | exists(this.getPattern(n))) + 1) * 4 |
|
||||
i = base and result = ":" and not this.isRule()
|
||||
or
|
||||
i = base and result = " -> " and this.isRule()
|
||||
or
|
||||
i = base + 2 and result = ";" and exists(this.getRuleExpression())
|
||||
)
|
||||
}
|
||||
|
||||
override PpAst getChild(int i) {
|
||||
i = 1 and result = this.getPattern().asBindingPattern().getTypeAccess()
|
||||
exists(int n, int base | exists(this.getPattern(n)) and base = n * 4 |
|
||||
i = base + 1 and
|
||||
result = this.getPattern(n).asBindingOrUnnamedPattern().getTypeAccess()
|
||||
or
|
||||
i = base + 1 and result = this.getPattern(n).asRecordPattern()
|
||||
)
|
||||
or
|
||||
i = 1 and result = this.getPattern().asRecordPattern()
|
||||
or
|
||||
i = 5 and result = this.getRuleExpression()
|
||||
or
|
||||
i = 5 and result = this.getRuleStatement()
|
||||
exists(int base | base = (max(int n | exists(this.getPattern(n))) + 1) * 4 |
|
||||
i = base + 1 and result = this.getRuleExpression()
|
||||
or
|
||||
i = base + 1 and result = this.getRuleStatement()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,11 @@ 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
|
||||
shouldPrint(lvde, _) and
|
||||
(
|
||||
lvde.getParent() instanceof SingleLocalVarDeclParent or
|
||||
lvde.getParent() instanceof PatternCase
|
||||
)
|
||||
} or
|
||||
TAnnotationsNode(Annotatable ann) {
|
||||
shouldPrint(ann, _) and
|
||||
@@ -415,6 +419,23 @@ final class ForStmtNode extends ExprStmtNode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `PatternCase`.
|
||||
*/
|
||||
final class PatternCaseNode extends ExprStmtNode {
|
||||
PatternCase pc;
|
||||
|
||||
PatternCaseNode() { pc = element }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
result = super.getChild(childIndex) and
|
||||
not result.(ElementNode).getElement() instanceof LocalVariableDeclExpr and
|
||||
not result.(ElementNode).getElement() instanceof TypeAccess
|
||||
or
|
||||
result = TLocalVarDeclNode(pc.getPattern(childIndex))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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`.
|
||||
@@ -423,8 +444,7 @@ private class SingleLocalVarDeclParent extends ExprOrStmt {
|
||||
SingleLocalVarDeclParent() {
|
||||
this instanceof EnhancedForStmt or
|
||||
this instanceof CatchClause or
|
||||
this.(InstanceOfExpr).isPattern() or
|
||||
this instanceof PatternCase
|
||||
this.(InstanceOfExpr).isPattern()
|
||||
}
|
||||
|
||||
/** Gets the variable declaration that this element contains */
|
||||
@@ -439,7 +459,7 @@ private class SingleLocalVarDeclParent extends ExprOrStmt {
|
||||
* 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.
|
||||
* For these cases, either a synthetic node is not necessary or a different synthetic node is used.
|
||||
*/
|
||||
final class SingleLocalVarDeclParentNode extends ExprStmtNode {
|
||||
SingleLocalVarDeclParent lvdp;
|
||||
@@ -643,7 +663,11 @@ final class LocalVarDeclSynthNode extends PrintAstNode, TLocalVarDeclNode {
|
||||
|
||||
LocalVarDeclSynthNode() { this = TLocalVarDeclNode(lvde) }
|
||||
|
||||
override string toString() { result = "(Single Local Variable Declaration)" }
|
||||
override string toString() {
|
||||
if lvde.getParent() instanceof PatternCase
|
||||
then result = "(Pattern case declaration)"
|
||||
else result = "(Single Local Variable Declaration)"
|
||||
}
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
childIndex = 0 and
|
||||
|
||||
@@ -539,12 +539,27 @@ class ConstCase extends SwitchCase {
|
||||
|
||||
/** A pattern case of a `switch` statement */
|
||||
class PatternCase extends SwitchCase {
|
||||
PatternExpr pattern;
|
||||
PatternCase() { exists(PatternExpr pe | pe.isNthChildOf(this, _)) }
|
||||
|
||||
PatternCase() { pattern.isNthChildOf(this, 0) }
|
||||
/**
|
||||
* DEPRECATED: alias for getPattern(0)
|
||||
*/
|
||||
deprecated PatternExpr getPattern() { result = this.getPattern(0) }
|
||||
|
||||
/** Gets this case's pattern. */
|
||||
PatternExpr getPattern() { result = pattern }
|
||||
/**
|
||||
* Gets this case's `n`th pattern.
|
||||
*/
|
||||
PatternExpr getPattern(int n) { result.isNthChildOf(this, n) }
|
||||
|
||||
/**
|
||||
* Gets any of this case's patterns.
|
||||
*/
|
||||
PatternExpr getAPattern() { result = this.getPattern(_) }
|
||||
|
||||
/**
|
||||
* Gets this case's sole pattern, if there is exactly one.
|
||||
*/
|
||||
PatternExpr getUniquePattern() { result = unique(PatternExpr pe | pe = this.getAPattern()) }
|
||||
|
||||
/** Gets the guard applicable to this pattern case, if any. */
|
||||
Expr getGuard() { result.isNthChildOf(this, -3) }
|
||||
|
||||
@@ -58,7 +58,13 @@ class LocalVariableDecl extends @localvar, LocalScopeVariable {
|
||||
/** Gets the callable in which this declaration occurs. */
|
||||
Callable getEnclosingCallable() { result = this.getCallable() }
|
||||
|
||||
override string toString() { result = this.getType().getName() + " " + this.getName() }
|
||||
override string toString() {
|
||||
exists(string sourceName |
|
||||
if this.getName() = "" then sourceName = "_" else sourceName = this.getName()
|
||||
|
|
||||
result = this.getType().getName() + " " + sourceName
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the initializer expression of this local variable declaration. */
|
||||
override Expr getInitializer() { result = this.getDeclExpr().getInit() }
|
||||
@@ -117,4 +123,11 @@ class Parameter extends Element, @param, LocalScopeVariable {
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Parameter" }
|
||||
|
||||
override string toString() {
|
||||
if this.getName() = "" then result = "<anonymous parameter>" else result = super.toString()
|
||||
}
|
||||
|
||||
/** Holds if this is an anonymous parameter, `_` */
|
||||
predicate isAnonymous() { this.getName() = "" }
|
||||
}
|
||||
|
||||
@@ -115,8 +115,24 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
|
||||
(
|
||||
pred.(Expr).getParent*() = sc.getSelectorExpr()
|
||||
or
|
||||
pred.(Expr).getParent*() = getClosestPrecedingPatternCase(sc).getGuard()
|
||||
// Ambiguous: in the case of `case String _ when x: case "SomeConstant":`, the guard `x`
|
||||
// passing edge will fall through into the constant case, and the guard failing edge
|
||||
// will test if the selector equals `"SomeConstant"` and if so branch to the same
|
||||
// case statement. Therefore don't label this a non-fall-through predecessor.
|
||||
exists(PatternCase previousPatternCase |
|
||||
previousPatternCase = getClosestPrecedingPatternCase(sc)
|
||||
|
|
||||
pred.(Expr).getParent*() = previousPatternCase.getGuard() and
|
||||
// Check there is any statement in between the previous pattern case and this one,
|
||||
// or the case is a rule, so there is no chance of a fall-through.
|
||||
(
|
||||
previousPatternCase.isRule() or
|
||||
not previousPatternCase.getIndex() = sc.getIndex() - 1
|
||||
)
|
||||
)
|
||||
or
|
||||
// Unambigious: on the test-passing edge there must be at least one intervening
|
||||
// declaration node, including anonymous `_` declarations.
|
||||
pred = getClosestPrecedingPatternCase(sc)
|
||||
)
|
||||
}
|
||||
@@ -201,13 +217,13 @@ class Guard extends ExprParent {
|
||||
or
|
||||
exists(PatternCase pc | this = pc |
|
||||
pc.getSelectorExpr() = testedExpr and
|
||||
testedType = pc.getPattern().getType()
|
||||
testedType = pc.getUniquePattern().getType()
|
||||
)
|
||||
) and
|
||||
(
|
||||
if
|
||||
exists(RecordPatternExpr rpe |
|
||||
rpe = [this.(InstanceOfExpr).getPattern(), this.(PatternCase).getPattern()]
|
||||
rpe = [this.(InstanceOfExpr).getPattern(), this.(PatternCase).getAPattern()]
|
||||
|
|
||||
not rpe.isUnrestricted()
|
||||
)
|
||||
|
||||
@@ -194,12 +194,17 @@ predicate simpleAstFlowStep(Expr e1, Expr e2) {
|
||||
// In the following three cases only record patterns need this flow edge, leading from the bound instanceof
|
||||
// or switch tested expression to a record pattern that will read its fields. Simple binding patterns are
|
||||
// handled via VariableAssign.getSource instead.
|
||||
exists(SwitchExpr se |
|
||||
e1 = se.getExpr() and e2 = se.getACase().(PatternCase).getPattern().asRecordPattern()
|
||||
// We only consider patterns that declare any identifiers
|
||||
exists(SwitchExpr se, RecordPatternExpr recordPattern | recordPattern = e2 |
|
||||
e1 = se.getExpr() and
|
||||
recordPattern = se.getACase().(PatternCase).getAPattern() and
|
||||
recordPattern.declaresAnyIdentifiers()
|
||||
)
|
||||
or
|
||||
exists(SwitchStmt ss |
|
||||
e1 = ss.getExpr() and e2 = ss.getACase().(PatternCase).getPattern().asRecordPattern()
|
||||
exists(SwitchStmt ss, RecordPatternExpr recordPattern | recordPattern = e2 |
|
||||
e1 = ss.getExpr() and
|
||||
recordPattern = ss.getACase().(PatternCase).getAPattern() and
|
||||
recordPattern.declaresAnyIdentifiers()
|
||||
)
|
||||
or
|
||||
exists(InstanceOfExpr ioe | e1 = ioe.getExpr() and e2 = ioe.getPattern().asRecordPattern())
|
||||
|
||||
@@ -63,7 +63,7 @@ dependency/A.java:
|
||||
# 31| 1: [SwitchStmt] switch (...)
|
||||
# 31| -1: [VarAccess] o
|
||||
# 32| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 32| 0: [TypeAccess] Used2
|
||||
# 32| 1: [LocalVariableDeclExpr] u2
|
||||
# 32| 1: [BreakStmt] break
|
||||
@@ -74,7 +74,7 @@ dependency/A.java:
|
||||
# 35| 0: [SwitchExpr] switch (...)
|
||||
# 35| -1: [VarAccess] o
|
||||
# 36| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 36| 0: [TypeAccess] Used3
|
||||
# 36| 1: [LocalVariableDeclExpr] u3
|
||||
# 36| 1: [YieldStmt] yield ...
|
||||
|
||||
@@ -52,9 +52,9 @@ Test.java:
|
||||
# 17| 0: [VarAccess] len
|
||||
# 17| 1: [IntegerLiteral] 4
|
||||
# 17| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 17| 0: [TypeAccess] String
|
||||
# 17| 1: [LocalVariableDeclExpr] s2
|
||||
# 17| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 18| 1: [ConstCase] case ...
|
||||
# 18| -1: [BlockStmt] { ... }
|
||||
# 18| 0: [StringLiteral] "e"
|
||||
@@ -74,7 +74,7 @@ Test.java:
|
||||
# 23| 0: [VarAccess] len
|
||||
# 23| 1: [IntegerLiteral] 4
|
||||
# 23| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 23| 0: [TypeAccess] String
|
||||
# 23| 1: [LocalVariableDeclExpr] s2
|
||||
# 24| 2: [ConstCase] case ...
|
||||
@@ -82,3 +82,23 @@ Test.java:
|
||||
# 24| 0: [StringLiteral] "g"
|
||||
# 25| 3: [DefaultCase] default
|
||||
# 25| -1: [BlockStmt] { ... }
|
||||
# 27| 5: [SwitchStmt] switch (...)
|
||||
# 27| -1: [VarAccess] s
|
||||
# 28| 0: [ConstCase] case ...
|
||||
# 28| 0: [StringLiteral] "h"
|
||||
# 29| 1: [PatternCase] case <Pattern>
|
||||
# 29| -3: [EQExpr] ... == ...
|
||||
# 29| 0: [VarAccess] len
|
||||
# 29| 1: [IntegerLiteral] 4
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 29| 0: [TypeAccess] String
|
||||
# 29| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 30| 2: [ConstCase] case ...
|
||||
# 30| 0: [StringLiteral] "i"
|
||||
# 31| 3: [LocalVariableDeclStmt] var ...;
|
||||
# 31| 0: [TypeAccess] String
|
||||
# 31| 1: [LocalVariableDeclExpr] target
|
||||
# 31| 0: [StringLiteral] "Shouldn't be controlled by any of those tests"
|
||||
# 32| 4: [BreakStmt] break
|
||||
# 33| 5: [DefaultCase] default
|
||||
# 34| 6: [BreakStmt] break
|
||||
|
||||
@@ -14,7 +14,7 @@ class Test {
|
||||
}
|
||||
int len = s.length();
|
||||
switch (s) {
|
||||
case String s2 when len == 4 -> { }
|
||||
case String _ when len == 4 -> { }
|
||||
case "e" -> { }
|
||||
default -> { }
|
||||
}
|
||||
@@ -24,5 +24,14 @@ class Test {
|
||||
case "g" -> { }
|
||||
default -> { }
|
||||
}
|
||||
switch (s) {
|
||||
case "h":
|
||||
case String _ when len == 4:
|
||||
case "i":
|
||||
String target = "Shouldn't be controlled by any of those tests";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
hasBranchEdge
|
||||
| Test.java:4:7:4:22 | case ... | Test.java:2:39:27:3 | { ... } | Test.java:4:7:4:22 | case ... | true |
|
||||
| Test.java:5:7:5:17 | case ... | Test.java:2:39:27:3 | { ... } | Test.java:5:7:5:17 | case ... | true |
|
||||
| Test.java:6:7:6:17 | case ... | Test.java:2:39:27:3 | { ... } | Test.java:6:7:6:17 | case ... | true |
|
||||
| Test.java:7:7:7:16 | default | Test.java:2:39:27:3 | { ... } | Test.java:7:7:7:16 | default | true |
|
||||
| Test.java:4:7:4:22 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:4:7:4:22 | case ... | true |
|
||||
| Test.java:5:7:5:17 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:5:7:5:17 | case ... | true |
|
||||
| Test.java:6:7:6:17 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:6:7:6:17 | case ... | true |
|
||||
| Test.java:7:7:7:16 | default | Test.java:2:39:36:3 | { ... } | Test.java:7:7:7:16 | default | true |
|
||||
| Test.java:10:7:10:22 | case ... | Test.java:3:9:3:21 | x | Test.java:10:7:10:22 | case ... | true |
|
||||
| Test.java:11:7:11:17 | case ... | Test.java:3:9:3:21 | x | Test.java:11:7:11:17 | case ... | true |
|
||||
| Test.java:12:7:12:17 | case ... | Test.java:3:9:3:21 | x | Test.java:12:7:12:17 | case ... | true |
|
||||
| Test.java:13:7:13:16 | default | Test.java:3:9:3:21 | x | Test.java:13:7:13:16 | default | true |
|
||||
| Test.java:17:7:17:37 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:17:19:17:20 | s2 | true |
|
||||
| Test.java:17:7:17:37 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | false |
|
||||
| Test.java:17:7:17:37 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | false |
|
||||
| Test.java:17:27:17:34 | ... == ... | Test.java:17:19:17:20 | s2 | Test.java:17:39:17:41 | { ... } | true |
|
||||
| Test.java:17:27:17:34 | ... == ... | Test.java:17:19:17:20 | s2 | Test.java:18:7:18:17 | case ... | false |
|
||||
| Test.java:17:27:17:34 | ... == ... | Test.java:17:19:17:20 | s2 | Test.java:19:7:19:16 | default | false |
|
||||
| Test.java:17:7:17:36 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:17:19:17:19 | <anonymous local variable> | true |
|
||||
| Test.java:17:7:17:36 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | false |
|
||||
| Test.java:17:7:17:36 | case <Pattern> | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | false |
|
||||
| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:17:38:17:40 | { ... } | true |
|
||||
| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:18:7:18:17 | case ... | false |
|
||||
| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:19:7:19:16 | default | false |
|
||||
| Test.java:18:7:18:17 | case ... | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | true |
|
||||
| Test.java:18:7:18:17 | case ... | Test.java:17:19:17:20 | s2 | Test.java:18:7:18:17 | case ... | true |
|
||||
| Test.java:18:7:18:17 | case ... | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:18:7:18:17 | case ... | true |
|
||||
| Test.java:19:7:19:16 | default | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | true |
|
||||
| Test.java:19:7:19:16 | default | Test.java:17:19:17:20 | s2 | Test.java:19:7:19:16 | default | true |
|
||||
| Test.java:19:7:19:16 | default | Test.java:17:19:17:19 | <anonymous local variable> | Test.java:19:7:19:16 | default | true |
|
||||
| Test.java:21:13:21:19 | unknown | Test.java:21:5:21:42 | switch (...) | Test.java:21:23:21:23 | s | true |
|
||||
| Test.java:21:13:21:19 | unknown | Test.java:21:5:21:42 | switch (...) | Test.java:21:27:21:27 | s | false |
|
||||
| Test.java:22:7:22:17 | case ... | Test.java:21:23:21:23 | s | Test.java:22:7:22:17 | case ... | true |
|
||||
@@ -31,6 +31,16 @@ hasBranchEdge
|
||||
| Test.java:24:7:24:17 | case ... | Test.java:23:19:23:20 | s2 | Test.java:24:7:24:17 | case ... | true |
|
||||
| Test.java:25:7:25:16 | default | Test.java:23:7:23:37 | case <Pattern> | Test.java:25:7:25:16 | default | true |
|
||||
| Test.java:25:7:25:16 | default | Test.java:23:19:23:20 | s2 | Test.java:25:7:25:16 | default | true |
|
||||
| Test.java:28:7:28:15 | case ... | Test.java:27:5:27:14 | switch (...) | Test.java:28:7:28:15 | case ... | true |
|
||||
| Test.java:29:7:29:34 | case <Pattern> | Test.java:29:7:29:34 | case <Pattern> | Test.java:29:19:29:19 | <anonymous local variable> | true |
|
||||
| Test.java:29:7:29:34 | case <Pattern> | Test.java:29:7:29:34 | case <Pattern> | Test.java:30:7:30:15 | case ... | false |
|
||||
| Test.java:29:7:29:34 | case <Pattern> | Test.java:29:7:29:34 | case <Pattern> | Test.java:33:7:33:14 | default | false |
|
||||
| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:30:7:30:15 | case ... | false |
|
||||
| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:30:7:30:15 | case ... | true |
|
||||
| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:33:7:33:14 | default | false |
|
||||
| Test.java:30:7:30:15 | case ... | Test.java:29:7:29:34 | case <Pattern> | Test.java:30:7:30:15 | case ... | true |
|
||||
| Test.java:33:7:33:14 | default | Test.java:29:7:29:34 | case <Pattern> | Test.java:33:7:33:14 | default | true |
|
||||
| Test.java:33:7:33:14 | default | Test.java:29:19:29:19 | <anonymous local variable> | Test.java:33:7:33:14 | default | true |
|
||||
#select
|
||||
| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | false | Test.java:7:7:7:16 | default |
|
||||
| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | true | Test.java:5:7:5:17 | case ... |
|
||||
@@ -40,7 +50,7 @@ hasBranchEdge
|
||||
| Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | true | Test.java:11:7:11:17 | case ... |
|
||||
| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | false | Test.java:13:7:13:16 | default |
|
||||
| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | true | Test.java:12:7:12:17 | case ... |
|
||||
| Test.java:17:27:17:34 | ... == ... | Test.java:17:27:17:29 | len | Test.java:17:34:17:34 | 4 | true | true | Test.java:17:39:17:41 | { ... } |
|
||||
| Test.java:17:26:17:33 | ... == ... | Test.java:17:26:17:28 | len | Test.java:17:33:17:33 | 4 | true | true | Test.java:17:38:17:40 | { ... } |
|
||||
| Test.java:18:7:18:17 | case ... | Test.java:16:13:16:13 | s | Test.java:18:12:18:14 | "e" | true | false | Test.java:19:7:19:16 | default |
|
||||
| Test.java:18:7:18:17 | case ... | Test.java:16:13:16:13 | s | Test.java:18:12:18:14 | "e" | true | true | Test.java:18:7:18:17 | case ... |
|
||||
| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:25:7:25:16 | default |
|
||||
@@ -48,3 +58,6 @@ hasBranchEdge
|
||||
| Test.java:23:27:23:34 | ... == ... | Test.java:23:27:23:29 | len | Test.java:23:34:23:34 | 4 | true | true | Test.java:23:39:23:41 | { ... } |
|
||||
| Test.java:24:7:24:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:24:12:24:14 | "g" | true | false | Test.java:25:7:25:16 | default |
|
||||
| Test.java:24:7:24:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:24:12:24:14 | "g" | true | true | Test.java:24:7:24:17 | case ... |
|
||||
| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:33:7:33:14 | default |
|
||||
| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | true | Test.java:28:7:28:15 | case ... |
|
||||
| Test.java:30:7:30:15 | case ... | Test.java:27:13:27:13 | s | Test.java:30:12:30:14 | "i" | true | false | Test.java:33:7:33:14 | default |
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args --release 21
|
||||
//semmle-extractor-options: --javac-args --release 22
|
||||
|
||||
@@ -26,6 +26,12 @@ public class Exhaustive {
|
||||
case Y y -> { }
|
||||
}
|
||||
|
||||
// Test the case where a pattern case falls directly out of a block:
|
||||
switch (i) {
|
||||
case X _:
|
||||
case Y _:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -98,6 +98,39 @@ public class Test {
|
||||
break;
|
||||
}
|
||||
|
||||
switch(thing) {
|
||||
case B(_, _):
|
||||
case Integer _, String _, A(_, _) when thing.toString().equals("abc"):
|
||||
case Float _:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
var result = switch(thing) {
|
||||
case B(_, _):
|
||||
case Integer _, String _, A(_, _) when thing.toString().equals("abc"):
|
||||
case Float _:
|
||||
yield 1;
|
||||
default:
|
||||
yield 2;
|
||||
};
|
||||
|
||||
switch ((String)thing) {
|
||||
case "a":
|
||||
case String _ when ((String)thing).length() == 5:
|
||||
case "b":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Test the case where a case falls out of a switch block without a break:
|
||||
switch(thing) {
|
||||
case String _:
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args --release 21
|
||||
//semmle-extractor-options: --javac-args --release 22
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
| Exhaustive.java:5:15:5:15 | { ... } | Exhaustive.java:5:15:5:15 | super(...) |
|
||||
| Exhaustive.java:6:15:6:15 | super(...) | Exhaustive.java:6:15:6:15 | Y |
|
||||
| Exhaustive.java:6:15:6:15 | { ... } | Exhaustive.java:6:15:6:15 | super(...) |
|
||||
| Exhaustive.java:8:47:29:3 | { ... } | Exhaustive.java:11:5:11:14 | switch (...) |
|
||||
| Exhaustive.java:8:47:35:3 | { ... } | Exhaustive.java:11:5:11:14 | switch (...) |
|
||||
| Exhaustive.java:11:5:11:14 | switch (...) | Exhaustive.java:11:13:11:13 | o |
|
||||
| Exhaustive.java:11:13:11:13 | o | Exhaustive.java:12:7:12:22 | case <Pattern> |
|
||||
| Exhaustive.java:12:7:12:22 | case <Pattern> | Exhaustive.java:12:19:12:19 | s |
|
||||
@@ -42,13 +42,20 @@
|
||||
| Exhaustive.java:25:7:25:17 | case <Pattern> | Exhaustive.java:25:14:25:14 | x |
|
||||
| Exhaustive.java:25:7:25:17 | case <Pattern> | Exhaustive.java:26:7:26:17 | case <Pattern> |
|
||||
| Exhaustive.java:25:14:25:14 | x | Exhaustive.java:25:19:25:21 | { ... } |
|
||||
| Exhaustive.java:25:19:25:21 | { ... } | Exhaustive.java:8:22:8:25 | test |
|
||||
| Exhaustive.java:25:19:25:21 | { ... } | Exhaustive.java:30:5:30:14 | switch (...) |
|
||||
| Exhaustive.java:26:7:26:17 | case <Pattern> | Exhaustive.java:26:14:26:14 | y |
|
||||
| Exhaustive.java:26:14:26:14 | y | Exhaustive.java:26:19:26:21 | { ... } |
|
||||
| Exhaustive.java:26:19:26:21 | { ... } | Exhaustive.java:8:22:8:25 | test |
|
||||
| Exhaustive.java:26:19:26:21 | { ... } | Exhaustive.java:30:5:30:14 | switch (...) |
|
||||
| Exhaustive.java:30:5:30:14 | switch (...) | Exhaustive.java:30:13:30:13 | i |
|
||||
| Exhaustive.java:30:13:30:13 | i | Exhaustive.java:31:7:31:15 | case <Pattern> |
|
||||
| Exhaustive.java:31:7:31:15 | case <Pattern> | Exhaustive.java:31:14:31:14 | <anonymous local variable> |
|
||||
| Exhaustive.java:31:7:31:15 | case <Pattern> | Exhaustive.java:32:7:32:15 | case <Pattern> |
|
||||
| Exhaustive.java:31:14:31:14 | <anonymous local variable> | Exhaustive.java:8:22:8:25 | test |
|
||||
| Exhaustive.java:32:7:32:15 | case <Pattern> | Exhaustive.java:32:14:32:14 | <anonymous local variable> |
|
||||
| Exhaustive.java:32:14:32:14 | <anonymous local variable> | Exhaustive.java:8:22:8:25 | test |
|
||||
| Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Test |
|
||||
| Test.java:1:14:1:17 | { ... } | Test.java:1:14:1:17 | super(...) |
|
||||
| Test.java:3:41:101:3 | { ... } | Test.java:5:6:5:19 | switch (...) |
|
||||
| Test.java:3:41:134:3 | { ... } | Test.java:5:6:5:19 | switch (...) |
|
||||
| Test.java:5:6:5:19 | switch (...) | Test.java:5:14:5:18 | thing |
|
||||
| Test.java:5:14:5:18 | thing | Test.java:6:8:6:23 | case <Pattern> |
|
||||
| Test.java:6:8:6:23 | case <Pattern> | Test.java:6:20:6:20 | s |
|
||||
@@ -288,26 +295,109 @@
|
||||
| Test.java:95:21:95:21 | x | Test.java:95:28:95:28 | y |
|
||||
| Test.java:95:28:95:28 | y | Test.java:95:15:95:29 | B(...) |
|
||||
| Test.java:95:36:95:36 | z | Test.java:95:13:95:37 | A(...) |
|
||||
| Test.java:96:10:96:15 | break | Test.java:3:22:3:25 | test |
|
||||
| Test.java:96:10:96:15 | break | Test.java:101:6:101:18 | switch (...) |
|
||||
| Test.java:97:8:97:15 | default | Test.java:98:10:98:15 | break |
|
||||
| Test.java:98:10:98:15 | break | Test.java:3:22:3:25 | test |
|
||||
| Test.java:105:8:105:8 | ...=... | Test.java:105:8:105:8 | <Expr>; |
|
||||
| Test.java:105:8:105:8 | ...=... | Test.java:105:8:105:8 | A |
|
||||
| Test.java:105:8:105:8 | <Expr>; | Test.java:105:8:105:8 | this |
|
||||
| Test.java:105:8:105:8 | <Expr>; | Test.java:105:8:105:8 | this |
|
||||
| Test.java:105:8:105:8 | b | Test.java:105:8:105:8 | ...=... |
|
||||
| Test.java:105:8:105:8 | field3 | Test.java:105:8:105:8 | ...=... |
|
||||
| Test.java:105:8:105:8 | super(...) | Test.java:105:8:105:8 | <Expr>; |
|
||||
| Test.java:105:8:105:8 | this | Test.java:105:8:105:8 | b |
|
||||
| Test.java:105:8:105:8 | this | Test.java:105:8:105:8 | field3 |
|
||||
| Test.java:105:8:105:8 | { ... } | Test.java:105:8:105:8 | super(...) |
|
||||
| Test.java:106:8:106:8 | ...=... | Test.java:106:8:106:8 | <Expr>; |
|
||||
| Test.java:106:8:106:8 | ...=... | Test.java:106:8:106:8 | B |
|
||||
| Test.java:106:8:106:8 | <Expr>; | Test.java:106:8:106:8 | this |
|
||||
| Test.java:106:8:106:8 | <Expr>; | Test.java:106:8:106:8 | this |
|
||||
| Test.java:106:8:106:8 | field1 | Test.java:106:8:106:8 | ...=... |
|
||||
| Test.java:106:8:106:8 | field2 | Test.java:106:8:106:8 | ...=... |
|
||||
| Test.java:106:8:106:8 | super(...) | Test.java:106:8:106:8 | <Expr>; |
|
||||
| Test.java:106:8:106:8 | this | Test.java:106:8:106:8 | field1 |
|
||||
| Test.java:106:8:106:8 | this | Test.java:106:8:106:8 | field2 |
|
||||
| Test.java:106:8:106:8 | { ... } | Test.java:106:8:106:8 | super(...) |
|
||||
| Test.java:98:10:98:15 | break | Test.java:101:6:101:18 | switch (...) |
|
||||
| Test.java:101:6:101:18 | switch (...) | Test.java:101:13:101:17 | thing |
|
||||
| Test.java:101:13:101:17 | thing | Test.java:102:8:102:20 | case <Pattern> |
|
||||
| Test.java:102:8:102:20 | case <Pattern> | Test.java:102:15:102:15 | <anonymous local variable> |
|
||||
| Test.java:102:8:102:20 | case <Pattern> | Test.java:103:8:103:77 | case <Pattern> |
|
||||
| Test.java:102:13:102:19 | B(...) | Test.java:105:10:105:15 | break |
|
||||
| Test.java:102:15:102:15 | <anonymous local variable> | Test.java:102:18:102:18 | <anonymous local variable> |
|
||||
| Test.java:102:18:102:18 | <anonymous local variable> | Test.java:102:13:102:19 | B(...) |
|
||||
| Test.java:103:8:103:77 | case <Pattern> | Test.java:103:21:103:21 | <anonymous local variable> |
|
||||
| Test.java:103:8:103:77 | case <Pattern> | Test.java:103:31:103:31 | <anonymous local variable> |
|
||||
| Test.java:103:8:103:77 | case <Pattern> | Test.java:103:36:103:36 | <anonymous local variable> |
|
||||
| Test.java:103:8:103:77 | case <Pattern> | Test.java:104:8:104:20 | case <Pattern> |
|
||||
| Test.java:103:21:103:21 | <anonymous local variable> | Test.java:103:47:103:51 | thing |
|
||||
| Test.java:103:31:103:31 | <anonymous local variable> | Test.java:103:47:103:51 | thing |
|
||||
| Test.java:103:34:103:40 | A(...) | Test.java:103:47:103:51 | thing |
|
||||
| Test.java:103:36:103:36 | <anonymous local variable> | Test.java:103:39:103:39 | <anonymous local variable> |
|
||||
| Test.java:103:39:103:39 | <anonymous local variable> | Test.java:103:34:103:40 | A(...) |
|
||||
| Test.java:103:47:103:51 | thing | Test.java:103:47:103:62 | toString(...) |
|
||||
| Test.java:103:47:103:62 | toString(...) | Test.java:103:71:103:75 | "abc" |
|
||||
| Test.java:103:47:103:76 | equals(...) | Test.java:104:8:104:20 | case <Pattern> |
|
||||
| Test.java:103:47:103:76 | equals(...) | Test.java:105:10:105:15 | break |
|
||||
| Test.java:103:71:103:75 | "abc" | Test.java:103:47:103:76 | equals(...) |
|
||||
| Test.java:104:8:104:20 | case <Pattern> | Test.java:104:19:104:19 | <anonymous local variable> |
|
||||
| Test.java:104:8:104:20 | case <Pattern> | Test.java:106:8:106:15 | default |
|
||||
| Test.java:104:19:104:19 | <anonymous local variable> | Test.java:105:10:105:15 | break |
|
||||
| Test.java:105:10:105:15 | break | Test.java:110:6:117:7 | var ...; |
|
||||
| Test.java:106:8:106:15 | default | Test.java:107:10:107:15 | break |
|
||||
| Test.java:107:10:107:15 | break | Test.java:110:6:117:7 | var ...; |
|
||||
| Test.java:110:6:117:7 | var ...; | Test.java:110:19:110:31 | switch (...) |
|
||||
| Test.java:110:10:110:31 | result | Test.java:119:6:119:27 | switch (...) |
|
||||
| Test.java:110:19:110:31 | switch (...) | Test.java:110:26:110:30 | thing |
|
||||
| Test.java:110:26:110:30 | thing | Test.java:111:8:111:20 | case <Pattern> |
|
||||
| Test.java:111:8:111:20 | case <Pattern> | Test.java:111:15:111:15 | <anonymous local variable> |
|
||||
| Test.java:111:8:111:20 | case <Pattern> | Test.java:112:8:112:77 | case <Pattern> |
|
||||
| Test.java:111:13:111:19 | B(...) | Test.java:114:10:114:17 | yield ... |
|
||||
| Test.java:111:15:111:15 | <anonymous local variable> | Test.java:111:18:111:18 | <anonymous local variable> |
|
||||
| Test.java:111:18:111:18 | <anonymous local variable> | Test.java:111:13:111:19 | B(...) |
|
||||
| Test.java:112:8:112:77 | case <Pattern> | Test.java:112:21:112:21 | <anonymous local variable> |
|
||||
| Test.java:112:8:112:77 | case <Pattern> | Test.java:112:31:112:31 | <anonymous local variable> |
|
||||
| Test.java:112:8:112:77 | case <Pattern> | Test.java:112:36:112:36 | <anonymous local variable> |
|
||||
| Test.java:112:8:112:77 | case <Pattern> | Test.java:113:8:113:20 | case <Pattern> |
|
||||
| Test.java:112:21:112:21 | <anonymous local variable> | Test.java:112:47:112:51 | thing |
|
||||
| Test.java:112:31:112:31 | <anonymous local variable> | Test.java:112:47:112:51 | thing |
|
||||
| Test.java:112:34:112:40 | A(...) | Test.java:112:47:112:51 | thing |
|
||||
| Test.java:112:36:112:36 | <anonymous local variable> | Test.java:112:39:112:39 | <anonymous local variable> |
|
||||
| Test.java:112:39:112:39 | <anonymous local variable> | Test.java:112:34:112:40 | A(...) |
|
||||
| Test.java:112:47:112:51 | thing | Test.java:112:47:112:62 | toString(...) |
|
||||
| Test.java:112:47:112:62 | toString(...) | Test.java:112:71:112:75 | "abc" |
|
||||
| Test.java:112:47:112:76 | equals(...) | Test.java:113:8:113:20 | case <Pattern> |
|
||||
| Test.java:112:47:112:76 | equals(...) | Test.java:114:10:114:17 | yield ... |
|
||||
| Test.java:112:71:112:75 | "abc" | Test.java:112:47:112:76 | equals(...) |
|
||||
| Test.java:113:8:113:20 | case <Pattern> | Test.java:113:19:113:19 | <anonymous local variable> |
|
||||
| Test.java:113:8:113:20 | case <Pattern> | Test.java:115:8:115:15 | default |
|
||||
| Test.java:113:19:113:19 | <anonymous local variable> | Test.java:114:10:114:17 | yield ... |
|
||||
| Test.java:114:10:114:17 | yield ... | Test.java:114:16:114:16 | 1 |
|
||||
| Test.java:114:16:114:16 | 1 | Test.java:110:10:110:31 | result |
|
||||
| Test.java:115:8:115:15 | default | Test.java:116:10:116:17 | yield ... |
|
||||
| Test.java:116:10:116:17 | yield ... | Test.java:116:16:116:16 | 2 |
|
||||
| Test.java:116:16:116:16 | 2 | Test.java:110:10:110:31 | result |
|
||||
| Test.java:119:6:119:27 | switch (...) | Test.java:119:22:119:26 | thing |
|
||||
| Test.java:119:14:119:26 | (...)... | Test.java:120:8:120:16 | case ... |
|
||||
| Test.java:119:14:119:26 | (...)... | Test.java:121:8:121:56 | case <Pattern> |
|
||||
| Test.java:119:22:119:26 | thing | Test.java:119:14:119:26 | (...)... |
|
||||
| Test.java:120:8:120:16 | case ... | Test.java:122:8:122:16 | case ... |
|
||||
| Test.java:121:8:121:56 | case <Pattern> | Test.java:121:20:121:20 | <anonymous local variable> |
|
||||
| Test.java:121:8:121:56 | case <Pattern> | Test.java:122:8:122:16 | case ... |
|
||||
| Test.java:121:8:121:56 | case <Pattern> | Test.java:124:8:124:15 | default |
|
||||
| Test.java:121:20:121:20 | <anonymous local variable> | Test.java:121:36:121:40 | thing |
|
||||
| Test.java:121:27:121:50 | length(...) | Test.java:121:55:121:55 | 5 |
|
||||
| Test.java:121:27:121:55 | ... == ... | Test.java:122:8:122:16 | case ... |
|
||||
| Test.java:121:27:121:55 | ... == ... | Test.java:124:8:124:15 | default |
|
||||
| Test.java:121:28:121:40 | (...)... | Test.java:121:27:121:50 | length(...) |
|
||||
| Test.java:121:36:121:40 | thing | Test.java:121:28:121:40 | (...)... |
|
||||
| Test.java:121:55:121:55 | 5 | Test.java:121:27:121:55 | ... == ... |
|
||||
| Test.java:122:8:122:16 | case ... | Test.java:123:10:123:15 | break |
|
||||
| Test.java:123:10:123:15 | break | Test.java:129:6:129:18 | switch (...) |
|
||||
| Test.java:124:8:124:15 | default | Test.java:125:10:125:15 | break |
|
||||
| Test.java:125:10:125:15 | break | Test.java:129:6:129:18 | switch (...) |
|
||||
| Test.java:129:6:129:18 | switch (...) | Test.java:129:13:129:17 | thing |
|
||||
| Test.java:129:13:129:17 | thing | Test.java:130:8:130:21 | case <Pattern> |
|
||||
| Test.java:130:8:130:21 | case <Pattern> | Test.java:130:20:130:20 | <anonymous local variable> |
|
||||
| Test.java:130:8:130:21 | case <Pattern> | Test.java:131:8:131:15 | default |
|
||||
| Test.java:130:20:130:20 | <anonymous local variable> | Test.java:131:8:131:15 | default |
|
||||
| Test.java:131:8:131:15 | default | Test.java:3:22:3:25 | test |
|
||||
| Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | <Expr>; |
|
||||
| Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | A |
|
||||
| Test.java:138:8:138:8 | <Expr>; | Test.java:138:8:138:8 | this |
|
||||
| Test.java:138:8:138:8 | <Expr>; | Test.java:138:8:138:8 | this |
|
||||
| Test.java:138:8:138:8 | b | Test.java:138:8:138:8 | ...=... |
|
||||
| Test.java:138:8:138:8 | field3 | Test.java:138:8:138:8 | ...=... |
|
||||
| Test.java:138:8:138:8 | super(...) | Test.java:138:8:138:8 | <Expr>; |
|
||||
| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | b |
|
||||
| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | field3 |
|
||||
| Test.java:138:8:138:8 | { ... } | Test.java:138:8:138:8 | super(...) |
|
||||
| Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | <Expr>; |
|
||||
| Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | B |
|
||||
| Test.java:139:8:139:8 | <Expr>; | Test.java:139:8:139:8 | this |
|
||||
| Test.java:139:8:139:8 | <Expr>; | Test.java:139:8:139:8 | this |
|
||||
| Test.java:139:8:139:8 | field1 | Test.java:139:8:139:8 | ...=... |
|
||||
| Test.java:139:8:139:8 | field2 | Test.java:139:8:139:8 | ...=... |
|
||||
| Test.java:139:8:139:8 | super(...) | Test.java:139:8:139:8 | <Expr>; |
|
||||
| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | field1 |
|
||||
| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | field2 |
|
||||
| Test.java:139:8:139:8 | { ... } | Test.java:139:8:139:8 | super(...) |
|
||||
|
||||
@@ -45,6 +45,13 @@ public class Test {
|
||||
|
||||
if (o instanceof R(S(var x), var y)) { }
|
||||
|
||||
switch(o) {
|
||||
case String _, Integer _:
|
||||
case R(S(_), _):
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args --release 21
|
||||
//semmle-extractor-options: --javac-args --release 22
|
||||
|
||||
@@ -84,5 +84,11 @@
|
||||
| Test.java:1:14:1:17 | Test | 83 | } |
|
||||
| Test.java:1:14:1:17 | Test | 84 | if (o instanceof R(S(var x), var y)) { |
|
||||
| Test.java:1:14:1:17 | Test | 85 | } |
|
||||
| Test.java:1:14:1:17 | Test | 86 | } |
|
||||
| Test.java:1:14:1:17 | Test | 87 | } |
|
||||
| Test.java:1:14:1:17 | Test | 86 | switch (o) { |
|
||||
| Test.java:1:14:1:17 | Test | 87 | case String _, Integer _: |
|
||||
| Test.java:1:14:1:17 | Test | 88 | case R(S(var _), var _): |
|
||||
| Test.java:1:14:1:17 | Test | 89 | default: |
|
||||
| Test.java:1:14:1:17 | Test | 90 | break; |
|
||||
| Test.java:1:14:1:17 | Test | 91 | } |
|
||||
| Test.java:1:14:1:17 | Test | 92 | } |
|
||||
| Test.java:1:14:1:17 | Test | 93 | } |
|
||||
|
||||
181
java/ql/test/library-tests/printAst/AnonDecls.java
Normal file
181
java/ql/test/library-tests/printAst/AnonDecls.java
Normal file
@@ -0,0 +1,181 @@
|
||||
import java.io.Closeable;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
record SubRecord(int z) { }
|
||||
record MyRecord(int x, SubRecord y) { }
|
||||
|
||||
public class AnonDecls {
|
||||
|
||||
public static void test(List<String> ss, Object o) {
|
||||
|
||||
// Note each construct is repeated to ensure this doesn't produce database inconsistencies
|
||||
|
||||
int _ = 1;
|
||||
int _ = 2;
|
||||
|
||||
try (Closeable _ = null) { } catch (Exception _) { }
|
||||
try (Closeable _ = null) { } catch (Exception _) { }
|
||||
|
||||
int x = 0;
|
||||
|
||||
for (int _ = 1; x < 10; x++) { }
|
||||
for (int _ = 2; x > 0; x--) { }
|
||||
|
||||
for (var _ : ss) { }
|
||||
for (var _ : ss) { }
|
||||
|
||||
BiFunction<Integer, Integer, Integer> f1 = (_, _) -> 1;
|
||||
BiFunction<Integer, Integer, Integer> f2 = (_, _) -> 2;
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord _:
|
||||
default:
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord (int _, SubRecord _):
|
||||
default:
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord (int _, SubRecord (int _)):
|
||||
default:
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord (_, _):
|
||||
default:
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_):
|
||||
default:
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_) when ss != null:
|
||||
default:
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
// Note use of binding patterns, not records with unnamed patterns as above
|
||||
case MyRecord _, SubRecord _:
|
||||
default:
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _ -> { }
|
||||
case MyRecord _ -> { }
|
||||
default -> { }
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _ -> { }
|
||||
case MyRecord (int _, SubRecord _) -> { }
|
||||
default -> { }
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _ -> { }
|
||||
case MyRecord (int _, SubRecord (int _)) -> { }
|
||||
default -> { }
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case SubRecord _ -> { }
|
||||
case MyRecord (_, _) -> { }
|
||||
default -> { }
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_) -> { }
|
||||
default -> { }
|
||||
}
|
||||
|
||||
switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_) when ss != null -> { }
|
||||
default -> { }
|
||||
}
|
||||
|
||||
var x1 = switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord _:
|
||||
default:
|
||||
yield 1;
|
||||
};
|
||||
|
||||
var x2 = switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord (int _, SubRecord _):
|
||||
default:
|
||||
yield 1;
|
||||
};
|
||||
|
||||
var x3 = switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord (int _, SubRecord (int _)):
|
||||
default:
|
||||
yield 1;
|
||||
};
|
||||
|
||||
var x4 = switch (o) {
|
||||
case SubRecord _:
|
||||
case MyRecord (_, _):
|
||||
default:
|
||||
yield 1;
|
||||
};
|
||||
|
||||
var x5 = switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_):
|
||||
default:
|
||||
yield 1;
|
||||
};
|
||||
|
||||
var x6 = switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_) when ss != null:
|
||||
default:
|
||||
yield 1;
|
||||
};
|
||||
|
||||
var x7 = switch (o) {
|
||||
case SubRecord _ -> 1;
|
||||
case MyRecord _ -> 2;
|
||||
default -> 3;
|
||||
};
|
||||
|
||||
var x8 = switch (o) {
|
||||
case SubRecord _ -> 1;
|
||||
case MyRecord (int _, SubRecord _) -> 2;
|
||||
default -> 3;
|
||||
};
|
||||
|
||||
var x9 = switch (o) {
|
||||
case SubRecord _ -> 1;
|
||||
case MyRecord (int _, SubRecord (int _)) -> 2;
|
||||
default -> 3;
|
||||
};
|
||||
|
||||
var x10 = switch (o) {
|
||||
case SubRecord _ -> 1;
|
||||
case MyRecord (_, _) -> 2;
|
||||
default -> 3;
|
||||
};
|
||||
|
||||
var x11 = switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_) -> 1;
|
||||
default -> 2;
|
||||
};
|
||||
|
||||
var x12 = switch (o) {
|
||||
case MyRecord (_, _), SubRecord(_) when ss != null -> 1;
|
||||
default -> 2;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -127,7 +127,7 @@ A.java:
|
||||
# 54| -1: [VarAccess] System.out
|
||||
# 54| -1: [TypeAccess] System
|
||||
# 54| 0: [VarAccess] s
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 54| 0: [TypeAccess] String
|
||||
# 54| 1: [LocalVariableDeclExpr] s
|
||||
# 55| 1: [PatternCase] case <Pattern>
|
||||
@@ -138,7 +138,7 @@ A.java:
|
||||
# 55| 0: [AddExpr] ... + ...
|
||||
# 55| 0: [StringLiteral] "An integer: "
|
||||
# 55| 1: [VarAccess] i
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 55| 0: [TypeAccess] Integer
|
||||
# 55| 1: [LocalVariableDeclExpr] i
|
||||
# 56| 2: [DefaultCase] default
|
||||
@@ -146,7 +146,7 @@ A.java:
|
||||
# 58| 3: [SwitchStmt] switch (...)
|
||||
# 58| -1: [VarAccess] thing
|
||||
# 59| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 59| 0: [TypeAccess] String
|
||||
# 59| 1: [LocalVariableDeclExpr] s
|
||||
# 60| 1: [ExprStmt] <Expr>;
|
||||
@@ -156,7 +156,7 @@ A.java:
|
||||
# 60| 0: [VarAccess] s
|
||||
# 61| 2: [BreakStmt] break
|
||||
# 62| 3: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 62| 0: [TypeAccess] Integer
|
||||
# 62| 1: [LocalVariableDeclExpr] i
|
||||
# 63| 4: [ExprStmt] <Expr>;
|
||||
@@ -175,14 +175,14 @@ A.java:
|
||||
# 68| -1: [VarAccess] thing
|
||||
# 69| 0: [PatternCase] case <Pattern>
|
||||
# 69| -1: [VarAccess] s
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 69| 0: [TypeAccess] String
|
||||
# 69| 1: [LocalVariableDeclExpr] s
|
||||
# 70| 1: [PatternCase] case <Pattern>
|
||||
# 70| -1: [AddExpr] ... + ...
|
||||
# 70| 0: [StringLiteral] "An integer: "
|
||||
# 70| 1: [VarAccess] i
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 70| 0: [TypeAccess] Integer
|
||||
# 70| 1: [LocalVariableDeclExpr] i
|
||||
# 71| 2: [DefaultCase] default
|
||||
@@ -192,13 +192,13 @@ A.java:
|
||||
# 73| 0: [SwitchExpr] switch (...)
|
||||
# 73| -1: [VarAccess] thing
|
||||
# 74| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 74| 0: [TypeAccess] String
|
||||
# 74| 1: [LocalVariableDeclExpr] s
|
||||
# 75| 1: [YieldStmt] yield ...
|
||||
# 75| 0: [VarAccess] s
|
||||
# 76| 2: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 76| 0: [TypeAccess] Integer
|
||||
# 76| 1: [LocalVariableDeclExpr] i
|
||||
# 77| 3: [YieldStmt] yield ...
|
||||
@@ -232,7 +232,7 @@ A.java:
|
||||
# 87| -1: [VarAccess] s
|
||||
# 87| 1: [IntegerLiteral] 3
|
||||
# 87| -1: [StringLiteral] "It's 3 letters long"
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 87| 0: [TypeAccess] String
|
||||
# 87| 1: [LocalVariableDeclExpr] s
|
||||
# 88| 2: [PatternCase] case <Pattern>
|
||||
@@ -241,7 +241,7 @@ A.java:
|
||||
# 88| -1: [VarAccess] s
|
||||
# 88| 1: [IntegerLiteral] 5
|
||||
# 88| -1: [StringLiteral] "it's 5 letters long"
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 88| 0: [TypeAccess] String
|
||||
# 88| 1: [LocalVariableDeclExpr] s
|
||||
# 89| 3: [DefaultCase] default
|
||||
@@ -252,7 +252,7 @@ A.java:
|
||||
# 91| -1: [VarAccess] thing
|
||||
# 92| 0: [PatternCase] case <Pattern>
|
||||
# 92| -1: [StringLiteral] "It's a string"
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 92| 0: [TypeAccess] String
|
||||
# 92| 1: [LocalVariableDeclExpr] s
|
||||
# 93| 1: [NullDefaultCase] case null, default
|
||||
@@ -332,3 +332,486 @@ A.java:
|
||||
# 130| 2: [FieldDeclaration] String field;
|
||||
# 131| 3: [Class] Middle
|
||||
# 131| 2: [FieldDeclaration] Inner inner;
|
||||
AnonDecls.java:
|
||||
# 0| [CompilationUnit] AnonDecls
|
||||
#-----| -1: (Imports)
|
||||
# 1| 1: [ImportType] import Closeable
|
||||
# 2| 2: [ImportType] import List
|
||||
# 3| 3: [ImportType] import BiFunction
|
||||
# 5| 1: [Class] SubRecord
|
||||
# 5| 2: [FieldDeclaration] int z;
|
||||
# 6| 2: [Class] MyRecord
|
||||
# 6| 2: [FieldDeclaration] int x;
|
||||
# 6| 3: [FieldDeclaration] SubRecord y;
|
||||
# 8| 3: [Class] AnonDecls
|
||||
# 10| 2: [Method] test
|
||||
# 10| 3: [TypeAccess] void
|
||||
#-----| 4: (Parameters)
|
||||
# 10| 0: [Parameter] ss
|
||||
# 10| 0: [TypeAccess] List<String>
|
||||
# 10| 0: [TypeAccess] String
|
||||
# 10| 1: [Parameter] o
|
||||
# 10| 0: [TypeAccess] Object
|
||||
# 10| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 14| 0: [TypeAccess] int
|
||||
# 14| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 14| 0: [IntegerLiteral] 1
|
||||
# 15| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 15| 0: [TypeAccess] int
|
||||
# 15| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 15| 0: [IntegerLiteral] 2
|
||||
# 17| 2: [TryStmt] try ...
|
||||
# 17| -3: [LocalVariableDeclStmt] var ...;
|
||||
# 17| 0: [TypeAccess] Closeable
|
||||
# 17| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 17| 0: [NullLiteral] null
|
||||
# 17| -1: [BlockStmt] { ... }
|
||||
# 17| 0: [CatchClause] catch (...)
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 17| 0: [TypeAccess] Exception
|
||||
# 17| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 17| 1: [BlockStmt] { ... }
|
||||
# 18| 3: [TryStmt] try ...
|
||||
# 18| -3: [LocalVariableDeclStmt] var ...;
|
||||
# 18| 0: [TypeAccess] Closeable
|
||||
# 18| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 18| 0: [NullLiteral] null
|
||||
# 18| -1: [BlockStmt] { ... }
|
||||
# 18| 0: [CatchClause] catch (...)
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 18| 0: [TypeAccess] Exception
|
||||
# 18| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 18| 1: [BlockStmt] { ... }
|
||||
# 20| 4: [LocalVariableDeclStmt] var ...;
|
||||
# 20| 0: [TypeAccess] int
|
||||
# 20| 1: [LocalVariableDeclExpr] x
|
||||
# 20| 0: [IntegerLiteral] 0
|
||||
# 22| 5: [ForStmt] for (...;...;...)
|
||||
#-----| 0: (For Initializers)
|
||||
# 22| 0: [TypeAccess] int
|
||||
# 22| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 22| 0: [IntegerLiteral] 1
|
||||
# 22| 1: [LTExpr] ... < ...
|
||||
# 22| 0: [VarAccess] x
|
||||
# 22| 1: [IntegerLiteral] 10
|
||||
# 22| 2: [BlockStmt] { ... }
|
||||
# 22| 3: [PostIncExpr] ...++
|
||||
# 22| 0: [VarAccess] x
|
||||
# 23| 6: [ForStmt] for (...;...;...)
|
||||
#-----| 0: (For Initializers)
|
||||
# 23| 0: [TypeAccess] int
|
||||
# 23| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 23| 0: [IntegerLiteral] 2
|
||||
# 23| 1: [GTExpr] ... > ...
|
||||
# 23| 0: [VarAccess] x
|
||||
# 23| 1: [IntegerLiteral] 0
|
||||
# 23| 2: [BlockStmt] { ... }
|
||||
# 23| 3: [PostDecExpr] ...--
|
||||
# 23| 0: [VarAccess] x
|
||||
# 25| 7: [EnhancedForStmt] for (... : ...)
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 25| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 25| 1: [VarAccess] ss
|
||||
# 25| 2: [BlockStmt] { ... }
|
||||
# 26| 8: [EnhancedForStmt] for (... : ...)
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 26| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 26| 1: [VarAccess] ss
|
||||
# 26| 2: [BlockStmt] { ... }
|
||||
# 28| 9: [LocalVariableDeclStmt] var ...;
|
||||
# 28| 0: [TypeAccess] BiFunction<Integer,Integer,Integer>
|
||||
# 28| 0: [TypeAccess] Integer
|
||||
# 28| 1: [TypeAccess] Integer
|
||||
# 28| 2: [TypeAccess] Integer
|
||||
# 28| 1: [LocalVariableDeclExpr] f1
|
||||
# 28| 0: [LambdaExpr] ...->...
|
||||
# 28| -4: [AnonymousClass] new BiFunction<Integer,Integer,Integer>(...) { ... }
|
||||
# 28| 2: [Method] apply
|
||||
#-----| 4: (Parameters)
|
||||
# 28| 0: [Parameter] <anonymous parameter>
|
||||
# 28| 1: [Parameter] <anonymous parameter>
|
||||
# 28| 5: [BlockStmt] { ... }
|
||||
# 28| 0: [ReturnStmt] return ...
|
||||
# 28| 0: [IntegerLiteral] 1
|
||||
# 28| -3: [TypeAccess] BiFunction<Integer,Integer,Integer>
|
||||
# 28| 0: [TypeAccess] Integer
|
||||
# 28| 1: [TypeAccess] Integer
|
||||
# 28| 2: [TypeAccess] Integer
|
||||
# 29| 10: [LocalVariableDeclStmt] var ...;
|
||||
# 29| 0: [TypeAccess] BiFunction<Integer,Integer,Integer>
|
||||
# 29| 0: [TypeAccess] Integer
|
||||
# 29| 1: [TypeAccess] Integer
|
||||
# 29| 2: [TypeAccess] Integer
|
||||
# 29| 1: [LocalVariableDeclExpr] f2
|
||||
# 29| 0: [LambdaExpr] ...->...
|
||||
# 29| -4: [AnonymousClass] new BiFunction<Integer,Integer,Integer>(...) { ... }
|
||||
# 29| 2: [Method] apply
|
||||
#-----| 4: (Parameters)
|
||||
# 29| 0: [Parameter] <anonymous parameter>
|
||||
# 29| 1: [Parameter] <anonymous parameter>
|
||||
# 29| 5: [BlockStmt] { ... }
|
||||
# 29| 0: [ReturnStmt] return ...
|
||||
# 29| 0: [IntegerLiteral] 2
|
||||
# 29| -3: [TypeAccess] BiFunction<Integer,Integer,Integer>
|
||||
# 29| 0: [TypeAccess] Integer
|
||||
# 29| 1: [TypeAccess] Integer
|
||||
# 29| 2: [TypeAccess] Integer
|
||||
# 31| 11: [SwitchStmt] switch (...)
|
||||
# 31| -1: [VarAccess] o
|
||||
# 32| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 32| 0: [TypeAccess] SubRecord
|
||||
# 32| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 33| 1: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 33| 0: [TypeAccess] MyRecord
|
||||
# 33| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 34| 2: [DefaultCase] default
|
||||
# 37| 12: [SwitchStmt] switch (...)
|
||||
# 37| -1: [VarAccess] o
|
||||
# 38| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 38| 0: [TypeAccess] SubRecord
|
||||
# 38| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 39| 1: [PatternCase] case <Pattern>
|
||||
# 39| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 39| -2: [TypeAccess] SubRecord
|
||||
# 39| -1: [TypeAccess] int
|
||||
# 39| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 39| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 40| 2: [DefaultCase] default
|
||||
# 43| 13: [SwitchStmt] switch (...)
|
||||
# 43| -1: [VarAccess] o
|
||||
# 44| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 44| 0: [TypeAccess] SubRecord
|
||||
# 44| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 45| 1: [PatternCase] case <Pattern>
|
||||
# 45| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 45| -1: [TypeAccess] int
|
||||
# 45| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 45| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 45| -1: [TypeAccess] int
|
||||
# 45| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 46| 2: [DefaultCase] default
|
||||
# 49| 14: [SwitchStmt] switch (...)
|
||||
# 49| -1: [VarAccess] o
|
||||
# 50| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 50| 0: [TypeAccess] SubRecord
|
||||
# 50| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 51| 1: [PatternCase] case <Pattern>
|
||||
# 51| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 51| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 51| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 52| 2: [DefaultCase] default
|
||||
# 55| 15: [SwitchStmt] switch (...)
|
||||
# 55| -1: [VarAccess] o
|
||||
# 56| 0: [PatternCase] case <Pattern>
|
||||
# 56| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 56| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 56| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 56| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 56| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 57| 1: [DefaultCase] default
|
||||
# 60| 16: [SwitchStmt] switch (...)
|
||||
# 60| -1: [VarAccess] o
|
||||
# 61| 0: [PatternCase] case <Pattern>
|
||||
# 61| -3: [NEExpr] ... != ...
|
||||
# 61| 0: [VarAccess] ss
|
||||
# 61| 1: [NullLiteral] null
|
||||
# 61| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 61| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 61| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 61| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 61| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 62| 1: [DefaultCase] default
|
||||
# 65| 17: [SwitchStmt] switch (...)
|
||||
# 65| -1: [VarAccess] o
|
||||
# 67| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 67| 0: [TypeAccess] MyRecord
|
||||
# 67| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
#-----| 1: (Pattern case declaration)
|
||||
# 67| 0: [TypeAccess] SubRecord
|
||||
# 67| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 68| 1: [DefaultCase] default
|
||||
# 71| 18: [SwitchStmt] switch (...)
|
||||
# 71| -1: [VarAccess] o
|
||||
# 72| 0: [PatternCase] case <Pattern>
|
||||
# 72| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 72| 0: [TypeAccess] SubRecord
|
||||
# 72| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 73| 1: [PatternCase] case <Pattern>
|
||||
# 73| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 73| 0: [TypeAccess] MyRecord
|
||||
# 73| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 74| 2: [DefaultCase] default
|
||||
# 74| -1: [BlockStmt] { ... }
|
||||
# 77| 19: [SwitchStmt] switch (...)
|
||||
# 77| -1: [VarAccess] o
|
||||
# 78| 0: [PatternCase] case <Pattern>
|
||||
# 78| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 78| 0: [TypeAccess] SubRecord
|
||||
# 78| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 79| 1: [PatternCase] case <Pattern>
|
||||
# 79| -1: [BlockStmt] { ... }
|
||||
# 79| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 79| -2: [TypeAccess] SubRecord
|
||||
# 79| -1: [TypeAccess] int
|
||||
# 79| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 79| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 80| 2: [DefaultCase] default
|
||||
# 80| -1: [BlockStmt] { ... }
|
||||
# 83| 20: [SwitchStmt] switch (...)
|
||||
# 83| -1: [VarAccess] o
|
||||
# 84| 0: [PatternCase] case <Pattern>
|
||||
# 84| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 84| 0: [TypeAccess] SubRecord
|
||||
# 84| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 85| 1: [PatternCase] case <Pattern>
|
||||
# 85| -1: [BlockStmt] { ... }
|
||||
# 85| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 85| -1: [TypeAccess] int
|
||||
# 85| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 85| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 85| -1: [TypeAccess] int
|
||||
# 85| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 86| 2: [DefaultCase] default
|
||||
# 86| -1: [BlockStmt] { ... }
|
||||
# 89| 21: [SwitchStmt] switch (...)
|
||||
# 89| -1: [VarAccess] o
|
||||
# 90| 0: [PatternCase] case <Pattern>
|
||||
# 90| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 90| 0: [TypeAccess] SubRecord
|
||||
# 90| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 91| 1: [PatternCase] case <Pattern>
|
||||
# 91| -1: [BlockStmt] { ... }
|
||||
# 91| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 91| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 91| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 92| 2: [DefaultCase] default
|
||||
# 92| -1: [BlockStmt] { ... }
|
||||
# 95| 22: [SwitchStmt] switch (...)
|
||||
# 95| -1: [VarAccess] o
|
||||
# 96| 0: [PatternCase] case <Pattern>
|
||||
# 96| -1: [BlockStmt] { ... }
|
||||
# 96| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 96| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 96| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 96| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 96| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 97| 1: [DefaultCase] default
|
||||
# 97| -1: [BlockStmt] { ... }
|
||||
# 100| 23: [SwitchStmt] switch (...)
|
||||
# 100| -1: [VarAccess] o
|
||||
# 101| 0: [PatternCase] case <Pattern>
|
||||
# 101| -3: [NEExpr] ... != ...
|
||||
# 101| 0: [VarAccess] ss
|
||||
# 101| 1: [NullLiteral] null
|
||||
# 101| -1: [BlockStmt] { ... }
|
||||
# 101| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 101| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 101| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 101| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 101| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 102| 1: [DefaultCase] default
|
||||
# 102| -1: [BlockStmt] { ... }
|
||||
# 105| 24: [LocalVariableDeclStmt] var ...;
|
||||
# 105| 1: [LocalVariableDeclExpr] x1
|
||||
# 105| 0: [SwitchExpr] switch (...)
|
||||
# 105| -1: [VarAccess] o
|
||||
# 106| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 106| 0: [TypeAccess] SubRecord
|
||||
# 106| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 107| 1: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 107| 0: [TypeAccess] MyRecord
|
||||
# 107| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 108| 2: [DefaultCase] default
|
||||
# 109| 3: [YieldStmt] yield ...
|
||||
# 109| 0: [IntegerLiteral] 1
|
||||
# 112| 25: [LocalVariableDeclStmt] var ...;
|
||||
# 112| 1: [LocalVariableDeclExpr] x2
|
||||
# 112| 0: [SwitchExpr] switch (...)
|
||||
# 112| -1: [VarAccess] o
|
||||
# 113| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 113| 0: [TypeAccess] SubRecord
|
||||
# 113| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 114| 1: [PatternCase] case <Pattern>
|
||||
# 114| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 114| -2: [TypeAccess] SubRecord
|
||||
# 114| -1: [TypeAccess] int
|
||||
# 114| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 114| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 115| 2: [DefaultCase] default
|
||||
# 116| 3: [YieldStmt] yield ...
|
||||
# 116| 0: [IntegerLiteral] 1
|
||||
# 119| 26: [LocalVariableDeclStmt] var ...;
|
||||
# 119| 1: [LocalVariableDeclExpr] x3
|
||||
# 119| 0: [SwitchExpr] switch (...)
|
||||
# 119| -1: [VarAccess] o
|
||||
# 120| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 120| 0: [TypeAccess] SubRecord
|
||||
# 120| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 121| 1: [PatternCase] case <Pattern>
|
||||
# 121| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 121| -1: [TypeAccess] int
|
||||
# 121| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 121| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 121| -1: [TypeAccess] int
|
||||
# 121| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 122| 2: [DefaultCase] default
|
||||
# 123| 3: [YieldStmt] yield ...
|
||||
# 123| 0: [IntegerLiteral] 1
|
||||
# 126| 27: [LocalVariableDeclStmt] var ...;
|
||||
# 126| 1: [LocalVariableDeclExpr] x4
|
||||
# 126| 0: [SwitchExpr] switch (...)
|
||||
# 126| -1: [VarAccess] o
|
||||
# 127| 0: [PatternCase] case <Pattern>
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 127| 0: [TypeAccess] SubRecord
|
||||
# 127| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 128| 1: [PatternCase] case <Pattern>
|
||||
# 128| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 128| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 128| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 129| 2: [DefaultCase] default
|
||||
# 130| 3: [YieldStmt] yield ...
|
||||
# 130| 0: [IntegerLiteral] 1
|
||||
# 133| 28: [LocalVariableDeclStmt] var ...;
|
||||
# 133| 1: [LocalVariableDeclExpr] x5
|
||||
# 133| 0: [SwitchExpr] switch (...)
|
||||
# 133| -1: [VarAccess] o
|
||||
# 134| 0: [PatternCase] case <Pattern>
|
||||
# 134| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 134| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 134| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 134| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 134| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 135| 1: [DefaultCase] default
|
||||
# 136| 2: [YieldStmt] yield ...
|
||||
# 136| 0: [IntegerLiteral] 1
|
||||
# 139| 29: [LocalVariableDeclStmt] var ...;
|
||||
# 139| 1: [LocalVariableDeclExpr] x6
|
||||
# 139| 0: [SwitchExpr] switch (...)
|
||||
# 139| -1: [VarAccess] o
|
||||
# 140| 0: [PatternCase] case <Pattern>
|
||||
# 140| -3: [NEExpr] ... != ...
|
||||
# 140| 0: [VarAccess] ss
|
||||
# 140| 1: [NullLiteral] null
|
||||
# 140| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 140| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 140| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 140| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 140| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 141| 1: [DefaultCase] default
|
||||
# 142| 2: [YieldStmt] yield ...
|
||||
# 142| 0: [IntegerLiteral] 1
|
||||
# 145| 30: [LocalVariableDeclStmt] var ...;
|
||||
# 145| 1: [LocalVariableDeclExpr] x7
|
||||
# 145| 0: [SwitchExpr] switch (...)
|
||||
# 145| -1: [VarAccess] o
|
||||
# 146| 0: [PatternCase] case <Pattern>
|
||||
# 146| -1: [IntegerLiteral] 1
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 146| 0: [TypeAccess] SubRecord
|
||||
# 146| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 147| 1: [PatternCase] case <Pattern>
|
||||
# 147| -1: [IntegerLiteral] 2
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 147| 0: [TypeAccess] MyRecord
|
||||
# 147| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 148| 2: [DefaultCase] default
|
||||
# 148| -1: [IntegerLiteral] 3
|
||||
# 151| 31: [LocalVariableDeclStmt] var ...;
|
||||
# 151| 1: [LocalVariableDeclExpr] x8
|
||||
# 151| 0: [SwitchExpr] switch (...)
|
||||
# 151| -1: [VarAccess] o
|
||||
# 152| 0: [PatternCase] case <Pattern>
|
||||
# 152| -1: [IntegerLiteral] 1
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 152| 0: [TypeAccess] SubRecord
|
||||
# 152| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 153| 1: [PatternCase] case <Pattern>
|
||||
# 153| -1: [IntegerLiteral] 2
|
||||
# 153| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 153| -2: [TypeAccess] SubRecord
|
||||
# 153| -1: [TypeAccess] int
|
||||
# 153| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 153| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 154| 2: [DefaultCase] default
|
||||
# 154| -1: [IntegerLiteral] 3
|
||||
# 157| 32: [LocalVariableDeclStmt] var ...;
|
||||
# 157| 1: [LocalVariableDeclExpr] x9
|
||||
# 157| 0: [SwitchExpr] switch (...)
|
||||
# 157| -1: [VarAccess] o
|
||||
# 158| 0: [PatternCase] case <Pattern>
|
||||
# 158| -1: [IntegerLiteral] 1
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 158| 0: [TypeAccess] SubRecord
|
||||
# 158| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 159| 1: [PatternCase] case <Pattern>
|
||||
# 159| -1: [IntegerLiteral] 2
|
||||
# 159| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 159| -1: [TypeAccess] int
|
||||
# 159| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 159| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 159| -1: [TypeAccess] int
|
||||
# 159| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 160| 2: [DefaultCase] default
|
||||
# 160| -1: [IntegerLiteral] 3
|
||||
# 163| 33: [LocalVariableDeclStmt] var ...;
|
||||
# 163| 1: [LocalVariableDeclExpr] x10
|
||||
# 163| 0: [SwitchExpr] switch (...)
|
||||
# 163| -1: [VarAccess] o
|
||||
# 164| 0: [PatternCase] case <Pattern>
|
||||
# 164| -1: [IntegerLiteral] 1
|
||||
#-----| 0: (Pattern case declaration)
|
||||
# 164| 0: [TypeAccess] SubRecord
|
||||
# 164| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 165| 1: [PatternCase] case <Pattern>
|
||||
# 165| -1: [IntegerLiteral] 2
|
||||
# 165| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 165| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 165| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 166| 2: [DefaultCase] default
|
||||
# 166| -1: [IntegerLiteral] 3
|
||||
# 169| 34: [LocalVariableDeclStmt] var ...;
|
||||
# 169| 1: [LocalVariableDeclExpr] x11
|
||||
# 169| 0: [SwitchExpr] switch (...)
|
||||
# 169| -1: [VarAccess] o
|
||||
# 170| 0: [PatternCase] case <Pattern>
|
||||
# 170| -1: [IntegerLiteral] 1
|
||||
# 170| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 170| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 170| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 170| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 170| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 171| 1: [DefaultCase] default
|
||||
# 171| -1: [IntegerLiteral] 2
|
||||
# 174| 35: [LocalVariableDeclStmt] var ...;
|
||||
# 174| 1: [LocalVariableDeclExpr] x12
|
||||
# 174| 0: [SwitchExpr] switch (...)
|
||||
# 174| -1: [VarAccess] o
|
||||
# 175| 0: [PatternCase] case <Pattern>
|
||||
# 175| -3: [NEExpr] ... != ...
|
||||
# 175| 0: [VarAccess] ss
|
||||
# 175| 1: [NullLiteral] null
|
||||
# 175| -1: [IntegerLiteral] 1
|
||||
# 175| 0: [RecordPatternExpr] MyRecord(...)
|
||||
# 175| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 175| 1: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 175| 1: [RecordPatternExpr] SubRecord(...)
|
||||
# 175| 0: [LocalVariableDeclExpr] <anonymous local variable>
|
||||
# 176| 1: [DefaultCase] default
|
||||
# 176| -1: [IntegerLiteral] 2
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args --release 21
|
||||
//semmle-extractor-options: --javac-args --release 22
|
||||
|
||||
@@ -58,6 +58,31 @@ public class Test {
|
||||
case null: default: i.take(source()); // Can't call C1.take (but we don't currently notice)
|
||||
}
|
||||
|
||||
switch(i) {
|
||||
case C1 _, C2 _:
|
||||
i.take(source()); // Must be either C1.take or C2.take (but we don't currently notice, because neither dominates)
|
||||
break;
|
||||
default:
|
||||
i.take(source()); // Can't call C1.take or C2.take (but we don't currently notice, because a multi-pattern case isn't understood as a type test)
|
||||
}
|
||||
|
||||
switch(i) {
|
||||
case C1 _, C2 _ when i.toString().equals("abc"):
|
||||
i.take(source()); // Must be either C1.take or C2.take (but we don't currently notice, because neither dominates)
|
||||
break;
|
||||
default:
|
||||
i.take(source()); // Can't call C1.take or C2.take (but we don't currently notice, because a multi-pattern case isn't understood as a type test)
|
||||
}
|
||||
|
||||
switch(i) {
|
||||
case C1 _:
|
||||
case C2 _:
|
||||
i.take(source()); // Must be either C1.take or C2.take (but we don't currently notice, because neither dominates)
|
||||
break;
|
||||
default:
|
||||
i.take(source()); // Can't call C1.take or C2.take
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args --release 21
|
||||
//semmle-extractor-options: --javac-args --release 22
|
||||
|
||||
@@ -30,3 +30,25 @@
|
||||
| Test.java:58:34:58:41 | source(...) | Test.java:8:65:8:65 | x |
|
||||
| Test.java:58:34:58:41 | source(...) | Test.java:9:74:9:74 | x |
|
||||
| Test.java:58:34:58:41 | source(...) | Test.java:10:82:10:82 | x |
|
||||
| Test.java:63:16:63:23 | source(...) | Test.java:7:65:7:65 | x |
|
||||
| Test.java:63:16:63:23 | source(...) | Test.java:8:65:8:65 | x |
|
||||
| Test.java:63:16:63:23 | source(...) | Test.java:9:74:9:74 | x |
|
||||
| Test.java:63:16:63:23 | source(...) | Test.java:10:82:10:82 | x |
|
||||
| Test.java:66:16:66:23 | source(...) | Test.java:7:65:7:65 | x |
|
||||
| Test.java:66:16:66:23 | source(...) | Test.java:8:65:8:65 | x |
|
||||
| Test.java:66:16:66:23 | source(...) | Test.java:9:74:9:74 | x |
|
||||
| Test.java:66:16:66:23 | source(...) | Test.java:10:82:10:82 | x |
|
||||
| Test.java:71:16:71:23 | source(...) | Test.java:7:65:7:65 | x |
|
||||
| Test.java:71:16:71:23 | source(...) | Test.java:8:65:8:65 | x |
|
||||
| Test.java:71:16:71:23 | source(...) | Test.java:9:74:9:74 | x |
|
||||
| Test.java:71:16:71:23 | source(...) | Test.java:10:82:10:82 | x |
|
||||
| Test.java:74:16:74:23 | source(...) | Test.java:7:65:7:65 | x |
|
||||
| Test.java:74:16:74:23 | source(...) | Test.java:8:65:8:65 | x |
|
||||
| Test.java:74:16:74:23 | source(...) | Test.java:9:74:9:74 | x |
|
||||
| Test.java:74:16:74:23 | source(...) | Test.java:10:82:10:82 | x |
|
||||
| Test.java:80:16:80:23 | source(...) | Test.java:7:65:7:65 | x |
|
||||
| Test.java:80:16:80:23 | source(...) | Test.java:8:65:8:65 | x |
|
||||
| Test.java:80:16:80:23 | source(...) | Test.java:9:74:9:74 | x |
|
||||
| Test.java:80:16:80:23 | source(...) | Test.java:10:82:10:82 | x |
|
||||
| Test.java:83:16:83:23 | source(...) | Test.java:9:74:9:74 | x |
|
||||
| Test.java:83:16:83:23 | source(...) | Test.java:10:82:10:82 | x |
|
||||
|
||||
Reference in New Issue
Block a user