mirror of
https://github.com/github/codeql.git
synced 2026-06-25 22:57:01 +02:00
unified/swift: add variable/property/accessor and enum mappings
This commit is contained in:
@@ -83,6 +83,209 @@ fn translation_rules() -> Vec<yeast::Rule> {
|
||||
// Blocks contain statement* directly.
|
||||
rule!((block statement: _+ @stmts) => (block stmt: {..stmts})),
|
||||
rule!((block) => (block)),
|
||||
// ---- Variables ----
|
||||
// property_binding rules — these produce variable_declaration and/or accessor_declaration
|
||||
// nodes for individual declarators. The outer property_declaration rule splices these out
|
||||
// and attaches binding/modifiers from the parent.
|
||||
|
||||
// Computed property with explicit accessors (get/set/modify) →
|
||||
// a sequence of accessor_declaration nodes, each with the property name
|
||||
// attached. Subsequent accessors will be tagged chained_declaration by
|
||||
// the outer property_declaration rule.
|
||||
rule!(
|
||||
(property_binding
|
||||
name: @pattern
|
||||
type: _? @ty
|
||||
computed_value: (computed_property accessor: _+ @accessors))
|
||||
=>
|
||||
{..{
|
||||
let name_text = __yeast_ctx.ast.source_text(pattern.into());
|
||||
let ty_ids: Vec<usize> = ty.iter().map(|&t| t.into()).collect();
|
||||
let acc_ids: Vec<usize> = accessors.iter().map(|&a| a.into()).collect();
|
||||
for &acc_id in &acc_ids {
|
||||
let ident = __yeast_ctx.literal("identifier", &name_text);
|
||||
__yeast_ctx.prepend_field(acc_id, "name", ident);
|
||||
for &ty_id in ty_ids.iter().rev() {
|
||||
__yeast_ctx.prepend_field(acc_id, "type", ty_id);
|
||||
}
|
||||
}
|
||||
acc_ids
|
||||
}}
|
||||
),
|
||||
// Computed property: shorthand getter (no explicit get/set, just statements) →
|
||||
// a single accessor_declaration with kind "get".
|
||||
rule!(
|
||||
(property_binding
|
||||
name: (pattern bound_identifier: @name)
|
||||
type: _? @ty
|
||||
computed_value: (computed_property statement: _* @body))
|
||||
=>
|
||||
(accessor_declaration
|
||||
name: (identifier #{name})
|
||||
type: {..ty}
|
||||
accessor_kind: (accessor_kind "get")
|
||||
body: (block stmt: {..body}))
|
||||
),
|
||||
// Stored property with willSet/didSet observers (initializer optional) →
|
||||
// variable_declaration followed by one accessor_declaration per observer,
|
||||
// each carrying the property name. Subsequent items are tagged
|
||||
// chained_declaration by the outer property_declaration rule.
|
||||
rule!(
|
||||
(property_binding
|
||||
name: (pattern bound_identifier: @name)
|
||||
type: _? @ty
|
||||
value: _? @val
|
||||
observers: (willset_didset_block willset: _? @ws didset: _? @ds))
|
||||
=>
|
||||
{..{
|
||||
let name_text = __yeast_ctx.ast.source_text(name.into());
|
||||
let val_ids: Vec<usize> = val.iter().map(|&v| v.into()).collect();
|
||||
let ty_ids: Vec<usize> = ty.iter().map(|&t| t.into()).collect();
|
||||
let mut obs_ids: Vec<usize> = Vec::new();
|
||||
obs_ids.extend(ws.iter().map(|&o| { let id: usize = o.into(); id }));
|
||||
obs_ids.extend(ds.iter().map(|&o| { let id: usize = o.into(); id }));
|
||||
let ident_for_var = __yeast_ctx.literal("identifier", &name_text);
|
||||
let pat = __yeast_ctx.node("name_pattern", vec![("identifier", vec![ident_for_var])]);
|
||||
let mut var_fields: Vec<(&str, Vec<usize>)> = vec![("pattern", vec![pat])];
|
||||
if !ty_ids.is_empty() {
|
||||
var_fields.push(("type", ty_ids));
|
||||
}
|
||||
if !val_ids.is_empty() {
|
||||
var_fields.push(("value", val_ids));
|
||||
}
|
||||
let var_id = __yeast_ctx.node("variable_declaration", var_fields);
|
||||
let mut result = vec![var_id];
|
||||
for obs_id in obs_ids {
|
||||
let ident = __yeast_ctx.literal("identifier", &name_text);
|
||||
__yeast_ctx.prepend_field(obs_id, "name", ident);
|
||||
result.push(obs_id);
|
||||
}
|
||||
result
|
||||
}}
|
||||
),
|
||||
// property_binding with any pattern name (identifier or destructuring)
|
||||
rule!(
|
||||
(property_binding
|
||||
name: @pattern
|
||||
type: _? @ty
|
||||
value: _? @val)
|
||||
=>
|
||||
(variable_declaration
|
||||
pattern: {pattern}
|
||||
type: {..ty}
|
||||
value: {..val})
|
||||
),
|
||||
// property_declaration: splice declarators (each may translate to multiple nodes —
|
||||
// variable_declaration and/or accessor_declaration), and attach the binding modifier
|
||||
// (let/var) and any outer modifiers to each. All children after the first additionally
|
||||
// get a synthetic chained_declaration modifier so the grouping can be recovered.
|
||||
rule!(
|
||||
(property_declaration
|
||||
binding: (value_binding_pattern mutability: @binding_kind)
|
||||
declarator: _* @decls
|
||||
(modifiers)* @mods)
|
||||
=>
|
||||
{..{
|
||||
let binding_text = __yeast_ctx.ast.source_text(binding_kind.into());
|
||||
let mod_ids: Vec<usize> = mods.iter().map(|&m| m.into()).collect();
|
||||
let decl_ids: Vec<usize> = decls.iter().map(|&d| d.into()).collect();
|
||||
for (i, &decl_id) in decl_ids.iter().enumerate() {
|
||||
if i > 0 {
|
||||
let chained = __yeast_ctx.literal("modifier", "chained_declaration");
|
||||
__yeast_ctx.prepend_field(decl_id, "modifier", chained);
|
||||
}
|
||||
for &mod_id in mod_ids.iter().rev() {
|
||||
__yeast_ctx.prepend_field(decl_id, "modifier", mod_id);
|
||||
}
|
||||
let binding_mod = __yeast_ctx.literal("modifier", &binding_text);
|
||||
__yeast_ctx.prepend_field(decl_id, "modifier", binding_mod);
|
||||
}
|
||||
decl_ids
|
||||
}}
|
||||
),
|
||||
// ---- Enums ----
|
||||
// enum_type_parameter → parameter (with optional name as pattern).
|
||||
rule!(
|
||||
(enum_type_parameter name: @name type: @ty)
|
||||
=>
|
||||
(parameter
|
||||
pattern: (name_pattern identifier: (identifier #{name}))
|
||||
type: {ty})
|
||||
),
|
||||
rule!(
|
||||
(enum_type_parameter type: @ty)
|
||||
=>
|
||||
(parameter type: {ty})
|
||||
),
|
||||
// enum_case_entry with associated values → class_like_declaration containing
|
||||
// a constructor whose parameters are the data parameters.
|
||||
rule!(
|
||||
(enum_case_entry
|
||||
name: @name
|
||||
data_contents: (enum_type_parameters parameter: _* @params))
|
||||
=>
|
||||
(class_like_declaration
|
||||
modifier: (modifier "enum_case")
|
||||
name: (identifier #{name})
|
||||
member: (constructor_declaration parameter: {..params} body: (block)))
|
||||
),
|
||||
// enum_case_entry with explicit raw value → variable_declaration with that value.
|
||||
rule!(
|
||||
(enum_case_entry name: @name raw_value: @val)
|
||||
=>
|
||||
(variable_declaration
|
||||
modifier: (modifier "enum_case")
|
||||
pattern: (name_pattern identifier: (identifier #{name}))
|
||||
value: {val})
|
||||
),
|
||||
// enum_case_entry without associated values → variable_declaration tagged enum_case.
|
||||
rule!(
|
||||
(enum_case_entry name: @name)
|
||||
=>
|
||||
(variable_declaration
|
||||
modifier: (modifier "enum_case")
|
||||
pattern: (name_pattern identifier: (identifier #{name})))
|
||||
),
|
||||
// enum_entry: flatten case entries; attach outer modifiers to each, and
|
||||
// chained_declaration on every entry after the first.
|
||||
rule!(
|
||||
(enum_entry case: _+ @cases (modifiers)* @mods)
|
||||
=>
|
||||
{..{
|
||||
let mod_ids: Vec<usize> = mods.iter().map(|&m| m.into()).collect();
|
||||
let case_ids: Vec<usize> = cases.iter().map(|&c| c.into()).collect();
|
||||
for (i, &case_id) in case_ids.iter().enumerate() {
|
||||
if i > 0 {
|
||||
let chained = __yeast_ctx.literal("modifier", "chained_declaration");
|
||||
__yeast_ctx.prepend_field(case_id, "modifier", chained);
|
||||
}
|
||||
for &mod_id in mod_ids.iter().rev() {
|
||||
__yeast_ctx.prepend_field(case_id, "modifier", mod_id);
|
||||
}
|
||||
}
|
||||
case_ids
|
||||
}}
|
||||
),
|
||||
// Plain assignment: `x = expr`
|
||||
rule!(
|
||||
(assignment operator: "=" target: (directly_assignable_expression expr: @target) result: @value)
|
||||
=>
|
||||
(assign_expr target: {target} value: {value})
|
||||
),
|
||||
// Compound assignment: `x += expr` etc.
|
||||
rule!(
|
||||
(assignment operator: @op target: (directly_assignable_expression expr: @target) result: @value)
|
||||
=>
|
||||
(compound_assign_expr target: {target} operator: (infix_operator #{op}) value: {value})
|
||||
),
|
||||
// Unwrap `type` wrapper node
|
||||
rule!((type name: @inner) => {inner}),
|
||||
// `directly_assignable_expression` is just a wrapper; unwrap it
|
||||
rule!((directly_assignable_expression expr: @inner) => {inner}),
|
||||
// Pattern with bound_identifier → name_pattern
|
||||
rule!((pattern bound_identifier: @name) => (name_pattern identifier: (identifier #{name}))),
|
||||
// Tuple pattern (destructuring)
|
||||
rule!((pattern (pattern)* @elems) => (tuple_pattern element: {..elems})),
|
||||
// ---- Fallbacks ----
|
||||
rule!(
|
||||
(_)
|
||||
|
||||
@@ -51,7 +51,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let f = { (x: Int) -> Int in x * 2 }"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "f"
|
||||
value: unsupported_node "{ (x: Int) -> Int in x * 2 }"
|
||||
|
||||
===
|
||||
Closure with shorthand parameters
|
||||
@@ -85,7 +91,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let f = { $0 + $1 }"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "f"
|
||||
value: unsupported_node "{ $0 + $1 }"
|
||||
|
||||
===
|
||||
Trailing closure
|
||||
@@ -170,7 +182,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let f = { [weak self] in self?.doThing() }"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "f"
|
||||
value: unsupported_node "{ [weak self] in self?.doThing() }"
|
||||
|
||||
===
|
||||
Multi-statement closure
|
||||
@@ -245,4 +263,10 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let f = { (x: Int) -> Int in\n let y = x + 1\n return y * 2\n}"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "f"
|
||||
value: unsupported_node "{ (x: Int) -> Int in\n let y = x + 1\n return y * 2\n}"
|
||||
|
||||
@@ -29,7 +29,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let xs = [1, 2, 3]"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "xs"
|
||||
value: unsupported_node "[1, 2, 3]"
|
||||
|
||||
===
|
||||
Empty array literal with type
|
||||
@@ -71,7 +77,14 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let xs: [Int] = []"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "xs"
|
||||
type: unsupported_node ": [Int]"
|
||||
value: unsupported_node "[]"
|
||||
|
||||
===
|
||||
Dictionary literal
|
||||
@@ -111,7 +124,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let d = [\"a\": 1, \"b\": 2]"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "d"
|
||||
value: unsupported_node "[\"a\": 1, \"b\": 2]"
|
||||
|
||||
===
|
||||
Set literal
|
||||
@@ -162,7 +181,14 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let s: Set<Int> = [1, 2, 3]"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "s"
|
||||
type: unsupported_node ": Set<Int>"
|
||||
value: unsupported_node "[1, 2, 3]"
|
||||
|
||||
===
|
||||
Tuple literal
|
||||
@@ -200,7 +226,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let t = (1, \"two\", 3.0)"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "t"
|
||||
value: tuple_expr "(1, \"two\", 3.0)"
|
||||
|
||||
===
|
||||
Subscript access
|
||||
@@ -243,7 +275,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let first = xs[0]"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "first"
|
||||
value: unsupported_node "xs[0]"
|
||||
|
||||
===
|
||||
Dictionary subscript
|
||||
@@ -286,7 +324,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let v = d[\"key\"]"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "v"
|
||||
value: unsupported_node "d[\"key\"]"
|
||||
|
||||
===
|
||||
Tuple member access
|
||||
@@ -319,4 +363,10 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let n = t.0"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "n"
|
||||
value: unsupported_node "t.0"
|
||||
|
||||
@@ -288,7 +288,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let y = x > 0 ? 1 : -1"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "y"
|
||||
value: unsupported_node "x > 0 ? 1 : -1"
|
||||
|
||||
===
|
||||
Switch statement
|
||||
|
||||
@@ -35,7 +35,14 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let x: Int? = nil"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
type: unsupported_node ": Int?"
|
||||
value: builtin_expr "nil"
|
||||
|
||||
===
|
||||
Optional chaining
|
||||
@@ -77,7 +84,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let n = obj?.foo?.bar"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "n"
|
||||
value: unsupported_node "obj?.foo?.bar"
|
||||
|
||||
===
|
||||
Force unwrap
|
||||
@@ -108,7 +121,18 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let n = opt!"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "n"
|
||||
value:
|
||||
unary_expr
|
||||
operand:
|
||||
name_expr
|
||||
identifier: identifier "opt"
|
||||
operator: postfix_operator "!"
|
||||
|
||||
===
|
||||
Nil-coalescing
|
||||
@@ -139,7 +163,19 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let n = opt ?? 0"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "n"
|
||||
value:
|
||||
binary_expr
|
||||
operator: infix_operator "??"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "opt"
|
||||
right: int_literal "0"
|
||||
|
||||
===
|
||||
Throwing function
|
||||
@@ -265,7 +301,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let result = try? foo()"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "result"
|
||||
value: unsupported_node "try? foo()"
|
||||
|
||||
===
|
||||
Try! expression
|
||||
@@ -303,4 +345,10 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let result = try! foo()"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "result"
|
||||
value: unsupported_node "try! foo()"
|
||||
|
||||
@@ -24,7 +24,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let x = 1"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
value: int_literal "1"
|
||||
|
||||
===
|
||||
Var binding
|
||||
@@ -52,7 +58,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "var x = 1"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "var"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
value: int_literal "1"
|
||||
|
||||
===
|
||||
Let with type annotation
|
||||
@@ -89,7 +101,14 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let x: Int = 1"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
type: unsupported_node ": Int"
|
||||
value: int_literal "1"
|
||||
|
||||
===
|
||||
Var without initialiser
|
||||
@@ -125,7 +144,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "var x: Int"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "var"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
type: unsupported_node ": Int"
|
||||
|
||||
===
|
||||
Tuple destructuring binding
|
||||
@@ -163,7 +188,13 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let (a, b) = pair"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern: tuple_pattern "(a, b)"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "pair"
|
||||
|
||||
===
|
||||
Multiple bindings on one line
|
||||
@@ -196,7 +227,21 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "let x = 1, y = 2"
|
||||
stmt:
|
||||
variable_declaration
|
||||
modifier: modifier "let"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
value: int_literal "1"
|
||||
variable_declaration
|
||||
modifier:
|
||||
modifier "let"
|
||||
modifier "chained_declaration"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "y"
|
||||
value: int_literal "2"
|
||||
|
||||
===
|
||||
Assignment
|
||||
@@ -220,7 +265,12 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "x = 1"
|
||||
stmt:
|
||||
assign_expr
|
||||
target:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
value: int_literal "1"
|
||||
|
||||
===
|
||||
Compound assignment
|
||||
@@ -244,4 +294,10 @@ source_file
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt: unsupported_node "x += 1"
|
||||
stmt:
|
||||
compound_assign_expr
|
||||
operator: infix_operator "+="
|
||||
target:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
value: int_literal "1"
|
||||
|
||||
Reference in New Issue
Block a user