Elixir: every alias/import edge is dropped at build — definition ids carry a file-stem prefix, reference ids do not
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
- #3566 de @pavanetti — cerrado sin fusionar
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 35/100
Línea de trabajo
Start in elixir.py around the definition and alias/import target ID generation, then trace build_from_json and compare the existing _resolve_kotlin_import_targets path. Reproduce with the supplied graphify update example and inspect graph.json. Done means valid Elixir module dependency edges survive the build while unresolved external modules remain dangling.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Version: 0.9.61 (fe66389) · macOS · Python 3.14
Summary
extract_elixir mints a module definition id as _make_id(file_stem, module_name) but mints the target of an alias/import/require/use edge as _make_id(module_name), with no stem. The two can never be equal, so build_from_json's node-set prune drops the edge and Elixir's entire module-dependency layer disappears from the graph.
The failure is silent in the way that matters: extraction reports no error, both endpoints exist as nodes, the file parses, the node count looks right. Only the edge is missing. A module aliased by a dozen callers reports degree 2, and community detection degenerates to roughly one community per file.
extract_elixir already assumes something downstream will reconcile this — its own dangling-edge filter deliberately exempts relation == "imports" so these edges survive the extractor. Nothing downstream ever resolves them.
Reproduction
mkdir -p repro/lib/my_app
cat > repro/lib/my_app/repo.ex <<'EOF'
defmodule MyApp.Repo do
def insert(x), do: x
end
EOF
cat > repro/lib/my_app/user.ex <<'EOF'
defmodule MyApp.User do
alias MyApp.Repo
def save(x), do: Repo.insert(x)
end
EOF
graphify update repro
python -c "
import json, collections
g = json.load(open('repro/graphify-out/graph.json'))
print(collections.Counter(e['relation'] for e in g['links']))"
No imports edge reaches graph.json. The extractor emitted one.
The two conflicting ids
lib/my_app/repo.ex NODE lib_my_app_repo_myapp_repo label 'MyApp.Repo' # elixir.py:119
lib/my_app/user.ex alias ... EDGE imports -> myapp_repo # elixir.py:167
lib_my_app_repo_myapp_repo != myapp_repo.
Measured impact
A 980-file Phoenix/Ecto application (lib/ only), graphify 0.9.61:
| before | after fix | |
|---|---|---|
imports edges emitted |
4,292 | 4,292 |
| surviving the build | 0 (0.0%) | 3,531 (82.3%) |
| cross-file edge share | 8.1% | 27.4% |
| Louvain communities / single-file | 562 / 445 | 113 / 49 |
Whole repo (2,470 .ex/.exs): 8,570 emitted, 0 surviving → 6,390 (74.6%). The residual unresolved are genuine externals (Logger, Ecto.Query, deps) with no node in the corpus, which correctly stay dangling.
Source contains 2,805 real alias/import statements; graph.json contained 28 imports edges.
Why the per-file extractor cannot fix it
An Elixir alias names a BEAM module, not a path, so extract_elixir — which sees one file at a time — cannot know which file defines it. Guessing a path from Macro.underscore conventions breaks on umbrella apps, :elixirc_paths, acronym modules (HTTPClient → http_client), and multi-module files. So the target_file approach from #2195 (which resolves path-valued specifiers on disk) does not apply here.
This is the same shape as Kotlin #2526, whose own docstring describes the identical symptom: "That target dangles (node ids carry a file-stem prefix), so build pruned every Kotlin import."
Note: no cross-module call edges either
Independent of this bug, extract_elixir emits no cross-module call edge in any style — Bar.run(x) after alias, and fully-qualified MyApp.Foo.Bar.run(x), both produce nothing. Fixing the ids therefore restores the module dependency layer, not a call graph. Worth stating so the improvement is not over-read.
The same asymmetry exists in other extractors
While confirming the above, the pattern definition = _make_id(stem, name) / reference = _make_id(name) was reproduced with 0 surviving cross-file edges in: Rust (use), Fortran, Julia, Apex, Verilog, Razor, Blade, Dart, Scala, Groovy, Zig, and Pascal (different root cause, same symptom). Partial loss in Go, PowerShell, Ruby, OCaml.
Two failure modes: dangling (target matches nothing, pruned) and sourced ghost (the reference site calls add_node, minting a duplicate stub attributed to the referencing file). Python, TS/JS, Svelte/Vue/Astro, PHP, C, C++, Obj-C, C#, Kotlin, Swift, Lua, SQL, Common Lisp, Bash verified OK.
Happy to split that into a separate tracking issue — flagging it here only because the Elixir fix is one instance of it.
Proposed fix
PR to follow: stamp the written module name as metadata.target_fqn and repoint the edge in a corpus-wide resolver, guarded on a single candidate so nothing is fabricated — mirroring _resolve_kotlin_import_targets. Definition ids are left untouched, so existing graphs keep their node ids.
- Lenguaje dominante
- Python
- Estrellas
- 124k
- Forks
- 11.9k
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Graphify-Labs/graphify
-
hooks: last-resort `python3` probe launches the Microsoft Store redirector on Windows (visible console flash, exit 9009)Posiblemente ocupada @Deepjyoti-Sarmah la tomó hace 6 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Graphify-Labs/graphify#4563 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
GRAPHIFY_DISABLE_THINKING is ignored by the claude backend, so thinking eats max_tokens and extraction truncatesPosiblemente ocupada @bercedev la tomó hace 7 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 69/100
Graphify-Labs/graphify#4546 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
--update runbook: graph.json backup instruction comes after the diff that needs it, so the graph diff never runsPosiblemente ocupada @sunildivakar96-cpu la tomó hace 7 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Graphify-Labs/graphify#4539 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
[Bug] Pi skill uses unsupported general-purpose subagent instead of delegateQuizá libre de nuevo @bercedev la tomó hace 9 días y no hay ningún pull request abierto. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Graphify-Labs/graphify#4494 · 7 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
Graphify-Labs/graphify#3763 ·
Los mantenedores suelen responder en 1 día
Todos los issues de Graphify-Labs/graphify
Issues similares
-
The changelog workflow excludes otelbot but not dependabot, so every Dependabot pull request fails the changelog checkPosiblemente ocupada @ocelotl la tomó hoy. Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
open-telemetry/opentelemetry-python#5825 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
cuga-project/cuga-agent#1020 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 70/100
microsoft/playwright#43640 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
stac-utils/stac-fastapi-elasticsearch-opensearch#965 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Los mantenedores suelen responder en 1 día