Contents

毕昇C语言 语言服务器Trait Highlight

设计原则

静态高亮(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. 效果如下

/trait-highlight.png

语义高亮

在插件的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