Skip to content
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

About document selectors that don't specify a scheme #1565

Closed
jrieken opened this issue Apr 17, 2018 · 0 comments
Closed

About document selectors that don't specify a scheme #1565

jrieken opened this issue Apr 17, 2018 · 0 comments
Assignees
Milestone

Comments

@jrieken
Copy link
Member

jrieken commented Apr 17, 2018

This issue is about document selectors, the scheme of documents, and what extensions authors should be aware about.

tl;dr

Not all text documents are stored on disk, e.g. newly created documents. Unless specified a document selector applies to all those documents. Use the scheme-property to narrow down on certain schemes, e.g. { scheme: 'file', language: 'typescript' } for TypeScript files that are stored on disk.

Document Selector

The VS Code extension API combines language-specific feature, like IntelliSense, with document selectors. They are an easy mechanism to narrow down on a specific language. For instance the snippet below registers a HoverProvider for TypeScript files - the document selector is the typescript language identifier string.

vscode.languages.registerHoverProvider('typescript', {
    provideHover(doc: vscode.TextDocument) {
        return new vscode.Hover('For *all* TypeScript documents.');
    }
})

A document selector is not just a language identifier, indeed that's the most basic form of it, and more complex selectors target the scheme, path, and language-identifier of a document, e.g. using a glob-pattern:

vscode.languages.registerHoverProvider({ pattern: '**/test/**' }, {
    provideHover(doc: vscode.TextDocument) {
        return new vscode.Hover('For documents inside `test`-folders only');
    }
})

The next snippet uses the scheme-filter and combines it with a language identifier. The untitled-scheme is for new files that have not yet been saved to disk.

vscode.languages.registerHoverProvider({ scheme: 'untitled', language: 'typescript' }, {
    provideHover(doc: vscode.TextDocument) {
        return new vscode.Hover('For new, unsaved TypeScript documents only');
    }
})

Document Scheme

The scheme of a document is something that's often overlooked but it is an important piece of information. Because almost all documents are saved on disk, extension authors typically assume "TypeScript files on disk" when using the typescript-selector. However, that is too lax and { scheme: 'file', language: 'typescript' } should be used.

The importance of this comes into play when features rely on reading/writing files from/to disk. Check out the snippet below:

vscode.languages.registerHoverProvider('typescript', { // 👎 too lax
    provideHover(doc: vscode.TextDocument) {
        const { size } = fs.statSync(doc.uri.fsPath); // ⚠️ what about 'untitled:/Untitled1.ts' or others?
        return new vscode.Hover(`Size in bytes is ${size}`); 
    }
})

The hover provider above wants to display the size of a document on disk but it fails to check that the document is actually kept on disk, e.g. it could be new and not yet saved. The correct way would be to tell VS Code that the provider can only work with files on disk.

vscode.languages.registerHoverProvider({ scheme: 'file', language: 'typescript' }, { // 👍 only works with files on disk
    provideHover(doc: vscode.TextDocument) {
        const { size } = fs.statSync(doc.uri.fsPath); 
        return new vscode.Hover(`Size in bytes is ${size}`); 
    }
})

Summary

Documents usually live on disk, but not always: there are untitled documents, cached documents git keeps around, documents from remote source like ftp and so forth. If your feature relies on disk-access make sure to use a document selector with the file-scheme, otherwise everything is OK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants