本文へ移動
cccskills
無料GitHub で公開日本語紹介

Language server

CarbonのLanguage ServerとVS Code拡張の構成、LSPリクエストの処理、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-language/carbon-langスター 33,929(GitHub 33,929 + cccskills 0)

実行スコア 未検証

インストール方法を見る

こんなときに便利

  • LSPハンドラーの追加場所を調べたいとき
  • Language Serverのテストを書きたいとき
  • テストの期待値を更新したいとき
  • VS Code拡張の起動設定を確認したいとき

日本語での紹介

できること

CarbonのLanguage Serverと、それを起動するVS Code拡張の実装を扱います。LSPリクエストをどこで登録し、ハンドラーや文書コンテキストをどう分担するか、Carbonソースとテストデータで文書の扱いがどう異なるかを確認できます。テストではfile_testの入力分割やLSP呼び出しキーワードを使い、期待値の更新には自動更新スクリプトを利用します。SemIRテキスト上の名前検索や、UTF-16の位置指定、テスト時の通信形式に関する注意点も説明しています。

こんなときに便利

CarbonのLanguage Serverに機能を加える開発者や、既存のリクエスト処理を追いたい人に向いています。テストの作成・更新や、VS Code拡張からサーバーを起動する設定を調べる場面にも役立ちます。

使い方の例

  • 「このLSPリクエストのハンドラーを追加する場所を教えて」
  • 「hoverと定義ジャンプを確認するfile_testを作って」
  • 「VS Code拡張がサーバーを起動する設定を説明して」

注意点

テスト実行にはbazeliskとfile_testを使います。VS Code拡張はcarbonPath設定で指定した実行ファイルをstdio経由で起動します。

この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。

資料チェック

SKILL.md の記述から、注意が要る操作と導入の前提を AI が確認しました。点数は実際に動かした結果(実行検証)だけで付けています。

安全面送信・削除・コマンド実行などの扱いが明示されているか
A良好テストやVS Code設定を扱い、削除・外部送信・認証情報操作の記載はない。
導入のしやすさ必要なツールや API キーが少ないか、書かれているか
B一部不足bazelisk、file_test、VS Code拡張とcarbonPath設定が前提だが導入手順はない。

点数には入れていません。 2026年10月26日 時点で AI(OpenAI Codex)が判定しました。目安なので、入れる前に原文も確認してください。

評価が違うと思ったら、見直しを依頼する

どの項目が、なぜ違うと思うかを書いてください。ログインは不要です。内容を SKILL.md と照らし合わせて評価を作り直し、この欄に反映します。

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

含まれるファイル(1)

  • SKILL.md8.3 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Language server

<!-- Part of the Carbon Language project, under the Apache License v2.0 with LLVM Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -->

Introduction

This skill covers toolchain/language_server/, which implements carbon language-server, and utils/vscode/, the VS Code extension that launches it.

Architecture

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.

Document kinds

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.

Tests

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.

Test file shape

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.

Traps

[!WARNING] A blank line inside the STDIN split breaks the JSON transport. It terminates a header block, so clangd logs a timestamped Warning: 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-SPLIT is also fine.

Other things worth knowing:

  • positionEncoding is UTF-16. A character is a UTF-16 code unit offset, not a byte offset.
  • Line and character numbers in requests are 0-based, while the locN_M suffixes in SemIR output are 1-based. Off-by-ones here are silent: the request succeeds and returns the wrong thing.
  • A split can hold a document that itself contains // 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.

The SemIR text reader

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:

  • There are exactly four scope keywords: file, generated, imports, and constants (InstNamer::GetScopeName). Everything else is @entityname.
  • A reference is %name within its own scope and scope.%name otherwise (InstNamer::GetNameFor). Names may contain . and may start with one, as in %.Self.frozen.
  • Type annotations are printed in the 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.
  • A specific @F(args) { } block uses @F's scope and defines nothing; each %name => value row references an instruction of the generic.

Validating a change to the reader

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:

  • Feed the request stream from a file, not a pipe. The server reads stdin as a file and reports error: Input/output error on a pipe.
  • Read the output as bytes. Python's text=True rewrites the \r\n framing, and Content-Length counts bytes.

VS Code extension

utils/vscode/ declares three languages in package.json:

Language idApplies to
carbon*.carbon
carbon-testdata**/testdata/**/*.carbon
semir*.semir

[!NOTE] The TextMate scope for SemIR is source.carbon-semir, but the language id is semir. 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.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Accessing GitHub issues

無料概要あり

コマンドラインからGitHub issueの本文やコメントを読み取り専用で確認し、URLや番号から対象リポジトリを指定する手順を案内します。

  • issueの本文とコメントを読みたいとき
  • URLからissueの内容を確認したいとき
  • 別リポジトリのissueを参照したいとき
carbon-language/carbon-lang3.4万2026年10月26日 更新

Agent tools

無料概要あり

AIアシスタントがCarbonのコードベースを扱う際に、専用ツールでファイルを閲覧・検索・編集し、一時ファイルを管理するためのルールを示します。

  • Carbonのファイルを規則に沿って検索したいとき
  • 専用ツールを使ったファイル編集を確認したいとき
  • 一時ファイルの置き場所と削除ルールを確認したいとき
carbon-language/carbon-lang3.4万2026年10月26日 更新

Bazel usage

無料概要あり

Bazeliskを使ったCarbonプロジェクトのビルド、テスト、実行、デバッグの基本手順を確認し、対象を絞った検証やASanの利用方法も把握できます。

  • Carbonのコードをビルドしたいとき
  • 変更箇所に関係するテストを実行したいとき
  • Bazelで作ったバイナリを起動したいとき
carbon-language/carbon-lang3.4万2026年10月26日 更新

Builtin functions

無料概要あり

Carbonコンパイラに組み込み関数を追加する際の登録、型シグネチャ検証、定数評価、LLVMコード生成、テスト方法を案内します。

  • 組み込み関数を登録したいとき
  • 定数評価の処理を実装したいとき
  • LLVM IRへの変換を追加したいとき
carbon-language/carbon-lang3.4万2026年10月26日 更新

Code style

無料概要あり

Carbonツールチェーンのコードを書く際に、言語ごとの整形方法やコメント、命名、ドキュメント、コミットメッセージの基準を確認できます。

  • Carbonコードの書式を整えたいとき
  • コメントやドキュメントを見直したいとき
  • コードの名前が意味に合うか確認したいとき
carbon-language/carbon-lang3.4万2026年10月26日 更新

Diagnostics

無料概要あり

Carbonコンパイラのエラーや警告を定義し、書式やソース位置のラベルを整え、テストで網羅性を確かめる方法を案内します。

  • 診断メッセージを追加したいとき
  • エラー位置にラベルを付けたいとき
  • 診断文の表記を統一したいとき
carbon-language/carbon-lang3.4万2026年10月26日 更新

carbon-language のスキルをすべて見る

このスキルの問題を報告する