毕昇C语言 语言服务器Trait Highlight
Contents
设计原则
静态高亮(TextMate Grammar)和语义高亮(Semantic Highlighting / Clangd)两个维度
静态高亮
VScode使用TextMate语法规则显示高亮。在插件的package.json 中可以设置grammars,指定高亮语法规则。
"grammars": [{
"language": "bsc",
"scopeName": "source.bsc",
"path": "./syntaxes/bsc.tmLanguage.json"
}],
"configurationDefaults": {
"[bsc]": {
"editor.semanticHighlighting.enabled": false
}
},
"semanticTokenColors": {
"interface": "#4EC9B0",
"type": "#4EC9B0",
"class": "#4EC9B0",
"typeParameter": "#1AAFB0"
}
bsc.tmLanguage.json文件
{
"scopeName": "source.bsc",
"name": "bsc",
"patterns": [
{ "include": "#trait-def" },
{ "include": "#keywords" },
{ "include": "source.c" }
],
"repository": {
"keywords": {
"patterns": [
{
"name": "keyword.control.trait.bsc",
"match": "\\b(trait|impl)\\b"
},
{
"name": "variable.language.this.bsc",
"match": "\\bThis\\b"
}
]
},
"trait-def": {
"match": "\\b(trait)\\s+([a-zA-Z_]\\w*)",
"captures": {
"1": { "name": "keyword.control.trait.bsc" },
"2": { "name": "entity.name.type.interface.bsc" }
}
}
}
}
高亮不显示
配置好高亮语法,但是调试插件时没有显示应有的高亮。尝试各种办法,定位问题是:vscode已经识别每个token的scope,但是vscode主题不能解析这个scope
临时解决方案是在用户项目目录的settings.json中设置自定义语法。
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": "entity.name.type.interface.bsc",
"settings": {
"foreground": "#4EC9B0",
"fontStyle": "bold"
}
},
{
"scope": "keyword.control.trait.bsc",
"settings": {
"foreground": "#C586C0"
}
},
{
"scope": "keyword.control.impl.bsc",
"settings": {
"foreground": "#C586C0"
}
},
{
"scope": "variable.language.this.bsc",
"settings": {
"foreground": "#569CD6"
}
}
]
},
使用moden主题
为了解决不显示高亮的问题,需要使用moden主题,支持标准scope。不需要在项目目录设置tokenColorCustomizations. 效果如下

语义高亮
在插件的package.json中 开启下面的选项,这样Clangd会分析AST并覆盖TextMate的高亮。
"editor.semanticHighlighting.enabled": true
trait定义语法是
trait TraitName {
// 定义 trait 中的方法签名
};
需要修改clangd后端,以识别trait相关AST节点。比如将TraitName识别为某个interface。高亮显示链条:
Lexer识别关键字 -> Parser构建TraitDecl节点 -> TargetFinder(FindTarget.cpp)识别该节点 -> getSemanticHighlightings调用kindForDecl获取Interface颜色。
前两步已经实现了,需要修改FindTarget.cpp的Add函数。这个函数用于分析和处理 AST 节点中的声明(Decl),识别它们指向的目标实体。
// 文件 clang-tool-extra/clangd/FindTarget.cpp - Add函数
void add(const Decl *Dcl, RelSet Flags) {
...
// 判断不同声明
if (const TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) {
add(TND->getUnderlyingType(), Flags | Rel::Underlying);
Flags |= Rel::Alias; // continue with the alias.
}
...
// 添加毕昇C的 TraitDecl节点判断
#if ENABLE_BSC
else if (const auto *TD = dyn_cast<TraitDecl>(D)) {
if (const auto *Def = TD->getDefinition()) {
D = Def;
// dlog("Adding Trait: {0}", D->getNameAsString());
}
}
#endif