From 0062954fcba2a7b4e808ab4f518ee3e8977c5200 Mon Sep 17 00:00:00 2001 From: Derek Clair Date: Thu, 3 Sep 2026 23:38:51 -0600 Subject: [PATCH 1/2] feat: add Elixir language support (.ex / .exs) Index Elixir modules, functions/macros (with arity identity and multi-clause grouping), structs, types, protocols, and alias/import/require/use. Remote Mod.fun calls resolve through aliases, pipes and &fun/arity captures are followed, and static GenServer.call/cast plus apply/spawn MFA targets link when the module is named in source. Closes #1219. --- .claude/skills/agent-eval/corpus.json | 23 + CHANGELOG.md | 2 + README.md | 4 +- __tests__/elixir-arity-resolution.test.ts | 118 +++ __tests__/extraction.test.ts | 310 +++++++ assets/languages/elixir.svg | 7 + docs/design/framework-coverage.md | 18 +- docs/design/rust-kernel-migration-plan.md | 1 + src/extraction/grammars.ts | 14 +- src/extraction/index.ts | 4 + src/extraction/languages/elixir.ts | 863 ++++++++++++++++++++ src/extraction/languages/index.ts | 2 + src/extraction/tree-sitter-helpers.ts | 2 +- src/extraction/tree-sitter.ts | 26 + src/extraction/wasm/tree-sitter-elixir.wasm | Bin 0 -> 1412267 bytes src/graph/named-symbol-flow.ts | 7 + src/resolution/index.ts | 2 +- src/resolution/name-matcher.ts | 73 +- src/types.ts | 1 + 19 files changed, 1455 insertions(+), 22 deletions(-) create mode 100644 __tests__/elixir-arity-resolution.test.ts create mode 100644 assets/languages/elixir.svg create mode 100644 src/extraction/languages/elixir.ts create mode 100644 src/extraction/wasm/tree-sitter-elixir.wasm diff --git a/.claude/skills/agent-eval/corpus.json b/.claude/skills/agent-eval/corpus.json index 150b4a601..9b5a10e69 100644 --- a/.claude/skills/agent-eval/corpus.json +++ b/.claude/skills/agent-eval/corpus.json @@ -493,6 +493,29 @@ "question": "How does a PUBLISH packet from an MQTT client reach the sessions of matching subscribers? Trace the flow from the connection/channel layer through the broker's routing to session delivery." } ], + "Elixir": [ + { + "name": "plug", + "repo": "https://github.com/elixir-plug/plug", + "size": "Small", + "files": "~80", + "question": "How does Plug.Builder compile a plug pipeline so a Conn reaches each plug's call/2 in order? Trace from use Plug.Builder through the compiled call/2." + }, + { + "name": "phoenix", + "repo": "https://github.com/phoenixframework/phoenix", + "size": "Medium", + "files": "~240", + "question": "How does an HTTP request arriving at Phoenix.Endpoint reach a controller action through the router and the controller pipeline?" + }, + { + "name": "blockscout", + "repo": "https://github.com/blockscout/blockscout", + "size": "Large", + "files": "~2500", + "question": "How does BlockScout fetch a newly imported block from the Ethereum JSON-RPC client and persist it so the block page can serve it? Trace from the indexer fetcher through the import pipeline to the schema." + } + ], "Solidity": [ { "name": "solmate", diff --git a/CHANGELOG.md b/CHANGELOG.md index 1815c4150..cb8899468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### New Features +- CodeGraph now indexes **Elixir** (`.ex`, `.exs`) — modules, functions and macros (with clauses and arities of the same name grouped as one symbol), `defp` visibility, `@spec` signatures, `@doc` docs, structs with their fields, `@type`/`@opaque` aliases, protocols and implementations, plus `alias`/`import`/`require`/`use`. Cross-module `Mod.fun(...)` calls resolve through aliases, `|>` pipes and `&fun/arity` captures are followed, `apply`/`spawn` that name a module and function as arguments link to that function, `GenServer.call/cast` on this module reaches `handle_call`/`handle_cast`, and `@behaviour` names the callback module. Re-index Elixir projects after upgrading. + - **A busy screen's picture is laid out by the parts of the screen.** A screen is a set of handlers with no order between them, so on a hub screen the old rows-by-distance collapsed into one enormous row — the main screen of one app put 89 boxes side by side on a canvas over 28,000px wide, every line a near-horizontal sweep across all of it. The Steps tab now groups a screen's picture by region — the component that owns each handler, named in a small caption over its boxes — with each region a column where a step sits above what it sets in motion, tiled in the screen's own source order. At rest the picture hides only two things: the screen's own fan-out — one line into each region stands in for it — and lines that point back up; every other line draws where it leads, between two regions included, and selecting a step brings out its whole story in the side panel, link by link. A box nothing points at is the screen's own doing — run on render or mount, or from a binding written inline — the key says so, and selecting it lights its line from the screen with what fires it. The same app's widest screen now lays out under 3,500px with every line local, and the whole picture fits on screen when it opens. Endpoints, handlers and the in-order reading are untouched, and nothing needs a re-index: the regions come from the same walk that draws the steps. - **Where the code chooses, the picture says so once.** A helper that ends `return (await hasSeenWelcome(id)) ? '/home/' : '/welcome/'` sends the app to one of two screens, but the Steps picture drew that as two separate arrows, each carrying the whole condition with one of them negated and both cut off at the same forty characters — and before you clicked anything, neither arrow was labelled at all, so nothing said it was a choice. Now sibling arrows out of one box that are the arms of one `if`, `switch` or ternary are drawn as the choice they are: the condition is written once under the box that decides it, and each arrow out says only which way it is — `yes`, `no`, or a case's own value. They are the only arrows labelled before you select anything, so the picture reads at a glance without becoming a wall of text. A one-sided guard — an early exit, an `if` with only one side drawn — still carries its condition on the arrow, and an arrow that is reached whether or not the condition holds never claims a side. Nothing needs a re-index: the decision is read from the source at request time. diff --git a/README.md b/README.md index a73d3b2bc..ad983d673 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ Every language below gets the same treatment — full structural extraction and COBOL Visual Basic .NET Erlang + Elixir Solidity Terraform / OpenTofu Nix @@ -289,7 +290,7 @@ CodeGraph's parsing engine is a **native Rust kernel**: 20 languages — TypeScr | **Full-Text Search** | Find code by name instantly across your entire codebase, powered by FTS5 | | **Impact Analysis** | Trace callers, callees, and the full impact radius of any symbol before making changes | | **Always Fresh** | File watcher uses native OS events (FSEvents/inotify/ReadDirectoryChangesW) with debounced auto-sync — the graph stays current as you code, zero config | -| **20+ Languages** | TypeScript, JavaScript, ArkTS, Python, Go, Rust, Java, C#, VB.NET, PHP, Ruby, C, C++, CUDA, Objective-C, Metal, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Nix, Erlang, CFML, COBOL, Solidity, Terraform/OpenTofu, Svelte, Vue, Astro, Liquid, Pascal/Delphi | +| **20+ Languages** | TypeScript, JavaScript, ArkTS, Python, Go, Rust, Java, C#, VB.NET, PHP, Ruby, C, C++, CUDA, Objective-C, Metal, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Nix, Erlang, Elixir, CFML, COBOL, Solidity, Terraform/OpenTofu, Svelte, Vue, Astro, Liquid, Pascal/Delphi | | **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across 17 frameworks | | **Mixed iOS / React Native / Expo** | Closes cross-language flows that static parsing misses: Swift ↔ ObjC bridging, React Native legacy bridge + TurboModules + Fabric view components, native → JS event emitters, Expo Modules | | **100% Local** | No data leaves your machine. No API keys. No external services. SQLite database only | @@ -896,6 +897,7 @@ is written): | COBOL | `.cbl`, `.cob`, `.cpy` | Full support (programs, sections/paragraphs with PERFORM/GO TO call edges, CALL 'literal' cross-program calls, COPY copybook imports — including standalone `.cpy` files — DATA DIVISION records/fields/88-levels, EXEC CICS LINK/XCTL and EXEC SQL INCLUDE targets; fixed and free format) | | Visual Basic .NET | `.vb` | Full support (classes, Modules, interfaces, structures, enums, properties, events, `Declare` P/Invoke, `Handles`/`WithEvents`, `Inherits`/`Implements` edges, call edges through VB's call/index paren ambiguity, `As New` instantiation, interpolated strings, LINQ, Unicode identifiers) | | Erlang | `.erl`, `.hrl`, `.escript`, `.app.src`, `.app` | Full support (functions with multi-clause/multi-arity grouping, `-spec` signatures, records with fields, `-type`/`-opaque` aliases, `-define` macros, `-include`/`-include_lib`/`-import` edges, local and `mod:fn` remote call edges, `fun name/arity` references, `spawn`/`apply`/`proc_lib`/`timer`/`rpc` MFA-argument call edges, `gen_server:call/cast(?MODULE)` → own `handle_call`/`handle_cast` links, `-behaviour` links, `-export`-based visibility) | +| Elixir | `.ex`, `.exs` | Full support (modules with nested `defmodule`, functions and macros with multi-clause/multi-arity grouping, `defp` visibility, `@spec` signatures and `@doc`/`@moduledoc`, `defstruct` fields, `@type`/`@typep`/`@opaque` aliases, `defprotocol`/`defimpl`, `alias`/`import`/`require`/`use` edges with alias expansion on calls, local and `Mod.fun` remote call edges including `|>` pipes and `&fun/arity` captures, `apply`/`spawn` MFA-argument call edges, `GenServer.call/cast(__MODULE__)` → own `handle_call`/`handle_cast` links, `@behaviour` links, `defdelegate`) | | Solidity | `.sol` | Full support (contracts, libraries, interfaces, structs, enums, modifiers, events, errors, state variables, `import`/`using` directives, `emit`/`revert` calls) | | Terraform / OpenTofu | `.tf`, `.tfvars`, `.tofu` | Full support (resources, data sources, modules, variables, outputs, providers incl. aliases, `locals`; `var.`/`local.`/`module.`/resource references with Terraform's per-directory scoping enforced; module calls bridged across the boundary — inputs to the child module's variables, `module.M.out` to the child's output, `source` to the module's files; cloudposse/atmos `remote-state` cross-component wiring when the component is statically named; `provider = aws.east` selections resolved up the module tree; `moved`/`import`/`removed`/`check` block references; `.tfvars` assignments linked to the variables they set) | | Nix | `.nix` | Full support (functions with simple/destructured/curried params, `let`/attrset bindings, `inherit`, `import ./path` file edges — `./dir` resolving through `default.nix` — plus NixOS module `imports = [ ./x.nix ]` lists and `callPackage ./pkg.nix` file edges; call edges; module-system option wiring — a config write like `launchd.user.agents.x = { ... }` links to the module declaring `options.launchd.user.agents`, so option flows trace across modules) | diff --git a/__tests__/elixir-arity-resolution.test.ts b/__tests__/elixir-arity-resolution.test.ts new file mode 100644 index 000000000..faa74bc6d --- /dev/null +++ b/__tests__/elixir-arity-resolution.test.ts @@ -0,0 +1,118 @@ +/** + * Elixir arity-aware resolution. + * + * Arity is part of a function's identity: `f/1` and `f/2` are unrelated + * definitions. Extraction gives each arity its own node (`Mod::f/1`) and + * stamps refs with the call-site arity; resolution must land each ref on the + * def of exactly that arity — except default-args (`def foo(a, b \\ 1)`), + * which index as the max arity and accept a shorter call when that file + * defines exactly one function of the name. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import * as os from 'node:os'; +import { CodeGraph } from '../src'; + +describe('elixir arity-aware resolution', () => { + let dir: string; + beforeEach(() => { dir = fs.mkdtempSync(path.join(os.tmpdir(), 'elixir-arity-')); }); + afterEach(() => { fs.rmSync(dir, { recursive: true, force: true }); }); + + async function callEdges(d: string): Promise> { + const cg = await CodeGraph.init(d, { silent: true }); + await cg.indexAll(); + const db = (cg as any).db.db; + const rows = db + .prepare( + `SELECT s.qualified_name sq, t.qualified_name tq + FROM edges e JOIN nodes s ON s.id = e.source JOIN nodes t ON t.id = e.target + WHERE e.kind IN ('calls','references') AND s.kind = 'function'` + ) + .all(); + cg.destroy(); + return rows; + } + + it('resolves the f/N -> f/N+1 delegation to a real edge, not a self-loop', async () => { + fs.mkdirSync(path.join(dir, 'lib'), { recursive: true }); + fs.writeFileSync( + path.join(dir, 'lib', 'deleg.ex'), + `defmodule Deleg do + def header(name, req) do + header(name, req, nil) + end + + def header(name, headers, default) do + Map.get(headers, name, default) + end +end +` + ); + const edges = await callEdges(dir); + expect(edges).toContainEqual({ sq: 'Deleg::header/2', tq: 'Deleg::header/3' }); + expect(edges.some((e) => e.sq === e.tq && e.sq.startsWith('Deleg::header'))).toBe(false); + }); + + it('resolves remote calls to the called arity and refuses a sibling arity', async () => { + fs.mkdirSync(path.join(dir, 'lib'), { recursive: true }); + fs.writeFileSync( + path.join(dir, 'lib', 'store.ex'), + `defmodule Store do + def get(k), do: get(k, nil) + def get(k, default), do: {k, default} +end +` + ); + fs.writeFileSync( + path.join(dir, 'lib', 'client.ex'), + `defmodule Client do + def fetch(k), do: Store.get(k, nil) + def broken(k), do: Store.get(k, nil, :extra) +end +` + ); + const edges = await callEdges(dir); + expect(edges).toContainEqual({ sq: 'Client::fetch/1', tq: 'Store::get/2' }); + expect(edges.some((e) => e.sq === 'Client::broken/1' && e.tq.startsWith('Store::get'))).toBe(false); + }); + + it('resolves a shorter call onto a default-args def when it is the only arity', async () => { + fs.mkdirSync(path.join(dir, 'lib'), { recursive: true }); + fs.writeFileSync( + path.join(dir, 'lib', 'opts.ex'), + `defmodule Opts do + def get(id, opts \\\\ []) do + {id, opts} + end + + def run(id), do: get(id) +end +` + ); + const edges = await callEdges(dir); + expect(edges).toContainEqual({ sq: 'Opts::run/1', tq: 'Opts::get/2' }); + }); + + it('resolves aliased remote calls across files', async () => { + fs.mkdirSync(path.join(dir, 'lib'), { recursive: true }); + fs.writeFileSync( + path.join(dir, 'lib', 'repo.ex'), + `defmodule MyApp.Repo do + def get(schema, id), do: {schema, id} +end +` + ); + fs.writeFileSync( + path.join(dir, 'lib', 'accounts.ex'), + `defmodule MyApp.Accounts do + alias MyApp.Repo + + def get_user(id), do: Repo.get(User, id) +end +` + ); + const edges = await callEdges(dir); + expect(edges).toContainEqual({ sq: 'MyApp.Accounts::get_user/1', tq: 'MyApp.Repo::get/2' }); + }); +}); diff --git a/__tests__/extraction.test.ts b/__tests__/extraction.test.ts index ad0ba2374..fbaa07611 100644 --- a/__tests__/extraction.test.ts +++ b/__tests__/extraction.test.ts @@ -150,6 +150,17 @@ describe('Language Detection', () => { expect(isSourceFile('default.nix')).toBe(true); }); + it('should detect Elixir files', () => { + expect(detectLanguage('lib/my_app/accounts.ex')).toBe('elixir'); + expect(detectLanguage('mix.exs')).toBe('elixir'); + expect(detectLanguage('test/my_app_test.exs')).toBe('elixir'); + expect(detectLanguage('config/config.exs')).toBe('elixir'); + expect(isSourceFile('lib/my_app.ex')).toBe(true); + expect(isSourceFile('mix.exs')).toBe(true); + expect(isLanguageSupported('elixir')).toBe(true); + expect(getSupportedLanguages()).toContain('elixir'); + }); + it('should detect a .h whose only C++ signal is an export-macro class as cpp', () => { // Lean Unreal-Engine style header: the class is annotated with an export // macro and carries no explicit `public:`/`virtual`/`namespace`/`template`, @@ -252,6 +263,8 @@ describe('Language Support', () => { expect(languages).toContain('dart'); expect(languages).toContain('solidity'); expect(languages).toContain('nix'); + expect(languages).toContain('elixir'); + expect(languages).toContain('erlang'); }); }); @@ -10939,6 +10952,303 @@ init(_) -> {ok, #{}}. }); }); +describe('Elixir Extraction', () => { + describe('Language detection', () => { + it('should report Elixir as supported', () => { + expect(isLanguageSupported('elixir')).toBe(true); + expect(getSupportedLanguages()).toContain('elixir'); + expect(isSourceFile('lib/foo.ex')).toBe(true); + expect(isSourceFile('mix.exs')).toBe(true); + }); + }); + + describe('Module and function extraction', () => { + it('should extract defmodule, public and private functions with arity-qualified names', () => { + const code = `defmodule MyApp.Accounts do + def get_user(id) do + id + end + + defp normalize(name) do + name + end +end +`; + const result = extractFromSource('lib/accounts.ex', code); + const mod = result.nodes.find((n) => n.kind === 'module'); + expect(mod?.name).toBe('MyApp.Accounts'); + const getUser = result.nodes.find((n) => n.kind === 'function' && n.name === 'get_user'); + const normalize = result.nodes.find((n) => n.kind === 'function' && n.name === 'normalize'); + expect(getUser?.qualifiedName).toBe('MyApp.Accounts::get_user/1'); + expect(getUser?.isExported).toBe(true); + expect(normalize?.qualifiedName).toBe('MyApp.Accounts::normalize/1'); + expect(normalize?.isExported).toBe(false); + expect(normalize?.visibility).toBe('private'); + expect(getUser?.language).toBe('elixir'); + }); + + it('should nest an inner defmodule under its parent', () => { + const code = `defmodule Foo do + defmodule Bar do + def baz, do: :ok + end +end +`; + const result = extractFromSource('lib/foo.ex', code); + const mods = result.nodes.filter((n) => n.kind === 'module').map((n) => n.name).sort(); + expect(mods).toEqual(['Foo', 'Foo.Bar']); + const baz = result.nodes.find((n) => n.name === 'baz'); + expect(baz?.qualifiedName).toBe('Foo.Bar::baz/0'); + }); + + it('should merge multi-clause functions of the same arity into one node', () => { + const code = `defmodule M do + def classify(:a), do: :atom + def classify(:b), do: :atom + def classify(_), do: :other +end +`; + const result = extractFromSource('lib/m.ex', code); + const fns = result.nodes.filter((n) => n.kind === 'function' && n.name === 'classify'); + expect(fns).toHaveLength(1); + expect(fns[0]!.startLine).toBe(2); + expect(fns[0]!.endLine).toBe(4); + expect(fns[0]!.qualifiedName).toBe('M::classify/1'); + }); + + it('should give same-name different-arity functions separate nodes', () => { + const code = `defmodule Gap do + def f(x), do: x + 1 + def f(x, y), do: x + y +end +`; + const result = extractFromSource('lib/gap.ex', code); + const fns = result.nodes.filter((n) => n.kind === 'function' && n.name === 'f'); + expect(fns).toHaveLength(2); + expect(fns.map((n) => n.qualifiedName).sort()).toEqual(['Gap::f/1', 'Gap::f/2']); + }); + + it('should attach @spec and @doc to the following function', () => { + const code = `defmodule M do + @doc "Fetches a value by key." + @spec fetch(binary()) :: {:ok, term()} | :not_found + def fetch(key) do + lookup(key) + end + + defp lookup(_k), do: :not_found +end +`; + const result = extractFromSource('lib/m.ex', code); + const fetch = result.nodes.find((n) => n.name === 'fetch'); + expect(fetch?.signature).toContain('@spec fetch(binary())'); + expect(fetch?.docstring).toBe('Fetches a value by key.'); + }); + + it('should fall back to the clause header as the signature', () => { + const code = `defmodule M do + def resize(w, h) when w > 0 and h > 0 do + {w, h} + end +end +`; + const result = extractFromSource('lib/m.ex', code); + const resize = result.nodes.find((n) => n.name === 'resize'); + expect(resize?.signature).toContain('def resize(w, h) when w > 0 and h > 0'); + }); + }); + + describe('Types, structs, protocols', () => { + it('should extract defstruct fields onto the enclosing module', () => { + const code = `defmodule User do + defstruct [:name, age: 0] +end +`; + const result = extractFromSource('lib/user.ex', code); + const fields = result.nodes.filter((n) => n.kind === 'field').map((n) => n.name).sort(); + expect(fields).toEqual(['age', 'name']); + }); + + it('should extract @type / @typep / @opaque as type aliases', () => { + const code = `defmodule M do + @type t :: atom() | binary() + @typep internal :: reference() + @opaque handle() :: reference() +end +`; + const result = extractFromSource('lib/m.ex', code); + const aliases = result.nodes.filter((n) => n.kind === 'type_alias').map((n) => n.name).sort(); + expect(aliases).toEqual(['handle', 'internal', 't']); + }); + + it('should extract defprotocol as an interface and defimpl as implements', () => { + const code = `defprotocol Drawable do + def draw(data) +end + +defimpl Drawable, for: User do + def draw(user), do: user.name +end +`; + const result = extractFromSource('lib/drawable.ex', code); + const proto = result.nodes.find((n) => n.kind === 'interface'); + expect(proto?.name).toBe('Drawable'); + const draw = result.nodes.filter((n) => n.name === 'draw'); + expect(draw.length).toBeGreaterThanOrEqual(1); + const impl = result.unresolvedReferences.find((r) => r.referenceKind === 'implements'); + expect(impl?.referenceName).toBe('Drawable'); + }); + }); + + describe('Import extraction', () => { + it('should extract alias, import, require, and use', () => { + const code = `defmodule M do + use GenServer + alias MyApp.Repo + alias MyApp.Accounts.User + import Ecto.Query + require Logger +end +`; + const result = extractFromSource('lib/m.ex', code); + const imports = result.nodes.filter((n) => n.kind === 'import').map((n) => n.name); + expect(imports).toContain('GenServer'); + expect(imports).toContain('MyApp.Repo'); + expect(imports).toContain('MyApp.Accounts.User'); + expect(imports).toContain('Ecto.Query'); + expect(imports).toContain('Logger'); + const refs = result.unresolvedReferences.filter((r) => r.referenceKind === 'imports').map((r) => r.referenceName); + expect(refs).toContain('MyApp.Repo'); + }); + }); + + describe('Call extraction', () => { + it('should record local calls with arity and remote calls module-qualified', () => { + const code = `defmodule M do + def run(x) do + y = prepare(x) + Other.process(y) + end + + defp prepare(x), do: x +end +`; + const result = extractFromSource('lib/m.ex', code); + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls).toContain('prepare/1'); + expect(calls).toContain('Other::process/1'); + }); + + it('should expand aliases on remote calls', () => { + const code = `defmodule M do + alias MyApp.Repo + alias Foo.Bar, as: Baz + + def go(id) do + Repo.get(User, id) + Baz.qux() + end +end +`; + const result = extractFromSource('lib/m.ex', code); + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls).toContain('MyApp.Repo::get/2'); + expect(calls).toContain('Foo.Bar::qux/0'); + }); + + it('should count piped calls with +1 arity and capture &fun/arity', () => { + const code = `defmodule M do + def piped(list) do + list + |> Enum.map(&String.upcase/1) + |> join() + end + + defp join(s), do: s +end +`; + const result = extractFromSource('lib/m.ex', code); + const refs = result.unresolvedReferences; + const calls = refs.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + const captures = refs.filter((r) => r.referenceKind === 'references').map((r) => r.referenceName); + expect(calls).toContain('Enum::map/2'); + expect(calls).toContain('join/1'); + expect(captures).toContain('String::upcase/1'); + }); + + it('should treat __MODULE__.fun as a local call and link GenServer.dispatch', () => { + const code = `defmodule Kv do + def get(key) do + GenServer.call(__MODULE__, {:get, key}) + end + + def handle_call({:get, k}, _from, state), do: {:reply, k, state} + + def kick, do: __MODULE__.get(:x) +end +`; + const result = extractFromSource('lib/kv.ex', code); + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls).toContain('handle_call/3'); + expect(calls).toContain('get/1'); + }); + + it('should lift static apply/spawn MFA arguments into call refs', () => { + const code = `defmodule M do + def boot(req) do + apply(Other, :handle, [req]) + spawn(M, :work, [req, :ok]) + end + + def work(_a, _b), do: :ok +end +`; + const result = extractFromSource('lib/m.ex', code); + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls).toContain('Other::handle/1'); + expect(calls).toContain('work/2'); + }); + + it('should stay silent on dynamic remote calls', () => { + const code = `defmodule M do + def run(mod) do + mod.handle(x) + end +end +`; + const result = extractFromSource('lib/m.ex', code); + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls.some((c) => c.includes('handle'))).toBe(false); + }); + + it('should emit a calls ref for defdelegate targets', () => { + const code = `defmodule M do + defdelegate count(), to: Repo +end +`; + const result = extractFromSource('lib/m.ex', code); + const count = result.nodes.find((n) => n.name === 'count'); + expect(count?.qualifiedName).toBe('M::count/0'); + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls).toContain('Repo::count/0'); + }); + }); + + describe('Behaviours', () => { + it('should emit an implements reference for @behaviour', () => { + const code = `defmodule M do + @behaviour MyApp.Worker + + def init(_), do: {:ok, %{}} +end +`; + const result = extractFromSource('lib/m.ex', code); + const impl = result.unresolvedReferences.find((r) => r.referenceKind === 'implements'); + expect(impl?.referenceName).toBe('MyApp.Worker'); + }); + }); +}); + describe('Terraform Extraction', () => { describe('Language detection', () => { it('should detect Terraform files', () => { diff --git a/assets/languages/elixir.svg b/assets/languages/elixir.svg new file mode 100644 index 000000000..6b4d377a2 --- /dev/null +++ b/assets/languages/elixir.svg @@ -0,0 +1,7 @@ + + Elixir + + + + ELIXIR + diff --git a/docs/design/framework-coverage.md b/docs/design/framework-coverage.md index abf6a2346..4367780b2 100644 --- a/docs/design/framework-coverage.md +++ b/docs/design/framework-coverage.md @@ -97,7 +97,19 @@ gets no Screens picture at all today: The Vue name-index (`VueAppRoutes.byName`) is the closest existing precedent for all of these. -### 3. Native UI — no route nodes at all +### 3. Phoenix — Elixir now indexes, the router does not + +Elixir extraction is in (`defmodule` / `def` / `alias` / `Mod.fun` / `|>` / +`GenServer.call`). **Missing:** Phoenix and Phoenix LiveView **route nodes**. +`scope "/", AppWeb do get "/", PageController, :index end`, `live "/x", FooLive`, +and `push_navigate(to: "/x")` / `<.link navigate={...}>` are unread, so a Phoenix +app has no Entry points and no Screens tab. Same shape as Rails `routes.rb`: a +router DSL whose destinations are controller-or-LiveView modules, not file paths. + +**Validate on:** `phoenixframework/phoenix` (the framework itself) and any +`phx.new` app, or BlockScout / Plausible. + +### 4. Native UI — no route nodes at all | Platform | Routes would come from | Navigation would come from | |---|---|---| @@ -110,7 +122,7 @@ All three are named in `scripts/try-repo.sh`'s presets as not modelled both name routes with string literals, which is the same shape every router above reads. -### 4. ArkTS / HarmonyOS — closest to done of anything here +### 5. ArkTS / HarmonyOS — closest to done of anything here **Has:** the hard half already. `arkuiRouterEdges` in `callback-synthesizer.ts` resolves `router.pushUrl('/pages/Detail')` to the @@ -136,7 +148,7 @@ Objective-C. the first two inherit the C rules and the third has none.) **No rules** — boxes draw, arrows carry no condition, and no arguments or -trigger labels are read: PHP, Ruby, Rust, Scala, Dart, Erlang, Lua, Luau, R, +trigger labels are read: PHP, Ruby, Rust, Scala, Dart, Erlang, Elixir, Lua, Luau, R, Solidity, COBOL, CFML, VB.NET, Nix, Terraform, Pascal/Delphi, Liquid, Razor, Twig, ArkTS, and the `.svelte` / `.vue` / `.astro` template languages. diff --git a/docs/design/rust-kernel-migration-plan.md b/docs/design/rust-kernel-migration-plan.md index 14ed2673e..8b265a0cb 100644 --- a/docs/design/rust-kernel-migration-plan.md +++ b/docs/design/rust-kernel-migration-plan.md @@ -644,6 +644,7 @@ parity before porting the language. | vbnet | `languages/vbnet.ts` | T2 | **vendored, patched + external scanner** | Our wasm is a patched grammar WITH a C external scanner — the kernel must build that scanner; ts-cli 0.24 dropped `\p{...}` classes during the original build (#1164). Highest grammar-build risk of any language. | ☐ | | cobol | `languages/cobol.ts` | T2 | **vendored fork** | Paragraph-extent reconstruction + copybook resolution are extraction logic (#1161, CardDemo 43/44). Port carefully or keep TS post-pass. | ☐ | | erlang | `languages/erlang.ts` | T2 | **vendored (WhatsApp/ELP)** | npm `tree-sitter-erlang` is HIJACKED — never source from it (#1165). gen_server dispatch is synthesis-side (fine). | ☐ | +| elixir | `languages/elixir.ts` | T2 | **vendored (elixir-lang 0.3.5)** | Everything is a `call` node — defs/directives live in visitNode, calls in extractCall; alias maps are per-module. GenServer/MFA is extraction-side. | ☐ | | nix | `languages/nix.ts` | T2 | **vendored (ABI-15 rebuild)** | Option-path synthesizer is synthesis-side; the `===`-always-false → `.equals()` lesson (#1190) is wasm-binding-specific and disappears natively — still gate on nixpkgs (44k files). | ☐ | | solidity | `languages/solidity.ts` | T2 | **vendored** | `modifier_invocation` outside body walk (#1170) is extraction-side; port it. | ☐ | | terraform | `languages/terraform.ts` | T2 | **vendored** | `:`-scoped refs for module-boundary bridging (#1173); metadata does NOT persist — re-read source (#1174). | ☐ | diff --git a/src/extraction/grammars.ts b/src/extraction/grammars.ts index c7710f200..6c80f5089 100644 --- a/src/extraction/grammars.ts +++ b/src/extraction/grammars.ts @@ -46,6 +46,7 @@ const WASM_GRAMMAR_FILES: Record = { cobol: 'tree-sitter-cobol.wasm', vbnet: 'tree-sitter-vbnet.wasm', erlang: 'tree-sitter-erlang.wasm', + elixir: 'tree-sitter-elixir.wasm', solidity: 'tree-sitter-solidity.wasm', terraform: 'tree-sitter-terraform.wasm', arkts: 'tree-sitter-arkts.wasm', @@ -162,6 +163,11 @@ export const EXTENSION_MAP: Record = { // (`.app`/`.app.src` resource files route via isErlangAppFile below: their // last-dot extension is too generic for this map.) '.escript': 'erlang', + // Elixir: modules (.ex) and scripts/tests/config (.exs). Mix + Phoenix. + // Vendored elixir-lang/tree-sitter-elixir 0.3.5 (Apache-2.0, ABI 14) — + // tree-sitter-wasms does not ship it; the npm package includes the wasm. + '.ex': 'elixir', + '.exs': 'elixir', // Spring config: `application.properties` / `application-*.properties`. Same // shape as the `.yml` variants — the YAML/properties extractor emits one node // per leaf key, and the Spring resolver links `@Value("${k}")` references. @@ -267,7 +273,10 @@ export async function initGrammars(): Promise { * MIT) — byte-identical to the npm tarball's artifact. It extends the * tree-sitter-javascript grammar the same way tree-sitter-typescript does, * adding `struct_declaration` and the `arkui_component_expression` build() - * DSL. Nix: tree-sitter-wasms doesn't ship it; we vendor a wasm built from + * DSL. Elixir: tree-sitter-wasms doesn't ship it; we vendor the prebuilt + * tree-sitter-elixir.wasm from elixir-lang/tree-sitter-elixir 0.3.5 + * (Apache-2.0, ABI 14) — byte-identical to the npm tarball's artifact. + * Nix: tree-sitter-wasms doesn't ship it; we vendor a wasm built from * nix-community/tree-sitter-nix @ 3d0173d (MIT) with tree-sitter-cli 0.25.10 * (`generate` + `build --wasm`, ABI 15 — upstream's checked-in parser.c is * still ABI 13; all 54 upstream corpus tests pass on the regenerated parser). @@ -290,7 +299,7 @@ export async function initGrammars(): Promise { */ const VENDORED_WASM_LANGS: ReadonlySet = new Set([ 'pascal', 'scala', 'lua', 'luau', 'csharp', 'r', 'cfml', 'cfscript', 'cfquery', - 'cobol', 'vbnet', 'erlang', 'terraform', 'arkts', 'nix', + 'cobol', 'vbnet', 'erlang', 'elixir', 'terraform', 'arkts', 'nix', 'typescript', 'tsx', 'javascript', 'jsx', 'java', 'python', 'go', // R7a (C/C++ kernel port prep): tree-sitter-c v0.24.2 (b780e47) + // tree-sitter-cpp v0.23.4 (f41e1a0), parser.c/scanner.c sha-matched against @@ -705,6 +714,7 @@ export function getLanguageDisplayName(language: Language): string { cobol: 'COBOL', vbnet: 'Visual Basic .NET', erlang: 'Erlang', + elixir: 'Elixir', terraform: 'Terraform', arkts: 'ArkTS', unknown: 'Unknown', diff --git a/src/extraction/index.ts b/src/extraction/index.ts index 93be48352..248185542 100644 --- a/src/extraction/index.ts +++ b/src/extraction/index.ts @@ -194,6 +194,10 @@ const DEFAULT_IGNORE_DIRS: ReadonlySet = new Set([ 'lua_modules', '.luarocks', // Delphi / RAD Studio IDE backups (duplicate .pas source — would double-count) '__history', '__recovery', + // Elixir / Mix — compiled beam output and language-server cache. Mix + // dependencies live in `deps/`, which is deliberately NOT listed (the name + // is first-party-prone); Mix projects gitignore it. + '_build', '.elixir_ls', // Generic cache '.cache', ]); diff --git a/src/extraction/languages/elixir.ts b/src/extraction/languages/elixir.ts new file mode 100644 index 000000000..326edee77 --- /dev/null +++ b/src/extraction/languages/elixir.ts @@ -0,0 +1,863 @@ +import type { Node as SyntaxNode } from 'web-tree-sitter'; +import { getNodeText, getChildByField, getPrecedingDocstring } from '../tree-sitter-helpers'; +import type { LanguageExtractor, ExtractorContext } from '../tree-sitter-types'; +import type { UnresolvedReference } from '../../types'; + +// Node names follow the vendored elixir-lang/tree-sitter-elixir grammar (0.3.5, +// ABI 14). Elixir has no dedicated def/module AST nodes — `defmodule`, `def`, +// `alias`, `if`, and ordinary calls are all `call` nodes whose `target` is an +// identifier (or a `dot` for `Mod.fun`). Three of those shapes don't fit the +// generic extractor, so definitions, directives, and attributes are dispatched +// through the visitNode hook; real calls (and `|> ident`, `&fun/arity`) go +// through extractCall via callTypes, reading the per-file alias/import maps +// populated below. + +const DEF_FUN = new Set([ + 'def', 'defp', 'defmacro', 'defmacrop', 'defguard', 'defguardp', + 'defdelegate', 'defn', 'defnp', +]); +const PRIVATE_FUN = new Set(['defp', 'defmacrop', 'defguardp', 'defnp']); +const DEF_MOD = new Set(['defmodule', 'defprotocol']); +const IMPORT_DIRECTIVES = new Set(['alias', 'import', 'require', 'use']); + +/** Kernel special forms / definition macros — never call edges (tags.scm). */ +const SPECIAL_FORMS = new Set([ + 'def', 'defp', 'defdelegate', 'defguard', 'defguardp', 'defmacro', 'defmacrop', + 'defn', 'defnp', 'defmodule', 'defprotocol', 'defimpl', 'defstruct', + 'defexception', 'defoverridable', 'alias', 'case', 'cond', 'else', 'for', + 'if', 'import', 'quote', 'receive', 'require', 'super', 'try', 'unless', + 'unquote', 'unquote_splicing', 'use', 'with', +]); + +const MFA_CALLEES = new Set([ + 'apply', 'spawn', 'spawn_link', 'spawn_monitor', +]); + +function collapseWs(text: string): string { + return text.replace(/\s+/g, ' ').trim(); +} + +function operatorOf(node: SyntaxNode, source: string): string { + const op = getChildByField(node, 'operator'); + return op ? getNodeText(op, source) : ''; +} + +function atomText(node: SyntaxNode, source: string): string { + const raw = getNodeText(node, source); + if (raw.startsWith(':')) { + const rest = raw.slice(1); + return rest.replace(/^["']([\s\S]*)["']$/, '$1'); + } + return raw.replace(/^['"]([\s\S]*)['"]$/, '$1'); +} + +function keywordName(node: SyntaxNode, source: string): string { + return getNodeText(node, source).replace(/:\s*$/, '').trim(); +} + +function stringContent(node: SyntaxNode, source: string): string { + const parts = node.namedChildren + .filter((c) => c.type === 'quoted_content') + .map((c) => getNodeText(c, source)); + if (parts.length > 0) return parts.join(''); + return getNodeText(node, source).replace(/^["']+|["']+$/g, ''); +} + +function argumentsNode(node: SyntaxNode): SyntaxNode | null { + return node.namedChildren.find((c) => c.type === 'arguments') ?? null; +} + +function doBlock(node: SyntaxNode): SyntaxNode | null { + return node.namedChildren.find((c) => c.type === 'do_block') ?? null; +} + +function keywordsNode(node: SyntaxNode): SyntaxNode | null { + return node.namedChildren.find((c) => c.type === 'keywords') + ?? argumentsNode(node)?.namedChildren.find((c) => c.type === 'keywords') + ?? null; +} + +function pairKey(pair: SyntaxNode): SyntaxNode | null { + return getChildByField(pair, 'key') ?? pair.namedChild(0); +} + +function pairValue(pair: SyntaxNode): SyntaxNode | null { + return getChildByField(pair, 'value') ?? pair.namedChild(1); +} + +function keywordValue(keywords: SyntaxNode | null, key: string, source: string): SyntaxNode | null { + if (!keywords) return null; + for (const pair of keywords.namedChildren) { + if (pair.type !== 'pair') continue; + const k = pairKey(pair); + const v = pairValue(pair); + if (k && v && keywordName(k, source) === key) return v; + } + return null; +} + +function targetNode(call: SyntaxNode): SyntaxNode | null { + return getChildByField(call, 'target'); +} + +function targetIdent(call: SyntaxNode, source: string): string | null { + const t = targetNode(call); + if (!t) return null; + if (t.type === 'identifier') return getNodeText(t, source); + return null; +} + +function isAttr(node: SyntaxNode, source: string): boolean { + return node.type === 'unary_operator' && operatorOf(node, source) === '@'; +} + +function attrName(node: SyntaxNode, source: string): string | null { + if (!isAttr(node, source)) return null; + const operand = getChildByField(node, 'operand'); + if (!operand) return null; + if (operand.type === 'identifier') return getNodeText(operand, source); + if (operand.type === 'call') return targetIdent(operand, source); + return null; +} + +function attrCall(node: SyntaxNode): SyntaxNode | null { + const operand = getChildByField(node, 'operand'); + return operand?.type === 'call' ? operand : null; +} + +// --- Per-file memos. Extraction is file-sequential within a worker. --- + +let stateFile = ''; +let aliasStack: Map[] = [new Map()]; +let importOnlyStack: Map[] = [new Map()]; // "map/2" → "Enum" +let moduleStack: string[] = []; +let lastFnName = ''; +let lastFnArity = -1; +let lastFnId = ''; + +function resetState(filePath: string): void { + if (filePath === stateFile) return; + stateFile = filePath; + aliasStack = [new Map()]; + importOnlyStack = [new Map()]; + moduleStack = []; + lastFnName = ''; + lastFnArity = -1; + lastFnId = ''; +} + +function aliases(): Map { + return aliasStack[aliasStack.length - 1]!; +} + +function importOnly(): Map { + return importOnlyStack[importOnlyStack.length - 1]!; +} + +function currentModule(): string | null { + return moduleStack[moduleStack.length - 1] ?? null; +} + +function expandAlias(mod: string): string { + const dot = mod.indexOf('.'); + const first = dot < 0 ? mod : mod.slice(0, dot); + const rest = dot < 0 ? '' : mod.slice(dot); + const mapped = aliases().get(first); + return mapped ? mapped + rest : mod; +} + +function nestModule(name: string): string { + const parent = currentModule(); + return parent ? `${parent}.${name}` : name; +} + +function qualifyCall(mod: string | null, fun: string, arity: number): string { + if (!mod || mod === currentModule()) return `${fun}/${arity}`; + return `${mod}::${fun}/${arity}`; +} + +/** Call-site arity, plus 1 per enclosing `|>` that this node is the right of. */ +function callArity(node: SyntaxNode, source: string): number { + const args = argumentsNode(node); + let arity = args ? args.namedChildCount : 0; + let cur: SyntaxNode = node; + for (;;) { + const parent = cur.parent; + if (!parent) break; + if (parent.type === 'binary_operator' && operatorOf(parent, source) === '|>') { + const right = getChildByField(parent, 'right'); + if (right && right.startIndex === cur.startIndex && right.endIndex === cur.endIndex) { + arity += 1; + cur = parent; + continue; + } + } + break; + } + return arity; +} + +interface FunHead { + name: string; + arity: number; + header: SyntaxNode; +} + +function unwrapWhen(node: SyntaxNode, source: string): SyntaxNode { + let cur = node; + while (cur.type === 'binary_operator' && operatorOf(cur, source) === 'when') { + const left = getChildByField(cur, 'left'); + if (!left) break; + cur = left; + } + return cur; +} + +function parseFunHead(defCall: SyntaxNode, source: string): FunHead | null { + const args = argumentsNode(defCall); + if (!args) return null; + const positional = args.namedChildren.filter((c) => c.type !== 'keywords'); + const raw = positional[0]; + if (!raw) return null; + const head = unwrapWhen(raw, source); + if (head.type === 'identifier') { + const name = getNodeText(head, source); + if (!name || name === 'unquote') return null; + return { name, arity: 0, header: head }; + } + if (head.type === 'call') { + const name = targetIdent(head, source); + if (!name || name === 'unquote') return null; + const headArgs = argumentsNode(head); + return { name, arity: headArgs ? headArgs.namedChildCount : 0, header: head }; + } + return null; +} + +function precedingAttrs(node: SyntaxNode, source: string): { doc?: string; spec?: SyntaxNode } { + const out: { doc?: string; spec?: SyntaxNode } = {}; + let prev = node.previousNamedSibling; + while (prev) { + if (prev.type === 'comment') { + prev = prev.previousNamedSibling; + continue; + } + if (isAttr(prev, source)) { + const name = attrName(prev, source); + if (name === 'doc' && out.doc === undefined) { + const call = attrCall(prev); + const args = call ? argumentsNode(call) : null; + const first = args?.namedChild(0); + if (first && (first.type === 'string' || first.type === 'charlist')) { + const text = stringContent(first, source).trim(); + if (text && text !== 'false') out.doc = text; + } else if (first && getNodeText(first, source) === 'false') { + out.doc = ''; + } + } else if (name === 'spec' && !out.spec) { + out.spec = prev; + } + prev = prev.previousNamedSibling; + continue; + } + break; + } + return out; +} + +function defSignature(defCall: SyntaxNode, spec: SyntaxNode | undefined, source: string): string | undefined { + if (spec) return collapseWs(getNodeText(spec, source)).slice(0, 300); + const body = doBlock(defCall) ?? keywordsNode(defCall); + const end = body ? body.startIndex : defCall.endIndex; + return collapseWs(source.substring(defCall.startIndex, end)) || undefined; +} + +function isContinuation(node: SyntaxNode, name: string, arity: number, source: string): boolean { + let prev = node.previousNamedSibling; + while (prev && (prev.type === 'comment' || isAttr(prev, source))) { + prev = prev.previousNamedSibling; + } + if (!prev || prev.type !== 'call') return false; + const ident = targetIdent(prev, source); + if (!ident || !DEF_FUN.has(ident)) return false; + const head = parseFunHead(prev, source); + return !!head && head.name === name && head.arity === arity; +} + +function recordAlias(asName: string, fullName: string): void { + if (asName && fullName) aliases().set(asName, fullName); +} + +function collectAlias(call: SyntaxNode, source: string): void { + const args = argumentsNode(call); + if (!args) return; + const as = keywordValue(keywordsNode(call), 'as', source); + const positional = args.namedChildren.filter((c) => c.type !== 'keywords'); + const target = positional[0]; + if (!target) return; + if (as && as.type === 'alias') { + const full = getNodeText(target, source); + recordAlias(getNodeText(as, source), full); + return; + } + if (target.type === 'alias') { + const full = getNodeText(target, source); + const last = full.includes('.') ? full.slice(full.lastIndexOf('.') + 1) : full; + recordAlias(last, full); + return; + } + // alias Foo.{One, Two} + if (target.type === 'dot') { + const left = getChildByField(target, 'left'); + const right = getChildByField(target, 'right'); + if (left?.type === 'alias' && right?.type === 'tuple') { + const prefix = getNodeText(left, source); + for (const child of right.namedChildren) { + if (child.type === 'alias') { + const name = getNodeText(child, source); + recordAlias(name, `${prefix}.${name}`); + } + } + } + } +} + +function collectImportOnly(call: SyntaxNode, source: string): void { + const args = argumentsNode(call); + if (!args) return; + const modNode = args.namedChildren.find((c) => c.type === 'alias'); + if (!modNode) return; + const mod = getNodeText(modNode, source); + const only = keywordValue(keywordsNode(call), 'only', source); + if (!only || only.type !== 'list') return; + const kws = only.namedChildren.find((c) => c.type === 'keywords') ?? only; + for (const pair of kws.namedChildren) { + if (pair.type !== 'pair') continue; + const key = getChildByField(pair, 'key'); + const value = getChildByField(pair, 'value'); + if (!key || value?.type !== 'integer') continue; + const fun = keywordName(key, source); + const arity = getNodeText(value, source); + importOnly().set(`${fun}/${arity}`, mod); + } +} + +function collectDirectives(body: SyntaxNode, source: string): void { + for (let i = 0; i < body.namedChildCount; i++) { + const child = body.namedChild(i); + if (!child || child.type !== 'call') continue; + const ident = targetIdent(child, source); + if (ident === 'alias') collectAlias(child, source); + else if (ident === 'import') collectImportOnly(child, source); + } +} + +function visitBody(node: SyntaxNode, ctx: ExtractorContext): void { + const block = doBlock(node); + if (block) ctx.visitFunctionBody(block, ctx.nodeStack[ctx.nodeStack.length - 1] ?? ''); + const doVal = keywordValue(keywordsNode(node), 'do', ctx.source); + if (doVal) ctx.visitFunctionBody(doVal, ctx.nodeStack[ctx.nodeStack.length - 1] ?? ''); +} + +function handleDefmodule(node: SyntaxNode, ctx: ExtractorContext, kind: 'module' | 'interface'): boolean { + const args = argumentsNode(node); + const nameNode = args?.namedChildren.find((c) => c.type === 'alias'); + if (!nameNode) return true; + const name = nestModule(getNodeText(nameNode, ctx.source)); + const attrs = precedingAttrs(node, ctx.source); + const mod = ctx.createNode(kind, name, node, { + docstring: attrs.doc || getPrecedingDocstring(node, ctx.source), + signature: defSignature(node, undefined, ctx.source), + isExported: true, + }); + if (!mod) return true; + // Elixir modules are dotted (`Foo.Bar`), not `::`-nested. Override the + // generic `Parent::Foo.Bar` qualifiedName so functions inside become + // `Foo.Bar::baz/1` rather than `Foo::Foo.Bar::baz/1`. + mod.qualifiedName = name; + const body = doBlock(node); + aliasStack.push(new Map()); + importOnlyStack.push(new Map()); + moduleStack.push(name); + ctx.pushScope(mod.id); + if (body) { + collectDirectives(body, ctx.source); + for (let i = 0; i < body.namedChildCount; i++) { + const child = body.namedChild(i); + if (child) ctx.visitNode(child); + } + } + ctx.popScope(); + moduleStack.pop(); + aliasStack.pop(); + importOnlyStack.pop(); + return true; +} + +function handleDefun(node: SyntaxNode, ctx: ExtractorContext): boolean { + const ident = targetIdent(node, ctx.source); + if (!ident) return true; + const head = parseFunHead(node, ctx.source); + if (!head) return true; + const { name, arity } = head; + + if (isContinuation(node, name, arity, ctx.source) && lastFnId && lastFnName === name && lastFnArity === arity) { + for (let i = ctx.nodes.length - 1; i >= 0; i--) { + const n = ctx.nodes[i]; + if (n && n.id === lastFnId) { + if (node.endPosition.row + 1 > n.endLine) n.endLine = node.endPosition.row + 1; + break; + } + } + ctx.pushScope(lastFnId); + visitBody(node, ctx); + ctx.popScope(); + return true; + } + + const attrs = precedingAttrs(node, ctx.source); + const isPrivate = PRIVATE_FUN.has(ident); + const fn = ctx.createNode('function', name, node, { + docstring: attrs.doc || getPrecedingDocstring(node, ctx.source), + signature: defSignature(node, attrs.spec, ctx.source), + isExported: !isPrivate, + visibility: isPrivate ? 'private' : 'public', + }); + if (!fn) return true; + const modName = currentModule(); + fn.qualifiedName = modName ? `${modName}::${name}/${arity}` : `${name}/${arity}`; + ctx.pushScope(fn.id); + visitBody(node, ctx); + if (ident === 'defdelegate') { + const to = keywordValue(keywordsNode(node), 'to', ctx.source); + const as = keywordValue(keywordsNode(node), 'as', ctx.source); + if (to && (to.type === 'alias' || to.type === 'identifier')) { + const destMod = to.type === 'alias' ? expandAlias(getNodeText(to, ctx.source)) : getNodeText(to, ctx.source); + const destFun = as ? atomText(as, ctx.source) : name; + ctx.addUnresolvedReference({ + fromNodeId: fn.id, + referenceName: qualifyCall(destMod, destFun, arity), + referenceKind: 'calls', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); + } + } + ctx.popScope(); + lastFnName = name; + lastFnArity = arity; + lastFnId = fn.id; + return true; +} + +function handleDefstruct(node: SyntaxNode, ctx: ExtractorContext): boolean { + const parentId = ctx.nodeStack[ctx.nodeStack.length - 1]; + if (!parentId) return true; + const args = argumentsNode(node); + if (!args) return true; + const addField = (name: string, fieldNode: SyntaxNode): void => { + if (name) ctx.createNode('field', name, fieldNode); + }; + const walk = (n: SyntaxNode): void => { + if (n.type === 'atom') addField(atomText(n, ctx.source), n); + else if (n.type === 'keywords') { + for (const pair of n.namedChildren) { + if (pair.type !== 'pair') continue; + const key = pairKey(pair); + if (key) addField(keywordName(key, ctx.source), pair); + } + } else if (n.type === 'list') { + for (const c of n.namedChildren) walk(c); + } + }; + for (const c of args.namedChildren) walk(c); + return true; +} + +function handleDefimpl(node: SyntaxNode, ctx: ExtractorContext): boolean { + const args = argumentsNode(node); + const protocol = args?.namedChildren.find((c) => c.type === 'alias'); + const forType = keywordValue(keywordsNode(node), 'for', ctx.source); + const parentId = ctx.nodeStack[ctx.nodeStack.length - 1]; + const fromId = parentId; + if (protocol && fromId) { + const targets: SyntaxNode[] = []; + if (forType?.type === 'alias') targets.push(forType); + else if (forType?.type === 'list') { + for (const c of forType.namedChildren) if (c.type === 'alias') targets.push(c); + } + // No `for:` — the impl sits inside the target module. + if (targets.length === 0 && currentModule()) { + ctx.addUnresolvedReference({ + fromNodeId: fromId, + referenceName: getNodeText(protocol, ctx.source), + referenceKind: 'implements', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); + } else { + for (const t of targets) { + ctx.addUnresolvedReference({ + fromNodeId: fromId, + referenceName: getNodeText(protocol, ctx.source), + referenceKind: 'implements', + line: t.startPosition.row + 1, + column: t.startPosition.column, + }); + } + } + } + const body = doBlock(node); + if (body) { + for (let i = 0; i < body.namedChildCount; i++) { + const child = body.namedChild(i); + if (child) ctx.visitNode(child); + } + } + return true; +} + +function handleImport(node: SyntaxNode, ctx: ExtractorContext): boolean { + const ident = targetIdent(node, ctx.source); + const args = argumentsNode(node); + if (!ident || !args) return true; + const mods: string[] = []; + const positional = args.namedChildren.filter((c) => c.type !== 'keywords'); + const first = positional[0]; + if (first?.type === 'alias') mods.push(getNodeText(first, ctx.source)); + else if (first?.type === 'dot') { + const left = getChildByField(first, 'left'); + const right = getChildByField(first, 'right'); + if (left?.type === 'alias' && right?.type === 'tuple') { + const prefix = getNodeText(left, ctx.source); + for (const c of right.namedChildren) { + if (c.type === 'alias') mods.push(`${prefix}.${getNodeText(c, ctx.source)}`); + } + } + } + const as = keywordValue(keywordsNode(node), 'as', ctx.source); + for (const mod of mods) { + const display = as && as.type === 'alias' && mods.length === 1 ? getNodeText(as, ctx.source) : mod; + ctx.createNode('import', display, node, { + signature: collapseWs(getNodeText(node, ctx.source)).slice(0, 200), + }); + const parentId = ctx.nodeStack[ctx.nodeStack.length - 1]; + if (parentId) { + ctx.addUnresolvedReference({ + fromNodeId: parentId, + referenceName: mod, + referenceKind: 'imports', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); + } + } + if (ident === 'alias') collectAlias(node, ctx.source); + if (ident === 'import') collectImportOnly(node, ctx.source); + return true; +} + +function handleAttribute(node: SyntaxNode, ctx: ExtractorContext): boolean { + const name = attrName(node, ctx.source); + const call = attrCall(node); + if (name === 'moduledoc') { + const args = call ? argumentsNode(call) : null; + const first = args?.namedChild(0); + const text = first && (first.type === 'string' || first.type === 'charlist') + ? stringContent(first, ctx.source).trim() + : ''; + if (text && text !== 'false') { + const modId = ctx.nodeStack[ctx.nodeStack.length - 1]; + const mod = modId ? ctx.nodes.find((n) => n.id === modId) : undefined; + if (mod && (mod.kind === 'module' || mod.kind === 'interface') && !mod.docstring) { + mod.docstring = text; + } + } + return true; + } + if (name === 'behaviour' || name === 'behavior') { + const args = call ? argumentsNode(call) : null; + const alias = args?.namedChildren.find((c) => c.type === 'alias'); + const parentId = ctx.nodeStack[ctx.nodeStack.length - 1]; + if (alias && parentId) { + ctx.addUnresolvedReference({ + fromNodeId: parentId, + referenceName: getNodeText(alias, ctx.source), + referenceKind: 'implements', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); + } + return true; + } + if (name === 'type' || name === 'typep' || name === 'opaque') { + const args = call ? argumentsNode(call) : null; + const first = args?.namedChild(0); + if (first) { + let typeNameNode: SyntaxNode | null = null; + if (first.type === 'binary_operator' && operatorOf(first, ctx.source) === '::') { + const left = getChildByField(first, 'left'); + if (left?.type === 'identifier') typeNameNode = left; + else if (left?.type === 'call') { + const t = targetNode(left); + if (t?.type === 'identifier') typeNameNode = t; + } + } else if (first.type === 'identifier') { + typeNameNode = first; + } + if (typeNameNode) { + ctx.createNode('type_alias', getNodeText(typeNameNode, ctx.source), node, { + signature: collapseWs(getNodeText(node, ctx.source)).slice(0, 200), + }); + } + } + return true; + } + // @doc / @spec attach to the next def via precedingAttrs; other attributes + // are consumed so their operand `call` nodes don't become bogus call refs. + return true; +} + +type CallRef = Pick; + +function emitImported(fun: string, arity: number, node: SyntaxNode, out: CallRef[]): void { + const mod = importOnly().get(`${fun}/${arity}`); + if (!mod) return; + out.push({ + referenceName: `${expandAlias(mod)}::${fun}/${arity}`, + referenceKind: 'calls', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); +} + +/** + * Call / capture / pipe-identifier refs for the elixir extractCall branch. + * Returns null when the node is a special form or definition (no call edge); + * otherwise the refs to emit (possibly empty). + */ +export function elixirCallRefs( + node: SyntaxNode, + source: string, + filePath: string, +): Array> | null { + resetState(filePath); + const line = node.startPosition.row + 1; + const column = node.startPosition.column; + + if (node.type === 'unary_operator') { + if (operatorOf(node, source) !== '&') return null; + const operand = getChildByField(node, 'operand'); + if (!operand || operand.type !== 'binary_operator' || operatorOf(operand, source) !== '/') return null; + const left = getChildByField(operand, 'left'); + const right = getChildByField(operand, 'right'); + if (!left || right?.type !== 'integer') return null; + const arity = getNodeText(right, source); + if (left.type === 'identifier') { + return [{ referenceName: `${getNodeText(left, source)}/${arity}`, referenceKind: 'references', line, column }]; + } + if (left.type === 'call') { + const t = targetNode(left); + if (t?.type === 'dot') { + const q = qualifyDot(t, source); + if (q) { + return [{ + referenceName: qualifyCall(q.mod, q.fun, Number(arity) || 0), + referenceKind: 'references', + line, + column, + }]; + } + } + const ident = targetIdent(left, source); + if (ident) { + return [{ referenceName: `${ident}/${arity}`, referenceKind: 'references', line, column }]; + } + } + if (left.type === 'dot') { + const q = qualifyDot(left, source); + if (q) { + return [{ + referenceName: qualifyCall(q.mod, q.fun, Number(arity) || 0), + referenceKind: 'references', + line, + column, + }]; + } + } + return null; + } + + if (node.type === 'binary_operator') { + if (operatorOf(node, source) !== '|>') return []; + const right = getChildByField(node, 'right'); + if (right?.type === 'identifier') { + const fun = getNodeText(right, source); + const refs: Array> = [ + { referenceName: `${fun}/1`, referenceKind: 'calls', line: right.startPosition.row + 1, column: right.startPosition.column }, + ]; + const mod = importOnly().get(`${fun}/1`); + if (mod) { + refs.push({ + referenceName: `${expandAlias(mod)}::${fun}/1`, + referenceKind: 'calls', + line: right.startPosition.row + 1, + column: right.startPosition.column, + }); + } + return refs; + } + return []; + } + + if (node.type !== 'call') return []; + + const ident = targetIdent(node, source); + if (ident && (SPECIAL_FORMS.has(ident) || DEF_FUN.has(ident) || DEF_MOD.has(ident) || ident === 'defimpl' || ident === 'defstruct' || ident === 'defexception')) { + return null; + } + + const target = targetNode(node); + const arity = callArity(node, source); + const refs: Array> = []; + + if (target?.type === 'identifier' && ident) { + refs.push({ referenceName: `${ident}/${arity}`, referenceKind: 'calls', line, column }); + emitImported(ident, arity, node, refs); + maybeMfa(node, source, ident, null, refs); + } else if (target?.type === 'dot') { + const q = qualifyDot(target, source); + if (!q) return []; + refs.push({ + referenceName: qualifyCall(q.mod, q.fun, arity), + referenceKind: 'calls', + line, + column, + }); + if (q.mod) { + refs.push({ + referenceName: q.mod, + referenceKind: 'references', + line: target.startPosition.row + 1, + column: target.startPosition.column, + }); + } + maybeGenServer(q.mod, q.fun, node, source, refs); + maybeMfa(node, source, q.fun, q.mod, refs); + } + + return refs; +} + +function qualifyDot(dot: SyntaxNode, source: string): { mod: string | null; fun: string } | null { + const left = getChildByField(dot, 'left'); + const right = getChildByField(dot, 'right'); + if (!right || (right.type !== 'identifier' && right.type !== 'atom')) return null; + const fun = right.type === 'atom' ? atomText(right, source) : getNodeText(right, source); + if (!left) return { mod: null, fun }; + if (left.type === 'alias') return { mod: expandAlias(getNodeText(left, source)), fun }; + if (left.type === 'identifier' && getNodeText(left, source) === '__MODULE__') { + return { mod: currentModule(), fun }; + } + return null; // variable receiver — dynamic +} + +function maybeGenServer( + mod: string | null, + fun: string, + node: SyntaxNode, + source: string, + refs: Array>, +): void { + if (mod !== 'GenServer' && mod !== 'Elixir.GenServer') return; + if (fun !== 'call' && fun !== 'cast') return; + const args = argumentsNode(node); + const target = args?.namedChild(0); + if (!target) return; + let targetMod: string | null = null; + if (target.type === 'identifier' && getNodeText(target, source) === '__MODULE__') { + targetMod = currentModule(); + } else if (target.type === 'alias') { + targetMod = expandAlias(getNodeText(target, source)); + } + if (!targetMod) return; + const handler = fun === 'cast' ? 'handle_cast' : 'handle_call'; + const arity = fun === 'cast' ? 2 : 3; + refs.push({ + referenceName: qualifyCall(targetMod, handler, arity), + referenceKind: 'calls', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); +} + +function maybeMfa( + node: SyntaxNode, + source: string, + fun: string, + mod: string | null, + refs: Array>, +): void { + if (!MFA_CALLEES.has(fun)) return; + if (mod && mod !== 'Kernel' && mod !== 'Process' && mod !== ':erlang' && mod !== 'erlang') return; + const args = argumentsNode(node); + if (!args || args.namedChildCount < 3) return; + const m = args.namedChild(0); + const f = args.namedChild(1); + const list = args.namedChild(2); + if (!m || !f || list?.type !== 'list') return; + let destMod: string | null = null; + if (m.type === 'alias') destMod = expandAlias(getNodeText(m, source)); + else if (m.type === 'identifier' && getNodeText(m, source) === '__MODULE__') destMod = currentModule(); + else if (m.type === 'atom') destMod = atomText(m, source); + else return; + if (f.type !== 'atom') return; + const destFun = atomText(f, source); + refs.push({ + referenceName: qualifyCall(destMod, destFun, list.namedChildCount), + referenceKind: 'calls', + line: f.startPosition.row + 1, + column: f.startPosition.column, + }); +} + +export const elixirExtractor: LanguageExtractor = { + // Definitions are `call` nodes dispatched via visitNode; real calls still + // use callTypes so visitFunctionBody (which does not invoke visitNode) sees + // them. unary_operator covers `&fun/arity`; binary_operator covers `|> ident`. + functionTypes: [], + classTypes: [], + methodTypes: [], + interfaceTypes: [], + structTypes: [], + enumTypes: [], + typeAliasTypes: [], + importTypes: [], + callTypes: ['call', 'unary_operator', 'binary_operator'], + variableTypes: [], + nameField: 'target', + bodyField: 'do_block', + paramsField: 'arguments', + + visitNode: (node, ctx) => { + resetState(ctx.filePath); + if (node.type === 'source') { + collectDirectives(node, ctx.source); + return false; + } + if (node.type === 'unary_operator' && operatorOf(node, ctx.source) === '@') { + return handleAttribute(node, ctx); + } + if (node.type !== 'call') return false; + const ident = targetIdent(node, ctx.source); + if (!ident) return false; + if (ident === 'defmodule') return handleDefmodule(node, ctx, 'module'); + if (ident === 'defprotocol') return handleDefmodule(node, ctx, 'interface'); + if (ident === 'defimpl') return handleDefimpl(node, ctx); + if (DEF_FUN.has(ident)) return handleDefun(node, ctx); + if (ident === 'defstruct' || ident === 'defexception') return handleDefstruct(node, ctx); + if (IMPORT_DIRECTIVES.has(ident)) return handleImport(node, ctx); + if (ident === 'quote' || ident === 'unquote' || ident === 'unquote_splicing') return true; + return false; + }, +}; diff --git a/src/extraction/languages/index.ts b/src/extraction/languages/index.ts index 6b760b01d..19df78dc2 100644 --- a/src/extraction/languages/index.ts +++ b/src/extraction/languages/index.ts @@ -32,6 +32,7 @@ import { cfqueryExtractor } from './cfquery'; import { cobolExtractor } from './cobol'; import { vbnetExtractor } from './vbnet'; import { erlangExtractor } from './erlang'; +import { elixirExtractor } from './elixir'; import { solidityExtractor } from './solidity'; import { terraformExtractor } from './terraform'; import { arktsExtractor } from './arkts'; @@ -65,6 +66,7 @@ export const EXTRACTORS: Partial> = { cobol: cobolExtractor, vbnet: vbnetExtractor, erlang: erlangExtractor, + elixir: elixirExtractor, solidity: solidityExtractor, terraform: terraformExtractor, arkts: arktsExtractor, diff --git a/src/extraction/tree-sitter-helpers.ts b/src/extraction/tree-sitter-helpers.ts index a6438e1b4..68dd9daf9 100644 --- a/src/extraction/tree-sitter-helpers.ts +++ b/src/extraction/tree-sitter-helpers.ts @@ -83,7 +83,7 @@ function cleanCommentMarkers(comment: string): string { return c .replace(/^\/\/[/!]?\s?/gm, '') // // , and Rust/Swift doc lines /// //! .replace(/^--\s?/gm, '') // Lua/Luau line comments - .replace(/^#\s?/gm, '') // Python/Ruby/shell line comments + .replace(/^#\s?/gm, '') // Python/Ruby/Elixir/shell line comments .replace(/^%+\s?/gm, '') // Erlang line comments (% / %% / %%%) .replace(/^\s*\*\s?/gm, '') // block-comment continuation (* foo) .trim(); diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 7ef90c273..308e323aa 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -23,6 +23,7 @@ import type { LanguageExtractor, ExtractorContext } from './tree-sitter-types'; import { EXTRACTORS } from './languages'; import { stripCppTemplateArgs } from './languages/c-cpp'; import { rustImplTypeName } from './languages/rust'; +import { elixirCallRefs } from './languages/elixir'; import { LiquidExtractor } from './liquid-extractor'; import { RazorExtractor } from './razor-extractor'; import { SvelteExtractor } from './svelte-extractor'; @@ -3787,6 +3788,31 @@ export class TreeSitterExtractor { return; } + // Elixir: `defmodule`/`def`/`alias`/`if` and ordinary calls are the same + // `call` node (target: identifier or dot). Definitions are consumed by + // visitNode; this branch sees the rest — local `foo/2`, remote + // `Foo.Bar::baz/1` (aliases expanded, `__MODULE__` → this module), + // `|> ident` (binary_operator), `&fun/arity` (unary_operator), plus + // GenServer.call/cast → handle_call/handle_cast and static apply/spawn MFA + // when the target is an alias or `__MODULE__`. Arity is part of identity, + // matching the qualifiedName suffix the extractor stamps on every def. + if (this.language === 'elixir') { + const refs = elixirCallRefs(node, this.source, this.filePath); + if (!refs) return; + const line = node.startPosition.row + 1; + const column = node.startPosition.column; + for (const r of refs) { + this.unresolvedReferences.push({ + fromNodeId: callerId, + referenceName: r.referenceName, + referenceKind: r.referenceKind, + line: r.line ?? line, + column: r.column ?? column, + }); + } + return; + } + // Erlang: a local call is `call(expr: atom, args)`; a remote call nests it // under `remote(module: remote_module, fun: call)` — the module qualifier // lives on the PARENT. Arity is part of a function's identity (#1610), so diff --git a/src/extraction/wasm/tree-sitter-elixir.wasm b/src/extraction/wasm/tree-sitter-elixir.wasm new file mode 100644 index 0000000000000000000000000000000000000000..128c34191dfe302c43281572f752f2f66449af42 GIT binary patch literal 1412267 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�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 literal 0 HcmV?d00001 diff --git a/src/graph/named-symbol-flow.ts b/src/graph/named-symbol-flow.ts index 3fc095c79..2fedf57fe 100644 --- a/src/graph/named-symbol-flow.ts +++ b/src/graph/named-symbol-flow.ts @@ -108,6 +108,13 @@ export function matchesSymbol(node: Node, symbol: string): boolean { // `Session::request` both become `Session::request` here. const colonSuffix = parts.join('::'); if (node.qualifiedName.includes(colonSuffix)) return true; + // Elixir (and similar) modules keep dots in the module name + // (`MyApp.Accounts::get_user/2`); a query `MyApp.Accounts.get_user` splits + // into three parts whose `::` join would be `MyApp::Accounts::get_user`. + if (parts.length >= 3) { + const dottedMod = `${parts.slice(0, -1).join('.')}::${lastPart}`; + if (node.qualifiedName.includes(dottedMod)) return true; + } // Stage 2: file-path containment. Rust modules and Python packages // are not in `qualifiedName` — they're encoded in the file path. So diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 7988c1bcf..c9bd7e29d 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -892,7 +892,7 @@ export class ReferenceResolver { : ref.referenceName; // Erlang refs carry the call-site arity (`f/1`, `mod::f/2` — #1610); the // name index stores bare names, so existence is checked arity-less. - if (ref.language === 'erlang') existenceName = existenceName.replace(/\/\d{1,3}$/, ''); + if (ref.language === 'erlang' || ref.language === 'elixir') existenceName = existenceName.replace(/\/\d{1,3}$/, ''); const tPre = this.profileStages ? process.hrtime.bigint() : 0n; const preFilterPass = isNixPathImportRef(ref) || diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index c74d8f272..50ec43a93 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -503,15 +503,47 @@ export function matchByQualifiedName( } } - // Erlang qualified refs (#1610): every erlang function's qualifiedName - // carries its arity (`mod::f/2`), and refs carry the call-site arity when it - // is statically known. - if (ref.language === 'erlang' && ref.referenceName.includes('::')) { + // Erlang / Elixir qualified refs: every function's qualifiedName carries + // its arity (`mod::f/2`, `Foo.Bar::baz/1`), and refs carry the call-site + // arity when it is statically known. + if ( + (ref.language === 'erlang' || ref.language === 'elixir') && + ref.referenceName.includes('::') + ) { // A ref WITH arity that missed the exact lookup names an arity that isn't // defined (or a module out of repo). Never fall through to the partial // match — its "last segment" would be the arity digits — and never settle - // for a sibling arity: silent beats wrong. - if (/\/\d{1,3}$/.test(ref.referenceName)) return null; + // for a sibling arity: silent beats wrong. Elixir default args + // (`def foo(a, b \\ 1)`) index as the MAX arity; a shorter call is the + // same def when this module defines exactly one function of that name. + if (/\/\d{1,3}$/.test(ref.referenceName)) { + if (ref.language === 'elixir') { + const q = /^(.*)::(.+)\/(\d{1,3})$/.exec(ref.referenceName); + if (q) { + const prefix = `${q[1]}::${q[2]}/`; + const callArity = Number(q[3]); + const sameName = keepForRef(context.getNodesByName(q[2]!)).filter( + (n) => + n.language === 'elixir' && + n.kind === 'function' && + n.qualifiedName.startsWith(prefix) && + /^\d{1,3}$/.test(n.qualifiedName.slice(prefix.length)), + ); + if (sameName.length === 1) { + const defArity = Number(sameName[0]!.qualifiedName.slice(prefix.length)); + if (defArity >= callArity) { + return { + original: ref, + targetNodeId: sameName[0]!.id, + confidence: 0.8, + resolvedBy: 'qualified-name', + }; + } + } + } + } + return null; + } // An arity-LESS qualified ref (dynamic MFA whose args list wasn't a // static literal): resolve only when the module defines exactly ONE arity // of that function; several arities with no signal is a guess. @@ -2548,16 +2580,16 @@ export function matchReference( }; } - // Erlang call/fun refs carry the call-site arity (`f/1` — #1610) because - // arity is part of the function's identity and every erlang function's + // Erlang / Elixir call/fun refs carry the call-site arity (`f/1`) because + // arity is part of the function's identity and every function's // qualifiedName carries it (`mod::f/1`). Resolve ONLY to a definition of // that exact arity: the call site's own file first (a local call targets its - // own module by language semantics; `-import`ed functions ride the - // cross-file branch), and when no definition of that arity exists anywhere, - // resolve to NOTHING rather than a sibling arity — the real target may be - // macro-generated or out of repo, and a wrong-arity edge is worse than none. + // own module by language semantics), and when no definition of that arity + // exists anywhere, resolve to NOTHING rather than a sibling arity — except + // Elixir default-args (`def foo(a, b \\ 1)` indexes as foo/2): a shorter + // local call matches when the file defines exactly one function of that name. if ( - ref.language === 'erlang' && + (ref.language === 'erlang' || ref.language === 'elixir') && !ref.referenceName.includes('::') && (ref.referenceKind === 'calls' || ref.referenceKind === 'references') ) { @@ -2565,11 +2597,12 @@ export function matchReference( if (am) { // endsWith is length-anchored, so `/1` cannot match `…/11`. const arityTail = `/${am[2]}`; + const lang = ref.language; const candidates = context .getNodesByName(am[1]!) .filter( (n) => - n.language === 'erlang' && n.kind === 'function' && n.qualifiedName.endsWith(arityTail), + n.language === lang && n.kind === 'function' && n.qualifiedName.endsWith(arityTail), ); if (candidates.length > 0) { const sameFile = candidates.find((n) => n.filePath === ref.filePath); @@ -2590,6 +2623,18 @@ export function matchReference( }; } } + if (lang === 'elixir') { + const callArity = Number(am[2]); + const sameFile = context + .getNodesByName(am[1]!) + .filter((n) => n.language === 'elixir' && n.kind === 'function' && n.filePath === ref.filePath); + if (sameFile.length === 1) { + const defArity = Number(/\/(\d{1,3})$/.exec(sameFile[0]!.qualifiedName)?.[1]); + if (Number.isFinite(defArity) && defArity >= callArity) { + return { original: ref, targetNodeId: sameFile[0]!.id, confidence: 0.8, resolvedBy: 'exact-match' }; + } + } + } return null; } } diff --git a/src/types.ts b/src/types.ts index 44ffaf4e4..77558e9c7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -117,6 +117,7 @@ export const LANGUAGES = [ 'cobol', 'vbnet', 'erlang', + 'elixir', 'terraform', 'unknown', ] as const; From 2cc2df26e848a5e59d6933e433bceee20cd57909 Mon Sep 17 00:00:00 2001 From: Derek Clair Date: Fri, 4 Sep 2026 01:17:21 -0600 Subject: [PATCH 2/2] fix: Elixir aliases, imports, local calls, and defimpl scopes Aliases and imports now apply in source order, including inside a function (copied maps, popped per clause). An explicit import only: list emits the qualified target and not the bare name. Local Elixir calls resolve to the caller's enclosing module. Each defimpl is its own module scope so two implementations in one file no longer share callback names. --- CHANGELOG.md | 2 +- __tests__/elixir-arity-resolution.test.ts | 43 +++++++ __tests__/extraction.test.ts | 131 ++++++++++++++++++- src/extraction/languages/elixir.ts | 147 +++++++++++++--------- src/resolution/name-matcher.ts | 56 ++++++++- 5 files changed, 310 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb8899468..b37a69aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### New Features -- CodeGraph now indexes **Elixir** (`.ex`, `.exs`) — modules, functions and macros (with clauses and arities of the same name grouped as one symbol), `defp` visibility, `@spec` signatures, `@doc` docs, structs with their fields, `@type`/`@opaque` aliases, protocols and implementations, plus `alias`/`import`/`require`/`use`. Cross-module `Mod.fun(...)` calls resolve through aliases, `|>` pipes and `&fun/arity` captures are followed, `apply`/`spawn` that name a module and function as arguments link to that function, `GenServer.call/cast` on this module reaches `handle_call`/`handle_cast`, and `@behaviour` names the callback module. Re-index Elixir projects after upgrading. +- CodeGraph now indexes **Elixir** (`.ex`, `.exs`) — modules, functions and macros (with clauses and arities of the same name grouped as one symbol), `defp` visibility, `@spec` signatures, `@doc` docs, structs with their fields, `@type`/`@opaque` aliases, protocols and implementations, plus `alias`/`import`/`require`/`use`. Cross-module `Mod.fun(...)` calls resolve through aliases, `|>` pipes and `&fun/arity` captures are followed, `apply`/`spawn` that name a module and function as arguments link to that function, `GenServer.call/cast` on this module reaches `handle_call`/`handle_cast`, and `@behaviour` names the callback module. Aliases apply in source order (including inside a function), a local call resolves to the enclosing module when a file holds more than one, an explicit `import Mod, only: [...]` no longer also binds the bare name, and each `defimpl` is its own scope so two implementations in one file no longer share callback names. Re-index Elixir projects after upgrading. - **A busy screen's picture is laid out by the parts of the screen.** A screen is a set of handlers with no order between them, so on a hub screen the old rows-by-distance collapsed into one enormous row — the main screen of one app put 89 boxes side by side on a canvas over 28,000px wide, every line a near-horizontal sweep across all of it. The Steps tab now groups a screen's picture by region — the component that owns each handler, named in a small caption over its boxes — with each region a column where a step sits above what it sets in motion, tiled in the screen's own source order. At rest the picture hides only two things: the screen's own fan-out — one line into each region stands in for it — and lines that point back up; every other line draws where it leads, between two regions included, and selecting a step brings out its whole story in the side panel, link by link. A box nothing points at is the screen's own doing — run on render or mount, or from a binding written inline — the key says so, and selecting it lights its line from the screen with what fires it. The same app's widest screen now lays out under 3,500px with every line local, and the whole picture fits on screen when it opens. Endpoints, handlers and the in-order reading are untouched, and nothing needs a re-index: the regions come from the same walk that draws the steps. diff --git a/__tests__/elixir-arity-resolution.test.ts b/__tests__/elixir-arity-resolution.test.ts index faa74bc6d..fcae7d1a9 100644 --- a/__tests__/elixir-arity-resolution.test.ts +++ b/__tests__/elixir-arity-resolution.test.ts @@ -94,6 +94,49 @@ end expect(edges).toContainEqual({ sq: 'Opts::run/1', tq: 'Opts::get/2' }); }); + it('resolves a local call to the enclosing module when the file has two modules', async () => { + fs.mkdirSync(path.join(dir, 'lib'), { recursive: true }); + fs.writeFileSync( + path.join(dir, 'lib', 'pair.ex'), + `defmodule First do + def work(x), do: {:first, x} + def run(x), do: work(x) +end + +defmodule Second do + def work(x), do: {:second, x} + def run(x), do: work(x) +end +` + ); + const edges = await callEdges(dir); + expect(edges).toContainEqual({ sq: 'First::run/1', tq: 'First::work/1' }); + expect(edges).toContainEqual({ sq: 'Second::run/1', tq: 'Second::work/1' }); + expect(edges.some((e) => e.sq === 'Second::run/1' && e.tq === 'First::work/1')).toBe(false); + expect(edges.some((e) => e.sq === 'First::run/1' && e.tq === 'Second::work/1')).toBe(false); + }); + + it('does not resolve an explicit import to an unrelated same-named function', async () => { + fs.mkdirSync(path.join(dir, 'lib'), { recursive: true }); + fs.writeFileSync( + path.join(dir, 'lib', 'other.ex'), + `defmodule Other do + def work(x), do: {:other, x} +end +` + ); + fs.writeFileSync( + path.join(dir, 'lib', 'client.ex'), + `defmodule Client do + import Foo, only: [work: 1] + def go(x), do: work(x) +end +` + ); + const edges = await callEdges(dir); + expect(edges.some((e) => e.sq === 'Client::go/1' && e.tq === 'Other::work/1')).toBe(false); + }); + it('resolves aliased remote calls across files', async () => { fs.mkdirSync(path.join(dir, 'lib'), { recursive: true }); fs.writeFileSync( diff --git a/__tests__/extraction.test.ts b/__tests__/extraction.test.ts index fbaa07611..d81ec2c78 100644 --- a/__tests__/extraction.test.ts +++ b/__tests__/extraction.test.ts @@ -11093,10 +11093,39 @@ end const result = extractFromSource('lib/drawable.ex', code); const proto = result.nodes.find((n) => n.kind === 'interface'); expect(proto?.name).toBe('Drawable'); - const draw = result.nodes.filter((n) => n.name === 'draw'); - expect(draw.length).toBeGreaterThanOrEqual(1); + const implMod = result.nodes.find((n) => n.kind === 'module' && n.name === 'Drawable.User'); + expect(implMod?.qualifiedName).toBe('Drawable.User'); + const draw = result.nodes.find((n) => n.kind === 'function' && n.name === 'draw' && n.qualifiedName !== 'Drawable::draw/1'); + expect(draw?.qualifiedName).toBe('Drawable.User::draw/1'); const impl = result.unresolvedReferences.find((r) => r.referenceKind === 'implements'); expect(impl?.referenceName).toBe('Drawable'); + expect(impl?.fromNodeId).toBe(implMod?.id); + }); + + it('should give each top-level defimpl its own scope so callbacks do not share qnames', () => { + const code = `defprotocol Drawable do + def draw(data) +end + +defimpl Drawable, for: User do + def draw(user), do: user.name +end + +defimpl Drawable, for: Post do + def draw(post), do: post.title +end +`; + const result = extractFromSource('lib/drawable.ex', code); + const draws = result.nodes + .filter((n) => n.kind === 'function' && n.name === 'draw' && n.qualifiedName.startsWith('Drawable.')) + .map((n) => n.qualifiedName) + .sort(); + expect(draws).toEqual(['Drawable.Post::draw/1', 'Drawable.User::draw/1']); + const impls = result.unresolvedReferences.filter((r) => r.referenceKind === 'implements'); + expect(impls).toHaveLength(2); + const userMod = result.nodes.find((n) => n.qualifiedName === 'Drawable.User'); + const postMod = result.nodes.find((n) => n.qualifiedName === 'Drawable.Post'); + expect(impls.map((r) => r.fromNodeId).sort()).toEqual([postMod?.id, userMod?.id].sort()); }); }); @@ -11156,6 +11185,104 @@ end expect(calls).toContain('Foo.Bar::qux/0'); }); + it('should apply aliases in source order, not the final binding for the whole module', () => { + const code = `defmodule M do + def early(id), do: Repo.get(id) + + alias A.Repo + + def mid(id), do: Repo.get(id) + + alias B.Repo + + def late(id), do: Repo.get(id) +end +`; + const result = extractFromSource('lib/m.ex', code); + const byFn = (name: string) => { + const fn = result.nodes.find((n) => n.kind === 'function' && n.name === name); + return result.unresolvedReferences + .filter((r) => r.referenceKind === 'calls' && r.fromNodeId === fn?.id) + .map((r) => r.referenceName); + }; + expect(byFn('early')).toContain('Repo::get/1'); + expect(byFn('early').some((c) => c.startsWith('A.Repo') || c.startsWith('B.Repo'))).toBe(false); + expect(byFn('mid')).toContain('A.Repo::get/1'); + expect(byFn('late')).toContain('B.Repo::get/1'); + }); + + it('should expand aliases and imports declared inside a function without leaking them', () => { + const code = `defmodule M do + def one(id) do + alias MyApp.Repo + Repo.get(id) + end + + def two(id) do + Repo.get(id) + end + + def three(x) do + import Foo, only: [work: 1] + work(x) + end + + def four(x), do: work(x) +end +`; + const result = extractFromSource('lib/m.ex', code); + const byFn = (name: string) => { + const fn = result.nodes.find((n) => n.kind === 'function' && n.name === name); + return result.unresolvedReferences + .filter((r) => r.referenceKind === 'calls' && r.fromNodeId === fn?.id) + .map((r) => r.referenceName); + }; + expect(byFn('one')).toContain('MyApp.Repo::get/1'); + expect(byFn('two')).toContain('Repo::get/1'); + expect(byFn('two').some((c) => c.startsWith('MyApp.Repo'))).toBe(false); + expect(byFn('three')).toEqual(['Foo::work/1']); + expect(byFn('four')).toEqual(['work/1']); + }); + + it('should not leak function-local aliases across multi-clause heads', () => { + const code = `defmodule M do + def foo(:a) do + alias A.Repo + Repo.get(1) + end + def foo(:b) do + Repo.get(2) + end +end +`; + const result = extractFromSource('lib/m.ex', code); + const foo = result.nodes.find((n) => n.kind === 'function' && n.name === 'foo'); + const calls = result.unresolvedReferences + .filter((r) => r.referenceKind === 'calls' && r.fromNodeId === foo?.id) + .map((r) => r.referenceName); + expect(calls).toContain('A.Repo::get/1'); + expect(calls).toContain('Repo::get/1'); + }); + + it('should emit only the qualified target for an explicit import only: list', () => { + const code = `defmodule M do + import Foo, only: [work: 1] + + def go(x) do + work(x) + x |> work() + end +end +`; + const result = extractFromSource('lib/m.ex', code); + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls.filter((c) => c === 'Foo::work/1' || c === 'work/1').sort()).toEqual([ + 'Foo::work/1', + 'Foo::work/1', + ]); + expect(calls).not.toContain('work/1'); + }); + it('should count piped calls with +1 arity and capture &fun/arity', () => { const code = `defmodule M do def piped(list) do diff --git a/src/extraction/languages/elixir.ts b/src/extraction/languages/elixir.ts index 326edee77..f0dbc8604 100644 --- a/src/extraction/languages/elixir.ts +++ b/src/extraction/languages/elixir.ts @@ -154,6 +154,17 @@ function importOnly(): Map { return importOnlyStack[importOnlyStack.length - 1]!; } +/** Copy of the current maps — function-local alias/import must not leak. */ +function pushCopiedDirectives(): void { + aliasStack.push(new Map(aliases())); + importOnlyStack.push(new Map(importOnly())); +} + +function popDirectives(): void { + aliasStack.pop(); + importOnlyStack.pop(); +} + function currentModule(): string | null { return moduleStack[moduleStack.length - 1] ?? null; } @@ -342,13 +353,10 @@ function collectImportOnly(call: SyntaxNode, source: string): void { } } -function collectDirectives(body: SyntaxNode, source: string): void { +function visitNamedChildren(body: SyntaxNode, ctx: ExtractorContext): void { for (let i = 0; i < body.namedChildCount; i++) { const child = body.namedChild(i); - if (!child || child.type !== 'call') continue; - const ident = targetIdent(child, source); - if (ident === 'alias') collectAlias(child, source); - else if (ident === 'import') collectImportOnly(child, source); + if (child) ctx.visitNode(child); } } @@ -380,13 +388,10 @@ function handleDefmodule(node: SyntaxNode, ctx: ExtractorContext, kind: 'module' importOnlyStack.push(new Map()); moduleStack.push(name); ctx.pushScope(mod.id); - if (body) { - collectDirectives(body, ctx.source); - for (let i = 0; i < body.namedChildCount; i++) { - const child = body.namedChild(i); - if (child) ctx.visitNode(child); - } - } + // Visit in source order so alias/import bindings apply only after they + // appear (Elixir aliases are lexical). Pre-collecting every directive + // left the last binding active for the whole module. + if (body) visitNamedChildren(body, ctx); ctx.popScope(); moduleStack.pop(); aliasStack.pop(); @@ -410,7 +415,9 @@ function handleDefun(node: SyntaxNode, ctx: ExtractorContext): boolean { } } ctx.pushScope(lastFnId); + pushCopiedDirectives(); visitBody(node, ctx); + popDirectives(); ctx.popScope(); return true; } @@ -427,6 +434,7 @@ function handleDefun(node: SyntaxNode, ctx: ExtractorContext): boolean { const modName = currentModule(); fn.qualifiedName = modName ? `${modName}::${name}/${arity}` : `${name}/${arity}`; ctx.pushScope(fn.id); + pushCopiedDirectives(); visitBody(node, ctx); if (ident === 'defdelegate') { const to = keywordValue(keywordsNode(node), 'to', ctx.source); @@ -443,6 +451,7 @@ function handleDefun(node: SyntaxNode, ctx: ExtractorContext): boolean { }); } } + popDirectives(); ctx.popScope(); lastFnName = name; lastFnArity = arity; @@ -474,45 +483,62 @@ function handleDefstruct(node: SyntaxNode, ctx: ExtractorContext): boolean { return true; } +function implTargetTypes(forType: SyntaxNode | null, source: string): string[] { + const names: string[] = []; + if (forType?.type === 'alias') names.push(expandAlias(getNodeText(forType, source))); + else if (forType?.type === 'list') { + for (const c of forType.namedChildren) { + if (c.type === 'alias') names.push(expandAlias(getNodeText(c, source))); + } + } + if (names.length === 0 && currentModule()) names.push(currentModule()!); + return names; +} + +function implModuleName(protocol: string, types: string[]): string { + if (types.length === 0) return protocol; + if (types.length === 1) return `${protocol}.${types[0]}`; + return `${protocol}.{${types.join(', ')}}`; +} + function handleDefimpl(node: SyntaxNode, ctx: ExtractorContext): boolean { const args = argumentsNode(node); - const protocol = args?.namedChildren.find((c) => c.type === 'alias'); - const forType = keywordValue(keywordsNode(node), 'for', ctx.source); - const parentId = ctx.nodeStack[ctx.nodeStack.length - 1]; - const fromId = parentId; + const protocolNode = args?.namedChildren.find((c) => c.type === 'alias'); + const protocol = protocolNode ? expandAlias(getNodeText(protocolNode, ctx.source)) : null; + const types = implTargetTypes(keywordValue(keywordsNode(node), 'for', ctx.source), ctx.source); + const implName = protocol ? implModuleName(protocol, types) : null; + const impl = implName + ? ctx.createNode('module', implName, node, { + signature: defSignature(node, undefined, ctx.source), + isExported: true, + }) + : null; + if (impl && implName) impl.qualifiedName = implName; + + const fromId = impl?.id ?? ctx.nodeStack[ctx.nodeStack.length - 1]; if (protocol && fromId) { - const targets: SyntaxNode[] = []; - if (forType?.type === 'alias') targets.push(forType); - else if (forType?.type === 'list') { - for (const c of forType.namedChildren) if (c.type === 'alias') targets.push(c); - } - // No `for:` — the impl sits inside the target module. - if (targets.length === 0 && currentModule()) { - ctx.addUnresolvedReference({ - fromNodeId: fromId, - referenceName: getNodeText(protocol, ctx.source), - referenceKind: 'implements', - line: node.startPosition.row + 1, - column: node.startPosition.column, - }); - } else { - for (const t of targets) { - ctx.addUnresolvedReference({ - fromNodeId: fromId, - referenceName: getNodeText(protocol, ctx.source), - referenceKind: 'implements', - line: t.startPosition.row + 1, - column: t.startPosition.column, - }); - } - } + ctx.addUnresolvedReference({ + fromNodeId: fromId, + referenceName: protocol, + referenceKind: 'implements', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); + } + + if (impl && implName) { + aliasStack.push(new Map()); + importOnlyStack.push(new Map()); + moduleStack.push(implName); + ctx.pushScope(impl.id); } const body = doBlock(node); - if (body) { - for (let i = 0; i < body.namedChildCount; i++) { - const child = body.namedChild(i); - if (child) ctx.visitNode(child); - } + if (body) visitNamedChildren(body, ctx); + if (impl) { + ctx.popScope(); + moduleStack.pop(); + aliasStack.pop(); + importOnlyStack.pop(); } return true; } @@ -620,15 +646,17 @@ function handleAttribute(node: SyntaxNode, ctx: ExtractorContext): boolean { type CallRef = Pick; -function emitImported(fun: string, arity: number, node: SyntaxNode, out: CallRef[]): void { +/** True when an explicit `import Mod, only: [fun: N]` covers this call. */ +function emitImported(fun: string, arity: number, node: SyntaxNode, out: CallRef[]): boolean { const mod = importOnly().get(`${fun}/${arity}`); - if (!mod) return; + if (!mod) return false; out.push({ referenceName: `${expandAlias(mod)}::${fun}/${arity}`, referenceKind: 'calls', line: node.startPosition.row + 1, column: node.startPosition.column, }); + return true; } /** @@ -693,13 +721,10 @@ export function elixirCallRefs( const right = getChildByField(node, 'right'); if (right?.type === 'identifier') { const fun = getNodeText(right, source); - const refs: Array> = [ - { referenceName: `${fun}/1`, referenceKind: 'calls', line: right.startPosition.row + 1, column: right.startPosition.column }, - ]; - const mod = importOnly().get(`${fun}/1`); - if (mod) { + const refs: Array> = []; + if (!emitImported(fun, 1, right, refs)) { refs.push({ - referenceName: `${expandAlias(mod)}::${fun}/1`, + referenceName: `${fun}/1`, referenceKind: 'calls', line: right.startPosition.row + 1, column: right.startPosition.column, @@ -714,6 +739,11 @@ export function elixirCallRefs( const ident = targetIdent(node, source); if (ident && (SPECIAL_FORMS.has(ident) || DEF_FUN.has(ident) || DEF_MOD.has(ident) || ident === 'defimpl' || ident === 'defstruct' || ident === 'defexception')) { + // Function bodies are walked via extractCall, not visitNode, so alias/ + // import inside a def never hit handleImport. Record them here against + // the function-scoped maps pushed around visitBody. + if (ident === 'alias') collectAlias(node, source); + else if (ident === 'import') collectImportOnly(node, source); return null; } @@ -722,8 +752,9 @@ export function elixirCallRefs( const refs: Array> = []; if (target?.type === 'identifier' && ident) { - refs.push({ referenceName: `${ident}/${arity}`, referenceKind: 'calls', line, column }); - emitImported(ident, arity, node, refs); + if (!emitImported(ident, arity, node, refs)) { + refs.push({ referenceName: `${ident}/${arity}`, referenceKind: 'calls', line, column }); + } maybeMfa(node, source, ident, null, refs); } else if (target?.type === 'dot') { const q = qualifyDot(target, source); @@ -841,10 +872,6 @@ export const elixirExtractor: LanguageExtractor = { visitNode: (node, ctx) => { resetState(ctx.filePath); - if (node.type === 'source') { - collectDirectives(node, ctx.source); - return false; - } if (node.type === 'unary_operator' && operatorOf(node, ctx.source) === '@') { return handleAttribute(node, ctx); } diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index 50ec43a93..968b07a14 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -2512,6 +2512,42 @@ export function dumpNameMatcherProfile(label: string): void { } } +/** `Mod::fun/N` → `Mod`; a file-level def with no module prefix yields null. */ +function elixirEnclosingModule(qn: string | undefined): string | null { + if (!qn) return null; + const sep = qn.indexOf('::'); + return sep > 0 ? qn.slice(0, sep) : null; +} + +function elixirCallerModule(ref: UnresolvedRef, context: ResolutionContext): string | null { + return elixirEnclosingModule(context.getNodeById?.(ref.fromNodeId)?.qualifiedName); +} + +/** + * Same-file Elixir defs of `name`, restricted to the caller's module when + * we know it. A later module in the same `.ex` file is not a local call. + */ +function elixirSameFileFns(context: ResolutionContext, name: string, ref: UnresolvedRef): Node[] { + const callerMod = elixirCallerModule(ref, context); + return context.getNodesByName(name).filter((n) => { + if (n.language !== 'elixir' || n.kind !== 'function' || n.filePath !== ref.filePath) return false; + if (!callerMod) return true; + return elixirEnclosingModule(n.qualifiedName) === callerMod; + }); +} + +function pickElixirEnclosingModuleDef( + candidates: Node[], + ref: UnresolvedRef, + context: ResolutionContext, +): Node | undefined { + const sameFile = candidates.filter((n) => n.filePath === ref.filePath); + if (sameFile.length === 0) return undefined; + const callerMod = elixirCallerModule(ref, context); + if (!callerMod) return sameFile[0]; + return sameFile.find((n) => elixirEnclosingModule(n.qualifiedName) === callerMod); +} + export function matchReference( ref: UnresolvedRef, context: ResolutionContext @@ -2588,6 +2624,9 @@ export function matchReference( // exists anywhere, resolve to NOTHING rather than a sibling arity — except // Elixir default-args (`def foo(a, b \\ 1)` indexes as foo/2): a shorter // local call matches when the file defines exactly one function of that name. + // Elixir files may hold several modules; a local call is scoped to the + // caller's enclosing module (`Mod::fun/N`), not the first same-name def + // in the file. if ( (ref.language === 'erlang' || ref.language === 'elixir') && !ref.referenceName.includes('::') && @@ -2605,9 +2644,16 @@ export function matchReference( n.language === lang && n.kind === 'function' && n.qualifiedName.endsWith(arityTail), ); if (candidates.length > 0) { - const sameFile = candidates.find((n) => n.filePath === ref.filePath); - if (sameFile) { - return { original: ref, targetNodeId: sameFile.id, confidence: 0.95, resolvedBy: 'exact-match' }; + if (lang === 'elixir') { + const local = pickElixirEnclosingModuleDef(candidates, ref, context); + if (local) { + return { original: ref, targetNodeId: local.id, confidence: 0.95, resolvedBy: 'exact-match' }; + } + } else { + const sameFile = candidates.find((n) => n.filePath === ref.filePath); + if (sameFile) { + return { original: ref, targetNodeId: sameFile.id, confidence: 0.95, resolvedBy: 'exact-match' }; + } } if (candidates.length === 1) { return { original: ref, targetNodeId: candidates[0]!.id, confidence: 0.8, resolvedBy: 'exact-match' }; @@ -2625,9 +2671,7 @@ export function matchReference( } if (lang === 'elixir') { const callArity = Number(am[2]); - const sameFile = context - .getNodesByName(am[1]!) - .filter((n) => n.language === 'elixir' && n.kind === 'function' && n.filePath === ref.filePath); + const sameFile = elixirSameFileFns(context, am[1]!, ref); if (sameFile.length === 1) { const defArity = Number(/\/(\d{1,3})$/.exec(sameFile[0]!.qualifiedName)?.[1]); if (Number.isFinite(defArity) && defArity >= callArity) {