feat(server): improve configuration file handling (#423)
## Summary
- **`[[rules]]`**: TOML array-of-tables config for per-file compilation
flag rules with glob pattern matching (`append`/`remove`). Patterns are
pre-compiled at config load time. Rules whose patterns all fail to
compile are dropped entirely (no silent no-op entries), and rules now
apply uniformly to every compilation — including the header-context
fallback path used when editing a header without its own CDB entry.
- **CDB auto-scan**: Default search scans workspace root + all immediate
subdirectories for `compile_commands.json`, replacing the hardcoded
directory list.
- **LSP `initializationOptions`**: Clients can pass config as JSON via
the LSP initialize request; priority is `initializationOptions >
clice.toml > defaults`.
- **XDG cache paths**: Default cache/index/logging paths prefer
`$XDG_CACHE_HOME/clice/<workspace-hash>/`; fall back to
`$HOME/.cache/clice/<hash>/`, then `<workspace>/.clice/`.
- **`${workspace}` substitution**: supported in `cache_dir`,
`index_dir`, `logging_dir`, and every `compile_commands_paths` entry.
No-op when `workspace_root` is empty.
- **Partial config support**: All TOML/JSON fields are optional via
`kota::meta::defaulted<T>`, so minimal config files work correctly.
- **Detailed diagnostics**: malformed `clice.toml` now logs line, column
and parser description (via toml++ direct parse); a malformed workspace
config surfaces a clear fallback warning instead of silently reverting
to defaults.
## Test plan
- [x] 28 unit tests for config (full suite 545 unit tests pass, Debug)
- [x] 119 integration tests pass
- [x] 2 smoke tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* XDG-based, workspace-scoped project cache (PCH/PCM and header caches
moved under project cache) with workspace fallback
* Initialization options JSON can override config (takes precedence over
file/defaults)
* Per-file pattern rules to append/remove compile flags; expanded
discovery of compilation databases (multiple paths)
* **Refactor**
* Configuration fields reorganized under a project scope; runtime
behavior now respects project-scoped values
* **Tests**
* New unit and integration tests for config parsing, rule matching, and
persistent 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:
@@ -256,7 +256,8 @@ kota::task<> scan_impl(CompilationDatabase& cdb,
|
||||
DependencyGraph& graph,
|
||||
ScanReport& report,
|
||||
ScanCache* ext_cache,
|
||||
kota::event_loop& loop) {
|
||||
kota::event_loop& loop,
|
||||
const RuleMatcher& rule_matcher) {
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
|
||||
// Reuse context groups and configs from cache when available (warm runs).
|
||||
@@ -355,9 +356,19 @@ kota::task<> scan_impl(CompilationDatabase& cdb,
|
||||
std::uint32_t config_id = next_config_id++;
|
||||
context_to_config_id[context] = config_id;
|
||||
auto representative_path = path_pool.resolve(file_ids[0]);
|
||||
|
||||
// Apply per-file rules so that `[[rules]]`-modified -I/-isystem/-std
|
||||
// flags are reflected in the search config used by the scan.
|
||||
// Rules are applied to the representative file and assumed to hold
|
||||
// for the whole context group (same CompilationInfo).
|
||||
std::vector<std::string> rule_append, rule_remove;
|
||||
if(rule_matcher)
|
||||
rule_matcher(representative_path, rule_append, rule_remove);
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
configs[config_id] =
|
||||
cdb.lookup_search_config(representative_path, {.query_toolchain = true});
|
||||
configs[config_id] = cdb.lookup_search_config(
|
||||
representative_path,
|
||||
{.query_toolchain = true, .remove = rule_remove, .append = rule_append});
|
||||
auto t1 = std::chrono::steady_clock::now();
|
||||
lookup_us += std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count();
|
||||
}
|
||||
@@ -819,14 +830,15 @@ kota::task<> scan_impl(CompilationDatabase& cdb,
|
||||
ScanReport scan_dependency_graph(CompilationDatabase& cdb,
|
||||
PathPool& path_pool,
|
||||
DependencyGraph& graph,
|
||||
ScanCache* cache) {
|
||||
ScanCache* cache,
|
||||
const RuleMatcher& rule_matcher) {
|
||||
ScanReport report;
|
||||
if(cdb.get_entries().empty()) {
|
||||
return report;
|
||||
}
|
||||
|
||||
kota::event_loop loop;
|
||||
loop.schedule(scan_impl(cdb, path_pool, graph, report, cache, loop));
|
||||
loop.schedule(scan_impl(cdb, path_pool, graph, report, cache, loop, rule_matcher));
|
||||
loop.run();
|
||||
return report;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user