Skip to documentation
SLOP

tiny.smg.name

Reference tiny.smg name

Defined in tiny.smg.

API (5)

Actions

Public operations.

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

Source

Called byCallsNo direct callsnamefallbackMatchestest; no linktools.smg.src.nametest: dotted translation maps repo pa...namedottedFromPath
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest; no linktools.smg.src.nametest: fallback declares no resolution...test; no linktools.smg.src.nametest: fallback resolves path forms be...private; no linktools.smg.src.namecollectnamedottedFromPathnamefallbackMatches
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callstest; no linktools.smg.src.nametest: leaf strips qualification for d...nameleaf
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest; no linktools.smg.src.nametest: subsequence anchors the leaf an...namematchesSubsequence
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callstest; no linktools.smg.src.nametest: suffix matches whole dotted seg...namematchesSuffix
Static calls · unresolved targets: 0 · external targets: 0.

Source: tools/smg/src/name.zig

zig
const std = @import("std");const testing_fallback_match_count = @import("root.zig").default_limits.suggestions.fallback_match_count;pub fn matchesSuffix(name: []const u8, suffix: []const u8) bool {    if (!std.mem.endsWith(u8, name, suffix)) return false;    if (name.len == suffix.len) return true;    return name[name.len - suffix.len - 1] == '.';}pub fn leaf(raw: []const u8) []const u8 {    if (std.mem.lastIndexOfScalar(u8, raw, '/')) |slash| {        const base = raw[slash + 1 ..];        const dot = std.mem.lastIndexOfScalar(u8, base, '.') orelse return base;        if (dot == 0) return base;        return base[0..dot];    }    const dot = std.mem.lastIndexOfScalar(u8, raw, '.') orelse return raw;    return raw[dot + 1 ..];}pub fn dottedFromPath(allocator: std.mem.Allocator, raw: []const u8) !?[]const u8 {    if (std.mem.indexOfScalar(u8, raw, '/') == null) return null;    var trimmed = raw;    while (std.mem.startsWith(u8, trimmed, "./")) trimmed = trimmed[2..];    while (trimmed.len != 0 and trimmed[0] == '/') trimmed = trimmed[1..];    while (trimmed.len != 0 and trimmed[trimmed.len - 1] == '/') trimmed = trimmed[0 .. trimmed.len - 1];    if (trimmed.len == 0) return null;    const base_start = if (std.mem.lastIndexOfScalar(u8, trimmed, '/')) |slash| slash + 1 else 0;    if (std.mem.lastIndexOfScalar(u8, trimmed[base_start..], '.')) |dot| {        if (dot != 0) trimmed = trimmed[0 .. base_start + dot];    }    const stem = trimmed[base_start..];    if (std.mem.eql(u8, stem, "index") or std.mem.eql(u8, stem, "__init__")) {        trimmed = if (base_start == 0) "root" else trimmed[0 .. base_start - 1];    }    const out = try allocator.dupe(u8, trimmed);    for (out) |*char| {        if (char.* == '/') char.* = '.';    }    return out;}pub fn matchesSubsequence(name: []const u8, query: []const u8) bool {    const query_dot = std.mem.lastIndexOfScalar(u8, query, '.') orelse return false;    const name_dot = std.mem.lastIndexOfScalar(u8, name, '.') orelse return false;    if (!std.mem.eql(u8, name[name_dot + 1 ..], query[query_dot + 1 ..])) return false;    var query_segments = std.mem.splitScalar(u8, query[0..query_dot], '.');    var name_segments = std.mem.splitScalar(u8, name[0..name_dot], '.');    var pending = query_segments.next();    while (pending) |segment| {        const candidate = name_segments.next() orelse return false;        if (std.mem.eql(u8, candidate, segment)) pending = query_segments.next();    }    return true;}pub fn fallbackMatches(allocator: std.mem.Allocator, names: []const []const u8, raw: []const u8, limit: usize) ![]const []const u8 {    if (try dottedFromPath(allocator, raw)) |translated| {        defer allocator.free(translated);        for (names) |name| {            if (std.mem.eql(u8, name, translated)) {                const out = try allocator.alloc([]const u8, 1);                out[0] = name;                return out;            }        }        const suffixed = try collect(allocator, names, translated, matchesSuffix, limit);        if (suffixed.len != 0) return suffixed;        return try collect(allocator, names, translated, matchesSubsequence, limit);    }    return try collect(allocator, names, raw, matchesSubsequence, limit);}fn collect(allocator: std.mem.Allocator, names: []const []const u8, query: []const u8, matches: fn ([]const u8, []const u8) bool, limit: usize) ![]const []const u8 {    var out: std.ArrayList([]const u8) = .empty;    errdefer out.deinit(allocator);    for (names) |name| {        if (!matches(name, query)) continue;        if (out.items.len == limit) {            out.deinit(allocator);            return &.{};        }        try out.append(allocator, name);    }    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);}test "suffix matches whole dotted segments only" {    try std.testing.expect(matchesSuffix("app.main", "main"));    try std.testing.expect(matchesSuffix("app.main", "app.main"));    try std.testing.expect(!matchesSuffix("app.domain", "main"));    try std.testing.expect(!matchesSuffix("main", "app.main"));}test "leaf strips qualification for dotted names and extensions for paths" {    try std.testing.expectEqualStrings("merge", leaf("lib.tracker.src.store.merge"));    try std.testing.expectEqualStrings("merge", leaf("lib/tracker/src/store/merge.zig"));    try std.testing.expectEqualStrings("tinyalloc", leaf("lib/tinyalloc"));    try std.testing.expectEqualStrings(".hidden", leaf("dir/.hidden"));    try std.testing.expectEqualStrings("plain", leaf("plain"));}test "dotted translation maps repo paths onto node names" {    const allocator = std.testing.allocator;    const translated = (try dottedFromPath(allocator, "lib/tracker/src/store/merge.zig")).?;    defer allocator.free(translated);    try std.testing.expectEqualStrings("lib.tracker.src.store.merge", translated);    const trimmed = (try dottedFromPath(allocator, "./lib/term/src/")).?;    defer allocator.free(trimmed);    try std.testing.expectEqualStrings("lib.term.src", trimmed);    const bare = (try dottedFromPath(allocator, "lib/tinyalloc")).?;    defer allocator.free(bare);    try std.testing.expectEqualStrings("lib.tinyalloc", bare);    const index = (try dottedFromPath(allocator, "tools/glom/src/index.zig")).?;    defer allocator.free(index);    try std.testing.expectEqualStrings("tools.glom.src", index);    const init = (try dottedFromPath(allocator, "analysis/src/analysis/__init__.py")).?;    defer allocator.free(init);    try std.testing.expectEqualStrings("analysis.src.analysis", init);    try std.testing.expectEqual(@as(?[]const u8, null), try dottedFromPath(allocator, "app.main"));}test "subsequence anchors the leaf and orders the qualifiers" {    try std.testing.expect(matchesSubsequence("lib.choir.src.core.context.dialects", "choir.context.dialects"));    try std.testing.expect(matchesSubsequence("lib.tracker.src.store.merge", "store.merge"));    try std.testing.expect(matchesSubsequence("app.main", "app.main"));    try std.testing.expect(!matchesSubsequence("lib.choir.src.core.dialects", "choir.context.dialects"));    try std.testing.expect(!matchesSubsequence("lib.choir.src.context.core.dialects", "choir.core.context.dialects"));    try std.testing.expect(!matchesSubsequence("lib.choir.src.core.context.dialects", "dialects"));    try std.testing.expect(!matchesSubsequence("dialects", "choir.context.dialects"));}test "fallback resolves path forms before subsequence forms" {    const allocator = std.testing.allocator;    const names = [_][]const u8{        "lib.choir.src.core.dialects",        "lib.choir.src.core.context.dialects",        "lib.tracker.src.store.merge",        "lib.tracker.src.store",    };    const path_hit = try fallbackMatches(allocator, &names, "lib/tracker/src/store/merge.zig", testing_fallback_match_count);    defer allocator.free(path_hit);    try std.testing.expectEqual(@as(usize, 1), path_hit.len);    try std.testing.expectEqualStrings("lib.tracker.src.store.merge", path_hit[0]);    const relative = try fallbackMatches(allocator, &names, "src/store/merge.zig", testing_fallback_match_count);    defer allocator.free(relative);    try std.testing.expectEqual(@as(usize, 1), relative.len);    try std.testing.expectEqualStrings("lib.tracker.src.store.merge", relative[0]);    const subsequence = try fallbackMatches(allocator, &names, "choir.context.dialects", testing_fallback_match_count);    defer allocator.free(subsequence);    try std.testing.expectEqual(@as(usize, 1), subsequence.len);    try std.testing.expectEqualStrings("lib.choir.src.core.context.dialects", subsequence[0]);    const ambiguous = try fallbackMatches(allocator, &names, "core.dialects", testing_fallback_match_count);    defer allocator.free(ambiguous);    try std.testing.expectEqual(@as(usize, 2), ambiguous.len);    const missing = try fallbackMatches(allocator, &names, "absent.node", testing_fallback_match_count);    defer allocator.free(missing);    try std.testing.expectEqual(@as(usize, 0), missing.len);}test "fallback declares no resolution beyond the candidate bound" {    const allocator = std.testing.allocator;    var names: std.ArrayList([]const u8) = .empty;    defer {        for (names.items) |name| allocator.free(name);        names.deinit(allocator);    }    for (0..testing_fallback_match_count + 1) |index| {        try names.append(allocator, try std.fmt.allocPrint(allocator, "pkg{d}.src.core.leaf", .{index}));    }    const flooded = try fallbackMatches(allocator, names.items, "core.leaf", testing_fallback_match_count);    defer allocator.free(flooded);    try std.testing.expectEqual(@as(usize, 0), flooded.len);}

Source: tools/smg/src/root.zig:27

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

Audit

Definitions6
Public names6
Members0
Version26.7.0
Revisiondaab053ee433