regexident/cargo-modules

Doesn't generate uses edges for fully namespaced components

Closed this issue · 4 comments

cargo modules generate graph --with-uses is very useful for understanding a crate. However, I notice that it doesn't generate uses edges when one module uses another's components by their fully namespaced names, rather than through a uses statement. Ideally it would, because whether or not the programmer uses a uses statement is just a syntactical detail. For example, I would expect the following crate to have uses edges for both "a -> b" and "a -> c". But it only has the former.

pub mod a {
    use self::b::X;

    pub mod b  {
        pub struct X{}
    }
    pub mod c {
        pub struct Y{}
    }

    pub struct Z {
        x: X,
        y: c::Y
    }
}
digraph {

    graph [
        label="cargo_modules_test",
        labelloc=t,

        pad=0.4,

        // Consider rendering the graph using a different layout algorithm, such as:
        // [dot, neato, twopi, circo, fdp, sfdp]
        layout=neato,
        overlap=false,
        splines="line",
        rankdir=LR,

        fontname="Helvetica", 
        fontsize="36",
    ];

    node [
        fontname="monospace",
        fontsize="10",
        shape="record",
        style="filled",
    ];

    edge [
        fontname="monospace",
        fontsize="10",
    ];

    "cargo_modules_test" [label="crate|cargo_modules_test", fillcolor="#5397c8"]; // "crate" node
    "cargo_modules_test::a" [label="pub mod|a", fillcolor="#81c169"]; // "mod" node
    "cargo_modules_test::a::b" [label="pub mod|a::b", fillcolor="#81c169"]; // "mod" node
    "cargo_modules_test::a::c" [label="pub mod|a::c", fillcolor="#81c169"]; // "mod" node

    "cargo_modules_test" -> "cargo_modules_test::a" [label="owns", color="#000000", style="solid"]; // "owns" edge
    "cargo_modules_test::a" -> "cargo_modules_test::a::b" [label="owns", color="#000000", style="solid"]; // "owns" edge
    "cargo_modules_test::a" -> "cargo_modules_test::a::c" [label="owns", color="#000000", style="solid"]; // "owns" edge
    "cargo_modules_test::a" -> "cargo_modules_test::a::b" [label="uses", color="#7f7f7f", style="Dashed"]; // "uses" edge

}

Hi @asomers, and thanks for the report! You are absolutely right in that this is currently an unfortunate limitation.

The rust-analyzer API that cargo-modules currently uses for obtaining the dependencies only seems to include explicit imports. It also currently only works on module level. As such cargo-modules currently can't tell you the dependencies of say a type or function.

I'll have to see if there is some alternative function in rust-analyzer that provides a more complete picture.

I thought it was something like that. If it can't be fixed, cie la vie.

I'm fairly certain there should be some way to get this information out of rust-analyzer. I just couldn't find any function that directly addresses cargo-module's needs.

I'm somewhat hesitant to asking the rust-analyzer for help as they are already generous enough to share the internal unstable APIs with third-party tools like cargo-modules. Effectively asking them for free user support on top of that feels a bit wrong to me.

Fixed by #227.

image
dot graph source
digraph {

    graph [
        label="github_issue_102",
        labelloc=t,

        pad=0.4,

        // Consider rendering the graph using a different layout algorithm, such as:
        // [dot, neato, twopi, circo, fdp, sfdp]
        layout=neato,
        overlap=false,
        splines="line",
        rankdir=LR,

        fontname="Helvetica", 
        fontsize="36",
    ];

    node [
        fontname="monospace",
        fontsize="10",
        shape="record",
        style="filled",
    ];

    edge [
        fontname="monospace",
        fontsize="10",
    ];

    "github_issue_102" [label="crate|github_issue_102", fillcolor="#5397c8"]; // "crate" node
    "github_issue_102::a" [label="pub mod|a", fillcolor="#81c169"]; // "mod" node
    "github_issue_102::a::b" [label="pub mod|a::b", fillcolor="#81c169"]; // "mod" node
    "github_issue_102::a::c" [label="pub mod|a::c", fillcolor="#81c169"]; // "mod" node

    "github_issue_102" -> "github_issue_102::a" [label="owns", color="#000000", style="solid"] [constraint=true]; // "owns" edge
    "github_issue_102::a" -> "github_issue_102::a::b" [label="owns", color="#000000", style="solid"] [constraint=true]; // "owns" edge
    "github_issue_102::a" -> "github_issue_102::a::b" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge
    "github_issue_102::a" -> "github_issue_102::a::c" [label="owns", color="#000000", style="solid"] [constraint=true]; // "owns" edge
    "github_issue_102::a" -> "github_issue_102::a::c" [label="uses", color="#7f7f7f", style="dashed"] [constraint=false]; // "uses" edge

}