Skip to content

Commit

Permalink
Try using a unique temp file for vdocs (#585)
Browse files Browse the repository at this point in the history
* Use a unique temp file for vdocs

* Try to fix `paths` filter for CI

* Whitespaaaaaaace

* Consistently clean up vdocs

Co-authored-by: Davis Vaughan <[email protected]>

* Update changelog

---------

Co-authored-by: Lionel Henry <[email protected]>
Co-authored-by: Davis Vaughan <[email protected]>
  • Loading branch information
3 people authored Oct 29, 2024
1 parent 7d1582d commit 914c4db
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 60 deletions.
1 change: 1 addition & 0 deletions apps/vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 1.117.0 (unreleased)

- Fix issue with temp files for LSP request virtual documents (<https://github.com/quarto-dev/quarto/pull/585>)
- Improved statement execution for Python `.qmd` files in Positron (<https://github.com/quarto-dev/quarto/pull/589>)

## 1.116.0 (Release on 2024-10-08)
Expand Down
11 changes: 2 additions & 9 deletions apps/vscode/src/lsp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import {
virtualDocUri,
} from "../vdoc/vdoc";
import { activateVirtualDocEmbeddedContent } from "../vdoc/vdoc-content";
import { deactivateVirtualDocTempFiles, isLanguageVirtualDoc } from "../vdoc/vdoc-tempfile";
import { vdocCompletions } from "../vdoc/vdoc-completion";

import {
Expand Down Expand Up @@ -160,8 +159,6 @@ export async function activateLsp(
}

export function deactivate(): Thenable<void> | undefined {
deactivateVirtualDocTempFiles();

if (!client) {
return undefined;
}
Expand Down Expand Up @@ -289,8 +286,7 @@ function embeddedGoToDefinitionProvider(engine: MarkdownEngine) {
adjustedPosition(vdoc.language, position)
);
const resolveLocation = (location: Location) => {
if (isLanguageVirtualDoc(vdoc.language, location.uri) ||
location.uri.toString() === vdocUri.uri.toString()) {
if (location.uri.toString() === vdocUri.uri.toString()) {
return new Location(
document.uri,
unadjustedRange(vdoc.language, location.range)
Expand All @@ -300,8 +296,7 @@ function embeddedGoToDefinitionProvider(engine: MarkdownEngine) {
}
};
const resolveLocationLink = (location: LocationLink) => {
if (isLanguageVirtualDoc(vdoc.language, location.targetUri) ||
location.targetUri.toString() === vdocUri.uri.toString()) {
if (location.targetUri.toString() === vdocUri.uri.toString()) {
const locationLink: LocationLink = {
targetRange: unadjustedRange(vdoc.language, location.targetRange),
originSelectionRange: location.originSelectionRange
Expand Down Expand Up @@ -349,5 +344,3 @@ function isWithinYamlComment(doc: TextDocument, pos: Position) {
const line = doc.lineAt(pos.line).text;
return !!line.match(/^\s*#\s*\| /);
}


74 changes: 23 additions & 51 deletions apps/vscode/src/vdoc/vdoc-tempfile.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* vdoc-tempfile.ts
*
* Copyright (C) 2022 by Posit Software, PBC
* Copyright (C) 2022-2024 by Posit Software, PBC
* Copyright (c) 2019 Takashi Tamura
*
* Unless you have received this program directly from Posit Software pursuant
Expand All @@ -17,6 +17,7 @@
import * as fs from "fs";
import * as path from "path";
import * as tmp from "tmp";
import * as uuid from "uuid";
import {
commands,
Hover,
Expand All @@ -27,42 +28,27 @@ import {
WorkspaceEdit,
} from "vscode";
import { VirtualDoc, VirtualDocUri } from "./vdoc";
import { EmbeddedLanguage } from "./languages";

// one virtual doc per language file extension
const languageVirtualDocs = new Map<String, TextDocument>();

export async function virtualDocUriFromTempFile(
virtualDoc: VirtualDoc,
docPath: string,
virtualDoc: VirtualDoc,
docPath: string,
local: boolean
) : Promise<VirtualDocUri> {
): Promise<VirtualDocUri> {
const newVirtualDocUri = (doc: TextDocument) =>
<VirtualDocUri>{
uri: doc.uri,
cleanup: async () => await deleteDocument(doc),
};

// if this is local then create it alongside the docPath and return a cleanup
// function to remove it when the action is completed.
// if this is local then create it alongside the docPath and return a cleanup
// function to remove it when the action is completed.
if (local || virtualDoc.language.localTempFile) {
const ext = virtualDoc.language.extension;
const vdocPath = path.join(path.dirname(docPath), `.vdoc.${ext}`);
fs.writeFileSync(vdocPath, virtualDoc.content);
const vdocUri = Uri.file(vdocPath);
const doc = await workspace.openTextDocument(vdocUri);
return {
uri: doc.uri,
cleanup: async () => await deleteDocument(doc)
};
}

// do we have an existing document?
const langVdoc = languageVirtualDocs.get(virtualDoc.language.extension);
if (langVdoc && !langVdoc.isClosed) {
if (langVdoc.getText() === virtualDoc.content) {
// if its content is identical to what's passed in then just return it
return { uri: langVdoc.uri };
} else {
// otherwise remove it (it will get recreated below)
await deleteDocument(langVdoc);
languageVirtualDocs.delete(virtualDoc.language.extension);
}
return newVirtualDocUri(doc);
}

// write the virtual doc as a temp file
Expand All @@ -71,31 +57,17 @@ export async function virtualDocUriFromTempFile(
// open the document and save a reference to it
const vdocUri = Uri.file(vdocTempFile);
const doc = await workspace.openTextDocument(vdocUri);
languageVirtualDocs.set(virtualDoc.language.extension, doc);

// if this is the first time getting a virtual doc for this
// language then execute a dummy request to cause it to load
if (!langVdoc) {
await commands.executeCommand<Hover[]>(
"vscode.executeHoverProvider",
vdocUri,
new Position(0, 0)
);
}

// return the uri
return { uri: doc.uri };
}

// delete any vdocs left open
export async function deactivateVirtualDocTempFiles() {
languageVirtualDocs.forEach(async (doc) => {
await deleteDocument(doc);
});
}
// TODO: Reevaluate whether this is necessary. Old comment:
// > if this is the first time getting a virtual doc for this
// > language then execute a dummy request to cause it to load
await commands.executeCommand<Hover[]>(
"vscode.executeHoverProvider",
vdocUri,
new Position(0, 0)
);

export function isLanguageVirtualDoc(langauge: EmbeddedLanguage, uri: Uri) {
return languageVirtualDocs.get(langauge.extension)?.uri.toString() === uri.toString();
return newVirtualDocUri(doc);
}

// delete a document
Expand All @@ -121,7 +93,7 @@ function createVirtualDocTempFile(virtualDoc: VirtualDoc) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
const tmpPath = path.join(vdocTempDir, ext, ".intellisense." + ext);
const tmpPath = path.join(vdocTempDir, ext, ".intellisense." + uuid.v4() + "." + ext);
fs.writeFileSync(tmpPath, virtualDoc.content);

return tmpPath;
Expand Down

0 comments on commit 914c4db

Please sign in to comment.