feat: header context protocol — queryContext, currentContext, switchContext (#398)
## Summary Add three LSP protocol extensions that allow users to manage compilation contexts for header files and source files with multiple CDB entries. ### Protocol extensions (`protocol.h`) | Command | Purpose | |---------|---------| | `clice/queryContext` | List all possible contexts for a file. Headers → host source files; sources → CDB entries. Paginated (10 per page, `offset` param). | | `clice/currentContext` | Query the active context override for a file (null if default). | | `clice/switchContext` | Set the active context, invalidate caches, trigger recompilation. | ### Header context resolution (`master_server.cpp`, `dependency_graph.cpp`) - `find_host_sources()`: BFS the reverse include graph to find source files that transitively include a header - `find_include_chain()`: BFS the forward include graph to find the shortest include chain from host to header - `resolve_header_context()`: walks the include chain, extracts content before each `#include` directive, concatenates with `#line` markers into a preamble file (hash-addressed under `.clice/header_context/`) - `fill_header_context_args()`: uses the host source's CDB entry, replaces source path with header path, injects `-include preamble.h` ### Compilation flow - Default: headers compile as standalone files (no context) - After `switchContext`: `fill_compile_args` checks `active_contexts` first → uses host's CDB entry + preamble injection - Fallback: if no CDB entry and no active context, auto-resolves via `resolve_header_context` - `#include` directive matching uses precise filename extraction from `"..."` / `<...>`, not substring matching ### Source file multiple contexts (`multi_context` workspace) - `queryContext` on a source file returns all CDB entries with distinguishing labels (extracted from `-D`, `-O`, `-std=` flags) ### Test data - `header_context/`: non-self-contained 3-level chain (`main.cpp` → `utils.h` → `inner.h`), `types.h` provides `Point` struct - `multi_context/`: single source with two CDB entries (`-DCONFIG_A`, `-DCONFIG_B`) ### Tests (9 integration tests) - queryContext returns host sources for headers - queryContext returns CDB entries for source files - currentContext defaults to null - switchContext sets active context, currentContext reflects it - Full flow: open → query → switch → hover works in non-self-contained header - Deep nested: switchContext + hover on `inner.h` (3 levels deep) - Multiple CDB entries: queryContext returns both CONFIG_A and CONFIG_B ## Test plan - [x] Unit tests: 465 passed - [x] Integration tests: 113 passed (9 new header context tests) - [x] Smoke test: 1/1 passed - [ ] Manual VSCode testing 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
6
tests/data/header_context/inner.h
Normal file
6
tests/data/header_context/inner.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
// Non self-contained: uses Point from the include chain.
|
||||
inline Point inner_origin() {
|
||||
return Point{0, 0};
|
||||
}
|
||||
8
tests/data/header_context/main.cpp
Normal file
8
tests/data/header_context/main.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
int main() {
|
||||
Point p{3, 4};
|
||||
int d = calc(p);
|
||||
return d;
|
||||
}
|
||||
12
tests/data/header_context/types.h
Normal file
12
tests/data/header_context/types.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
struct Point {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
inline int distance(Point a, Point b) {
|
||||
int dx = a.x - b.x;
|
||||
int dy = a.y - b.y;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
9
tests/data/header_context/utils.h
Normal file
9
tests/data/header_context/utils.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Non self-contained header: uses Point from types.h without including it.
|
||||
// Depends on the including source file to provide the types.h include.
|
||||
#pragma once
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
inline int calc(Point p) {
|
||||
return distance(p, inner_origin());
|
||||
}
|
||||
Reference in New Issue
Block a user