본문으로 건너뛰기
cccskills
무료GitHub에 공개한국어 소개

Language server

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-language/carbon-lang스타 33,929(GitHub 33,929 + cccskills 0)

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • LSP 처리기 추가 위치 찾기
  • 언어 서버 테스트 작성
  • 테스트 기대값 갱신
  • VS Code 확장 실행 설정 확인

한국어 소개

할 수 있는 일

이 스킬은 Carbon 언어 서버와 서버를 실행하는 VS Code 확장을 다룹니다. LSP 요청을 등록하는 위치, 처리기와 문서 문맥의 역할 분담, Carbon 소스 문서와 테스트 데이터의 처리 차이를 설명합니다. 테스트에서는 file_test 입력 분할과 LSP 호출 키워드를 사용하며, 자동 갱신 스크립트로 기대 출력을 업데이트하는 방법을 안내합니다. SemIR 텍스트에서 이름을 찾는 방법, UTF-16 위치 오프셋, 테스트 통신 형식에서 주의할 점도 다룹니다.

이럴 때 유용합니다

Carbon 언어 서버에 기능을 추가하거나 기존 요청 처리 흐름을 확인할 때 활용할 수 있습니다. 테스트를 작성하거나 갱신하고, VS Code 확장이 서버를 시작하는 설정을 확인할 때도 유용합니다.

사용 예시

  • “이 LSP 요청의 처리기는 어디에 추가해야 하나요?”
  • “hover와 정의 이동을 확인하는 file_test를 작성해 주세요.”
  • “VS Code 확장이 서버를 실행하는 설정을 설명해 주세요.”

주의 사항

테스트 실행에는 bazelisk와 file_test를 사용합니다. VS Code 확장은 carbonPath 설정에 지정된 실행 파일을 stdio로 시작합니다.

이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.

문서 점검

AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.

안전성전송·삭제·명령 실행 등을 명시하고 있는가
A양호자료는 테스트와 VS Code 설정을 다루며 삭제, 외부 전송, 인증 정보 접근은 언급하지 않습니다.
도입의 용이성필요한 도구나 API 키가 적고 적혀 있는가
B일부 부족bazelisk, file_test, carbonPath가 설정된 VS Code 확장을 전제로 하지만 설치 절차는 없습니다.

점수에는 넣지 않았습니다. 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 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Accessing GitHub issues

무료요약 있음

명령줄의 `gh`로 GitHub 이슈 본문과 댓글을 읽기 전용으로 확인하는 방법을 안내합니다. 번호나 URL로 이슈를 찾고 다른 저장소를 지정하는 방법, 댓글이 많은 경우 JSON과 `jq`로 내용을 추출하는 방법을 다룹니다.

  • 이슈 본문과 댓글 읽기
  • URL로 이슈 내용 확인
  • 다른 저장소의 이슈 조회
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Agent tools

무료요약 있음

Carbon 저장소에서 일하는 AI 도우미가 전용 환경 도구로 파일을 읽고 검색하고 편집하는 규칙을 안내합니다. 임시 파일을 둘 위치와 삭제 시점, 사용자 지정 프로그램을 허용하는 경우도 설명합니다.

  • 정해진 도구로 Carbon 파일 검색
  • 파일 변경에 맞는 전용 도구 선택
  • 임시 파일 위치와 삭제 규칙 확인
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Bazel usage

무료요약 있음

Carbon 프로젝트에서 Bazelisk로 빌드, 테스트, 실행하는 기본 절차를 안내합니다. 대상을 지정한 검증, ASan 활성화, 시스템 의존성 변경 후 캐시 재생성도 다룹니다.

  • Carbon 코드 빌드
  • 변경 사항과 관련된 테스트 실행
  • Bazel로 빌드한 프로그램 실행
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Builtin functions

무료요약 있음

Carbon 컴파일러에 내장 함수를 추가하는 절차를 안내합니다. 함수 등록과 시그니처 검증부터 상수 평가, 런타임 호출의 LLVM IR 생성, Prelude 연결, 최소 Prelude를 이용한 개별 테스트까지 다룹니다.

  • 내장 함수 등록
  • 상수 평가 구현
  • LLVM IR 생성 추가
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Code style

무료요약 있음

Carbon 툴체인의 Bazel, C++, Carbon, Markdown, Python 파일 서식 기준을 안내합니다. 주석, 문서, 이름, 설계 원칙과 변경 내용을 설명하는 커밋 메시지 작성법도 다룹니다.

  • Carbon 코드와 관련 파일 서식 정리
  • 주석과 문서 검토
  • 이름이 실제 의미에 맞는지 확인
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Diagnostics

무료요약 있음

Carbon 도구 체인에서 오류와 경고 진단을 추가하거나 수정하는 방법을 안내합니다. 진단 종류 등록, 형식이 지정된 인수로 메시지 구성, 소스 위치에 라벨과 문맥 연결, 문구 규칙 및 테스트 범위 확인을 다룹니다.

  • 진단 메시지 추가
  • 소스 위치에 라벨 지정
  • 진단 문구 통일
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

carbon-language의 스킬 모두 보기

이 스킬의 문제 신고