## 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>
69 lines
2.5 KiB
Python
69 lines
2.5 KiB
Python
"""Integration tests for clice configuration (clice.toml + initializationOptions).
|
|
|
|
Each workspace's main.cpp references a macro that is only defined when the
|
|
rule's `-D<macro>=...` is applied. When rules are applied, compilation is
|
|
clean; otherwise an undeclared-identifier diagnostic surfaces.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from tests.integration.utils.assertions import (
|
|
assert_clean_compile,
|
|
assert_has_errors,
|
|
get_errors,
|
|
)
|
|
|
|
|
|
@pytest.mark.workspace("config_rules_no_config")
|
|
async def test_baseline_without_rules(client, workspace):
|
|
uri, _ = await client.open_and_wait(workspace / "main.cpp")
|
|
assert_has_errors(client, uri, "Expected diagnostics without any rules applied")
|
|
errors = get_errors(client.diagnostics[uri])
|
|
assert any("FROM_INIT" in (d.message or "") for d in errors), (
|
|
f"Expected a diagnostic referencing FROM_INIT, got: {errors}"
|
|
)
|
|
|
|
|
|
@pytest.mark.workspace("config_rules_toml")
|
|
async def test_rules_from_toml(client, workspace):
|
|
uri, _ = await client.open_and_wait(workspace / "main.cpp")
|
|
assert_clean_compile(client, uri)
|
|
|
|
symbols = await client.document_symbols(uri)
|
|
assert symbols, "Expected document symbols for value()/main()"
|
|
hover = await client.hover_at(uri, line=4, character=4) # on 'main'
|
|
assert hover is not None
|
|
|
|
|
|
@pytest.mark.workspace("config_rules_no_config")
|
|
@pytest.mark.init_options(
|
|
{"rules": [{"patterns": ["**/*.cpp"], "append": ["-DFROM_INIT=1"]}]}
|
|
)
|
|
async def test_rules_from_init_options(client, workspace):
|
|
uri, _ = await client.open_and_wait(workspace / "main.cpp")
|
|
assert_clean_compile(client, uri)
|
|
|
|
|
|
@pytest.mark.workspace("config_rules_toml")
|
|
@pytest.mark.init_options(
|
|
{"rules": [{"patterns": ["**/*.cpp"], "append": ["-DUNRELATED"]}]}
|
|
)
|
|
async def test_init_options_replaces_toml_rules(client, workspace):
|
|
uri, _ = await client.open_and_wait(workspace / "main.cpp")
|
|
assert_has_errors(
|
|
client, uri, "initializationOptions should have overridden clice.toml rules"
|
|
)
|
|
errors = get_errors(client.diagnostics[uri])
|
|
assert any("FROM_TOML" in (d.message or "") for d in errors), (
|
|
f"Expected FROM_TOML diagnostic after override, got: {errors}"
|
|
)
|
|
|
|
|
|
@pytest.mark.workspace("config_rules_no_config")
|
|
@pytest.mark.init_options(
|
|
{"rules": [{"patterns": ["**/does_not_match.cpp"], "append": ["-DFROM_INIT=1"]}]}
|
|
)
|
|
async def test_rules_pattern_mismatch(client, workspace):
|
|
uri, _ = await client.open_and_wait(workspace / "main.cpp")
|
|
assert_has_errors(client, uri, "Rule pattern should not have matched main.cpp")
|