Repository navigation
fix: complete session columns in grouped and nested pipelines - #1901
Conversation
eitsupi
left a comment
There was a problem hiding this comment.
Reviewed by ChatGPT.
No clear correctness issues were identified, but there is one performance concern worth checking before merging.
getPipelineCompletionItems() now passes the entire document text from the beginning (or the current R Markdown chunk) to the cursor into getPipelineSource(). This means every completion triggered by ( or , tokenizes and parses all preceding code, even when the completion is unrelated to a pipeline.
Since completion runs frequently on the extension host, this could affect responsiveness in large R files. Cancellation is also checked only after parsing completes.
Could we benchmark this with large R files (e.g., several thousand to tens of thousands of lines)? If the overhead is significant, limiting the parsing scope or introducing caching may be necessary.
The custom parser also adds a considerable maintenance burden. I suggest keeping its scope explicitly limited to resolving pipeline sources rather than gradually expanding it into a general-purpose R parser.
|
Addressed the performance and cancellation concerns in bddd864. The provider now keeps a weakly held cache per document. It reuses an unchanged lexical prefix and its enclosing pipeline context, scans only the suffix after the checkpoint, and discards completed statements and earlier call arguments before parsing. Earlier edits, cursor moves into the cached prefix, and changed R Markdown regions restart scanning as needed. Cold scans yield between chunks, so cancellation and document version changes can interrupt completion and suppress stale results. The benchmark now covers 1,000, 10,000, and 50,000 preceding lines, both pipeline and ordinary completion calls, repeated requests, and edits at the cursor. An earlier pipeline is included so ordinary calls cannot benefit from simply searching the whole document for a pipe. Local ordinary-call medians over nine runs were:
For the 50,000-line pipeline case, the cold scan took 37.26 ms in total, with a maximum observed event-loop blocking interval of 1.02 ms, compared with 61.50 ms for the original cold scan. These measurements cover the resolver separately from VS Code document extraction, using Node 26.12.0 on macOS. They are reproducible with The helper remains limited to pipeline source lookup, with no document evaluation or general R analysis. Parsing is bounded to 4,096 retained tokens and 128 nesting levels; oversized expressions return no session column suggestions. Validation: 123 resolver tests and 68 focused VS Code tests passed, including cache invalidation, cancellation, stale-document handling, and malformed-code recovery. All six CI checks are now green on bddd864: macOS, Linux, and Windows tests, build, formatting, and lint. |
Pipeline column completion stopped at the first nonempty line of the selected expression, so wrapping
raw %>% select()in multiline parentheses removed the session column suggestions. The same lookup could select the wrong input in nested or neighboring pipelines.Resolve the initial session symbol from the expression containing the cursor. The resolver handles grouping, calls, argument and statement boundaries, operator precedence, comments, normal/raw strings, quoted and Unicode names, native pipes, and magrittr pipes including nested dot placeholders. R Markdown completion is limited to the current R chunk. Computed inputs remain unresolved, and column suggestions continue to use the initial object's cached session names without evaluating document code.
Each document has a weakly held lexical-prefix cache. Repeated requests and edits after a safe checkpoint scan only the changed suffix; edits before it and cursor moves into it restart scanning. Completed statements and earlier call arguments are discarded while retaining their enclosing pipeline context. Cold scans yield between chunks of roughly 8,192 characters, and cancellation or a document version change suppresses stale results. Source resolution is limited to 4096 retained tokens and 128 levels of nesting; oversized expressions yield no session column suggestions. This helper only resolves pipeline sources and does not perform general R analysis or evaluation.
Fixes #1495.
Validation:
vscode.executeCompletionItemProvider, R Markdown chunk isolation, cancellation, and stale document versions (VS Code 1.142.0).git diff --checkpassed.Benchmark (
node scripts/benchmark-pipeline-completion.cjs, Node 26.12.0 on macOS): the source lookup is measured separately from VS Code document extraction. Both ordinary calls and pipeline calls are tested, with an earlier pipeline in the file. The table shows ordinary-call medians over nine runs, comparing the original PR head74def8awith the cache:The 50,000-line pipeline case measured 37.26 ms cold, 0.355 ms cached, and 0.443 ms after cursor edits. A
setImmediateheartbeat observed a maximum blocking interval of 1.02 ms during that cold scan, compared with 61.50 ms during the original cold scan. These are local measurements, not CI timing thresholds. The benchmark accepts a compiled earlier resolver module as its optional first argument for reproducing comparisons.