在语言服务器协议规范中,语义标记响应有一个数据字段,它是标记的整数数组。
export interface SemanticTokens {
/**
* The actual tokens.
*/
data: uinteger[];
}
在所有示例中,语义标记都是在客户端使用 SemanticTokensBuilder 完成的,SemanticTokensBuilder 为每个标记类型指定行和列范围。你如何做服务器端?当 VSCode 发送“textDocument/semanticTokens/full”方法时,语言服务器返回什么?
通过查看示例也许最容易解释。此示例改编自 https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocument_semanticTokens。
假设您的文件具有内容
\n\n foo bars\n\n bazzled\n
,即用空格呈现,它看起来像这样:
foo bars
bazzled
在以下位置有三个标记(使用 0 索引):
foo
,第 2 行,第 5 个字符bars
,第 2 行,第 10 个字符bazzled
,第 5 行,第 2 个字符这是服务器可以响应的一个可能的有效
data
:
// 1st token, 2nd token, 3rd token
[ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ]
这只是以下信息的压缩形式:
[ { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, // first token
{ deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 }, // second token
{ deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } // third token
]
也就是说,每组 5 个连续元素对应一个 token。这 5 个元素按顺序具有以下含义:
deltaLine
:此标记与上一个标记之间的行差异deltaStartChar
:此标记与前一个标记之间的起始字符差异(如果前一个标记位于同一行),或者只是此标记的起始字符(如果前一个标记位于不同行)length
:这个token的长度tokenType
:令牌类型图例的索引tokenModifiers
:令牌修饰符的位标志因此,例如,第二个标记具有
deltaLine = 0
,表示它与第一个标记在同一行,而 deltaStartChar = 5
表示它在第一个标记开始后 5 个字符开始。第一个标记之前没有标记,因此它的位置被视为绝对位置。
tokenType
是令牌类型图例的索引,它是在协议初始化握手期间建立的。令牌修饰符的图例也在初始化握手期间建立。
虽然上面的
tokenModifiers
值只是一个整数,但它会被解释为一个位向量,其中每个位指示相应的修饰符是打开还是关闭。例如,上面为第一个标记 (foo
) 分配了修饰符 0b11
,表示第 0 个和第 1 个标记修饰符都处于活动状态,所有其他修饰符不适用于该标记。
我在 Github 上找到了维护者的这个答案,很有用。
如果它被移动,链接将不再有效或以某种方式消失, 这里简要介绍一下要点:
connection.onInitialize((params: InitializeParams): InitializeResult => {
return {
capabilities: {
semanticTokensProvider: {
legend: {
// set your tokens here
tokenTypes: [],
tokenModifiers: [],
}
}
}
};
});
connection.onRequest("textDocument/semanticTokens/full", (params: SemanticTokensParams) => {
// Implement your logic to provide semantic tokens for the given document here.
// You should return the semantic tokens as a response.
const semanticTokens = computeSemanticTokens(params.textDocument.uri);
return semanticTokens;
});
function computeSemanticTokens(params: string): SemanticTokens {
return { data: [] };
}