You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS Code语言服务器扩展输入点号后connection.onCompletion无补全问题

问题根因

你当前的实现存在两个核心问题导致点号触发时无补全:

  1. 补全逻辑无差别返回全量全局关键词、命令补全项,未针对.触发的场景做特殊处理。VS Code收到补全项后会用.后的输入内容作为过滤词匹配补全项标签,全局补全项几乎没有.开头的,全部被过滤后就显示「No Suggestions」。
  2. 没有解析.左侧的标识符对应类型,自然无法返回关联的类成员补全项。
解决方案

按以下步骤调整即可实现点号后成员补全:

  • 第一步:将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 17:24:01