tiny.smg.command.analyze.support
Defined in command.analyze.
API (2)
Actions
Public operations.
Source
Source: tools/smg/src/command/analyze/root.zig:3
zig
pub const support = @import("support.zig");Source: tools/smg/src/command/analyze/support.zig
zig
const std = @import("std");const smg = @import("../../root.zig");const diff = smg.diff;const graph_mod = smg.graph;const model = smg.model;const output = smg.cli.output;const text = smg.text;pub fn deltaNames(allocator: std.mem.Allocator, result: diff.Result) ![]const []const u8 { var out: std.ArrayList([]const u8) = .empty; for (result.added_nodes) |node| try appendUniqueDeltaName(allocator, &out, node.name); for (result.changed_nodes) |node| try appendUniqueDeltaName(allocator, &out, node.node.name); for (result.added_edges) |edge| { try appendUniqueDeltaName(allocator, &out, edge.source); try appendUniqueDeltaName(allocator, &out, edge.target); } return try out.toOwnedSlice(allocator);}pub fn writeScopeWarning(allocator: std.mem.Allocator, graph: graph_mod.Graph, filter: []const u8) !void { const candidate_names = try candidates(allocator, graph, filter); var out: std.Io.Writer.Allocating = .init(allocator); errdefer out.deinit(); try out.writer.print("Warning: no nodes matching {s}", .{filter}); if (candidate_names.len != 0) { try out.writer.writeAll(". Did you mean:"); for (candidate_names[0..@min(candidate_names.len, 5)]) |candidate| try out.writer.print("\n {s}", .{candidate}); } try out.writer.writeByte('\n'); try output.writeErr(out.written());}fn candidates(allocator: std.mem.Allocator, graph: graph_mod.Graph, filter: []const u8) ![]const []const u8 { const suffix = if (std.mem.lastIndexOfScalar(u8, filter, '.')) |index| filter[index + 1 ..] else filter; const middle = try std.fmt.allocPrint(allocator, ".{s}.", .{suffix}); const end = try std.fmt.allocPrint(allocator, ".{s}", .{suffix}); var out: std.ArrayList([]const u8) = .empty; for (graph.nodes.items) |node| { if (std.mem.indexOf(u8, node.name, middle) == null and !std.mem.endsWith(u8, node.name, end)) continue; const index = std.mem.lastIndexOf(u8, node.name, end) orelse continue; const candidate = try std.fmt.allocPrint(allocator, "{s}.{s}", .{ node.name[0..index], suffix }); if (!text.list.containsString(out.items, candidate)) try out.append(allocator, candidate); } std.mem.sort([]const u8, out.items, {}, stringLess); return try out.toOwnedSlice(allocator);}fn stringLess(_: void, a: []const u8, b: []const u8) bool { return std.mem.lessThan(u8, a, b);}fn appendUniqueDeltaName(allocator: std.mem.Allocator, list: *std.ArrayList([]const u8), name: []const u8) !void { if (!text.list.containsString(list.items, name)) try list.append(allocator, name);}test "delta names preserve first occurrence order" { const added_nodes = [_]model.Node{.{ .name = "new", .type = model.NodeType.module, }}; const changed_nodes = [_]diff.ChangedNode{.{ .node = .{ .name = "changed", .type = model.NodeType.function }, .changes = &.{}, }}; const added_edges = [_]model.Edge{ .{ .source = "new", .rel = model.RelType.calls, .target = "changed" }, .{ .source = "extra", .rel = model.RelType.imports, .target = "new" }, }; const names = try deltaNames(std.testing.allocator, .{ .added_nodes = &added_nodes, .changed_nodes = &changed_nodes, .added_edges = &added_edges, }); defer std.testing.allocator.free(names); try std.testing.expectEqual(@as(usize, 3), names.len); try std.testing.expectEqualStrings("new", names[0]); try std.testing.expectEqualStrings("changed", names[1]); try std.testing.expectEqualStrings("extra", names[2]);}test "analyze scope candidates match python suffix suggestions" { 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.service", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "app.service.Worker", .type = model.NodeType.class }); try graph_mod.addNode(&graph, .{ .name = "pkg.service", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "pkg.service.Helper", .type = model.NodeType.class }); try graph_mod.addNode(&graph, .{ .name = "pkg.other", .type = model.NodeType.module }); const candidate_names = try candidates(allocator, graph, "service"); try std.testing.expectEqual(@as(usize, 2), candidate_names.len); try std.testing.expectEqualStrings("app.service", candidate_names[0]); try std.testing.expectEqualStrings("pkg.service", candidate_names[1]); const none = try candidates(allocator, graph, "missing"); try std.testing.expectEqual(@as(usize, 0), none.len);}Audit
| Definitions | 3 |
|---|---|
| Public names | 5 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |