Skip to documentation
SLOP

tiny.smg.cli.json

Reference tiny.smg cli json

Defined in cli.

API (10)

Actions

Public operations.

No direct callersNo direct callsclijson
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callerscli.jsonrenderEdgeArraycli.outputwriteOutcli.jsonedgeArray
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallscli.jsonedgeArraytest; no linktools.smg.src.cli.jsontest: array renderers preserve minifi...modelwriteEdgeDataJsonObjectcli.jsonrenderEdgeArray
Static calls · unresolved targets: 0 · external targets: 6.
Called byCallscli.jsonstringArraytest; no linktools.smg.src.cli.jsontest: array renderers preserve minifi...cli.jsonwriteStringArrayValuecli.jsonrenderStringArray
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callerscli.jsonrenderStringArraycli.outputwriteOutcli.jsonstringArray
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest; no linktools.smg.src.cli.jsontest: about json preserves coupling c...cli.jsonwriteStringArrayValuemodelwriteNodeDataJsonObjectcli.jsonwriteAbout
Static calls · unresolved targets: 2 · external targets: 7.
Called byCallstest; no linktools.smg.src.cli.jsontest: impact and between json preserv...cli.jsonwriteStringArrayValuecli.jsonwriteBetween
Static calls · unresolved targets: 1 · external targets: 7.
Called byCallscli.jsonwriteFindingcli.factsfloatTextcli.jsonwriteFactValue
Static calls · unresolved targets: 1 · external targets: 2.
Called byCallstest; no linktools.smg.src.cli.jsontest: finding json preserves quantifi...command.checkwriteJsoncli.jsonwriteFactValuecli.jsonwriteStringArrayValuecli.jsonwriteFinding
Static calls · unresolved targets: 1 · external targets: 5.
Called byCallstest; no linktools.smg.src.cli.jsontest: impact and between json preserv...cli.jsonwriteStringArrayValuecli.jsonwriteImpact
Static calls · unresolved targets: 1 · external targets: 5.
Called byCallsNo direct callscli.jsonrenderStringArraycli.jsonwriteAboutcli.jsonwriteBetweencli.jsonwriteFindingcli.jsonwriteImpactcli.jsonwriteStringArrayValue
Static calls · unresolved targets: 1 · external targets: 2.

Source: tools/smg/src/cli/json.zig

zig
const std = @import("std");const pretty_json = @import("pretty").json;const smg = @import("../root.zig");const facts = smg.cli.facts;const output = smg.cli.output;const model = smg.model;const rules = smg.rules;pub fn writeAbout(writer: *std.Io.Writer, node: model.Node, depth: usize, full: bool, coupling_only: bool, incoming_all: usize, outgoing_all: usize, incoming: []const model.Edge, outgoing: []const model.Edge, path: []const []const u8, neighbors: []const []const u8) !void {    var out = pretty_json.Writer.init(writer, .minified);    try out.beginObject();    try out.objectField("node");    try model.writeNodeDataJsonObject(node, &out);    var incoming_display = incoming;    var outgoing_display = outgoing;    var neighbors_display = neighbors;    if (!full) {        if (incoming_display.len > 10) incoming_display = incoming_display[0..10];        if (outgoing_display.len > 10) outgoing_display = outgoing_display[0..10];        if (neighbors_display.len > 10) neighbors_display = neighbors_display[0..10];    }    if (depth >= 1) {        try out.objectField("containment_path");        try writeStringArrayValue(&out, path);        try out.objectField("incoming");        try out.beginArray();        for (incoming_display) |edge| {            try out.beginObject();            try out.objectField("source");            try out.write(edge.source);            try out.objectField("rel");            try out.write(edge.rel);            try out.endObject();        }        try out.endArray();        try out.objectField("outgoing");        try out.beginArray();        for (outgoing_display) |edge| {            try out.beginObject();            try out.objectField("target");            try out.write(edge.target);            try out.objectField("rel");            try out.write(edge.rel);            try out.endObject();        }        try out.endArray();        try out.objectField("incoming_total");        try out.write(incoming.len);        try out.objectField("outgoing_total");        try out.write(outgoing.len);        const incoming_truncated = incoming.len - incoming_display.len;        const outgoing_truncated = outgoing.len - outgoing_display.len;        const neighbors_truncated = neighbors.len - neighbors_display.len;        const edge_truncated = !full and (incoming_truncated != 0 or outgoing_truncated != 0);        const neighbor_truncated = !full and depth >= 2 and neighbors_truncated != 0;        if (edge_truncated) {            try out.objectField("truncated");            try out.beginObject();            if (incoming_truncated != 0) {                try out.objectField("incoming");                try out.write(incoming_truncated);            }            if (outgoing_truncated != 0) {                try out.objectField("outgoing");                try out.write(outgoing_truncated);            }            if (neighbor_truncated) {                try out.objectField("neighbors");                try out.write(neighbors_truncated);            }            try out.endObject();        }        if (coupling_only) {            try out.objectField("hidden_rels");            try out.beginObject();            try out.objectField("incoming");            try out.write(incoming_all - incoming.len);            try out.objectField("outgoing");            try out.write(outgoing_all - outgoing.len);            try out.endObject();        }        if (depth >= 2) {            try out.objectField("neighbors");            try writeStringArrayValue(&out, neighbors_display);            try out.objectField("neighbors_total");            try out.write(neighbors.len);            if (neighbor_truncated and !edge_truncated) {                try out.objectField("truncated");                try out.beginObject();                try out.objectField("neighbors");                try out.write(neighbors_truncated);                try out.endObject();            }        }    }    try out.endObject();    try writer.writeByte('\n');}pub fn writeImpact(writer: *std.Io.Writer, target: []const u8, names: []const []const u8, total: usize, limit: i64, coupling_only: bool) !void {    var out = pretty_json.Writer.init(writer, .minified);    try out.beginObject();    try out.objectField("target");    try out.write(target);    try out.objectField("affected");    try writeStringArrayValue(&out, names);    try out.objectField("count");    try out.write(total);    try out.objectField("displayed");    try out.write(names.len);    try out.objectField("truncated");    try out.write(names.len < total);    try out.objectField("limit");    try out.write(limit);    try out.objectField("coupling_only");    try out.write(coupling_only);    try out.endObject();    try writer.writeByte('\n');}pub fn writeBetween(writer: *std.Io.Writer, source: []const u8, target: []const u8, path: ?[]const []const u8, direct: []const model.Edge) !void {    var out = pretty_json.Writer.init(writer, .minified);    try out.beginObject();    try out.objectField("source");    try out.write(source);    try out.objectField("target");    try out.write(target);    try out.objectField("path");    if (path) |items| {        try writeStringArrayValue(&out, items);    } else {        try out.write(null);    }    try out.objectField("direct_edges");    try out.beginArray();    for (direct) |edge| {        try out.beginObject();        try out.objectField("source");        try out.write(edge.source);        try out.objectField("rel");        try out.write(edge.rel);        try out.objectField("target");        try out.write(edge.target);        try out.endObject();    }    try out.endArray();    try out.endObject();    try writer.writeByte('\n');}pub fn stringArray(allocator: std.mem.Allocator, values: []const []const u8) !u8 {    return try output.writeOut(try renderStringArray(allocator, values));}pub fn renderStringArray(allocator: std.mem.Allocator, values: []const []const u8) ![]const u8 {    var out: std.Io.Writer.Allocating = .init(allocator);    errdefer out.deinit();    var writer = pretty_json.Writer.init(&out.writer, .minified);    try writeStringArrayValue(&writer, values);    try out.writer.writeByte('\n');    return try out.toOwnedSlice();}pub fn edgeArray(allocator: std.mem.Allocator, edges: []const model.Edge) !u8 {    return try output.writeOut(try renderEdgeArray(allocator, edges));}pub fn renderEdgeArray(allocator: std.mem.Allocator, edges: []const model.Edge) ![]const u8 {    var out: std.Io.Writer.Allocating = .init(allocator);    errdefer out.deinit();    var writer = pretty_json.Writer.init(&out.writer, .minified);    try writer.beginArray();    for (edges) |edge| try model.writeEdgeDataJsonObject(edge, &writer);    try writer.endArray();    try out.writer.writeByte('\n');    return try out.toOwnedSlice();}pub fn writeFinding(allocator: std.mem.Allocator, writer: *pretty_json.Writer, finding: rules.Finding) !void {    try writer.beginObject();    try writer.objectField("rule");    try writer.write(finding.rule);    try writer.objectField("type");    try writer.write(finding.type);    try writer.objectField("message");    try writer.write(finding.message);    try writer.objectField("witnesses");    try writer.beginArray();    if (finding.predicates.len != 0) {        for (finding.predicates) |predicate| {            try writer.beginObject();            try writer.objectField("kind");            try writer.write("predicate");            try writer.objectField("subject");            try writer.write(predicate.subject);            try writer.objectField("assertion");            try writer.write(predicate.assertion);            try writer.objectField("facts");            try writer.beginObject();            for (predicate.facts) |fact| {                try writer.objectField(fact.name);                try writeFactValue(allocator, writer, fact.value);            }            try writer.endObject();            try writer.endObject();        }    } else if (finding.edges.len != 0) {        try writer.beginObject();        try writer.objectField("kind");        try writer.write("edge");        try writer.objectField("edges");        try writer.beginArray();        for (finding.edges) |edge| {            try writer.beginObject();            try writer.objectField("source");            try writer.write(edge.source);            try writer.objectField("rel");            try writer.write(edge.rel);            try writer.objectField("target");            try writer.write(edge.target);            try writer.endObject();        }        try writer.endArray();        try writer.endObject();    } else if (finding.nodes.len != 0) {        try writer.beginObject();        try writer.objectField("kind");        try writer.write("node");        try writer.objectField("nodes");        try writeStringArrayValue(writer, finding.nodes);        try writer.endObject();    }    try writer.endArray();    try writer.endObject();}pub fn writeFactValue(allocator: std.mem.Allocator, writer: *pretty_json.Writer, value: rules.FactValue) !void {    switch (value) {        .number => |number| {            if (number == @floor(number)) {                try writer.write(@as(i64, @intFromFloat(number)));            } else {                try writer.write(number);            }        },        .float_number => |number| {            const raw = try facts.floatText(allocator, number);            defer allocator.free(raw);            try writer.raw(raw);        },        .boolean => |boolean| try writer.write(boolean),    }}pub fn writeStringArrayValue(writer: *pretty_json.Writer, values: []const []const u8) !void {    try writer.beginArray();    for (values) |value| try writer.write(value);    try writer.endArray();}test "about json preserves coupling contract" {    var out: std.Io.Writer.Allocating = .init(std.testing.allocator);    defer out.deinit();    const node = model.Node{ .name = "app.main", .type = model.NodeType.function, .file = "src/app.py", .line = 1, .docstring = "main doc\nmore" };    const incoming = [_]model.Edge{};    const outgoing = [_]model.Edge{.{ .source = "app.main", .rel = model.RelType.calls, .target = "app.helper" }};    const path = [_][]const u8{ "app", "app.main" };    try writeAbout(&out.writer, node, 1, false, true, 1, 1, &incoming, &outgoing, &path, &.{});    try std.testing.expectEqualStrings(        \\{"node":{"name":"app.main","type":"function","file":"src/app.py","line":1,"docstring":"main doc\nmore"},"containment_path":["app","app.main"],"incoming":[],"outgoing":[{"target":"app.helper","rel":"calls"}],"incoming_total":0,"outgoing_total":1,"hidden_rels":{"incoming":1,"outgoing":0}}        \\    , out.written());}test "impact and between json preserve command schemas" {    var out: std.Io.Writer.Allocating = .init(std.testing.allocator);    defer out.deinit();    try writeImpact(&out.writer, "app.helper", &.{"app.main"}, 1, 20, true);    const path = [_][]const u8{ "a", "b" };    const direct = [_]model.Edge{.{ .source = "a", .rel = model.RelType.calls, .target = "b" }};    try writeBetween(&out.writer, "a", "b", &path, &direct);    try writeBetween(&out.writer, "a", "d", null, &.{});    try std.testing.expectEqualStrings(        "{\"target\":\"app.helper\",\"affected\":[\"app.main\"],\"count\":1,\"displayed\":1,\"truncated\":false,\"limit\":20,\"coupling_only\":true}\n" ++            "{\"source\":\"a\",\"target\":\"b\",\"path\":[\"a\",\"b\"],\"direct_edges\":[{\"source\":\"a\",\"rel\":\"calls\",\"target\":\"b\"}]}\n" ++            "{\"source\":\"a\",\"target\":\"d\",\"path\":null,\"direct_edges\":[]}\n",        out.written(),    );}test "array renderers preserve minified newline output" {    const allocator = std.testing.allocator;    const strings = try renderStringArray(allocator, &.{ "a", "b" });    defer allocator.free(strings);    try std.testing.expectEqualStrings("[\"a\",\"b\"]\n", strings);    const edges = [_]model.Edge{.{ .source = "a", .rel = model.RelType.calls, .target = "b" }};    const edge_json = try renderEdgeArray(allocator, &edges);    defer allocator.free(edge_json);    try std.testing.expectEqualStrings("[{\"source\":\"a\",\"rel\":\"calls\",\"target\":\"b\"}]\n", edge_json);}test "finding json preserves quantified predicate witness contract" {    const allocator = std.testing.allocator;    const fact = rules.PredicateFact{ .name = "fan_out", .value = .{ .number = 1 } };    const predicate = rules.PredicateWitness{ .subject = "core.lib", .assertion = "fan_out <= 0", .facts = &.{fact} };    const finding = rules.Finding{        .rule = "fan-out",        .type = "quantified",        .message = "1 subject(s) failed fan_out <= 0",        .nodes = &.{"core.lib"},        .predicates = &.{predicate},    };    var out: std.Io.Writer.Allocating = .init(allocator);    defer out.deinit();    var writer = pretty_json.Writer.init(&out.writer, .minified);    try writeFinding(allocator, &writer, finding);    try std.testing.expectEqualStrings(        \\{"rule":"fan-out","type":"quantified","message":"1 subject(s) failed fan_out <= 0","witnesses":[{"kind":"predicate","subject":"core.lib","assertion":"fan_out <= 0","facts":{"fan_out":1}}]}    , out.written());}

Source: tools/smg/src/cli/root.zig:4

zig
pub const json = @import("json.zig");

Audit

Definitions11
Public names11
Members0
Version26.7.0
Revisiondaab053ee433