Commit d472529
feat: workspace indexing + subprocess removal + workspace/symbol (#14)
* refactor: remove subprocess isolation for module resolution
tree-sitter-perl is stable — subprocess overhead and JSON serialization
boundary no longer justified. Production now uses the same direct
in-process parsing path that tests always used.
Deleted:
- parse_in_subprocess() — subprocess spawn + 5s timeout + SIGKILL
- subprocess_main() — JSON serialization of ExportedSub metadata
- --parse-exports CLI mode in main.rs
- subprocess_main forwarding in module_index.rs
- PARSE_TIMEOUT constant
- #[cfg(not(test))] / #[cfg(test)] split on parse_module()
- inferred_type_from_tag import (was only used for JSON deserialization)
Net: -253 lines. One code path for production and tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: workspace indexing with Rayon + workspace/symbol search
Workspace indexing:
- Scans workspace root for *.pm, *.pl, *.t files using `ignore` crate
(respects .gitignore, skips blib/, node_modules/, etc.)
- Parallel parsing with Rayon (defaults to num_cpus threads)
- catch_unwind per file for defense-in-depth, 1MB file size cap
- Background-spawned from initialized(), non-blocking
- File watchers registered for create/change/delete via
workspace/didChangeWatchedFiles
workspace/symbol:
- Searches open documents (freshest) then workspace index
- Fuzzy substring match on symbol name
- Returns subs, methods, packages, classes with location
New dependencies: rayon = "1", ignore = "0.4"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add progress reporting for workspace indexing + spawn_blocking for file watchers
- window/workDoneProgress begin/end for workspace indexing (matches
cpanfile indexing pattern)
- did_change_watched_files now uses spawn_blocking to avoid blocking
the async runtime on bulk file changes (branch switch, git checkout)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: cross-file rename, prepareRename, range formatting, linked editing
Cross-file rename (Part C):
- RenameKind enum determines single-file vs cross-file scope
- Variable rename stays single-file (lexical scope)
- Function/method/package rename searches open docs + workspace index
- rename_function, rename_method, rename_package on FileAnalysis
prepareRename:
- Returns range + placeholder for symbol/ref at cursor
- Capability registered with prepare_provider: true
Range formatting (Part E):
- Extracts selected lines, pipes to perltidy, returns edits
- Reuses the existing perltidy integration pattern
Linked editing range (Part F):
- When cursor is on a symbol, all references become editable ranges
- Reuses find_references for the range collection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: e2e tests for single-file and cross-file rename
Single-file: $pi → $tau in sample.pl — applies edit, verifies all
occurrences renamed, then undoes to restore original content.
Cross-file: process → execute on $worker->process() in inheritance.pl —
verifies WorkspaceEdit contains edits in both inheritance.pl AND
BaseWorker.pm without applying (no file modification).
Added rename() and apply_workspace_edit() helpers to test/lsp.lua.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: method rename replaces only the method name, not the whole expression
MethodCall refs now store method_name_span separately from the expression
span. rename_method uses it for precise name-only replacement.
Before: $self->process({ input => 1 }) → execute
After: $self->execute({ input => 1 })
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: rename_sub searches both FunctionCall and MethodCall refs
In Perl, sub foo can be called as foo() or $obj->foo(). The old
rename_function only searched FunctionCall, rename_method only searched
MethodCall. Cross-file rename from a sub definition missed all method
call sites.
Unified into rename_sub which searches both ref kinds. Backend dispatch
uses rename_sub for both RenameKind::Function and RenameKind::Method.
Unit test confirms: sub emit + emit('event') + $self->emit('done')
all found by rename_sub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: CLI modes for rename and workspace-symbol + fixes
--rename <root> <file> <line> <col> <new_name>: index workspace, perform
cross-file rename, output JSON edits. Canonicalizes paths so file_path
matches workspace_index keys.
--workspace-symbol <root> <query>: index workspace, search symbols.
--help / --version for discoverability.
Fixes from review:
- Path canonicalization for workspace_index key matching
- Target file pulled from workspace_index (no separate parse)
- DRY span_to_json helper for edit serialization
- Variable/HashKey single-file cases consolidated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: hash key rename with tree context + Moo constructor arg keys
Bug A partial fix: rename_at_with_tree passes tree/source through to
find_references so hash key owner resolution works when the tree is
available (LSP path). Hash key rename for function-return keys works
end-to-end. Direct hash assignment keys remain a known limitation
(Bug B from the catalogue — needs symbol_at to find HashKeyDefs).
Bug D fix: visit_has_call now synthesizes HashKeyDef symbols owned by
"new" for each Moo/Moose/Mojo has attribute. Foo->new(username => ...)
connects to `has username`.
Also:
- symbols::rename gains tree/source params, backend passes them
- rename_at_with_tree public API for callers that have tree context
- Unit test for Moo constructor HashKeyDef synthesis
- Unit test for rename_sub covering both call kinds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add ref coverage + provenance principles to architecture rules
Two new architecture rules in CLAUDE.md:
Rule 7: Every meaningful token gets a ref. If a user can put their
cursor on a token and it means something, ref_at() must return a ref
for it. Documents known gaps (fat-comma keys in call args, hash
literal keys, framework constructor args) and the specificity rule
(narrowest span wins when refs overlap).
Rule 8: Provenance — refs should trace back to their source. Derived
refs (constant folding, import re-export, framework synthesis) need
traceable derivation chains. Documents six provenance chains: constant
folding backwards, has→accessor→constructor→hash key, import list,
return hash key→caller deref, package→file path, inherited overrides.
Also updates: file map (CLI modes, no subprocess), cross-file section
(subprocess removal, workspace indexing), LSP capabilities (rename
cross-file, workspace/symbol, rangeFormatting, linkedEditingRange,
use-line completion).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: spec ref coverage gaps + provenance for rename improvements
Part 1 — Ref coverage (Rule 7):
- Gap A: ref_at() specificity — narrowest span wins when refs overlap
- Gap B: Fat-comma keys in call args need HashKeyAccess refs
- Gap C: HashKeyDef symbols need correct selection_span for symbol_at
- Gap D: find_references for hash keys — collect defs + accesses by owner
- Gap E: Hash deref keys resolve via Gap D once owner chain works
Part 2 — Provenance (Rule 8):
- Chain 1: Constant folding backwards — folded_from span on Ref
- Chain 2: Import list rename — verify emit_refs_for_strings works
- Chain 3: has → accessor → constructor → hash key unified rename
- Chain 4: Return hash key → caller deref (works once Gap D fixed)
- Chain 5: Package rename → file rename (stretch)
- Chain 6: Inherited override tracking (stretch)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: e2e coverage for hash key rename + Moo constructor arg rename
E2e tests added:
- Hash key rename from $db_config->{host} — verifies def + access updated
- Moo constructor arg rename from MooApp->new(name => ...) — verifies
has def + constructor arg updated
CLI fix: --rename HashKey branch now parses tree for owner resolution.
Cleanup: merged rename_at and rename_at_with_tree into single rename_at
with tree/source params. Zero warnings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>1 parent 1b92ea1 commit d472529
File tree
15 files changed
+1357
-276
lines changed- docs
- lua/test
- src
15 files changed
+1357
-276
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
32 | | - | |
| 32 | + | |
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
| 38 | + | |
39 | 39 | | |
40 | | - | |
| 40 | + | |
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
44 | 59 | | |
45 | 60 | | |
46 | | - | |
47 | | - | |
| 61 | + | |
| 62 | + | |
48 | 63 | | |
49 | 64 | | |
50 | 65 | | |
51 | 66 | | |
52 | 67 | | |
53 | 68 | | |
54 | 69 | | |
55 | | - | |
| 70 | + | |
56 | 71 | | |
57 | 72 | | |
58 | 73 | | |
| |||
93 | 108 | | |
94 | 109 | | |
95 | 110 | | |
96 | | - | |
| 111 | + | |
97 | 112 | | |
98 | 113 | | |
99 | 114 | | |
| |||
121 | 136 | | |
122 | 137 | | |
123 | 138 | | |
124 | | - | |
| 139 | + | |
125 | 140 | | |
126 | 141 | | |
127 | 142 | | |
| |||
132 | 147 | | |
133 | 148 | | |
134 | 149 | | |
135 | | - | |
| 150 | + | |
136 | 151 | | |
137 | 152 | | |
138 | 153 | | |
139 | 154 | | |
140 | | - | |
141 | | - | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
142 | 165 | | |
143 | 166 | | |
144 | 167 | | |
145 | 168 | | |
146 | 169 | | |
147 | 170 | | |
148 | 171 | | |
149 | | - | |
150 | | - | |
| 172 | + | |
| 173 | + | |
151 | 174 | | |
152 | 175 | | |
153 | 176 | | |
154 | 177 | | |
155 | 178 | | |
156 | 179 | | |
| 180 | + | |
157 | 181 | | |
158 | 182 | | |
| 183 | + | |
| 184 | + | |
159 | 185 | | |
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
| 16 | + | |
15 | 17 | | |
16 | 18 | | |
0 commit comments