tiny.smg.view
Defined in tiny.smg.
API (20)
Actions
Public operations.
SuggestionQuery.deinitSuggestionQuery.initSuggestionQuery.rankallEdgesallNodescontainsEdgeincominglookupoutgoingresolveresolveOnescopePrefixsortEdgessortNodessuggestsuggestNodessuggestionLessThanvalidate
Types and contracts
Public types and contracts.
Source
Source: tools/smg/src/root.zig:37
zig
pub const view = @import("view.zig");Source: tools/smg/src/view.zig
zig
const std = @import("std");const alloc_phase = @import("alloc_phase");const graph_mod = @import("graph.zig");const limits_mod = @import("limits/root.zig");const model = @import("model.zig");const name_mod = @import("name.zig");const testing_limits = @import("root.zig").default_limits.suggestions;pub fn containsEdge(graph: graph_mod.Graph, source: []const u8, rel: []const u8, target: []const u8) !bool { var stack: [4096]u8 = undefined; const key_len = graph_mod.edgeKeyLen(source, rel, target); const key = if (key_len <= stack.len) graph_mod.edgeKeyInto(stack[0..key_len], source, rel, target) else try graph_mod.edgeKey(graph.allocator, source, rel, target); defer if (key_len > stack.len) graph.allocator.free(key); return graph.edge_index.contains(key);}pub fn resolve(graph: graph_mod.Graph, allocator: std.mem.Allocator, raw: []const u8) ![]const []const u8 { var out: std.ArrayList([]const u8) = .empty; errdefer out.deinit(allocator); if (graph.node_index.contains(raw)) { try out.append(allocator, raw); return try out.toOwnedSlice(allocator); } if (graph_mod.suffixIndexReady(graph)) { try graph_mod.appendSuffixMatches(graph, allocator, raw, &out); } else { for (graph.nodes.items) |node| { if (name_mod.matchesSuffix(node.name, raw)) try out.append(allocator, node.name); } } std.mem.sort([]const u8, out.items, {}, cmpString); return try out.toOwnedSlice(allocator);}pub fn lookup(graph: graph_mod.Graph, allocator: std.mem.Allocator, raw: []const u8, limits: limits_mod.Suggestions) ![]const []const u8 { const direct = try resolve(graph, allocator, raw); if (direct.len != 0) return direct; allocator.free(direct); const names = try allocator.alloc([]const u8, graph.nodes.items.len); defer allocator.free(names); for (graph.nodes.items, 0..) |node, index| names[index] = node.name; return try name_mod.fallbackMatches(allocator, names, raw, limits.fallback_match_count);}pub fn resolveOne(graph: graph_mod.Graph, allocator: std.mem.Allocator, raw: []const u8) ![]const u8 { const matches = try resolve(graph, allocator, raw); defer allocator.free(matches); if (matches.len == 0) return graph_mod.Error.NodeNotFound; if (matches.len > 1) return graph_mod.Error.AmbiguousName; return matches[0];}pub const SuggestionRank = struct { score: u8, spread: usize,};pub const SuggestionQuery = struct { allocator: std.mem.Allocator, normalized: []u8, normalized_len: usize, leaf: []u8, rows: []usize, pub fn init(allocator: std.mem.Allocator, raw: []const u8, limits: limits_mod.Suggestions) !?SuggestionQuery { const normalized = try allocator.alloc(u8, limits.normalized_name_bytes); errdefer allocator.free(normalized); const leaf = try allocator.alloc(u8, limits.normalized_name_bytes); errdefer allocator.free(leaf); const row_entries = try alloc_phase.capacity.add(usize, limits.normalized_name_bytes, 1); const row_count = try alloc_phase.capacity.mul(usize, row_entries, 2); const rows = try allocator.alloc(usize, row_count); errdefer allocator.free(rows); const value = normalizeInto(normalized, name_mod.leaf(raw)) orelse { allocator.free(rows); allocator.free(leaf); allocator.free(normalized); return null; }; if (value.len == 0) { allocator.free(rows); allocator.free(leaf); allocator.free(normalized); return null; } return .{ .allocator = allocator, .normalized = normalized, .normalized_len = value.len, .leaf = leaf, .rows = rows, }; } pub fn deinit(self: *SuggestionQuery) void { self.allocator.free(self.rows); self.allocator.free(self.leaf); self.allocator.free(self.normalized); self.* = undefined; } pub fn rank(self: *SuggestionQuery, name: []const u8) ?SuggestionRank { const query = self.normalized[0..self.normalized_len]; const leaf = normalizeInto(self.leaf, name_mod.leaf(name)) orelse return null; if (leaf.len == 0) return null; const score: u8 = if (std.mem.eql(u8, leaf, query)) 0 else if (query.len >= 3 and std.mem.indexOf(u8, leaf, query) != null) 1 else if (boundedDistance(leaf, query, 2, self.rows)) |distance| 1 + distance else if (leaf.len >= 3 and std.mem.indexOf(u8, query, leaf) != null) 4 else return null; return .{ .score = score, .spread = @max(leaf.len, query.len) - @min(leaf.len, query.len), }; }};const Scored = struct { name: []const u8, rank: SuggestionRank,};pub fn suggestionLessThan( a_name: []const u8, a_rank: SuggestionRank, b_name: []const u8, b_rank: SuggestionRank,) bool { if (a_rank.score != b_rank.score) return a_rank.score < b_rank.score; if (a_rank.spread != b_rank.spread) return a_rank.spread < b_rank.spread; if (a_name.len != b_name.len) return a_name.len < b_name.len; return std.mem.lessThan(u8, a_name, b_name);}pub fn suggest(allocator: std.mem.Allocator, names: []const []const u8, raw: []const u8, limit: usize, limits: limits_mod.Suggestions) ![]const []const u8 { var query = (try SuggestionQuery.init(allocator, raw, limits)) orelse return &.{}; defer query.deinit(); var scored: std.ArrayList(Scored) = .empty; defer scored.deinit(allocator); for (names) |name| { if (std.mem.eql(u8, name, raw)) continue; const rank = query.rank(name) orelse continue; try scored.append(allocator, .{ .name = name, .rank = rank }); } std.mem.sort(Scored, scored.items, {}, scoredLess); const count = @min(limit, scored.items.len); const out = try allocator.alloc([]const u8, count); for (scored.items[0..count], 0..) |entry, index| out[index] = entry.name; return out;}pub fn suggestNodes(graph: graph_mod.Graph, allocator: std.mem.Allocator, raw: []const u8, limit: usize, limits: limits_mod.Suggestions) ![]const []const u8 { const names = try allocator.alloc([]const u8, graph.nodes.items.len); defer allocator.free(names); for (graph.nodes.items, 0..) |node, index| names[index] = node.name; return try suggest(allocator, names, raw, limit, limits);}fn normalizeInto(buffer: []u8, raw: []const u8) ?[]const u8 { var length: usize = 0; for (raw) |char| { if (char == '_' or char == '-') continue; if (length == buffer.len) return null; buffer[length] = std.ascii.toLower(char); length += 1; } return buffer[0..length];}fn boundedDistance(a: []const u8, b: []const u8, max: u8, rows: []usize) ?u8 { const longer = if (a.len >= b.len) a else b; const shorter = if (a.len >= b.len) b else a; if (longer.len - shorter.len > max) return null; const row_len = shorter.len + 1; if (row_len > rows.len / 2) return null; var previous = rows[0..row_len]; var current = rows[row_len .. row_len * 2]; for (0..shorter.len + 1) |index| previous[index] = @intCast(index); for (longer, 0..) |char, row| { current[0] = row + 1; var row_min = current[0]; for (shorter, 0..) |other, column| { const substitution = previous[column] + @intFromBool(char != other); const insertion = current[column] + 1; const deletion = previous[column + 1] + 1; current[column + 1] = @min(substitution, @min(insertion, deletion)); row_min = @min(row_min, current[column + 1]); } if (row_min > max) return null; @memcpy(previous[0 .. shorter.len + 1], current[0 .. shorter.len + 1]); } const distance = previous[shorter.len]; return if (distance <= max) @intCast(distance) else null;}fn scoredLess(_: void, a: Scored, b: Scored) bool { return suggestionLessThan(a.name, a.rank, b.name, b.rank);}pub fn incoming(graph: graph_mod.Graph, allocator: std.mem.Allocator, name: []const u8, rel: ?[]const u8) ![]const model.Edge { var out: std.ArrayList(model.Edge) = .empty; errdefer out.deinit(allocator); for (graph_mod.incomingEdges(&graph, name)) |edge_index| { const edge = graph.edges.items[edge_index]; if (rel == null or std.mem.eql(u8, edge.rel, rel.?)) try out.append(allocator, edge); } std.mem.sort(model.Edge, out.items, {}, cmpIncoming); return try out.toOwnedSlice(allocator);}pub fn outgoing(graph: graph_mod.Graph, allocator: std.mem.Allocator, name: []const u8, rel: ?[]const u8) ![]const model.Edge { var out: std.ArrayList(model.Edge) = .empty; errdefer out.deinit(allocator); for (graph_mod.outgoingEdges(&graph, name)) |edge_index| { const edge = graph.edges.items[edge_index]; if (rel == null or std.mem.eql(u8, edge.rel, rel.?)) try out.append(allocator, edge); } std.mem.sort(model.Edge, out.items, {}, cmpOutgoing); return try out.toOwnedSlice(allocator);}pub fn allNodes(graph: graph_mod.Graph, allocator: std.mem.Allocator, type_name: ?[]const u8) ![]const model.Node { var out: std.ArrayList(model.Node) = .empty; errdefer out.deinit(allocator); for (graph.nodes.items) |node| { if (type_name == null or std.mem.eql(u8, node.type, type_name.?)) try out.append(allocator, node); } sortNodes(out.items); return try out.toOwnedSlice(allocator);}pub fn sortNodes(nodes: []model.Node) void { std.mem.sort(model.Node, nodes, {}, cmpNode);}pub fn allEdges(graph: graph_mod.Graph, allocator: std.mem.Allocator) ![]const model.Edge { var out: std.ArrayList(model.Edge) = .empty; errdefer out.deinit(allocator); for (graph.edges.items) |edge| try out.append(allocator, edge); sortEdges(out.items); return try out.toOwnedSlice(allocator);}pub fn sortEdges(edges: []model.Edge) void { std.mem.sort(model.Edge, edges, {}, cmpEdge);}pub fn validate(graph: graph_mod.Graph, allocator: std.mem.Allocator) ![]const []const u8 { var out: std.ArrayList([]const u8) = .empty; errdefer { freeStrings(allocator, out.items); out.deinit(allocator); } for (graph.edges.items) |edge| { if (!graph.node_index.contains(edge.source)) { const issue = try std.fmt.allocPrint(allocator, "dangling edge source: {s}", .{edge.source}); errdefer allocator.free(issue); try out.append(allocator, issue); } if (!graph.node_index.contains(edge.target)) { const issue = try std.fmt.allocPrint(allocator, "dangling edge target: {s}", .{edge.target}); errdefer allocator.free(issue); try out.append(allocator, issue); } } return try out.toOwnedSlice(allocator);}pub fn scopePrefix(graph: graph_mod.Graph, allocator: std.mem.Allocator, module_filter: []const u8) !graph_mod.Graph { var scoped = graph_mod.init(allocator); errdefer graph_mod.deinit(&scoped); const prefix_owned = !std.mem.endsWith(u8, module_filter, "."); const prefix = if (prefix_owned) try std.fmt.allocPrint(allocator, "{s}.", .{module_filter}) else module_filter; defer if (prefix_owned) allocator.free(prefix); const nodes = try allNodes(graph, allocator, null); defer allocator.free(nodes); for (nodes) |node| { if (std.mem.eql(u8, node.name, module_filter) or std.mem.startsWith(u8, node.name, prefix)) try graph_mod.addNode(&scoped, node); } const edges = try allEdges(graph, allocator); defer allocator.free(edges); for (edges) |edge| { if (scoped.node_index.contains(edge.source) and scoped.node_index.contains(edge.target)) try graph_mod.addEdge(&scoped, edge); } return scoped;}fn freeStrings(allocator: std.mem.Allocator, values: []const []const u8) void { for (values) |value| allocator.free(value);}fn cmpString(_: void, a: []const u8, b: []const u8) bool { return std.mem.lessThan(u8, a, b);}fn cmpNode(_: void, a: model.Node, b: model.Node) bool { return std.mem.lessThan(u8, a.name, b.name);}fn cmpEdge(_: void, a: model.Edge, b: model.Edge) bool { const source = std.mem.order(u8, a.source, b.source); if (source != .eq) return source == .lt; const rel = std.mem.order(u8, a.rel, b.rel); if (rel != .eq) return rel == .lt; return std.mem.lessThan(u8, a.target, b.target);}fn cmpIncoming(_: void, a: model.Edge, b: model.Edge) bool { const rel = std.mem.order(u8, a.rel, b.rel); if (rel != .eq) return rel == .lt; return std.mem.lessThan(u8, a.source, b.source);}fn cmpOutgoing(_: void, a: model.Edge, b: model.Edge) bool { const rel = std.mem.order(u8, a.rel, b.rel); if (rel != .eq) return rel == .lt; return std.mem.lessThan(u8, a.target, b.target);}test "resolve suffix and validate edge" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); const meta = try model.sourcePair(allocator, "manual"); try graph_mod.addNode(&graph, .{ .name = "pkg.mod", .type = model.NodeType.module, .metadata = meta }); try graph_mod.addNode(&graph, .{ .name = "pkg.mod.f", .type = model.NodeType.function, .metadata = meta }); try graph_mod.addEdge(&graph, .{ .source = "pkg.mod", .rel = model.RelType.contains, .target = "pkg.mod.f", .metadata = meta }); try std.testing.expectEqualStrings("pkg.mod.f", try resolveOne(graph, allocator, "f")); const issues = try validate(graph, allocator); try std.testing.expectEqual(@as(usize, 0), issues.len);}test "lookup widens resolve with path and subsequence stages" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); for ([_][]const u8{ "lib.pkg.src.core.merge", "lib.pkg.src.core", "lib.other.src.core.split", "tools.glom.src" }) |node_name| { try graph_mod.addNode(&graph, .{ .name = node_name, .type = model.NodeType.module }); } const exact = try lookup(graph, allocator, "lib.pkg.src.core.merge", testing_limits); try std.testing.expectEqual(@as(usize, 1), exact.len); const path = try lookup(graph, allocator, "lib/pkg/src/core/merge.zig", testing_limits); try std.testing.expectEqual(@as(usize, 1), path.len); try std.testing.expectEqualStrings("lib.pkg.src.core.merge", path[0]); const relative = try lookup(graph, allocator, "src/core/merge.zig", testing_limits); try std.testing.expectEqual(@as(usize, 1), relative.len); try std.testing.expectEqualStrings("lib.pkg.src.core.merge", relative[0]); const package_path = try lookup(graph, allocator, "tools/glom/src/index.zig", testing_limits); try std.testing.expectEqual(@as(usize, 1), package_path.len); try std.testing.expectEqualStrings("tools.glom.src", package_path[0]); const subsequence = try lookup(graph, allocator, "pkg.core.merge", testing_limits); try std.testing.expectEqual(@as(usize, 1), subsequence.len); try std.testing.expectEqualStrings("lib.pkg.src.core.merge", subsequence[0]); const strict = try resolve(graph, allocator, "pkg.core.merge"); try std.testing.expectEqual(@as(usize, 0), strict.len); const absent = try lookup(graph, allocator, "no/such/file.zig", testing_limits); try std.testing.expectEqual(@as(usize, 0), absent.len);}test "resolve matches agree between linear and indexed suffix lookup" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); for ([_][]const u8{ "app.main", "lib.main", "app.helper", "domain", "remain" }) |name| { try graph_mod.addNode(&graph, .{ .name = name, .type = model.NodeType.function }); } const linear = try resolve(graph, allocator, "main"); try std.testing.expectEqual(@as(usize, 2), linear.len); try std.testing.expectEqualStrings("app.main", linear[0]); try std.testing.expectEqualStrings("lib.main", linear[1]); const linear_missing = try resolve(graph, allocator, "absent"); try std.testing.expectEqual(@as(usize, 0), linear_missing.len); try graph_mod.buildSuffixIndex(&graph); const indexed = try resolve(graph, allocator, "main"); try std.testing.expectEqual(@as(usize, 2), indexed.len); try std.testing.expectEqualStrings("app.main", indexed[0]); try std.testing.expectEqualStrings("lib.main", indexed[1]); const exact = try resolve(graph, allocator, "app.main"); try std.testing.expectEqual(@as(usize, 1), exact.len);}test "suggest ranks case and separator variants above typos" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); const names = [_][]const u8{ "store.IssueStateStore.mark_status", "store.IssueStateStore.mark_stale", "app.markstatus.render", "lib.unrelated", }; const exact = try suggest(allocator, &names, "markstatus", 5, testing_limits); try std.testing.expectEqual(@as(usize, 1), exact.len); try std.testing.expectEqualStrings("store.IssueStateStore.mark_status", exact[0]); const typo = try suggest(allocator, &names, "mark_statsu", 5, testing_limits); try std.testing.expect(typo.len >= 1); try std.testing.expectEqualStrings("store.IssueStateStore.mark_status", typo[0]); const none = try suggest(allocator, &names, "zzzqqq", 5, testing_limits); try std.testing.expectEqual(@as(usize, 0), none.len);}test "suggest matches partial leaves and respects the limit" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); const names = [_][]const u8{ "compiler.lowering.emit", "compiler.lowering.emitAll", "compiler.lowering.emitOne", "compiler.lowering.emitMany", "compiler.lowering.emitSome", "compiler.lowering.emitEach", }; const partial = try suggest(allocator, &names, "emit", 5, testing_limits); try std.testing.expectEqual(@as(usize, 5), partial.len); try std.testing.expectEqualStrings("compiler.lowering.emit", partial[0]);}test "suggest nodes reads names from the graph" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); try graph_mod.addNode(&graph, .{ .name = "app.main", .type = model.NodeType.function }); try graph_mod.addNode(&graph, .{ .name = "app.helper", .type = model.NodeType.function }); const suggestions = try suggestNodes(graph, allocator, "app.mian", 5, testing_limits); try std.testing.expectEqual(@as(usize, 1), suggestions.len); try std.testing.expectEqualStrings("app.main", suggestions[0]);}test "contains edge frees long lookup keys" { const source = &(@as([4100]u8, @splat('s'))); const target = &(@as([4100]u8, @splat('t'))); var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); try graph_mod.addNode(&graph, .{ .name = source, .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = target, .type = model.NodeType.function }); try graph_mod.addEdge(&graph, .{ .source = source, .rel = model.RelType.calls, .target = target }); try std.testing.expect(try containsEdge(graph, source, model.RelType.calls, target));}test "view helpers clean up allocation failures" { try std.testing.checkAllAllocationFailures( std.testing.allocator, checkViewAllocationFailures, .{}, );}fn checkViewAllocationFailures(allocator: std.mem.Allocator) !void { var graph = graph_mod.init(allocator); defer graph_mod.deinit(&graph); try graph_mod.addNode(&graph, .{ .name = "app", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "app.main", .type = model.NodeType.function }); try graph_mod.addNode(&graph, .{ .name = "lib.util", .type = model.NodeType.function }); try graph_mod.addEdge(&graph, .{ .source = "app", .rel = model.RelType.contains, .target = "app.main" }); try graph_mod.addEdge(&graph, .{ .source = "app.main", .rel = model.RelType.calls, .target = "lib.util" }); const matches = try resolve(graph, allocator, "main"); defer allocator.free(matches); try std.testing.expectEqual(@as(usize, 1), matches.len); try std.testing.expectEqualStrings("app.main", try resolveOne(graph, allocator, "main")); const incoming_edges = try incoming(graph, allocator, "app.main", null); defer allocator.free(incoming_edges); const outgoing_edges = try outgoing(graph, allocator, "app.main", null); defer allocator.free(outgoing_edges); const nodes = try allNodes(graph, allocator, null); defer allocator.free(nodes); const edges = try allEdges(graph, allocator); defer allocator.free(edges); const issues = try validate(graph, allocator); defer { freeStrings(allocator, issues); allocator.free(issues); } var scoped = try scopePrefix(graph, allocator, "app"); defer graph_mod.deinit(&scoped); try std.testing.expectEqual(@as(usize, 2), scoped.nodes.items.len);}test "validate returns owned issue strings" { var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); try graph.edges.append(std.testing.allocator, .{ .source = "missing", .rel = model.RelType.calls, .target = "also_missing", }); const issues = try validate(graph, std.testing.allocator); defer { freeStrings(std.testing.allocator, issues); std.testing.allocator.free(issues); } try std.testing.expectEqual(@as(usize, 2), issues.len);}test "incoming edges sort by relationship then source" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); try graph_mod.addNode(&graph, .{ .name = "target", .type = model.NodeType.function }); try graph_mod.addNode(&graph, .{ .name = "owner", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "caller", .type = model.NodeType.function }); try graph_mod.addEdge(&graph, .{ .source = "owner", .rel = model.RelType.contains, .target = "target" }); try graph_mod.addEdge(&graph, .{ .source = "caller", .rel = model.RelType.calls, .target = "target" }); const incoming_edges = try incoming(graph, allocator, "target", null); try std.testing.expectEqualStrings(model.RelType.calls, incoming_edges[0].rel); try std.testing.expectEqualStrings("caller", incoming_edges[0].source); try std.testing.expectEqualStrings(model.RelType.contains, incoming_edges[1].rel); try std.testing.expectEqualStrings("owner", incoming_edges[1].source);}test "scope prefix keeps matching nodes and internal edges" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); try graph_mod.addNode(&graph, .{ .name = "app", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "app.main", .type = model.NodeType.function }); try graph_mod.addNode(&graph, .{ .name = "lib", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "lib.util", .type = model.NodeType.function }); try graph_mod.addEdge(&graph, .{ .source = "app", .rel = model.RelType.contains, .target = "app.main" }); try graph_mod.addEdge(&graph, .{ .source = "app.main", .rel = model.RelType.calls, .target = "lib.util" }); const scoped = try scopePrefix(graph, allocator, "app"); try std.testing.expectEqual(@as(usize, 2), scoped.nodes.items.len); try std.testing.expectEqual(@as(usize, 1), scoped.edges.items.len); try std.testing.expect(graph_mod.getNode(&scoped, "app") != null); try std.testing.expect(graph_mod.getNode(&scoped, "app.main") != null);}Complete caller list for view.allEdges
15 direct callers.
tools.smg.src.analysis.report.layeringRows[function] — private; no exact target attools/smg/src/analysis/report.zig:2299in nearest public ownertools.smg.src.analysis.reporttiny.smg.cli.subgraph.prune[function] attools/smg/src/cli/subgraph.zig:35tiny.smg.cli.subgraph.writeSummary[function] attools/smg/src/cli/subgraph.zig:9tiny.smg.command.between.directEdges[function] attools/smg/src/command/between.zig:48tiny.smg.concepts.analyze[function] attools/smg/src/concepts.zig:97tiny.smg.exports.toDot[function] attools/smg/src/export.zig:161tiny.smg.exports.toDsm[function] attools/smg/src/export.zig:177tiny.smg.exports.toJson[function] attools/smg/src/export.zig:9tiny.smg.exports.toMermaid[function] attools/smg/src/export.zig:146tiny.smg.exports.toText[function] attools/smg/src/export.zig:123tools.smg.src.rules.checkConcepts[function] — private; no exact target attools/smg/src/rules.zig:1141in nearest public ownertiny.smg.rulestools.smg.src.rules.checkCycles[function] — private; no exact target attools/smg/src/rules.zig:1063in nearest public ownertiny.smg.rulestools.smg.src.rules.checkLayering[function] — private; no exact target attools/smg/src/rules.zig:1132in nearest public ownertiny.smg.rulestools.smg.src.view.checkViewAllocationFailures[function] — private; no exact target attools/smg/src/view.zig:464in nearest public ownertiny.smg.viewtiny.smg.view.scopePrefix[function] attools/smg/src/view.zig:278
Complete caller list for view.allNodes
23 direct callers.
tools.smg.src.analysis.overview.connectedRows[function] — private; no exact target attools/smg/src/analysis/overview.zig:105in nearest public ownertools.smg.src.analysis.overviewtools.smg.src.analysis.overview.moduleRows[function] — private; no exact target attools/smg/src/analysis/overview.zig:136in nearest public ownertools.smg.src.analysis.overviewtools.smg.src.analysis.report.classMetricsWithIndex[function] — private; no exact target attools/smg/src/analysis/report.zig:1771in nearest public ownertools.smg.src.analysis.reporttools.smg.src.analysis.report.deadCodeRowsWithIndex[function] — private; no exact target attools/smg/src/analysis/report.zig:2272in nearest public ownertools.smg.src.analysis.reporttools.smg.src.analysis.report.featureEnvyRowsWithIndex[function] — private; no exact target attools/smg/src/analysis/report.zig:2348in nearest public ownertools.smg.src.analysis.reporttools.smg.src.analysis.report.godFileRowsWithIndex[function] — private; no exact target attools/smg/src/analysis/report.zig:2403in nearest public ownertools.smg.src.analysis.reporttools.smg.src.analysis.report.moduleNodes[function] — private; no exact target attools/smg/src/analysis/report.zig:2032in nearest public ownertools.smg.src.analysis.reporttools.smg.src.analysis.report.shotgunSurgeryRowsWithIndex[function] — private; no exact target attools/smg/src/analysis/report.zig:2381in nearest public ownertools.smg.src.analysis.reporttiny.smg.blame.entriesForFile[function] attools/smg/src/blame.zig:30tools.smg.src.churn.buildFileIndex[function] — private; no exact target attools/smg/src/churn.zig:83in nearest public ownertiny.smg.churntools.smg.src.cli.subgraph.subgraphDegrees[function] — private; no exact target attools/smg/src/cli/subgraph.zig:56in nearest public ownertiny.smg.cli.subgraphtiny.smg.cli.subgraph.writeSummary[function] attools/smg/src/cli/subgraph.zig:9tools.smg.src.concepts.materialize[function] — private; no exact target attools/smg/src/concepts.zig:275in nearest public ownertiny.smg.conceptstiny.smg.exports.toDot[function] attools/smg/src/export.zig:161tiny.smg.exports.toDsm[function] attools/smg/src/export.zig:177tiny.smg.exports.toJson[function] attools/smg/src/export.zig:9tiny.smg.exports.toMermaid[function] attools/smg/src/export.zig:146tiny.smg.exports.toText[function] attools/smg/src/export.zig:123tools.smg.src.rules.checkQuantified[function] — private; no exact target attools/smg/src/rules.zig:1163in nearest public ownertiny.smg.rulestiny.smg.rules.quantifiedMetricValidationMessage[function] attools/smg/src/rules.zig:1287tools.smg.src.storage.nodes.saveGraph[function] — private; no exact target attools/smg/src/storage/nodes.zig:308in nearest public ownertiny.smg.storage.nodestools.smg.src.view.checkViewAllocationFailures[function] — private; no exact target attools/smg/src/view.zig:464in nearest public ownertiny.smg.viewtiny.smg.view.scopePrefix[function] attools/smg/src/view.zig:278
Complete caller list for view.incoming
11 direct callers.
tools.smg.src.cli.subgraph.subgraphDegrees[function] — private; no exact target attools/smg/src/cli/subgraph.zig:56in nearest public ownertiny.smg.cli.subgraphtiny.smg.command.about.command.run[function] attools/smg/src/command/about/command.zig:16tools.smg.src.command.about.render.test_about_text_renders_coupling_context_and_hidden_edge_count[function] — test; no exact target attools/smg/src/command/about/render.zig:117in nearest public ownertiny.smg.command.about.rendertiny.smg.command.node.show[function] attools/smg/src/command/node.zig:49tiny.smg.command.query.run[function] attools/smg/src/command/query.zig:19tools.smg.src.command.usages.test_usage_rows_filter_coupling_edges_and_render_compact_locations[function] — test; no exact target attools/smg/src/command/usages.zig:189in nearest public ownertiny.smg.command.usagestools.smg.src.export.containingOwner[function] — private; no exact target attools/smg/src/export.zig:340in nearest public ownertiny.smg.exportstiny.smg.query.containmentPath[function] attools/smg/src/query.zig:9tools.smg.src.rules.checkDead[function] — private; no exact target attools/smg/src/rules.zig:1090in nearest public ownertiny.smg.rulestools.smg.src.view.checkViewAllocationFailures[function] — private; no exact target attools/smg/src/view.zig:464in nearest public ownertiny.smg.viewtools.smg.src.view.test_incoming_edges_sort_by_relationship_then_source[function] — test; no exact target attools/smg/src/view.zig:510in nearest public ownertiny.smg.view
Complete caller list for view.outgoing
8 direct callers.
tools.smg.src.analysis.overview.moduleRows[function] — private; no exact target attools/smg/src/analysis/overview.zig:136in nearest public ownertools.smg.src.analysis.overviewtools.smg.src.cli.subgraph.subgraphDegrees[function] — private; no exact target attools/smg/src/cli/subgraph.zig:56in nearest public ownertiny.smg.cli.subgraphtiny.smg.command.about.command.run[function] attools/smg/src/command/about/command.zig:16tools.smg.src.command.about.render.test_about_text_renders_coupling_context_and_hidden_edge_count[function] — test; no exact target attools/smg/src/command/about/render.zig:117in nearest public ownertiny.smg.command.about.rendertiny.smg.command.node.show[function] attools/smg/src/command/node.zig:49tiny.smg.command.query.run[function] attools/smg/src/command/query.zig:19tools.smg.src.rules.checkDead[function] — private; no exact target attools/smg/src/rules.zig:1090in nearest public ownertiny.smg.rulestools.smg.src.view.checkViewAllocationFailures[function] — private; no exact target attools/smg/src/view.zig:464in nearest public ownertiny.smg.view
Complete caller list for view.resolve
8 direct callers.
tools.smg.src.batch.mutation.remove[function] — private; no exact target attools/smg/src/batch/mutation.zig:168in nearest public ownertools.smg.src.batch.mutationtools.smg.src.batch.mutation.update[function] — private; no exact target attools/smg/src/batch/mutation.zig:210in nearest public ownertools.smg.src.batch.mutationtools.smg.src.scan.pipeline.scan.cResolveQualifiedScope[function] — private; no exact target attools/smg/src/scan/pipeline/scan.zig:4097in nearest public ownertools.smg.src.scan.pipeline.scantools.smg.src.view.checkViewAllocationFailures[function] — private; no exact target attools/smg/src/view.zig:464in nearest public ownertiny.smg.viewtiny.smg.view.lookup[function] attools/smg/src/view.zig:39tiny.smg.view.resolveOne[function] attools/smg/src/view.zig:49tools.smg.src.view.test_lookup_widens_resolve_with_path_and_subsequence_stages[function] — test; no exact target attools/smg/src/view.zig:343in nearest public ownertiny.smg.viewtools.smg.src.view.test_resolve_matches_agree_between_linear_and_indexed_suffix_lookup[function] — test; no exact target attools/smg/src/view.zig:372in nearest public ownertiny.smg.view
Audit
| Definitions | 21 |
|---|---|
| Public names | 21 |
| Members | 7 |
| Version | 26.7.0 |
| Revision | daab053ee433 |