虚拟工作区

诸如 GitHub Repositories 等扩展,可以在一个或多个由 文件系统提供程序 支持的文件夹上打开 VS Code。当扩展实现文件系统提供程序时,工作区资源可能不位于本地磁盘,而是虚拟的(位于服务器或云端),且编辑操作也会在那里进行。

这种配置被称为虚拟工作区。当 VS Code 窗口中打开虚拟工作区时,左下角的远程指示器会通过标签进行提示,这与其他远程开发窗口类似。

Remote indicator

并非所有扩展都能处理虚拟资源,有些扩展可能要求资源必须位于磁盘上。部分扩展使用的工具依赖于磁盘访问、需要同步文件访问,或者缺乏必要的文件系统抽象。在这种情况下,当处于虚拟工作区时,VS Code 会向用户指示他们正处于受限模式,并且某些扩展会被停用或功能受限。

通常,用户希望尽可能多的扩展能在虚拟工作区中运行,并希望在浏览和编辑远程资源时获得良好的用户体验。本指南介绍了扩展如何针对虚拟工作区进行测试、描述了允许其在虚拟工作区中工作的修改建议,并介绍了 virtualWorkspaces 能力属性。

修改扩展以支持虚拟工作区,对于在 Web 版 VS Code 中良好运行也是重要的一步。Web 版 VS Code 完全在浏览器内运行,由于浏览器沙箱机制,工作区默认为虚拟的。有关详细信息,请参阅 Web 扩展指南。

我的扩展受影响吗?

如果扩展没有可执行代码,仅为声明式扩展(如主题、快捷键、代码片段或语法高亮扩展),则可以在虚拟工作区中运行,无需任何修改。

包含代码的扩展(即定义了 main 入口点的扩展)则需要检查,并可能需要进行修改。

在虚拟工作区中运行你的扩展

安装 GitHub Repositories 扩展,并从命令面板运行 Open GitHub Repository... 命令。该命令会显示一个快速选择下拉菜单,你可以粘贴任何 GitHub URL,或选择搜索特定的存储库或拉取请求。

这将打开一个虚拟工作区窗口,其中所有资源都是虚拟的。

检查扩展代码是否已为虚拟资源做好准备

VS Code 对虚拟文件系统的 API 支持已经存在很长一段时间了。你可以查阅 文件系统提供程序 API

文件系统提供程序会注册一个新的 URI 方案(例如 vscode-vfs),该文件系统上的资源将由使用此方案的 URI 表示(vscode-vfs://github/microsoft/vscode/package.json)。

检查你的扩展如何处理从 VS Code API 返回的 URI

  • 切勿假设 URI 方案总是 fileURI.fsPath 仅在 URI 方案为 file 时才能使用。
  • 注意是否有使用 fs Node 模块进行文件系统操作的情况。如果可能,请使用 vscode.workspace.fs API,它会委托给适当的文件系统提供程序。
  • 检查是否有依赖 fs 访问权限的第三方组件(例如语言服务器或 Node 模块)。
  • 如果你从命令运行可执行文件和任务,请检查这些命令在虚拟工作区窗口中是否有意义,或者是否应该禁用它们。

声明你的扩展是否支持虚拟工作区

package.jsoncapabilities 下的 virtualWorkspaces 属性用于声明扩展是否支持虚拟工作区。

不支持虚拟工作区

下面的示例声明扩展不支持虚拟工作区,且不应在虚拟工作区设置中被 VS Code 启用。

{
  "capabilities": {
    "virtualWorkspaces": {
      "supported": false,
      "description": "Debugging is not possible in virtual workspaces."
    }
  }
}

部分支持或完全支持虚拟工作区

当扩展能够工作或部分工作于虚拟工作区时,应定义 "virtualWorkspaces": true

{
  "capabilities": {
    "virtualWorkspaces": true
  }
}

如果扩展可以工作但功能有限,应向用户解释其限制。

{
  "capabilities": {
    "virtualWorkspaces": {
      "supported": "limited",
      "description": "In virtual workspaces, resolving and finding references across files is not supported."
    }
  }
}

该描述会显示在“扩展”视图中。

Extensions view

扩展随后应禁用在虚拟工作区中不支持的功能,如下所述。

默认值

对于所有尚未填写 virtualWorkspaces 能力的扩展,"virtualWorkspaces": true 是默认值。

然而,在测试虚拟工作区时,我们整理了一份我们认为应该在虚拟工作区中禁用的扩展列表。该列表可在 issue #122836 中找到。这些扩展的默认值为 "virtualWorkspaces": false

当然,扩展作者更清楚是否应该做出此决定。扩展 package.json 中的 virtualWorkspaces 能力将覆盖我们的默认设置,我们最终将弃用我们的列表。

当打开虚拟工作区时禁用功能

禁用命令和视图贡献

命令、视图以及许多其他贡献的可用性可以通过 when 子句 中的上下文键进行控制。

当所有工作区文件夹都位于虚拟文件系统上时,会设置 virtualWorkspace 上下文键。以下示例仅在非虚拟工作区时才在命令面板中显示 npm.publish 命令。

{
  "menus": {
    "commandPalette": [
      {
        "command": "npm.publish",
        "when": "!virtualWorkspace"
      }
    ]
  }
}

resourceScheme 上下文键设置为文件资源管理器中当前选中元素或编辑器中打开元素的 URI 方案。

在下面的示例中,npm.runSelectedScript 命令仅在底层资源位于本地磁盘时,才会出现在编辑器上下文菜单中。

{
  "menus": {
    "editor/context": [
      {
        "command": "npm.runSelectedScript",
        "when": "resourceFilename == 'package.json' && resourceScheme == file"
      }
    ]
  }
}

以编程方式检测虚拟工作区

要检查当前工作区是否由非 file 方案组成且是虚拟的,你可以使用以下源代码:

const isVirtualWorkspace =
  workspace.workspaceFolders &&
  workspace.workspaceFolders.every(f => f.uri.scheme !== 'file');

语言扩展与虚拟工作区

对虚拟工作区的语言支持有哪些期望?

要求所有扩展都能完全处理虚拟资源是不现实的。许多扩展使用依赖同步文件访问和磁盘文件的外部工具。因此,仅提供有限功能(例如如下列出的基础单文件支持)是可以接受的。

A. 基础语言支持

  • TextMate 分词和颜色标记
  • 特定于语言的编辑支持:括号匹配、注释、回车规则、折叠标记
  • 代码片段

B. 单文件语言支持

  • 文档符号(大纲)、折叠、选择范围
  • 文档高亮、语义高亮、文档颜色
  • 基于当前文件和静态语言库的补全、悬停提示、签名帮助、查找引用/声明
  • 格式化、联动编辑
  • 语法验证、同文件语义验证和代码操作

C. 跨文件、感知工作区的语言支持

  • 跨文件引用
  • 工作区符号
  • 工作区/项目内所有文件的验证

VS Code 内置的丰富语言扩展(TypeScript、JSON、CSS、HTML、Markdown)在处理虚拟资源时,仅限于单文件语言支持。

禁用语言扩展

如果单文件模式不可行,语言扩展也可以决定在虚拟工作区中禁用该扩展。

如果你的扩展同时提供了语法高亮和需要禁用的丰富语言支持,那么语法高亮也会被禁用。为避免这种情况,你可以创建一个独立于丰富语言支持的基础语言扩展(包含语法、语言配置、代码片段),将扩展拆分为两个。

  • 基础语言扩展设置 "virtualWorkspaces": true,并提供语言 ID、配置、语法和代码片段。
  • 丰富语言扩展设置 "virtualWorkspaces": false 并包含 main 文件。它贡献语言支持、命令,并对基础语言扩展有扩展依赖(extensionDependencies)。丰富语言扩展应保留原有扩展 ID,以便用户通过安装单个扩展即可继续获得完整功能。

你可以在内置语言扩展中看到这种方法,例如 JSON 扩展由 JSON 扩展本身和 JSON 语言功能扩展组成。

这种分离也有助于在 受限模式 下运行 不受信任的工作区。丰富语言扩展通常需要信任,而基础语言功能可以在任何设置下运行。

语言选择器

当为语言功能(例如补全、悬停、代码操作等)注册提供程序时,请确保指定该提供程序支持的方案。

return vscode.languages.registerCompletionItemProvider(
  { language: 'typescript', scheme: 'file' },
  {
    provideCompletionItems(document, position, token) {
      // ...
    }
  }
);

语言服务器协议 (LSP) 对访问虚拟资源的支持如何?

目前正在开展向 LSP 添加文件系统提供程序支持的工作。可在语言服务器协议 issue #1264 中进行跟踪。

© . This site is unofficial and not affiliated with Microsoft.