Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/vscode/src/@types/hooks.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare module 'positron' {
runtime: PositronRuntime;
languages: PositronLanguages;
window: PositronWindow;
StatementRangeSyntaxError: typeof StatementRangeSyntaxError;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we access StatementRangeSyntaxError as a value and not just as a type, it must live here as well. i.e. we do err instanceof hooks.StatementRangeSyntaxError and throw new hooks.StatementRangeSyntaxError() with it.

This explains why I was seeing weird errors during yarn run build dev of

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';
quarto:dev:          ╵                        ~~~~~~~~~~

}

export interface PositronRuntime {
Expand Down Expand Up @@ -58,6 +59,11 @@ declare module 'positron' {
readonly code?: string;
}

export class StatementRangeSyntaxError extends Error {
readonly line?: number;
constructor(line?: number);
}

export interface PositronWindow {
createPreviewPanel(
viewType: string,
Expand Down
42 changes: 35 additions & 7 deletions apps/vscode/src/host/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
import * as vscode from 'vscode';
import * as hooks from 'positron';

import semver from "semver";
import { ExtensionHost, HostWebviewPanel, HostStatementRangeProvider, HostHelpTopicProvider } from '.';
import { CellExecutor, cellExecutorForLanguage, executableLanguages, isKnitrDocument, pythonWithReticulate } from './executors';
import { ExecuteQueue } from './execute-queue';
import { MarkdownEngine } from '../markdown/engine';
import { virtualDoc, adjustedPosition, unadjustedRange, withVirtualDocUri, VirtualDocStyle } from "../vdoc/vdoc";
import { virtualDoc, adjustedPosition, unadjustedRange, withVirtualDocUri, VirtualDocStyle, unadjustedLine } from "../vdoc/vdoc";
import { Position, Range } from 'vscode';
import { Uri } from 'vscode';

Expand Down Expand Up @@ -200,18 +201,45 @@ class EmbeddedStatementRangeProvider implements HostStatementRangeProvider {
position: vscode.Position,
token: vscode.CancellationToken): Promise<hooks.StatementRange | undefined> {
const vdoc = await virtualDoc(document, position, this._engine, VirtualDocStyle.Block);
if (vdoc) {
return await withVirtualDocUri(vdoc, document.uri, "statementRange", async (uri: vscode.Uri) => {

if (!vdoc) {
return undefined;
}

return await withVirtualDocUri(vdoc, document.uri, "statementRange", async (uri: vscode.Uri) => {
try {
const result = await vscode.commands.executeCommand<hooks.StatementRange>(
"vscode.executeStatementRangeProvider",
uri,
adjustedPosition(vdoc.language, position)
);
return { range: unadjustedRange(vdoc.language, result.range), code: result.code };
});
} else {
return undefined;
}
} catch (err) {
let hooks = hooksApi();

if (!hooks) {
throw err;
}

// 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.
// We can't use `semver.lt()` because calendar versioning isn't compatible with semver due to the
// leading `0` in `03`. Instead, we use lexicographic string comparison and rely on the year and
// month to be zero padded so sorting always works correctly.
if (hooks.version < "2026.03.0") {
throw err;
}

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);
} else {
// Rethrow unrecognized error
throw err;
}
}
});
};
}

Expand Down
14 changes: 11 additions & 3 deletions apps/vscode/src/vdoc/vdoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,21 @@ export function isBlockOfLanguage(language: EmbeddedLanguage) {
};
}

// adjust position for inject
// adjust line for inject
export function adjustedLine(language: EmbeddedLanguage, line: number): number {
return line + (language.inject?.length || 0);
}

export function unadjustedLine(language: EmbeddedLanguage, line: number): number {
return line - (language.inject?.length || 0);
}

export function adjustedPosition(language: EmbeddedLanguage, pos: Position) {
return new Position(pos.line + (language.inject?.length || 0), pos.character);
return new Position(adjustedLine(language, pos.line), pos.character);
}

export function unadjustedPosition(language: EmbeddedLanguage, pos: Position) {
return new Position(pos.line - (language.inject?.length || 0), pos.character);
return new Position(unadjustedLine(language, pos.line), pos.character);
}

export function unadjustedRange(language: EmbeddedLanguage, range: Range) {
Expand Down
Loading