Skip to content

Support functions in View() #8262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 25, 2025
Merged
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
2 changes: 1 addition & 1 deletion extensions/positron-r/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@
},
"positron": {
"binaryDependencies": {
"ark": "0.1.193"
"ark": "0.1.194"
},
"minimumRVersion": "4.2.0",
"minimumRenvVersion": "1.0.9"
Expand Down
8 changes: 7 additions & 1 deletion extensions/positron-r/src/virtual-documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import * as vscode from 'vscode';
import { RequestType } from 'vscode-languageclient';
import { LanguageClient } from 'vscode-languageclient/node';
import { LOGGER } from './extension';

interface VirtualDocumentParams {
path: string;
Expand All @@ -27,6 +28,11 @@ export class VirtualDocumentProvider implements vscode.TextDocumentContentProvid
path: uri.path,
};

return await this._client.sendRequest(VIRTUAL_DOCUMENT_REQUEST_TYPE, params, token);
try {
return await this._client.sendRequest(VIRTUAL_DOCUMENT_REQUEST_TYPE, params, token);
} catch (err) {
LOGGER.warn(`Failed to provide document for URI '${uri}': ${err}`);
return 'Error: This document does not exist';
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you think about including the URI and error in the document body, or showing it in a notification, so it's easier to diagnose without digging into logs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about that but I worried about making this less user friendly. The main question is whether this should be considered a regular UI message or an exceptional one that warrants presenting debug info to the user.

It would probably be fine to do the latter for now, but if we ever have vdocs representing transient objects with good lifecycle management (vdoc goes out of scope with the object they represent), then this error message would be a normal part of the user experience.

I plan to reuse this mechanism for the fallback vdocs of the debugger. Currently they are managed via DAP and a big downside is that the names of these editors don't have a .R extension and Positron doesn't activate R language support in these editors. By using ark: URIs pointing to documents fully managed by Ark, we'll have better control. Unlike the documents created by View(), these documents will be cleaned up, when the debugging session ends. So users might start seeing this message more regularly (not entirely sure, maybe that will only be the case if we notify the frontend provider that the document has been updated).

}
}
}
3 changes: 2 additions & 1 deletion positron/comms/variables-backend-openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@
"schema": {
"description": "The ID of the viewer that was opened.",
"type": "string"
}
},
"required": false
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,15 @@ class ExtHostLanguageRuntimeSessionAdapter extends Disposable implements ILangua
} else if (ev.name === UiFrontendEvent.OpenEditor) {
// Open an editor
const ed = ev.data as OpenEditorEvent;

let file = URI.parse(ed.file);
if (!file.scheme) {
// If the URI doesn't have a scheme, assume it's a file URI
file = URI.file(ed.file);
}

const editor: ITextResourceEditorInput = {
resource: URI.file(ed.file),
resource: file,
options: { selection: { startLineNumber: ed.line, startColumn: ed.column } }
};
this._editorService.openEditor(editor);
Expand Down
10 changes: 5 additions & 5 deletions src/vs/workbench/api/common/positron/extHostMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,14 @@ export class ExtHostMethods implements extHostProtocol.ExtHostMethodsShape {
}

async createDocument(contents: string, languageId: string): Promise<null> {

const uri = await this.documents.createDocumentData({
content: contents, language: languageId
content: contents,
language: languageId,
});
const documentData = await this.documents.ensureDocumentData(uri);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is just a small cleanup to use await syntax that I did while I was planning to do more changes here. I didn't end up modifying this handler, but I thought we might keep the cleanup. It causes the handler to only resolve when showTextDocument() has resolved, which I think is probably best in terms of assumptions made by the requester.


const opts: TextEditorOpenOptions = { preview: true };
this.documents.ensureDocumentData(uri).then(documentData => {
this.editors.showTextDocument(documentData.document, opts);
});
await this.editors.showTextDocument(documentData.document, opts);

// TODO: Return a document ID
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@ export const VariableItem = (props: VariableItemProps) => {
));
}

// If a binding was returned, save the binding between the viewer and the variable item.
// If a binding was returned, save the binding between the viewer and the
// variable item. Note that it's valid for backends to not return any ID
// if no comm was open. This happens with Ark when the user views a
// function object: a virtual document is opened in an editor but is not
// managed by a comm.
if (viewerId) {
explorerService.setInstanceForVar(viewerId, item.id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ export class PositronVariable {
/**
* Requests that the language runtime open a viewer for this variable.
*
* @returns The ID of the viewer that was opened.
* @returns The ID of the viewer that was opened, if any.
*/
async view(): Promise<string> {
async view(): Promise<string | undefined> {
const path = this.parentKeys.concat(this.data.access_key);
return this._comm.view(path);
}
Expand Down Expand Up @@ -268,4 +268,3 @@ export class VariablesClientInstance extends Disposable {
}));
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ export class PositronVariablesComm extends PositronBaseComm {
*
* @returns The ID of the viewer that was opened.
*/
view(path: Array<string>): Promise<string> {
view(path: Array<string>): Promise<string | undefined> {
return super.performRpc('view', ['path'], [path]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export class VariableItem implements IVariableItem {
/**
* Requests that a viewer be opened for this variable.
*/
async view(): Promise<string> {
async view(): Promise<string | undefined> {
return this._variable.view();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@ export interface IVariableItem {
/**
* Requests that a data viewer be opened for this variable.
*/
view(): Promise<string>;
view(): Promise<string | undefined>;
}