2 Commits
Author SHA1 Message Date
Ayushraj06-bit 48de61551a fix(elixir): scope import/use to the declaring module, not the file
The unqualified-call scope added for #4001 collected every `import` and
`use` in a file into one list, so an import in one module leaked into a
sibling module defined in the same file: `MyApp.Sibling.go/1` calling
`fmt(x)` still bound to `MyApp.Helpers.fmt/1` because `MyApp.Importer`
imported it. Elixir scopes `import`/`use` to the module body it appears
in and to the modules nested in it.

Record targets per enclosing module, with the file's top level as its
own scope, and build each call's scope from its own module, the modules
enclosing it, and the top level. Each raw call now gets its own list
rather than sharing one mutable list with every other call in the file.
A module nested in a same-named module shares its node id, so the walk
up the enclosing chain stops at a module it has already visited.

Follow-up to #4015. Refs #4001

(cherry picked from commit e508142dac)
2026-10-04 20:23:14 +01:00
Ayushraj06-bit c96a743b0c fix(elixir): scope unqualified calls to imported and used modules
The shared cross-file call pass bound an unqualified call to any
same-named def in the corpus. In Elixir an unqualified call can only
reach the caller's own module, Kernel, or a module the file imports or
uses, so DSL calls landed on unrelated project functions: every
migration's `table(:users)` (Ecto.Migration, brought in by `use`) became
a calls edge to a Phoenix component's `table/1`, making it the top god
node.

The Elixir extractor now records, on each raw call, the modules its file
names in `import` or `use` (`alias` and `require` do not bring functions
into scope). The shared pass keeps only candidates whose file defines one
of those modules, the same way Go selectors are already filtered by
import path, and leaves the call unresolved otherwise. The module index
is read from the resolution nodes, so an unchanged file's modules still
count on an incremental rebuild.

Calls into a module that a `use` macro imports indirectly (for example
`use MyAppWeb, :live_view` importing CoreComponents) are no longer
resolved, since that import is not visible in the source.

Refs #4001

(cherry picked from commit 98d4ae9878)
2026-10-04 02:07:00 +01:00