mirror of
https://github.com/github/codeql.git
synced 2026-07-30 23:13:01 +02:00
unified: Handle assignment etc. in unresolved operator sequences
Adds rules for mapping things like `=` and `as!` to `infix_operator`s, so that they are present in the output (which for unresolved operators expects an alternating sequence of values and `infix_operator`s). For ternary operators, we expand this into _two_ unresolved infix operators, `?` and `:` respectively.
This commit is contained in:
@@ -205,6 +205,28 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
|
||||
=>
|
||||
(assign_expr target: {l} value: {r})
|
||||
),
|
||||
// In an unresolved `sequenceExpr` (below) the operator positions are not
|
||||
// only `binaryOperatorExpr`s: a plain assignment (`=`), an `as`/`is` cast
|
||||
// and the ternary `?:` can also appear unfolded. Map each to an
|
||||
// `infix_operator` (keeping its spelling) so the sequence stays a clean
|
||||
// alternation of operands and operators instead of dropping the operator
|
||||
// to an opaque `unsupported_node`. These bare nodes only occur inside an
|
||||
// unresolved sequence — folded forms are handled by the dedicated rules
|
||||
// above (assignment) and below (`ternaryExpr`).
|
||||
rule!((assignmentExpr) @op => (infix_operator #{op})),
|
||||
rule!((unresolvedAsExpr) @op => (infix_operator #{op})),
|
||||
rule!((unresolvedIsExpr) @op => (infix_operator #{op})),
|
||||
// The ternary is a three-part operator (`? thenExpr :`) that *wraps* a
|
||||
// nested expression. Splice it into `?`, the then-expression, `:` so the
|
||||
// then-expression survives as a real (traversable) operand rather than
|
||||
// being buried in an opaque token.
|
||||
rule!(
|
||||
(unresolvedTernaryExpr questionMark: @@q thenExpression: @then colon: @@c)
|
||||
=>
|
||||
expr_or_operator* {
|
||||
vec![tree!((infix_operator #{q})), then, tree!((infix_operator #{c}))]
|
||||
}
|
||||
),
|
||||
// Escape hatch: an operator chain the front-end could not resolve
|
||||
// (because it uses an operator of unknown precedence, e.g. imported from
|
||||
// another module) stays a flat `sequenceExpr`. Preserve it as an
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
func casts(_ a: Any, _ b: Int) {
|
||||
_ = a as Int .& b
|
||||
_ = a is Int .& b
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
sequenceExpr
|
||||
elements:
|
||||
discardAssignmentExpr
|
||||
wildcard: _
|
||||
assignmentExpr
|
||||
equal: =
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
unresolvedAsExpr
|
||||
asKeyword: as
|
||||
typeExpr
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ".&"
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
codeBlockItem
|
||||
item:
|
||||
sequenceExpr
|
||||
elements:
|
||||
discardAssignmentExpr
|
||||
wildcard: _
|
||||
assignmentExpr
|
||||
equal: =
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
unresolvedIsExpr
|
||||
isKeyword: is
|
||||
typeExpr
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ".&"
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
name: identifier "casts"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
trailingComma: ,
|
||||
type:
|
||||
identifierType
|
||||
name: Any
|
||||
firstName: _
|
||||
secondName: identifier "a"
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: _
|
||||
secondName: identifier "b"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
name: identifier "casts"
|
||||
parameter:
|
||||
parameter
|
||||
external_name: identifier "_"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Any"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "a"
|
||||
parameter
|
||||
external_name: identifier "_"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "b"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
unresolved_operator_sequence
|
||||
element:
|
||||
name_expr
|
||||
identifier: identifier "_"
|
||||
infix_operator "="
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
infix_operator "as"
|
||||
unsupported_node "Int"
|
||||
infix_operator ".&"
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
unresolved_operator_sequence
|
||||
element:
|
||||
name_expr
|
||||
identifier: identifier "_"
|
||||
infix_operator "="
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
infix_operator "is"
|
||||
unsupported_node "Int"
|
||||
infix_operator ".&"
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
@@ -0,0 +1,4 @@
|
||||
func casts(_ a: Any, _ b: Int) {
|
||||
_ = a as Int .& b
|
||||
_ = a is Int .& b
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
func choose(_ c: Bool, _ a: Int, _ b: Int, _ d: Int) -> Int {
|
||||
return c ? a : b .& d
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
sequenceExpr
|
||||
elements:
|
||||
declReferenceExpr
|
||||
baseName: identifier "c"
|
||||
unresolvedTernaryExpr
|
||||
colon: :
|
||||
questionMark: ?
|
||||
thenExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ".&"
|
||||
declReferenceExpr
|
||||
baseName: identifier "d"
|
||||
returnKeyword: return
|
||||
name: identifier "choose"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
trailingComma: ,
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Bool"
|
||||
firstName: _
|
||||
secondName: identifier "c"
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
trailingComma: ,
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: _
|
||||
secondName: identifier "a"
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
trailingComma: ,
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: _
|
||||
secondName: identifier "b"
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: _
|
||||
secondName: identifier "d"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
name: identifier "choose"
|
||||
parameter:
|
||||
parameter
|
||||
external_name: identifier "_"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Bool"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "c"
|
||||
parameter
|
||||
external_name: identifier "_"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "a"
|
||||
parameter
|
||||
external_name: identifier "_"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "b"
|
||||
parameter
|
||||
external_name: identifier "_"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "d"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value:
|
||||
unresolved_operator_sequence
|
||||
element:
|
||||
name_expr
|
||||
identifier: identifier "c"
|
||||
infix_operator "?"
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
infix_operator ":"
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
infix_operator ".&"
|
||||
name_expr
|
||||
identifier: identifier "d"
|
||||
@@ -0,0 +1,3 @@
|
||||
func choose(_ c: Bool, _ a: Int, _ b: Int, _ d: Int) -> Int {
|
||||
return c ? a : b .& d
|
||||
}
|
||||
@@ -92,7 +92,7 @@ top_level
|
||||
element:
|
||||
name_expr
|
||||
identifier: identifier "_"
|
||||
unsupported_node "="
|
||||
infix_operator "="
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
infix_operator ".&"
|
||||
|
||||
Reference in New Issue
Block a user