Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions labs/code-graph/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ Measured on x86_64-linux with `nix path-info -Sh` and `stat`, nixpkgs `6510408d`

| | Size |
|---|---|
| `packages.default` binary (glibc, stripped) | 15.8 MiB (16,591,008 bytes) |
| `packages.default` binary (glibc, stripped) | 15.9 MiB (16,636,064 bytes) |
| `packages.default` closure | 62.8 MiB |
| `packages.static` (musl) binary and closure | 15.9 MiB (static, no other file) |
| `packages.static` with `xz -9e` | 1.1 MiB (a measurement only: see the xz warning in [`ptbr-pdf`](../ptbr-pdf/README.md#benchmark-from-pandoc-to-rust)) |
| `packages.static` (musl) binary and closure | 16.0 MiB (16,734,160 bytes; static, no other file) |
| `packages.static` with `xz -9e` | 1.1 MiB (1,192,652 bytes) (a measurement only: see the xz warning in [`ptbr-pdf`](../ptbr-pdf/README.md#benchmark-from-pandoc-to-rust)) |
| nixpkgs `graphify` 0.9.74, closure | 579.7 MiB |

The 18.3 MB ceiling in `checks.size` is the measured binary plus 10%. Most of the size is the Scala,
Expand Down
1 change: 1 addition & 0 deletions labs/code-graph/assets/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
var n = D.n[i];
row(n[0], "t");
row(n[1] + (n[2] ? " " + n[2] : ""));
if (n[7]) row("label: " + n[7]);
row("community: " + n[4]);
if (n[5]) {
var a = document.createElement("a");
Expand Down
6 changes: 6 additions & 0 deletions labs/code-graph/tools/src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub struct Node {
pub cname: String,
/// the short name of the linked repository this node stands for (`--link`), else empty
pub repo: String,
/// a linked node's own label, its `label` being the PATH it was found by (`--link`)
pub orig: String,
/// where that repository's graph.html is, focused on the node (`--link`), else empty
pub href: String,
}
Expand Down Expand Up @@ -69,6 +71,9 @@ impl Graph {
m.insert("external".into(), v);
m.insert("type".into(), json!("external"));
}
if !n.orig.is_empty() {
m.insert("linked_label".into(), json!(n.orig));
}
if !n.href.is_empty() {
m.insert("href".into(), json!(n.href));
}
Expand Down Expand Up @@ -143,6 +148,7 @@ impl Graph {
.unwrap_or("")
.to_string(),
href: s(n, "href"),
orig: s(n, "linked_label"),
community: n.get("community").and_then(Value::as_u64).unwrap_or(0) as usize,
cname,
});
Expand Down
32 changes: 22 additions & 10 deletions labs/code-graph/tools/src/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const RELS: &[&str] = &[
"inherits",
"implements",
"references",
"depends_on",
];

fn esc(s: &str) -> String {
Expand Down Expand Up @@ -170,23 +171,34 @@ pub fn render(g: &Graph, title: &str) -> String {
}
o += "</g><g id=\"lab\">";
// labels for the best-connected nodes, skipping any that would overlap one already placed
// always labelled: the nodes of a linked repository and the files that point at them
let mut always: Vec<bool> = g.nodes.iter().map(|x| !x.repo.is_empty()).collect();
for e in &g.edges {
if !g.nodes[e.t].repo.is_empty() {
always[e.s] = true;
}
}
let mut order: Vec<usize> = (0..n)
.filter(|&i| !g.nodes[i].external || !g.nodes[i].repo.is_empty())
.collect();
order.sort_by_key(|&i| (g.nodes[i].repo.is_empty(), std::cmp::Reverse(deg[i]), i));
order.sort_by_key(|&i| (!always[i], std::cmp::Reverse(deg[i]), i));
let mut boxes: Vec<(f64, f64, f64, f64)> = Vec::new();
for i in order.into_iter().take(400) {
for i in order
.into_iter()
.take(400 + always.iter().filter(|&&a| a).count())
{
let (x, y) = (pos[i].0 + 8.0, pos[i].1 + 4.0);
let b = (
x,
y - 13.0,
x + 7.6 * g.nodes[i].label.chars().count() as f64,
y + 3.0,
);
if boxes.len() >= 70
|| boxes
.iter()
.any(|q| b.0 < q.2 && q.0 < b.2 && b.1 < q.3 && q.1 < b.3)
if !always[i]
&& (boxes.len() >= 70
|| boxes
.iter()
.any(|q| b.0 < q.2 && q.0 < b.2 && b.1 < q.3 && q.1 < b.3))
{
continue;
}
Expand Down Expand Up @@ -232,12 +244,12 @@ pub fn render(g: &Graph, title: &str) -> String {
);
}
o += "</ul><h2>Relations</h2><ul class=\"rels\">";
for r in RELS {
for r in RELS.iter().filter(|r| g.edges.iter().any(|e| e.rel == **r)) {
let _ = write!(o, "<li><i class=\"l {r}\"></i>{r}</li>");
}
o += "</ul></aside>\n</main>\n";
let data = json!({
"n": g.nodes.iter().map(|x| json!([x.label, x.file, if x.line > 0 { format!("L{}", x.line) } else { String::new() }, x.community, x.cname, x.href, x.id])).collect::<Vec<_>>(),
"n": g.nodes.iter().map(|x| json!([x.label, x.file, if x.line > 0 { format!("L{}", x.line) } else { String::new() }, x.community, x.cname, x.href, x.id, x.orig])).collect::<Vec<_>>(),
"e": g.edges.iter().map(|e| json!([e.s, e.t, e.rel])).collect::<Vec<_>>(),
"v": [0, 0, w, h],
});
Expand Down Expand Up @@ -266,8 +278,8 @@ i.s0,.c0{fill:var(--c0);background:var(--c0)}i.s1,.c1{fill:var(--c1);background:
i.s4,.c4{fill:var(--c4);background:var(--c4)}i.s5,.c5{fill:var(--c5);background:var(--c5)}i.s6,.c6{fill:var(--c6);background:var(--c6)}i.s7,.c7{fill:var(--c7);background:var(--c7)}
i.s8,.c8{fill:var(--c8);background:var(--c8)}i.s9,.c9{fill:var(--c9);background:var(--c9)}i.s10,.c10{fill:var(--c10);background:var(--c10)}i.s11,.c11{fill:var(--c11);background:var(--c11)}
i{display:inline-block;width:10px;height:10px;border-radius:50%;flex:none}svg circle{background:none;stroke:var(--bg);stroke-width:1}svg circle.x{opacity:.55}svg circle.r{fill:var(--bg);stroke-width:2.5;stroke-dasharray:3 2}i.r{background:none;border:2px dashed var(--mut)}
.e{stroke-width:1;stroke:var(--mut);opacity:.35}.e.contains,.e.method,.e.defines{opacity:.18}.e.calls{stroke:var(--c1);opacity:.6}.e.imports_from,.e.imports{stroke:var(--c0);opacity:.5}.e.inherits,.e.implements{stroke:var(--c3);opacity:.7}.e.references{stroke:var(--c2);opacity:.4}
i.l{width:16px;height:3px;border-radius:0;background:var(--mut)}i.l.calls{background:var(--c1)}i.l.imports_from,i.l.imports{background:var(--c0)}i.l.inherits,i.l.implements{background:var(--c3)}i.l.references{background:var(--c2)}
.e{stroke-width:1;stroke:var(--mut);opacity:.35}.e.contains,.e.method,.e.defines{opacity:.18}.e.calls{stroke:var(--c1);opacity:.6}.e.imports_from,.e.imports{stroke:var(--c0);opacity:.5}.e.inherits,.e.implements{stroke:var(--c3);opacity:.7}.e.references{stroke:var(--c2);opacity:.4}.e.depends_on{stroke:var(--c4);opacity:.9;stroke-width:1.5;stroke-dasharray:4 3}
i.l{width:16px;height:3px;border-radius:0;background:var(--mut)}i.l.calls{background:var(--c1)}i.l.imports_from,i.l.imports{background:var(--c0)}i.l.inherits,i.l.implements{background:var(--c3)}i.l.references{background:var(--c2)}i.l.depends_on{background:var(--c4)}
text{font-size:13px;fill:var(--fg);paint-order:stroke;stroke:var(--bg);stroke-width:3px;pointer-events:none}
svg.f circle{opacity:.1}svg.f .e{opacity:.03}svg.f circle.on{opacity:1}svg.f .e.on{opacity:.9;stroke-width:1.6}svg.f #lab{display:none}svg circle.pick{stroke:var(--fg);stroke-width:2}
@media (max-width:760px){main{flex-direction:column}aside{width:auto;max-height:40vh;border-left:0;border-top:1px solid var(--line)}}
Expand Down
9 changes: 8 additions & 1 deletion labs/code-graph/tools/src/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,17 @@ fn enc(s: &str) -> String {
pub fn apply(g: &mut Graph, files: &[(String, String)], links: &[Link]) {
// (referencing file, link, target node in the linked graph) -> first line
let mut found: BTreeMap<(&str, usize, usize), u32> = BTreeMap::new();
// the first PATH, in sorted order, that resolved to each node: its label
let mut via: BTreeMap<(usize, usize), String> = BTreeMap::new();
for (path, text) in files {
for (li, l) in links.iter().enumerate() {
for (p, line) in refs(&l.name, text) {
if let Some(t) = resolve(&l.graph, &p) {
found.entry((path.as_str(), li, t)).or_insert(line);
let v = via.entry((li, t)).or_insert_with(|| p.clone());
if p < *v {
*v = p;
}
}
}
}
Expand Down Expand Up @@ -178,7 +184,8 @@ pub fn apply(g: &mut Graph, files: &[(String, String)], links: &[Link]) {
let o = &l.graph.nodes[t];
g.nodes.push(Node {
id: format!("{}:{}", l.name, o.id),
label: format!("{}: {}", l.name, o.label),
label: format!("{}: {}", l.name, via[&(li, t)]),
orig: o.label.clone(),
file: format!("{}:{}", l.name, o.file),
line: o.line,
external: true,
Expand Down
5 changes: 4 additions & 1 deletion labs/code-graph/tools/tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ fn link_adds_the_referenced_nodes_of_another_repository() {
let g = linked(&a, &out, &spec);
let x = node(&g, "b:labs_x_flake");
assert_eq!(x["external"], "b");
assert_eq!(x["label"], "b: flake.nix");
assert_eq!(x["label"], "b: labs/x");
assert_eq!(x["linked_label"], "flake.nix");
assert_eq!(x["href"], "b.html#node=labs_x_flake");
assert_eq!(x["source_file"], "b:labs/x/flake.nix");
assert_eq!(x["community_name"], "b");
Expand All @@ -324,6 +325,8 @@ fn link_adds_the_referenced_nodes_of_another_repository() {
// the page: one relative link per external node, no network, no href attribute
let h = std::fs::read_to_string(out.join("graph.html")).unwrap();
assert!(h.contains("b.html#node=labs_x_flake") && h.contains("external: b"));
// the relations legend lists what the graph has
assert!(h.contains("<i class=\"l depends_on\">") && !h.contains("<i class=\"l references\">"));
for bad in [
"http://", "https://", "src=", "href=", "@import", "url(", "<link",
] {
Expand Down
Loading