Skip to content

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 recovery
  • FuzzyMatcher: 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 stable Fid identifiers 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 of clice.toml and LSP initializationOptions, 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: Loads compile_commands.json and parses every entry once into an interned, classified argument structure identified by a stable ConfigID. 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 -cc1 command lines on demand
  • Toolchain: 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 kind
  • SearchConfig: 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. CompilationUnitRef provides a unified read-only view for accessing source location mappings, preprocessor directives, AST nodes, and more. This is the primary input for src/feature/ and src/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 DependencyDirectivesScanner to 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 walks
  • TemplateResolver: 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 map
  • ProjectIndex: The global layer — externally visible symbols, plus the record of which translation units contributed which files
  • Shard: 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 the ProjectIndex
  • BlobDatabase: 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's service/ 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 invalidation
  • PCHFamily / 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 lint
  • Workspace: The disk-truth aggregate — compilation database, dependency graph, artifact registries, project index. Core invariant: unsaved buffer contents of open files never modify the Workspace; it only reflects the state on disk
  • ContextResolver: Resolves the compile command and includer context a file is compiled under, owning header-context verdicts, user context choices, and synthesized preambles
  • IndexStore / 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 capacity
  • StatefulWorker: 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 here
  • ASTProjection / 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 publication
  • Invalidator: The invalidation engine — folds file events (buffer opens/saves, on-disk changes, compilation-database reloads, worker crashes) into a deduplicated set of invalidation effects
  • FileTracker: Stat-polling discovery of changes that happen outside the editor (a regenerated compile_commands.json, git checkout), feeding events to the Invalidator
  • Quarantine: 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. Under readonly = 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 events
  • ASTFamily: The document-AST node family in the task graph — schedules compiles for open documents and publishes their results
  • Dispatcher: 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 answers ContentModified for a buffer the client already edited away
  • IndexQuery: 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 protocols
  • ContextService: 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 the Invalidator's effects through its single dispatch entry point
  • LSPClient: 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:

text
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.