vscode语法高亮依赖textmate语法定义(tmlanguage.json),而非javascript实时分析;核心是正则分词+作用域匹配主题样式,需正确配置package.json的languages和grammars字段,并确保scope被主题支持。

VSCode 语法高亮靠的是 TextMate 语法定义,不是插件自己写代码染色
VSCode 默认不运行 JavaScript 来做实时词法分析,它用的是静态的 tmLanguage.json 文件——本质是 TextMate 的 JSON 化语法描述。所有内置语言(如 javascript、html)和绝大多数第三方语言插件(比如 Sass、myLanguage)都走这条路。你看到的“高亮”,其实是编辑器把文本按正则切分成 token,再查表套样式。
这意味着:写一个语言支持插件,核心工作就是写好 grammars 字段指向的 .tmLanguage.json,而不是监听 document change 去手动改颜色。
- 正则必须用双反斜杠转义,比如匹配数字要写
"\b[0-9]+\b",不是[0-9]+ -
scopeName必须全局唯一,且要跟package.json中grammars.language对齐,否则整个语法不会加载 - 作用域名(如
keyword.control.js)决定了最终渲染的颜色,它依赖当前主题是否定义了该 scope 的样式
自定义语言插件必须配对 package.json + tmLanguage.json
只放一个 .tmLanguage.json 文件进项目没用。VSCode 根本不知道该什么时候加载它。你得在插件根目录的 package.json 里显式声明:
-
contributes.languages告诉 VSCode:“我支持一种叫myLanguage的语言,文件后缀是.mylang” -
contributes.grammars告诉 VSCode:“当文档语言是myLanguage时,请加载这个myLanguage.tmLanguage.json文件做分词” - 缺任意一项,打开
.mylang文件只会显示纯文本,毫无高亮
常见错误是只改了 tmLanguage.json 却忘了在 package.json 的 grammars 数组里加对应项,或者拼错了 language 字段值(大小写敏感)。
高亮颜色不生效?先检查主题是否覆盖了你的 scope
写了正确的正则、配好了 package.json,但关键字还是灰色?大概率是当前主题压根没定义 keyword.other.mylang 这个 scope 的颜色。VSCode 的高亮是“语法作用域 → 主题样式 → 渲染结果”三级链路,断一环就白搭。
- 按
Ctrl+Shift+P输入Developer: Inspect Editor Tokens,把光标放在想调试的词上,看实际解析出的作用域名是什么 - 去
settings.json里加editor.tokenColorCustomizations.textMateRules,直接强制指定该 scope 的前景色或背景色 - 不要试图用
editor.colorCustomizations覆盖全局,它只管编辑器 UI 元素,不管代码 token
比如你想让 keyword.other.mylang 显示为红色,就得这么写:
{
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": "keyword.other.mylang",
"settings": { "foreground": "#ff0000" }
}
]
}
}
别指望 highlight-words 或 Color Highlight 替代语法高亮
highlight-words 是手动触发的临时标记,用于追踪变量、调试路径;Color Highlight 只识别颜色字面量(#fff、rgb())。它们都不参与语言解析流程,也不影响 keyword、string 这类语法 token 的着色逻辑。
如果你发现 console.log 没高亮、function 关键字是白色、JSX 标签没颜色——这不是插件装少了,而是语言扩展本身没装,或 tmLanguage.json 规则太弱、没覆盖到这些结构。这时候该去看 JavaScript Language Features 插件是否启用,或换用更完整的 Better JavaScript 扩展,而不是折腾高亮工具。
真正难的从来不是“怎么让某个词变红”,而是“怎么让编辑器准确识别出这个词确实是 keyword 而不是 plain text”。后者需要理解语法结构、设计合理的作用域嵌套、处理嵌套引号/注释等边界情况——这些没法靠快捷键一键解决。











