Draft
Conversation
To resolve ``` quarto:dev: ✘ [ERROR] Could not resolve "positron" quarto:dev: quarto:dev: src/host/hooks.ts:19:23: quarto:dev: 19 │ import * as hooks from 'positron'; ```
DavisVaughan
commented
Feb 18, 2026
Comment on lines
+218
to
+226
| // TODO: Remove this once `apps/vscode/package.json` bumps to `"positron": "^2026.03.0"` or higher. | ||
| // For now we avoid aggressive bumping due to https://github.com/posit-dev/positron/issues/11321. | ||
| if (semver.gte(hooks.version, "2026.03.0")) { | ||
| if (err instanceof hooks.StatementRangeSyntaxError) { | ||
| // Rethrow syntax error with unadjusted line number, so Positron's notification will | ||
| // jump to the correct line | ||
| throw new hooks.StatementRangeSyntaxError(err.line ? unadjustedLine(vdoc.language, err.line) : undefined); | ||
| } | ||
| } |
Collaborator
Author
There was a problem hiding this comment.
Version guarding on the expected next positron release of "2026.03.0"
DavisVaughan
added a commit
to posit-dev/positron
that referenced
this pull request
Feb 24, 2026
Addresses #8350 - Requires posit-dev/ark#1040 - Blocks quarto-dev/quarto#919 Builds on: - quarto-dev/quarto#914 - posit-dev/ark#1030 # Summary This PR adds a new throwable `StatementRangeSyntaxError` to `positron.d.ts`. ```ts /** * An error thrown by a {@link StatementRangeProvider} to indicate that a statement range * cannot be provided due to a syntax error in the document. */ export class StatementRangeSyntaxError extends Error { /** * Zero indexed line number where the syntax error occurred. */ readonly line?: number; /** * Creates a new statement range syntax error. * * @param line Zero indexed line number where the syntax error occurred. */ constructor(line?: number); } ``` This is the only public facing API change from this PR. The idea is that from extension land (`positron-r`, `positron-python`, and `quarto`) you should be able to throw a `StatementRangeSyntaxError` from your `provideStatementRange()` provider, with an optional `line` number of where the syntax error _roughly_ starts. This gets propagated up through the main thread and into our `Cmd+Enter` handling in `positronConsoleActions.ts`, where we now detect this special case and: - Emit an info level notification telling the user that we can't execute code due to a syntax error. If the `line` number is present, we give them a button to jump to that line. - Bail from `Cmd+Enter` handling altogether. We don't even do one-line-at-a-time execution. #8350 has proved that this is just too confusing when you are trying to execute code after a syntax error. Here is what the end result looks like in an R script: https://github.com/user-attachments/assets/23dca240-06af-40d5-8b1b-a8b24af99259 Note how you can execute R code _above_ the first syntax error, thanks to posit-dev/ark#1030. It is only _below_ the first syntax error that we emit this notification and refuse to execute. It even works in roxygen2 comments where we have a little "subdocument": https://github.com/user-attachments/assets/ec920753-400d-4493-b534-188dcf4e2a65 And lastly, it works in Quarto, where we have a "virtual document" for R/Python and map the `line` number from that virtual document back into the original Qmd, thanks to quarto-dev/quarto#919 (note that if you try to run that Quarto PR, you need to remove the version guard on Positron 2026.03.0 manually). Additionally, quarto-dev/quarto#914 ensures that you can use StatementRange in any syntax-error-free cell, even if some other cell in the document has a syntax error. https://github.com/user-attachments/assets/a01b9ed1-22fe-4169-b088-a8393800d9db # Design I considered many different designs along the way, but landed on a model of: - Extension host side _models errors as throwable errors_, i.e. with `StatementRange` and `throw StatementRangeSyntaxError` ```ts export interface StatementRange { readonly range: vscode.Range; readonly code?: string; } export class StatementRangeSyntaxError extends Error { readonly line?: number; constructor(line?: number); } ``` - Main thread side _models errors as data_, i.e. a single `IStatementRange` type made up as: ```ts type IStatementRange = IStatementRangeSuccess | IStatementRangeRejection type IStatementRangeRejection = IStatementRangeSyntaxRejection export interface IStatementRangeSuccess { readonly kind: StatementRangeKind.Success; readonly range: IRange; readonly code?: string; } export interface IStatementRangeSyntaxRejection { readonly kind: StatementRangeKind.Rejection; readonly rejectionKind: StatementRangeRejectionKind.Syntax; readonly line?: number; } ``` Some rationale: - Backwards compatible and public facing `StatementRange` doesn't change - Can add new error/rejection variants as needed - Can't easily model main thread side errors as, well, `Error`s, because the `StatementRangeSyntaxError` doesn't serialize across the extension -> main thread boundary well. You basically have to turn it into some "data" type anyways to do this, and then it doesn't feel worth it to convert back on the main thread side. - Ark's custom `StatementRange` LSP Request also now uses the "success" vs "rejection" model. From Ark's LSP-ish perspective, a "rejection" is an allowed value that can be returned as an LSP Response. We reserve the JSONRPC error path for true "holy crap something horrible happened and I can't complete this request" cases. The end result looks like this: <img width="5127" height="4470" alt="test" src="https://github.com/user-attachments/assets/b341c1dd-edac-45a2-9aed-03a4b05b3c01" /> # Prior art There isn't much prior art for exactly what I'm trying to do here, but there is a little bit: - `FileSystemError` with its various flavors. Not quite the same as us because none of the flavors have any metadata to pass through, like `line`. That metadata is what steered me away from trying to have one overarching `StatementRangeError` class that could contain something like `static SyntaxError(line?: number): StatementRangeError`. I did try this, but the boilerplate didn't feel worth it. https://github.com/posit-dev/positron/blob/31c0111d42eaff76f06e1800836663e5765e1df1/src/vscode-dts/vscode.d.ts#L9474-L9486 - `Rejection`, which is used by the `RenameProvider`. Catches an error from the LSP side of things and converts it into a `Rejection` "data" type, kind of like we do. Strangely does `RenameProvider & Rejection` as the return value type. - Defined here https://github.com/posit-dev/positron/blob/9754ca9e56524315fa6b2d1981fb6cb82ef5cd7b/src/vs/editor/common/languages.ts#L2127-L2138 - Catching the error here https://github.com/posit-dev/positron/blob/9754ca9e56524315fa6b2d1981fb6cb82ef5cd7b/src/vs/workbench/api/common/extHostLanguageFeatures.ts#L882-L903 # QA ### Release Notes #### New Features - Stepping through code with `Cmd + Enter` now works more reliably when there are syntax errors in the document: - For R code: - [Code _above_ the first syntax error](posit-dev/ark#1030) can now be executed reliably with `Cmd + Enter` - [Code _below_ the first syntax error](#11907) causes a notification to pop up that informs you that reliable execution is impossible and provides you with a button to jump to the syntax error - For Quarto documents, a syntax error in one chunk no longer affects the ability to [run code in other chunks](quarto-dev/quarto#914) ### QA Notes QA: It would be nice to have two integration tests ```r 1 + 1 # <put cursor here and execute this, it should work now and send the whole statement> 2 + \ 2 ``` ```r 1 + \ 1 2 + 2 # <put cursor here and execute this, it should not send anything, and a notification should pop up> ``` `@:ark` `@:quarto` `@:console` --------- Signed-off-by: Davis Vaughan <davis@posit.co> Co-authored-by: Lionel Henry <lionel.hry@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
StatementRangeSyntaxErrorposit-dev/positron#11907 first, with finalized type namesIt feels to me like we should still use the "old"
hooks.d.tssystem for this, becauseStatementRangeis already tied up in thathooks.d.tsfile. Mixinghooks.d.tsand types from@posit-dev/positrondoesn't feel like it would be a very good idea for this extension of an existing feature, IIUC.IIUC, we can technically go ahead and merge this even without the next Positron release due to the version guard.