文档选择器

插件的特性可以通过语言、类型、位置等文档选择器类型加以筛选,本节将深入文档选择器、文档协议等插件创作者应该了解的内容。

不在磁盘上的文件


并不是所有文件都是储存在磁盘上的,比如一份刚刚创建的文件。除非特别指明,文档选择器通常会应用于所有文档类型。使用DocumentFilterscheme属性将协议范围缩小,比如说,{ scheme: 'file', language: 'typescript' }是特定的用于储存在磁盘上的TypeScript文件。

文档选择器


VS Code插件API结合了特定的语言特性, 通过文档选择器的DocumentSelector类型, 可以支持例如智能感知(IntelliSense)等特性. 这是实现特定语言所支持特性的最为简单的机制.

下面的片段注册了一个Typescript文件的HoverProvider, 此时的文档选择器是typescript语言标识符.

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

文档选择器可以不只是一个语言标识符, 还可以是复杂选择器——比如基于协议(scheme)和文件路径的DocumentFilter, 文件路径支持pattern参数和glob模式:

  1. vscode.languages.registerHoverProvider(
  2. { pattern: '**/test/**' },
  3. {
  4. provideHover(doc: vscode.TextDocument) {
  5. return new vscode.Hover('For documents inside `test`-folders only');
  6. }
  7. }
  8. );

下面这个片段, 使用合并后的协议(scheme)过滤器和语言标识符作为参数. 未命名的(untitled)协议正是为暂未保存到本地磁盘的文件准备的.

  1. vscode.languages.registerHoverProvider(
  2. { scheme: 'untitled', language: 'typescript' },
  3. {
  4. provideHover(doc: vscode.TextDocument) {
  5. return new vscode.Hover('For new, unsaved TypeScript documents only');
  6. }
  7. }
  8. );

文档协议


文档协议经常会被忽视, 但是它提供了很重要的信息. 插件开发者经常假设自己正在处理的文档也是存在磁盘上的. 用一个简单的typescript选择器做个例子, 假设Typescript文件在磁盘上, 不过大部分开发场景都过于宽松了,使用了诸如{ scheme: 'file', language: 'typescript' }显式的选择器。

当某项功能依赖于从磁盘上读/写文件时, 这个问题显得尤为重要. 请看下面的代码:

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

上面的例子中, 悬浮提示器想展示文件占用的磁盘大小, 但是它不会检查文档是不是真的存储在磁盘上. 比如, 一个新创建但是未保存的文件. 正确的做法是告诉VS Code只在文件存储在磁盘上时才开始工作.

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

总结


文档通常都储存在文件系统中,但也有例外:未保存的新文件、Git使用的缓存文件、FTP上的远程文件等等。如果你的插件特性依赖于磁盘读取,那么你就要用文档选择器时应带上file协议。

下一步

阅读下列文章来了解更多有关于VS Code可拓展模型的知识.