GCC Code Coverage Report


src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
26 / 26
100.0%
Branches:
6 / 6, 2 excl
100.0%
Functions:
4 / 4
100.0%

visualizer/dependency-graph-visualizer.spice
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 // Std imports
4 import "std/text/stringstream";
5 import "std/data/vector";
6 import "std/io/filepath";
7
8 // Own imports
9 import "@/global/global-resource-manager";
10 import "@/compiler-pass";
11 import "@/source-file";
12 import "@/reader/code-loc";
13
14 /**
15 * Visualizer for the import dependency graph.
16 *
17 * Jobs:
18 * - Walk the SourceFile dependency tree starting from the main file
19 * - Emit one Graphviz dot node per source file, one edge per import relationship
20 */
21 760 public type DependencyGraphVisualizer struct {
22 compose public CompilerPass compilerPass
23 Vector<SourceFile*> printedFiles
24 }
25
26 760 public p DependencyGraphVisualizer.ctor(GlobalResourceManager& resourceManager, SourceFile* sourceFile) {
27 760 this.compilerPass = CompilerPass(resourceManager, sourceFile);
28 760 this.printedFiles = Vector<SourceFile*>();
29 760 }
30
31 /**
32 * Entry point: generate the dependency graph dot code starting from the root source file.
33 *
34 * @param output Output stream to write the dot node/edge lines into
35 */
36 760 public p DependencyGraphVisualizer.getDependencyGraph(StringStream& output) {
37 760 assert this.sourceFile.isMainFile;
38 760 this.printedFiles.clear();
39 760 this.getDependencyGraphNode(output, this.sourceFile);
40 760 }
41
42 /**
43 * Recursively emit dot nodes and edges for currentSourceFile and its transitive dependencies.
44 *
45 * @param output Output stream
46 * @param currentSourceFile Source file to emit
47 */
48 6533 p DependencyGraphVisualizer.getDependencyGraphNode(StringStream& output, SourceFile* currentSourceFile) {
49 // Skip if already printed (handles diamonds / shared dependencies)
50
2/2
✓ Branch 0 taken 36863 times.
✓ Branch 1 taken 3499 times.
40362 foreach SourceFile* printedFile : this.printedFiles {
51
2/2
✓ Branch 0 taken 3034 times.
✓ Branch 1 taken 33829 times.
36863 if printedFile == currentSourceFile {
52 3034 return;
53 }
54 33829 }
55 3499 this.printedFiles.pushBack(currentSourceFile);
56
57 // Emit a node for this source file using a path relative to the main file. Both paths are resolved to their canonical form first, so symlinks along the way (e.g. to the std) do not matter
58 3499 const String mainFilePath = String(this.sourceFile.filePath.toString());
59 3499 const String nodeId = getRelativePath(String(currentSourceFile.filePath.toString()), mainFilePath);
60 3499 output << " \"" << nodeId << "\" [color=\"lightgreen\",label=\"" << currentSourceFile.fileName << "\"];\n";
61
62 // Recurse into dependencies and emit edges
63
2/2
✓ Branch 0 taken 5773 times.
✓ Branch 1 taken 3499 times.
9272 foreach dyn depEntry : currentSourceFile.dependencies {
64 5773 SourceFile* dependency = depEntry.getSecond();
65 5773 this.getDependencyGraphNode(output, dependency);
66 5773 const String depNodeId = getRelativePath(String(dependency.filePath.toString()), mainFilePath);
67 5773 output << " \"" << nodeId << "\" -> \"" << depNodeId << "\";\n";
68 5773 }
69 3499 }
70