feat(elixir): add native static module and arity resolution (#81, with the review round) - #207
Open
joyful-ii-V-I wants to merge 23 commits into
Open
feat(elixir): add native static module and arity resolution (#81, with the review round)#207joyful-ii-V-I wants to merge 23 commits into
joyful-ii-V-I wants to merge 23 commits into
Conversation
Preserve upstream's Hermes, Git hardening, and document-indexing changes alongside native Elixir resolution. Register all four added gates and derive the published loop count as 567 from the merged runner. Both branches independently used parser revision 85. Assign revision 86 and update the quality mirror and documentation so caches from either branch are rejected. Preserve both extraction histories in the tripwire log; refresh its hash in a separate golden-only commit. Keep README source locations from the correct side of each merge.
Upstream advanced past this branch's previous merge with the ChaConeMemo warm-floor fix, the tgrep --regex line-anchor harvest and the --for --detail max_tokens disclosure. Five files conflicted, all of them counters or captures: - test/regression.sh: the gate loop is the sorted UNION — this branch's elixirsemanticcheck plus upstream's chaconecheck, formaxtokenscheck and grepanchorcheck. 570 gates, derived from the merged runner, never carried. - README.md, docs/EVALS.md, present/deck5_ripwire_build.js: the published gate count follows that loop to 570. - README.md's --callers example rows were stale on BOTH sides after graph.h moved; re-captured from the merged binary (readmeexamplecheck passes). - CHANGELOG.md: both Unreleased entries kept. The Elixir entry said parser version 85, the revision this branch used before integration; the integrated extractor is 86 (src/ingest_cache.h, mirrored in src/quality.h, logged in qschemetripcheck). Corrected — the CHANGELOG is where a cache-compatibility reader looks first. Verified on the merged tree: clean rebuild, 570-gate suite (576 pass / 4 skip / 4 fail, every failure reproduced as environmental or pre-existing — clang 14 rejecting a C++20 structured-binding capture in graph.h, a missing /usr/bin/time, and recallpassagecheck's P10 arm which its own header declares expected-red), a clean ASan/LSan run, byte-identical repeat maps and well-formed XML. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013VUC4dGmaT2bFJvPJtsjvf
…-uses on Elixir defs Three of the six actionable review findings on #81 reproduced; this is those three. 1. src/ingest_model.h — expandElixirImplementationReferences appended a multi-target defimpl's cloned references to the TAIL of ing.references, whose contract is (fileId, startByte, name, role, isInherit) order. A clone carries its original's coordinates, so the tail was full of earlier bytes and earlier files. Two consumers read that order rather than re-deriving it: graph.h's chaUpDeclared records a derived type's direct bases in source order (Elixir's Extends refs from defimpl ARE cloned), and editpreview.h splices a re-parsed file in by partitioning on fileId, which only reproduces a real re-ingest while each file's refs are one ascending run. Each clone is now spliced in beside the reference it came from — the same position a re-sort would give it, at no sorting cost. 2. src/mcpverbs.h — the MCP uses verb gated the Elixir resolver path on `defs`, which resolveAllByName fills for EVERY language, while the CLI gates on the same list filtered to Lang::Elixir. An Elixir reference whose calleeName matched a definition in another language therefore took the resolver path in MCP, matched nothing, and vanished — while the CLI still reported it through the name filter. That is the divergence mcpclidiffcheck exists to prevent. Now filtered the same way, off the raw selector, exactly as resolveUsesSelector does. 3. docs/ARCHITECTURE.md — the Elixir prose claimed resolution the tree does not do. Four gaps reproduce on this tip and are now disclosed in Static limits rather than left to contradict the PR notes: a later `import M, except:` replaces an earlier `only:` selection instead of subtracting; a dotted nested `defmodule Inner.Deep` registers no implicit prefix alias, so `Inner.Deep.target()` resolves to nothing; `alias __MODULE__, as: Current` in a multi-target defimpl binds every implementation to the FIRST target; and `&_seed/0` is dropped by the underscore filter. Honesty in output is a feature (CLAUDE.md non-negotiable #3) — these are floors, and the document now says so. The three remaining findings did not reproduce and are unchanged: reachesAny's exact name compare is correct because no non-Call Elixir reference carries an arity suffix (they are module names and @attributes, matched against symbols whose scope is empty or the enclosing module), and eliximportcheck.sh sets `set -u`, not `set -e`, so its FAIL branch and fail=1 accounting do run. Verified: elixircheck, eliximportcheck, elixirsemanticcheck, mcpclidiffcheck, editpreviewcheck, editroundtripcheck, qschemetripcheck and qextractionkeycheck pass; multi-target defimpl output is unchanged; ASan/LSan clean on the Elixir fixtures and on the repo; repeat maps byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013VUC4dGmaT2bFJvPJtsjvf
Real conflicts (5 files) and their resolution: - test/regression.sh: both branches independently extended the gate-name loop (570 vs 572 entries). Took the UNION (573) after confirming neither side deleted a gate script that the other kept — the 3 upstream-only gates (grepignorecheck, helpbudgetcheck, rustanccheck) plus this branch's elixirsemanticcheck all exist on disk. - src/ingest_cache.h / src/quality.h: both branches independently bumped kParserVer to 86 (this branch for Elixir module/name/arity resolution, main for a Ruby receiver-dedupe fix that landed the same day). Per this codebase's own documented convention — rebasing a fork's parser version onto main means re-bumping to the next free number, never keeping the fork's value — the Elixir bump moves to 87. Rebuilt and re-pinned test/qschemetrip.hash; test/qextractionkeycheck.sh confirms the mirror. - README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every 570/572 gate-count mention reconciled to 573 (verified consistent by test/manifestcheck.sh). One deck hunk also carried an unrelated adjacent edit (43 vs 46 surveyed repos) — kept 46, the value docs/LINEAGE.md and test/readmedriftcheck.sh already treat as authoritative. Also fixed two merge-caused consequences the gate suite caught: - docs/ARCHITECTURE.md's "parser revision 86 (rich 87)" line and the CHANGELOG heading/note now read 87 (rich 88), matching the re-bump above. - The merge shifted line numbers in src/graph.h enough that the newest showcase capture's pinned seed (src/graph.h:3112) no longer resolved to rankGraphTeleport (showcasecapturecheck.sh arm H). Regenerated the capture via test/showcase_capture.py rather than hand-editing the seed. Regeneration surfaced a separate latent bug already described by the file's own "wave-3 close" comment: two --stray-content demos were still hard-coded to a "lane" branch substring instead of using the existing _refFamily fallback, so they break on any checkout without a live lane/* branch (the common case once a PR's branch is merged and deleted). Moved both onto _refFamily, matching the pattern already used two lines below them. Regenerated docs/COMMANDS.md from the fresh capture to match (test/docscommandscheck.sh arm G). Verified: test/manifestcheck.sh, test/readmedriftcheck.sh, test/qextractionkeycheck.sh, test/showcasecapturecheck.sh, test/docscommandscheck.sh, test/ripwirepubliccheck.sh, test/printffmtparitycheck.sh all ALL PASS. Full suite via test/pargates.py: 579 pass / 4 skip (all environment gated, e.g. no RIPWIRE_BASE reference binary) / 4 fail, and every failure confirmed pre-existing and unrelated to this merge by reproducing it against a pristine build of upstream/main or of this branch's own pre-merge tip: columnarcommacheck.sh (a Clang-14-specific structured-binding-capture rejection already present on upstream/main), recallpassagecheck.sh (P10 natural-language parity, already red on this branch before the merge, tracked as concurrent lane F1 work), padscalecheck.sh (a timing-sensitive scaling run, already red on upstream/main), and g1freshcheck.sh (a local, gitignored asan/ build directory predating this session, not part of the tree). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
…eview) upstream/main gained PR #99 (an opt-remarks lane, test/optremarkshotcheck.sh) while the first merge round was under review. Same union treatment as the first round: - test/regression.sh: union of both gate lists (573 + optremarkshotcheck = 574), confirmed the new script exists on disk and neither side dropped a gate the other kept. - README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every 573 gate-count mention bumped to 574, reverified by test/manifestcheck.sh. No graph.h changes this round, so the showcase-capture seed did not drift again; test/showcasecapturecheck.sh and test/docscommandscheck.sh stayed green without regenerating anything. Verified: test/manifestcheck.sh, test/qschemetripcheck.sh, test/readmedriftcheck.sh, test/docscommandscheck.sh all ALL PASS. Full suite via test/pargates.py: 580 pass / 4 skip (environment-gated) / 4 fail, the same four pre-existing, merge-unrelated failures already root-caused in the prior commit (columnarcommacheck.sh, recallpassagecheck.sh, padscalecheck.sh, g1freshcheck.sh). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
upstream/main is under continuous automated merge activity (a new lane/* PR landing roughly every 15-20 minutes); it gained test/callsrankordercheck.sh while round two was being verified and pushed. Same mechanical resolution as the prior two rounds: - test/regression.sh: union of both gate lists (574 + callsrankordercheck = 575), confirmed the new script exists on disk and no gate was dropped by either side. - README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every 574 gate-count mention bumped to 575, reverified by test/manifestcheck.sh. Verified: test/manifestcheck.sh, test/qschemetripcheck.sh, test/showcasecapturecheck.sh, test/docscommandscheck.sh, test/readmedriftcheck.sh all ALL PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
upstream/main gained a new MCP capability-disclosure lane (test/capdisclosurecheck.sh, touching src/mcpverbs.h and src/verbs_navigate.h) while round three was being verified and pushed. Both source files auto-merged cleanly (no textual overlap); only the usual two hot spots needed hand resolution: - test/regression.sh: union of both gate lists (575 + capdisclosurecheck = 576), confirmed the new script exists on disk and no gate was dropped by either side. - README.md, docs/EVALS.md, present/deck5_ripwire_build.js: every 575 gate-count mention bumped to 576, reverified by test/manifestcheck.sh. Verified: test/manifestcheck.sh, test/qschemetripcheck.sh, test/showcasecapturecheck.sh, test/docscommandscheck.sh, test/readmedriftcheck.sh, test/capdisclosurecheck.sh (the new gate itself), test/mcpverbscheck.sh, test/mcpcontractcheck.sh and test/usesselectorcheck.sh (covering the two auto-merged source files) all ALL PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011GwrshgLdo2XNQn8pQhbgz
…/arity resolution) — parser version 95 REHEARSAL ONLY — local branch pr81-rehearsal, never pushed. Resolves the 15 conflicted files of merging main into @henry-hz's head 9046edc, assuming PR #139 (kParserVer 93, kCacheVersion 21) and PR #172 (kParserVer 94) land first: - src/ingest_cache.h, src/quality.h: kParserVer / kIngestParserVerMirror 95 (branch carried 87, main 92); kCacheVersion / kIngestCacheVersionMirror 21 (#139's format; #81 changes no record shape). - src/ingest_elixir.h, src/ingest_sidecap.h: the branch's semantics kept (ElixirContext scopeOf/moduleOf, attribute refs, alias/atom/dot/__MODULE__ receivers, the refined @-attribute filter); converted to main's #127 API (fieldChild/NodeField, kindIs) since the by-name nodeFieldText overload is gone on main. NodeField gains Operand (src/infra/fieldid.h). #include <charconv> added (review item 1). - src/graph.h: PROVISIONAL accounting on the Elixir no-candidate drop — disposition Undefined/Unresolved instead of Unaccounted, so main's 6b8dc9d conservation alert stops firing on every Elixir corpus (it fired on test/elixirfix: 10 of 19 sites). No edge changes; review item 2's design choice stays open. - test/regression.sh: gate-list union (606 + elixirsemanticcheck = 607); test/gateexitcheck.sh: both rows. - test/qschemetrip.hash, test/printf_parity.manifest, gate-count sites, docs/COMMANDS.md: regenerated from the merged build. docs/captures/*: main's side (the 09-12 capture's graph.h seed now needs a ref-clean re-record: rankGraphTeleport moved 3357 -> 3371). - CHANGELOG.md, README.md, docs/ARCHITECTURE.md: both sides, renumbered to 95/21/10. Wanted gate set after this commit: gates=12 pass=11 fail=1 — the one failure is showcasecapturecheck arm (H), the seed line, which only a re-recorded capture can fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eview items 2 to 5 A gate before the code it measures (CONTRIBUTING section 2). On b0bd2cf it is red on the rows the PR #81 review named: a call delivered by `use` was dropped with no header count; a variable bound on the right of `=` in a pattern became a zero-arity call of a same-named function; --edit-check read run(x) -> run(x, y) as new-symbol with 0 callers; --for by an exact function name routed name-exact and then scored nothing (no_candidates). Its controls are green on the same binary: the lexical import that makes the same call resolve, the body-match calls that must keep their edge, a clean-tree edit-check, the explicit name/N spelling, and the nested-module import and attribute-read use-sites behind the reachesAny finding. Listed in test/regression.sh; the gate count regenerates to 608. Red by design until the commits that follow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…pped without a count With no lexical candidate the resolver continued out of the resolve loop; no edge was minted (correct: a same-spelled function in an unrelated module is the false edge it exists to refuse) but nothing recorded the drop, so a caller set could shrink 55 -> 3 with every gauge reading zero. The rehearsal merge's provisional one-liner named a disposition and nothing else, which declinecheck arm F now shows was internally inconsistent: census unresolved=2 beside header unresolved=1. Decision (review item 2): count, never guess. A spelling some in-repo definition carries is unresolved (the header gauge and the caller's own unresolvedOut, the vocabulary the name ladder already uses for a lang-filtered name); a spelling no definition carries is undefined, which has no header surface by design; in a multi-root run a name defined only in another root is that root's, OtherRoot. Modelling what __using__ injects stays open. declinecheck's Elixir row is re-pinned to the same rule: its fixture called ex_hop(m) against two `def ex_hop do` (arity 0), an arity no definition carries, so under name/N the call was undefined rather than the two-candidate decline the arm meant to exercise. The call is now ex_hop(); Elixir never reaches the tier-3 ladder, so the refusal reads as unresolved=2 (header and every answer's graph_unresolved=) and declined= is 16, not 17. The arm was already red on b0bd2cf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…came a zero-arity call
bindingScope answered "not a binding" the moment it met a `=` whose left side did not
contain the identifier, so in `def join(%Socket{} = socket, _)`, a `%S{} = s ->` clause
or a `{:ok, %{} = m} <- x` generator the right-hand variable was never recorded; its later
reads in the body were bare identifiers with no visible binding and resolved as calls of a
same-named zero-arity function (12 false callers of one socket/0 on a framework corpus).
The right of `=` binds exactly when the whole match sits in a pattern, and only the
construct above can say so: the walk now continues upward from such a `=` and lets the
def head, stab clause or generator decide. A body-level `x = y` reaches the def head, is
outside it, and stays a call, which the rhs/0 and bare_rhs/0 controls pin. `<-` and `\\`
are unchanged: their right sides are an expression and a default value.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…o callers Elixir keys a callable as name/N, so run(x) -> run(x, y) renamed run/1 to run/2: the quality key (path, scope, name) no longer matched the HEAD baseline (new-symbol), the in-edge walk found nothing (no reference spells run/2) and --quality-delta reported a dead symbol beside a brand-new one. The callers the edit had just broken were the rows the verb exists to print, and it printed none. The quality key now folds the arity out of an Elixir name through one Symbol overload of pathQualifiedKey, the single keying rule every site (quality, merge-scout, lanes) goes through: run/1 and run/2 are two entities (canonicalId keeps the arity) but one piece of source, as C++ overloads of f already are. That is a change of what a cached Snapshot means, so kQSnapCacheScheme is 11 and the tripwire is re-pinned. --edit-check folds the overload set and its ambiguity groups the same way, recovers the old arity's callers through a fold-arity ElixirResolver (the caller's own aliases, imports and receiver, asked about the function rather than one arity of it), and flags them: an Elixir clause's arity is exact unless a default widens it, which arityExact now says (cc_paramArityExact's language gate had left every Elixir definition unflaggable). run(x, y \\ 1) reports the contract change and flags nobody. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ame/N The router's whole-name index and the name-exact scorer compared the query token with the symbol name byte for byte, so `generate_phoenix_app` routed name-exact on its snake shape, matched no whole name, and the ranking came back empty (no_candidates); a plain word such as `text` did not route at all. The arity-less spelling of an Elixir name/N is now a second whole-name token in the index and the scorer (one document token either way, so every other language scores byte-identically), and the body head's anchor test accepts it too: the anchor resolved to the right file and then filtered its own definition out of the head, leaving bodies="0" reason="no_candidates" beside a correct first row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…us through `$?` after the fact The gate runs under `set -u`, not `set -e`, so the FAIL branch was reachable; but the verdict was taken from `$?` on the line after the heredoc in an `A && ok || no` chain (ShellCheck SC2181/SC2015). The python block is now the condition of an if, so a failed assertion is a FAIL row and fail=1 by construction. Proven live: with `def go` renamed in a fixture copy the gate prints `FAIL alias call resolution failed` and exits 1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The entry already names parser version 95 and cache format 21; it now records the four review findings closed on the branch, the use-delivered drop's disclosure, the pattern binding, the arity fold behind --edit-check (snapshot scheme 10 -> 11) and --for by exact name, each with its row in test/elixirnamearitycheck.sh. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s 95 over #139's 93, absorb loop unioned, pins re-derived Eight conflicts: version ladders, re-pin logs, the absorb loop and generated counts. No Elixir or Ruby logic conflicted. #172 (kParserVer 94) is merged next, so this commit's 95 already sits over both. - src/ingest_cache.h, src/quality.h: kParserVer and kIngestParserVerMirror stay 95; both notes kept, 95 above 93. kCacheVersion 21 keeps main's description of #139's format change, plus the branch's note that #81 appends RecvKind / LocalBindKind enumerators to the existing u8 and changes no record shape. - test/qschemetripcheck.sh: both RE-PIN LOG entries, the Elixir pair above #139's. - test/qschemetrip.hash: re-derived on the merged tree (UPDATE_GOLDEN=1 starting from main's value). It equals the branch's pre-merge ce851b68: main changed no manifest function, and the branch already declared 95 over 21. - test/regression.sh: main's loop order kept, elixirsemanticcheck and elixirnamearitycheck inserted where the branch had them (609). - README.md, docs/EVALS.md, present/deck5_ripwire_build.js: gate count regenerated by docs/gatecount_build.py (609 at 8 sites). - CHANGELOG.md merged clean: the Elixir entry (parser version 95) and #139's Ruby entry both kept. Binary-derived outputs (test/printf_parity.manifest, docs/COMMANDS.md, the showcase capture) are re-derived after the #172 merge, from one clean build of the combined tree. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#172's 94, captureTagsFacts takes both parameters, pins re-derived REHEARSAL, local only: #172 (the `#if 0` filter over every role and definition) is not merged yet. Its head is based on main 558a2e0, which the previous commit already brought in, so once #172 lands the final `git merge origin/main` has nothing left to resolve here. Ten conflicts; two are code. - src/ingest_sidecap.h, src/ingest_parsepool.h: captureTagsFacts keeps both new parameters — #81's Elixir bind/include outputs and #172's decided-dead ranges, walked once per file by the worker — as (..., defs, refs, binds, includes, ppDead), and both call sites pass both. The function-local ppDead recompute the branch still carried is gone. #172's firstRefOfFile window is taken before ElixirContext::prepare, so it spans every ref the function appends. At the tail #172's filter runs first ("before anything else reads either one"), then #81's defimpl expansion, then foldFieldDefs. The order changes no output: preprocDeadRangesFor is empty for every non-C-family language, so the filter is a no-op on an Elixir file and the expansion never runs on a C-family one. One comment paragraph says why the bind/include windows the function now appends (Elixir only) are not filtered. - src/ingest_cache.h, src/quality.h: kParserVer and kIngestParserVerMirror 95; notes kept 95 / 94 / 93. kCacheVersion 21: neither #172 nor #81 changes a record shape. - test/qschemetripcheck.sh: #172's RE-PIN LOG entry kept under the Elixir pair, which records the second re-derivation. - test/qschemetrip.hash: re-derived (UPDATE_GOLDEN=1 starting from #172's 045d24c5) = ce851b68, the branch's own value: neither #139 nor #172 touched a manifest function or kMergeDiffArgs, and the hashed declaration lines read 95 over 21. - test/regression.sh: #172's loop order kept, elixirsemanticcheck and elixirnamearitycheck where the branch had them (610). - README.md, docs/EVALS.md, present/deck5_ripwire_build.js: gate count regenerated by docs/gatecount_build.py (610 at 8 sites). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the changelog entry ran into Upgrade notes The note beside kParserVer in src/ingest_cache.h was written for the rehearsal merge, before review item 4 moved kQSnapCacheScheme 10 -> 11 for the arity-key fold. It now says that move belongs to quality.h's key, not to the extraction change the note records. CHANGELOG.md: the Elixir entry's last paragraph ran straight into `### Upgrade notes` with no blank line. Comments and prose only: kParserVer 95, kCacheVersion 21 and kQSnapCacheScheme 11 do not move, and test/qschemetripcheck.sh hashes only the declaration lines, so its pin stays ce851b68. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nkGraphTeleport seed moved to graph.h:3406 showcasecapturecheck arm (H) was red on the merged tree: the published --at=src/graph.h:3362 seed no longer resolved to rankGraphTeleport once #81's graph.h lines landed above it. Recorded by test/showcase_capture.py, which re-derives the seed via bodySeed, in a ref-clean clone: detached at f92a54d, no remote configured, local refs limited to public main, the v* tags and the public lane/* branches, TMPDIR empty. The generator reads the checkout's local branch names, so a machine's own lane names would otherwise be published. Checked by hand before copying back: the 8 lane/* names are all in main's capture or on the public remote; no absolute home, temp or scratch path; no private corpus name, no email. 52 headings carry a recorded exit code in both main's capture and this one, and none changed; the one renamed heading is the --stray-content ref family the generator picks from local refs (`lane/` where main's says `lane`). docs/COMMANDS.md regenerated from the new samples (175 flags, 161 samples, --check clean). Gates: showcasecapturecheck, ripwirepubliccheck, docscommandscheck, gatecountcheck, manifestcheck — gates=5 pass=5 skip=0 fail=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…free, the tree is unchanged Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 5 minutes. View limit detailsLimit details: You’ve used all 4 included reviews currently available. This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (49)
Comment |
This was referenced Sep 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is @henry-hz's Elixir work from #81, finished with the review round. GitHub refuses maintainer pushes to the fork's branch, so the finished branch comes from this repository instead. Henry's commits are unchanged and keep their authorship; the maintainer commits sit on top as merges and fixes, with no rebase and no squash. Because #81's head commit is part of this branch, #81 shows as merged when this one merges.
From #81 (@henry-hz)
Elixir calls resolve natively by module, name and arity through the existing tree-sitter pipeline, with no Elixir, Mix or language-server dependency.
alias Real.Work, as: Wfollowed byW.run(x)resolves toReal.Work::run/1, never to an unrelated module'srun/1.Macro expansion and runtime dispatch stay static-analysis limits, documented in
docs/ARCHITECTURE.md#elixir-extraction.The review round (maintainer commits)
#if 0stopped serving calls and went on serving every other role #172: parser version 95 (kParserVerand itsquality.hmirror), cache format 21 unchanged, 610 gates.captureTagsFactstakes both fix(ingest):#if 0stopped serving calls and went on serving every other role #172's dead ranges and the Elixir outputs; the order changes no output.usecould answer now count in the map header'sunresolved=and every answer'sgraph_unresolved=instead of disappearing.__using__is still not modelled.def join(%Socket{} = socket, _),socketis a binding, so reads of it are no longer zero-arity calls of a same-named function.run(x)→run(x, y)is a--edit-checkcontract change with every old-arity caller flagged, and a--quality-deltaparams row, instead of a dead symbol beside a new one (kQSnapCacheScheme10 → 11). A default argument still reports the change and flags nobody.--forby a bare function name (generate_app) routes name-exact and ranks thename/Nsymbol first.eliximportcheck.shFAIL branch is nowif …; then ok; else no; fi. ThereachesAnyexact-name finding is declined, with the reason on its thread.declinecheck's Elixir fixture callsex_hop()with the arity the fixture defines.rankGraphTeleportseed moved tosrc/graph.h:3406.Evidence
test/elixirnamearitycheck.sh(26 rows): red on the pre-review binary on exactly the reviewed rows, green on every control.elixircheck8/8,eliximportcheck22/22,elixirsemanticcheck1/1,elixirnamearitycheck26/26, with the same counts under ASan and no sanitizer output. LeakSanitizer is clean on the repo and the Elixir fixtures.🤖 Generated with Claude Code