mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
Basic extraction of record patterns
This commit is contained in:
@@ -774,6 +774,7 @@ case @expr.kind of
|
||||
| 86 = @valueeqexpr
|
||||
| 87 = @valueneexpr
|
||||
| 88 = @propertyref
|
||||
| 89 = @recordpatternexpr
|
||||
;
|
||||
|
||||
/** Holds if this `when` expression was written as an `if` expression. */
|
||||
|
||||
@@ -529,7 +529,7 @@ private module ControlFlowGraphImpl {
|
||||
or
|
||||
this instanceof LocalVariableDeclExpr and
|
||||
not this = any(InstanceOfExpr ioe).getLocalVariableDeclExpr() and
|
||||
not this = any(PatternCase pc).getDecl()
|
||||
not this = any(PatternCase pc).getPattern()
|
||||
or
|
||||
this instanceof StringTemplateExpr
|
||||
or
|
||||
@@ -971,7 +971,7 @@ private module ControlFlowGraphImpl {
|
||||
(
|
||||
if exists(pc.getGuard())
|
||||
then last(pc.getGuard(), last, BooleanCompletion(true, _))
|
||||
else last = pc.getDecl()
|
||||
else last = pc.getPattern()
|
||||
) and
|
||||
not pc.isRule() and
|
||||
completion = NormalCompletion()
|
||||
@@ -1332,7 +1332,7 @@ private module ControlFlowGraphImpl {
|
||||
last(case.(PatternCase).getGuard(), preBodyNode, completion) and
|
||||
completion = basicBooleanCompletion(true)
|
||||
) else (
|
||||
preBodyNode = case.(PatternCase).getDecl() and completion = NormalCompletion()
|
||||
preBodyNode = case.(PatternCase).getPattern() and completion = NormalCompletion()
|
||||
)
|
||||
) else (
|
||||
preBodyNode = case and completion = NormalCompletion()
|
||||
@@ -1351,7 +1351,7 @@ private module ControlFlowGraphImpl {
|
||||
result = getASuccessorSwitchCase(case)
|
||||
or
|
||||
completion = basicBooleanCompletion(true) and
|
||||
result = case.getDecl()
|
||||
result = case.getPattern()
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -1362,7 +1362,7 @@ private module ControlFlowGraphImpl {
|
||||
exists(PatternCase case, Expr guard |
|
||||
guard = case.getGuard() and
|
||||
(
|
||||
n = case.getDecl() and
|
||||
n = case.getPattern() and
|
||||
result = first(guard) and
|
||||
completion = NormalCompletion()
|
||||
or
|
||||
|
||||
@@ -82,7 +82,7 @@ predicate depends(RefType t, RefType dep) {
|
||||
or
|
||||
// the type accessed in a pattern-switch case statement in `t`.
|
||||
exists(PatternCase pc | t = pc.getEnclosingCallable().getDeclaringType() |
|
||||
usesType(pc.getDecl().getType(), dep)
|
||||
usesType(pc.getPattern().getType(), dep)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2541,3 +2541,10 @@ class NotNullExpr extends UnaryExpr, @notnullexpr {
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NotNullExpr" }
|
||||
}
|
||||
|
||||
/** A record pattern expr, as in `if (x instanceof SomeRecord(int field))`. */
|
||||
class RecordPatternExpr extends Expr, @recordpatternexpr {
|
||||
override string toString() { result = this.getType().toString() + "(...)" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RecordPatternExpr" }
|
||||
}
|
||||
|
||||
@@ -507,7 +507,7 @@ class SwitchCase extends Stmt, @case {
|
||||
class ConstCase extends SwitchCase {
|
||||
ConstCase() {
|
||||
exists(Expr e |
|
||||
e.getParent() = this and e.getIndex() >= 0 and not e instanceof LocalVariableDeclExpr
|
||||
e.getParent() = this and e.getIndex() >= 0 and not e instanceof Pattern
|
||||
)
|
||||
// For backward compatibility, we don't include `case null, default:` here, on the assumption
|
||||
// this will come as a surprise to CodeQL that predates that statement's validity.
|
||||
@@ -531,14 +531,35 @@ class ConstCase extends SwitchCase {
|
||||
override string getAPrimaryQlClass() { result = "ConstCase" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A binding or record pattern.
|
||||
*
|
||||
* Note binding patterns are represented as `LocalVariableDeclExpr`s.
|
||||
*/
|
||||
class Pattern extends Expr {
|
||||
Pattern() {
|
||||
(this.getParent() instanceof SwitchCase or this.getParent() instanceof InstanceOfExpr)
|
||||
and
|
||||
(this instanceof LocalVariableDeclExpr or this instanceof RecordPatternExpr)
|
||||
}
|
||||
|
||||
LocalVariableDeclExpr asBindingPattern() {
|
||||
result = this
|
||||
}
|
||||
|
||||
RecordPatternExpr asRecordPattern() {
|
||||
result = this
|
||||
}
|
||||
}
|
||||
|
||||
/** A pattern case of a `switch` statement */
|
||||
class PatternCase extends SwitchCase {
|
||||
LocalVariableDeclExpr patternVar;
|
||||
Pattern pattern;
|
||||
|
||||
PatternCase() { patternVar.isNthChildOf(this, 0) }
|
||||
PatternCase() { pattern.isNthChildOf(this, 0) }
|
||||
|
||||
/** Gets the variable declared by this pattern case. */
|
||||
LocalVariableDeclExpr getDecl() { result.isNthChildOf(this, 0) }
|
||||
/** Gets this case's pattern. */
|
||||
Pattern getPattern() { result.isNthChildOf(this, 0) }
|
||||
|
||||
/** Gets the guard applicable to this pattern case, if any. */
|
||||
Expr getGuard() { result.isNthChildOf(this, -3) }
|
||||
|
||||
@@ -180,7 +180,7 @@ private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
|
||||
selector = sc.getSelectorExpr() and
|
||||
(
|
||||
if sc instanceof PatternCase
|
||||
then caseblock.getFirstNode() = sc.(PatternCase).getDecl().getControlFlowNode()
|
||||
then caseblock.getFirstNode() = sc.(PatternCase).getPattern().getControlFlowNode()
|
||||
else (
|
||||
caseblock.getFirstNode() = sc.getControlFlowNode() and
|
||||
// Check there is no fall-through edge from a previous case:
|
||||
|
||||
@@ -447,7 +447,7 @@ private predicate patternCaseGuarded(Expr e, RefType t) {
|
||||
exists(PatternCase pc |
|
||||
e = getAProbableAlias([pc.getSwitch().getExpr(), pc.getSwitchExpr().getExpr()]) and
|
||||
guardControls_v1(pc, e.getBasicBlock(), true) and
|
||||
t = pc.getDecl().getType()
|
||||
t = pc.getPattern().getType()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ private predicate step(Node n1, Node n2) {
|
||||
)
|
||||
or
|
||||
exists(PatternCase pc |
|
||||
pc.getDecl() = def.(BaseSsaUpdate).getDefiningExpr() and
|
||||
pc.getPattern() = def.(BaseSsaUpdate).getDefiningExpr() and
|
||||
(
|
||||
pc.getSwitch().getExpr() = n1.asExpr()
|
||||
or
|
||||
|
||||
Reference in New Issue
Block a user