Found while fixing #1111. Out of scope for that PR, filing separately.
The WASM Julia extractor at src/extractors/julia.ts has three additional bugs surfaced by comparison with the native extractor (crates/codegraph-core/src/extractors/julia.rs), none of which are exercised by existing WASM fixtures:
1. handleAbstractDef never extracts abstract types
The tree-sitter-julia grammar nests the identifier inside type_head:
abstract_definition
type_head
identifier "AbstractShape"
Current code:
const nameNode = node.childForFieldName('name') || findChild(node, 'identifier');
findChild(node, 'identifier') only inspects direct children of abstract_definition, so it returns null for every input. As a result, no abstract type definitions are ever recorded on the WASM side — including the existing native test extracts_abstract_type (abstract type AbstractShape end) and extracts_parameterized_abstract_type_base_name (abstract type AbstractVector{T} <: AbstractArray{T,1} end).
Native fix in crates/codegraph-core/src/extractors/julia.rs handle_abstract_def falls back to find_child(node, "type_head") → find_base_name(...).
2. handleMacroDef finds wrong identifier
For macro mymac(x) x end, findChild(node, 'identifier') finds the body's x (the macro returns x), recording the macro as @x instead of @mymac. The native code uses the signature_call helper (now also present in WASM as signatureCall after #1111) to unwrap macro_definition → signature → call_expression → identifier.
3. handleCall doesn't skip the function/macro signature
Current guard:
if (node.parent?.type === 'function_definition') return;
The signature's call_expression actually has parent.type === 'signature', not function_definition. As a result, function greet(name) ... end records both a definition greet and a call named greet. The native code (julia.rs, handle_call) skips when parent.kind() == \"signature\" and the grandparent is function_definition or macro_definition. The native test does_not_record_function_signature_as_call covers this.
Acceptance criteria
Found while fixing #1111. Out of scope for that PR, filing separately.
The WASM Julia extractor at
src/extractors/julia.tshas three additional bugs surfaced by comparison with the native extractor (crates/codegraph-core/src/extractors/julia.rs), none of which are exercised by existing WASM fixtures:1.
handleAbstractDefnever extracts abstract typesThe tree-sitter-julia grammar nests the identifier inside
type_head:Current code:
findChild(node, 'identifier')only inspects direct children ofabstract_definition, so it returnsnullfor every input. As a result, no abstract type definitions are ever recorded on the WASM side — including the existing native testextracts_abstract_type(abstract type AbstractShape end) andextracts_parameterized_abstract_type_base_name(abstract type AbstractVector{T} <: AbstractArray{T,1} end).Native fix in
crates/codegraph-core/src/extractors/julia.rshandle_abstract_deffalls back tofind_child(node, "type_head") → find_base_name(...).2.
handleMacroDeffinds wrong identifierFor
macro mymac(x) x end,findChild(node, 'identifier')finds the body'sx(the macro returnsx), recording the macro as@xinstead of@mymac. The native code uses thesignature_callhelper (now also present in WASM assignatureCallafter #1111) to unwrapmacro_definition → signature → call_expression → identifier.3.
handleCalldoesn't skip the function/macro signatureCurrent guard:
The signature's
call_expressionactually hasparent.type === 'signature', notfunction_definition. As a result,function greet(name) ... endrecords both a definitiongreetand a call namedgreet. The native code (julia.rs,handle_call) skips whenparent.kind() == \"signature\"and the grandparent isfunction_definitionormacro_definition. The native testdoes_not_record_function_signature_as_callcovers this.Acceptance criteria
handle_abstract_def'stype_headfallback (reusing thefindBaseNamehelper added in Julia WASM extractor has the same parameterized-type / qualified-def / qualified-selected-import bugs that #1098 fixed in native #1111).handleMacroDefto use the existingsignatureCallhelper and guard with!base.includes('.')if module-prefixing.handleCallto skipparent === 'signature' && grandparent ∈ {function_definition, macro_definition}.extracts_abstract_type,extracts_parameterized_abstract_type_base_name,extracts_macro_def,does_not_record_function_signature_as_call.