VSCode: 在内存中创建一个带有URI 的文档用于自动化测试?
VSCode: Create a document in memory with URI for automated testing?
背景
我创建了一个与文档交互的扩展。为了测试扩展我需要创建文档,扩展可以使用。扩展 必须通过 uri.
访问文档
目前我正在使用 vscode.workspace.openTextDocument({content: _content, language: _language});
创建文档。问题是,它没有有效的 URI。
问题
如何在内存中创建具有有效 URI 的虚拟文档?
由于没有本地解决方案,我创建了我的解决方案并想在这里分享:
A TextDocumentContentProvider
用于内存中的文件。示例用法如下所示
memoryfile.ts
import * as vscode from 'vscode';
const _SCHEME = "inmemoryfile";
/**
* Registration function for In-Memory files.
* You need to call this once, if you want to make use of
* `MemoryFile`s.
**/
export function register_memoryFileProvider ({ subscriptions }: vscode.ExtensionContext)
{
const myProvider = new (class implements vscode.TextDocumentContentProvider
{
provideTextDocumentContent(uri: vscode.Uri): string
{
let memDoc = MemoryFile.getDocument (uri);
if (memDoc == null)
return "";
return memDoc.read ();
}
})();
subscriptions.push(vscode.workspace.registerTextDocumentContentProvider(
_SCHEME, myProvider));
}
/**
* Management class for in-memory files.
**/
class MemoryFileManagement
{
private static _documents: {[key: string]: MemoryFile} = {};
private static _lastDocId: number = 0;
public static getDocument(uri: vscode.Uri) : MemoryFile | null
{
return MemoryFileManagement._documents[uri.path];
}
private static _getNextDocId(): string{
MemoryFileManagement._lastDocId++;
return "_" + MemoryFileManagement._lastDocId + "_";
}
public static createDocument(extension = "")
{
let path = MemoryFileManagement._getNextDocId ();
if (extension != "")
path += "." + extension;
let self = new MemoryFile(path);
MemoryFileManagement._documents[path] = self;
return self;
}
}
/**
* A file in memory
**/
export class MemoryFile
{
/******************
** Static Area **
******************/
public static getDocument(uri: vscode.Uri) : MemoryFile | null {
return MemoryFileManagement.getDocument (uri);
}
public static createDocument(extension = "") {
return MemoryFileManagement.createDocument (extension);
}
/******************
** Object Area **
******************/
public content: string = "";
public uri: vscode.Uri;
constructor (path: string)
{
this.uri = vscode.Uri.from ({scheme: _SCHEME, path: path})
}
public write(strContent: string){
this.content += strContent;
}
public read(): string {
return this.content;
}
public getUri(): vscode.Uri {
return this.uri;
}
}
用法示例
注册提供商
您需要在测试代码开头的某处注册提供者(我在 index.ts
实例化 Mocha
之前注册):
register_memoryFileProvider (extensionContext);
(How do I get the extension context?)
创建文档
创建和使用文件的过程如下:
// create the in-memory document
let memfile = MemoryFile.createDocument ("ts");
memfile.write ("my content");
// create a vscode.TextDocument from the in-memory document.
let doc = await vscode.workspace.openTextDocument (memfile.getUri ());
备注
- 请注意,LSP 命令可能不适用于方法,因为它们可能已注册到某个特定的 schema.
正如 rioV8 所说,您还可以使用现有文档并更改其内容。这里的代码:
export class TmpFile
{
private static _lastDocId: number = 0;
private static _getNextDocId(): string{
this._lastDocId++;
return "tmpfile_" + this._lastDocId;
}
public static async createDocument(strContent: string, extension:string = "")
: Promise<vscode.TextDocument | null>
{
let folder = "/tmp"
let filename = this._getNextDocId ();
let ext = (extension != "" ? "." + extension : "");
const newFile = vscode.Uri.parse('untitled:' + path.join(folder, filename + ext));
{
const edit = new vscode.WorkspaceEdit();
edit.insert(newFile, new vscode.Position(0, 0), strContent);
let success = await vscode.workspace.applyEdit(edit);
if (!success)
return null;
}
let document = await vscode.workspace.openTextDocument(newFile);
return document;
}
}
专业人士
- 它是一个文件(架构),因此所有 LSP 命令都可以使用
- 路径(上面使用的)甚至不需要存在。
缺点
- 文件真的在编辑器中打开了。您需要稍后关闭它
- 该文件是编辑器中的更改文件,因此它会要求您在关闭时保存更改。
- 无法在 vscode 中关闭文件。您只能 运行:
vscode.window.showTextDocument(doc.uri, {preview: true, preserveFocus: false})
.then(() => {
return vscode.commands.executeCommand('workbench.action.closeActiveEditor');
});
```<br>
which is a rather nasty workaround.
背景
我创建了一个与文档交互的扩展。为了测试扩展我需要创建文档,扩展可以使用。扩展 必须通过 uri.
访问文档目前我正在使用 vscode.workspace.openTextDocument({content: _content, language: _language});
创建文档。问题是,它没有有效的 URI。
问题
如何在内存中创建具有有效 URI 的虚拟文档?
由于没有本地解决方案,我创建了我的解决方案并想在这里分享:
A TextDocumentContentProvider
用于内存中的文件。示例用法如下所示
memoryfile.ts
import * as vscode from 'vscode';
const _SCHEME = "inmemoryfile";
/**
* Registration function for In-Memory files.
* You need to call this once, if you want to make use of
* `MemoryFile`s.
**/
export function register_memoryFileProvider ({ subscriptions }: vscode.ExtensionContext)
{
const myProvider = new (class implements vscode.TextDocumentContentProvider
{
provideTextDocumentContent(uri: vscode.Uri): string
{
let memDoc = MemoryFile.getDocument (uri);
if (memDoc == null)
return "";
return memDoc.read ();
}
})();
subscriptions.push(vscode.workspace.registerTextDocumentContentProvider(
_SCHEME, myProvider));
}
/**
* Management class for in-memory files.
**/
class MemoryFileManagement
{
private static _documents: {[key: string]: MemoryFile} = {};
private static _lastDocId: number = 0;
public static getDocument(uri: vscode.Uri) : MemoryFile | null
{
return MemoryFileManagement._documents[uri.path];
}
private static _getNextDocId(): string{
MemoryFileManagement._lastDocId++;
return "_" + MemoryFileManagement._lastDocId + "_";
}
public static createDocument(extension = "")
{
let path = MemoryFileManagement._getNextDocId ();
if (extension != "")
path += "." + extension;
let self = new MemoryFile(path);
MemoryFileManagement._documents[path] = self;
return self;
}
}
/**
* A file in memory
**/
export class MemoryFile
{
/******************
** Static Area **
******************/
public static getDocument(uri: vscode.Uri) : MemoryFile | null {
return MemoryFileManagement.getDocument (uri);
}
public static createDocument(extension = "") {
return MemoryFileManagement.createDocument (extension);
}
/******************
** Object Area **
******************/
public content: string = "";
public uri: vscode.Uri;
constructor (path: string)
{
this.uri = vscode.Uri.from ({scheme: _SCHEME, path: path})
}
public write(strContent: string){
this.content += strContent;
}
public read(): string {
return this.content;
}
public getUri(): vscode.Uri {
return this.uri;
}
}
用法示例
注册提供商
您需要在测试代码开头的某处注册提供者(我在 index.ts
实例化 Mocha
之前注册):
register_memoryFileProvider (extensionContext);
(How do I get the extension context?)
创建文档
创建和使用文件的过程如下:
// create the in-memory document
let memfile = MemoryFile.createDocument ("ts");
memfile.write ("my content");
// create a vscode.TextDocument from the in-memory document.
let doc = await vscode.workspace.openTextDocument (memfile.getUri ());
备注
- 请注意,LSP 命令可能不适用于方法,因为它们可能已注册到某个特定的 schema.
正如 rioV8 所说,您还可以使用现有文档并更改其内容。这里的代码:
export class TmpFile
{
private static _lastDocId: number = 0;
private static _getNextDocId(): string{
this._lastDocId++;
return "tmpfile_" + this._lastDocId;
}
public static async createDocument(strContent: string, extension:string = "")
: Promise<vscode.TextDocument | null>
{
let folder = "/tmp"
let filename = this._getNextDocId ();
let ext = (extension != "" ? "." + extension : "");
const newFile = vscode.Uri.parse('untitled:' + path.join(folder, filename + ext));
{
const edit = new vscode.WorkspaceEdit();
edit.insert(newFile, new vscode.Position(0, 0), strContent);
let success = await vscode.workspace.applyEdit(edit);
if (!success)
return null;
}
let document = await vscode.workspace.openTextDocument(newFile);
return document;
}
}
专业人士
- 它是一个文件(架构),因此所有 LSP 命令都可以使用
- 路径(上面使用的)甚至不需要存在。
缺点
- 文件真的在编辑器中打开了。您需要稍后关闭它
- 该文件是编辑器中的更改文件,因此它会要求您在关闭时保存更改。
- 无法在 vscode 中关闭文件。您只能 运行:
vscode.window.showTextDocument(doc.uri, {preview: true, preserveFocus: false})
.then(() => {
return vscode.commands.executeCommand('workbench.action.closeActiveEditor');
});
```<br>
which is a rather nasty workaround.