Source Code Overview
This document describes the responsibilities and role of each module in the clice source tree, providing readers with a high-level understanding of the overall project structure. For detailed design information on each module, refer to the corresponding topic documents.
Project Vision
clice is a brand-new C++ language server, redesigned from the architecture level to solve long-standing problems in previous C++ language servers. Key features:
Compilation Context: clice is the first language server to introduce compilation context as a formal concept. Every step of compilation, indexing, and querying explicitly distinguishes the current compilation context, and users can query and switch between them. See Compilation Context.
Multi-process Architecture: A master + worker process model isolates Clang's memory leaks and crashes while enabling priority-aware scheduling and real-time memory monitoring. See Multi-process Architecture.
Coroutine-based Async Model: Built on C++20 coroutines and the kotatsu library, replacing traditional callback-style async and making business logic clearer.
Unified Compile Scheduling: Every expensive build product — preamble PCHs, C++20 module PCMs, document ASTs, one-shot batch runs — is a node in a single compile task graph with shared builds, real-time cooperative cancellation, and dependency-aware invalidation. See Compile Task Graph.
Module Overview
src/support/ — Foundation Utility Library
General-purpose utilities and infrastructure shared by all other modules.
CacheStore: The on-disk artifact store for file-shaped build products (PCH/PCM and friends) — atomic pair commits, namespace quotas, LRU eviction, and crash recoveryFuzzyMatcher: Token-aware fuzzy matching for code completion and symbol search- Markup / Doxygen: Parsing and formatting of documentation comments
- Logging, filesystem abstractions, string utilities, etc.
src/vfs/ — File Identity and Versions
FileTable: Internalizes file paths as stableFididentifiers used throughout the system, and owns the shared per-file facts derived from them — stat stamps, content versions, scan results, directory listings. The two-layer freshness check (stat fast path, then content hash with stamp repair) lives here once and is shared by every consumer: PCH validation, index staleness, and disk polling.
src/config/ — Configuration
Config: Loading and merging ofclice.tomland LSPinitializationOptions, strict unknown-key validation, and the JSON schema the configuration docs are generated from.
src/command/ — Compilation Command Processing
Commands read from the compilation database (CDB) are raw commands generated by the build system and cannot be fed directly to the Clang frontend -- they may contain options meant only for code generation, lack system header search paths, or include parameters irrelevant to a language server. This module parses each command once into a structured form that the rest of the system consumes.
CompilationDatabase: Loadscompile_commands.jsonand parses every entry once into an interned, classified argument structure identified by a stableConfigID. On top of that it applies user configuration rules, synthesizes fallback commands for files without an entry, derives the input language, computes entry identity hashes, and renders driver or-cc1command lines on demandToolchain: Queries system compilers for implicit compilation parameters (such as system header search paths), with a two-layer cache — probe results per driver invocation shape, and synthesized flag sets per input kindSearchConfig: A four-tier model for header search paths (Quoted / Angled / System / After), matching Clang's internal search logic
See Compilation Command Resolution.
src/compile/ — Compilation Abstraction
Wraps the Clang compiler, abstracting Clang APIs into safe, unified compilation interfaces. This layer is purely a compilation abstraction with no server logic.
CompilationUnit/CompilationUnitRef: RAII wrappers around the Clang AST context.CompilationUnitRefprovides a unified read-only view for accessing source location mappings, preprocessor directives, AST nodes, and more. This is the primary input forsrc/feature/andsrc/semantic/.CompilationParams: Describes the complete configuration for a single compilation, including compilation type (Preamble / Content / Completion / Indexing, etc.), file remapping, PCH/PCM reuse, etc.- Diagnostic and clang-tidy collection during compilation.
src/syntax/ — Lightweight Syntax Processing
Syntax-level processing that does not require a full AST. Runs before compilation to quickly obtain structural information and dependency relationships for files.
Lexer: A token-level utility built on Clang's raw lexer. Does not run the preprocessor. Used for directive scanning, include path resolution, etc.DependencyGraph: A global include/module dependency graph supporting forward queries, reverse queries, host source file search, include chain lookup, etc.- Dependency scanning: Wraps Clang's
DependencyDirectivesScannerto quickly extract include and module dependencies IncludeResolver: Resolves include paths to actual files based on search path configuration- Preamble synthesis: Builds the prefix/suffix files that let a header compile under its host's preprocessor state
See Dependency Scanning.
src/semantic/ — Semantic Analysis
Semantic analysis capabilities beyond Clang's native APIs. Takes a CompilationUnitRef and extracts higher-level semantic information.
Semantics: The unified semantic map — a single AST traversal per compilation records every interesting node and its token ownership; selection, feature projections, and index production are pure queries over the map rather than separate AST walksTemplateResolver: Resolves dependent names through pseudo-instantiation, enabling semantic analysis to see through template contexts. See Template Resolver.SymbolKind/RelationKind: Fine-grained symbol kinds and relation types
src/index/ — Symbol Index
Symbol indexing system with cross-translation-unit query support. Layered as:
TUIndex: Index rows produced from a single compilation, projected from the semantic mapProjectIndex: The global layer — externally visible symbols, plus the record of which translation units contributed which filesShard: The per-file storage unit. Each compilation context that preprocesses the file differently contributes a variant, deduplicated by the content identity of its encoded rows; names local to the file live in the shard itself, only external names enter theProjectIndexBlobDatabase: Persistence backend — all index blobs live in a single LMDB database
See Symbol Index.
src/feature/ — LSP Feature Implementations
Concrete implementations of LSP features. Each feature takes a CompilationUnitRef and returns the corresponding LSP response data. This layer is purely computational -- it has no involvement with network communication, state management, or process scheduling.
Includes: code completion, hover information, signature help, semantic highlighting, inlay hints, document symbols, document links, folding ranges, formatting, diagnostics, etc.
feature/only covers single-file, AST-based feature implementations. Cross-file navigation features (go to definition, find references, etc.) are served from index data by the server'sservice/layer (Features/IndexQuery). Some features involve multi-phase processing -- for example, include path completion in code completion can be resolved at the syntax layer without full compilation.
src/sched/ — Compile Scheduling Core
The task-graph engine that decides what gets built, when, and shares the results.
TaskGraph: The shared build graph. Every expensive product is a node; concurrent requests for the same node join one build round instead of duplicating work, cancellation is cooperative, and edges drive dependency-aware invalidationPCHFamily/PCMFamily/TURunFamily: Node families for preamble PCHs (keyed by content), C++20 module PCMs (with import edges and provider tracking), and one-shot translation-unit runs shared by indexing and lintWorkspace: The disk-truth aggregate — compilation database, dependency graph, artifact registries, project index. Core invariant: unsaved buffer contents of open files never modify theWorkspace; it only reflects the state on diskContextResolver: Resolves the compile command and includer context a file is compiled under, owning header-context verdicts, user context choices, and synthesized preamblesIndexStore/IndexPump: Index persistence transactions (merge, save, reconcile with the CDB) and the background scheduler that feeds stale files through workers with foreground-aware budgeting- Bootstrap and batch drivers: cold-start orchestration for the server, and the headless execution mode behind
clice index/clice lint
src/worker/ — Worker Processes
WorkerPool: Manages worker process lifecycles and scheduling — spawn/monitor/respawn with crash budgets and cooldown revival, stateful placement with document affinity, and stateless dispatch with priority queues and foreground-aware capacityStatefulWorker: Holds document ASTs and serves query requests- Stateless workers execute one-shot tasks (PCH/PCM builds, completion, formatting, indexing runs)
src/server/ — Server Runtime
The language server's core runtime, responsible for assembling all the layers above into a runnable service.
protocol/ — Protocol definitions. Describes the message formats for communication between the master process and worker processes, as well as between the server and clients. Includes Worker protocol (compilation/query/build requests), LSP extension protocol (compilation context switching, etc.), and the control protocol through which clice index and clice query --fresh ask a running server to index.
state/ — Document state and the invalidation machinery.
Session/SessionStore: The open-buffer truth for each open file — content, document version, generation, and serving state — created on didOpen and destroyed on didClose. Compile products do not live hereASTProjection/ASTProjectionTable: The published products of each document's most recent compilation (feature results, PCH key, dependency snapshot) — an immutable read model replaced wholesale on each publicationInvalidator: The invalidation engine — folds file events (buffer opens/saves, on-disk changes, compilation-database reloads, worker crashes) into a deduplicated set of invalidation effectsFileTracker: Stat-polling discovery of changes that happen outside the editor (a regeneratedcompile_commands.json,git checkout), feeding events to theInvalidatorQuarantine: Per-document crash accounting — documents whose content keeps killing workers are isolated and recover through licensed probe attempts
service/ — Read-side services consuming compilation and index results.
Features: Assembles each feature's answer from its providers — the worker's AST, the PCH's cached preamble products, or the index — routing each request by readiness: an up-to-date AST answers when available, otherwise index-backed projections answer immediately. Underreadonly = on/auto, documents serve exclusively from the index until an edit escalates them to full AST service; compilation is pull-based throughout, triggered by requests rather than lifecycle eventsASTFamily: The document-AST node family in the task graph — schedules compiles for open documents and publishes their resultsDispatcher: The document side of talking to workers — every request carrying an open document's content (stateful queries, interactive completion/signature builds, formatting) is admitted through the document's quarantine, dispatched, and landed through one exit that answersContentModifiedfor a buffer the client already edited awayIndexQuery: Read-only queries over every index source — the project index, per-file shards, and the live data of open files — under one freshness arbitration, answering in domain values that the transports project onto their protocolsContextService: The protocol adapter for compilation-context queries and switching
transport/ — Protocol endpoints driving the server.
MasterServer: The composition root. Owns the workspace, sessions, worker pool, and all services above, and executes theInvalidator's effects through its single dispatch entry pointLSPClient: Request handlers for the LSP protocol- The control channel: a loopback listener the server opens while it holds the workspace's index writer lock, recorded next to the lock for the command-line tools to find
See Multi-process Architecture.
src/driver/ — Subcommands
Entry points for the clice binary: serve (the LSP server), worker, index (batch indexing), lint (batch clang-tidy), inspect, format, query, and doc.
Inter-module Relationships
The data flow roughly follows this direction:
command (structured compile commands)
↓
sched (task graph: PCH / PCM / AST / TU-run scheduling) ──→ worker (processes)
↓ products
compile (drives Clang compilation)
↓
semantic (semantic map) ──→ index (TUIndex / shards / ProjectIndex)
↓
feature (produces LSP responses)
The server layer assembles all of the above via sessions, routing,
invalidation, and transports into a runnable service.support, vfs, config, and syntax are cross-cutting layers shared by multiple modules.
