Repository navigation
feat: initial CompileGraph integration into MasterServer - #376
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds C++20 module-aware compilation to the server: a lazy CompileGraph, module provenance and PCM tracking, precompilation of imported modules during build/drain, safer LSP position-to-offset mapping, shared debounce timers, protocol/result payload updates, and extensive tests/fixtures for module scenarios. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant Server as MasterServer
participant CG as CompileGraph
participant CDB as CompilationDatabase
participant Worker as Worker
participant FS as FileSystem
Client->>Server: textDocument/didOpen / didSave / didClose
activate Server
Server->>CG: resolve/update(path_id) (lazy)
activate CG
CG->>CDB: scan_precise / lookup file & imports
CDB-->>CG: file path & imports
CG-->>Server: required module nodes / dirtied units
deactivate CG
Server->>Server: erase stale pcm_paths for dirtied units
loop for each required module node
Server->>CG: compile(module_node)
activate CG
CG->>Server: request BuildPCM (with transitive pcms)
Server->>Worker: BuildPCMParams (pcms)
Worker->>FS: invoke compiler -> produce PCM
Worker-->>Server: BuildPCMResult (pcm_path)
Server->>CG: provide pcm_path
deactivate CG
end
Server->>Worker: CompileParams for consumer (with all pcms)
Worker->>FS: compile consumer source
Worker-->>Server: compile result / diagnostics
Server-->>Client: publish diagnostics / responses
deactivate Server
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
2ccc6e6 to
277546e
Compare
Wire CompileGraph into MasterServer for automatic module dependency compilation. When a file is opened/changed, the server scans for module imports, compiles their PCMs in dependency order, then passes all available PCMs to the stateful worker. Server changes: - Scan imports via scan_precise() and compile deps before stateful build - Handle module implementation units (module M; without export) - Self-PCM exclusion to avoid "multiple module declarations" - Stop drain when prerequisite PCM build fails - Cascade invalidation on save: rebuild open importers - Use pre-captured cancellation token for dispatch correctness - Use forward-slash CDB paths for Windows compatibility Tests added: - 24 C++ integration tests (compile_graph_integration_tests.cpp) - 3 worker-level tests (module_worker_tests.cpp) - 24 Python integration tests (test_modules.py) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…co_await Two bugs found during review: 1. drain_scheduled was not reset when module dependency compilation failed, permanently blocking future builds for that document. 2. doc_it iterator captured before compile_graph co_awaits was used after suspension without re-lookup, risking use-after-invalidation if the document map was modified during module dep compilation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
277546e to
7caa188
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/integration/test_modules.py (1)
71-83: Consider making the initialization sleep configurable.The 1-second sleep is hardcoded. For slower CI environments or complex workspaces, this might not be sufficient.
💡 Optional: Make sleep duration configurable
-async def _init(client, workspace: Path): +async def _init(client, workspace: Path, init_delay: float = 1.0): """Initialize the LSP server with a workspace.""" result = await client.initialize_async( InitializeParams( capabilities=ClientCapabilities(), root_uri=workspace.as_uri(), workspace_folders=[WorkspaceFolder(uri=workspace.as_uri(), name="test")], ) ) client.initialized(InitializedParams()) # Give the server time to load CDB and scan dependency graph. - await asyncio.sleep(1.0) + await asyncio.sleep(init_delay) return result🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/integration/test_modules.py` around lines 71 - 83, The hardcoded 1.0s delay in _init can fail on slow CI; make it configurable by adding an optional parameter (e.g., init_delay: float = 1.0) to _init and use that value instead of the literal in the asyncio.sleep call, or read a fallback from an environment variable (e.g., os.getenv("TEST_INIT_SLEEP")). Update any callers of _init in tests to use the new parameter when needed and preserve the current default so existing tests keep the same behavior; reference _init, client.initialize_async, and asyncio.sleep when locating the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@tests/integration/test_modules.py`:
- Around line 71-83: The hardcoded 1.0s delay in _init can fail on slow CI; make
it configurable by adding an optional parameter (e.g., init_delay: float = 1.0)
to _init and use that value instead of the literal in the asyncio.sleep call, or
read a fallback from an environment variable (e.g.,
os.getenv("TEST_INIT_SLEEP")). Update any callers of _init in tests to use the
new parameter when needed and preserve the current default so existing tests
keep the same behavior; reference _init, client.initialize_async, and
asyncio.sleep when locating the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3f03ec60-ec62-4aea-acbf-6026f0d54d44
📒 Files selected for processing (8)
src/server/master_server.cppsrc/server/master_server.hsrc/server/protocol.hsrc/server/stateless_worker.cpptests/conftest.pytests/integration/test_modules.pytests/unit/server/compile_graph_integration_tests.cpptests/unit/server/module_worker_tests.cpp
- Fix timer use-after-free: shared_ptr for debounce timers so drain coroutines survive didClose erasing the map entry - Fix fill_compile_args silent failure: return bool, callers handle missing CDB entries gracefully - Fix dep failure waste: break on first failed PCM, guard impl-unit section with deps_ok check - Fix didClose orphaned compilations: cancel compile_graph on close - Fix Windows -I path: use as_posix() for all tmp_path args in tests - Increase _init() sleep for CI robustness - Strengthen test_module_compile_error: assert line number and severity - Add unit tests: WhenAllPartialFailure, UpdateUnknownPathId, EmptyGraphNoCompile - Add integration tests: test_no_modules_plain_cpp (null compile_graph), test_circular_module_dependency (cycle detection + server liveness) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/server/master_server.cpp (2)
118-127: Consider logging when multiple files provide the same module.When
mod_idscontains multiple entries (multiple files exporting the same module name), onlymod_ids[0]is compiled. This is likely intentional, but if it occurs, it might indicate a configuration issue worth logging.💡 Optional: Add debug logging for ambiguous module providers
for(auto& mod_name: scan_result.modules) { auto mod_ids = dependency_graph.lookup_module(mod_name); + if(mod_ids.size() > 1) { + LOG_DEBUG("Module {} has {} providers, using first", mod_name, mod_ids.size()); + } if(!mod_ids.empty()) { auto r = co_await compile_graph->compile(mod_ids[0]).catch_cancel();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/server/master_server.cpp` around lines 118 - 127, When dependency_graph.lookup_module(scan_result.modules) returns multiple providers, the code currently just compiles mod_ids[0] which can hide ambiguous exports; update the loop in which scan_result.modules is iterated to detect when mod_ids.size() > 1 and emit a debug/warn log including the module name and the list of provider IDs (or file names) before proceeding to compile via compile_graph->compile(mod_ids[0]) so operators can investigate configuration issues (look for symbols: scan_result.modules, dependency_graph.lookup_module, mod_ids, compile_graph->compile, mod_ids[0]).
690-700: Minor comment clarification.The comment on line 692 says "rebuilt by its own didChange", but
didSavedoesn't necessarily follow adidChange. The saved file would be rebuilt via the normaldidOpen/didChangeflow if it's open. The skip is still correct (avoid double-scheduling), but the comment could be slightly misleading.📝 Optional: Clarify the comment
for(auto dirty_id: dirtied) { if(dirty_id == path_id) - continue; // The saved file itself is rebuilt by its own didChange. + continue; // The saved file itself; already scheduled via didOpen/didChange. if(documents.count(dirty_id)) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/server/master_server.cpp` around lines 690 - 700, The comment on the skip in the loop (around the dirtied/path_id check) is misleading: change the comment for the if(dirty_id == path_id) continue; to say that we skip scheduling the saved file to avoid double-scheduling because it may already be rebuilt via open/change notifications (didOpen/didChange) when the document is open, rather than asserting it is rebuilt by its own didChange; keep the existing skip behavior and refer to symbols dirtied, path_id, didSave, didOpen, didChange, and schedule_build when updating the comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/server/master_server.cpp`:
- Around line 118-127: When dependency_graph.lookup_module(scan_result.modules)
returns multiple providers, the code currently just compiles mod_ids[0] which
can hide ambiguous exports; update the loop in which scan_result.modules is
iterated to detect when mod_ids.size() > 1 and emit a debug/warn log including
the module name and the list of provider IDs (or file names) before proceeding
to compile via compile_graph->compile(mod_ids[0]) so operators can investigate
configuration issues (look for symbols: scan_result.modules,
dependency_graph.lookup_module, mod_ids, compile_graph->compile, mod_ids[0]).
- Around line 690-700: The comment on the skip in the loop (around the
dirtied/path_id check) is misleading: change the comment for the if(dirty_id ==
path_id) continue; to say that we skip scheduling the saved file to avoid
double-scheduling because it may already be rebuilt via open/change
notifications (didOpen/didChange) when the document is open, rather than
asserting it is rebuilt by its own didChange; keep the existing skip behavior
and refer to symbols dirtied, path_id, didSave, didOpen, didChange, and
schedule_build when updating the comment.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fcad4a81-9f2d-4bbf-9eb2-d9f5c6f83951
📒 Files selected for processing (4)
src/server/master_server.cppsrc/server/master_server.htests/integration/test_modules.pytests/unit/server/compile_graph_tests.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/integration/test_modules.py
… style fixes - Extract inline C++ source files from test_modules.py into tests/data/modules/<case>/ directories (26 test cases, 61 files) - Remove unused tmp_path parameters and _data_dir wrapper - Deduplicate _write_cdb by delegating to _write_cdb_entries - Use raw string literals instead of escaped quotes (claude.md) - Replace .count() with .contains() for C++20 idiom (claude.md) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/unit/server/compile_graph_integration_tests.cpp (1)
180-188: Unnecessarythiscapture in test lambdas.The
thiscapture in the test lambda appears unused. While harmless, removing it would improve clarity.✨ Suggested cleanup
- auto test = [this, &cg, &env, pid_a]() -> et::task<> { + auto test = [&cg, &env, pid_a]() -> et::task<> {This pattern repeats throughout the test file.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/server/compile_graph_integration_tests.cpp` around lines 180 - 188, The lambda named test is capturing this unnecessarily; remove this from the capture list (i.e., change [this, &cg, &env, pid_a] to [&cg, &env, pid_a]) and update any other similar test lambdas in tests/unit/server/compile_graph_integration_tests.cpp to drop the unused this capture so captures only include cg, env, pid_a (and any other actually used variables) before scheduling with loop.schedule(...) and running with loop.run().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@tests/unit/server/compile_graph_integration_tests.cpp`:
- Around line 180-188: The lambda named test is capturing this unnecessarily;
remove this from the capture list (i.e., change [this, &cg, &env, pid_a] to
[&cg, &env, pid_a]) and update any other similar test lambdas in
tests/unit/server/compile_graph_integration_tests.cpp to drop the unused this
capture so captures only include cg, env, pid_a (and any other actually used
variables) before scheduling with loop.schedule(...) and running with
loop.run().
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d756e3d2-ccc7-468b-94eb-cc2f22e35a2d
📒 Files selected for processing (66)
src/server/master_server.cpptests/data/modules/chained_modules/mod_a.cppmtests/data/modules/chained_modules/mod_b.cppmtests/data/modules/circular_module_dependency/cycle_a.cppmtests/data/modules/circular_module_dependency/cycle_b.cppmtests/data/modules/circular_module_dependency/ok.cppmtests/data/modules/class_export_and_inheritance/circle.cppmtests/data/modules/class_export_and_inheritance/shape.cppmtests/data/modules/consumer_imports_module/main.cpptests/data/modules/consumer_imports_module/math.cppmtests/data/modules/deep_chain/m1.cppmtests/data/modules/deep_chain/m2.cppmtests/data/modules/deep_chain/m3.cppmtests/data/modules/deep_chain/m4.cppmtests/data/modules/deep_chain/m5.cppmtests/data/modules/diamond_modules/base.cppmtests/data/modules/diamond_modules/left.cppmtests/data/modules/diamond_modules/right.cppmtests/data/modules/diamond_modules/top.cppmtests/data/modules/dotted_module_name/app.cppmtests/data/modules/dotted_module_name/io.cppmtests/data/modules/export_block/block.cppmtests/data/modules/export_block/consumer.cppmtests/data/modules/export_namespace/calc.cppmtests/data/modules/export_namespace/ns.cppmtests/data/modules/global_module_fragment/gmf.cppmtests/data/modules/global_module_fragment/legacy.htests/data/modules/gmf_with_import/base.cppmtests/data/modules/gmf_with_import/combined.cppmtests/data/modules/gmf_with_import/util.htests/data/modules/hover_on_imported_symbol/defs.cppmtests/data/modules/hover_on_imported_symbol/use.cpptests/data/modules/independent_modules/x.cppmtests/data/modules/independent_modules/y.cppmtests/data/modules/module_compile_error/bad.cppmtests/data/modules/module_compile_error/good.cppmtests/data/modules/module_implementation_unit/greeter.cppmtests/data/modules/module_implementation_unit/greeter_impl.cpptests/data/modules/module_partitions/lib.cppmtests/data/modules/module_partitions/part_a.cppmtests/data/modules/module_partitions/part_b.cppmtests/data/modules/no_modules_plain_cpp/plain.cpptests/data/modules/partition_chain/core.cppmtests/data/modules/partition_chain/sys.cppmtests/data/modules/partition_chain/types.cppmtests/data/modules/partition_interface/part.cppmtests/data/modules/partition_interface/primary.cppmtests/data/modules/partition_with_external_import/app.cppmtests/data/modules/partition_with_external_import/ext.cppmtests/data/modules/partition_with_external_import/part.cppmtests/data/modules/partition_with_gmf/cfg.cppmtests/data/modules/partition_with_gmf/config.htests/data/modules/partition_with_gmf/part_cfg.cppmtests/data/modules/private_module_fragment/priv.cppmtests/data/modules/re_export/core.cppmtests/data/modules/re_export/user.cppmtests/data/modules/re_export/wrapper.cppmtests/data/modules/save_recompile/leaf.cppmtests/data/modules/save_recompile/mid.cppmtests/data/modules/single_module_no_deps/mod_a.cppmtests/data/modules/template_export/tmpl.cppmtests/data/modules/template_export/use_tmpl.cppmtests/integration/test_modules.pytests/unit/server/compile_graph_integration_tests.cpptests/unit/server/compile_graph_tests.cpptests/unit/server/module_worker_tests.cpp
✅ Files skipped from review due to trivial changes (47)
- tests/data/modules/partition_with_gmf/config.h
- tests/data/modules/gmf_with_import/util.h
- tests/data/modules/save_recompile/mid.cppm
- tests/data/modules/global_module_fragment/legacy.h
- tests/data/modules/re_export/core.cppm
- tests/data/modules/partition_with_external_import/app.cppm
- tests/data/modules/save_recompile/leaf.cppm
- tests/data/modules/module_compile_error/bad.cppm
- tests/data/modules/circular_module_dependency/cycle_b.cppm
- tests/data/modules/module_compile_error/good.cppm
- tests/data/modules/hover_on_imported_symbol/use.cpp
- tests/data/modules/partition_with_gmf/cfg.cppm
- tests/data/modules/partition_interface/part.cppm
- tests/data/modules/module_partitions/part_a.cppm
- tests/data/modules/deep_chain/m4.cppm
- tests/data/modules/dotted_module_name/io.cppm
- tests/data/modules/diamond_modules/left.cppm
- tests/data/modules/circular_module_dependency/ok.cppm
- tests/data/modules/chained_modules/mod_a.cppm
- tests/data/modules/deep_chain/m1.cppm
- tests/data/modules/independent_modules/y.cppm
- tests/data/modules/single_module_no_deps/mod_a.cppm
- tests/data/modules/class_export_and_inheritance/shape.cppm
- tests/data/modules/partition_chain/types.cppm
- tests/data/modules/deep_chain/m5.cppm
- tests/data/modules/no_modules_plain_cpp/plain.cpp
- tests/data/modules/template_export/use_tmpl.cppm
- tests/data/modules/consumer_imports_module/math.cppm
- tests/data/modules/export_block/block.cppm
- tests/data/modules/partition_with_gmf/part_cfg.cppm
- tests/data/modules/independent_modules/x.cppm
- tests/data/modules/deep_chain/m2.cppm
- tests/data/modules/partition_interface/primary.cppm
- tests/data/modules/chained_modules/mod_b.cppm
- tests/data/modules/partition_with_external_import/ext.cppm
- tests/data/modules/gmf_with_import/base.cppm
- tests/data/modules/partition_with_external_import/part.cppm
- tests/data/modules/class_export_and_inheritance/circle.cppm
- tests/data/modules/deep_chain/m3.cppm
- tests/data/modules/module_partitions/part_b.cppm
- tests/data/modules/dotted_module_name/app.cppm
- tests/data/modules/diamond_modules/base.cppm
- tests/data/modules/hover_on_imported_symbol/defs.cppm
- tests/data/modules/export_namespace/ns.cppm
- tests/data/modules/template_export/tmpl.cppm
- tests/data/modules/partition_chain/core.cppm
- tests/integration/test_modules.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/unit/server/compile_graph_tests.cpp
Add safe_to_offset() that validates line/character bounds before calling PositionMapper::to_offset(), returning std::nullopt instead of asserting. Applied to forward_stateful, forward_stateless, and didChange handlers. Also fix hover test coordinate (line=1 -> line=3 for magic_number()). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/server/master_server.cpp (1)
143-154: Consider logging whenscan_precisefails or returns no CDB results.If
cdb.lookup()returns empty results (line 143), the code silently skips module dependency compilation. While this might be intentional for files without CDB entries, a debug log could help diagnose unexpected build failures.💡 Suggested enhancement
bool deps_ok = true; - if(!cdb_results.empty()) { + if(cdb_results.empty()) { + LOG_DEBUG("No CDB entry for {}, skipping module scan", file_path); + } else { auto scan_result = scan_precise(cdb_results[0].arguments, cdb_results[0].directory);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/server/master_server.cpp` around lines 143 - 154, When cdb_results is empty or scan_precise produces no modules the code silently skips dependency compilation; update the block around cdb_results, scan_precise, and the dependency loop to emit a debug/info log when cdb_results.empty() or when scan_precise returns an empty/failed result so unexpected misses are visible; specifically add a log entry referencing the file/path or the inputs used (use existing logger in this module) before skipping, and also log any error/empty condition returned by scan_precise(mods) (symbols: cdb_results, scan_precise, dependency_graph.lookup_module, compile_graph->compile, deps_ok) so maintainers can see why compilation was skipped.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/server/master_server.cpp`:
- Around line 348-381: Add deterministic teardown to avoid use-after-free:
implement an explicit MasterServer destructor (~MasterServer()) that calls
compile_graph->cancel_all() (or equivalent cancel method) before the
compile_graph unique_ptr is destroyed, ensuring no queued lambdas
(dispatch/resolve) will run after MasterServer begins destruction; and implement
an explicit CompileGraph destructor (~CompileGraph()) that cancels remaining
work and synchronously waits for all pending et::task instances to finish or be
cancelled (e.g. signal cancellation and join/wait any worker futures/promises)
before returning, so stored lambdas that capture this are never invoked after
CompileGraph/MasterServer are destroyed. Ensure the destructors reference the
existing methods/fields (compile_graph, cancel_all, dispatch/resolve task
queues) to locate the implementation points.
---
Nitpick comments:
In `@src/server/master_server.cpp`:
- Around line 143-154: When cdb_results is empty or scan_precise produces no
modules the code silently skips dependency compilation; update the block around
cdb_results, scan_precise, and the dependency loop to emit a debug/info log when
cdb_results.empty() or when scan_precise returns an empty/failed result so
unexpected misses are visible; specifically add a log entry referencing the
file/path or the inputs used (use existing logger in this module) before
skipping, and also log any error/empty condition returned by scan_precise(mods)
(symbols: cdb_results, scan_precise, dependency_graph.lookup_module,
compile_graph->compile, deps_ok) so maintainers can see why compilation was
skipped.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0fb798ff-e85d-4456-95c9-b720b6ec0015
📒 Files selected for processing (2)
src/server/master_server.cpptests/integration/test_modules.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/integration/test_modules.py
- Replace free function safe_to_offset with SafePositionMapper struct that constructs mapper and counts lines once, reused across multiple position conversions (e.g. didChange range.start + range.end) - Parallelize module dependency compilation in run_build_drain using et::when_all instead of serial co_await loop - Fix hover test coordinates to match actual use.cpp layout (line=3) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/server/master_server.cpp (1)
390-392: Consider adding explicitco_return;to silence static analysis warning.The static analysis tool flags a missing return statement. While falling off the end of a coroutine returning
et::task<>is valid C++20 behavior (equivalent toco_return;), an explicit statement would silence the warning and make the intent clearer.compile_graph = std::make_unique<CompileGraph>(std::move(dispatch), std::move(resolve)); LOG_INFO("CompileGraph initialized with {} module(s)", path_to_module.size()); + co_return; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/server/master_server.cpp` around lines 390 - 392, The coroutine that constructs compile_graph (where you call std::make_unique<CompileGraph>(std::move(dispatch), std::move(resolve)) and then LOG_INFO("CompileGraph initialized with {} module(s)", path_to_module.size())) returns et::task<>; add an explicit co_return; as the final statement in that function to silence the static-analysis warning and make the intent clear (i.e., append a single co_return; after the LOG_INFO line in the function that sets compile_graph).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/server/master_server.cpp`:
- Around line 390-392: The coroutine that constructs compile_graph (where you
call std::make_unique<CompileGraph>(std::move(dispatch), std::move(resolve)) and
then LOG_INFO("CompileGraph initialized with {} module(s)",
path_to_module.size())) returns et::task<>; add an explicit co_return; as the
final statement in that function to silence the static-analysis warning and make
the intent clear (i.e., append a single co_return; after the LOG_INFO line in
the function that sets compile_graph).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: edef0aa4-92bc-435e-839a-d404c852b065
📒 Files selected for processing (1)
src/server/master_server.cpp
CompileGraph internally parallelizes transitive deps via when_all, so the caller does not need its own when_all. Use a simple serial loop and let CompileGraph handle scheduling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PositionMapper::to_position() and to_offset() now return std::optional. Remove SafePositionMapper wrapper and use PositionMapper directly. Dereference with * where offsets are from trusted sources (clang AST, replacements). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dispatch/resolve lambdas capture `this` and live inside CompileGraph. Call cancel_all() before the unique_ptr destructor runs to prevent use-after-free on pending tasks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Initial integration of
CompileGraph(#375) intoMasterServer, enabling basic end-to-end C++20 module support: on-demand PCM building, dependency-ordered compilation, cascade invalidation on save, and diagnostic integration.This is a first-pass implementation — the core pipeline works, but there are known areas for follow-up:
.clice/cache/; no disk cleanup on invalidationrun_build_drainscans imports itself rather than delegating fully to CompileGraphChanges
Module dependency compilation (
master_server.cpp)Before sending a file to the stateful worker,
run_build_drainnow:scan_precise()to discover module dependenciescompile_graph->compile(), which recursively builds transitive PCMsmodule M;implicitly needs the interface PCMbuild_running/drain_scheduledco_awaitto avoid use-after-invalidationCascade invalidation (
didSave/didClose)didSave: callscompile_graph->update()to mark transitive dependents dirty, removes stale PCM paths, schedules rebuilds for open dirtied filesdidClose: cancels in-flight compilations for the closed fileOther fixes in this PR
shared_ptrto prevent use-after-free whendidClosedestroys the timer mid-waitfill_compile_argsreturnsbool; callers handle empty CDB gracefullyPositionMappercall sites to the newoptionalreturn API from eventideTest plan
🤖 Generated with Claude Code