LSP: stdlib completion + hover generated from lib/ signature comments (fixes #590)#691
Merged
InauguralPhysicist merged 1 commit intoJul 22, 2026
Conversation
…InauguralSystems#590) handle_completion/handle_hover served builtin_docs[] and document-local symbols, but the 75-module pure-EigenScript lib/ layer (815 public functions) was invisible: typing `stats.` offered nothing, and hovering a lib/ call showed nothing. tools/gen_lsp_stdlib_index.sh (shell+awk, zero-dependency, in the style of tools/stdlib_index_check.sh) scrapes lib/*.eigs for public `define name(params)` definitions (leading-underscore names stay private) plus their rule-2 `# name of args -> type` signature comment (docs/STDLIB.md "Writing Library Functions"), emitting src/lsp_stdlib_index.h: a static {module, name, params, detail} table. Functions without a signature comment fall back to the `define name(params) as:` shape — back-filling those comments is tracked separately in STDLIB.md, not papered over here. The header is a build artifact, not committed (the build/ amalgamation precedent, InauguralSystems#397): .gitignore'd, and regenerated by the Makefile lsp target and build.sh lsp before eigenlsp compiles, so install.sh and both CI lsp legs pick it up automatically. eigenlsp serves the table through the existing paths, scoped by the document's own import-symbol tracking: - completion: an imported module's public functions are offered as kind-3 Function items with the signature as detail; unimported modules stay invisible. - hover: a dotted `mod.name` pins the module; a bare name matches any imported module's function. Either way the detail is the signature comment or the define-shape fallback. tests/test_lsp.py gains 8 checks (imported offered w/ signature detail, fallback detail, unimported absent, no-import empty, hover signature, hover fallback, hover unimported -> null); the [88] header count moves 23 -> 80 (it had already drifted from the real 72). Gates: release suite 3138/3138, asan+ubsan suite (detect_leaks=1) 3142/3142, test_lsp_asan.sh 80/80 with no sanitizer reports, tools/stdlib_index_check.sh + selftest green. Co-Authored-By: Kimi K3 <noreply@kimi.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.
Implements #590: the ~75-module
lib/layer becomes visible to LSP completion and hover, driven by a build-time generated table.What
tools/gen_lsp_stdlib_index.sh(new, shell+awk, zero-dependency, conventions followstdlib_index_check.sh): scrapes everylib/*.eigsfor line-start publicdefine name(params)definitions (leading-underscore = private, excluded) plus the rule-2# name of args -> typesignature comment from the comment block directly above. Emitssrc/lsp_stdlib_index.h(static const char *stdlib_docs[][4]— module, name, params, detail). Current tree: 815 public functions across 75 modules (the issue's ~808 was the 2026-07-13 audit count).lib/*.eigs+ the script → header) so the table regenerates beforeeigenlspcompiles;build.sh lspruns the generator too. The header is generated, not committed — matches the repo's.gitignored-generated-artifacts precedent (build/, make lib + two-file amalgamation: ship the embeddable artifact #397).src/eigenlsp.c(+61): completion offers an imported module's public functions as kind-3 Function items with the signature as detail (unimported modules stay invisible — reuses the existing SYM_IMPORT tracking); hover onmod.nameresolves against that module, bare names against any imported module; missing signature comments fall back to thedefine name(params) as:shape (~70% of lib/ functions currently lack the rule-2 comment — deliberately NOT back-filled here, that's tracked separately in STDLIB.md).tests/test_lsp.py(offer/detail/fallback/omit-unimported/empty-without-import/hover×3). The[88]section header said "(23 checks)" while the harness actually ran 72 — corrected to the new true count of 80 (the pass/fail gate counts dynamically; the header is cosmetic).Verification
RESULTS: 3138/3138 passed, 0 failed;[88]all 80 LSP checks pass;stdlib_index_check.shgreen incl. selftest.3142/3142 passed, 0 sanitizer reports; the LSP-specific sanitizer gate (tests/test_lsp_asan.sh) passes 80/80.Maintainer-facing choices (overrule freely)
list.dropvsstore.drop) serves the first match deterministically; dotted hover is exact. Kept simple since qualified calls are the house style.map) — matches the handler's existing behavior for local defines shadowing builtins.lib/audio.eigswrites=>instead of->); a comment-shape lint felt like its own issue, not part of this one.Generated by Claude Fable 5 (brief, review), Kimi K3 (implementation)