Cache overlay#52
Conversation
Collect struct-literal completion candidates into completionIndex to pick best span at completion time. Change struct literal prefix check to accept source.Location. Replace local maxInt64 usage with existing max and drop the helper. Add dry_test.fer and fix import. Rules check: - wrapper added: no - duplicated logic: no - helper added: collectStructLiteralCompletionCandidates to centralize candidate collection (allowed by RULES.md)
Introduce Compiler.ParsePathWithOverlay and pipeline overlay methods (ParseEntryOverlay, ParseEntryOverlayForIDE) with shared finishEntryParse and scheduleParseOverlayFile to parse temporary overlay contents without changing module identity. LSP now writes hover overlays into FERRET_CACHE (or user cache), prunes stale overlays, and uses ParsePathWithOverlay for in-memory buffers. Add ferretCacheDir, hoverOverlayDir, functionPointer helpers and tests for overlay behavior. Rules check: no pass-through wrappers added; reused pipeline logic; added helpers limited to cache/overlay management.
| "compiler/internal/core/context" | ||
| "compiler/internal/core/diagnostics" | ||
| "compiler/internal/core/phase" | ||
| compiler "compiler/internal/driver" | ||
| "compiler/internal/driver" | ||
| "compiler/internal/ir/hir" |
There was a problem hiding this comment.
The import was changed from an aliased import to an unaliased one, but this file still calls compiler.New(...). As-is, this test won’t compile (undefined compiler) and the driver import may become unused. Either restore the aliased import (compiler "compiler/internal/driver") or update call sites to use driver.New(...) consistently.
| tempPath, err := writeHoverOverlay(path, text) | ||
| if err != nil { | ||
| return parse(path), path, func() {} | ||
| } | ||
| cleanup := func() { _ = os.Remove(tempPath) } | ||
| return parse(tempPath), tempPath, cleanup | ||
| if functionPointer(parse) != functionPointer(defaultParse) { | ||
| return parse(path), path, cleanup | ||
| } | ||
| return compiler.ParsePathWithOverlay(path, tempPath, ide), path, cleanup |
There was a problem hiding this comment.
If writeHoverOverlay fails (e.g., cache dir can’t be created, FERRET_CACHE is relative, or FERRET_CACHE=off), parseForProject silently falls back to parsing the on-disk file, which makes hover/completion/rename ignore unsaved overlay text. Consider falling back to os.CreateTemp("", ...) (or another writable temp location) so overlays still work, and/or surfacing the error to the client/logs so it’s not silently incorrect.
| import "std/string" | ||
|
|
||
| #[allow_unused] | ||
| fn usefn(val: i32, callback: fn(i32) ) { | ||
| callback(val * 2) |
There was a problem hiding this comment.
This new .fer file doesn’t appear to be referenced by tests, docs, or build scripts (looks like a local scratch/repro file). If it’s not intended as a committed fixture/example, it should be removed or moved under an appropriate examples/tests directory so it doesn’t add noise to the repo root.
| } | ||
| item := strings.TrimSpace(body[itemStart:]) | ||
| if item == "" { | ||
| return "", true |
There was a problem hiding this comment.
In struct literal completion context, this currently returns ok=true even when the current item is empty (no leading .). Since struct field assignments in Ferret syntax require the .field = value form (see internal/frontend/parser/expr.go:292-300), the LSP completion items (which only provide Label) will insert name/age without the leading ., producing invalid (or at least unintended) syntax when a user accepts a completion at an empty line.
Consider either (a) only enabling struct-field completions when the user has already typed . (i.e., require strings.HasPrefix(item, ".")), or (b) extending the completion payload to support an insert text/text edit that inserts . + field name when needed.
| return "", true | |
| return "", false |
| content, err := os.ReadFile(overlayFile) | ||
| if err != nil { | ||
| p.ctx.Diagnostics.Add( | ||
| diagnostics.NewError(fmt.Sprintf("cannot read module %s", mod.ImportPath)). |
There was a problem hiding this comment.
parseOverlayFile reports read failures using the same message/code as normal module file reads ("cannot read module %s" + ErrModuleNotFound), but in this path the failing resource is the overlay file (overlayFile). This makes diagnostics misleading when the overlay temp file is missing/unreadable.
Consider mentioning the overlay path in the diagnostic (and/or using a more specific error code/message) so users can tell whether the real module file or the overlay failed to read.
| diagnostics.NewError(fmt.Sprintf("cannot read module %s", mod.ImportPath)). | |
| diagnostics.NewError(fmt.Sprintf("cannot read overlay file %s for module %s", overlayFile, mod.ImportPath)). |
No description provided.