I created an extension that interacts with documents. In order to test the extension I need to create documents, that the extension can work with. The extension has to access the document via uri.
Currently I'm using vscode.workspace.openTextDocument({content: _content, language: _language});
for document creation. The problem is, it does not have a valid URI.
How can I create a virtual document in memory, that has a valid URI?
As there was no native solution to this, I created my and I'd like to share it here:
A TextDocumentContentProvider
for files in memory. Example usage shown below
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;
}
}
You need to register the provider somewhere in the beginning of your test code (I do it in index.ts
before Mocha
is instantiated):
register_memoryFileProvider (extensionContext);
(How do I get the extension context?)
Creating and using a file works as follows:
// 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 ());