Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Unified: Handle Swift's macro expansion expr
  • Loading branch information
paldepind committed Oct 2, 2026
commit 78320a0a66872d917b025c916f570fdf642b21fe
29 changes: 25 additions & 4 deletions unified/extractor/src/languages/swift/swift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,31 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
=>
(argument name_node: (identifier #{lbl})? value: {val})
),
// An additional labeled trailing closure, such as the `c: { ... }` in
// `foo { 42 } c: { ... }`, is turned into an argument to the function.
rule!(
(multipleTrailingClosureElement label: @@label closure: @closure)
=>
(argument name_node: (identifier #{label}) value: {closure})
),
rule!(
(macroExpansionExpr

@paldepind paldepind Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think handling these as macro calls might be just fine. And if not we can always tweak later.

macroName: @@name
genericArgumentClause: (genericArgumentClause arguments: (genericArgument argument: @type_args)*)?
Comment on lines +724 to +725

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not handling moduleSelector anywhere yet, so this is consistent.

arguments: _* @args
trailingClosure: _? @trailing
additionalTrailingClosures: _* @additional)
=>
macro_call_expr {
let mut arguments = args;
arguments.extend(trailing.into_iter().map(|trailing| tree!((argument value: {trailing}))));
arguments.extend(additional);
tree!((macro_call_expr
macro_name_node: (identifier #{name})
type_argument: {type_args}
argument: {arguments}))
}
),
// Member access (`list.append`). The `declName` is itself a
// `declReferenceExpr`; pull its `baseName` out as the member identifier.
// A leading-dot access (`.foo`) has no explicit base — the base is an
Expand Down Expand Up @@ -1196,10 +1221,6 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
}
}
),
// Selector expression: `#selector(inner)` -- not yet supported
// (swift-syntax represents `#selector`/`#keyPath` and other macro
// expansions uniformly as a `macroExpansionExpr`).
rule!((macroExpansionExpr) => (unsupported_node)),
// A nominal type's `inheritanceClause` (`: Base, Proto`) becomes a list
// of `base_type`s, one per inherited type. Each declaration keyword
// gets its own rule; the bodies are identical but for the keyword.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,45 @@ top_level source="⟨body⟩"
body:
block source="⟨stmt⟩\n\n⟨stmt⟩\n\n⟨stmt⟩"
stmt:
unsupported_node "#expect(value == 42)" source="#expect(value == 42)"
unsupported_node "#custom<Int>(value) {\n value\n} completion: {\n value\n}" source="#custom<Int>(value) {\n value\n} completion: {\n value\n}"
unsupported_node "#Preview {\n let previewValue = 42\n previewValue\n}" source="#Preview {\n let previewValue = 42\n previewValue\n}"
macro_call_expr source="#⟨macro_name_node⟩(⟨argument⟩)"
macro_name_node: identifier "expect" source="expect"
argument:
argument source="⟨value⟩"
value:
binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩"
left: identifier "value" source="value"
operator: infix_operator "==" source="=="
right: int_literal "42" source="42"
macro_call_expr source="#⟨macro_name_node⟩<⟨type_argument⟩>(⟨argument⟩) ⟨argument⟩ ⟨argument⟩"
macro_name_node: identifier "custom" source="custom"
type_argument: identifier "Int" source="Int"
argument:
argument source="⟨value⟩"
value: identifier "value" source="value"
argument source="⟨value⟩"
value:
function_expr source="{\n ⟨body⟩\n}"
body:
block source="⟨stmt⟩"
stmt: identifier "value" source="value"
argument source="⟨name_node⟩: ⟨value⟩"
name_node: identifier "completion" source="completion"
value:
function_expr source="{\n ⟨body⟩\n}"
body:
block source="⟨stmt⟩"
stmt: identifier "value" source="value"
macro_call_expr source="#⟨macro_name_node⟩ ⟨argument⟩"
macro_name_node: identifier "Preview" source="Preview"
argument:
argument source="⟨value⟩"
value:
function_expr source="{\n ⟨body⟩\n}"
body:
block source="⟨stmt⟩\n ⟨stmt⟩"
stmt:
variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩"
modifier: modifier "let" source="let"
pattern: identifier "previewValue" source="previewValue"
value: int_literal "42" source="42"
identifier "previewValue" source="previewValue"
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ top_level source="⟨body⟩"
variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩"
modifier: modifier "let" source="let"
pattern: identifier "currentLine" source="currentLine"
value: unsupported_node "#line" source="#line"
value:
macro_call_expr source="#⟨macro_name_node⟩"
macro_name_node: identifier "line" source="line"
Loading