Skip to content

Commit 1e167df

Browse files
committed
unified/swift: add type and declaration-family mappings
1 parent f362707 commit 1e167df

7 files changed

Lines changed: 594 additions & 27 deletions

File tree

unified/extractor/src/languages/swift/swift.rs

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,274 @@ fn translation_rules() -> Vec<yeast::Rule> {
665665
imported_expr: {name}
666666
modifier: {..mods})
667667
),
668+
// ---- Types and classes ----
669+
// Self expression → name_expr
670+
rule!((self_expression) => (name_expr identifier: (identifier "self"))),
671+
// Super expression → super_expr
672+
rule!((super_expression) => (super_expr)),
673+
// Modifiers — unwrap to individual modifier children
674+
rule!((modifiers _* @mods) => {..mods}),
675+
rule!((attribute) @m => (modifier #{m})),
676+
rule!((visibility_modifier) @m => (modifier #{m})),
677+
rule!((function_modifier) @m => (modifier #{m})),
678+
rule!((member_modifier) @m => (modifier #{m})),
679+
rule!((mutation_modifier) @m => (modifier #{m})),
680+
rule!((ownership_modifier) @m => (modifier #{m})),
681+
rule!((property_modifier) @m => (modifier #{m})),
682+
rule!((parameter_modifier) @m => (modifier #{m})),
683+
rule!((inheritance_modifier) @m => (modifier #{m})),
684+
rule!((property_behavior_modifier) @m => (modifier #{m})),
685+
// Type annotations — unwrap
686+
rule!((type_annotation type: @inner) => {inner}),
687+
// user_type is split into simple_user_type parts.
688+
// Keep a conservative textual fallback to avoid dropping type information.
689+
rule!((user_type) @ty => (named_type_expr name: (identifier #{ty}))),
690+
// Tuple type → tuple_type_expr
691+
rule!((tuple_type element: _* @elems) => (tuple_type_expr element: {..elems})),
692+
rule!((tuple_type_item name: @name type: @ty) => (tuple_type_element name: (identifier #{name}) type: {ty})),
693+
rule!((tuple_type_item type: @ty) => (tuple_type_element type: {ty})),
694+
// Array type `[T]` → generic_type_expr with Array base
695+
rule!((array_type element: @e) => (generic_type_expr
696+
base: (named_type_expr name: (identifier "Array"))
697+
type_argument: {e})),
698+
// Dictionary type `[K: V]` → generic_type_expr with Dictionary base
699+
rule!((dictionary_type key: @k value: @v) => (generic_type_expr
700+
base: (named_type_expr name: (identifier "Dictionary"))
701+
type_argument: {k}
702+
type_argument: {v})),
703+
// Optional type `T?` → generic_type_expr with Optional base
704+
rule!((optional_type wrapped: @w) => (generic_type_expr
705+
base: (named_type_expr name: (identifier "Optional"))
706+
type_argument: {w})),
707+
// Function type `(Params) -> Ret` → function_type_expr.
708+
rule!((function_type parameter: _* @ps return_type: @ret) => (function_type_expr parameter: {..ps} return_type: {ret})),
709+
rule!((function_type_parameter name: @name type: @ty) => (parameter external_name: (identifier #{name}) type: {ty})),
710+
rule!((function_type_parameter type: @ty) => (parameter type: {ty})),
711+
// Selector expression: `#selector(inner)` -- not yet supported
712+
rule!(
713+
(selector_expression _ @inner)
714+
=>
715+
(unsupported_node)
716+
),
717+
// Key path expressions are currently unsupported.
718+
rule!((key_path_expression) => (unsupported_node)),
719+
// Inheritance specifier → base_type
720+
rule!((inheritance_specifier inherits_from: @ty) => (base_type type: {ty})),
721+
// Class declaration with body containing members
722+
rule!(
723+
(class_declaration
724+
declaration_kind: @kind
725+
name: @name
726+
body: (class_body member: _* @members)
727+
(inheritance_specifier)* @bases
728+
(modifiers)* @mods)
729+
=>
730+
(class_like_declaration
731+
modifier: (modifier #{kind})
732+
modifier: {..mods}
733+
name: (identifier #{name})
734+
base_type: {..bases}
735+
member: {..members})
736+
),
737+
// Enum class declaration: same as a regular class but with an enum body.
738+
rule!(
739+
(class_declaration
740+
declaration_kind: @kind
741+
name: @name
742+
body: (enum_class_body member: _* @members)
743+
(inheritance_specifier)* @bases
744+
(modifiers)* @mods)
745+
=>
746+
(class_like_declaration
747+
modifier: (modifier #{kind})
748+
modifier: {..mods}
749+
name: (identifier #{name})
750+
base_type: {..bases}
751+
member: {..members})
752+
),
753+
// Class declaration with empty body
754+
rule!(
755+
(class_declaration
756+
declaration_kind: @kind
757+
name: @name
758+
body: _
759+
(inheritance_specifier)* @bases
760+
(modifiers)* @mods)
761+
=>
762+
(class_like_declaration
763+
modifier: (modifier #{kind})
764+
modifier: {..mods}
765+
name: (identifier #{name})
766+
base_type: {..bases})
767+
),
768+
// Protocol declaration
769+
rule!(
770+
(protocol_declaration
771+
name: @name
772+
body: (protocol_body member: _* @members)
773+
(inheritance_specifier)* @bases
774+
(modifiers)* @mods)
775+
=>
776+
(class_like_declaration
777+
modifier: (modifier "protocol")
778+
modifier: {..mods}
779+
name: (identifier #{name})
780+
base_type: {..bases}
781+
member: {..members})
782+
),
783+
// Protocol function — return type and body statements both optional.
784+
rule!(
785+
(protocol_function_declaration
786+
name: @name
787+
(parameter)* @params
788+
return_type: _? @ret
789+
body: (block statement: _* @body_stmts)?
790+
(modifiers)* @mods)
791+
=>
792+
(function_declaration
793+
modifier: {..mods}
794+
name: (identifier #{name})
795+
parameter: {..params}
796+
return_type: {..ret}
797+
body: (block stmt: {..body_stmts}))
798+
),
799+
// Init declaration → constructor_declaration. Body statements optional;
800+
// body itself is also optional (protocol requirement).
801+
rule!(
802+
(init_declaration
803+
(parameter)* @params
804+
body: (block statement: _* @body_stmts)?
805+
(modifiers)* @mods)
806+
=>
807+
(constructor_declaration
808+
modifier: {..mods}
809+
parameter: {..params}
810+
body: (block stmt: {..body_stmts}))
811+
),
812+
// Deinit declaration → destructor_declaration. Body statements optional.
813+
rule!(
814+
(deinit_declaration
815+
body: (block statement: _* @body_stmts)
816+
(modifiers)* @mods)
817+
=>
818+
(destructor_declaration
819+
modifier: {..mods}
820+
body: (block stmt: {..body_stmts}))
821+
),
822+
// Typealias declaration
823+
rule!(
824+
(typealias_declaration name: @name value: @val (modifiers)* @mods)
825+
=>
826+
(type_alias_declaration
827+
modifier: {..mods}
828+
name: (identifier #{name})
829+
r#type: {val})
830+
),
831+
// Subscript declaration (not yet supported -- grammar needs to distinguish plain calls from subscript calls)
832+
rule!(
833+
(subscript_declaration (parameter)* @params (modifiers)* @mods)
834+
=>
835+
(unsupported_node)
836+
),
837+
// Associated type declaration (with optional bound)
838+
rule!(
839+
(associatedtype_declaration name: @name inherits_from: _? @bound (modifiers)* @mods)
840+
=>
841+
(associated_type_declaration
842+
modifier: {..mods}
843+
name: (identifier #{name})
844+
bound: {..bound})
845+
),
846+
// Protocol property declaration: translate each accessor requirement to an
847+
// accessor_declaration without a body, carrying the property name and type.
848+
// Subsequent accessors get chained_declaration (same flattening as computed properties).
849+
rule!(
850+
(protocol_property_declaration
851+
name: @pattern
852+
requirements: (protocol_property_requirements accessor: _+ @accessors)
853+
type: _? @ty
854+
(modifiers)* @mods)
855+
=>
856+
{..{
857+
let name_text = __yeast_ctx.ast.source_text(pattern.into());
858+
let mod_ids: Vec<usize> = mods.iter().map(|&m| m.into()).collect();
859+
let ty_ids: Vec<usize> = ty.iter().map(|&t| t.into()).collect();
860+
let acc_ids: Vec<usize> = accessors.iter().map(|&a| a.into()).collect();
861+
for (i, &acc_id) in acc_ids.iter().enumerate() {
862+
if i > 0 {
863+
let chained = __yeast_ctx.literal("modifier", "chained_declaration");
864+
__yeast_ctx.prepend_field(acc_id, "modifier", chained);
865+
}
866+
for &mod_id in mod_ids.iter().rev() {
867+
__yeast_ctx.prepend_field(acc_id, "modifier", mod_id);
868+
}
869+
for &ty_id in ty_ids.iter().rev() {
870+
__yeast_ctx.prepend_field(acc_id, "type", ty_id);
871+
}
872+
let ident = __yeast_ctx.literal("identifier", &name_text);
873+
__yeast_ctx.prepend_field(acc_id, "name", ident);
874+
}
875+
acc_ids
876+
}}
877+
),
878+
// getter_specifier / setter_specifier → bodyless accessor_declaration
879+
rule!((getter_specifier) => (accessor_declaration accessor_kind: (accessor_kind "get"))),
880+
rule!((setter_specifier) => (accessor_declaration accessor_kind: (accessor_kind "set"))),
881+
// protocol_property_requirements wrapper — should be consumed by above; fallback
882+
rule!((protocol_property_requirements accessor: _* @accs) => {..accs}),
883+
// Computed getter → accessor_declaration (body optional).
884+
rule!(
885+
(computed_getter body: (block statement: _* @body)?)
886+
=>
887+
(accessor_declaration
888+
accessor_kind: (accessor_kind "get")
889+
body: (block stmt: {..body}))
890+
),
891+
// Computed setter with explicit parameter name.
892+
rule!(
893+
(computed_setter parameter: @param body: (block statement: _* @body))
894+
=>
895+
(accessor_declaration
896+
accessor_kind: (accessor_kind "set")
897+
parameter: (parameter pattern: (name_pattern identifier: (identifier #{param})))
898+
body: (block stmt: {..body}))
899+
),
900+
// Computed setter without explicit parameter name; body optional.
901+
rule!(
902+
(computed_setter body: (block statement: _* @body)?)
903+
=>
904+
(accessor_declaration
905+
accessor_kind: (accessor_kind "set")
906+
body: (block stmt: {..body}))
907+
),
908+
// Computed modify → accessor_declaration
909+
rule!(
910+
(computed_modify body: (block statement: _* @body))
911+
=>
912+
(accessor_declaration
913+
accessor_kind: (accessor_kind "modify")
914+
body: (block stmt: {..body}))
915+
),
916+
// willset/didset block — spread to children
917+
rule!((willset_didset_block _* @clauses) => {..clauses}),
918+
// willset clause → accessor_declaration (body optional).
919+
rule!(
920+
(willset_clause body: (block statement: _* @body)?)
921+
=>
922+
(accessor_declaration
923+
accessor_kind: (accessor_kind "willSet")
924+
body: (block stmt: {..body}))
925+
),
926+
// didset clause → accessor_declaration (body optional).
927+
rule!(
928+
(didset_clause body: (block statement: _* @body)?)
929+
=>
930+
(accessor_declaration
931+
accessor_kind: (accessor_kind "didSet")
932+
body: (block stmt: {..body}))
933+
),
934+
// Preprocessor conditionals — unsupported
935+
rule!((diagnostic) => (unsupported_node)),
668936
// ---- Fallbacks ----
669937
rule!(
670938
(_)

unified/extractor/tests/corpus/swift/closures.txt

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,12 @@ top_level
7373
pattern:
7474
name_pattern
7575
identifier: identifier "x"
76-
type: unsupported_node "Int"
77-
return_type: unsupported_node "Int"
76+
type:
77+
named_type_expr
78+
name: identifier "Int"
79+
return_type:
80+
named_type_expr
81+
name: identifier "Int"
7882

7983
===
8084
Closure with shorthand parameters
@@ -245,11 +249,13 @@ top_level
245249
call_expr
246250
callee:
247251
member_access_expr
248-
base: unsupported_node "self"
252+
base:
253+
name_expr
254+
identifier: identifier "self"
249255
member: identifier "doThing"
250256
capture_declaration:
251257
variable_declaration
252-
modifier: unsupported_node "weak" <-- ERROR: The field variable_declaration.modifier should contain modifier, but got unsupported_node
258+
modifier: modifier "weak"
253259
pattern:
254260
name_pattern
255261
identifier: identifier "self"
@@ -363,5 +369,9 @@ top_level
363369
pattern:
364370
name_pattern
365371
identifier: identifier "x"
366-
type: unsupported_node "Int"
367-
return_type: unsupported_node "Int"
372+
type:
373+
named_type_expr
374+
name: identifier "Int"
375+
return_type:
376+
named_type_expr
377+
name: identifier "Int"

unified/extractor/tests/corpus/swift/collections.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,14 @@ top_level
8888
pattern:
8989
name_pattern
9090
identifier: identifier "xs"
91-
type: unsupported_node ": [Int]"
91+
type:
92+
generic_type_expr
93+
base:
94+
named_type_expr
95+
name: identifier "Array"
96+
type_argument:
97+
named_type_expr
98+
name: identifier "Int"
9299
value: array_literal "[]"
93100

94101
===
@@ -192,7 +199,9 @@ top_level
192199
pattern:
193200
name_pattern
194201
identifier: identifier "s"
195-
type: unsupported_node ": Set<Int>"
202+
type:
203+
named_type_expr
204+
name: identifier "Set<Int>"
196205
value:
197206
array_literal
198207
element:

unified/extractor/tests/corpus/swift/functions.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ top_level
135135
pattern:
136136
name_pattern
137137
identifier: identifier "b"
138-
return_type: unsupported_node "Int"
138+
return_type:
139+
named_type_expr
140+
name: identifier "Int"
139141

140142
===
141143
Function with named parameters
@@ -365,7 +367,9 @@ top_level
365367
pattern:
366368
name_pattern
367369
identifier: identifier "values"
368-
return_type: unsupported_node "Int"
370+
return_type:
371+
named_type_expr
372+
name: identifier "Int"
369373

370374
===
371375
Function call
@@ -554,7 +558,9 @@ top_level
554558
pattern:
555559
name_pattern
556560
identifier: identifier "x"
557-
return_type: unsupported_node "T"
561+
return_type:
562+
named_type_expr
563+
name: identifier "T"
558564

559565
===
560566
Leading-dot expression value

0 commit comments

Comments
 (0)