Skip to content

release: 2026-06-03#730

Merged
aviatesk merged 20 commits into
releasefrom
releases/2026-06-03
Jun 3, 2026
Merged

release: 2026-06-03#730
aviatesk merged 20 commits into
releasefrom
releases/2026-06-03

Conversation

@aviatesk

@aviatesk aviatesk commented Jun 3, 2026

Copy link
Copy Markdown
Owner

This PR releases version 2026-06-03.

Checklist

  • release / Test JETLS.jl with release environment
  • release / test_app / Test jetls serve
  • release / test_app / Test jetls check
  • release / test_app / Test jetls schema
  • release / check_schemas / Check schemas are up to date

Post-merge

  • The releases/2026-06-03 branch can be deleted after merging
  • CHANGELOG.md will be automatically updated on master

github-actions Bot and others added 20 commits May 27, 2026 07:43
Clarify why `FileInfo.syntax_tree0` exists and how it should be accessed. The field is an optional pruned `st0` cache for unsynced workspace files whose syntax trees are scanned repeatedly by diagnostics and global occurrence search.

Mention `build_syntax_tree` as the access path because it returns a copy that can be safely passed through lowering, whose pipeline mutates syntax graph state.

Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Remove the unused raw-tree caching mode from `FileInfo`. The constructor
now treats `cache_tree=true` as the single supported cached-tree path
and always stores a pruned `st0`, matching the current unsynced-file use
case and the field documentation.

This keeps the default path cache-free while making the keyword type
stricter and avoiding the misleading `nothing` / `false` distinction.
`FileInfo` now always stores a pruned `st0` snapshot. This moves
the cost to file-info creation: the first read pays `build_tree` plus
`JS.prune`, which is more expensive than rebuilding `st0` alone.

`build_syntax_tree` returns a copy of that cache so lowering can
mutate the tree without touching shared state. The synced-document
path reuses the tree already built for testset discovery, and unsynced
files no longer need a separate `cache_tree` switch.

Performance measurement example: On this commit, `src/diagnostic.jl` is
about 89KiB. Rebuilding `st0` for it takes about 11ms and allocates
12.1MiB across 153k objects. Building and pruning the initial cache
takes about 22ms and 18.2MiB across 191k objects, while copying the
cached pruned tree takes about 60us and 1.4MiB across 49 objects.

That tradeoff is acceptable for synced documents because a normal edit
is followed by several same-version requests, such as diagnostics,
document links, document highlights, semantic tokens, and code actions.
User interaction can then add hover, definition, document symbols, and
occurrence queries.

One caveat is that `JS.prune` preserves source locations but can
collapse source-only provenance nodes. For example, short-form
function definitions may lose the intermediate `K"function"` node and
surface as `K"="` instead. `TypeAnnotation` handles this by falling
back to method-like lowered nodes when dispatching type queries for
that range.

The same caveat appears in document symbols for `@nospecialize`
arguments. After pruning, the provenance textref can survive in an
st0-shaped macrocall, so document-symbol extraction accepts that
shape alongside the st3 macrocall form.

Co-authored-by: GPT-5 Codex <noreply@openai.com>
Add an optional per-`FileInfo` `InferredContextCache` and route synced
LSP type-query paths through it. The cache is keyed by context module,
world, and top-level range so stale analysis results are not reused.

Only synchronized file snapshots allocate this cache. Unsynced
`FileInfo` entries keep it as `nothing` to avoid retaining heavy
inferred trees for workspace-wide paths.

The memory measurements behind that choice are significant. A pruned
`st0` cache for JETLS `src/` is about 29.74 MiB, with
`src/diagnostic.jl` alone at 1.72 MiB. The inferred contexts are much
heavier: about 10.41 MiB for `src/diagnostic.jl` and 5.89 MiB for
`src/utils/ast.jl` after pruning and summary extraction.

Measuring all of JETLS `src/` with file-appropriate context modules
retains about 124.22 MiB for inferred-context cache entries, compared
with 29.74 MiB for the pruned `st0` cache. That is a different cost
profile from the `st0` cache, so the inferred cache stays scoped to
synchronized documents.

Cache misses build outside the cache lock, accepting duplicate
inference during races so unrelated cache hits do not wait on lowering
or inference.

Full-analysis updates clear synced inferred-context caches so old
analysis worlds can be released before the next type query rebuilds
against the latest context.

Tests cover cache hits, separate top-level entries, uncached rebuilds,
cache clearing, and queryability through `get_type_for_range`.

Co-authored-by: GPT-5 Codex <noreply@openai.com>
Remove the June 2026 legacy configuration aliases now that the announcement window has elapsed.

Update the changelog entry to describe the aliases as removed instead of continuing the deprecation announcement.
…726)

* analysis: Fix `unused-argument` false positive on nested `@generated`

`compute_binding_occurrences` previously checked only whether the
*top* of the lowerable subtree was a `@generated` macrocall (via
`is_generated0(st0)`). That missed cases where the `@generated`
function lives inside another construct -- e.g. as an inner
constructor in a `struct` body -- producing a false
`lowering/unused-argument` diagnostic and breaking find-references,
document-highlight, and rename on the argument.

The detection is now per-binding via `flattened_provenance`: for
each `:argument` binding whose provenance includes a `@generated`
ancestor, inert-node uses of the argument name within the same
`@generated` macrocall range are recorded as `:use` occurrences.

As a side effect, the `is_generated::Bool` parameter (and `st0`
field destructuring at call sites) is dropped from
`compute_binding_occurrences`, `_select_target_binding`,
`local_document_highlights!`, `find_local_references!`,
`find_local_binding_declarations`, and `local_binding_rename`,
since the per-binding check on `st3` no longer needs a hint from
the original parse tree.

- Closes #722

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* analysis: Drop `SyntaxList` alloc in generated-arg detection

`enclosing_generated_range` (formerly `innermost_generated_range`)
no longer goes through `JS.flattened_provenance`, which would
materialize a `SyntaxList` of the full macro-expansion chain just
to find one entry. It now walks the chain step-by-step via
`JS.macro_prov`, returning on the first `@generated` match -- no
list allocation.

Picking the innermost `@generated` is the semantically right
choice here:

- `@generated` cannot be a closure (Julia rejects nested
  `@generated function` at parse time with "Global method
  definition needs to be placed at the top level"), so the macro
  chain reaching any node we inspect contains at most one
  `@generated`; innermost and outermost coincide.

- Even if nesting were possible, only the innermost `@generated`'s
  argument bindings have a static link to inert references in its
  body. An outer `@generated`'s parameters would appear as free
  identifiers in the inner body, with no static path back to the
  outer binding.

Restores `compute_binding_occurrences` performance to master-level
on JETLS source files measured with `experiments/jlbench.jl`
(previously +7-10% from the per-binding provenance scan; now
within noise).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* more tests

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Document the user-facing responsiveness improvements from reusing prepared syntax trees and prior type-aware analysis results.
* diagnostics: Clarify tail assignment diagnostics

Address #723. In tail-position assignments, Julia
returns the assignment expression, while the assigned binding itself may
still never be read.

For example, in:

    function f()
        x = 1
    end

the function returns the value of `x = 1`, not a later read of `x`.
The old `Unused local binding x` wording did not explain that
implicit-return distinction. JETLS now reports this message, wrapped
here:

    Local binding `x` is not read; consider `return x`
    to return it explicitly

For tail dead stores, JETLS similarly reports a message of the form,
wrapped here:

    Value assigned to `x` is returned directly;
    consider `return x` to return the binding explicitly

Classify returned assignment expressions and report this more specific
message. Simple block-tail assignments also carry insertion metadata so
the quick fix can add that explicit return.

Co-Authored-By: Codex GPT-5 <noreply@openai.com>

* address review comment, wording tweak

---------

Co-authored-by: Codex GPT-5 <noreply@openai.com>
Avoid emitting empty `containerName` values for workspace symbols.

The root cause is fixed in `document-symbol.jl` by preserving detail
text for later bindings in multiline `let` and `for` headers. The
`workspace_symbol_container_name` normalization is kept as a defensive
guard against empty `containerName` values reaching workspace symbol
responses.

Co-authored-by: Codex GPT-5 <noreply@openai.com>
Prefer explicit return fixes before rename and deletion actions for tail unused local assignments. Suppress statement deletion when a value is returned implicitly, while keeping assignment deletion available.

Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Scope the pruned `st0` snapshot to synchronized documents and let
unsynced `FileInfo` values rebuild syntax trees only on demand. Open
documents still reuse copied cached trees, while workspace files no
longer retain parsed syntax trees after global searches.

Move workspace-wide diagnostics and global occurrence lookups toward
summary caches instead: `PerFileDiagnosticsResult` now carries the
cross-file summaries needed by diagnostics, and
`BindingOccurrencesCache` stores a lazily built file-level global
occurrence summary for warm definition, declaration, and reference
searches.

This keeps warm global searches at least comparable to the previous
unsynced-`st0` cache path while reducing retained memory. In the JETLS
self-analysis scenario measured during development, unsynced file cache
size dropped by roughly 22 MiB, the occurrence cache grew by roughly 6
MiB, and the net major-cache footprint fell by about 16 MiB. End-to-end
heap snapshots after `findReferences` showed the same order of
improvement, from roughly 483 MiB down to 467 MiB.

Co-authored-by: GPT-5 Codex <noreply@openai.com>
@aviatesk
aviatesk merged commit a42a435 into release Jun 3, 2026
10 checks passed
@aviatesk
aviatesk deleted the releases/2026-06-03 branch June 3, 2026 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant