refactor(command): split CompilationContext into ResolvedFlags → CompileCommand → to_argv() (#408)

## Summary

- Replace flat `CompilationContext { directory, arguments }` with a
three-layer abstraction: `ResolvedFlags` (file-independent flags) →
`CompileCommand` (+ source file) → `to_argv()` (full argv on demand)
- `ResolvedFlags.flags` never contains source file path or
`-main-file-name`, making it directly usable as a clean cache key input
(e.g. PCH sharing across files with identical preambles)
- `to_argv()` handles `-main-file-name` insertion for cc1 mode
automatically — consumers no longer need to search/replace in the
argument list
- Eliminates the pollute-then-clean anti-pattern in `lookup()` and the
manual source-file replacement in `fill_header_context_args()`

## Test plan

- [x] `pixi run format` — no changes
- [x] `pixi run unit-test` — 481 passed
- [x] `pixi run integration-test` — 113 passed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Unified compile-command handling across the server and tools for more
consistent argument and flag behavior (driver vs frontend modes).
* **New Features**
* Added an LRU-backed in-memory cache to improve performance and
eviction control.
* **Chores**
* Added an option to control injection of resource-directory flags
(enabled by default).
* **Tests**
* Updated unit and integration tests to adopt the new command
representation and verify cache behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ykiko
2026-04-08 22:18:25 +08:00
committed by GitHub
parent 9c9e6b0bcb
commit 2bbdf6c02b
9 changed files with 239 additions and 178 deletions

View File

@@ -29,10 +29,8 @@ CompileGraph::dispatch_fn make_dispatch(CompilationDatabase& cdb,
CompilationParams cp;
cp.kind = CompilationKind::ModuleInterface;
cp.directory = results[0].directory.str();
for(auto* arg: results[0].arguments) {
cp.arguments.push_back(arg);
}
cp.directory = results[0].resolved.directory.str();
cp.arguments = results[0].to_argv();
// Fill ALL available PCM paths (clang needs transitive deps too).
for(auto& [pid, pcm_path]: pcm_paths) {
@@ -72,7 +70,7 @@ CompileGraph::resolve_fn make_resolver(CompilationDatabase& cdb,
return {};
}
auto scan_result = scan_precise(results[0].arguments, results[0].directory);
auto scan_result = scan_precise(results[0].to_argv(), results[0].resolved.directory);
llvm::SmallVector<std::uint32_t> deps;
for(auto& mod_name: scan_result.modules) {
@@ -1034,7 +1032,7 @@ TEST_CASE(ReResolveAfterUpdate) {
if(results.empty()) {
return {};
}
auto scan_result = scan_precise(results[0].arguments, results[0].directory);
auto scan_result = scan_precise(results[0].to_argv(), results[0].resolved.directory);
llvm::SmallVector<std::uint32_t> deps;
for(auto& mod_name: scan_result.modules) {
auto mod_ids = env.graph.lookup_module(mod_name);
@@ -1150,10 +1148,8 @@ TEST_CASE(ModuleImplementationUnit) {
CompilationParams cp;
cp.kind = CompilationKind::Content;
cp.directory = results[0].directory.str();
for(auto* arg: results[0].arguments) {
cp.arguments.push_back(arg);
}
cp.directory = results[0].resolved.directory.str();
cp.arguments = results[0].to_argv();
// Pass the built PCM so clang can resolve `module Greeter;`.
for(auto& [pid, pcm_path]: env.pcm_paths) {
for(auto& [mod_name, mod_ids]: env.graph.modules()) {