虚拟工作区

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

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

远程指示器

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

一般来说,用户希望尽可能多的扩展能够在虚拟工作区中工作,并在浏览和编辑远程资源时拥有良好的用户体验。本指南展示了扩展如何针对虚拟工作区进行测试,描述了允许它们在虚拟工作区中工作的修改,并介绍了virtualWorkspaces能力属性。

修改扩展以与虚拟工作区配合使用也是在VS Code for the Web中良好工作的重要步骤。VS Code for the Web 完全在浏览器内运行,并且由于浏览器沙箱的原因,工作区是虚拟的。有关更多详细信息,请参阅Web Extensions指南。

我的扩展受影响了吗?

当扩展没有可执行代码,而是像主题、键绑定、片段或语法扩展那样纯粹是声明性的时,它可以在虚拟工作空间中运行,无需进行任何修改。

带有代码的扩展,即定义main入口点的扩展,需要检查和可能的修改。

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

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

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

审查扩展代码是否已准备好用于虚拟资源

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节点模块的使用。如果可能,使用vscode.workspace.fs API,它会委托给适当的文件系统提供者。
  • 检查依赖于fs访问的第三方组件(例如,语言服务器或节点模块)。
  • 如果您从命令运行可执行文件和任务,请检查这些命令在虚拟工作区窗口中是否有意义,或者是否应禁用它们。

指示您的扩展是否可以处理虚拟工作区

package.json 中的 capabilities 下的 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."
    }
  }
}

描述显示在扩展视图中:

扩展视图

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

默认

"virtualWorkspaces": true 是所有尚未填写 virtualWorkspaces 功能的扩展的默认设置。

然而,在测试虚拟工作空间时,我们列出了一份我们认为应该在虚拟工作空间中禁用的扩展列表。 该列表可以在问题 #122836 中找到。这些扩展默认情况下具有 "virtualWorkspaces": false

当然,扩展作者更有能力做出这个决定。扩展的package.json中的virtualWorkspaces能力将覆盖我们的默认设置,我们最终将淘汰我们的列表。

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

禁用命令和查看贡献

命令和视图的可用性以及许多其他贡献可以通过when clauses中的上下文键来控制。

当所有工作区文件夹都位于虚拟文件系统上时,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添加文件系统提供者支持。在语言服务器协议问题 #1264中跟踪。