OpenCode LSP 自动诊断修复循环 移植指南

OpenCode 核心能力:LSP 实时诊断 → AI 自动读取 → 诊断→分析→修复 自主循环
目标工具:ZCode / CodeBuddy / AtomCode / KimiCode / Qoder


一、OpenCode 的 LSP 联动机制拆解

OpenCode 的"诊断→分析→修复"自动循环由三层组成:

┌─────────────────────────────────────────────────────────┐
│  Layer 1: LSP 客户端层                                   │
│  - 打开文件时自动匹配并启动对应 LSP 服务器               │
│  - 监听 textDocument/publishDiagnostics 推送             │
│  - 将诊断信息(错误码、行列号、severity)结构化存储      │
├─────────────────────────────────────────────────────────┤
│  Layer 2: AI 上下文注入层                                │
│  - 每次对话前,自动将当前文件的 LSP 诊断注入系统 Prompt   │
│  - 格式:文件路径 + 诊断列表(含 severity/消息/位置)    │
│  - AI 无需用户手动贴日志,直接基于结构化诊断推理          │
├─────────────────────────────────────────────────────────┤
│  Layer 3: 自主修复循环层                                 │
│  - AI 生成修复代码 → 写入文件 → 触发 LSP 重新诊断         │
│  - 若诊断未清零,自动进入下一轮修复                      │
│  - 直到 diagnostics 为空或达到最大迭代次数               │
└─────────────────────────────────────────────────────────┘

关键协议:LSP 的 textDocument/publishDiagnostics 通知是推送式的,客户端无需轮询,服务器在文件变更后主动推送诊断 cite🛠web_search:15#18:~:text=诊断信息是推送式的,语言服务器在文件打开或更改时发送诊断。


二、各工具移植可行性评估

工具 LSP 原生支持 自动诊断→修复 移植难度 推荐方案
CodeBuddy ✅ 完整(官方插件+4.11.0 LSP 语义工具) ✅ 已支持(“同一轮中注意到并修复”) ⭐ 极低 直接配置使用
ZCode ⚠️ 插件体系含 LSP,但第三方评测称"暂不支持" ❓ 未明确 ⭐⭐ 低 写 LSP 插件或等官方更新
AtomCode ⚠️ 配置中有 [lsp] 段,默认关闭 ❌ 无自动循环 ⭐⭐⭐ 中等 启用 LSP + 自定义 Hook
KimiCode ❌ 无 LSP 客户端 ❌ 无自动循环 ⭐⭐⭐⭐ 高 lsp-mcp-server 桥接
Qoder ❌ 依赖外部 IDE 的 LSP ❌ 无自动循环 ⭐⭐⭐⭐ 高 lsp-mcp-server 桥接

三、逐工具移植方案

1. CodeBuddy — 最接近 OpenCode,几乎零移植成本

CodeBuddy 官方已完整实现 LSP 联动自动诊断修复 cite🛠web_search:14#6:~:text=自动诊断:每次编辑后,语言服务器会自动分析更改并报告错误和警告。CodeBuddy Code 可以看到类型错误、缺失的导入和语法问题,无需运行编译器或 linter。如果引入错误,会在同一轮中注意到并修复。无需任何配置即可工作,且 4.11.0 版本新增了 LSP 语义工具 cite🛠web_search:14#14:~:text=新增 LSP 语义工具,提升 Agent 代码理解与导航能力。

配置方式

# 1. 安装对应语言的 LSP 插件(以 C++ 为例)
codebuddy plugin install codebuddy-lsp-cpp

# 2. 确保语言服务器在 PATH 中
which clangd  # 或 pylsp, gopls, rust-analyzer 等

# 3. 打开项目,自动诊断即生效
# CodeBuddy 会自动读取 diagnostics 并尝试修复

AscendC 场景适配

CodeBuddy 的 LSP 插件体系支持自定义语言服务器 cite🛠web_search:14#6:~:text=你也可以为其他语言 创建自己的 LSP 插件。但 AscendC 没有现成的 LSP 服务器,需要:

  1. clangd 做基础 C++ 语法检查(.cpp 文件)
  2. 通过 Hooks 在保存后自动执行 bash build.sh 捕获编译日志 cite🛠web_search:14#9:~:text=Hooks(钩子)…自动响应 CodeBuddy 事件
  3. 将编译日志通过 MCP 或 Hook 回传给 AI
// CodeBuddy 插件 hooks/hooks.json 示例
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash build.sh 2>&1 | tee /tmp/build.log"
          }
        ]
      }
    ]
  }
}

2. ZCode — 插件化 LSP,需确认版本

ZCode 官方文档显示插件体系包含 LSP 组件 cite🛠web_search:14#13:~:text=LSP|语言服务,为对应语言提供补全、诊断等能力,但第三方评测(Version 0.15.1)提到"暂不支持LSP" cite🛠web_search:14#15:~:text=暂不支持LSP(语言服务器协议),代码智能提示功能相对有限。

可能原因:LSP 支持在较新版本(>0.15.1)中加入,或处于 Beta 阶段。

移植方案 A(官方已支持 LSP)

# 1. 创建 LSP 插件目录
mkdir -p ~/.zcode/plugins/ascendc-lsp

# 2. 编写 plugin.json
cat > ~/.zcode/plugins/ascendc-lsp/plugin.json << 'EOF'
{
  "name": "ascendc-lsp",
  "version": "1.0.0",
  "components": {
    "lsp": {
      "command": "clangd",
      "args": ["--background-index", "--clang-tidy"],
      "fileTypes": [".cpp", "h"]
    }
  }
}
EOF

# 3. 在 ZCode 中启用插件
# 插件管理页面 → 启用 ascendc-lsp

移植方案 B(官方暂不支持 LSP)

使用 MCP 桥接 方案(见第 5 节通用方案),或等待 ZCode 官方更新。


3. AtomCode — 启用内置 LSP + 自定义 Hook

AtomCode 配置文件中有 [lsp] 段,但默认关闭 cite🛠web_search:14#10:~:text=[lsp] enabled = false auto_detect = false。

移植步骤

# ~/.atomcode/config.toml
[lsp]
enabled = true          # 启用 LSP
auto_detect = true      # 自动检测语言服务器

# 手动指定 AscendC 相关语言的 LSP 服务器
[lsp.servers.cpp]
command = "clangd"
args = ["--background-index", "--clang-tidy", "--header-insertion=iwyu"]

[lsp.servers.python]
command = "pylsp"
args = []

自动修复循环

AtomCode 目前没有内置的"诊断→修复"自动循环,需要通过 SubagentHook 模拟:

# ~/.atomcode/config.toml
[subagent]
enabled = true
initial_turns = 4
max_turns = 12

# 自定义 Hook:保存文件后自动读取 LSP 诊断
[hooks.on_save]
action = "read_diagnostics"
target = "lsp"

⚠️ AtomCode 的 Hook 语法需参考官方文档,以上为概念示例。


4. KimiCode — 无 LSP,必须用 MCP 桥接

KimiCode 没有 LSP 客户端,但支持 shell 模式! 前缀执行命令,输出自动写入上下文)和高达 1M token 的长上下文 cite🛠web_search:4#0:~:text=shell 模式…命令输出会写入上下文。

移植方案:lsp-mcp-server 桥接

# 1. 安装 lsp-mcp-server(通用 LSP-MCP 桥接工具)
npm install -g tritlo/lsp-mcp

# 2. 配置 KimiCode 的 MCP(如果支持)
# 或在 KimiCode 对话中手动调用

# 3. 启动 LSP-MCP 桥接(以 C++ 为例)
npx tritlo/lsp-mcp cpp $(which clangd) --stdio

# 4. 在 KimiCode 中使用工具调用获取诊断
# 工具:get_diagnostics, get_code_actions, open_document 等

lsp-mcp-server 提供的工具 cite🛠web_search:15#8:~:text=get_diagnostics:获取打开文件的诊断消息(错误、警告) cite🛠web_search:15#15:~:text=支持10种语言24种代码智能功能:

工具 功能
get_diagnostics 获取当前文件诊断(错误/警告)
get_code_actions 获取自动修复建议
open_document 将文件加载到 LSP 服务器
get_completions 代码补全
get_info_on_location 悬停信息(类型/文档)

KimiCode 中的使用流程

# 在 Kimi Code 对话中
!npx tritlo/lsp-mcp cpp $(which clangd) --stdio &

# 然后让 AI 调用 MCP 工具获取诊断
# 由于 KimiCode 没有内置 MCP 工具调用框架,需要:
# 1. 手动执行命令获取诊断
!echo '{"jsonrpc":"2.0","id":1,"method":"textDocument/diagnostics","params":{"uri":"file:///path/to/kernel.cpp"}}' | npx tritlo/lsp-mcp cpp $(which clangd) --stdio

# 2. 将输出贴回对话,AI 分析并修复

局限:KimiCode 没有 OpenCode 的自动循环,每次需要手动触发 LSP 诊断并贴回结果。


5. Qoder — 依赖外部 IDE,需外部桥接

Qoder 本身没有内置 LSP 客户端,对比分析显示它"依赖IDE(LSP)" cite🛠web_search:15#9:~:text=Qoder|意图感知(行为预测)|否|依赖IDE(LSP)|基于数据飞轮的持续优化。这意味着 Qoder 的代码智能能力来自外部 IDE(如 JetBrains、VS Code)的 LSP。

移植方案:外部 IDE + lsp-mcp-server 桥接

工作流:
  VS Code / JetBrains(含 LSP) ←──→ lsp-mcp-server ←──→ Qoder
                ↑                      (MCP 协议)
                └──── 诊断信息通过 MCP 暴露给 Qoder

配置步骤

  1. 在 VS Code 中安装 lsp-mcp-server 扩展
  2. 配置 MCP 服务器连接到 Qoder
  3. Qoder 通过 MCP 工具调用获取诊断并修复
// .mcp.json(Qoder 配置)
{
  "mcpServers": {
    "lsp-bridge": {
      "type": "stdio",
      "command": "npx",
      "args": ["tritlo/lsp-mcp", "cpp", "/usr/bin/clangd", "--stdio"]
    }
  }
}

四、通用方案:lsp-mcp-server 桥接(适用于所有工具)

对于没有原生 LSP 支持的工具(KimiCode、Qoder、旧版 ZCode),lsp-mcp-server 是最通用的桥接方案 cite🛠web_search:15#15:~:text=lsp-mcp-server是一个连接Claude Code与语言服务器协议(LSP)的桥接服务器,提供语义化代码智能功能。

架构

┌─────────────┐     MCP 协议      ┌─────────────────┐     LSP 协议      ┌──────────────┐
│  AI 工具    │ ←──────────────→ │  lsp-mcp-server │ ←──────────────→ │  LSP 服务器   │
│ (任何工具)  │   (stdio/sse)    │   (桥接中间件)   │   (stdio/tcp)   │ (clangd等)   │
└─────────────┘                  └─────────────────┘                 └──────────────┘

安装与配置

# 1. 安装 lsp-mcp-server
npm install -g tritlo/lsp-mcp

# 2. 配置任意 AI 工具的 MCP
# 支持 Claude Code、Cursor、VS Code、OpenCode 等任何支持 MCP 的工具

# 3. 启动桥接(以 AscendC 的 C++ 文件为例)
npx tritlo/lsp-mcp cpp $(which clangd) --stdio

MCP 工具列表(AI 可直接调用)

工具 功能 对应 LSP 方法
start_lsp 启动 LSP 服务器
open_document 打开文件分析 textDocument/didOpen
get_diagnostics 获取诊断信息 textDocument/publishDiagnostics
get_code_actions 获取修复建议 textDocument/codeAction
get_completions 代码补全 textDocument/completion
get_info_on_location 悬停信息 textDocument/hover
restart_lsp_server 重启 LSP

自动修复循环实现

# 伪代码:任何支持 MCP 的 AI 工具都可以实现此循环
async def auto_fix_loop(file_path, max_iterations=5):
    for i in range(max_iterations):
        # 1. 打开文件
        await mcp.call("open_document", {"file": file_path})

        # 2. 获取诊断
        diagnostics = await mcp.call("get_diagnostics", {"file": file_path})

        # 3. 若无诊断,退出循环
        if not diagnostics:
            print("✅ 无错误,修复完成")
            break

        # 4. AI 基于诊断生成修复
        fix = await ai.generate_fix(diagnostics)

        # 5. 应用修复
        await mcp.call("apply_edit", fix)

        # 6. 等待 LSP 重新诊断(推送式)
        await asyncio.sleep(0.5)

    return diagnostics

五、AscendC 场景的特殊适配

AscendC 算子开发没有现成的 LSP 服务器,需要组合方案:

方案:clangd(C++ 语法)+ 编译日志(CANN 语义)

Layer 1: C++ 语法检查
  └─ clangd 分析 .cpp / .h 文件的语法、类型错误

Layer 2: CANN 编译检查(通过 Hook/MCP)
  └─ 保存后自动执行 `bash build.sh`
  └─ 解析 build.log 中的 CANN 错误码

Layer 3: AI 联合诊断
  └─ 将 clangd 诊断 + CANN 编译错误 合并为统一诊断列表
  └─ AI 基于合并诊断生成修复方案

实现方式(以 CodeBuddy 为例)

// CodeBuddy 插件配置
{
  "lsp": {
    "cpp": {
      "command": "clangd",
      "args": ["--background-index"]
    }
  },
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash build.sh 2>&1 | python3 /path/to/cann-log-parser.py"
          }
        ]
      }
    ]
  },
  "mcpServers": {
    "cann-log-parser": {
      "command": "python3",
      "args": ["/path/to/cann-log-parser.py", "--mcp-mode"]
    }
  }
}

cann-log-parser.py 功能:

  • 解析 build.log 中的 ERROR:
  • 提取错误码、文件路径、行号
  • 转换为 LSP 诊断格式({uri, range, severity, message}
  • 通过 MCP 暴露给 AI

六、各工具移植总结

工具 当前 LSP 状态 移植路径 自动修复循环实现 AscendC 适配难度
CodeBuddy ✅ 原生支持(4.11.0+) 直接配置 LSP 插件 + Hooks 内置"同一轮修复" ⭐ 低(需写编译日志 Hook)
ZCode ⚠️ 插件体系含 LSP(Beta) 写 LSP 插件或等官方 需自定义 Subagent 循环 ⭐⭐ 中
AtomCode ⚠️ 配置中有 LSP,默认关 启用 LSP + 自定义 Hook 需手动配置循环 ⭐⭐⭐ 中高
KimiCode ❌ 无 LSP lsp-mcp-server 桥接 手动触发(无自动循环) ⭐⭐⭐⭐ 高
Qoder ❌ 依赖外部 IDE 外部 IDE + lsp-mcp-server 依赖外部 IDE 的循环 ⭐⭐⭐⭐ 高

推荐优先级

  1. CodeBuddy:最接近 OpenCode 体验,优先使用
  2. ZCode:如果版本 ≥ 0.16+ 且 LSP 插件可用,次优选择
  3. 通用桥接:KimiCode / Qoder / 旧版工具统一使用 lsp-mcp-server

七、关键代码:CANN 编译日志 → LSP 诊断转换器

# cann-log-parser.py — 将 CANN build.log 转换为 LSP 诊断格式
import re
import json
import sys

def parse_cann_log(log_path):
    diagnostics = []

    # CANN 错误码正则
    error_pattern = re.compile(
        r'(?P<file>[\w/]+\.(cpp|h|json)):(?P<line>\d+):(?P<col>\d+):\s*'
        r'(?P<severity>error|warning|note):\s*(?P<message>.+)'
    )

    with open(log_path, 'r') as f:
        for line in f:
            match = error_pattern.search(line)
            if match:
                severity_map = {
                    'error': 1,      # LSP Error
                    'warning': 2,    # LSP Warning
                    'note': 3        # LSP Information
                }
                diagnostics.append({
                    'uri': f"file://{os.path.abspath(match.group('file'))}",
                    'range': {
                        'start': {'line': int(match.group('line'))-1, 'character': int(match.group('col'))-1},
                        'end': {'line': int(match.group('line'))-1, 'character': int(match.group('col'))}
                    },
                    'severity': severity_map.get(match.group('severity'), 1),
                    'message': match.group('message'),
                    'source': 'CANN'
                })

    return diagnostics

# MCP 模式:通过 stdio 接收请求,返回诊断
if __name__ == '__main__' and '--mcp-mode' in sys.argv:
    while True:
        line = sys.stdin.readline()
        if not line:
            break
        req = json.loads(line)
        if req.get('method') == 'get_diagnostics':
            log_file = req['params'].get('log_file', 'build/build.log')
            result = parse_cann_log(log_file)
            print(json.dumps({'id': req['id'], 'result': result}))
            sys.stdout.flush()

将此脚本作为 MCP 服务器注册到任意 AI 工具,即可实现 CANN 编译日志的 LSP 化诊断回灌。

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐