Skip to content

Swift: initializers are not extracted — calls inside init are attributed to the file #2379

Closed

Description

@Studnicky

Version

codebase-memory-mcp 0.11.0

Platform

macOS (Apple Silicon)

Install channel

GitHub release archive / install.sh / install.ps1

Binary variant

standard

What happened, and what did you expect?

Swift initializers are not extracted as functions. Every init produces no node, and calls made inside one are attributed to the file's module node instead. Calls from different initializers to the same callee collapse into one file-level edge, so trace_path and caller queries lose the initializer entirely.

It affects every initializer form: struct, class, convenience, failable, and initializers declared in extensions. The file parses cleanly (parse_partial_count: 0), so nothing reports the loss. Ordinary methods in the same types are attributed correctly.

The cause is that swift_func_types (internal/cbm/lang_specs.c:573) lists function_declaration, protocol_function_declaration and macro_declaration, but not init_declaration. The grammar's init_declaration also has no name field, so both definition extraction and the enclosing-function QN for calls need a name derived from the owning type.

Kotlin's secondary_constructor has the same shape and is already handled (kotlin_func_types in lang_specs.c:451, the branch in extract_defs.c:5272).

Expected: each initializer becomes a function node (for example Box.init), and its calls come from that node.

Reproduction

Inits.swift:

func helper() -> Int { 1 }
func other() -> Int { 2 }

struct Box {
    let value: Int
    init() {
        value = helper()
    }
    func read() -> Int {
        other()
    }
}

final class Holder {
    let value: Int
    init(seed: Int) {
        value = helper() + seed
    }
    convenience init() {
        self.init(seed: other())
    }
}

enum Mode {
    case on
    init?(flag: Bool) {
        if helper() > 0 { self = .on } else { return nil }
    }
}

extension Box {
    init(raw: Int) {
        value = other()
    }
}
codebase-memory-mcp cli --json index_repository '{"repo_path":"<dir>"}'
codebase-memory-mcp cli --json query_graph '{"project":"<project>","query":"MATCH (a)-[:CALLS]->(b) RETURN a.name AS caller, b.name AS callee ORDER BY caller, callee","format":"json"}'

Result on 0.11.0 (parse_partial_count: 0, 11 nodes):

["Inits.swift", "helper"]
["Inits.swift", "other"]
["read", "other"]

There are five initializers with five calls between them. None becomes a node, and their calls collapse into two edges from the file. The method read is attributed correctly. Querying for nodes whose name contains init returns only the project node.

Logs

No response

Diagnostics trajectory (memory / performance / leak issues)

No response

Project scale (if relevant)

1 file, 11 nodes, 14 edges

Confirmations

  • I searched existing issues and this is not a duplicate.
  • My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.

Proposed fix. Mirror the Kotlin secondary_constructor handling:

  • Add init_declaration to swift_func_types.
  • In extract_class_methods, name the definition from the owning type.
  • In compute_func_qn, resolve the enclosing type (init_declaration → class_body → the declaring type) so a call's enclosing QN is the initializer's.

Tests in tests/test_extraction.c, failing on the current tree, will assert a function definition and call attribution for the struct, class, convenience, failable and extension forms.

Related: #2377 covers typed-throws initializers failing to parse. That is a grammar issue. This one is extraction and reproduces with plain initializers on the current grammar, so the two fixes are independent.

Prepared with AI assistance; I reviewed and verified the reproduction and results.

Activity

  1. added
    bugSomething isn't working
    priority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.
    and removed
    windowsWindows-specific issues
    on Oct 19, 2026
  2. DeusData commented on Oct 19, 2026

    @DeusData
    Owner

    Thank you for covering the different initializer forms and separating extraction from the typed-throws grammar report. The file-level collapse of initializer calls is the key behavior to verify. The proposed ownership naming still needs review.

  3. DeusData commented on Oct 25, 2026

    @DeusData
    Owner

    Thank you for the detailed Swift initializer examples. The missing initializer nodes and calls attributed to the file still need maintainer follow-up. Sorry for the delay; I’ll follow up soon.

  4. DeusData commented on Nov 3, 2026

    @DeusData
    Owner

    Fixed on main in e0c7a1d (#2395, thanks to @Studnicky): calls inside Swift lifecycle members are now attributed to the member that makes them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions