Skip to content

refactor: diagnostic handling - #337

Merged
16bit-ykiko merged 16 commits into
mainfrom
improve-compilation-unit
Jan 3, 2026
Merged

16bit-ykiko merged 16 commits into
mainfrom
improve-compilation-unit

Conversation

@16bit-ykiko

@16bit-ykiko 16bit-ykiko commented Jan 1, 2026 •

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Refactor

    • Compilation results now surface explicit status states (completed/cancelled/setup/fatal) and provide value-style access; diagnostics are returned directly from compilation units.
  • New Features

    • Per-unit clang‑tidy integration and diagnostic hooks enabled for linting and tooling.
  • Bug Fixes

    • Safer diagnostic range and emission handling to avoid null/invalid cases.
  • Chores

    • Updated developer docs, CI/workflow config, project metadata, and ignores.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 1, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Refactors the compilation model to a ref-based CompilationUnitRef/Self with CompilationKind and CompilationStatus; public compile/preprocess/complete APIs now return CompilationUnit; diagnostics and clang-tidy are per-unit; many call sites and tests updated to use unit.completed()/unit.diagnostics() and CompilationKind.

Changes

Cohort / File(s) Summary
Core unit surface
include/Compiler/CompilationUnit.h, src/Compiler/CompilationUnit.cpp, src/Compiler/CompilationUnitImpl.h
Introduces CompilationUnitRef (holds Self*) and derived CompilationUnit; renames Kind→CompilationKind; adds CompilationStatus; moves impl state into CompilationUnitRef::Self; removes old Impl header.
Compilation API
include/Compiler/Compilation.h, src/Compiler/Compilation.cpp
preprocess, compile (incl. PCH/PCM overloads) and complete now return CompilationUnit; CompilationParams::kind uses CompilationKind; params.diagnostics removed; run/create_invocation signatures made unit-centric.
Per‑unit diagnostics & tidy
include/Compiler/Diagnostic.h, src/Compiler/Diagnostic.cpp, include/Compiler/Tidy.h, src/Compiler/Tidy.cpp, src/Compiler/TidyImpl.h, src/Compiler/Implement.h
Removes legacy Diagnostic/Tidy headers; introduces Implement.h exposing CompilationUnitRef::Self, tidy API and create_diagnostic(CompilationUnitRef); DiagnosticCollector now binds to unit and appends into unit.diagnostics().
Directive collection
include/Compiler/Directive.h, src/Compiler/Directive.cpp
Removes Directive::attach(...); directive collection moved into CompilationUnitRef::Self::collect_directives() using unit's CompilerInstance/Preprocessor.
Server & tasks
src/Server/Document.cpp, src/Server/Indexer.cpp, src/Server/Feature.cpp, include/Server/Server.h
Removes forwarded diagnostics param from PCH/AST builders and OpenFile::diagnostics; uses CompilationKind enum values; success checks now use unit.completed(); diagnostics published from unit.diagnostics(); TUIndex build adjusted to accept unit.
Compilation internals
src/Compiler/Compilation.cpp
Moves orchestration and lifetimes to unit-centric model (remapped buffers, run_clang returns CompilationStatus); frontend/actions and diagnostics routed through unit state.
API call-site adaptions
many feature/index/AST files (e.g., src/Feature/*, src/Index/*, include/Feature/*, include/Index/*)
Replaces CompilationUnit& / unit->... usage with CompilationUnitRef / unit... or unit.* accessors; update builders/visitors/collectors to accept CompilationUnitRef; replace truthy/optional checks with unit.completed()/setup_fail()/fatal_error().
Tests
tests/unit/**
Tests updated to use .completed()/setup_fail()/fatal_error() and unit.diagnostics(); switch to CompilationKind values; adapt access patterns from pointer-like to value-like.
Build/config/docs
pixi.toml, .github/workflows/*, docs/*, .clangd, .gitignore
Pixi task reorg toward test grouping; CI action inputs simplified; docs updated (pixi shell); .clangd trimmed and added to .gitignore.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as CompilationAPI
    participant Unit as CompilationUnit
    participant Self as CompilationUnitRef::Self
    participant Diag as DiagnosticCollector
    participant Tidy as ClangTidyChecker

    Client->>API: compile(params)
    activate API
    API->>Unit: construct CompilationUnit(Self*)
    activate Unit
    Unit->>Self: initialize (remapped buffers, instance, checker)
    activate Self
    API->>Diag: create_diagnostic(Unit)
    API->>Self: unit.configure_tidy() [optional]
    Self->>Tidy: register checks (if configured)
    API->>Self: run_clang()/frontend action
    rect rgb(230,245,230)
      Self->>Diag: emit diagnostics
      Diag-->>Self: append to unit.diagnostics()
    end
    Self->>Unit: set status (Completed/Cancelled/SetupFail/FatalError)
    deactivate Self
    Unit-->>API: return CompilationUnit
    API-->>Client: CompilationUnit
    Client->>Unit: query (completed?/diagnostics()/status())
    Unit-->>Client: results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped into code with a curious nose,
Units now hold what every compile knows.
No shared vectors, each diagnostic sings,
Status flags flutter on tiny ref-wings.
Tests cheer, tidy hums — the rabbit happily hops.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.61% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'refactor: diagnostic handling' accurately reflects the main objective of this changeset, which comprehensively refactors diagnostic handling throughout the codebase by moving diagnostics storage from external parameters to per-unit storage within CompilationUnitRef::Self.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dee5e13 and 83fdc80.

⛔ Files ignored due to path filters (1)
  • pixi.lock is excluded by !**/*.lock
📒 Files selected for processing (61)
  • .clangd
  • .github/workflows/publish-clice.yml
  • .github/workflows/test-cmake.yml
  • .github/workflows/test-xmake.yml
  • .gitignore
  • docs/en/dev/build.md
  • docs/zh/dev/build.md
  • include/AST/FilterASTVisitor.h
  • include/AST/Selection.h
  • include/AST/Semantic.h
  • include/AST/SourceCode.h
  • include/Compiler/Compilation.h
  • include/Compiler/CompilationUnit.h
  • include/Compiler/Diagnostic.h
  • include/Compiler/Directive.h
  • include/Compiler/Tidy.h
  • include/Feature/Diagnostic.h
  • include/Feature/DocumentLink.h
  • include/Feature/DocumentSymbol.h
  • include/Feature/FoldingRange.h
  • include/Feature/Hover.h
  • include/Feature/InlayHint.h
  • include/Feature/SemanticToken.h
  • include/Index/IncludeGraph.h
  • include/Index/Shared.h
  • include/Index/TUIndex.h
  • include/Server/Server.h
  • pixi.toml
  • src/AST/Selection.cpp
  • src/Compiler/Command.cpp
  • src/Compiler/Compilation.cpp
  • src/Compiler/CompilationUnit.cpp
  • src/Compiler/CompilationUnitImpl.h
  • src/Compiler/Diagnostic.cpp
  • src/Compiler/Directive.cpp
  • src/Compiler/Implement.h
  • src/Compiler/Module.cpp
  • src/Compiler/Tidy.cpp
  • src/Compiler/TidyImpl.h
  • src/Feature/CodeCompletion.cpp
  • src/Feature/Diagnostic.cpp
  • src/Feature/DocumentLink.cpp
  • src/Feature/DocumentSymbol.cpp
  • src/Feature/FoldingRange.cpp
  • src/Feature/Hover.cpp
  • src/Feature/InlayHint.cpp
  • src/Feature/SemanticToken.cpp
  • src/Feature/SignatureHelp.cpp
  • src/Index/IncludeGraph.cpp
  • src/Index/TUIndex.cpp
  • src/Index/USRGeneration.cpp
  • src/Server/Document.cpp
  • src/Server/Feature.cpp
  • src/Server/Indexer.cpp
  • tests/unit/AST/ResolverTests.cpp
  • tests/unit/Compiler/DiagnosticTests.cpp
  • tests/unit/Compiler/ModuleTests.cpp
  • tests/unit/Compiler/PreambleTests.cpp
  • tests/unit/Compiler/TidyTests.cpp
  • tests/unit/Compiler/ToolchainTests.cpp
  • tests/unit/Test/Tester.cpp

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@clice-io clice-io deleted a comment from vercel Bot Jan 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dee5e13 and 7849110.

📒 Files selected for processing (18)
  • include/Compiler/Compilation.h
  • include/Compiler/CompilationUnit.h
  • src/Compiler/Compilation.cpp
  • src/Compiler/CompilationUnit.cpp
  • src/Compiler/CompilationUnitImpl.h
  • src/Compiler/Module.cpp
  • src/Feature/CodeCompletion.cpp
  • src/Feature/SignatureHelp.cpp
  • src/Index/TUIndex.cpp
  • src/Index/USRGeneration.cpp
  • src/Server/Document.cpp
  • src/Server/Indexer.cpp
  • tests/unit/Compiler/DiagnosticTests.cpp
  • tests/unit/Compiler/ModuleTests.cpp
  • tests/unit/Compiler/PreambleTests.cpp
  • tests/unit/Compiler/TidyTests.cpp
  • tests/unit/Compiler/ToolchainTests.cpp
  • tests/unit/Test/Tester.cpp
🧰 Additional context used
🧬 Code graph analysis (10)
src/Server/Document.cpp (3)
src/Feature/DocumentLink.cpp (2)
  • document_links (11-40)
  • document_links (11-11)
src/Compiler/CompilationUnit.cpp (2)
  • diagnostics (227-229)
  • diagnostics (227-227)
src/Feature/Diagnostic.cpp (2)
  • diagnostics (9-121)
  • diagnostics (9-9)
tests/unit/Compiler/DiagnosticTests.cpp (1)
src/Compiler/Compilation.cpp (6)
  • compile (357-362)
  • compile (357-357)
  • compile (364-391)
  • compile (364-364)
  • compile (393-413)
  • compile (393-393)
src/Feature/SignatureHelp.cpp (1)
src/Compiler/Compilation.cpp (2)
  • complete (415-442)
  • complete (415-415)
src/Index/TUIndex.cpp (1)
src/Index/MergedIndex.cpp (2)
  • relation (60-65)
  • relation (60-60)
include/Compiler/CompilationUnit.h (1)
src/Compiler/CompilationUnit.cpp (4)
  • success (20-22)
  • success (20-20)
  • error (24-26)
  • error (24-24)
src/Server/Indexer.cpp (1)
src/Index/TUIndex.cpp (2)
  • build (169-177)
  • build (169-169)
src/Compiler/Compilation.cpp (2)
src/Compiler/CompilationUnit.cpp (6)
  • diagnostics (227-229)
  • diagnostics (227-227)
  • error (24-26)
  • error (24-24)
  • build_at (235-237)
  • build_at (235-235)
src/Compiler/Directive.cpp (2)
  • attach (265-268)
  • attach (265-266)
include/Compiler/Compilation.h (2)
src/Compiler/Compilation.cpp (10)
  • preprocess (353-355)
  • preprocess (353-353)
  • compile (357-362)
  • compile (357-357)
  • compile (364-391)
  • compile (364-364)
  • compile (393-413)
  • compile (393-393)
  • complete (415-442)
  • complete (415-415)
tests/unit/Test/Tester.cpp (2)
  • compile (30-44)
  • compile (30-30)
src/Feature/CodeCompletion.cpp (1)
src/Compiler/Compilation.cpp (2)
  • complete (415-442)
  • complete (415-415)
tests/unit/Compiler/ModuleTests.cpp (2)
src/Compiler/Compilation.cpp (6)
  • compile (357-362)
  • compile (357-357)
  • compile (364-391)
  • compile (364-364)
  • compile (393-413)
  • compile (393-393)
tests/unit/Test/Tester.cpp (2)
  • compile (30-44)
  • compile (30-30)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: xmake / build (macos-15, debug)
  • GitHub Check: xmake / build (macos-15, releasedbg)
  • GitHub Check: cmake / build (macos-15, Debug)
  • GitHub Check: xmake / build (windows-2025, releasedbg)
  • GitHub Check: xmake / build (ubuntu-24.04, releasedbg)
  • GitHub Check: cmake / build (ubuntu-24.04, Debug)
  • GitHub Check: xmake / build (ubuntu-24.04, debug)
  • GitHub Check: clice / publish-clice (windows-2025, clice.zip, clice-x64-windows-msvc.zip, clice-symbol.zip, clice-x64-w...
  • GitHub Check: cmake / build (windows-2025, RelWithDebInfo)
  • GitHub Check: clice / publish-clice (macos-15, clice.tar.gz, clice-arm64-macos-darwin.tar.gz, clice-symbol.tar.gz, clic...
🔇 Additional comments (32)
src/Index/USRGeneration.cpp (1)

788-794: Good defensive fix to prevent null dereference.

The additional null check prevents a crash when hasTypeConstraint() returns true but getTypeConstraint() returns null. The FIXME comment indicates this is a workaround for an underlying inconsistency in the AST API.

Consider investigating why hasTypeConstraint() and getTypeConstraint() can be inconsistent—this should ideally be fixed at the source in the Clang AST implementation rather than guarded at each call site. No other unguarded uses of getTypeConstraint() were found in the file.

include/Compiler/Compilation.h (1)

66-80: LGTM! Clean API refactor.

The return type changes from CompilationResult to CompilationUnit are consistent across all five function declarations and align with the PR's objective to eliminate std::expected-based error handling in favor of success() and error() methods on CompilationUnit.

src/Feature/SignatureHelp.cpp (1)

206-209: LGTM! Correct API usage.

The code properly uses the new unit.success() API to check compilation status. The FIXME comment appropriately indicates that actual error handling is deferred for future implementation.

src/Server/Indexer.cpp (1)

14-14: LGTM! Proper API migration.

The changes correctly adopt the new CompilationUnit API:

  • Error checking uses unit.success()
  • Error messages accessed via unit.error()
  • Unit passed directly to TUIndex::build() instead of being dereferenced

The designated initializer syntax on line 14 is also a nice touch for clarity.

Also applies to: 28-33

src/Server/Document.cpp (2)

216-221: LGTM! Proper error handling in PCH build.

The PCH compilation result is correctly checked using unit.success(), error messages are extracted via unit.error(), and the unit is passed directly to document_links() without dereferencing.


330-352: LGTM! Consistent API usage in AST build.

The AST compilation result handling correctly mirrors the PCH pattern:

  • Status checked with ast.success()
  • Errors logged using ast.error()
  • AST passed directly to diagnostics() and moved without dereferencing

All changes align with the new CompilationUnit API.

tests/unit/Compiler/TidyTests.cpp (1)

26-27: LGTM! Test correctly updated for new API.

The test properly migrates from optional-like semantics (has_value(), operator->) to the new direct value API (success(), direct member access). The test logic remains unchanged.

tests/unit/Test/Tester.cpp (2)

34-34: LGTM! API migration correctly implemented.

The changes correctly adapt to the new CompilationUnit API: explicit success check via success() method and direct move semantics without dereferencing.

Also applies to: 42-42


83-83: LGTM! Consistent API migration.

The same API migration pattern is correctly applied in compile_with_pch(), maintaining consistency with the compile() method.

Also applies to: 107-107, 115-115

include/Compiler/CompilationUnit.h (1)

55-58: LGTM! Clean and explicit API design.

The new success() and error() accessors provide a clear, explicit interface for checking compilation status. Returning std::string by value for error() is a reasonable trade-off—it avoids lifetime issues at the cost of a copy on error paths, which are not performance-critical.

tests/unit/Compiler/ModuleTests.cpp (1)

30-30: LGTM! Test helper correctly updated.

The explicit success() check aligns with the new API and makes the test setup logic clear.

src/Feature/CodeCompletion.cpp (1)

435-436: LGTM! Appropriate error handling for code completion.

The variable rename from info to unit better reflects the actual type. The explicit success() check aligns with the new API. The TODO for error handling is appropriate—returning an empty completion list on failure provides graceful degradation for the user.

tests/unit/Compiler/ToolchainTests.cpp (2)

76-77: LGTM! API migration is correct.

The test correctly migrates to the new CompilationUnit API using success() for status checks and direct member access for diagnostics.


115-116: LGTM! Consistent API migration.

The Clang test case correctly adopts the same API pattern as the GCC test.

src/Compiler/Module.cpp (2)

109-111: LGTM! Correct error handling with new API.

The error path correctly checks unit.success() and propagates the error message via unit.error() using std::unexpected.


113-118: LGTM! Consistent API migration.

All access patterns correctly migrated from pointer-like (unit->...) to direct value access (unit....).

src/Compiler/CompilationUnitImpl.h (1)

15-15: LGTM! Error message storage added.

The error_message field appropriately stores error state for the new API's error() method.

src/Index/TUIndex.cpp (3)

78-78: LGTM! Variable naming convention improved.

The rename to relation_range follows the codebase's snake_case convention.


93-93: LGTM! Consistent variable usage.

Correctly updated to use the renamed relation_range variable.


100-100: LGTM! Consistent variable usage.

Correctly updated to use the renamed relation_range variable.

tests/unit/Compiler/PreambleTests.cpp (5)

71-71: LGTM! API migration correct.

The test correctly uses unit.success() to verify successful PCH compilation.


86-86: LGTM! Consistent API usage.

Correctly verifies successful compilation with PCH using the new API.


187-202: LGTM! Complete API migration.

All access patterns correctly migrated from pointer-like (unit->file_id(), unit->include_location()) to direct value access (unit.file_id(), unit.include_location()). The preprocessing success check is also properly updated.


256-256: LGTM! Consistent test update.

Correctly uses the new success() method in the chain test.


271-271: LGTM! Final verification correct.

The final step of the chain test correctly verifies compilation success with the new API.

src/Compiler/CompilationUnit.cpp (2)

28-35: LGTM!

The pointer-based access to src_mgr is consistent with the new Impl design.


309-314: Good defensive check added.

Adding include.fid.isValid() before inserting into all_files is a sensible guard against invalid file IDs.

src/Compiler/Compilation.cpp (5)

200-228: LGTM on the refactored run_clang structure.

The refactor cleanly centralizes error handling through impl->error_message. The early creation of impl and unit allows consistent error returns throughout the function.


240-242: Consistent error handling pattern.

All error paths correctly populate impl->error_message and return the unit early. Since impl->instance remains null on error paths, success() will correctly return false.

Also applies to: 258-260, 285-287, 294-298, 303-306


339-348: LGTM on state assignment.

The ordering correctly captures the SourceManager pointer before moving instance. The raw pointer to src_mgr is safe as it's owned by the CompilerInstance stored in impl->instance.


353-362: Clean API transition.

The public functions now return CompilationUnit directly, aligning with the simplified error-handling model.


415-442: LGTM!

The complete() function correctly adapts to the new return type while maintaining its code-completion setup logic.

Comment thread src/Compiler/CompilationUnit.cpp Outdated
Comment thread src/Compiler/CompilationUnitImpl.h Outdated
Comment thread src/Index/TUIndex.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
pixi.toml (1)

88-104: Consider moving unit-test to feature.test.tasks for consistency.

The unit-test task (line 88-90) remains under [feature.build.tasks] while integration-test and test have been moved to [feature.test.tasks]. For organizational clarity and consistency, consider moving unit-test under feature.test as well, since all three are test-related tasks.

That said, if unit-test intentionally stays under feature.build because it only needs build dependencies (not pytest), the current structure is functionally correct since the default environment includes both features.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1496c75 and daaabd5.

⛔ Files ignored due to path filters (1)
  • pixi.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • .github/workflows/publish-clice.yml
  • docs/en/dev/build.md
  • docs/zh/dev/build.md
  • include/Compiler/Compilation.h
  • include/Server/Server.h
  • pixi.toml
  • src/Compiler/Compilation.cpp
  • src/Server/Document.cpp
  • tests/unit/Test/Tester.cpp
💤 Files with no reviewable changes (1)
  • include/Server/Server.h
✅ Files skipped from review due to trivial changes (1)
  • docs/zh/dev/build.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/publish-clice.yml
  • include/Compiler/Compilation.h
  • tests/unit/Test/Tester.cpp
🧰 Additional context used
🧬 Code graph analysis (2)
src/Compiler/Compilation.cpp (2)
src/Compiler/CompilationUnit.cpp (6)
  • build_at (235-237)
  • build_at (235-235)
  • diagnostics (227-229)
  • diagnostics (227-227)
  • error (24-26)
  • error (24-24)
src/Compiler/Directive.cpp (2)
  • attach (265-268)
  • attach (265-266)
src/Server/Document.cpp (2)
src/Compiler/CompilationUnit.cpp (4)
  • success (20-22)
  • success (20-20)
  • diagnostics (227-229)
  • diagnostics (227-227)
src/Feature/Diagnostic.cpp (2)
  • diagnostics (9-121)
  • diagnostics (9-9)
🪛 Cppcheck (2.19.0)
src/Server/Document.cpp

[error] 208-208: Uninitialized variable

(uninitvar)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: xmake / build (ubuntu-24.04, debug)
  • GitHub Check: xmake / build (ubuntu-24.04, releasedbg)
  • GitHub Check: xmake / build (macos-15, releasedbg)
  • GitHub Check: xmake / build (windows-2025, releasedbg)
  • GitHub Check: cmake / build (windows-2025, RelWithDebInfo)
  • GitHub Check: clice / publish-clice (ubuntu-24.04, clice.tar.gz, clice-x86_64-linux-gnu.tar.gz, clice-symbol.tar.gz, cl...
  • GitHub Check: xmake / build (macos-15, debug)
  • GitHub Check: clice / publish-clice (macos-15, clice.tar.gz, clice-arm64-macos-darwin.tar.gz, clice-symbol.tar.gz, clic...
  • GitHub Check: clice / publish-clice (windows-2025, clice.zip, clice-x64-windows-msvc.zip, clice-symbol.zip, clice-x64-w...
  • GitHub Check: cmake / build (macos-15, Debug)
  • GitHub Check: cmake / build (ubuntu-24.04, Debug)
🔇 Additional comments (12)
docs/en/dev/build.md (1)

33-33: LGTM!

The simplified command aligns with the updated pixi.toml configuration where the default environment now includes both build and test features, making the explicit -e develop flag unnecessary.

pixi.toml (3)

1-2: LGTM!

The tombi format directive to disable table-keys-order formatting is a reasonable configuration choice that allows maintainers to organize TOML sections in a logical order rather than alphabetical.


19-23: LGTM!

Including test in the default environment ensures developers have access to testing dependencies (pytest, pytest-asyncio) without needing to specify a separate environment. This aligns well with the documentation update to use pixi shell without flags.


139-157: LGTM!

Placing these helper tasks under the global [tasks] namespace (rather than feature-specific sections) makes them available across all environments, which is appropriate for utility tasks like build-llvm, upload-llvm, and delete-artifacts.

src/Compiler/Compilation.cpp (3)

341-344: Pointer assignment ordering is correct.

impl->src_mgr is assigned while instance is still valid, then instance is moved into impl->instance. The SourceManager remains valid since it's owned by the CompilerInstance now stored in impl->instance.


352-361: Function signatures consistently updated to return CompilationUnit.

Both preprocess and compile now return CompilationUnit directly, aligning with the new API surface.


200-227: LGTM! The refactored error handling and ownership model looks solid.

The function now returns CompilationUnit directly with error state encapsulated in Impl. The flow correctly creates the unit early, allowing all error paths to set impl->error_message and return the partially-constructed unit. The CompilationUnit class properly takes ownership of the raw impl pointer—the constructor stores it, the move constructor transfers ownership with proper nullification, copy is deleted to prevent double-deletion, and the destructor correctly deletes the pointer.

src/Server/Document.cpp (5)

173-179: Signature simplification looks good.

Removing the diagnostics parameter in favor of accessing them via unit.diagnostics() is cleaner and aligns with the unit-based error handling pattern.


208-226: The static analysis warning is a false positive.

Cppcheck reports "Uninitialized variable" at line 208, but all captured variables (params, pch, message, links, path) are properly initialized before the lambda executes. This is likely Cppcheck struggling with coroutine/lambda interactions.

The co_await ensures the lambda completes before the coroutine continues, so captured references remain valid throughout execution.

One minor observation: on line 212, std::move(unit.error()) is redundant since error() returns std::string by value (already an rvalue), but it's harmless.


320-328: LGTM! Consistent use of the new unit-based API.

The error handling correctly uses unit.success(), unit.error(), and unit.diagnostics() matching the refactored pattern.


331-337: Diagnostics generation updated correctly.

Using feature::diagnostics(kind, mapping, unit) aligns with the relevant code snippet showing the function signature expects a CompilationUnit&.


343-343: Move into shared_ptr is appropriate.

Creating a shared_ptr from a moved CompilationUnit properly transfers ownership for shared access to the AST.

@16bit-ykiko 16bit-ykiko changed the title refactor: compilation result refactor: diagnostic handling Jan 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Compiler/CompilationUnit.cpp (1)

46-47: Incorrect assertion condition.

Line 47 checks end.isValid() but the message says "Input source range should be a file range". This should likely check end.isFileID() instead. Also, begin.isValid() is already checked on line 46, so end.isValid() is redundant there.

🔎 Proposed fix
     assert(begin.isValid() && end.isValid() && "Invalid source range");
-    assert(begin.isFileID() && end.isValid() && "Input source range should be a file range");
+    assert(begin.isFileID() && end.isFileID() && "Input source range should be a file range");
♻️ Duplicate comments (1)
src/Compiler/CompilationUnit.cpp (1)

20-26: Null pointer dereference risk remains unaddressed.

The past review comment correctly identified that success() and error() dereference self without null checks. Since the move constructor sets other.self = nullptr (line 209 in header), and the destructor guards with if(self && ...), calling these methods on a moved-from object will crash.

🔎 Proposed fix
-bool CompilationUnitRef::success() {
-    return self->instance != nullptr;
+bool CompilationUnitRef::success() const {
+    return self && self->instance != nullptr;
 }

-std::string CompilationUnitRef::error() {
-    return self->error_message;
+std::string CompilationUnitRef::error() const {
+    return self ? self->error_message : std::string{};
 }
🧹 Nitpick comments (3)
include/Compiler/CompilationUnit.h (2)

41-44: Consider adding const qualifiers to accessor methods.

success() and error() are query methods that don't modify state and should be marked const. This allows calling them on const references and communicates intent.

🔎 Proposed fix
 public:
-    bool success();
+    bool success() const;

-    std::string error();
+    std::string error() const;

204-204: Reorder member initializer list to match initialization order.

Base classes are initialized before members in C++. The current order (kind(kind), CompilationUnitRef(impl)) is misleading and will trigger -Wreorder warnings on most compilers.

🔎 Proposed fix
-    CompilationUnit(Kind kind, Self* impl) : kind(kind), CompilationUnitRef(impl) {}
+    CompilationUnit(Kind kind, Self* impl) : CompilationUnitRef(impl), kind(kind) {}
src/Compiler/CompilationUnit.cpp (1)

269-271: Variable shadowing reduces readability.

The loop variable deps shadows the outer deps StringSet. While this works, it's confusing and error-prone if the code is later modified.

🔎 Proposed fix
-    for(auto& deps: deps) {
-        result.emplace_back(deps.getKey().str());
+    for(auto& entry: deps) {
+        result.emplace_back(entry.getKey().str());
     }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between daaabd5 and 88d1fef.

📒 Files selected for processing (11)
  • include/Compiler/CompilationUnit.h
  • include/Compiler/Diagnostic.h
  • include/Compiler/Tidy.h
  • src/Compiler/Compilation.cpp
  • src/Compiler/CompilationUnit.cpp
  • src/Compiler/CompilationUnitImpl.h
  • src/Compiler/Diagnostic.cpp
  • src/Compiler/Implement.h
  • src/Compiler/Tidy.cpp
  • src/Compiler/TidyImpl.h
  • tests/unit/Compiler/TidyTests.cpp
💤 Files with no reviewable changes (3)
  • src/Compiler/TidyImpl.h
  • src/Compiler/CompilationUnitImpl.h
  • include/Compiler/Tidy.h
🧰 Additional context used
🧬 Code graph analysis (3)
include/Compiler/CompilationUnit.h (2)
src/Compiler/CompilationUnit.cpp (7)
  • success (20-22)
  • success (20-20)
  • error (24-26)
  • error (24-24)
  • diagnostics (228-230)
  • diagnostics (228-228)
  • CompilationUnit (7-18)
src/Compiler/Implement.h (1)
  • Self (66-109)
src/Compiler/Compilation.cpp (3)
src/Compiler/CompilationUnit.cpp (4)
  • build_at (236-238)
  • build_at (236-236)
  • error (24-26)
  • error (24-24)
src/Compiler/Diagnostic.cpp (2)
  • create_diagnostic (259-261)
  • create_diagnostic (259-259)
src/Compiler/Directive.cpp (2)
  • attach (265-268)
  • attach (265-266)
src/Compiler/CompilationUnit.cpp (1)
include/Compiler/CompilationUnit.h (1)
  • interested_content (83-216)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: cmake / build (macos-15, Debug)
  • GitHub Check: xmake / build (macos-15, releasedbg)
  • GitHub Check: clice / publish-clice (macos-15, clice.tar.gz, clice-arm64-macos-darwin.tar.gz, clice-symbol.tar.gz, clic...
  • GitHub Check: xmake / build (ubuntu-24.04, debug)
  • GitHub Check: xmake / build (ubuntu-24.04, releasedbg)
  • GitHub Check: clice / publish-clice (ubuntu-24.04, clice.tar.gz, clice-x86_64-linux-gnu.tar.gz, clice-symbol.tar.gz, cl...
  • GitHub Check: xmake / build (macos-15, debug)
  • GitHub Check: clice / publish-clice (windows-2025, clice.zip, clice-x64-windows-msvc.zip, clice-symbol.zip, clice-x64-w...
  • GitHub Check: xmake / build (windows-2025, releasedbg)
  • GitHub Check: cmake / build (windows-2025, RelWithDebInfo)
  • GitHub Check: cmake / build (ubuntu-24.04, Debug)
🔇 Additional comments (18)
include/Compiler/Diagnostic.h (1)

12-13: LGTM: Clean forward declaration.

The forward declaration reduces header coupling and aligns with the refactored diagnostic handling that now uses CompilationUnitRef.

src/Compiler/Tidy.cpp (1)

1-1: LGTM: Header consolidation.

The include refactoring to Implement.h aligns with the broader reorganization of the compilation unit implementation surface.

tests/unit/Compiler/TidyTests.cpp (1)

25-26: LGTM: Correct API usage.

The changes correctly use the new CompilationUnit API with success() to check compilation status and direct access to diagnostics() instead of the previous optional-style access.

src/Compiler/Diagnostic.cpp (4)

3-3: LGTM: Header consolidation.

Consistent with the refactoring to consolidate implementation headers into Implement.h.


206-215: LGTM: Improved ownership model.

The refactoring from shared pointer ownership to CompilationUnitRef-based storage provides clearer ownership semantics and aligns with the new ref-driven diagnostic collection model.


254-254: LGTM: Member type updated consistently.

The private member type change aligns with the constructor refactoring and the new diagnostic ownership model.


259-261: LGTM: Factory function signature updated.

The factory function signature correctly reflects the new CompilationUnitRef-based API.

src/Compiler/Compilation.cpp (6)

3-3: LGTM: Header consolidation.

Consistent with the refactoring to consolidate implementation details into Implement.h.


221-222: LGTM: Consistent error handling pattern.

The error handling consistently sets self->error_message and returns the unit object instead of using std::unexpected. This aligns well with the new API where unit.success() checks compilation status and unit.error() retrieves error messages.

Also applies to: 235-236, 253-254, 280-281, 291-292, 299-300


248-249: LGTM: Centralized state management.

Moving all compilation state (top-level declarations, directives, buffer, resolver, build timing, and instance) into the Self object provides a clean, centralized state management approach that can be accessed through CompilationUnitRef.

Also applies to: 271-271, 304-304, 311-311, 324-324, 333-339


208-208: LGTM: Updated diagnostic creation.

The call to create_diagnostic(self) correctly uses the refactored API where diagnostics are collected directly into the CompilationUnitRef instead of a separate shared vector.


347-407: LGTM: Public API refactored consistently.

All public compilation functions (preprocess, compile overloads, and complete) now return CompilationUnit instead of a result-style type. This provides a cleaner, value-based API where callers use success() and error() accessors to check compilation status.


198-207: No action needed. The CompilationUnit class properly manages the Self* pointer through RAII: the constructor takes ownership, the destructor explicitly deletes it (line 17 in src/Compiler/CompilationUnit.cpp), and move semantics are correctly implemented to prevent double deletion.

include/Compiler/CompilationUnit.h (1)

206-210: LGTM!

The deleted copy constructor and move constructor correctly implement move-only semantics, properly transferring ownership of self and nullifying the source to prevent double-deletion.

src/Compiler/CompilationUnit.cpp (2)

7-18: LGTM!

The destructor correctly guards against null self, properly manages the preprocessor lifecycle by detaching before EndSourceFile(), and ensures cleanup with delete self.


328-331: LGTM!

The assertion correctly validates that the TemplateResolver is available before dereferencing. Similar defensive checks are consistently applied across other optional members.

src/Compiler/Implement.h (2)

27-41: LGTM!

The ClangTidyChecker class properly encapsulates the clang-tidy integration components. Public members are acceptable here as this appears to be a configuration/state holder used internally.


111-116: LGTM!

The DiagnosticCollector follows a clean factory pattern with create_diagnostic(). The class properly inherits from clang::DiagnosticConsumer and maintains a pointer to the checker for adjusting diagnostic levels.

Comment thread src/Compiler/Implement.h
Comment thread src/Compiler/Implement.h Outdated
Comment thread tests/unit/Compiler/TidyTests.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
include/Compiler/CompilationUnit.h (1)

37-37: Empty enum CompilationStatus appears unused.

This enum is declared but has no enumerators and is not referenced elsewhere in this file. If this is intended for future use, consider adding a TODO comment explaining its purpose. Otherwise, it may be dead code.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88d1fef and d6109c2.

📒 Files selected for processing (8)
  • include/Compiler/Compilation.h
  • include/Compiler/CompilationUnit.h
  • include/Compiler/Diagnostic.h
  • src/Compiler/Compilation.cpp
  • src/Server/Document.cpp
  • src/Server/Feature.cpp
  • src/Server/Indexer.cpp
  • tests/unit/Test/Tester.cpp
💤 Files with no reviewable changes (1)
  • include/Compiler/Diagnostic.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/Test/Tester.cpp
🧰 Additional context used
🧬 Code graph analysis (2)
src/Server/Document.cpp (2)
src/Compiler/CompilationUnit.cpp (4)
  • success (20-22)
  • success (20-20)
  • diagnostics (228-230)
  • diagnostics (228-228)
src/Feature/Diagnostic.cpp (2)
  • diagnostics (9-121)
  • diagnostics (9-9)
src/Server/Indexer.cpp (1)
src/Index/TUIndex.cpp (2)
  • build (169-177)
  • build (169-169)
🪛 Cppcheck (2.19.0)
src/Server/Document.cpp

[error] 208-208: Uninitialized variable

(uninitvar)


[error] 312-312: Found an exit path from function with non-void return type that has missing return statement

(missingReturn)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: xmake / build (macos-15, debug)
  • GitHub Check: xmake / build (ubuntu-24.04, releasedbg)
  • GitHub Check: xmake / build (macos-15, releasedbg)
  • GitHub Check: xmake / build (ubuntu-24.04, debug)
  • GitHub Check: clice / publish-clice (ubuntu-24.04, clice.tar.gz, clice-x86_64-linux-gnu.tar.gz, clice-symbol.tar.gz, cl...
  • GitHub Check: clice / publish-clice (macos-15, clice.tar.gz, clice-arm64-macos-darwin.tar.gz, clice-symbol.tar.gz, clic...
  • GitHub Check: cmake / build (windows-2025, RelWithDebInfo)
  • GitHub Check: cmake / build (macos-15, Debug)
  • GitHub Check: xmake / build (windows-2025, releasedbg)
  • GitHub Check: cmake / build (ubuntu-24.04, Debug)
  • GitHub Check: clice / publish-clice (windows-2025, clice.zip, clice-x64-windows-msvc.zip, clice-symbol.zip, clice-x64-w...
🔇 Additional comments (17)
src/Compiler/Compilation.cpp (4)

198-223: LGTM on the refactored run_clang entry and error handling.

The function correctly initializes CompilationUnitRef::Self via raw allocation and wraps it in CompilationUnit. Error cases consistently populate self->error_message before returning the unit. The ownership transfer is handled properly via the CompilationUnit constructor.


245-255: LGTM on ProxyAction setup and source file handling.

The conditional for collecting top-level declarations correctly checks both clang_tidy and CompilationKind::Content, and error paths consistently set self->error_message before returning.


332-343: LGTM on final state population.

Build timing metrics, source manager references, and action/instance ownership are properly transferred to self before returning the unit.


347-356: LGTM on public API wrappers.

preprocess and compile correctly delegate to run_clang with the appropriate action types and return CompilationUnit consistently.

include/Compiler/CompilationUnit.h (2)

199-209: LGTM on the CompilationUnit class design.

The move constructor correctly transfers ownership by moving self and nullifying the source's pointer. The deleted copy constructor prevents accidental copies. The member initializer order in the primary constructor (line 201) is correct since base classes are always initialized before members regardless of the textual order.


189-196: LGTM on the CompilationUnitRef design.

The forward-declared Self struct with protected pointer member provides a clean separation between the public interface and implementation details.

src/Server/Feature.cpp (2)

32-38: LGTM on CompilationKind enum migration.

The change from CompilationUnit::Completion to CompilationKind::Completion correctly aligns with the refactored enum location.


90-96: LGTM on signature help enum update.

Consistent with the enum migration pattern applied in on_completion.

src/Server/Indexer.cpp (2)

11-14: LGTM on compilation params setup.

The enum migration to CompilationKind::Indexing and the addition of .query_toolchain = true are consistent with the broader refactor. The designated initializer syntax is clean.


26-34: LGTM on unit-based result handling.

The change from truthiness check to unit.success() and from TUIndex::build(*unit) to TUIndex::build(unit) correctly aligns with the new CompilationUnit value-based API.

include/Compiler/Compilation.h (2)

16-18: LGTM on CompilationParams update.

The kind member type migration to CompilationKind is consistent with the enum relocation.


62-77: LGTM on API return type changes.

The migration from CompilationResult (expected-style) to CompilationUnit (value-style with success()/error() accessors) simplifies the public API surface. All function signatures are updated consistently.

src/Server/Document.cpp (5)

174-179: LGTM on signature update for build_pch_task.

The removal of the diagnostics parameter aligns with the unit-based diagnostics model where diagnostics are accessed via unit.diagnostics() instead of being passed as a separate parameter.


208-226: LGTM on PCH build error handling.

The lambda correctly uses the unit-based API: unit.success() for status check, unit.error() for the error message, and unit.diagnostics() for iterating through diagnostics. The message variable referenced by cppcheck is initialized on line 205 before the lambda, so the static analysis warning is a false positive.


320-328: LGTM on AST build error handling.

Consistent with the PCH build path, using unit.success(), unit.error(), and unit.diagnostics() for error reporting. The static analysis warning about a missing return at line 312 is a false positive—this is a coroutine function with proper co_return statements.


331-343: LGTM on diagnostics publishing and AST storage.

The diagnostics are correctly generated via feature::diagnostics(kind, mapping, unit) and the AST is stored as std::make_shared<CompilationUnit>(std::move(unit)), properly transferring ownership.


277-278: LGTM on task creation update.

The build_pch_task call correctly omits the old diagnostics parameter and moves content ownership into the task.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Compiler/CompilationUnit.cpp (1)

11-324: Establish class invariant for self pointer.

Every method in this file unconditionally dereferences self without null checks. You have two options:

  1. Establish a class invariant: Document that self must never be null except in moved-from objects, and mark moved-from objects as unusable (either through assertions or by making methods check success() first).

  2. Add null checks everywhere: Check self in every method, which would be verbose but safer.

Given the design, option 1 seems more appropriate. Consider:

  • Adding assert(self) at the start of methods that require valid state
  • Documenting that methods must not be called on moved-from objects
  • Making the move constructor private or documenting the invariant clearly
♻️ Duplicate comments (2)
src/Compiler/CompilationUnit.cpp (1)

7-9: Critical: Null pointer dereference risk in success().

This issue was flagged in a previous review but remains unaddressed. The method dereferences self without a null check. Since the move constructor (line 205-207 in the header) sets other.self = nullptr, calling success() on a moved-from object will crash.

Additionally, this method should be const since it doesn't modify state.

🔎 Proposed fix
-bool CompilationUnitRef::success() {
+bool CompilationUnitRef::success() const {
+    return self && self->instance != nullptr;
-    return self->instance != nullptr;
 }

Also update the declaration in include/Compiler/CompilationUnit.h.

Based on past review comments.

src/Compiler/Implement.h (1)

20-20: Document the intended use of the empty TidyParams struct.

TidyParams is currently empty but is passed to configure() and configure_tidy(). Document whether this is a placeholder for future extension or if parameters will be added.

🧹 Nitpick comments (3)
include/Compiler/CompilationUnit.h (2)

37-37: Unused enum declaration.

CompilationStatus is declared but never used in the codebase. Consider removing it or documenting its intended future use.

🔎 Verify usage across the codebase
#!/bin/bash
# Search for any usage of CompilationStatus
rg -n "CompilationStatus" --type=cpp --type=h

163-163: Consider providing a const overload for diagnostics().

Returning a mutable reference prevents calling this method on const CompilationUnitRef objects. While the current non-const version is needed for building diagnostics, consider adding a const overload for read-only access:

auto diagnostics() const -> const std::vector<Diagnostic>&;

This would improve const-correctness throughout the API.

src/Compiler/Implement.h (1)

107-107: Resolve or track the TODO comment.

The TODO questions whether modifying the unit-level traversal scope is acceptable. This design decision should be resolved and documented, or tracked as a follow-up issue.

Do you want me to open a new issue to track this TODO?

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f71dbf8 and bf64d0a.

📒 Files selected for processing (8)
  • .gitignore
  • include/Compiler/CompilationUnit.h
  • include/Compiler/Directive.h
  • src/Compiler/Compilation.cpp
  • src/Compiler/CompilationUnit.cpp
  • src/Compiler/Diagnostic.cpp
  • src/Compiler/Directive.cpp
  • src/Compiler/Implement.h
💤 Files with no reviewable changes (1)
  • include/Compiler/Directive.h
🧰 Additional context used
🧬 Code graph analysis (3)
src/Compiler/Compilation.cpp (2)
src/Compiler/Diagnostic.cpp (2)
  • create_diagnostic (252-254)
  • create_diagnostic (252-252)
src/Compiler/CompilationUnit.cpp (3)
  • success (7-9)
  • success (7-7)
  • CompilationUnit (322-324)
src/Compiler/Directive.cpp (1)
src/Compiler/Compilation.cpp (2)
  • instance (79-86)
  • instance (79-80)
src/Compiler/Diagnostic.cpp (2)
tests/unit/Test/Tester.cpp (2)
  • range (138-151)
  • range (138-138)
include/AST/SourceCode.h (1)
  • range (71-95)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: xmake / build (windows-2025, releasedbg)
  • GitHub Check: cmake / build (ubuntu-24.04, Debug)
  • GitHub Check: xmake / build (macos-15, debug)
  • GitHub Check: xmake / build (ubuntu-24.04, releasedbg)
  • GitHub Check: xmake / build (ubuntu-24.04, debug)
  • GitHub Check: xmake / build (macos-15, releasedbg)
  • GitHub Check: clice / publish-clice (macos-15, clice.tar.gz, clice-arm64-macos-darwin.tar.gz, clice-symbol.tar.gz, clic...
  • GitHub Check: cmake / build (windows-2025, RelWithDebInfo)
  • GitHub Check: clice / publish-clice (windows-2025, clice.zip, clice-x64-windows-msvc.zip, clice-symbol.zip, clice-x64-w...
  • GitHub Check: cmake / build (macos-15, Debug)
  • GitHub Check: clice / publish-clice (ubuntu-24.04, clice.tar.gz, clice-x86_64-linux-gnu.tar.gz, clice-symbol.tar.gz, cl...
🔇 Additional comments (8)
.gitignore (1)

63-63: LGTM!

Adding .clangd to the IDE/Editors section is appropriate—it ignores the clang language server cache directory. Placement and format are consistent with surrounding entries.

src/Compiler/Directive.cpp (1)

267-270: LGTM - Clean refactoring to unit-centric design.

The migration from a free function to a member function of CompilationUnitRef::Self properly encapsulates directive collection within the compilation unit's lifecycle. The Preprocessor is now obtained from the unit's instance rather than passed as a parameter, which aligns well with the overall refactoring goals.

src/Compiler/Diagnostic.cpp (2)

153-203: LGTM - Improved encapsulation of diagnostic range computation.

The refactoring of diagnostic_range into a member function of DiagnosticCollector that uses the unit's context is a good design improvement. This eliminates the need to pass LangOptions as a parameter and ensures consistent access to location information through the unit's interface.


207-244: Add null safety guard to CompilationUnitRef::operator->().

The operator->() returns self directly without null validation. Since move semantics allow self to be nullptr, this creates undefined behavior risk. Add a runtime check or assert in operator->(), or alternatively add a null check guard before any use of unit-> in HandleDiagnostic (lines 213, 238). At minimum, ensure the DiagnosticCollector constructor validates that unit.self is not null.

src/Compiler/Compilation.cpp (2)

140-148: Good practice: Explicit memory management with clear ownership.

Setting RetainRemappedFileBuffers = true and transferring ownership to self.remapped_buffers ensures deterministic cleanup. The comment clearly explains why this is necessary (CompilerInstance doesn't reliably clear these buffers, especially on early abort).


161-177: Essential safeguard: Disabling side-effect output options.

Explicitly disabling help, stats, version, time-trace, and other output options is critical for LSP operation. These outputs would corrupt the JSON-RPC transport if written to stdout/stderr. Well done.

src/Compiler/CompilationUnit.cpp (1)

322-324: LGTM - Proper cleanup in destructor.

The destructor correctly deletes self, completing the ownership pattern established in Compilation.cpp where Self* is allocated with new and transferred to CompilationUnit.

src/Compiler/Implement.h (1)

119-128: Destructor logic is correctly implemented and well-documented.

The pattern of calling instance->getPreprocessor().EndSourceFile() in run_tidy() (line 115) and then detaching the preprocessor before action->EndSourceFile() in the destructor (lines 125-126) is intentional design, not fragility. The code explicitly documents the clang lifecycle requirements:

  • run_tidy() already notifies the preprocessor of EOF to flush diagnostics without destroying ASTContext (lines 112-115)
  • The destructor keeps the preprocessor alive via shared_ptr to satisfy Sema's requirements during EndSourceFile() (line 123)
  • Detaching the preprocessor (line 125) prevents double EOF notification
  • The ordering constraint is explained in the comments (lines 103, 121-122)

The same pattern appears consistently in Compilation.cpp where EndSourceFile() is called early in error paths before action reset. This is a well-reasoned approach to clang's documented lifecycle, not an undocumented fragile dependency.

Comment thread include/Compiler/CompilationUnit.h Outdated
Comment thread src/Compiler/Compilation.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
src/Compiler/Implement.h (2)

14-14: Avoid using namespace in header files.

This issue was already flagged in a previous review. The using namespace clang::tidy; directive in a header pollutes the global namespace for all translation units that include this file.


75-76: Typo in comment.

This was already noted in a previous review: "diretive" should be "directive".

src/Compiler/Compilation.cpp (1)

318-339: Exception safety concern with raw new - previously flagged.

The raw new at line 322 without RAII protection was already identified in a past review. If an exception occurs before line 338, the Self* will leak. Consider using std::unique_ptr as suggested in the previous review.

src/Compiler/CompilationUnit.cpp (1)

7-13: Accessors should have const qualifiers.

The kind() and status() methods are read-only accessors and should be marked const. This was flagged in a previous review.

🧹 Nitpick comments (2)
src/Server/Document.cpp (1)

318-326: Consider enabling diagnostic logging on AST build failure.

The error logging at lines 321-324 is commented out. Unlike PCH builds where diagnostics are logged (lines 214-216), AST build failures silently return without any diagnostic information. Consider enabling similar logging for consistency and debugging purposes.

     if(!unit.completed()) {
         /// FIXME: Fails needs cancel waiting tasks.
-        /// LOG_ERROR("Building AST fails for {}, Beacuse: {}", path, unit.error());
-        /// for(auto& diagnostic: unit.diagnostics()) {
-        ///     LOG_ERROR("{}", diagnostic.message);
-        /// }
+        LOG_ERROR("Building AST fails for {}", path);
+        for(auto& diagnostic: unit.diagnostics()) {
+            LOG_ERROR("{}", diagnostic.message);
+        }
         co_return;
     }
include/Compiler/CompilationUnit.h (1)

44-79: Consider adding const qualifiers to status query methods.

The status query methods (kind(), status(), completed(), cancelled(), setup_fail(), fatal_error()) don't modify state and should be const for proper const-correctness. This enables calling these methods on const references.

🔎 Proposed fix
-    CompilationKind kind();
+    CompilationKind kind() const;

-    CompilationStatus status();
+    CompilationStatus status() const;

     /// Parse finished; ASTContext is usable but diagnostics may still contain errors.
-    bool completed() {
+    bool completed() const {
         return status() == CompilationStatus::Completed;
     }

     /// Compilation was cancelled; consumers should not touch any state.
-    bool cancelled() {
+    bool cancelled() const {
         return status() == CompilationStatus::Cancelled;
     }

     /// Failed during initial setup; diagnostics exist (location-free), ASTContext
     /// is unavailable.
-    bool setup_fail() {
+    bool setup_fail() const {
         return status() == CompilationStatus::SetupFail;
     }

     /// Hit an unrecoverable error; diagnostics and decoded source locations
     /// are usable, other states are not unavailable.
-    bool fatal_error() {
+    bool fatal_error() const {
         return status() == CompilationStatus::FatalError;
     }

Based on past review comments highlighting const-correctness issues.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf64d0a and f3367d8.

📒 Files selected for processing (15)
  • include/Compiler/CompilationUnit.h
  • src/Compiler/Compilation.cpp
  • src/Compiler/CompilationUnit.cpp
  • src/Compiler/Implement.h
  • src/Compiler/Module.cpp
  • src/Feature/CodeCompletion.cpp
  • src/Feature/SignatureHelp.cpp
  • src/Server/Document.cpp
  • src/Server/Indexer.cpp
  • tests/unit/Compiler/DiagnosticTests.cpp
  • tests/unit/Compiler/ModuleTests.cpp
  • tests/unit/Compiler/PreambleTests.cpp
  • tests/unit/Compiler/TidyTests.cpp
  • tests/unit/Compiler/ToolchainTests.cpp
  • tests/unit/Test/Tester.cpp
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/unit/Compiler/TidyTests.cpp
  • src/Server/Indexer.cpp
  • tests/unit/Compiler/PreambleTests.cpp
  • tests/unit/Test/Tester.cpp
🧰 Additional context used
🧬 Code graph analysis (6)
src/Feature/CodeCompletion.cpp (1)
src/Compiler/Compilation.cpp (2)
  • complete (409-438)
  • complete (409-409)
src/Compiler/Compilation.cpp (2)
src/Compiler/Diagnostic.cpp (2)
  • create_diagnostic (252-254)
  • create_diagnostic (252-252)
src/Compiler/CompilationUnit.cpp (1)
  • CompilationUnit (326-328)
include/Compiler/CompilationUnit.h (2)
src/Compiler/Implement.h (1)
  • Self (55-99)
src/Compiler/CompilationUnit.cpp (7)
  • kind (7-9)
  • kind (7-7)
  • status (11-13)
  • status (11-11)
  • diagnostics (213-215)
  • diagnostics (213-213)
  • CompilationUnit (326-328)
src/Compiler/CompilationUnit.cpp (2)
src/Feature/SemanticToken.cpp (11)
  • location (93-116)
  • location (93-93)
  • fid (73-85)
  • fid (88-91)
  • fid (88-88)
  • fid (119-202)
  • fid (119-119)
  • tokens (214-240)
  • tokens (214-214)
  • decl (17-35)
  • decl (17-19)
include/Compiler/CompilationUnit.h (1)
  • interested_content (118-244)
src/Compiler/Implement.h (3)
include/Compiler/Directive.h (1)
  • clice (8-140)
src/Compiler/Tidy.cpp (9)
  • is_registered_tidy_check (23-40)
  • is_registered_tidy_check (23-23)
  • is_fast_tidy_check (42-54)
  • is_fast_tidy_check (42-42)
  • ClangTidyChecker (250-251)
  • adjust_level (253-291)
  • adjust_level (254-255)
  • adjust_diag (293-315)
  • adjust_diag (293-293)
include/Compiler/CompilationUnit.h (1)
  • CompilationUnitRef (44-246)
src/Feature/SignatureHelp.cpp (1)
src/Compiler/Compilation.cpp (2)
  • complete (409-438)
  • complete (409-409)
🪛 Cppcheck (2.19.0)
src/Server/Document.cpp

[error] 208-208: Uninitialized variable

(uninitvar)


[error] 312-312: Found an exit path from function with non-void return type that has missing return statement

(missingReturn)

🔇 Additional comments (20)
src/Feature/SignatureHelp.cpp (1)

206-209: LGTM!

The migration to the new CompilationUnit API is correct. The code now checks unit.completed() instead of relying on the previous truthiness-based pattern, which is clearer and more explicit about the unit's state.

src/Feature/CodeCompletion.cpp (1)

435-438: LGTM!

The change correctly adopts the new CompilationUnit API pattern, checking unit.completed() for success. This is consistent with the signature help implementation and the broader refactoring.

tests/unit/Compiler/ToolchainTests.cpp (1)

76-77: LGTM!

The test updates correctly reflect the new CompilationUnit API:

  • unit.completed() replaces the previous optional/pointer-style check
  • unit.diagnostics() uses direct value access instead of pointer dereference

These changes are consistent across both GCC and Clang test cases.

Also applies to: 115-116

src/Compiler/Implement.h (1)

108-121: The TODO about traversal scope side effects remains valid and unresolved.

Line 111 correctly raises a concern: setTraversalScope() modifies the ASTContext to restrict traversal to top_level_decls but is never reset. The scope remains restricted when the TemplateResolver is instantiated immediately after at line 310 in Compilation.cpp. Whether this affects the resolver's ability to perform semantic resolution depends on Clang's API semantics, which cannot be determined from code inspection alone. The concern merits either clarification in a follow-up comment or explicit scope restoration before resolver instantiation.

tests/unit/Compiler/ModuleTests.cpp (1)

29-33: LGTM!

The API migration from boolean result to unit.completed() is correct and aligns with the new unit-centric compilation flow.

src/Server/Document.cpp (3)

208-224: Static analysis: potential uninitialized variable warning is a false positive.

The static analyzer flagged line 208 for an uninitialized variable, but all captured references (params, pch, message, links, path) are properly initialized before the lambda is invoked via async::submit. The path parameter at line 177 is initialized from the function argument.

The code correctly handles the new unit-based API flow.


211-223: Diagnostic handling during PCH build is incomplete but tracked.

The FIXME at line 212 correctly identifies that diagnostics should be flushed through feature::diagnostic for proper LSP reporting. The current logging approach is acceptable for debugging but won't surface errors to the user through the LSP protocol.


341-341: LGTM!

Correct use of move semantics to transfer ownership of the CompilationUnit into a shared_ptr for storage.

src/Compiler/Compilation.cpp (3)

140-149: Good practice: explicit buffer lifetime management.

The comment at lines 141-143 clearly explains why RetainRemappedFileBuffers is set to true and that cleanup happens in CompilationUnit's destructor. This is a sensible approach to handle the non-deterministic cleanup behavior of CompilerInstance.


208-316: Well-structured compilation flow with proper status handling.

The internal run_clang function has clear status transitions:

  • SetupFail for early configuration failures (diagnostic engine, invocation, target, action begin)
  • FatalError for execution errors or PCH/PCM generation failures
  • Cancelled when the stop flag is set
  • Completed on success

The error handling at lines 290-295 correctly prevents serializing a potentially corrupt AST when generating PCH/PCM files.


343-438: LGTM! Consistent public API returning CompilationUnit.

All public entry points (preprocess, compile overloads, complete) now consistently return CompilationUnit, enabling callers to query completion status and access diagnostics uniformly. The before_execute and after_execute callbacks are well-organized for different compilation modes.

tests/unit/Compiler/DiagnosticTests.cpp (4)

83-99: Good test coverage for setup failure scenario.

The TargetError test correctly validates:

  • setup_fail() returns true for invalid target triple
  • Diagnostics are still accessible despite setup failure
  • Diagnostic has no valid file location (as expected for command-line errors)

The test appropriately uses an unknown target triple aa-bb-cc to trigger the setup failure path.


101-117: LGTM! Error test correctly validates completed state with errors.

The test confirms that completed() returns true even when parse errors occur, which is the expected behavior - the AST is built (though potentially incomplete) and diagnostics are available.


119-134: Good addition: Warning diagnostic test.

This new test case validates warning-level diagnostics and confirms the diagnostic collection works for non-error diagnostics. The use of -Wall -Wunused-variable flags is appropriate.


136-163: LGTM! PCHError and ASTError tests validate error state differentiation.

  • PCHError: Correctly expects fatal_error() because PCH generation is aborted when errors occur (to prevent corrupted PCH files)
  • ASTError: Correctly expects completed() for the same code without PCH output, as the AST can still be used despite errors

This demonstrates the important distinction between PCH/PCM generation (which must abort on errors) and regular AST building (which can tolerate errors).

include/Compiler/CompilationUnit.h (2)

15-42: Well-designed enum types for compilation state.

The CompilationKind enum clearly documents each compilation mode with helpful comments. The CompilationStatus enum provides a clean state machine for tracking compilation outcomes.


230-244: LGTM! Proper ownership semantics in CompilationUnit.

The move constructor correctly transfers ownership by nullifying the source's self pointer. Combined with the deleted copy constructor and the destructor that deletes self, this provides correct RAII semantics.

Note: The kind member at line 243 shadows the base class method kind() at line 55. This appears intentional as the derived class stores the kind directly while the base accesses it through self. Consider whether this duplication is necessary.

src/Compiler/CompilationUnit.cpp (3)

79-107: LGTM! Efficient file path caching implementation.

The path caching logic correctly:

  1. Checks the cache first
  2. Retrieves the real path (with fallback to virtual path)
  3. Allocates stable storage via BumpPtrAllocator
  4. Stores in cache for future lookups

The null-terminated allocation (line 102) ensures C-string compatibility.


261-288: LGTM! Symbol ID generation with caching.

Both getSymbolID implementations follow the same efficient pattern:

  1. Check cache first
  2. Generate USR on cache miss
  3. Compute hash and cache it
  4. Return SymbolID with hash and name

The caching prevents redundant USR generation for frequently accessed symbols.


326-328: Destructor correctly manages Self ownership.

The destructor simply deletes the self pointer. Since CompilationUnit is the sole owner (move constructor nullifies source), this is correct. The deleted copy constructor prevents double-delete scenarios.

Note: Consider adding a null check for safety if a moved-from unit is accidentally destroyed twice (though this shouldn't happen with proper usage):

CompilationUnit::~CompilationUnit() {
    delete self;  // delete nullptr is safe, so this is fine as-is
}

Actually, delete nullptr is well-defined and safe in C++, so the current implementation is correct even for moved-from objects.

Comment thread src/Compiler/Module.cpp
@16bit-ykiko

Copy link
Copy Markdown
Member Author

@coderabbitai summary

@coderabbitai

coderabbitai Bot commented Jan 3, 2026

Copy link
Copy Markdown
✅ Actions performed

Summary regeneration triggered.

@16bit-ykiko
16bit-ykiko merged commit dd8f0dd into main Jan 3, 2026
19 checks passed
@16bit-ykiko
16bit-ykiko deleted the improve-compilation-unit branch January 3, 2026 08:23
@16bit-ykiko

Copy link
Copy Markdown
Member Author

@coderabbitai summary

@coderabbitai

coderabbitai Bot commented Jan 3, 2026

Copy link
Copy Markdown
✅ Actions performed

Summary regeneration triggered.

@coderabbitai coderabbitai Bot mentioned this pull request May 4, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant