仓颉 cangjie-language-server 开发指南:LSP 架构解析与 build.py 构建测试实战
发布时间:2026/10/13 11:49:22 锦皓数字建站

开发工具CLI代码质量【免费下载链接】cangjie_tools仓颉编程语言命令行工具包括仓颉包管理工具、仓颉格式化工具、仓颉多语言桥接工具及仓颉语言服务。项目地址https://gitcode.com/Cangjie/cangjie_tools点击查看免费下载cangjie-language-server 是 cangjie_tools 仓库中为 DevEco Studio 提供仓颉Cangjie语言服务的语言服务器后端最终编译产物为LSPServer可执行文件。本文基于其开发者指南结合仓库源码完整讲解该项目的系统架构、目录结构、构建前置依赖、build.py构建命令与选项、测试用例的运行机制以及产物安装与清理方式帮助开发者从 0 到 1 完成语言服务的编译、测试与二次开发。一、系统架构Protocol 交互、LSP 特性、AST 管理与符号索引根据开发者指南cangjie-language-server 是一个语言服务器Language Server作为后端必须搭配 DevEco Studio 客户端使用。它通过 LSPLanguage Server Protocol协议与客户端通信整体架构由以下四个部分构成Protocol 交互管理使用 LSP 协议实现与 DevEco Studio 客户端的通信包括消息封装、消息转发和消息处理LSP 特性实现代码补全、定义跳转、语法高亮等语言服务功能AST 管理实现抽象语法树AST的构建和管理符号索引实现符号索引的生成和修改并提供搜索索引的功能。其中文档列出的 6 项核心 LSP 特性为特性功能说明CodeCompletion代码补全在开发者编写代码时根据输入的代码内容提供实时仓颉代码联想和补全能力Definition定义跳转根据开发者指定的仓颉代码符号类名、函数名、变量名等跳转到代码定义位置Hover悬浮提示鼠标悬停时显示代码的详细信息如定义类型、相关注释等SemanticHighlight语法高亮根据仓颉语言的变量类型提供服务端语法高亮对类名、函数名、变量名等显示不同颜色Diagnostic代码诊断当代码不符合仓颉语法或语义规则时在相关代码段给出错误或告警信息Rename重命名提供代码重命名功能自动修改符号的定义处和所有引用处1.1 从源码看四大模块的落地位置架构图中的四个模块在src/目录下都有清晰的对应实现Protocol 交互管理→ src/json-rpc。该目录定义了 LSP 协议数据结构Protocol.h 中实现了TextDocumentPositionParams、TypeHierarchyItem、CallHierarchyItem等请求/响应结构及其 JSON 序列化函数以及标准输入输出传输层 StdioTransport.h。在 main.cpp 中可以看到服务启动时通过TransportRegistrar注册名为stdio的传输层并设置stdin/stdout作为消息通道——这正是 LSP 标准的 stdio 传输方式注释// LSP Starting over stdin/stdout也印证了这一点。LSP 特性→ src/languageserver/capabilities。该目录下按特性拆分了 20 个子模块除文档列出的 6 项外还包括documentHighlight、documentSymbol、signatureHelp、workspaceSymbol、typeHierarchy、callHierarchy、codeLens、breakpoints、overrideMethods、refactor、fileRefactor、prepareRename、shutdown等。请求分发入口是 ArkLanguageServer.h其中声明了OnCompletion、OnGoToDefinition、OnHover、OnRename、OnSemanticTokens、OnDocumentDidOpen、OnDocumentDidChange等全部请求处理函数各特性的具体执行逻辑则封装在 ArkServer.h 聚合的CompletionImpl、LocateSymbolAtImpl、SemanticHighlightImpl、RenameImpl等实现类中。AST 管理→ ArkAST.h。ArkAST结构在构造时即调用DoLexer完成词法分析并对外提供GetCurTokenByPos按位置取 token、GetDeclByPosition按位置定位声明节点、GetOverloadDecls等接口配合DocCache缓存文档版本实现增量解析与复用。符号索引→ src/languageserver/index。该目录包含MemIndex内存索引、IndexStorage索引存储、IndexDatabase/BackgroundIndexDBSQLite 持久化索引库、SymbolCollector符号收集器等。从源码结构看索引的内存与磁盘表示遵循 generate/index.fbs 定义的 FlatBuffers schema其中Symbol表包含id、name、scope、location、kind、signature、comments等字段Ref、Sym2Ref表记录引用关系——即文档所述“符号索引的生成和修改”的持久化格式。构建脚本会自动用flatc工具把index.fbs编译为 C 头文件见下文 build.py 分析而索引库的运行时持久化则依赖第三方 SQLite见 src/CMakeLists.txt 中 amalgamation 静态库的编译定义。1.2 启动流程与运行时行为结合 main.cpp 的启动逻辑可以还原LSPServer的实际运行过程解析环境变量StringifyEnvironmentPointer从envp中提取CANGJIE_PATH、CANGJIE_HOME以及动态库搜索路径Linux 为LD_LIBRARY_PATH、Windows 为PATH、macOS 为DYLD_FALLBACK_LIBRARY_PATH并统一转换为绝对路径解析命令行选项支持--log-path日志路径、--enable-log是否开启日志、-V注册崩溃报告处理器CrashReporter::RegisterHandlers、--disable-incremental-optimization关闭增量优化、--cache-path指定索引缓存路径启用 SQLite 索引库等选项初始化索引库当启用索引库时在cache-path/.cache/index/下创建index.db并通过valid.txt中记录的编译器版本号CANGJIE_VERSION做缓存失效判断——版本不匹配时自动删除旧库重建注册 stdio 传输层并进入事件循环ArkLanguageServer::Run()阻塞处理 LSP 消息直到收到 shutdown/exit 通知若退出模式异常未先发送 shutdown 请求会向 stderr 输出告警。二、目录结构开发者指南给出的目录结构如下cangjie-language-server/ |-- build # 语言服务源码构建脚本存放文件夹 |-- doc # 语言服务开发指南和用户指南存放文件夹 |-- figures # 语言服务文档图片存放文件夹 |-- generate # 语言服务自定义索引结构文件存放文件夹 |-- index.fbs # 语言服务自定义索引结构文件 |-- src # 语言服务源码文件夹 |-- json-rpc # 语言服务解析处理 LSP 协议的文件夹 |-- languageserver # 语言服务实现整体功能的文件夹 |-- capabilities # 语言服务实现 LSP 特性的文件夹 |-- common # 语言服务实现基础功能的文件夹 |-- index # 语言服务实现索引功能的文件夹 |-- logger # 语言服务实现日志功能的文件夹 |-- launcher # 语言服务启动和初始化的文件夹实际仓库中还包含指南未展开的两个目录补充说明如下build/当前包含构建入口脚本 build.py负责第三方依赖拉取、CMake 配置、编译、测试、安装与清理下文详述test/测试工程目录。test/CMakeLists.txt 汇总了 20 余个特性测试目标completion、goToDefinition、references、semanticHighlight、hover、diagnostic、rename、typeHierarchy、callHierarchy、codeLens、codeAction、crossLanguageDefinition 等并链接进统一的gtest_LSPServer_test可执行文件test/message/下按特性存放.test请求消息与.base期望结果成对文件test/testChr/存放各特性对应的仓颉源码样例testCase.list维护用例清单。顶层 CMakeLists.txt 声明了工程的基本约束CMake ≥ 3.14.1、C17、默认 Debug 构建类型并统一输出到output/bin可执行文件与output/lib库ENABLE_TEST开启时才引入test/子目录并enable_testing()。三、构建准备依赖与前置条件3.1 为什么依赖仓颉 SDKcjc 构建产物语言服务的核心编译/分析能力由仓颉编译器内核提供因此构建依赖cjc。构建前需先完成仓颉 SDK或 cjc 前置构建产物的构建更多软件依赖参见仓颉 SDK 的环境准备说明。这一点在 build.py 的prepare_cangjie函数中得到直接印证脚本会读取CANGJIE_HOME环境变量把 SDK 下的include/头文件与tools/lib或tools/binWindows 下libcangjie-lsp.dll位于tools/bin中的libcangjie-lsp.so|dll|dylib拷贝到工程内src/lib/cangjie/目录——这正是 src/CMakeLists.txt 中lib/cangjie/include与lib/cangjie/lib/cjnative两个路径的由来最终LSPServer链接的libcangjie-lsp.so或.dylib/.dll就来自这里。3.2 获取源码与配置环境变量通过git clone命令获取语言服务源码cangjie-language-server 位于 cangjie_tools 仓库内cd ${WORKDIR} git clone https://gitcode.com/Cangjie/cangjie_tools.git完成前置构建准备后配置环境变量export CANGJIE_HOME/path/to/cangjie # (for Linux/macOS) set CANGJIE_HOME/path/to/cangjie # (for Windows) # /path/to/cangjie 路径为仓颉 SDK或前置依赖 cjc 构建产物路径根据实际情况作调整。 # Linux 交叉编译 Windows 场景需要准备 Windows 的 SDK。注意 build.py 中build的第一道检查即CANGJIE_HOME未设置时直接打印build failed, CANGJIE_HOME environment variable not found并退出因此该变量是构建的硬性前提。3.3 build.py 自动准备的第三方依赖prepare_build还会在third_party/下自动完成以下工作见 build.py无需手动准备nlohmann/jsonjson-v3.11.3LSP JSON 消息处理克隆third_party_json仓库的OpenHarmony-v6.0-Release分支flatbuffers克隆并固定到指定 commit随后执行generate_flat_header——用 CMake 构建flatc编译器再对 generate/index.fbs 执行flatc --cpp生成符号索引用的index_generated.h头文件SQLite amalgamation从third_party_sqlite仓库取源码把shell.c/sqlite3.c等聚合为 amalgamation 文件供 CMake 直接编译为静态库。四、构建步骤与命令解析4.1 基础构建进入cangjie-language-server/build目录通过build.py编译项目python3 build.py build -t release # (for Linux/MacOS) python3 build.py build -t release --target windows-x86_64 # (for Linux-to-Windows 交叉编译)构建完成后将在output/bin下生成LSPServer二进制。从 build.py 的实现看build子命令实际执行两步CMake 配置generate_cmake_commands在build-lsp目录执行cmake 工程根目录 -G generator -DCOMPILER_TYPENinja|MINGW -DCMAKE_BUILD_TYPERelease|Debug|RelWithDebInfo 生成器按平台选择Windows 为MinGW Makefiles其余为Unix Makefiles--target windows-x86_64时追加-DCROSS_WINDOWSON -DCMAKE_SYSTEM_NAMEWindows -DCMAKE_C_COMPILERx86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILERx86_64-w64-mingw32-g即通过 MinGW 工具链实现 Linux → Windows 交叉编译编译cmake --build build-lsp [-j N]。最终可执行目标定义在 src/CMakeLists.txtadd_executable(LSPServer launcher/main.cpp)链接JsonRPC、LSPlanguageserver 目标、libflatbuffers.a、sqlite3等库各平台分别导入链接仓颉 SDK 提供的libcangjie-lsp.so/libcangjie-lsp.dylib/libcangjie-lsp.dll。Linux Release 构建还会追加-pie、-z,relro -z,now -z,noexecstack等安全链接选项并执行 strip。4.2 构建选项详解build.py的build子命令提供如下额外选项与build.py中argparse定义一致--target TARGET指定编译目标产物的运行平台可选值native/windows-x86_64默认native本地平台。当前仅支持linux平台上通过--target windows-x86_64交叉编译 Windows 产物-t, --build-type BUILD_TYPE指定构建产物版本可选值debug/release/relwithdebinfo映射到 CMake 的Debug/Release/RelWithDebInfo-j, --job JOB指定编译时的并发度透传给cmake --build -j--test编译运行测试用例的产物-h, --help打印build功能的帮助信息。其中--test在 CMake 配置阶段追加-DENABLE_TESTON -DENABLE_COVERAGEON -DNO_EXCEPTIONSON -DCMAKE_CXX_FLAGS-fno-exceptions见 build.py。ENABLE_TEST同时控制两处行为顶层 CMakeLists.txt 中enable_testing()并引入test/子目录src/CMakeLists.txt 中为LSPServer追加-fno-exceptions编译选项保证测试模式与正常模式的代码行为可对齐验证。五、运行测试用例5.1 编译测试产物使用build.py编译用于测试的项目python3 build.py build -t release --test构建完成后将在output/bin下同时生成LSPServer与gtest_LSPServer_test两个二进制。测试可执行文件在 test/CMakeLists.txt 中定义入口为test/main.cpp链接libLSPServerlib.a由launcher/main.cpp编译的静态库、GTest::gtest以及各特性测试静态库CompletionTest、GoToDefinitionTest、DiagnosticTest、CodeActionTest等 20 余个和libflatbuffers.a、sqlite3最终通过add_test注册到 CTest。5.2 执行测试python3 build.py testtest子命令的运行机制见 build.py先执行source CANGJIE_HOME/envsetup.sh gtest_LSPServer_test --gtest_list_testsWindows 为envsetup.bat获取测试套清单并按名称是否包含/参数化路径区分并行测试套与串行测试套并行套在ThreadPoolExecutor中并发执行--gtest_filtersuite*每个套输出result_suite.json报告汇总结果若有失败套打印Total suites / Passed / Failed统计及具体失败的用例含GetParam()参数值并以非零码退出全部通过则输出All test suites passed。5.3 测试框架的组织方式从 CompletionTest.cpp 等用例代码可以观察到统一的参数化模式每个特性对应一个 gtestTestWithParamTestParam参数化测试类用例清单来自testCase.listGetTestCaseList(feature)单条用例执行流程读取test/message/feature/Case.test中的 LSP 请求 JSON → 结合testChr/下的仓颉源码工程构造请求 → 启动LSPServer子进程StartLspServer→ 将返回结果与Case.base期望文件比对CheckResult/ShowDiff。这种“请求消息 期望结果”成对文件的组织方式completion 特性多达 352 对使回归测试可直接覆盖补全、跳转、诊断、重命名等全部核心 LSP 特性。六、build.py 的其他功能除build外build.py顶层还提供以下子命令与指南一致并对照 build.py 的参数定义确认install [--prefix PREFIX]将构建产物安装到指定路径即把output/bin整目录拷贝到目标文件夹不指定--prefix时仅提示产物位于cangjie-language-server/output/bin。执行install前需要先成功执行build且目标路径必须是已存在的文件夹clean清除默认路径的构建产物包括output/、build-lsp/、third_party/json、flatbuffers、sqlite3以及src/lib/中从 SDK 拷贝来的仓颉头文件与库test运行测试用例见上一节-h, --help打印build.py的帮助信息。七、仓颉 SDK 集成构建与产物定位对于仓颉 SDK 集成构建即将语言服务产物纳入 SDK 一体化构建流程请参考仓颉 SDK 的集成构建指导文档按当前 SDK 版本要求执行。从用户侧视角补充产物的部署位置LSPServer需要放置在仓颉 SDK 的tools/bin目录下与libcangjie-lsp等运行时库配套并由 DevEco Studio 客户端拉起。user_guide.md 还列出了LSPServer的启动参数可供联调时参考--test 以测试模式启动 LSPServer --disableAutoImport 禁用代码补全的自动包导入功能 --enable-logvalue 默认不产生日志传 true 开启日志生成 --log-pathvalue 设置日志生成路径 -V 开启崩溃日志生成功能这些参数与 main.cpp 中ConfigByOptions的解析逻辑一一对应log-path、enable-log、-V注册崩溃处理器等。八、小结cangjie-language-server 以“stdio 传输的 LSP 服务进程”为形态把仓颉编译器内核能力经libcangjie-lsp动态库暴露封装为 DevEco Studio 可消费的补全、跳转、诊断、重命名等特性并辅以 FlatBuffers 定义的符号索引格式与 SQLite 持久化索引库。开发侧的全部入口收敛在build/build.py设置好CANGJIE_HOME指向仓颉 SDK或 cjc 构建产物后build完成依赖准备与编译--testtest完成参数化 gtest 回归install/clean完成产物管理与清理跨平台场景目前支持 Linux 原生、macOS 原生与 Linux → WindowsMinGW交叉编译三条路径。赞分享开发工具CLI代码质量【免费下载链接】cangjie_tools仓颉编程语言命令行工具包括仓颉包管理工具、仓颉格式化工具、仓颉多语言桥接工具及仓颉语言服务。项目地址https://gitcode.com/Cangjie/cangjie_tools点击查看免费下载相关推荐27B推理大模型装进8.6GBTernary-Bonsai-2-27B-mlx-2bit三元量化本地大模型初探27B推理大模型装进8.6GBTernary Bonsai 2 27B mlx 2bit三元量化本地大模型初探 Ternary Bonsai 2 27B ml大模型模型量化本地部署模型优化推理模型人工智能2025最强仓颉开发插件intellij-cangjie全功能解析与实战指南2025最强仓颉开发插件intellij cangjie全功能解析与实战指南 你还在为仓颉开发效率低下而烦恼 作为新兴的系统级编程语言仓颉CangjieIDE代码编辑器开发工具编程语言仓颉标准库源码构建实战build.py 三步完成编译、交叉编译与构建系统底层解析仓颉标准库源码构建实战build.py 三步完成编译、交叉编译与构建系统底层解析 本篇技术指南以 stdlib/build_std_zh.md https:/编程语言语言运行时标准库垃圾回收并发编程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。