Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
289eb5a
fix: recognize a launcher that cannot reach the V1 compatibility comp…
metif12 Oct 3, 2026
e506666
test: recognise the reworded "make is unavailable" refusal too
metif12 Oct 3, 2026
3d3ba5d
fix: correct compile target and path resolution for multifile diagnos…
metif12 Oct 7, 2026
8cf8b10
fix: resolve Windows launcher shim to the real V compiler
metif12 Oct 7, 2026
dde0247
Merge remote-tracking branch 'upstream/master' into fix/recognize-mis…
metif12 Oct 7, 2026
51981a6
Fix merge fallout: drop stray braces and thread compile_target throug…
metif12 Oct 7, 2026
a9ae450
Fix undefined compile_target: thread it through line_info_result and …
metif12 Oct 8, 2026
aa24779
feat: tiered diagnostics with fast unknown-import check
metif12 Oct 8, 2026
f8eaf56
feat: persistent diagnostics cache keyed on program fingerprint
metif12 Oct 8, 2026
f14562b
Merge remote-tracking branch 'upstream/master' into feat/tiered-diagn…
metif12 Oct 8, 2026
b11028a
test: give the wrapper fixture the vlib dir a real install has
metif12 Oct 8, 2026
2e42f2f
Merge branch 'feat/persistent-diag-cache' into feat/tiered-diagnostics
metif12 Oct 8, 2026
af3df7f
perf: answer line-info from the shared diagnostics-server pool
metif12 Oct 8, 2026
a757928
feat: fast tier reports certain parse errors for the edited buffer
metif12 Oct 8, 2026
c4c8e27
test: compiler-compatibility matrix for line-info modes
metif12 Oct 8, 2026
eb62219
docs: record pooled line-info, fast parse errors, compat matrix
metif12 Oct 8, 2026
94e3608
Merge remote-tracking branch 'upstream/master' into feat/tiered-diagn…
metif12 Oct 8, 2026
5fdbd0a
test: broad direct coverage for handlers, interop, index, lsp, main
metif12 Oct 8, 2026
7fd0540
test: cover rename, module-import, expression-type helpers; fix temp-…
metif12 Oct 8, 2026
69dbe93
test: regression coverage for nested programs and cold-open siblings
metif12 Oct 9, 2026
ed107a9
perf: per-stage timing breakdown for slow checks
metif12 Oct 9, 2026
47d9e2c
fix: apply the index size gate to open buffers
metif12 Oct 9, 2026
bbb77fe
perf: stable overlay dir with sync-only-changed files
metif12 Oct 9, 2026
c79b459
feat: granular inlay-hint toggles
metif12 Oct 9, 2026
8cd9cdf
feat: trigram fuzzy ranking for workspace symbols
metif12 Oct 9, 2026
9144e36
perf: pre-size the symbol index before bulk walks
metif12 Oct 9, 2026
dcbe82d
docs: record fingerprint cache, pool routing, parse errors, matrix
metif12 Oct 9, 2026
2df3084
fix: apply the index size gate to open buffers
metif12 Oct 9, 2026
4d8d0d5
perf: pre-size the symbol index before bulk walks
metif12 Oct 9, 2026
677d507
feat: refuse renames that shadow a binding or break an interface
metif12 Oct 9, 2026
be1336f
feat: fill struct literal quickfix
metif12 Oct 9, 2026
3399c32
feat: advertise range formatting, inline values, linked editing; fix …
metif12 Oct 9, 2026
6f4dbb2
docs: record Phase 3 and Phase 5 results
metif12 Oct 9, 2026
d94fbc9
perf: reserve the symbol index for partial walks too
metif12 Oct 9, 2026
ab2aeeb
feat: layered configuration with defines and per-project vls.json
metif12 Oct 9, 2026
8b6e4b2
feat: extract variable and inline variable refactors
metif12 Oct 9, 2026
9fea537
docs: record Phase 3 and Phase 4 completion
metif12 Oct 9, 2026
c939163
feat: extract function, add import, implement missing members assists
metif12 Oct 9, 2026
e4e3fdb
feat: extract function, add import, implement missing members assists
metif12 Oct 9, 2026
219c382
perf: memoize the project listing, gate hashes on file metadata, boun…
metif12 Oct 10, 2026
c6a1ba2
feat: answer interactive requests while a check is in flight
metif12 Oct 10, 2026
0c4b8ea
perf: refresh the index in the background, answer requests from it as…
metif12 Oct 10, 2026
a24fe4a
perf: warm rename checks and richer hover
metif12 Oct 10, 2026
0f4a450
perf: build the program copy at save time, not when the next question…
metif12 Oct 10, 2026
b52c2a1
docs: record the optimization pass and what it deliberately left out
metif12 Oct 10, 2026
148bb35
feat: bound the diagnostics published for one file
metif12 Oct 10, 2026
4c53b83
feat: apply a project's vls.json when a file of it is opened, and pub…
metif12 Oct 10, 2026
63425c9
feat: hover shows the value of a constant reached through its module
metif12 Oct 10, 2026
04a0118
feat: rename interface members across implementors, move declarations…
metif12 Oct 11, 2026
6011517
perf: check only the changed file's module when the program's imports…
metif12 Oct 11, 2026
85f11f8
docs: record the reword workflow, and the thread-priority measurement…
metif12 Oct 11, 2026
ff2d1bc
feat: link imports and the URLs in comments
metif12 Oct 11, 2026
8e2b305
feat: answer textDocument/diagnostic from the diagnostics already com…
metif12 Oct 11, 2026
f6400d9
feat: workspace/diagnostic answers the Problems pane in one report
metif12 Oct 11, 2026
3af7ba3
fix: clamp index reservation, gate occurrences, treat unsaved buffers…
metif12 Oct 11, 2026
941b1b8
fix: carry the three index-memory review findings over from #547
metif12 Oct 11, 2026
cd28b51
test: pin the innermost call in signature help
metif12 Oct 12, 2026
042e925
docs: close out refactor-members and extract-to-file on the roadmap
metif12 Oct 12, 2026
aa09b7f
feat: structural search and replace
metif12 Oct 12, 2026
3b07e41
fix: refuse an interpolation match wherever the rule matched it
metif12 Oct 12, 2026
829906e
fix: refuse an `$else` branch, an attribute, and an annotated field type
metif12 Oct 12, 2026
da7e82e
fix: stop SSR hanging on any file with a line comment, and add its en…
metif12 Oct 12, 2026
1e5f30e
test: pin the render's wrap with a template operator, and the escapes…
metif12 Oct 13, 2026
4a6bcf3
docs: record the refusals SSR grew since the roadmap entry
metif12 Oct 13, 2026
2712272
fix: rewrite a call that shares its line with the rule
metif12 Oct 13, 2026
f707373
fix: survive a code action whose selection runs backwards
metif12 Oct 13, 2026
b11693d
test: survive a client's malformed selection positions
metif12 Oct 13, 2026
9bfec8e
refactor: share the line-start lookup, drop a wrapper, prefix a leake…
metif12 Oct 13, 2026
12aee8f
refactor: three guards read the document, not the app, and say so
metif12 Oct 13, 2026
8c1183c
docs: re-measure the comparison against the tree, closing what this b…
metif12 Oct 13, 2026
14a5cba
docs: Phase 1 lists only what stands, and names it
metif12 Oct 14, 2026
f3997f1
fix: say where a structural-replace rule is, rather than offering not…
metif12 Oct 14, 2026
6dba57f
perf: fingerprint the code, so a comment edit does not reach the comp…
metif12 Oct 14, 2026
c5b03a5
lsp: let a CodeAction carry a command
metif12 Oct 14, 2026
e8e5223
config: add a coverageDirectory tier beside the other three
metif12 Oct 14, 2026
a8fb888
Offer to generate the tests an untested function is missing
metif12 Oct 14, 2026
6bfa78d
Merge remote-tracking branch 'origin/fix/index-memory-ci' into showcase
metif12 Oct 14, 2026
6ec76d6
fix: hover answers without rushing the pending slow check
metif12 Oct 15, 2026
a781be2
fix: accept workspace previousResultIds as an LSP array
metif12 Oct 15, 2026
b123958
fix: accept workspace previousResultIds as an LSP array
metif12 Oct 15, 2026
83e2683
test: fix self-contradicting initialize fixture to advertise generate…
metif12 Oct 15, 2026
cd8b336
showcase: merge feat/tiered-diagnostics
metif12 Oct 15, 2026
5b44ff9
docs: point at v ls --install as the supported install path
metif12 Oct 15, 2026
37b5bcb
test: give stop() a ceiling a loaded runner can meet
metif12 Oct 17, 2026
197437b
vls: share worker diag cache with pull diagnostics (P1)
metif12 Oct 23, 2026
a577f52
vls: clear stale workspace diagnostics by reporting clean cached docs…
metif12 Oct 23, 2026
3c1cf2c
vls: synchronize compiler_answer_ms access across threads (P1)
metif12 Oct 23, 2026
b8ad3cd
vls: keep skipped oversized open buffers across shallow refresh (P1)
metif12 Oct 23, 2026
71d8625
vls: per-App config store to prevent TCP client config leak (P1)
metif12 Oct 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ Build & test (development)
# V struct JSON attributes
- Use `@[json]` attributes only when a field name does not exactly match the JSON name.

# Rewording a commit that is not HEAD
- Do not use `git rebase -i`: this host runs the sequence editor through `sh`, so
`%1` never expands and the rebase dies with "there was a problem with the editor".
- The reliable path is a temp branch plus a replay, which needs no force-push:
`git checkout -b tmp <sha>`, `git commit --amend -F msg.txt` there, then
`git rebase --onto tmp <old-sha> feat/<branch>` and `git branch -D tmp`.
- Always run `git add` and `git commit` sequentially, never as parallel tool calls:
two parallel calls race and one commit ends up holding both tracks' files, which
then needs the reword above. After grouping, verify with `git log --stat -1`.

Mandatory guardrails (enforced for all agent work)
- Add `2>&1` to commands so all output is captured.
- Keep `.md` lines ≤ 100 characters.
Expand Down
92 changes: 92 additions & 0 deletions COMPARISON.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Language-server comparison: gopls, rust-analyzer, zls vs vls

Why these three: Go is V's syntactic parent, Rust is the
aspirational maturity target, Zig is the closest lifecycle
peer (young systems language, breaking compiler).

## Architecture

- gopls: per-package summaries, persistent file cache,
pruned invalidation (skip importers when exports
unchanged). Two-tier diagnostics (instant + deferred vet).
- rust-analyzer: Salsa queries over ItemTree/DefMap/Body;
laziness first, incrementality second; proc-macros and
flycheck out-of-process; per-request cancellation.
- zls: per-file `std.zig.Ast` + heuristic semantics (no
full comptime); strict 1:1 version lock with Zig; custom
build runner; opt-in build-on-save via a `check` step.
- vls: per-file token index + full project re-check;
shell-free compiler argv + overlay; scheduler + pool
of max 3 diagnostic servers; index-first fallbacks.

## Feature gap summary

Measured against the tree as of the last pass over it. What this
branch closed is marked; what stands is kept as it was found.

- Incrementality: all three peers beat vls (export
summaries / Salsa / per-module units vs full re-check).
Still open — a change confined to a function body now
checks that file's module rather than the whole tree,
and a slow check is reused from a per-program
fingerprint cache, but the unit of re-check is still a
program, not an item.
- Diagnostics tiers: peers split fast/slow. **Closed** —
each edit schedules a fast index-only check (150ms
debounce) and the full compiler check (800ms idle),
and the slow answer replaces the fast one.
- Refactors: gopls and rust-analyzer offer extract/inline/
fill/struct assists with safety checks; vls has 2 actions
(remove unknown import, contiguous organizeImports).
**Closed** — ten actions, all gated on a kind filter and
a shape check: quick fixes for a diagnostic, organize
imports, fill struct literal, extract or inline a
variable, extract function, add an import, implement
missing members, move a declaration to a module of its
own, and structural search and replace.
- Rename safety: gopls checks shadowing + interface
satisfaction; vls refuses on incomplete scope only.
**Closed** — rename refuses names that shadow a binding
or break an interface, and renames an interface's
members across its implementors.
- Config: zls layers editor > `zls.json` (+ schema) >
per-build file; vls relies on `VLS_V_COMMAND`/`VFLAGS`.
**Closed** — editor settings > project `vls.json` >
`VLS_DEFINES`, with the schema published and defines
salted into the diagnostics fingerprint.
- Compat: zls chose lockstep; vls probes compiler modes
(`unknown/direct/compat/missing`) for a version range.
Still true, and the missing-compat case is reported
rather than answered emptily.

## Criticism (what to fix, in roadmap order)

1. No real incrementality — the cached answer is per
program and per fingerprint, not per item.
2. One-tier diagnostics — **closed** by the two-tier
scheduler above.
3. Index masks compiler gaps instead of measuring them —
still open.
4. Refactors are text edits, not semantic operations —
still open for the text edits; the structural replace
is deliberately scope-negative and refuses rather than
guesses, and rename now checks the scope it moves into.
5. Config is env-var folklore (`VFLAGS`-in-shell) —
**closed** by layered configuration.
6. Dispatched stubs (inlineValue literals-only,
same-line linkedEditing, empty onTypeFormatting) —
**closed**; all three are implemented and advertised.
7. No perf budget or observability story — partly closed:
`VLS_PERF_LOG=1` logs a per-stage breakdown of a slow
check, first measurement being the compiler run at 97
percent of it. A budget is still undecided.

## Sources

- https://go.dev/gopls/ and /features/, /workspace/, /settings/
- https://go.dev/blog/gopls-scalability
- https://rust-analyzer.github.io/book/ (features, assists,
diagnostics, architecture, non_cargo_based_projects)
- https://github.com/zigtools/zls and https://zigtools.org/zls/
- vls tree: index.v, interop.v, diagnostics_scheduler.v,
diagnostics_server.v, handlers.v, main.v, v3_line_info.v
59 changes: 48 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Build with: `v .`

Or let the compiler install it for you: `v ls --install` (see `v help ls`
for update and source-build options).

Check the installed version with `vls --version` or `vls version`. Both print `VLS 0.0.3`
and exit without starting the server. LSP `initialize` reports the same version in `serverInfo`.

Expand Down Expand Up @@ -76,39 +79,73 @@ also visualize line coverage; set `v.vls.coverage.enabled` to `false` to turn th
### Code behind a compile-time flag

V compiles the code inside `$if flag ? { ... }` only when the program is built with `-d flag`.
VLS runs the compiler without defines, so that code is not checked: it gets no errors, and hover
and go-to-definition find little or nothing in it. V adds the options in the `VFLAGS` environment
variable to every command, so set it where VLS runs to work on such a block. For example, close
the editor and start it again from a shell:
VLS runs the compiler without defines, so that code used to get no errors, and hover and
go-to-definition found little or nothing in it. It now checks that code when the flag is given.

Set `vls.defines` in the editor's settings for VLS, naming the flag the code uses:

```json
"vls.defines": ["-d", "flag"]
```

The joined spelling, `["-dflag"]`, is accepted too. To keep the flag with the project rather than
in the editor, put a `vls.json` in the folder that holds the nearest `v.mod`:

```json
{ "defines": ["-d", "flag"] }
```

A `vls.json` may also set `inlayHints`, `diagnostics` and `coverageDirectory`. The settings
the editor sends win over the project's file, and the file over `VLS_DEFINES` in the environment,
which also works for an editor with no settings of its own. The nearest `vls.json` is read when a
file of its project is opened, so its switches apply before the first check rather than after it.
The keys the file accepts are listed in [`vls.schema.json`](vls.schema.json). The defines reach
the checks only: `v fmt`, hover, go-to-definition and completion run without them. The code inside
`$if !flag ? { ... }` is then the one left unchecked.

### Generating tests for untested functions

A coverage recording is what tells VLS which functions a test run never entered. Record one, then
point the project at it:

```sh
VFLAGS='-d flag' code .
v -no-skip-unused -coverage vcov/ test ./
```

In Sublime Text, add `"VFLAGS": "-d flag"` to the `env` of its server configuration. The code
inside `$if !flag ? { ... }` is then the one left unchecked.
```json
{ "coverageDirectory": "vcov" }
```

`coverageDirectory` may also be sent by the editor as `vls.coverageDirectory`, which wins over the
file. With it set, a `.v` file whose functions were never entered offers a code action per
function: `Generate test for 'foo'`. The action runs `v cover --write-tests`, which appends one
`test_foo()` beside the source with a zero-value call and a `// TODO:` line. It is a starting
point, not a test: the generator cannot know what the function should return.

`-no-skip-unused` belongs with the recording. Without it a function nothing calls is dropped from
the build, so its coverage cannot be reported at all.

### Features

#### Instant errors

<img width="1932" height="432" alt="image" src="https://github.com/user-attachments/assets/a842e103-b3c2-427f-956f-fffff07970dc" />
![image](https://github.com/user-attachments/assets/a842e103-b3c2-427f-956f-fffff07970dc)

#### Go to definition

https://github.com/user-attachments/assets/fb4ee6ff-4765-46b7-a21e-267691253d8e

#### Autocomplete for module functions

<img width="1246" height="592" alt="image" src="https://github.com/user-attachments/assets/0d4e1849-2e6c-47f8-9a45-322fe25d9bef" />
![image](https://github.com/user-attachments/assets/0d4e1849-2e6c-47f8-9a45-322fe25d9bef)

#### Information about function parameters

<img width="1494" height="450" alt="image" src="https://github.com/user-attachments/assets/46cc391b-fcdc-4083-ab62-97edd815ddd9" />
![image](https://github.com/user-attachments/assets/46cc391b-fcdc-4083-ab62-97edd815ddd9)

#### Autocomplete for struct fields and methods

<img width="1804" height="392" alt="image" src="https://github.com/user-attachments/assets/478bfd20-201a-476f-88cd-583fad52d6cc" />
![image](https://github.com/user-attachments/assets/478bfd20-201a-476f-88cd-583fad52d6cc)

### Zed

Expand Down
Loading
Loading