mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-29 10:05:21 +00:00
fix(swift): extract macro declarations and resolve freestanding macro calls
Swift 5.9 macros were dropped entirely. `macro stringify(...) = #externalMacro(...)` parses as a `macro_declaration` (freestanding or attached), which was in neither `function_types` nor `class_types`, so the symbol never entered the graph. A freestanding call `#stringify(...)` parses as a `macro_invocation`, not a `call_expression`, so its call edge was lost too. - Add `macro_declaration` to the Swift `function_types`. It has no `name` field, but the name is a bare `simple_identifier` child already covered by `name_fallback_child_types`, so the existing name resolution handles it; the generic `<T>` type parameter is excluded by the existing type-param scope pass (no `t` god node). - Add `macro_invocation` to `call_types` and give it a callee branch in walk_calls: a freestanding macro is a free top-level symbol (resolved by bare name, no `self` receiver). Calls inside the macro's arguments (`#stringify(helper())`) still resolve because walk_calls recurses into the invocation's children. Attached-macro *usage* (`@AddCompletion` on a type) is an attribute, not a `macro_invocation`, so it is not linked to the macro — left unresolved (fail-closed); the declaration itself is still extracted.
This commit is contained in:
1 parent
0a351eaa37
commit
f893a6e2da
3 files changed
+98
-3
No files matched your search
+8
-2
@@ -1715,9 +1715,15 @@ _SWIFT_CONFIG = LanguageConfig(
|
||||
# `protocol { ... }`; tree-sitter-swift gives it its own node type rather than
|
||||
# reusing `function_declaration`, so without it a protocol's method contract
|
||||
# is dropped and the protocol becomes an empty node.
|
||||
function_types=frozenset({"function_declaration", "protocol_function_declaration", "init_declaration", "deinit_declaration", "subscript_declaration"}),
|
||||
# `macro_declaration` is the Swift 5.9 `macro stringify(...) = #externalMacro(...)`
|
||||
# form (freestanding or attached). It has no `name` field — the name is a bare
|
||||
# `simple_identifier` child, already covered by `name_fallback_child_types` — so
|
||||
# without it the whole declaration (and its `#name` call sites) was dropped.
|
||||
function_types=frozenset({"function_declaration", "protocol_function_declaration", "init_declaration", "deinit_declaration", "subscript_declaration", "macro_declaration"}),
|
||||
import_types=frozenset({"import_declaration"}),
|
||||
call_types=frozenset({"call_expression"}),
|
||||
# `macro_invocation` is a freestanding macro call `#stringify(...)`; it is not a
|
||||
# `call_expression`, so it needs its own callee branch in walk_calls.
|
||||
call_types=frozenset({"call_expression", "macro_invocation"}),
|
||||
call_function_field="",
|
||||
call_accessor_node_types=frozenset({"navigation_expression"}),
|
||||
call_accessor_field="",
|
||||
|
||||
@@ -8765,9 +8765,18 @@ def _extract_generic(
|
||||
callee_name = _read_text(node, source)
|
||||
self_receiver = "self"
|
||||
elif config.ts_module == "tree_sitter_swift":
|
||||
# Freestanding macro call `#stringify(...)`: `macro_invocation` is
|
||||
# `# simple_identifier call_suffix`. The macro is a free top-level
|
||||
# symbol, not a method on `self`, so resolve it by bare name without
|
||||
# a receiver (an unresolved `#name` stays unresolved — fail-closed).
|
||||
if node.type == "macro_invocation":
|
||||
for child in node.children:
|
||||
if child.type == "simple_identifier":
|
||||
callee_name = _read_text(child, source)
|
||||
break
|
||||
# Swift: first child may be simple_identifier or navigation_expression
|
||||
first = node.children[0] if node.children else None
|
||||
if first:
|
||||
if node.type != "macro_invocation" and first:
|
||||
if first.type == "simple_identifier":
|
||||
callee_name = _read_text(first, source)
|
||||
# Inside a method a bare `save()` is `self.save()`.
|
||||
|
||||
Reference in new issue
Block a user