VS Code语言服务器扩展输入点号后connection.onCompletion无补全问题
问题根因
你当前的实现存在两个核心问题导致点号触发时无补全:
- 补全逻辑无差别返回全量全局关键词、命令补全项,未针对
.触发的场景做特殊处理。VS Code收到补全项后会用.后的输入内容作为过滤词匹配补全项标签,全局补全项几乎没有.开头的,全部被过滤后就显示「No Suggestions」。 - 没有解析
.左侧的标识符对应类型,自然无法返回关联的类成员补全项。
解决方案
按以下步骤调整即可实现点号后成员补全:
- 第一步:将
onCompletion回调的入参类型从TextDocumentPositionParams替换为CompletionParams,获取触发补全的字符triggerCharacter - 第二步:判断如果是
.触发的补全,解析光标前的文本,提取.左侧的标识符 - 第三步:从你维护的符号表中查询该标识符对应的类/结构类型,生成对应成员的补全项
- 第四步:按需决定是否保留全局补全项,建议点号场景优先返回成员补全,避免全局项干扰
调整后核心代码示例
connection.onCompletion( async (params: node.CompletionParams): Promise<node.CompletionItem[] | node.CompletionList | undefined> => { console.log("completion"); const doc = documents.get(params.textDocument.uri); if (!doc) return undefined; const list:node.CompletionList = node.CompletionList.create([], true); // 处理点号触发的成员补全 if (params.triggerCharacter === '.') { const text = doc.getText(); const offset = doc.offsetAt(params.position); // 匹配点号左侧的标识符,可根据你的语法规则调整正则 const leftText = text.slice(0, offset - 1); const identifierMatch = leftText.match(/[a-zA-Z_$][a-zA-Z0-9_$]*$/); if (identifierMatch) { const targetSymbol = identifierMatch[0]; // 从你的符号表查询该符号对应的类型,替换为你自己的查询逻辑 const symbolType = yourSymbolService.getTypeOfSymbol(targetSymbol, params.position, doc.uri); if (symbolType?.members) { // 生成成员补全项 const memberCompletions = symbolType.members.map(member => ({ label: member.name, kind: member.isMethod ? node.CompletionItemKind.Method : node.CompletionItemKind.Field, detail: member.typeSignature, documentation: member.description, sortText: `0_${member.name}` // 确保成员补全排在最前面 })); list.items.push(...memberCompletions); // 点号场景仅返回成员补全,不需要全局补全的话直接返回 return list; } } } // 常规场景返回全局补全项 list.items = list.items.concat(comp.GetAGKKeywordCompletionItems(), comp.GetAGKCommandCompletionItems(), agkDocs.getALLCompletionItems()); list.items.push(sense.GetCommentSnippetCompletionItem(doc, params.position)); list.items.push(sense.GetCommentSnippetCompletionItem(doc, params.position, true)); console.log("END completion"); return list; } );
注意事项
- 如果你的语法支持链式调用(如
a.b.c),需要调整左侧标识符的解析逻辑,递归解析链式表达式的最终类型 - 如果需要同时保留成员补全和全局补全,可给全局补全项设置
sortText: '1_xxx',确保成员补全优先级更高 - 如果你的补全项设置了
filterText,确保点号场景的成员补全项的filterText不需要带.前缀,LSP会自动处理过滤逻辑
内容的提问来源于stack exchange,提问作者IronManhood
相关产品推荐
相关产品推荐

