Unify CLI and editor semantic navigation - #107
Merged
Merged
Conversation
injectedAliasRefs collected use sites by tokenizing every file that uses an injector before checking whether it held a candidate reference. On a large umbrella that is nearly every file: a references call for Tiger.Repo.get tokenized ~19,900 files and allocated ~2.4 GB to keep the ~200 that matter. Fetch the candidate references first and read use sites only in those files; consumerColumns never consulted any other file, so results are unchanged. scanRefStream also walked every token from the start of the file for each line it checked. Both token streams are in byte order, so binary search to the line's first token instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A hot references result such as Tiger.Factory.insert (98k locations) encoded to ~19 MB, past the 16 MiB line limit. The daemon wrote it anyway, so the client's reader gave up on the connection and every other call multiplexed on it failed too. Send lookup and references locations as a file table plus entries that index into it, in their original order. Each path is sent once, which brings that result to ~4 MB. The Go API of LookupResult and ReferencesResult is unchanged; decoding rejects a file index outside the table. writeJSONLine now refuses a line the reader would reject before writing anything, so the stream stays in step. An oversized control result fails only its own call, and a workspace/changed notification with too many paths is sent as a full change, as the runtime already does when a subscriber drops changes. The encoding is a breaking wire change, so ContractVersion is bumped to 2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A deleted reindex target resolved its workspace from the missing path itself, so outside a project the error named the deleted file as the workspace, and -y tried to start a daemon in a directory that does not exist. The search now starts from the nearest existing ancestor. A mistyped reindex path printed "Reindexed" like a real one. The daemon now checks, before pruning, whether a missing target was indexed as a file or a directory, and the CLI says when there was nothing there. It still exits 0: the index already matches the disk, and the watcher may have pruned a deleted file first. lookup --strict could answer a generated function with the defmodule line of a lexical parent, which is a fallback in a different module. The new ExactModule option, set only for strict lookups, keeps generated results to the module itself; editors keep the parent fallback that BEAM-only modules such as route helpers rely on. The daemon's headless language service never receives initialize, so DEXTER_DEBUG had no effect for CLI and MCP calls. It is now also read when the server is constructed. A new test keeps references through an injected alias from growing with the files that use the injector without naming the target (0.5 MB for 400 such files, against 77 MB before the candidate-first change). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A library that another Mix project compiles as a path dependency has no _build of its own: tiger builds libs/* inside apps/tiger. Generated functions for its modules, and for modules generated beneath them, were looked up in a build that does not exist. A module without source also took the workspace root as its build, so EORWeb.Router.Helpers was never found. Modules without source now take their nearest lexical parent's source as the hint that places them. When the hinted build has no BEAM, or the workspace holds several builds, the builds found in the workspace are asked for the owning project's application (read from its mix.exs), and the most recently compiled BEAM wins. A single build keeps the existing path unchanged. With the workspace daemon, debug lines only reached the daemon's log. Each editor session now forwards its own lines to its editor as window/logMessage through a bounded queue that drops lines rather than block a request on a slow editor, and reports how many it dropped. README and CHANGELOG describe where logs go and the CLI's semantic navigation; the issue checklist names `dexter version`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Summary
.dexterdirectoryTesting
make testmake lintgo test -race ./internal/lsp ./internal/daemon ./internal/workspaceNote
Medium Risk
Touches core navigation, daemon contract version 2 (forces daemon replacement), and reference resolution on large codebases; behavior changes are intentional but wide-reaching for CLI and editor parity.
Overview
CLI
lookupandreferencesnow use the same semantic engine as the editor — sharedLookupName/ReferenceNameson the headless LSP service coverusechains, injected aliases, generated BEAM symbols, delegates, and bare in-module calls; duplicate hits on one line are deduped.lookup --strictmaps toExactModuleso generated-only modules do not fall back to a parent’s source. Go-to-definition and find-references in the LSP delegate into the same helpers.Daemon wire protocol bumps
ContractVersionto 2 — lookup/reference payloads dedupe file paths via a file table so large reference lists stay under the 16 MiB line cap; oversize responses fail only that call, and oversizedworkspace/changednotifications downgrade to a full change.Reindex and workspace guards — reindexing a deleted file or directory prunes the index; mistyped paths report “nothing there” via
Store.HasPath/ReindexResult.Missing. Project detection requires a realmix.exs,.git, or.dexter/dexter.db, not an empty.dexterfolder; deleted reindex targets resolve the workspace from the nearest existing ancestor.Performance and monorepo BEAMs — find-references through injected aliases tokenizes only files that already have candidate refs (large monorepo fix). Generated-function lookup scans other compiled Mix projects in the workspace and picks the newest BEAM when a path-dep library has no local
_build.Debug logging — session debug lines go to the editor as
window/logMessage;DEXTER_DEBUGapplies when the headless server is constructed (CLI/daemon withoutinitialize).Reviewed by Cursor Bugbot for commit cd71354. Bugbot is set up for automated code reviews on this repo. Configure here.