本技能介绍如何使用命令行`gh`只读查看GitHub issue正文和评论,支持通过编号或URL定位,也可指定其他仓库,并说明如何提取大量评论。
- 查看issue正文和评论
- 通过URL读取issue
- 查看其他仓库的issue
本技能介绍Carbon语言服务器及其VS Code扩展的实现,包括LSP请求注册与处理、文档类型、SemIR文本读取,以及使用file_test编写和更新测试期望值。
Instructions for working on Carbon's LSP language server, including its architecture, its file_test-based tests, and the VS Code extension.
实测评分 未实测
查看安装方法本技能介绍Carbon语言服务器及启动它的VS Code扩展。内容说明LSP请求在哪里注册、处理器与文档上下文如何分工,以及Carbon源码文档和测试数据在处理方式上的区别。测试部分讲解如何使用file_test输入分段和LSP调用关键字,并通过自动更新脚本更新期望输出。还介绍SemIR文本中的名称查找、UTF-16位置偏移,以及测试通信格式需要留意的事项。
开发Carbon语言服务器的新功能或追踪现有请求处理流程时,可以参考本技能。编写或更新测试,以及检查VS Code扩展如何启动服务器时也适用。
file_test。”运行测试需要bazelisk和file_test。VS Code扩展通过stdio启动carbonPath设置所指定的可执行文件。
本介绍由 AI(OpenAI Codex)根据公开的 SKILL.md 撰写。准确的规格请查看下方原文。
AI 根据 SKILL.md 的内容检查了需要注意的操作和使用前提。评分只依据实际运行的结果(实测对比)。
不计入评分。 由 AI(OpenAI Codex)于 2026年10月26日 评估。仅供参考,安装前请同时查看原文。
安装前可以查看交给 AI 代理的指令内容。
This skill covers toolchain/language_server/,
which implements carbon language-server, and
utils/vscode/, the VS Code extension that launches it.
The server is built on clangd's LSP transport (clang::clangd), not on a
Carbon-specific one. That means clangd's Protocol.h types (Position,
Range, Location, Hover, MarkupContent) are the interface currency.
server.cpp / incoming_messages.cpp: message dispatch. A handler must be
registered in incoming_messages.cpp before it can be called.handle_*.cpp: one file per request family, each declaring its entry point
in handle.h.handle_initialize.cpp: the advertised capabilities. Adding a capability
changes Content-Length in every test that calls initialize, so expect
a large autoupdate diff.context.h / context.cpp: Context::File per open document, plus the
compile driver. Context::File::unit() has a CARBON_CHECK on the compile
driver, so any handler that reaches for the parse tree must first rule out
documents that were never compiled.position.h, sem_ir_index.h: mapping source positions to SemIR
instructions for real Carbon files.sem_ir_text.h, handle_sem_ir_text.h: navigation within the formatted
SemIR in a test file's // CHECK:STDOUT: lines. This is a heuristic text
index, deliberately independent of the real SemIR data structures. See
the SemIR text reader.The server handles two kinds of document, distinguished by the languageId
from textDocument/didOpen, with a content sniff as a fallback:
carbon: a real Carbon file. Compiled; diagnostics published.carbon-testdata: a test file. Not compiled, because we lack logic to
split it into one file per // --- split marker.[!IMPORTANT] A handler that assumes every file was compiled will crash on a test file. When adding one, give the test-file path an explicit early return.
There is no language-server-specific test target.
toolchain/language_server/BUILD only declares
filegroup(name = "testdata"), which is pulled into
//toolchain/testing:all_testdata and run by //toolchain/testing:file_test.
# Run just the language server tests (or any subset).
bazelisk test //toolchain/testing:file_test \
--test_arg=--file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon
# See the raw output, which is much easier to read than a test failure.
bazelisk run //toolchain/testing:file_test -- --dump_output \
--file_tests=toolchain/language_server/testdata/position/hover_and_goto.carbon
# Update expectations. Never hand-write CHECK lines.
./toolchain/autoupdate_testdata.py toolchain/language_server/testdata/...
These tests run serially, because clangd's logging is a global singleton.
The request stream is a // --- STDIN split written with the [[@LSP-*]]
keywords, and the responses land in a trailing // --- AUTOUPDATE-SPLIT.
Documents come from other splits by way of "text": "FROM_FILE_SPLIT", which
is substituted with the content of the split whose name matches the uri.
// --- position.carbon
fn Abs(n: i32) -> i32 { return n; }
// --- STDIN
[[@LSP-CALL:initialize:"capabilities": {}]]
[[@LSP-NOTIFY:textDocument/didOpen:
"textDocument": {
"uri": "file:/position.carbon",
"languageId": "carbon",
"text": "FROM_FILE_SPLIT"
}
]]
[[@LSP-CALL:textDocument/hover:
"textDocument": {"uri": "file:/position.carbon"},
"position": {"line": 0, "character": 3}
]]
[[@LSP-CALL:shutdown]]
[[@LSP-NOTIFY:exit]]
// --- AUTOUPDATE-SPLIT
Full keyword documentation is in
testing/file_test/README.md.
[!WARNING] A blank line inside the
STDINsplit breaks the JSON transport. It terminates a header block, so clangd logs a timestampedWarning: Missing Content-Length header, or zero-length message.The timestamp makes the test unreproducible, so it fails on the next run. Comment lines between messages are fine; blank lines are not. A single blank line immediately before// --- AUTOUPDATE-SPLITis also fine.
Other things worth knowing:
positionEncoding is UTF-16. A character is a UTF-16 code unit
offset, not a byte offset.locN_M
suffixes in SemIR output are 1-based. Off-by-ones here are silent: the
request succeeds and returns the wrong thing.// CHECK:STDOUT:
lines, because CHECK lines only form expectations inside the
AUTOUPDATE-SPLIT. Such a document still can't contain a literal // ---
line, which would split the enclosing test file; write it as
[[@0x2f]]/ --- name.carbon.sem_ir_text.cpp indexes the formatted SemIR inside a test file's
// CHECK:STDOUT: lines so that hover and go-to-definition work on operand
names. It is a heuristic reader, not a parser, and its correctness rests on
facts about toolchain/sem_ir/formatter.cpp and
toolchain/sem_ir/inst_namer.cpp. Re-check these if the formatter changes:
file, generated, imports, and
constants (InstNamer::GetScopeName). Everything else is @entityname.%name within its own scope and scope.%name otherwise
(InstNamer::GetNameFor). Names may contain . and may start with one,
as in %.Self.frozen.constants scope.
Formatter::FormatTypeOfInst does
llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::Constants),
so in %x: %foo = ... a bare %foo means constants.%foo. This does not
apply to ordinary operands or to [concrete = ...] annotations.*_decl braces hold the declared entity's scope. The braces of
%F.decl: ... = fn_decl @F [...] { ... } { ... } are lexically inside
file { }, but their names belong to @F.!with Self: switches scope without a brace, until !members:
switches it back. Brace counting alone cannot see this.specific @F(args) { } block uses @F's scope and defines nothing; each
%name => value row references an instruction of the generic.The unit tests only cover a handful of cases. To check a change against the
real corpus, drive the server over a sample of check testdata, hovering on
every %name, and compare the resolved fraction before and after. Roughly 99%
of names resolve; the residue are names the formatter references but never
emits a definition line for, such as %I.WithSelf.F, which only ever appears
inside a [symbolic = ...] annotation.
Two things to get right in such a harness:
error: Input/output error on a pipe.text=True rewrites the \r\n
framing, and Content-Length counts bytes.utils/vscode/ declares three languages in package.json:
| Language id | Applies to |
|---|---|
carbon | *.carbon |
carbon-testdata | **/testdata/**/*.carbon |
semir | *.semir |
[!NOTE] The TextMate scope for SemIR is
source.carbon-semir, but the language id issemir. Markdown code fences in hover text resolve language ids, so a fence must say```semir.
extension.ts launches the server over stdio, using the carbonPath setting
(default ./bazel-bin/toolchain/carbon). Its documentSelector controls which
files are sent to the server at all; a new document kind has to be added there
as well as in the server.
还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
本技能介绍如何使用命令行`gh`只读查看GitHub issue正文和评论,支持通过编号或URL定位,也可指定其他仓库,并说明如何提取大量评论。
本技能为在 Carbon 代码库中工作的 AI 助手规定文件查看、搜索和编辑工具,并说明临时文件的存放与清理规则,以及何时可以编写和运行自定义程序。
了解如何在 Carbon 项目中通过 Bazelisk 构建、测试和运行程序,包括指定目标、启用 ASan,以及系统依赖变更后重建缓存。
本技能介绍如何为Carbon编译器添加内置函数,包括类型注册、签名验证、常量求值、运行时LLVM IR生成、Prelude绑定,以及使用最小Prelude编写针对性测试。
了解 Carbon 工具链对 Bazel、C++、Carbon、Markdown 和 Python 文件的格式规范,并查看注释、文档、命名、设计及提交说明的写作要求。
本技能介绍如何在Carbon工具链中添加或修改错误和警告,包括注册诊断类型、用带类型的参数构造消息、为源码位置添加标签和上下文,以及检查措辞规范和测试覆盖。