使VS Code解析并显示一种新语言的结构到VSC的轮廓区域
make VS Code parse and display the structure of a new language to the outline region of VSC
我试图通过将语言定义添加到 VSC 来使 VSC 显示包含 DSL(领域特定语言)的文档的结构。该结构应出现在 VSC "outline view" 中,其中显示已安装语言的所有文档结构(如 json、markdown、html 等)
DSL 非常简单,只需要一些大写字母的元素出现在大纲中并保持层次结构:
WORD xxx
GRAMMAR xxx
STRUCTURE xxx xxx
xxx xxx xxx xxx
MEANING xxx xxx xxx
SUB_MEANING xxx xxx xxx xxx
SUB_SUB_MEANING xxx xxx xxx
我遵循了 Whosebug 上的所有提示,这些提示都导致了 VSC and/or 语言服务器协议 (LSP) 的官方文档。然而,none 有帮助,一点也没有-.-
是的,我可以使用 CodeMap 扩展,但我不想依赖它,因为 VSC 实际上能够理解新语言。对于众所周知的语言,不需要创建专用的树视图元素或其他东西,因此必须有一种方法让 VSC 解析语言结构。
"outline view" 在 VSC 中保持为空。
我发现如果删除文件夹 "xxx-language-features"(xxx 代表语言),安装的语言支持(例如)markdown 或 json 也不会为 "Outline" 生成任何内容VSC 的扩展文件夹。所以看来我也需要语言功能扩展。
我浏览了 https://code.visualstudio.com/api/language-extensions/language-configuration-guide and https://microsoft.github.io/language-server-protocol/ 和许多其他内容,包括来自 VSC Github-Repo 的 LSP 示例,但是 NOTHING 对我有帮助那。我还尝试借助 "yo code" 创建一种新语言。没有什么。
Microsoft 提供的 LSP 示例是针对明文文件的……为明文创建语言服务器有多大用处?!我想举一个关于语言的例子。查看扩展中的编译文件无济于事,因为它们被缩小了。
关于该问题没有完整的 "how to" - 因此,我们将不胜感激!
我如何告诉 VSC 将文档结构解析为 "outline view"?
大纲视图由 Document Symbols Request 填充。面包屑导航也是如此,当然还有常规的文档符号弹出窗口(转到→转到文件中的符号...)。
层次结构是通过使用 DocumentSymbol.children
而不是返回平面列表来实现的。
我在错误的地方寻找解决方案,可能在浪费了几天之后只见树木不见森林。一位同事然后对这个问题有了初步的了解,几个小时后他想出了下面的解决方案。基本上,DocumentSymbolProvider 是一个人所需要的。
搜索此关键字会提供一些示例,例如. The official docs 然而,除了您可以创建实例的信息外,什么都不提供,而关于如何使用它的重要代码由 ...
表示。哇 - 这就是我所说的文档 -.-
仍有一些事情不清楚,但至少我们现在可以使用该基础:
class MLWDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
public provideDocumentSymbols(document: vscode.TextDocument,
token: vscode.CancellationToken): Thenable<vscode.SymbolInformation[]> {
return new Promise((resolve, reject) => {
// that's the important variable. It must be a multidimensional array, one dimension for each level you need to display.
let symbols = [];
let icon_main = vscode.SymbolKind.Class;
let icon_second = vscode.SymbolKind.Field;
let icon_third = vscode.SymbolKind.String;
// check each line of the document about your keywords
for (let i = 0; i < document.lineCount; i++) {
let line = document.lineAt(i);
if(line.text.trim().startsWith("WORD")) {
symbols.push(new vscode.DocumentSymbol("Level 1: WORD", document.lineAt(i+1).text.trim(), icon_main, line.range, line.range ));
} /* elses for the levels below */
}
resolve(symbols);
});
}
}
我想 Gamma11 的答案不知何故很接近。由于官方文档中缺少关于在哪里以及如何使用它的信息,不幸的是它不能真正帮助我们。
获得有关 VSC 编码的知识似乎非常困难,因为文档除了基本结构外没有提供太多信息。
如果有人知道有关于 classes/interfaces/functions 的完整示例或描述的网站,请发表评论。在将近 20 年的编码生涯中,我从未见过这么大的项目如此缺乏文档,其中主要部分由 ...
表示,或者根本没有关于对象的任何内容 -.-
你有几种方法可以解决这个问题,你可以:
- 创建一个 IDE-exclusive 扩展来完成所有工作(解析文件、理解所有标记的含义并提供符号列表等)
- 使用实现 Microsoft 指定的 language server protocol 的语言服务器创建语言服务器客户端扩展。在这种情况下,您的 VSCode 扩展本质上是一个“shell”扩展,用于启动语言服务器并与之通信。 return 由服务器编辑的信息如何处理已经由
vscode-languageclient
包的 LanguageClient
class. 开箱即用地实现了
选项 2. 有一个巨大的优势:它解决了 N*M 问题:所有支持语言服务器协议的编辑器都可以与您的语言服务器通信,因此可以轻松地为多个编辑器提供语言支持 (VSCode、Visual Studio、Atom、Vim、emacs 等,IntelliJ 以有限的方式使用第 3 方插件)以最小的努力。
在你的问题中,我不清楚你是打算编写一个扩展来完成所有工作,还是你打算开发一个语言服务器和一个 language-client 扩展来配合它。
答案实际上取决于您的语言(或 DSL)的复杂性。如果它的语法有些复杂,并且您已经有一个编译器,那么制作一个语言服务器就很有意义,因为大部分解析和逻辑已经在编译器中实现了。如果你的语言真的像你举的例子一样简单而且没有语法,那么它可能有点过分了。
如果你走“语言服务器”路线,那么有不同语言的库可以简化服务器的实现,它们负责 LSP 的 JSON-RPC 部分,你只需要覆盖由语言服务器协议定义的方法(例如 LSP4J for any JVM language, or vscode-languageserver 用于 NodeJS(尽管它的名称,包并不特定于 VSCode))。
在这种情况下,让 VSCode 的大纲视图填充符号的层次结构只需要您在语言服务器中实现 textDocument/documentSymbol 请求,扩展中不需要其他任何东西,它由 vscode-languageclient
包的 LanguageClient
class!
- 如果您的语言客户端支持分层文档符号:在语言服务器
initialize
方法中,您将收到带 textDocument.documentSymbol.hierarchicalDocumentSymbolSupport == true
的 InitializeParams(VSCode 支持此功能)然后您 return DocumentSymbol[]
(其中有一个 children
属性,从而为您的客户提供符号树)。
- 如果您的语言服务器客户端不支持分层文档符号(例如Visual Studio),那么您return
SymbolInformation[]
,这是一个简单的符号列表。
需要注意的一件重要事情:VSCode 在显示符号树时考虑 DocumentSymbol
的 range
属性(在大纲视图中)。您的 children 符号的 range
必须包含在它们的 parent 的 range
或 VSCode 中不会在大纲视图中显示任何符号,即使您的符号树结构和 selectionRange
s 是正确的。
range
是 definition 范围(符号的整个定义,例如对于打字稿 class,它从关键字 class
开始并结束}
) 和 selectionRange
通常只是符号的标记范围(但根据规范,它还可以包括文档注释块和可见性修饰符,这是实现者的选择)。
例如
class MyClass {
/**
* Some method documentation
*/
private function myFunction(param1) {
console.log(param1);
}
}
在这种情况下,范围将是
rangeOfClass = {
"start": { "line": 0, "character": 0 },
"end": { "line": 7, "character": 1 }
};
rangeOfMethod = {
"start": { "line": 4, "character": 2 },
"end": { "line": 6, "character": 3 }
};
选择范围只能是交易品种的名称
selectionRangeOfClass = {
"start": { "line": 0, "character": 6 },
"end": { "line": 0, "character": 13 }
};
selectionRangeOfMethod = {
"start": { "line": 4, "character": 19 },
"end": { "line": 4, "character": 29 }
};
或者它可以包括从文档、关键字和修饰符到符号的末尾
selectionRangeOfClass = {
"start": { "line": 0, "character": 0 },
"end": { "line": 0, "character": 13 }
};
selectionRangeOfMethod = {
"start": { "line": 1, "character": 2 },
"end": { "line": 4, "character": 29 }
};
我试图通过将语言定义添加到 VSC 来使 VSC 显示包含 DSL(领域特定语言)的文档的结构。该结构应出现在 VSC "outline view" 中,其中显示已安装语言的所有文档结构(如 json、markdown、html 等)
DSL 非常简单,只需要一些大写字母的元素出现在大纲中并保持层次结构:
WORD xxx
GRAMMAR xxx
STRUCTURE xxx xxx
xxx xxx xxx xxx
MEANING xxx xxx xxx
SUB_MEANING xxx xxx xxx xxx
SUB_SUB_MEANING xxx xxx xxx
我遵循了 Whosebug 上的所有提示,这些提示都导致了 VSC and/or 语言服务器协议 (LSP) 的官方文档。然而,none 有帮助,一点也没有-.- 是的,我可以使用 CodeMap 扩展,但我不想依赖它,因为 VSC 实际上能够理解新语言。对于众所周知的语言,不需要创建专用的树视图元素或其他东西,因此必须有一种方法让 VSC 解析语言结构。
"outline view" 在 VSC 中保持为空。 我发现如果删除文件夹 "xxx-language-features"(xxx 代表语言),安装的语言支持(例如)markdown 或 json 也不会为 "Outline" 生成任何内容VSC 的扩展文件夹。所以看来我也需要语言功能扩展。
我浏览了 https://code.visualstudio.com/api/language-extensions/language-configuration-guide and https://microsoft.github.io/language-server-protocol/ 和许多其他内容,包括来自 VSC Github-Repo 的 LSP 示例,但是 NOTHING 对我有帮助那。我还尝试借助 "yo code" 创建一种新语言。没有什么。 Microsoft 提供的 LSP 示例是针对明文文件的……为明文创建语言服务器有多大用处?!我想举一个关于语言的例子。查看扩展中的编译文件无济于事,因为它们被缩小了。
关于该问题没有完整的 "how to" - 因此,我们将不胜感激! 我如何告诉 VSC 将文档结构解析为 "outline view"?
大纲视图由 Document Symbols Request 填充。面包屑导航也是如此,当然还有常规的文档符号弹出窗口(转到→转到文件中的符号...)。
层次结构是通过使用 DocumentSymbol.children
而不是返回平面列表来实现的。
我在错误的地方寻找解决方案,可能在浪费了几天之后只见树木不见森林。一位同事然后对这个问题有了初步的了解,几个小时后他想出了下面的解决方案。基本上,DocumentSymbolProvider 是一个人所需要的。
搜索此关键字会提供一些示例,例如...
表示。哇 - 这就是我所说的文档 -.-
仍有一些事情不清楚,但至少我们现在可以使用该基础:
class MLWDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
public provideDocumentSymbols(document: vscode.TextDocument,
token: vscode.CancellationToken): Thenable<vscode.SymbolInformation[]> {
return new Promise((resolve, reject) => {
// that's the important variable. It must be a multidimensional array, one dimension for each level you need to display.
let symbols = [];
let icon_main = vscode.SymbolKind.Class;
let icon_second = vscode.SymbolKind.Field;
let icon_third = vscode.SymbolKind.String;
// check each line of the document about your keywords
for (let i = 0; i < document.lineCount; i++) {
let line = document.lineAt(i);
if(line.text.trim().startsWith("WORD")) {
symbols.push(new vscode.DocumentSymbol("Level 1: WORD", document.lineAt(i+1).text.trim(), icon_main, line.range, line.range ));
} /* elses for the levels below */
}
resolve(symbols);
});
}
}
我想 Gamma11 的答案不知何故很接近。由于官方文档中缺少关于在哪里以及如何使用它的信息,不幸的是它不能真正帮助我们。
获得有关 VSC 编码的知识似乎非常困难,因为文档除了基本结构外没有提供太多信息。
如果有人知道有关于 classes/interfaces/functions 的完整示例或描述的网站,请发表评论。在将近 20 年的编码生涯中,我从未见过这么大的项目如此缺乏文档,其中主要部分由 ...
表示,或者根本没有关于对象的任何内容 -.-
你有几种方法可以解决这个问题,你可以:
- 创建一个 IDE-exclusive 扩展来完成所有工作(解析文件、理解所有标记的含义并提供符号列表等)
- 使用实现 Microsoft 指定的 language server protocol 的语言服务器创建语言服务器客户端扩展。在这种情况下,您的 VSCode 扩展本质上是一个“shell”扩展,用于启动语言服务器并与之通信。 return 由服务器编辑的信息如何处理已经由
vscode-languageclient
包的LanguageClient
class. 开箱即用地实现了
选项 2. 有一个巨大的优势:它解决了 N*M 问题:所有支持语言服务器协议的编辑器都可以与您的语言服务器通信,因此可以轻松地为多个编辑器提供语言支持 (VSCode、Visual Studio、Atom、Vim、emacs 等,IntelliJ 以有限的方式使用第 3 方插件)以最小的努力。
在你的问题中,我不清楚你是打算编写一个扩展来完成所有工作,还是你打算开发一个语言服务器和一个 language-client 扩展来配合它。
答案实际上取决于您的语言(或 DSL)的复杂性。如果它的语法有些复杂,并且您已经有一个编译器,那么制作一个语言服务器就很有意义,因为大部分解析和逻辑已经在编译器中实现了。如果你的语言真的像你举的例子一样简单而且没有语法,那么它可能有点过分了。
如果你走“语言服务器”路线,那么有不同语言的库可以简化服务器的实现,它们负责 LSP 的 JSON-RPC 部分,你只需要覆盖由语言服务器协议定义的方法(例如 LSP4J for any JVM language, or vscode-languageserver 用于 NodeJS(尽管它的名称,包并不特定于 VSCode))。
在这种情况下,让 VSCode 的大纲视图填充符号的层次结构只需要您在语言服务器中实现 textDocument/documentSymbol 请求,扩展中不需要其他任何东西,它由 vscode-languageclient
包的 LanguageClient
class!
- 如果您的语言客户端支持分层文档符号:在语言服务器
initialize
方法中,您将收到带textDocument.documentSymbol.hierarchicalDocumentSymbolSupport == true
的 InitializeParams(VSCode 支持此功能)然后您 returnDocumentSymbol[]
(其中有一个children
属性,从而为您的客户提供符号树)。 - 如果您的语言服务器客户端不支持分层文档符号(例如Visual Studio),那么您return
SymbolInformation[]
,这是一个简单的符号列表。
需要注意的一件重要事情:VSCode 在显示符号树时考虑 DocumentSymbol
的 range
属性(在大纲视图中)。您的 children 符号的 range
必须包含在它们的 parent 的 range
或 VSCode 中不会在大纲视图中显示任何符号,即使您的符号树结构和 selectionRange
s 是正确的。
range
是 definition 范围(符号的整个定义,例如对于打字稿 class,它从关键字 class
开始并结束}
) 和 selectionRange
通常只是符号的标记范围(但根据规范,它还可以包括文档注释块和可见性修饰符,这是实现者的选择)。
例如
class MyClass {
/**
* Some method documentation
*/
private function myFunction(param1) {
console.log(param1);
}
}
在这种情况下,范围将是
rangeOfClass = {
"start": { "line": 0, "character": 0 },
"end": { "line": 7, "character": 1 }
};
rangeOfMethod = {
"start": { "line": 4, "character": 2 },
"end": { "line": 6, "character": 3 }
};
选择范围只能是交易品种的名称
selectionRangeOfClass = {
"start": { "line": 0, "character": 6 },
"end": { "line": 0, "character": 13 }
};
selectionRangeOfMethod = {
"start": { "line": 4, "character": 19 },
"end": { "line": 4, "character": 29 }
};
或者它可以包括从文档、关键字和修饰符到符号的末尾
selectionRangeOfClass = {
"start": { "line": 0, "character": 0 },
"end": { "line": 0, "character": 13 }
};
selectionRangeOfMethod = {
"start": { "line": 1, "character": 2 },
"end": { "line": 4, "character": 29 }
};