tiny.smg.api
Defined in tiny.smg.
Render-neutral public-surface facts derived from a scanned graph.
API (63)
Actions
Public operations.
PublicDeclaration.bindingSource: Returns validated source evidence for the exported binding.PublicDeclaration.bindingSourceSpan: Returns the exact source span of the exported binding.PublicDeclaration.canonicalSource: Returns validated source evidence for the canonical definition.PublicDeclaration.canonicalSourceSpan: Returns the exact source span of the canonical definition.PublicDeclaration.documentation: Returns source-owned export docs or docs on the exact canonical declaration.PublicMember.documentation: Returns source-owned documentation attached to this member.PublicMember.identifier: Returns the exact identifier token, or null for a positional field.PublicMember.sourceSpan: Returns the exact half-open source byte range of sourceSpelling.PublicMember.sourceSpelling: Returns the exact source spelling of the member, excluding its docs.PublicMember.typeExpression: Returns the exact field type expression when the source has one.PublicMember.valueExpression: Returns an exact field default or enum assigned-value expression.PublicMemberGap.documentation: Returns source-owned documentation attached to this member.PublicMemberGap.identifier: Returns an exact identifier token when the source member has one.PublicMemberGap.sourceSpan: Returns the exact half-open source byte range of sourceSpelling.PublicMemberGap.sourceSpelling: Returns the exact source spelling of the unsupported member.aliasTargetcontainerKind: Returns the explicit Zig container category stored by the scanner.declarationSource: Returns validated file, span, and digest evidence for one declaration node.declarationSourceSpan: Returns a validated exact source span stored on one declaration node.directAliasTarget: Returns a source expression proved to be a direct declaration alias.explicitDeclaredType: Returns the exact source-spelled Zig type annotation, or null when omitted.freePublicDeclarations: Releases the record slice returned by publicDeclarations.freePublicMemberGaps: Releases the record slice returned by publicMemberGaps.freePublicMembers: Releases the record slice returned by publicMembers.isPublicisTestDeclaration: Returns whether the scanner marked a declaration as test-only.ownerForFile: Returns the borrowed name of the scanned module or package that owns a source file.publicDeclarations: Returns public children in stable exported-name order.publicMemberGaps: Returns explicit source members omitted from the supported projection.publicMembers: Returns canonical members admitted through one public Zig declaration.resolvePublicPath: Resolves one exact dotted path through the public surface of an owner.signaturesourceDigest: Returns the SHA-256 digest for exact source bytes.verifiedSource: Returns the exact declaration bytes after validating their stored span and digest.visibility
Types and contracts
Public types and contracts.
ContainerKind: A Zig container category preserved independently from graph node roles.DeclarationSource: Validated source location and digest for one declaration.ErrorMemberGapKind: Why a source member is preserved but not projected as a PublicMember.MemberKind: A source-level member category that is part of a public Zig type surface.PublicDeclaration: A public binding and the definition reached through its alias chain.PublicMember: A member admitted through a public export and owned by its canonical type.PublicMemberGap: A source member deliberately outside the supported public projection.SourceSpan: An exact half-open byte range in a source file.
Values and defaults
Public values and defaults.
alias_target_keycontainer_kind_keydeclared_type_keydeclared_type_state_keydirect_alias_target_keymember_expression_keymember_gap_keymember_identifier_keymember_order_keymember_type_keysignature_keysource_digest_bytessource_digest_hex_bytessource_end_byte_keysource_hash_keysource_spelling_keysource_start_byte_keytest_keyvisibility_key
Source
Source: tools/smg/src/api.zig
zig
//! Render-neutral public-surface facts derived from a scanned graph.const std = @import("std");const graph_mod = @import("graph.zig");const limits_mod = @import("limits/root.zig");const model = @import("model.zig");const testing_limits = @import("root.zig").default_limits.api;pub const visibility_key = "visibility";pub const test_key = "test";pub const signature_key = "signature";pub const alias_target_key = "alias_target";pub const direct_alias_target_key = "zig_direct_alias_target";pub const declared_type_key = "zig_declared_type";pub const declared_type_state_key = "zig_declared_type_state";pub const container_kind_key = "zig_container_kind";pub const member_identifier_key = "zig_member_identifier";pub const member_order_key = "zig_member_order";pub const source_spelling_key = "zig_source_spelling";pub const member_type_key = "zig_member_type";pub const member_expression_key = "zig_member_expression";pub const member_gap_key = "zig_member_gap";pub const source_start_byte_key = "source_start_byte";pub const source_end_byte_key = "source_end_byte";pub const source_hash_key = "source_sha256";pub const source_digest_bytes = std.crypto.hash.sha2.Sha256.digest_length;pub const source_digest_hex_bytes = source_digest_bytes * 2;pub const Error = graph_mod.Error || error{ AliasCycle, DeclaredTypeUnavailable, InvalidPublicPath, InvalidSourceDigest, InvalidSourceSpan, InvalidPublicMember, NotPublicDeclaration, PublicPathDepthExceeded, PublicPathNotFound, SourceDigestUnavailable, SourceDigestMismatch, SourceFileUnavailable, SourceSpanUnavailable,};/// A Zig container category preserved independently from graph node roles.pub const ContainerKind = enum { @"struct", @"enum", error_set, @"union", @"opaque",};/// A source-level member category that is part of a public Zig type surface.pub const MemberKind = enum { field, enum_tag, error_member,};/// Why a source member is preserved but not projected as a PublicMember.pub const MemberGapKind = enum { unsupported_container_member, unsupported_member_syntax,};/// An exact half-open byte range in a source file.pub const SourceSpan = struct { start_byte: u32, end_byte: u32,};/// Validated source location and digest for one declaration.pub const DeclarationSource = struct { file: []const u8, span: SourceSpan, digest: [source_digest_bytes]u8,};/// A public binding and the definition reached through its alias chain.pub const PublicDeclaration = struct { exported: model.Node, canonical: model.Node, /// Returns source-owned export docs or docs on the exact canonical declaration. pub fn documentation(self: PublicDeclaration) ?[]const u8 { if (self.exported.docstring) |docstring| return docstring; if (sameSourceFile(self.exported, self.canonical)) { if (moduleNode(self.canonical)) return null; } return self.canonical.docstring; } /// Returns the exact source span of the exported binding. pub fn bindingSourceSpan(self: PublicDeclaration) Error!SourceSpan { return declarationSourceSpan(self.exported); } /// Returns the exact source span of the canonical definition. pub fn canonicalSourceSpan(self: PublicDeclaration) Error!SourceSpan { return declarationSourceSpan(self.canonical); } /// Returns validated source evidence for the exported binding. pub fn bindingSource(self: PublicDeclaration) Error!DeclarationSource { return declarationSource(self.exported); } /// Returns validated source evidence for the canonical definition. pub fn canonicalSource(self: PublicDeclaration) Error!DeclarationSource { return declarationSource(self.canonical); }};/// Returns a validated exact source span stored on one declaration node.pub fn declarationSourceSpan(node: model.Node) Error!SourceSpan { const start_raw = model.pairValue(node.metadata, source_start_byte_key); const end_raw = model.pairValue(node.metadata, source_end_byte_key); if (start_raw == null and end_raw == null) return error.SourceSpanUnavailable; if (start_raw == null or end_raw == null) return error.InvalidSourceSpan; const start = std.fmt.parseInt(u32, start_raw.?, 10) catch return error.InvalidSourceSpan; const end = std.fmt.parseInt(u32, end_raw.?, 10) catch return error.InvalidSourceSpan; if (start >= end) return error.InvalidSourceSpan; return .{ .start_byte = start, .end_byte = end };}/// Returns validated file, span, and digest evidence for one declaration node.pub fn declarationSource(node: model.Node) Error!DeclarationSource { const file = node.file orelse return error.SourceFileUnavailable; if (file.len == 0) return error.SourceFileUnavailable; const encoded = model.pairValue(node.metadata, source_hash_key) orelse return error.SourceDigestUnavailable; if (encoded.len != source_digest_hex_bytes) { return error.InvalidSourceDigest; } for (encoded) |byte| { if (!std.ascii.isHex(byte) or std.ascii.isUpper(byte)) { return error.InvalidSourceDigest; } } var digest: [source_digest_bytes]u8 = undefined; _ = std.fmt.hexToBytes(&digest, encoded) catch return error.InvalidSourceDigest; return .{ .file = file, .span = try declarationSourceSpan(node), .digest = digest, };}/// Returns the SHA-256 digest for exact source bytes.pub fn sourceDigest(source: []const u8) [source_digest_bytes]u8 { var digest: [source_digest_bytes]u8 = undefined; std.crypto.hash.sha2.Sha256.hash(source, &digest, .{}); return digest;}/// Returns the exact declaration bytes after validating their stored span and digest.pub fn verifiedSource( evidence: DeclarationSource, contents: []const u8,) Error![]const u8 { if (evidence.span.start_byte >= evidence.span.end_byte or evidence.span.end_byte > contents.len) { return error.InvalidSourceSpan; } const exact = contents[evidence.span.start_byte..evidence.span.end_byte]; const digest = sourceDigest(exact); if (!std.mem.eql(u8, &digest, &evidence.digest)) { return error.SourceDigestMismatch; } return exact;}/// A member admitted through a public export and owned by its canonical type.////// The record and its strings borrow from the unchanged graph. Only the slice/// returned by publicMembers is allocated.pub const PublicMember = struct { owner: PublicDeclaration, node: model.Node, kind: MemberKind, /// The zero-based ordinal among source members owned by the canonical type. order: u32, /// Returns the exact identifier token, or null for a positional field. pub fn identifier(self: PublicMember) ?[]const u8 { return memberIdentifier(self.node); } /// Returns the exact source spelling of the member, excluding its docs. pub fn sourceSpelling(self: PublicMember) []const u8 { return model.pairValue(self.node.metadata, source_spelling_key) orelse unreachable; } /// Returns the exact field type expression when the source has one. pub fn typeExpression(self: PublicMember) ?[]const u8 { return model.pairValue(self.node.metadata, member_type_key); } /// Returns an exact field default or enum assigned-value expression. /// /// The explicit member kind determines how a renderer labels the value. pub fn valueExpression(self: PublicMember) ?[]const u8 { return model.pairValue(self.node.metadata, member_expression_key); } /// Returns source-owned documentation attached to this member. pub fn documentation(self: PublicMember) ?[]const u8 { return self.node.docstring; } /// Returns the exact half-open source byte range of sourceSpelling. pub fn sourceSpan(self: PublicMember) SourceSpan { return memberSourceSpan(self.node) orelse unreachable; }};/// A source member deliberately outside the supported public projection.////// The record and its strings borrow from the unchanged graph. Only the slice/// returned by publicMemberGaps is allocated.pub const PublicMemberGap = struct { owner: PublicDeclaration, node: model.Node, kind: MemberGapKind, /// The zero-based ordinal among source members owned by the canonical type. order: u32, /// Returns an exact identifier token when the source member has one. pub fn identifier(self: PublicMemberGap) ?[]const u8 { return memberIdentifier(self.node); } /// Returns the exact source spelling of the unsupported member. pub fn sourceSpelling(self: PublicMemberGap) []const u8 { return model.pairValue(self.node.metadata, source_spelling_key) orelse unreachable; } /// Returns source-owned documentation attached to this member. pub fn documentation(self: PublicMemberGap) ?[]const u8 { return self.node.docstring; } /// Returns the exact half-open source byte range of sourceSpelling. pub fn sourceSpan(self: PublicMemberGap) SourceSpan { return memberSourceSpan(self.node) orelse unreachable; }};/// Returns the borrowed name of the scanned module or package that owns a source file.pub fn ownerForFile(graph: graph_mod.Graph, file: []const u8) Error![]const u8 { var owner: ?[]const u8 = null; for (graph.nodes.items) |node| { if (!moduleNode(node)) continue; if (!std.mem.eql(u8, node.file orelse continue, file)) continue; if (owner != null) return error.AmbiguousName; owner = node.name; } return owner orelse error.NodeNotFound;}/// Returns public children in stable exported-name order.////// The slice owns only its records. Node strings borrow from the unchanged graph.pub fn publicDeclarations( allocator: std.mem.Allocator, graph: graph_mod.Graph, owner: []const u8, limits: limits_mod.Api,) (std.mem.Allocator.Error || Error)![]PublicDeclaration { if (graph_mod.getNode(&graph, owner) == null) return error.NodeNotFound; var count: usize = 0; for (graph_mod.outgoingEdges(&graph, owner)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; const node = graph_mod.getNode(&graph, edge.target) orelse continue; if (isPublic(node)) count += 1; } const declarations = try allocator.alloc(PublicDeclaration, count); errdefer allocator.free(declarations); var index: usize = 0; for (graph_mod.outgoingEdges(&graph, owner)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; const node = graph_mod.getNode(&graph, edge.target) orelse continue; if (!isPublic(node)) continue; declarations[index] = .{ .exported = node, .canonical = try canonicalDeclaration(graph, node, limits), }; index += 1; } std.debug.assert(index == declarations.len); std.mem.sort(PublicDeclaration, declarations, {}, declarationLessThan); return declarations;}/// Releases the record slice returned by publicDeclarations.pub fn freePublicDeclarations( allocator: std.mem.Allocator, declarations: []PublicDeclaration,) void { allocator.free(declarations);}/// Resolves one exact dotted path through the public surface of an owner.////// The returned nodes borrow from the unchanged graph. A quoted Zig identifier/// may contain dots and is treated as one path component.pub fn resolvePublicPath( allocator: std.mem.Allocator, graph: graph_mod.Graph, owner: []const u8, path: []const u8, limits: limits_mod.Api,) (std.mem.Allocator.Error || Error)!PublicDeclaration { if (path.len == 0 or path[0] == '.' or path[path.len - 1] == '.') { return error.InvalidPublicPath; } var current_owner = owner; var remaining = path; for (0..limits.public_path_depth) |_| { const component_end = try publicPathComponentEnd(remaining); const component = remaining[0..component_end]; if (component.len == 0) return error.InvalidPublicPath; const declarations = try publicDeclarations(allocator, graph, current_owner, limits); defer freePublicDeclarations(allocator, declarations); var found: ?PublicDeclaration = null; for (declarations) |declaration| { const name = directPublicName(current_owner, declaration.exported.name) orelse continue; if (!std.mem.eql(u8, name, component)) continue; if (found != null) return error.AmbiguousName; found = declaration; } const declaration = found orelse return error.PublicPathNotFound; if (component_end == remaining.len) return declaration; current_owner = declaration.canonical.name; remaining = remaining[component_end + 1 ..]; } return error.PublicPathDepthExceeded;}fn directPublicName(owner: []const u8, name: []const u8) ?[]const u8 { if (!std.mem.startsWith(u8, name, owner)) return null; if (name.len <= owner.len or name[owner.len] != '.') return null; const suffix = name[owner.len + 1 ..]; if (suffix.len == 0) return null; return suffix;}fn publicPathComponentEnd(path: []const u8) Error!usize { if (std.mem.startsWith(u8, path, "@\"")) { var index: usize = 2; var escaped = false; while (index < path.len) : (index += 1) { const byte = path[index]; if (escaped) { escaped = false; continue; } if (byte == '\\') { escaped = true; continue; } if (byte != '"') continue; if (index + 1 == path.len or path[index + 1] == '.') return index + 1; return error.InvalidPublicPath; } return error.InvalidPublicPath; } return std.mem.indexOfScalar(u8, path, '.') orelse path.len;}/// Returns canonical members admitted through one public Zig declaration.////// The slice owns only its records. Nodes and strings borrow from the unchanged/// graph. Opaque and non-container declarations return an empty slice.pub fn publicMembers( allocator: std.mem.Allocator, graph: graph_mod.Graph, declaration: PublicDeclaration,) (std.mem.Allocator.Error || Error)![]PublicMember { if (!isPublic(declaration.exported)) return error.NotPublicDeclaration; const owner = graph_mod.getNode(&graph, declaration.canonical.name) orelse return error.NodeNotFound; const expected = supportedMemberKind(containerKind(owner) orelse return &.{}) orelse return &.{}; return try projectPublicMembers(allocator, graph, declaration, owner, expected);}fn projectPublicMembers( allocator: std.mem.Allocator, graph: graph_mod.Graph, declaration: PublicDeclaration, owner: model.Node, expected: MemberKind,) (std.mem.Allocator.Error || Error)![]PublicMember { var count: usize = 0; for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; const node = graph_mod.getNode(&graph, edge.target) orelse continue; const kind = nodeMemberKind(node) orelse continue; if (kind != expected) return error.InvalidPublicMember; count += 1; } if (count == 0) return &.{}; const members = try allocator.alloc(PublicMember, count); errdefer allocator.free(members); var index: usize = 0; for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; const node = graph_mod.getNode(&graph, edge.target) orelse continue; const kind = nodeMemberKind(node) orelse continue; std.debug.assert(kind == expected); members[index] = try publicMember(declaration, node, kind); index += 1; } std.debug.assert(index == members.len); std.mem.sort(PublicMember, members, {}, memberLessThan); return members;}/// Releases the record slice returned by publicMembers.pub fn freePublicMembers( allocator: std.mem.Allocator, members: []PublicMember,) void { if (members.len != 0) allocator.free(members);}/// Returns explicit source members omitted from the supported projection.////// The slice owns only its records. Nodes and strings borrow from the unchanged/// graph. A container with no unsupported source members returns an empty slice.pub fn publicMemberGaps( allocator: std.mem.Allocator, graph: graph_mod.Graph, declaration: PublicDeclaration,) (std.mem.Allocator.Error || Error)![]PublicMemberGap { if (!isPublic(declaration.exported)) return error.NotPublicDeclaration; const owner = graph_mod.getNode(&graph, declaration.canonical.name) orelse return error.NodeNotFound; if (containerKind(owner) == null) return &.{}; var count: usize = 0; for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; const node = graph_mod.getNode(&graph, edge.target) orelse continue; if (!std.mem.eql(u8, node.type, model.NodeType.member_gap)) continue; count += 1; } if (count == 0) return &.{}; const gaps = try allocator.alloc(PublicMemberGap, count); errdefer allocator.free(gaps); var index: usize = 0; for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; const node = graph_mod.getNode(&graph, edge.target) orelse continue; if (!std.mem.eql(u8, node.type, model.NodeType.member_gap)) continue; gaps[index] = try publicMemberGap(declaration, node); index += 1; } std.debug.assert(index == gaps.len); std.mem.sort(PublicMemberGap, gaps, {}, memberGapLessThan); return gaps;}/// Releases the record slice returned by publicMemberGaps.pub fn freePublicMemberGaps( allocator: std.mem.Allocator, gaps: []PublicMemberGap,) void { if (gaps.len != 0) allocator.free(gaps);}pub fn visibility(node: model.Node) ?[]const u8 { return model.pairValue(node.metadata, visibility_key);}pub fn isPublic(node: model.Node) bool { return std.mem.eql(u8, visibility(node) orelse return false, "public");}/// Returns whether the scanner marked a declaration as test-only.pub fn isTestDeclaration(node: model.Node) bool { return std.mem.eql(u8, model.pairValue(node.metadata, test_key) orelse return false, "true");}pub fn signature(node: model.Node) ?[]const u8 { return model.pairValue(node.metadata, signature_key);}pub fn aliasTarget(node: model.Node) ?[]const u8 { return model.pairValue(node.metadata, alias_target_key);}/// Returns a source expression proved to be a direct declaration alias.pub fn directAliasTarget(node: model.Node) ?[]const u8 { return model.pairValue(node.metadata, direct_alias_target_key);}/// Returns the exact source-spelled Zig type annotation, or null when omitted.////// The returned slice borrows node metadata from the unchanged graph./// DeclaredTypeUnavailable means the scanner could not prove either state or/// encountered contradictory metadata. This fact makes no semantic type-/// equality claim.pub fn explicitDeclaredType(node: model.Node) Error!?[]const u8 { const state = model.pairValue(node.metadata, declared_type_state_key) orelse return error.DeclaredTypeUnavailable; const value = model.pairValue(node.metadata, declared_type_key); if (std.mem.eql(u8, state, "omitted")) { if (value != null) return error.DeclaredTypeUnavailable; return null; } if (!std.mem.eql(u8, state, "explicit")) { return error.DeclaredTypeUnavailable; } const raw = value orelse return error.DeclaredTypeUnavailable; if (raw.len == 0) return error.DeclaredTypeUnavailable; return raw;}test "explicit declared type distinguishes omitted and unavailable states" { const Expectation = union(enum) { unavailable, omitted, explicit: []const u8, }; const cases = [_]struct { name: []const u8, metadata: []const model.Pair, expectation: Expectation, }{ .{ .name = "missing state", .metadata = &.{}, .expectation = .unavailable }, .{ .name = "unknown state", .metadata = &.{.{ .key = declared_type_state_key, .value = "unknown" }}, .expectation = .unavailable }, .{ .name = "explicit missing value", .metadata = &.{.{ .key = declared_type_state_key, .value = "explicit" }}, .expectation = .unavailable }, .{ .name = "explicit empty value", .metadata = &.{ .{ .key = declared_type_state_key, .value = "explicit" }, .{ .key = declared_type_key, .value = "" } }, .expectation = .unavailable }, .{ .name = "omitted with value", .metadata = &.{ .{ .key = declared_type_state_key, .value = "omitted" }, .{ .key = declared_type_key, .value = "u8" } }, .expectation = .unavailable }, .{ .name = "omitted", .metadata = &.{.{ .key = declared_type_state_key, .value = "omitted" }}, .expectation = .omitted }, .{ .name = "explicit", .metadata = &.{ .{ .key = declared_type_state_key, .value = "explicit" }, .{ .key = declared_type_key, .value = "?*const u8" } }, .expectation = .{ .explicit = "?*const u8" } }, }; for (cases) |case| { const node: model.Node = .{ .name = case.name, .type = model.NodeType.constant, .metadata = case.metadata }; switch (case.expectation) { .unavailable => try std.testing.expectError(error.DeclaredTypeUnavailable, explicitDeclaredType(node)), .omitted => try std.testing.expect((try explicitDeclaredType(node)) == null), .explicit => |expected| { const actual = (try explicitDeclaredType(node)).?; try std.testing.expectEqualStrings(expected, actual); try std.testing.expect(actual.ptr == model.pairValue(node.metadata, declared_type_key).?.ptr); }, } }}/// Returns the explicit Zig container category stored by the scanner.pub fn containerKind(node: model.Node) ?ContainerKind { const raw = model.pairValue(node.metadata, container_kind_key) orelse return null; return std.meta.stringToEnum(ContainerKind, raw);}fn publicMember( owner: PublicDeclaration, node: model.Node, kind: MemberKind,) Error!PublicMember { if (kind != .field and memberIdentifier(node) == null) { return error.InvalidPublicMember; } if (model.pairValue(node.metadata, source_spelling_key) == null) { return error.InvalidPublicMember; } const order = memberOrder(node) orelse return error.InvalidPublicMember; _ = memberSourceSpan(node) orelse return error.InvalidPublicMember; if (node.file == null or node.line == null or node.end_line == null) { return error.InvalidPublicMember; } return .{ .owner = owner, .node = node, .kind = kind, .order = order };}fn publicMemberGap( owner: PublicDeclaration, node: model.Node,) Error!PublicMemberGap { const raw = model.pairValue(node.metadata, member_gap_key) orelse return error.InvalidPublicMember; const kind = std.meta.stringToEnum(MemberGapKind, raw) orelse return error.InvalidPublicMember; if (model.pairValue(node.metadata, source_spelling_key) == null) { return error.InvalidPublicMember; } const order = memberOrder(node) orelse return error.InvalidPublicMember; _ = memberSourceSpan(node) orelse return error.InvalidPublicMember; if (node.file == null or node.line == null or node.end_line == null) { return error.InvalidPublicMember; } return .{ .owner = owner, .node = node, .kind = kind, .order = order };}fn memberIdentifier(node: model.Node) ?[]const u8 { return model.pairValue(node.metadata, member_identifier_key);}fn memberOrder(node: model.Node) ?u32 { const raw = model.pairValue(node.metadata, member_order_key) orelse return null; return std.fmt.parseInt(u32, raw, 10) catch null;}fn memberSourceSpan(node: model.Node) ?SourceSpan { const start_raw = model.pairValue(node.metadata, source_start_byte_key) orelse return null; const end_raw = model.pairValue(node.metadata, source_end_byte_key) orelse return null; const start = std.fmt.parseInt(u32, start_raw, 10) catch return null; const end = std.fmt.parseInt(u32, end_raw, 10) catch return null; if (start > end) return null; return .{ .start_byte = start, .end_byte = end };}fn supportedMemberKind(kind: ContainerKind) ?MemberKind { return switch (kind) { .@"struct", .@"union" => .field, .@"enum" => .enum_tag, .error_set => .error_member, .@"opaque" => null, };}fn nodeMemberKind(node: model.Node) ?MemberKind { if (std.mem.eql(u8, node.type, model.NodeType.field)) return .field; if (std.mem.eql(u8, node.type, model.NodeType.enum_tag)) return .enum_tag; if (std.mem.eql(u8, node.type, model.NodeType.error_member)) { return .error_member; } return null;}fn canonicalDeclaration(graph: graph_mod.Graph, declaration: model.Node, limits: limits_mod.Api) Error!model.Node { return canonicalDeclarationDepth(graph, declaration, 0, limits);}fn canonicalDeclarationDepth( graph: graph_mod.Graph, declaration: model.Node, depth: usize, limits: limits_mod.Api,) Error!model.Node { if (depth == limits.alias_resolution_depth) return error.AliasCycle; var current = declaration; for (0..graph.nodes.items.len + 1) |_| { const owner = declarationOwner(graph, current.name) orelse return current; const next = try resolveAliasTarget(graph, owner, current, depth, limits) orelse return current; if (std.mem.eql(u8, next.name, current.name)) return current; if (std.mem.eql(u8, next.name, declaration.name)) { if (current.file != null and declaration.file != null and !std.mem.eql(u8, current.file.?, declaration.file.?)) return current; return error.AliasCycle; } current = next; } return error.AliasCycle;}fn resolveAliasTarget( graph: graph_mod.Graph, owner: []const u8, declaration: model.Node, depth: usize, limits: limits_mod.Api,) Error!?model.Node { const raw = directAliasTarget(declaration) orelse return null; if (graph_mod.getNode(&graph, raw)) |node| return node; const dot = std.mem.indexOfScalar(u8, raw, '.') orelse { const child = childNamed(graph, owner, raw); if (child) |node| { if (!std.mem.eql(u8, node.name, declaration.name)) return node; } if (!importBinding(declaration)) return child; return localPackageRoot(graph, owner, raw) orelse child; }; const binding = childNamed(graph, owner, raw[0..dot]) orelse return null; if (std.mem.eql(u8, binding.name, declaration.name)) return declaration; const base = try canonicalDeclarationDepth(graph, binding, depth + 1, limits); return joinedNode(graph, base.name, raw[dot..]);}fn importBinding(node: model.Node) bool { return std.mem.indexOf(u8, signature(node) orelse return false, "@import(") != null;}fn localPackageRoot( graph: graph_mod.Graph, owner: []const u8, raw: []const u8,) ?model.Node { if (std.mem.indexOfScalar(u8, raw, '.') != null) return null; var end = std.mem.lastIndexOfScalar(u8, owner, '.') orelse return null; while (true) { const prefix = owner[0..end]; const candidate = joinedChildNode(graph, prefix, raw); if (candidate) |node| { if (moduleNode(node)) { if (std.mem.eql(u8, node.type, model.NodeType.package)) { return childNamed(graph, node.name, "root") orelse node; } return node; } } end = std.mem.lastIndexOfScalar(u8, prefix, '.') orelse break; } return null;}fn joinedChildNode( graph: graph_mod.Graph, prefix: []const u8, leaf: []const u8,) ?model.Node { return dottedJoinedNode(graph, prefix, leaf);}fn dottedJoinedNode( graph: graph_mod.Graph, prefix: []const u8, leaf: []const u8,) ?model.Node { if (leaf.len != 0) { var iterator = graph_mod.suffixIterator(&graph, leaf); while (iterator.nextNode()) |node| { if (node.name.len != prefix.len + 1 + leaf.len) continue; if (!std.mem.startsWith(u8, node.name, prefix)) continue; if (node.name[prefix.len] != '.') continue; if (std.mem.eql(u8, node.name[prefix.len + 1 ..], leaf)) return node.*; } return null; } for (graph.nodes.items) |node| { if (node.name.len != prefix.len + 1 + leaf.len) continue; if (!std.mem.startsWith(u8, node.name, prefix)) continue; if (node.name[prefix.len] != '.') continue; if (std.mem.eql(u8, node.name[prefix.len + 1 ..], leaf)) return node; } return null;}fn declarationOwner(graph: graph_mod.Graph, name: []const u8) ?[]const u8 { var owner: ?[]const u8 = null; for (graph_mod.incomingEdges(&graph, name)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; if (owner != null) return null; owner = edge.source; } return owner;}fn childNamed( graph: graph_mod.Graph, owner: []const u8, leaf: []const u8,) ?model.Node { for (graph_mod.outgoingEdges(&graph, owner)) |edge_index| { const edge = graph.edges.items[edge_index]; if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue; const node = graph_mod.getNode(&graph, edge.target) orelse continue; const split = std.mem.lastIndexOfScalar(u8, node.name, '.') orelse 0; const start = split + @intFromBool(split != 0); if (std.mem.eql(u8, node.name[start..], leaf)) return node; } return null;}fn joinedNode( graph: graph_mod.Graph, prefix: []const u8, suffix: []const u8,) ?model.Node { if (suffix.len != 0 and suffix[0] == '.') { return dottedJoinedNode(graph, prefix, suffix[1..]); } for (graph.nodes.items) |node| { if (node.name.len != prefix.len + suffix.len) continue; if (!std.mem.startsWith(u8, node.name, prefix)) continue; if (std.mem.eql(u8, node.name[prefix.len..], suffix)) return node; } return null;}fn expectExactJoinedNodes(graph: graph_mod.Graph) !void { try std.testing.expectEqualStrings( "pkg.foo.Value", joinedChildNode(graph, "pkg.foo", "Value").?.name, ); try std.testing.expectEqualStrings( "pkg.foo.Part.Value", joinedNode(graph, "pkg.foo", ".Part.Value").?.name, ); try std.testing.expectEqualStrings( "pkg.foo.@\"dot.name\"", joinedNode(graph, "pkg.foo", ".@\"dot.name\"").?.name, ); try std.testing.expectEqualStrings( "pkg.foox", joinedNode(graph, "pkg.foo", "x").?.name, ); try std.testing.expectEqualStrings( "pkg.foo", joinedNode(graph, "pkg.foo", "").?.name, ); try std.testing.expectEqualStrings( "pkg.foo.", joinedNode(graph, "pkg.foo", ".").?.name, ); try std.testing.expectEqualStrings( "pkg.foo.", joinedChildNode(graph, "pkg.foo", "").?.name, ); try std.testing.expect(joinedNode(graph, "pkg.foo", ".Missing") == null);}test "exact joined nodes preserve indexed and linear semantics" { var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); for ([_][]const u8{ "pkg.foo", "pkg.foo.Value", "pkg.foobar.Value", "alt.foo.Value", "other.foo.Value", "pkg.foo.Part.Value", "pkg.foo.@\"dot.name\"", "pkg.foox", "pkg.foo.", }) |name| try graph_mod.addNode(&graph, .{ .name = name, .type = model.NodeType.type }); try expectExactJoinedNodes(graph); try graph_mod.buildSuffixIndex(&graph); try std.testing.expect(graph_mod.suffixIndexReady(graph)); try expectExactJoinedNodes(graph); try graph_mod.addNode(&graph, .{ .name = "new.foo.Value", .type = model.NodeType.type }); try std.testing.expect(!graph_mod.suffixIndexReady(graph)); try expectExactJoinedNodes(graph); try std.testing.expectEqualStrings( "new.foo.Value", joinedChildNode(graph, "new.foo", "Value").?.name, );}fn moduleNode(node: model.Node) bool { return std.mem.eql(u8, node.type, model.NodeType.module) or std.mem.eql(u8, node.type, model.NodeType.package);}fn sameSourceFile(left: model.Node, right: model.Node) bool { const left_file = left.file orelse return false; const right_file = right.file orelse return false; return std.mem.eql(u8, left_file, right_file);}fn declarationLessThan(_: void, left: PublicDeclaration, right: PublicDeclaration) bool { return std.mem.lessThan(u8, left.exported.name, right.exported.name);}fn memberLessThan(_: void, left: PublicMember, right: PublicMember) bool { if (left.order != right.order) return left.order < right.order; return std.mem.lessThan(u8, left.node.name, right.node.name);}fn memberGapLessThan(_: void, left: PublicMemberGap, right: PublicMemberGap) bool { if (left.order != right.order) return left.order < right.order; return std.mem.lessThan(u8, left.node.name, right.node.name);}test "public declaration spans preserve binding and canonical evidence" { const binding_bytes = "pub const Alias"; const canonical_bytes = "pub const Value = struct {};"; const binding_hash = std.fmt.bytesToHex(sourceDigest(binding_bytes), .lower); const canonical_hash = std.fmt.bytesToHex(sourceDigest(canonical_bytes), .lower); const binding_metadata = [_]model.Pair{ .{ .key = source_start_byte_key, .value = "4" }, .{ .key = source_end_byte_key, .value = "19" }, .{ .key = source_hash_key, .value = &binding_hash }, }; const canonical_metadata = [_]model.Pair{ .{ .key = source_start_byte_key, .value = "30" }, .{ .key = source_end_byte_key, .value = "90" }, .{ .key = source_hash_key, .value = &canonical_hash }, }; const declaration = PublicDeclaration{ .exported = .{ .name = "root.Alias", .type = model.NodeType.constant, .file = "root.zig", .metadata = &binding_metadata }, .canonical = .{ .name = "root.Value", .type = model.NodeType.class, .file = "value.zig", .metadata = &canonical_metadata }, }; try std.testing.expectEqual(@as(u32, 4), (try declaration.bindingSourceSpan()).start_byte); try std.testing.expectEqual(@as(u32, 90), (try declaration.canonicalSourceSpan()).end_byte); try std.testing.expectEqualStrings("root.zig", (try declaration.bindingSource()).file); try std.testing.expectEqual(binding_hash, std.fmt.bytesToHex( (try declaration.bindingSource()).digest, .lower, )); const missing = model.Node{ .name = "root.Missing", .type = model.NodeType.constant }; try std.testing.expectError(error.SourceSpanUnavailable, declarationSourceSpan(missing)); try std.testing.expectError(error.SourceFileUnavailable, declarationSource(missing)); const malformed = [_]model.Pair{ .{ .key = source_start_byte_key, .value = "9" }, .{ .key = source_end_byte_key, .value = "9" }, .{ .key = source_hash_key, .value = "not-a-digest" }, }; const invalid = model.Node{ .name = "root.Invalid", .type = model.NodeType.constant, .file = "root.zig", .metadata = &malformed, }; try std.testing.expectError(error.InvalidSourceSpan, declarationSourceSpan(invalid)); try std.testing.expectError(error.InvalidSourceDigest, declarationSource(invalid));}test "declaration source requires complete lower-case evidence" { const span_only = [_]model.Pair{ .{ .key = source_start_byte_key, .value = "0" }, .{ .key = source_end_byte_key, .value = "8" }, }; const missing_digest = model.Node{ .name = "root.MissingDigest", .type = model.NodeType.constant, .file = "root.zig", .metadata = &span_only, }; try std.testing.expectError( error.SourceDigestUnavailable, declarationSource(missing_digest), ); const upper_hash = [_]model.Pair{ .{ .key = source_start_byte_key, .value = "0" }, .{ .key = source_end_byte_key, .value = "8" }, .{ .key = source_hash_key, .value = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" }, }; var invalid = missing_digest; invalid.metadata = &upper_hash; try std.testing.expectError(error.InvalidSourceDigest, declarationSource(invalid));}test "verified source rejects stale and out-of-range declaration evidence" { const contents = "prefix pub fn run() void {} suffix"; const exact = "pub fn run() void {}"; const start = std.mem.indexOf(u8, contents, exact).?; var evidence = DeclarationSource{ .file = "root.zig", .span = .{ .start_byte = @intCast(start), .end_byte = @intCast(start + exact.len), }, .digest = sourceDigest(exact), }; try std.testing.expectEqualStrings( exact, try verifiedSource(evidence, contents), ); evidence.digest[0] ^= 1; try std.testing.expectError( error.SourceDigestMismatch, verifiedSource(evidence, contents), ); evidence.span.end_byte = @intCast(contents.len + 1); try std.testing.expectError(error.InvalidSourceSpan, verifiedSource(evidence, contents));}test "exact public paths traverse canonical aliases and quoted identifiers" { const public = [_]model.Pair{.{ .key = visibility_key, .value = "public" }}; const alias = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "core.Block" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); for ([_]model.Node{ .{ .name = "root", .type = model.NodeType.module }, .{ .name = "root.Block", .type = model.NodeType.type, .metadata = &alias }, .{ .name = "core", .type = model.NodeType.module }, .{ .name = "core.Block", .type = model.NodeType.class, .metadata = &public }, .{ .name = "core.Block.getPredecessors", .type = model.NodeType.method, .metadata = &public, }, .{ .name = "core.Block.@\"dot.name\"", .type = model.NodeType.method, .metadata = &public, }, }) |node| try graph_mod.addNode(&graph, node); for ([_]model.Edge{ .{ .source = "root", .rel = model.RelType.contains, .target = "root.Block" }, .{ .source = "core", .rel = model.RelType.contains, .target = "core.Block" }, .{ .source = "core.Block", .rel = model.RelType.contains, .target = "core.Block.getPredecessors", }, .{ .source = "core.Block", .rel = model.RelType.contains, .target = "core.Block.@\"dot.name\"", }, }) |edge| try graph_mod.addEdge(&graph, edge); const method = try resolvePublicPath( std.testing.allocator, graph, "root", "Block.getPredecessors", testing_limits, ); try std.testing.expectEqualStrings( "core.Block.getPredecessors", method.canonical.name, ); const quoted = try resolvePublicPath( std.testing.allocator, graph, "root", "Block.@\"dot.name\"", testing_limits, ); try std.testing.expectEqualStrings("core.Block.@\"dot.name\"", quoted.canonical.name); try std.testing.expectError( error.PublicPathNotFound, resolvePublicPath(std.testing.allocator, graph, "root", "Block.missing", testing_limits), ); try std.testing.expectError( error.InvalidPublicPath, resolvePublicPath(std.testing.allocator, graph, "root", "Block.", testing_limits), );}test "public declarations resolve aliases and retain export facts" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); defer graph_mod.deinit(&graph); try addProjectionFixture(&graph); const owner = try ownerForFile(graph, "lib/api/src/root.zig"); try std.testing.expectEqualStrings("lib.api.src.root", owner); const declarations = try publicDeclarations(std.testing.allocator, graph, owner, testing_limits); defer freePublicDeclarations(std.testing.allocator, declarations); try std.testing.expectEqual(@as(usize, 2), declarations.len); try std.testing.expectEqualStrings("lib.api.src.root.run", declarations[0].exported.name); try std.testing.expectEqualStrings("lib.api.src.site.root.run", declarations[0].canonical.name); try std.testing.expectEqualStrings("Runs the site.", declarations[0].documentation().?); try std.testing.expectEqualStrings("pub const run = site.run;", signature(declarations[0].exported).?); try std.testing.expectEqualStrings("lib.api.src.site.root", declarations[1].canonical.name);}test "public declarations resolve local packages through private import bindings" { const public_alias = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "schema" }, .{ .key = signature_key, .value = "pub const event = @import(\"schema\");" }, }; const public_event_alias = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "event.Event" }, }; const public_schema_event_alias = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "event_data.Event" }, }; const private_import = [_]model.Pair{ .{ .key = visibility_key, .value = "private" }, .{ .key = direct_alias_target_key, .value = "pkg.src.schema.event" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); const nodes = [_]model.Node{ .{ .name = "pkg.src.root", .type = model.NodeType.module }, .{ .name = "pkg.src.root.event", .type = model.NodeType.constant, .metadata = &public_alias }, .{ .name = "pkg.src.root.Event", .type = model.NodeType.type, .metadata = &public_event_alias }, .{ .name = "pkg.src.schema", .type = model.NodeType.package }, .{ .name = "pkg.src.schema.root", .type = model.NodeType.module }, .{ .name = "pkg.src.schema.root.event_data", .type = model.NodeType.constant, .metadata = &private_import }, .{ .name = "pkg.src.schema.root.Event", .type = model.NodeType.type, .metadata = &public_schema_event_alias }, .{ .name = "pkg.src.schema.event", .type = model.NodeType.module }, .{ .name = "pkg.src.schema.event.Event", .type = model.NodeType.class, .docstring = "Durable event." }, }; for (nodes) |node| try graph_mod.addNode(&graph, node); const edges = [_]model.Edge{ .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.event" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.Event" }, .{ .source = "pkg.src.schema", .rel = model.RelType.contains, .target = "pkg.src.schema.root" }, .{ .source = "pkg.src.schema.root", .rel = model.RelType.contains, .target = "pkg.src.schema.root.event_data" }, .{ .source = "pkg.src.schema.root", .rel = model.RelType.contains, .target = "pkg.src.schema.root.Event" }, .{ .source = "pkg.src.schema.event", .rel = model.RelType.contains, .target = "pkg.src.schema.event.Event" }, }; for (edges) |edge| try graph_mod.addEdge(&graph, edge); try graph_mod.buildSuffixIndex(&graph); const declarations = try publicDeclarations( std.testing.allocator, graph, "pkg.src.root", testing_limits, ); defer freePublicDeclarations(std.testing.allocator, declarations); try std.testing.expectEqual(@as(usize, 2), declarations.len); try std.testing.expectEqualStrings( "pkg.src.schema.event.Event", declarations[0].canonical.name, ); try std.testing.expectEqualStrings( "pkg.src.schema.root", declarations[1].canonical.name, );}test "public declarations resolve local packages through same-name import bindings" { const public_capacity = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "capacity" }, .{ .key = signature_key, .value = "pub const capacity = @import(\"capacity\");" }, }; const public_helper = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "support" }, }; const private_support = [_]model.Pair{ .{ .key = visibility_key, .value = "private" }, }; const public_budget = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); const nodes = [_]model.Node{ .{ .name = "pkg.src.root", .type = model.NodeType.module, .file = "pkg/src/root.zig" }, .{ .name = "pkg.src.root.capacity", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .line = 3, .metadata = &public_capacity }, .{ .name = "pkg.src.root.helper", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .line = 4, .metadata = &public_helper }, .{ .name = "pkg.src.root.support", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .line = 5, .metadata = &private_support }, .{ .name = "pkg.src.capacity", .type = model.NodeType.package }, .{ .name = "pkg.src.capacity.root", .type = model.NodeType.module, .file = "pkg/src/capacity/root.zig" }, .{ .name = "pkg.src.capacity.root.Budget", .type = model.NodeType.class, .file = "pkg/src/capacity/root.zig", .line = 2, .docstring = "Bounded byte budget.", .metadata = &public_budget }, }; for (nodes) |node| try graph_mod.addNode(&graph, node); const edges = [_]model.Edge{ .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.capacity" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.helper" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.support" }, .{ .source = "pkg.src.capacity", .rel = model.RelType.contains, .target = "pkg.src.capacity.root" }, .{ .source = "pkg.src.capacity.root", .rel = model.RelType.contains, .target = "pkg.src.capacity.root.Budget" }, }; for (edges) |edge| try graph_mod.addEdge(&graph, edge); try graph_mod.buildSuffixIndex(&graph); const declarations = try publicDeclarations( std.testing.allocator, graph, "pkg.src.root", testing_limits, ); defer freePublicDeclarations(std.testing.allocator, declarations); try std.testing.expectEqual(@as(usize, 2), declarations.len); try std.testing.expectEqualStrings("pkg.src.root.capacity", declarations[0].exported.name); try std.testing.expectEqualStrings("pkg.src.capacity.root", declarations[0].canonical.name); try std.testing.expectEqualStrings("pkg/src/root.zig", declarations[0].exported.file.?); try std.testing.expectEqualStrings("pkg/src/capacity/root.zig", declarations[0].canonical.file.?); try std.testing.expectEqualStrings("pkg.src.root.helper", declarations[1].exported.name); try std.testing.expectEqualStrings("pkg.src.root.support", declarations[1].canonical.name); const member = try resolvePublicPath( std.testing.allocator, graph, "pkg.src.root", "capacity.Budget", testing_limits, ); try std.testing.expectEqualStrings("pkg.src.capacity.root.Budget", member.canonical.name); try std.testing.expectEqualStrings("Bounded byte budget.", member.documentation().?);}test "public declarations keep unresolvable same-name import bindings terminal" { const public_std = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "std" }, .{ .key = signature_key, .value = "pub const std = @import(\"std\");" }, }; const public_capacity = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "capacity" }, .{ .key = signature_key, .value = "pub const capacity = @import(\"capacity\");" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); const nodes = [_]model.Node{ .{ .name = "pkg.src.root", .type = model.NodeType.module, .file = "pkg/src/root.zig" }, .{ .name = "pkg.src.root.std", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .metadata = &public_std }, .{ .name = "pkg.src.root.capacity", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .metadata = &public_capacity }, .{ .name = "other.src.capacity", .type = model.NodeType.package }, .{ .name = "other.src.capacity.root", .type = model.NodeType.module, .file = "other/src/capacity/root.zig" }, }; for (nodes) |node| try graph_mod.addNode(&graph, node); const edges = [_]model.Edge{ .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.std" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.capacity" }, .{ .source = "other.src.capacity", .rel = model.RelType.contains, .target = "other.src.capacity.root" }, }; for (edges) |edge| try graph_mod.addEdge(&graph, edge); try graph_mod.buildSuffixIndex(&graph); const declarations = try publicDeclarations( std.testing.allocator, graph, "pkg.src.root", testing_limits, ); defer freePublicDeclarations(std.testing.allocator, declarations); try std.testing.expectEqual(@as(usize, 2), declarations.len); try std.testing.expectEqualStrings("pkg.src.root.capacity", declarations[0].exported.name); try std.testing.expectEqualStrings("pkg.src.root.capacity", declarations[0].canonical.name); try std.testing.expectEqualStrings("pkg.src.root.std", declarations[1].exported.name); try std.testing.expectEqualStrings("pkg.src.root.std", declarations[1].canonical.name);}test "public declarations resolve dotted private alias chains" { const public_harness = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "harness.Harness" }, }; const public_agent = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "pkg.src.agent.root" }, }; const public_harness_namespace = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "pkg.src.agent.harness.root" }, }; const private_harness = [_]model.Pair{ .{ .key = visibility_key, .value = "private" }, .{ .key = direct_alias_target_key, .value = "agent.harness" }, }; const public_log = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "log.Log" }, }; const private_history = [_]model.Pair{ .{ .key = visibility_key, .value = "private" }, .{ .key = direct_alias_target_key, .value = "pkg.src.history.root" }, }; const private_log = [_]model.Pair{ .{ .key = visibility_key, .value = "private" }, .{ .key = direct_alias_target_key, .value = "history.log" }, }; const public_history_log = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "pkg.src.history.log" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); const nodes = [_]model.Node{ .{ .name = "pkg.src.root", .type = model.NodeType.module }, .{ .name = "pkg.src.root.agent", .type = model.NodeType.constant, .metadata = &public_agent }, .{ .name = "pkg.src.root.harness", .type = model.NodeType.constant, .metadata = &private_harness }, .{ .name = "pkg.src.root.Harness", .type = model.NodeType.type, .metadata = &public_harness }, .{ .name = "pkg.src.root.history", .type = model.NodeType.constant, .metadata = &private_history }, .{ .name = "pkg.src.root.log", .type = model.NodeType.constant, .metadata = &private_log }, .{ .name = "pkg.src.root.Log", .type = model.NodeType.type, .metadata = &public_log }, .{ .name = "pkg.src.agent.root", .type = model.NodeType.module }, .{ .name = "pkg.src.agent.root.harness", .type = model.NodeType.constant, .metadata = &public_harness_namespace }, .{ .name = "pkg.src.agent.harness.root", .type = model.NodeType.module }, .{ .name = "pkg.src.agent.harness.root.Harness", .type = model.NodeType.class, .docstring = "Deterministic session owner." }, .{ .name = "pkg.src.history.root", .type = model.NodeType.module }, .{ .name = "pkg.src.history.root.log", .type = model.NodeType.constant, .metadata = &public_history_log }, .{ .name = "pkg.src.history.log", .type = model.NodeType.module }, .{ .name = "pkg.src.history.log.Log", .type = model.NodeType.class, .docstring = "Committed history owner." }, }; for (nodes) |node| try graph_mod.addNode(&graph, node); const edges = [_]model.Edge{ .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.agent" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.harness" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.Harness" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.history" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.log" }, .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.Log" }, .{ .source = "pkg.src.agent.root", .rel = model.RelType.contains, .target = "pkg.src.agent.root.harness" }, .{ .source = "pkg.src.agent.harness.root", .rel = model.RelType.contains, .target = "pkg.src.agent.harness.root.Harness" }, .{ .source = "pkg.src.history.root", .rel = model.RelType.contains, .target = "pkg.src.history.root.log" }, .{ .source = "pkg.src.history.log", .rel = model.RelType.contains, .target = "pkg.src.history.log.Log" }, }; for (edges) |edge| try graph_mod.addEdge(&graph, edge); try graph_mod.buildSuffixIndex(&graph); const declarations = try publicDeclarations( std.testing.allocator, graph, "pkg.src.root", testing_limits, ); defer freePublicDeclarations(std.testing.allocator, declarations); try std.testing.expectEqual(@as(usize, 3), declarations.len); try std.testing.expectEqualStrings( "pkg.src.agent.harness.root.Harness", declarations[0].canonical.name, ); try std.testing.expectEqualStrings( "pkg.src.history.log.Log", declarations[1].canonical.name, ); try std.testing.expectEqualStrings("pkg.src.agent.root", declarations[2].canonical.name);}test "public declarations stop at self-resolving import bindings" { const public_import = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = alias_target_key, .value = "pretty" }, .{ .key = direct_alias_target_key, .value = "pretty" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); try graph_mod.addNode(&graph, .{ .name = "root", .type = model.NodeType.module, }); try graph_mod.addNode(&graph, .{ .name = "root.pretty", .type = model.NodeType.constant, .metadata = &public_import, }); try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = "root.pretty", }); const declarations = try publicDeclarations(std.testing.allocator, graph, "root", testing_limits); defer freePublicDeclarations(std.testing.allocator, declarations); try std.testing.expectEqual(@as(usize, 1), declarations.len); try std.testing.expectEqualStrings("root.pretty", declarations[0].canonical.name);}test "public declarations reject nontrivial alias cycles" { const public_first = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = alias_target_key, .value = "second" }, .{ .key = direct_alias_target_key, .value = "second" }, }; const private_second = [_]model.Pair{ .{ .key = alias_target_key, .value = "first" }, .{ .key = direct_alias_target_key, .value = "first" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); try graph_mod.addNode(&graph, .{ .name = "root", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "root.first", .type = model.NodeType.constant, .metadata = &public_first, }); try graph_mod.addNode(&graph, .{ .name = "root.second", .type = model.NodeType.constant, .metadata = &private_second, }); try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = "root.first", }); try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = "root.second", }); try std.testing.expectError( error.AliasCycle, publicDeclarations(std.testing.allocator, graph, "root", testing_limits), );}test "public declarations bound recursive dotted alias cycles" { const public_value = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = direct_alias_target_key, .value = "first.Value" }, }; const first = [_]model.Pair{ .{ .key = visibility_key, .value = "private" }, .{ .key = direct_alias_target_key, .value = "second.Value" }, }; const second = [_]model.Pair{ .{ .key = visibility_key, .value = "private" }, .{ .key = direct_alias_target_key, .value = "first.Value" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); const nodes = [_]model.Node{ .{ .name = "root", .type = model.NodeType.module }, .{ .name = "root.Value", .type = model.NodeType.type, .metadata = &public_value }, .{ .name = "root.first", .type = model.NodeType.constant, .metadata = &first }, .{ .name = "root.second", .type = model.NodeType.constant, .metadata = &second }, }; for (nodes) |node| try graph_mod.addNode(&graph, node); for (nodes[1..]) |node| try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = node.name, }); try std.testing.expectError( error.AliasCycle, publicDeclarations(std.testing.allocator, graph, "root", testing_limits), );}test "public members retain canonical ownership and stable source order" { const public_container = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = container_kind_key, .value = "struct" }, }; const later = memberFixtureMetadata("later", "1", "later: u8", "20", "29"); const earlier = memberFixtureMetadata("earlier", "0", "earlier: u8", "5", "16"); var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); try graph_mod.addNode(&graph, .{ .name = "root", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "root.Options", .type = model.NodeType.class, .file = "root.zig", .metadata = &public_container, }); try addMemberFixtureNode(&graph, "root.Options.later", &later); try addMemberFixtureNode(&graph, "root.Options.earlier", &earlier); try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = "root.Options" }); try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.later" }); try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.earlier" }); const declarations = try publicDeclarations(std.testing.allocator, graph, "root", testing_limits); defer freePublicDeclarations(std.testing.allocator, declarations); const members = try publicMembers(std.testing.allocator, graph, declarations[0]); defer freePublicMembers(std.testing.allocator, members); try std.testing.expectEqual(@as(usize, 2), members.len); try std.testing.expectEqualStrings("earlier", members[0].identifier().?); try std.testing.expectEqualStrings(declarations[0].canonical.name, members[0].owner.canonical.name); try std.testing.expectEqual(@as(u32, 5), members[0].sourceSpan().start_byte); const malformed = [_]model.Pair{ .{ .key = member_identifier_key, .value = "broken" }, .{ .key = member_order_key, .value = "2" }, .{ .key = source_spelling_key, .value = "broken: u8" }, .{ .key = source_start_byte_key, .value = "30" }, }; try addMemberFixtureNode(&graph, "root.Options.broken", &malformed); try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.broken" }); try std.testing.expectError( error.InvalidPublicMember, publicMembers(std.testing.allocator, graph, declarations[0]), );}test "public member gaps preserve explicit unsupported source facts" { const public_container = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = container_kind_key, .value = "struct" }, }; const gap_metadata = [_]model.Pair{ .{ .key = member_gap_key, .value = "unsupported_member_syntax" }, .{ .key = member_order_key, .value = "0" }, .{ .key = source_spelling_key, .value = "u8" }, .{ .key = source_start_byte_key, .value = "5" }, .{ .key = source_end_byte_key, .value = "7" }, }; var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); try graph_mod.addNode(&graph, .{ .name = "root", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "root.Tuple", .type = model.NodeType.class, .file = "root.zig", .metadata = &public_container, }); try graph_mod.addNode(&graph, .{ .name = "root.Tuple.$smg-gap-0", .type = model.NodeType.member_gap, .file = "root.zig", .line = 1, .end_line = 1, .metadata = &gap_metadata, }); try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = "root.Tuple" }); try graph_mod.addEdge(&graph, .{ .source = "root.Tuple", .rel = model.RelType.contains, .target = "root.Tuple.$smg-gap-0" }); const declarations = try publicDeclarations(std.testing.allocator, graph, "root", testing_limits); defer freePublicDeclarations(std.testing.allocator, declarations); const gaps = try publicMemberGaps(std.testing.allocator, graph, declarations[0]); defer freePublicMemberGaps(std.testing.allocator, gaps); try std.testing.expectEqual(@as(usize, 1), gaps.len); try std.testing.expectEqual(MemberGapKind.unsupported_member_syntax, gaps[0].kind); try std.testing.expect(gaps[0].identifier() == null); try std.testing.expectEqualStrings("u8", gaps[0].sourceSpelling()); try std.testing.expectEqual(@as(u32, 5), gaps[0].sourceSpan().start_byte);}test "public member record allocation propagates out of memory" { const public_container = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = container_kind_key, .value = "struct" }, }; const member_metadata = memberFixtureMetadata("field", "0", "field: u8", "0", "9"); var graph = graph_mod.init(std.testing.allocator); defer graph_mod.deinit(&graph); try graph_mod.addNode(&graph, .{ .name = "root.Options", .type = model.NodeType.class, .file = "root.zig", .metadata = &public_container, }); try addMemberFixtureNode(&graph, "root.Options.field", &member_metadata); try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.field" }); const owner = graph_mod.getNode(&graph, "root.Options").?; var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{ .fail_index = 0, }); try std.testing.expectError( error.OutOfMemory, projectPublicMembers( failing.allocator(), graph, .{ .exported = owner, .canonical = owner }, owner, .field, ), );}fn memberFixtureMetadata( comptime identifier: []const u8, comptime order: []const u8, comptime spelling: []const u8, comptime start: []const u8, comptime end: []const u8,) [5]model.Pair { return .{ .{ .key = member_identifier_key, .value = identifier }, .{ .key = member_order_key, .value = order }, .{ .key = source_spelling_key, .value = spelling }, .{ .key = source_start_byte_key, .value = start }, .{ .key = source_end_byte_key, .value = end }, };}fn addMemberFixtureNode( graph: *graph_mod.Graph, name: []const u8, metadata: []const model.Pair,) !void { try graph_mod.addNode(graph, .{ .name = name, .type = model.NodeType.field, .file = "root.zig", .line = 1, .end_line = 1, .metadata = metadata, });}fn addProjectionFixture(graph: *graph_mod.Graph) !void { const scanned = [_]model.Pair{.{ .key = "source", .value = "scan" }}; const public_site = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = alias_target_key, .value = "lib.api.src.site.root" }, .{ .key = direct_alias_target_key, .value = "lib.api.src.site.root" }, }; const public_run = [_]model.Pair{ .{ .key = visibility_key, .value = "public" }, .{ .key = signature_key, .value = "pub const run = site.run;" }, .{ .key = alias_target_key, .value = "site.run" }, .{ .key = direct_alias_target_key, .value = "site.run" }, }; try graph_mod.addNode(graph, .{ .name = "lib.api.src.root", .type = model.NodeType.module, .file = "lib/api/src/root.zig", .metadata = &scanned, }); try graph_mod.addNode(graph, .{ .name = "lib.api.src.root.site", .type = model.NodeType.constant, .metadata = &public_site, }); try graph_mod.addNode(graph, .{ .name = "lib.api.src.root.run", .type = model.NodeType.constant, .file = "lib/api/src/root.zig", .metadata = &public_run, }); try graph_mod.addNode(graph, .{ .name = "lib.api.src.root.hidden", .type = model.NodeType.constant, .metadata = &scanned, }); try graph_mod.addNode(graph, .{ .name = "lib.api.src.site.root", .type = model.NodeType.module, .file = "lib/api/src/site/root.zig", .metadata = &scanned, }); try graph_mod.addNode(graph, .{ .name = "lib.api.src.site.root.run", .type = model.NodeType.function, .file = "lib/api/src/site/root.zig", .docstring = "Runs the site.", .metadata = &scanned, }); const contains = model.RelType.contains; try graph_mod.addEdge(graph, .{ .source = "lib.api.src.root", .rel = contains, .target = "lib.api.src.root.site" }); try graph_mod.addEdge(graph, .{ .source = "lib.api.src.root", .rel = contains, .target = "lib.api.src.root.run" }); try graph_mod.addEdge(graph, .{ .source = "lib.api.src.root", .rel = contains, .target = "lib.api.src.root.hidden" }); try graph_mod.addEdge(graph, .{ .source = "lib.api.src.site.root", .rel = contains, .target = "lib.api.src.site.root.run" });}Source: tools/smg/src/root.zig:11
zig
/// Projects public declarations, members, and exact source evidence.pub const api = @import("api.zig");Complete caller list for api.directAliasTarget
8 direct callers.
tools.smg.src.api.resolveAliasTarget[function] — private; no exact target attools/smg/src/api.zig:678in nearest public ownertiny.smg.apitools.smg.src.scan.pipeline.scan.test_zig_tree_scan_exposes_declared_types_and_mutable_storage_semantics[function] — test; no exact target attools/smg/src/scan/pipeline/scan.zig:4737in nearest public ownertools.smg.src.scan.pipeline.scantools.smg.src.scan.test.expectZigComplexDeclaredTypes[function] — private; no exact target attools/smg/src/scan/test.zig:4979in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigDeclaredTypeGraph[function] — private; no exact target attools/smg/src/scan/test.zig:4949in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_ast_scan_resolves_imported_public_type_re-exports[function] — test; no exact target attools/smg/src/scan/test.zig:4838in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_projection_admits_package_imports_without_canonicalizing_factory_calls[function] — test; no exact target attools/smg/src/scan/test.zig:5329in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_projection_keeps_module_and_callable_documentation_provenance_exact[function] — test; no exact target attools/smg/src/scan/test.zig:5367in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_scan_resolves_same-name_imports_to_the_sibling_package_root[function] — test; no exact target attools/smg/src/scan/test.zig:3267in nearest public ownertools.smg.src.scan.test
Complete caller list for api.freePublicDeclarations
21 direct callers.
tiny.smg.api.resolvePublicPath[function] attools/smg/src/api.zig:317tools.smg.src.api.test_public_declarations_keep_unresolvable_same-name_import_bindings_terminal[function] — test; no exact target attools/smg/src/api.zig:1197in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_aliases_and_retain_export_facts[function] — test; no exact target attools/smg/src/api.zig:1051in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_dotted_private_alias_chains[function] — test; no exact target attools/smg/src/api.zig:1240in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_local_packages_through_private_import_bindings[function] — test; no exact target attools/smg/src/api.zig:1072in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_local_packages_through_same-name_import_bindings[function] — test; no exact target attools/smg/src/api.zig:1133in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_stop_at_self-resolving_import_bindings[function] — test; no exact target attools/smg/src/api.zig:1327in nearest public ownertiny.smg.apitools.smg.src.api.test_public_member_gaps_preserve_explicit_unsupported_source_facts[function] — test; no exact target attools/smg/src/api.zig:1473in nearest public ownertiny.smg.apitools.smg.src.api.test_public_members_retain_canonical_ownership_and_stable_source_order[function] — test; no exact target attools/smg/src/api.zig:1430in nearest public ownertiny.smg.apitools.smg.src.scan.pipeline.scan.test_zig_tree_scan_exposes_declared_types_and_mutable_storage_semantics[function] — test; no exact target attools/smg/src/scan/pipeline/scan.zig:4737in nearest public ownertools.smg.src.scan.pipeline.scantools.smg.src.scan.test.expectZigDeclaredTypeGraph[function] — private; no exact target attools/smg/src/scan/test.zig:4949in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigNestedMembers[function] — private; no exact target attools/smg/src/scan/test.zig:5205in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigPublicProjection[function] — private; no exact target attools/smg/src/scan/test.zig:5296in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigStructMembers[function] — private; no exact target attools/smg/src/scan/test.zig:5175in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigUnionAndPositionalMembers[function] — private; no exact target attools/smg/src/scan/test.zig:5232in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.onlyPublicMemberName[function] — private; no exact target attools/smg/src/scan/test.zig:5519in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_Chiclet_scan_preserves_public_declarations_imports_and_documentation[function] — test; no exact target attools/smg/src/scan/test.zig:1149in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_member_refresh_retires_removed_fields_and_source_facts[function] — test; no exact target attools/smg/src/scan/test.zig:5480in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_projection_admits_package_imports_without_canonicalizing_factory_calls[function] — test; no exact target attools/smg/src/scan/test.zig:5329in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_projection_keeps_module_and_callable_documentation_provenance_exact[function] — test; no exact target attools/smg/src/scan/test.zig:5367in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_scan_resolves_same-name_imports_to_the_sibling_package_root[function] — test; no exact target attools/smg/src/scan/test.zig:3267in nearest public ownertools.smg.src.scan.test
Complete caller list for api.publicDeclarations
23 direct callers.
tiny.smg.api.resolvePublicPath[function] attools/smg/src/api.zig:317tools.smg.src.api.test_public_declarations_bound_recursive_dotted_alias_cycles[function] — test; no exact target attools/smg/src/api.zig:1396in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_keep_unresolvable_same-name_import_bindings_terminal[function] — test; no exact target attools/smg/src/api.zig:1197in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_reject_nontrivial_alias_cycles[function] — test; no exact target attools/smg/src/api.zig:1356in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_aliases_and_retain_export_facts[function] — test; no exact target attools/smg/src/api.zig:1051in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_dotted_private_alias_chains[function] — test; no exact target attools/smg/src/api.zig:1240in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_local_packages_through_private_import_bindings[function] — test; no exact target attools/smg/src/api.zig:1072in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_resolve_local_packages_through_same-name_import_bindings[function] — test; no exact target attools/smg/src/api.zig:1133in nearest public ownertiny.smg.apitools.smg.src.api.test_public_declarations_stop_at_self-resolving_import_bindings[function] — test; no exact target attools/smg/src/api.zig:1327in nearest public ownertiny.smg.apitools.smg.src.api.test_public_member_gaps_preserve_explicit_unsupported_source_facts[function] — test; no exact target attools/smg/src/api.zig:1473in nearest public ownertiny.smg.apitools.smg.src.api.test_public_members_retain_canonical_ownership_and_stable_source_order[function] — test; no exact target attools/smg/src/api.zig:1430in nearest public ownertiny.smg.apitools.smg.src.scan.pipeline.scan.test_zig_tree_scan_exposes_declared_types_and_mutable_storage_semantics[function] — test; no exact target attools/smg/src/scan/pipeline/scan.zig:4737in nearest public ownertools.smg.src.scan.pipeline.scantools.smg.src.scan.test.expectZigDeclaredTypeGraph[function] — private; no exact target attools/smg/src/scan/test.zig:4949in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigNestedMembers[function] — private; no exact target attools/smg/src/scan/test.zig:5205in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigPublicProjection[function] — private; no exact target attools/smg/src/scan/test.zig:5296in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigStructMembers[function] — private; no exact target attools/smg/src/scan/test.zig:5175in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.expectZigUnionAndPositionalMembers[function] — private; no exact target attools/smg/src/scan/test.zig:5232in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.onlyPublicMemberName[function] — private; no exact target attools/smg/src/scan/test.zig:5519in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_Chiclet_scan_preserves_public_declarations_imports_and_documentation[function] — test; no exact target attools/smg/src/scan/test.zig:1149in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_member_refresh_retires_removed_fields_and_source_facts[function] — test; no exact target attools/smg/src/scan/test.zig:5480in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_projection_admits_package_imports_without_canonicalizing_factory_calls[function] — test; no exact target attools/smg/src/scan/test.zig:5329in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_public_projection_keeps_module_and_callable_documentation_provenance_exact[function] — test; no exact target attools/smg/src/scan/test.zig:5367in nearest public ownertools.smg.src.scan.testtools.smg.src.scan.test.test_zig_scan_resolves_same-name_imports_to_the_sibling_package_root[function] — test; no exact target attools/smg/src/scan/test.zig:3267in nearest public ownertools.smg.src.scan.test
Audit
| Definitions | 64 |
|---|---|
| Public names | 64 |
| Members | 25 |
| Version | 26.7.0 |
| Revision | daab053ee433 |