文档选择器怎么限定语言和协议?
结论
DocumentSelector 用来声明 Provider 对哪些文档生效。至少写语言,远程或虚拟文档还要写 scheme,需要时再加 pattern。不写 scheme 时,自定义协议上的同类语言可能不触发,或者误触发。
展开
const selector: vscode.DocumentSelector = [
{ language: "typescript", scheme: "file" },
{ language: "typescript", scheme: "untitled" },
{ language: "typescript", scheme: "vscode-vfs" }
];
vscode.languages.registerCompletionItemProvider(selector, provider, ".");
三个字段:
language:语言 id,来自contributes.languages或内置语言。scheme:file、untitled、vscode-vfs,或你自己的协议。pattern:glob,例如只对**/test/**/*.ts生效。
选择器可以是语言 id 字符串,也可以是对象数组。对象数组是「或」:命中任意一条就调用 Provider。
远程开发里工作区文件经常不是你以为的单纯本地 file。把 scheme 写死成 file 且不做其他条目时,SSH 上的文档可能没有补全。更稳的做法是明确列出你支持的 scheme,而不是省略后碰运气。
pattern 用来收窄到某个目录。它替代不了权限检查,只是少做无用计算。
容易讲错的点
- 语言 id 和文件后缀不是一回事。用户可以把
.txt当成 TypeScript 打开,选择器看的是语言模式。 - 选择器不匹配时,Provider 根本不会被调用。回调里再判断语言,说明注册范围已经太大了。
- 同一个位置可以有多个插件的 Provider,它们会一起被询问。返回结果要能和别人共存,不要清空别人的诊断集合。