虚拟工作区
像 GitHub 存储库 扩展这样的扩展在由 文件系统提供程序 支持的一个或多个文件夹上打开 VS Code。当扩展实现文件系统提供程序时,工作区资源可能不会位于本地磁盘上,而是**虚拟**的,位于服务器或云端,编辑操作也会在那里进行。
这种配置称为**虚拟工作区**。当在 VS Code 窗口中打开虚拟工作区时,左下角的远程指示器中的标签会指示这一点,类似于其他 远程开发 窗口。
并非所有扩展都能够使用虚拟资源,可能需要资源位于磁盘上。一些扩展使用依赖于磁盘访问的工具,需要同步文件访问,或者没有必要的文件系统抽象。在这种情况下,当处于虚拟工作区时,VS Code 会向用户指示他们正在受限模式下运行,并且某些扩展被停用或以有限的功能运行。
通常,用户希望尽可能多的扩展在虚拟工作区中运行,并且在浏览和编辑远程资源时具有良好的用户体验。本指南介绍了扩展如何针对虚拟工作区进行测试,描述了允许它们在虚拟工作区中运行的修改,并介绍了 virtualWorkspaces
功能属性。
修改扩展以使用虚拟工作区也是在 VS Code for the Web 中良好运行的重要步骤。VS Code for the Web entièrement inside a browser and workspaces are virtual due to the browser sandbox. See the Web Extensions guide for more details.
我的扩展是否受影响?
当扩展没有可执行代码,而是纯粹的声明性代码(如主题、键绑定、代码片段或语法扩展)时,它可以在虚拟工作区中运行,无需任何修改。
具有代码的扩展,即定义了 main
入口点的扩展,需要检查并可能需要修改。
针对虚拟工作区运行你的扩展
安装 GitHub 存储库 扩展,并从命令面板运行**打开 GitHub 存储库...** 命令。该命令显示一个快速选择下拉菜单,你可以在其中粘贴任何 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.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 子句 中的上下文键进行控制。
当所有工作区文件夹都位于虚拟文件系统上时,virtualWorkspace
上下文键被设置。下面的示例仅在不在虚拟工作区时才在命令面板中显示命令 npm.publish
{
"menus": {
"commandPalette": [
{
"command": "npm.publish",
"when": "!virtualWorkspace"
}
]
}
}
resourceScheme
上下文键被设置为文件资源管理器中当前选定元素的 URI 方案或编辑器中打开的元素的 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。