feat: discovery-first tool resolution (make Mason optional)#21
Open
charliie-dev wants to merge 4 commits into
Open
feat: discovery-first tool resolution (make Mason optional)#21charliie-dev wants to merge 4 commits into
charliie-dev wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements a discovery-first tool resolution model so that tools already available on $PATH (system-provided or Mason-provided) are used directly, while Mason becomes an optional installer backend rather than a hard runtime gate. This supports environments like NixOS/FreeBSD where Mason-installed binaries may be unavailable or undesirable.
Changes:
- Add shared helpers for
$PATHprobing, Masonspec.binextraction, and aggregated “missing tools” warnings. - Rework LSP and DAP setup to be driven by desired dependency lists with discovery-first resolution and deferred installs.
- Update Mason bootstrap for formatters/linters to only install when the tool isn’t already on
$PATH, aggregating missing-tool warnings.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| lua/modules/utils/tools.lua | New helper module for executable discovery + aggregated missing-tool warnings. |
| lua/modules/configs/tool/dap/init.lua | Switch DAP setup to discovery-first resolution instead of mason-nvim-dap’s installed-only handler gating. |
| lua/modules/configs/completion/servers/shuck.lua | Update server comment to reflect the new discovery-first resolution model. |
| lua/modules/configs/completion/mason.lua | Only install formatter/linter packages when not already available on $PATH; aggregate missing warnings. |
| lua/modules/configs/completion/mason-lspconfig.lua | Drive LSP setup via discovery-first resolution + deferred installs, using mason-lspconfig mappings. |
| lua/modules/configs/completion/lsp.lua | Remove external_lsp_deps wiring; rely on centralized discovery-first LSP setup. |
| lua/core/settings.lua | Collapse external/system LSP list into unified lsp_deps list with discovery-first semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
06a08f0 to
f59ded6
Compare
f59ded6 to
60ff088
Compare
60ff088 to
33c45cb
Compare
33c45cb to
2c843f0
Compare
2c843f0 to
b6144a1
Compare
Introduce modules/utils/tools.lua: a shared layer that treats Mason as one installer backend rather than a hard requirement. Provides any_executable ($PATH probe), package_binaries (a package's declared binaries), and missing_collector — a per-subsystem aggregator that reports tools which could not be set up in a single deferred warning. The collector has two buckets: mark (a real tool that isn't available — install it) and mark_unknown (a name the installer registry doesn't recognize — a typo or outdated name to fix in config), rendered as separate cause-appropriate sections. track() performs the async install itself under pcall, so a package whose install() errors or returns a bad handle is recorded as missing instead of aborting the caller's resolution loop; its "closed" handler runs on the main loop via vim.schedule_wrap (Mason fires it from a fast event context) and pcalls recheck() so a throwing recheck can't leave the warning permanently suppressed.
Drive LSP server setup discovery-first via the shared tools helper: a server already on $PATH (system / Nix / Mason) is configured as-is; otherwise Mason installs it when it ships a package; a name the registry doesn't recognize is surfaced as an unknown-name config error. Make the mason-registry requires optional so a Mason-less setup still configures system-provided servers. Fold external_lsp_deps into lsp_deps (shuck now lives there) and clarify that nixd / nil_ls are resolved from $PATH first, else Mason-installed, since the resolver no longer needs a separate "configure but don't install" list.
Only install formatters/linters that aren't already on $PATH, so systems that provide their own tools (NixOS/BSD) aren't nagged every startup. Unknown Mason package names (typo / removed) are reported via the collector's mark_unknown bucket so the warning points at the config, not a manual install.
Resolve debug adapters discovery-first through the shared helper and make the mason-registry / mason-nvim-dap requires optional, so a Mason-less setup still configures adapters that resolve their own binary (client configs / $PATH). Configure an adapter as soon as it has a client config (its own discovery-first resolver) rather than waiting on the Mason install, so e.g. python debugging via system debugpy works this session. On a Mason-less setup, best-effort validate a table adapter's resolved command and surface it as missing if empty/not on $PATH (e.g. codelldb via vim.fn.exepath). Make the delve client Mason-agnostic: guard mason-registry, only auto-install when go-debug-adapter is neither installed nor on $PATH, return after kicking off an install, and error (marking delve missing) when the bundle or a `node` runtime can't be resolved. Resolve debugpy without Mason in the python client, probing python interpreters instead of assuming one. Resolve Mason's install root via mason.settings (with a $MASON fallback) rather than the env var alone.
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.
Feasibility POC — RFC ayamir/nvimdots#1293
Implements the "separate tool discovery from tool installation" idea from this comment: Mason becomes one installer backend, not a hard requirement. On FreeBSD/NixOS/etc. — where Mason's prebuilt binaries don't run — system-provided tools are used directly, with no manual symlinking and no startup notification spam.
No new toggle, no OS detection. Behaviour is driven purely by availability.
Resolution model (per tool)
Applied to LSP, DAP, formatters, and linters. conform/nvim-lint already resolve from
$PATH, so only their install gating changed.Changes
modules/utils/tools.lua(new)$PATHcheck, Masonspec.binresolver, per-subsystem warning aggregator (one message, not N)mason-lspconfig.lua,lsp.lua,settings.lualsp_deps;external_lsp_depsmerged intolsp_deps(auto-classified via the mason-lspconfig mapping — no more deciding which list a server goes in)mason.lua$PATHdap/init.luadap_depsinstead of mason-nvim-dap's installed-only handler gatingsettings.lualsp_deps: absorbsnixd/nil_ls/shuckexternal_lsp_deps: removedformatter_deps/linter_deps/dap_deps/treesitter_deps: unchangedVerification
stylua+selene: clean.mason-registry.is_installed,mason-lspconfiglspconfig_to_package,vim.lsp.config[name].cmd[1](incl.nil_ls→nil),pkg.spec.bin, and allmason-nvim-dap.mappings.*.lua_lsvia the new resolver, no errors.Known POC limitations
$PATHdetection relies on the Mason package's declared binaries (nvim-dap has no uniform command registry); adapters with an explicit client config resolve their own binary viavim.fn.exepath.cmdis a function (rare) can't be$PATH-probed; it falls back to the Mason-package check.