Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion en/clice/design/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ General-purpose utilities and infrastructure shared by all other modules.

### `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 — the last observation of each file on disk, content versions, scan results, directory listings. The two-layer freshness check (stat fast path, then content hash) lives here once and is shared by every consumer: PCH validation, index staleness, and disk polling. Every look that finds other content than the last one is reported as a change, whoever looked.
- `FileTable`: Internalizes file paths as stable `Fid` identifiers used throughout the system, and owns the shared per-file facts derived from them — the last observation of each file on disk, content versions, scan results, directory listings. A file has one `Fid` however a path spells it: it is identified by the name the operating system gives it (through symlinks, and on Windows through letter case, junctions and subst drives), and shown to the user under the name the user knows it by — the open document's, else the build's. The two-layer freshness check (stat fast path, then content hash) lives here once and is shared by every consumer: PCH validation, index staleness, and disk polling. Every look that finds other content than the last one is reported as a change, whoever looked.

### `src/config/` — Configuration

Expand Down
4 changes: 3 additions & 1 deletion en/clice/design/symbol-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ clice's index system is redesigned to address these problems: it separates the g

The index system needs a way to identify the same symbol across files and translation units. clice uses `SymbolHash` (a 64-bit integer) as the unique identifier for each symbol.

`SymbolHash` is the hash of the symbol's **entity**: a description of the declaration built from the properties every redeclaration shares, so that it comes out identical in every translation unit and every process. The entity is the declaration's context chain (namespaces, enclosing classes and functions, with class template specializations carrying their arguments), its own name, and for the declarations the language allows to coexist under one name, what tells them apart: the parameter types and qualifiers of a function, the template head with its constraints, the arguments of a specialization. Types enter the hash canonically, so a typedef and the type it names hash the same. Constraint and other dependent expressions enter through a port of Clang's own canonical expression profile, the one Sema uses to decide whether two templates are the same, with every pointer-valued leaf replaced by a stable value. Declarations with internal linkage (`static` functions and variables, members of anonymous namespaces) also carry the path of the file that first declares them, as do unnamed types and, outside system headers, typedef names: a `static` helper in a header is one symbol in every unit that includes the header, and two helpers with the same name in two source files are two symbols. A macro is its name and the position of its `#define`; a named module is its full name.
`SymbolHash` is the hash of the symbol's **entity**: a description of the declaration built from the properties every redeclaration shares, so that it comes out identical in every translation unit and every process. The entity is the declaration's context chain (namespaces, enclosing classes and functions, with class template specializations carrying their arguments), its own name, and for the declarations the language allows to coexist under one name, what tells them apart: the parameter types and qualifiers of a function, the template head with its constraints, the arguments of a specialization. Types enter the hash canonically, so a typedef and the type it names hash the same. Constraint and other dependent expressions enter through a port of Clang's own canonical expression profile, the one Sema uses to decide whether two templates are the same, with every pointer-valued leaf replaced by a stable value. Declarations with internal linkage (`static` functions and variables, members of anonymous namespaces) also carry the file that first declares them, as do unnamed types and, outside system headers, typedef names: a `static` helper in a header is one symbol in every unit that includes the header, and two helpers with the same name in two source files are two symbols. A macro is its name and the position of its `#define`; a named module is its full name. A file inside the workspace enters these hashes by its path relative to the workspace root, so every symbol keeps its hash when the checkout moves.

`SymbolHash` has two key properties. First, cross-file consistency: the same symbol always has the same `SymbolHash` regardless of which file it appears in. `std::string` seen in file A and `std::string` seen in file B have the same hash, allowing all definitions and references to be associated through it — this is the foundation of cross-file navigation. Second, compactness: a 64-bit integer is better suited as a hash table key and for serialized storage than a variable-length description.

Expand Down Expand Up @@ -105,6 +105,8 @@ Which variants are **live** is controlled by variant masks derived from the cont

All index blobs — shards, manifests, the serialized `ProjectIndex` — live in a single embedded LMDB database. Blob encodings are canonical and self-describing; on load a blob is validated once and then used directly as a memory-mapped, zero-copy view. There is no deserialize-into-structs step on the read path.

Every path the database records for a file inside the workspace is relative to the workspace root, and so are the paths in the command hashes it keeps: a checkout moved or copied elsewhere — its cache directory inside it, its compilation database generated for the new place — finds its index current and reindexes nothing. Files outside the workspace keep their absolute paths.

A reader such as `clice query` opens the index by binding the global table and the search index in place from the database's read snapshot and fetches a shard the first time a query reaches it; nothing is decoded and no row is copied. The writer keeps its changes as an in-memory delta over the same view — only the rows a merge touches are copied — and folds them into the next blob it writes; it also loads every manifest and verifies every shard at startup, since it reconciles them.

### Per-TU Context
Expand Down
Binary file added public/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion zh/clice/design/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ clice 是一个全新的 C++ 语言服务器,从架构层面重新设计,旨

### `src/vfs/` — 文件标识与版本

- `FileTable`:将文件路径映射为全系统使用的稳定 `Fid` 标识,并管理据此得到的各文件共享信息——每个文件在磁盘上最近一次的观察记录、内容版本、扫描结果和目录列表。两层时效性检查(先走 stat 快速路径,再计算内容哈希)集中实现在此处,供所有使用方共享:PCH 验证、索引过期判断和磁盘轮询。无论由谁查看,只要某次查看发现的内容与上一次不同,就会报告为一次变化。
- `FileTable`:将文件路径映射为全系统使用的稳定 `Fid` 标识,并管理据此得到的各文件共享信息——每个文件在磁盘上最近一次的观察记录、内容版本、扫描结果和目录列表。同一个文件无论路径怎么写,都只有一个 `Fid`:识别文件时用的是操作系统给它的名字(穿透符号链接;在 Windows 上还会穿透大小写差异、junction 和 subst 盘符),展示给用户时则用用户熟悉的名字——已打开文档所用的名字,否则是构建所用的名字。两层时效性检查(先走 stat 快速路径,再计算内容哈希)集中实现在此处,供所有使用方共享:PCH 验证、索引过期判断和磁盘轮询。无论由谁查看,只要某次查看发现的内容与上一次不同,就会报告为一次变化。

### `src/config/` — 配置

Expand Down
4 changes: 3 additions & 1 deletion zh/clice/design/symbol-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ clice 重新设计了索引系统以解决这些问题:将全局符号目录

索引系统需要一种跨文件和翻译单元识别同一符号的方式。clice 使用 `SymbolHash`(一个 64 位整数)作为每个符号的唯一标识符。

`SymbolHash` 是符号**实体**(entity)的哈希值:实体是一份声明的描述,只由所有重声明共有的属性构成,因此在每个翻译单元、每个进程中都得到相同的结果。实体包含声明的上下文链(命名空间、外层的类和函数,其中类模板特化还带上自己的模板实参)、声明自身的名字,以及在语言允许同名共存时用来区分它们的信息:函数的参数类型和限定符、模板头及其约束、特化的模板实参。类型以规范形式进入哈希,因此 typedef 与它所命名的类型哈希相同。约束表达式和其他依赖表达式通过移植 Clang 自身的规范表达式 profile 进入哈希——Sema 正是用它判断两个模板是否相同——其中所有指针值的叶子节点都替换为稳定的值。具有内部链接的声明(`static` 函数和变量、匿名命名空间的成员)还会带上首次声明它的文件路径,匿名类型以及系统头文件之外的 typedef 名字也一样:头文件中的 `static` 辅助函数,在每个包含该头文件的翻译单元里都是同一个符号;两个源文件中同名的两个辅助函数,则是两个不同的符号。宏的实体是它的名字加上 `#define` 所在的位置;具名模块(named module)的实体则是它的完整名字。
`SymbolHash` 是符号**实体**(entity)的哈希值:实体是一份声明的描述,只由所有重声明共有的属性构成,因此在每个翻译单元、每个进程中都得到相同的结果。实体包含声明的上下文链(命名空间、外层的类和函数,其中类模板特化还带上自己的模板实参)、声明自身的名字,以及在语言允许同名共存时用来区分它们的信息:函数的参数类型和限定符、模板头及其约束、特化的模板实参。类型以规范形式进入哈希,因此 typedef 与它所命名的类型哈希相同。约束表达式和其他依赖表达式通过移植 Clang 自身的规范表达式 profile 进入哈希——Sema 正是用它判断两个模板是否相同——其中所有指针值的叶子节点都替换为稳定的值。具有内部链接的声明(`static` 函数和变量、匿名命名空间的成员)还会带上首次声明它的文件,匿名类型以及系统头文件之外的 typedef 名字也一样:头文件中的 `static` 辅助函数,在每个包含该头文件的翻译单元里都是同一个符号;两个源文件中同名的两个辅助函数,则是两个不同的符号。宏的实体是它的名字加上 `#define` 所在的位置;具名模块(named module)的实体则是它的完整名字。工作区内的文件以相对于工作区根目录的路径进入这些哈希,因此检出目录(checkout)整体移动之后,每个符号的哈希都保持不变。

`SymbolHash` 有两个关键特性。第一,跨文件一致性:同一个符号无论出现在哪个文件中,其 `SymbolHash` 始终相同。文件 A 中的 `std::string` 与文件 B 中的 `std::string` 具有相同的哈希,因此可以通过它关联所有定义和引用——这是跨文件导航的基础。第二,紧凑性:相比可变长度的描述,64 位整数更适合用作哈希表键和进行序列化存储。

Expand Down Expand Up @@ -105,6 +105,8 @@ clice 的解决办法是让**编码后的字节本身成为标识**。每个变

所有索引数据块——分片、清单和序列化的 `ProjectIndex`——都存储在同一个嵌入式 LMDB 数据库中。数据块采用规范的自描述编码;加载时只需验证一次,之后便可直接用作内存映射的零拷贝视图。读取路径中不存在先反序列化为结构体的步骤。

数据库为工作区内的文件记录的每个路径都相对于工作区根目录,它保存的命令哈希中的路径也一样:把检出目录移动或复制到别处——缓存目录就在其中,编译数据库也按新位置重新生成——索引依然是最新的,不需要重新索引任何文件。工作区之外的文件保留绝对路径。

像 `clice query` 这样的读取方打开索引时,会从数据库的读快照中原地绑定全局表和搜索索引,某个分片要等到第一次有查询触及它时才取出来;整个过程不解码,也不复制任何一行。写入方则把自己的改动保存为同一份视图之上的内存增量——只有合并真正触及的行才会被复制——并在写出下一个数据块时将其并入;写入方还要负责协调清单与分片,因此会在启动时加载全部清单并校验每个分片。

### 每个 TU 的上下文
Expand Down
Loading