Skip to content

fix(rust): attach crate-root lib.rs annotations in multi-crate workspace scans - #4

Open
nightscape wants to merge 1 commit into
GitSmart86:mainfrom
nightscape:fix/cargo-workspace-crate-lib-attach
Open

nightscape wants to merge 1 commit into
GitSmart86:mainfrom
nightscape:fix/cargo-workspace-crate-lib-attach

Conversation

@nightscape

Copy link
Copy Markdown

Problem

Scanning a Cargo workspace (many crates under one root) loses all crate-level annotations. Every crate's <crate>/src/lib.rs resolves to the constant module path _lib, so:

  1. walker's docs_map (keyed by module path) dedups all crate libs down to one.
  2. ir_builder::module_path_to_dir_path maps _lib. (scan root).

Net effect: no crate gets its @c4 level or description, and ir validate has nothing annotated to compare (it silently passes even when crates are added/removed).

Fix

  • path_resolver::path_to_module_name: a crate-root lib.rs now derives a unique module path from its crate directory (stripping a trailing src). A lib.rs at the scan root still maps to _lib (single-crate behavior unchanged).
  • ir_builder::module_path_to_dir_path: collapse <crate>/src/lib.rs<crate> so the annotation lands on the crate node.

Verified

Against a 20-crate workspace: crate //! descriptions and @c4 levels now attach to crate nodes (0 → 13 with descriptions from existing docs; @c4 container attaches). Single-crate scans and all existing unit tests unchanged; added a multi-crate path_resolver test.

🤖 Generated with Claude Code

In a Cargo workspace scan, every crate's <crate>/src/lib.rs was mapped to
the constant module path "_lib", so the docs map deduped them to one and
ir_builder mapped "_lib" to the scan root. Result: no crate-level @C4
levels or descriptions, and `ir validate` had nothing annotated to compare.

- path_resolver: give crate-root lib.rs a unique crate-dir module path
  (stripping a trailing `src`); a lib.rs at the scan root still maps to _lib.
- ir_builder: collapse <crate>/src/lib.rs to <crate> so annotations land on
  the crate node.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 14, 2026 09:24

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR improves how crate-root lib.rs files are mapped to IR/module paths, especially in multi-crate workspace scans, to avoid collisions and to attach annotations to the crate node rather than the physical src/ directory.

Changes:

  • Collapse <crate>/src/lib.rs directory mapping to <crate> in the IR builder so annotations land on the crate node.
  • Update Rust path resolver to derive unique module names for workspace crates’ lib.rs (instead of always _lib).
  • Add tests covering workspace crate lib.rs behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
core/archidoc-engine/src/ir_builder.rs Collapses src/lib.rs to the crate directory for annotation placement.
adapters/archidoc-rust/src/path_resolver.rs Derives unique module names for workspace lib.rs and adds a regression test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +70 to 81
let mut dir = relative.parent().unwrap_or(Path::new("."));
// A crate-root `lib.rs` represents its crate, not the `src/` directory
// it physically lives in. Collapse `<crate>/src/lib.rs` to `<crate>` so
// the annotation lands on the crate node.
if filename == "lib.rs"
&& dir.file_name().and_then(|n| n.to_str()) == Some("src")
{
dir = dir.parent().unwrap_or(Path::new("."));
}
let dir_str = dir.to_string_lossy().replace('\\', "/");
if !dir_str.is_empty() {
return dir_str;
Comment on lines +21 to +33
let crate_dir = match parent.file_name().and_then(|n| n.to_str()) {
Some("src") => parent.parent().unwrap_or(Path::new("")),
_ => parent,
};
let parts: Vec<&str> = crate_dir
.components()
.filter_map(|c| c.as_os_str().to_str())
.collect();
return if parts.is_empty() {
"_lib".to_string()
} else {
parts.join(".")
};
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.

2 participants