虚拟工作区
像 GitHub Repositories 这样的扩展通过 文件系统提供程序 在一个或多个文件夹上打开 VS Code。当扩展实现文件系统提供程序时,工作区资源可能不在本地磁盘上,而是 虚拟 的,位于服务器或云上,编辑操作也在此处进行。
这种配置称为 虚拟工作区。当虚拟工作区在 VS Code 窗口中打开时,将在左下角的远程指示器中显示一个标签,这与其他 远程开发 窗口类似。

并非所有扩展都能处理虚拟资源,并且可能需要本地磁盘上的资源。一些扩展使用依赖于磁盘访问的工具,需要同步文件访问,或者缺乏必要的文件系统抽象。在这些情况下,当处于虚拟工作区时,VS Code 会向用户指示他们正在以受限模式运行,并且某些扩展已被禁用或功能受限。
总的来说,用户希望尽可能多的扩展能在虚拟工作区中工作,并在浏览和编辑远程资源时获得良好的用户体验。本指南展示了扩展如何针对虚拟工作区进行测试,描述了允许它们在虚拟工作区中工作的修改,并介绍了 virtualWorkspaces 功能属性。
修改扩展以支持虚拟工作区也是在 VS Code for the Web 中良好工作的关键一步。VS Code for the Web 完全在浏览器中运行,由于浏览器沙箱的限制,工作区是虚拟的。有关更多详细信息,请参阅 Web 扩展 指南。
我的扩展受到影响吗?
当扩展不包含可执行代码,而仅是声明性的(如主题、键绑定、片段或语法扩展)时,它可以在虚拟工作区中运行,无需修改。
包含代码的扩展,即定义了 main 入口点的扩展,需要进行检查,并可能需要修改。
针对虚拟工作区运行你的扩展
安装 GitHub Repositories 扩展,并通过命令面板运行 Open GitHub Repository... 命令。该命令会显示一个 Quick Pick 下拉菜单,你可以粘贴任何 GitHub URL,或选择搜索特定存储库或拉取请求。
这将打开一个 VS Code 窗口,用于虚拟工作区,其中所有资源都是虚拟的。
审查扩展代码是否已准备好处理虚拟资源
VS Code API 对虚拟文件系统的支持已经存在相当长一段时间了。你可以查看 文件系统提供程序 API。
为新的 URI 方案(例如 vscode-vfs)注册一个文件系统提供程序,并且该文件系统上的资源将由使用该方案的 URI 表示(vscode-vfs://github/microsoft/vscode/package.json)。
检查你的扩展如何处理从 VS Code API 返回的 URI
- 永远不要假设 URI 方案是
file。只有当 URI 方案是file时,才能使用URI.fsPath。 - 留意对
fsNode.js 模块的文件系统操作的使用。如果可能,请使用vscode.workspace.fsAPI,它会委托给适当的文件系统提供程序。 - 检查依赖于
fs访问的第三方组件(例如,语言服务器或 Node.js 模块)。 - 如果你通过命令运行可执行文件和任务,请检查这些命令在虚拟工作区窗口中是否有意义,或者它们是否应该被禁用。
指示你的扩展是否支持虚拟工作区
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 功能的所有扩展,"virtualWorkspaces": true 是默认值。
然而,在测试虚拟工作区时,我们发现了一些我们认为在虚拟工作区中应该禁用的扩展列表。该列表可以在 issue #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 添加文件系统提供程序支持。在语言服务器协议 issue #1264 中进行跟踪。