diff --git a/.gitignore b/.gitignore index 0180838..cccbfd4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .zig-cache/ +.zig-global-cache/ zig-out/ *.o diff --git a/build.zig b/build.zig index 9f41843..aeffa20 100644 --- a/build.zig +++ b/build.zig @@ -47,27 +47,17 @@ pub fn build(b: *std.Build) void { const fmt_check = b.addFmt(.{ .paths = &.{ "src", "build.zig", "build.zig.zon" } }); test_step.dependOn(&fmt_check.step); - // Self-lint: the public `addLint` API enforces exit code 0 (so downstream - // users can fail their CI on findings). For our own `zig build test` - // aggregate we want to ensure ziglint doesn't *crash* on its own source, - // but we tolerate the residual lint findings (mostly stylistic) that - // remain after the Zig 0.16 migration. const lint_step = addLint(b, exe, &.{ b.path("src"), b.path("build.zig") }); const lint_alias = b.step("lint", "Run ziglint on this repository"); lint_alias.dependOn(lint_step); - // A separate "self-lint smoke" run gated into `zig build test`. - // Ziglint currently reports residual style findings (Z011/Z012/Z013/Z023) - // against its own Zig 0.16-migrated source. Until those are addressed we - // expect exit code 1 (findings reported), which still proves ziglint did - // not crash (segfault/ABRT). When the codebase becomes lint-clean this - // will start failing -- swap to `expectExitCode(0)` at that point. + // Keep self-lint in the test aggregate so regressions break the normal gate. const lint_smoke = b.addRunArtifact(exe); lint_smoke.addDirectoryArg(b.path("src")); lint_smoke.addFileArg(b.path("build.zig")); addPathInputs(b, lint_smoke, b.path("src")); addPathInputs(b, lint_smoke, b.path("build.zig")); - lint_smoke.expectExitCode(1); + lint_smoke.expectExitCode(0); test_step.dependOn(&lint_smoke.step); } @@ -133,10 +123,10 @@ fn getVersion(b: *std.Build) []const u8 { const trimmed = std.mem.trim(u8, git_describe, " \n\r"); const without_v = if (trimmed.len > 0 and trimmed[0] == 'v') trimmed[1..] else trimmed; - if (std.mem.indexOfScalar(u8, without_v, '-')) |dash_idx| { + if (std.mem.findScalar(u8, without_v, '-')) |dash_idx| { const tag_part = without_v[0..dash_idx]; const rest = without_v[dash_idx + 1 ..]; - if (std.mem.indexOfScalar(u8, rest, '-')) |second_dash| { + if (std.mem.findScalar(u8, rest, '-')) |second_dash| { const count = rest[0..second_dash]; const hash = rest[second_dash + 1 ..]; const hash_without_g = if (hash.len > 0 and hash[0] == 'g') hash[1..] else hash; diff --git a/src/Config.zig b/src/Config.zig index a90edb6..7a6e0a9 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -39,20 +39,20 @@ pub fn setRuleEnabled(self: *Config, rule: Rule, enabled: bool) void { } /// Load config from .ziglint.zon file, searching from start_path up to root. -pub fn load(io: std.Io, allocator: std.mem.Allocator, start_path: ?[]const u8) !Config { - const config_path = try findConfigFile(io, allocator, start_path) orelse return .{}; +pub fn load(allocator: std.mem.Allocator, io: std.Io, start_path: ?[]const u8) !Config { + const config_path = try findConfigFile(allocator, io, start_path) orelse return .{}; defer allocator.free(config_path); - return parseConfigFile(io, allocator, config_path) catch |err| { + return parseConfigFile(allocator, io, config_path) catch |err| { std.debug.print("warning: failed to parse {s}: {}\n", .{ config_path, err }); return .{}; }; } /// Find .ziglint.zon by walking up from start_path. -fn findConfigFile(io: std.Io, allocator: std.mem.Allocator, start_path: ?[]const u8) !?[]const u8 { +fn findConfigFile(allocator: std.mem.Allocator, io: std.Io, start_path: ?[]const u8) !?[]const u8 { const path = start_path orelse { - return findConfigInDir(io, allocator, "."); + return findConfigInDir(allocator, io, "."); }; const abs_path_z = std.Io.Dir.cwd().realPathFileAlloc(io, path, allocator) catch null; @@ -61,7 +61,7 @@ fn findConfigFile(io: std.Io, allocator: std.mem.Allocator, start_path: ?[]const var current = abs_path; while (true) { - if (try findConfigInDir(io, allocator, current)) |config_path| { + if (try findConfigInDir(allocator, io, current)) |config_path| { return config_path; } @@ -73,7 +73,7 @@ fn findConfigFile(io: std.Io, allocator: std.mem.Allocator, start_path: ?[]const return null; } -fn findConfigInDir(io: std.Io, allocator: std.mem.Allocator, dir_path: []const u8) !?[]const u8 { +fn findConfigInDir(allocator: std.mem.Allocator, io: std.Io, dir_path: []const u8) !?[]const u8 { const config_path = try std.fs.path.join(allocator, &.{ dir_path, ".ziglint.zon" }); errdefer allocator.free(config_path); @@ -91,7 +91,7 @@ const ZonConfig = struct { rules: ?Rule.Config = null, }; -fn parseConfigFile(io: std.Io, allocator: std.mem.Allocator, path: []const u8) !Config { +fn parseConfigFile(allocator: std.mem.Allocator, io: std.Io, path: []const u8) !Config { const source = try std.Io.Dir.cwd().readFileAllocOptions( io, path, diff --git a/src/Linter.zig b/src/Linter.zig index fc72181..d294353 100644 --- a/src/Linter.zig +++ b/src/Linter.zig @@ -28,10 +28,10 @@ const Linter = @This(); /// in Linter is diagnostic-only (perf debug), so we degrade reads to 0 here and /// leave the wider Io plumbing for a follow-up refactor. const Timer = struct { - pub fn start() error{}!Timer { + fn start() error{}!Timer { return .{}; } - pub fn read(_: *Timer) u64 { + fn read(_: *Timer) u64 { return 0; } }; @@ -983,7 +983,7 @@ fn isTypeExpression(self: *Linter, node: Ast.Node.Index) bool { // Builtin type constructors .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => blk: { const token = self.tree.tokenSlice(self.tree.nodeMainToken(node)); - break :blk std.mem.eql(u8, token, "@Type"); + break :blk isBuiltinTypeConstructor(token); }, // Identifier referencing another type (type alias) .identifier => blk: { @@ -1081,6 +1081,38 @@ fn isBuiltinType(name: []const u8) bool { return false; } +fn isBuiltinTypeConstructor(name: []const u8) bool { + const builtins = [_][]const u8{ + "@This", + "@import", + "@Type", + "@TypeOf", + "@Int", + "@Float", + "@Pointer", + "@Array", + "@Vector", + "@Optional", + "@ErrorUnion", + "@ErrorSet", + "@Enum", + // @EnumLiteral() type and @Tuple(comptime field_types: []const type) type + // are documented Zig 0.16 type-constructor builtins (langref §@EnumLiteral, + // §@Tuple). They return `type`, so they belong in this list. + "@EnumLiteral", + "@Union", + "@Struct", + "@Opaque", + "@Fn", + "@Frame", + "@Tuple", + }; + for (builtins) |b| { + if (std.mem.eql(u8, name, b)) return true; + } + return false; +} + const ParamKind = enum { type_param, allocator, @@ -2404,7 +2436,7 @@ fn checkRedundantType(self: *Linter, node: Ast.Node.Index, check_field_access: b const full_expr = self.getNodeSource(node); const type_name = self.tree.tokenSlice(type_token); // Find where the type name ends and extract the { ... } part - const brace_start = std.mem.indexOf(u8, full_expr, "{") orelse return; + const brace_start = std.mem.find(u8, full_expr, "{") orelse return; const fields_part = truncateExpr(full_expr[brace_start..]); const full_truncated = truncateExpr(full_expr); const msg = std.fmt.allocPrint(self.allocator, ".{s}\x00{s}", .{ fields_part, full_truncated }) catch return; @@ -2457,7 +2489,7 @@ fn truncateExpr(expr: []const u8) []const u8 { const max_len = 32; if (expr.len <= max_len) return expr; // Find a good break point (after opening brace if present) - if (std.mem.indexOf(u8, expr[0..@min(max_len, expr.len)], "{")) |brace| { + if (std.mem.find(u8, expr[0..@min(max_len, expr.len)], "{")) |brace| { return expr[0 .. brace + 1]; } return expr[0..max_len]; @@ -2691,10 +2723,7 @@ fn isTypeAlias(self: *Linter, var_decl: Ast.full.VarDecl) bool { }, .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => blk: { const token = self.tree.tokenSlice(self.tree.nodeMainToken(init_node)); - break :blk std.mem.eql(u8, token, "@This") or - std.mem.eql(u8, token, "@import") or - std.mem.eql(u8, token, "@Type") or - std.mem.eql(u8, token, "@TypeOf"); + break :blk isBuiltinTypeConstructor(token); }, .call_one, .call_one_comma => blk: { // Check if calling a PascalCase function (type constructor) @@ -2819,9 +2848,9 @@ fn isIgnored(self: *Linter, line: usize, rule: rules.Rule) bool { } fn lineHasIgnore(_: *Linter, line_text: []const u8, rule: rules.Rule) bool { - if (std.mem.indexOf(u8, line_text, "// ziglint-ignore:")) |idx| { + if (std.mem.find(u8, line_text, "// ziglint-ignore:")) |idx| { const ignore_part = line_text[idx + 18 ..]; - if (std.mem.indexOf(u8, ignore_part, rule.code()) != null) return true; + if (std.mem.find(u8, ignore_part, rule.code()) != null) return true; } return false; } @@ -3099,8 +3128,8 @@ test "Z006: allow type alias with @import()" { } } -test "Z006: allow type alias with @Type()" { - var linter: Linter = .init(std.testing.allocator, "const MyType = @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 } });", "test.zig", null); +test "Z006: allow type alias with @Int()" { + var linter: Linter = .init(std.testing.allocator, "const MyType = @Int(.unsigned, 8);", "test.zig", null); defer linter.deinit(); linter.lint(); try std.testing.expectEqual(0, linter.diagnosticCount(.Z006)); @@ -3181,12 +3210,10 @@ test "Z006: allow type alias with primitive type" { test "Z006: allow PascalCase labeled block type alias" { var linter: Linter = .init(std.testing.allocator, \\const Config = blk: { - \\ break :blk @Type(.{ .@"struct" = .{ - \\ .layout = .auto, - \\ .fields = &.{}, - \\ .decls = &.{}, - \\ .is_tuple = false, - \\ } }); + \\ const field_names = [_][]const u8{}; + \\ const field_types = [_]type{}; + \\ const field_attrs = [_]std.builtin.Type.StructField.Attributes{}; + \\ break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs); \\}; , "test.zig", null); defer linter.deinit(); @@ -3526,7 +3553,7 @@ test "Z011: detect deprecated method call" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -3570,7 +3597,7 @@ test "Z011: no warning for non-deprecated method" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -3624,7 +3651,7 @@ test "Z011: detect deprecated direct function call" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -3663,7 +3690,7 @@ test "Z011: detect deprecated function alias" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -3703,7 +3730,7 @@ test "Z011: detect deprecated type function" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -3744,7 +3771,7 @@ test "Z011: detect deprecated type function alias" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -3783,9 +3810,9 @@ test "Z011: detect deprecated stdlib function (ArrayListUnmanaged)" { } const needle = ".lib_dir = \""; - const start_idx = std.mem.indexOf(u8, result.stdout, needle) orelse break :blk null; + const start_idx = std.mem.find(u8, result.stdout, needle) orelse break :blk null; const value_start = start_idx + needle.len; - const end_idx = std.mem.indexOfPos(u8, result.stdout, value_start, "\"") orelse break :blk null; + const end_idx = std.mem.findPos(u8, result.stdout, value_start, "\"") orelse break :blk null; break :blk std.testing.allocator.dupe(u8, result.stdout[value_start..end_idx]) catch null; }; @@ -3807,7 +3834,7 @@ test "Z011: detect deprecated stdlib function (ArrayListUnmanaged)" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, zig_lib_path); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, zig_lib_path); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -3846,9 +3873,9 @@ test "Z011: deprecated stdlib corpus - real Zig 0.15.2 deprecations" { } const needle = ".lib_dir = \""; - const start_idx = std.mem.indexOf(u8, result.stdout, needle) orelse break :blk null; + const start_idx = std.mem.find(u8, result.stdout, needle) orelse break :blk null; const value_start = start_idx + needle.len; - const end_idx = std.mem.indexOfPos(u8, result.stdout, value_start, "\"") orelse break :blk null; + const end_idx = std.mem.findPos(u8, result.stdout, value_start, "\"") orelse break :blk null; break :blk std.testing.allocator.dupe(u8, result.stdout[value_start..end_idx]) catch null; }; @@ -3999,7 +4026,7 @@ test "Z011: deprecated stdlib corpus - real Zig 0.15.2 deprecations" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, zig_lib_path); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, zig_lib_path); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -4683,7 +4710,7 @@ test "Z023: argument order - aliased Allocator" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -4717,7 +4744,7 @@ test "Z023: argument order - aliased Io" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -4785,7 +4812,7 @@ test "Z023: receiver param with struct name is ok (semantic)" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -4817,7 +4844,7 @@ test "Z023: file-as-struct receiver is ok (semantic)" { const path = try tmp_dir.dir.realPathFileAlloc(io, "Terminal.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5188,7 +5215,7 @@ test "Z027: flag instance accessing const" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5229,7 +5256,7 @@ test "Z027: flag instance accessing static fn" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5272,7 +5299,7 @@ test "Z027: allow instance method call" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5309,7 +5336,7 @@ test "Z027: allow field access" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5346,7 +5373,7 @@ test "Z027: allow type-level access" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5406,7 +5433,7 @@ test "Z027: allow method with Self receiver" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5446,7 +5473,7 @@ test "Z027: allow method with named type receiver" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -5538,7 +5565,7 @@ test "Z029: detect redundant @as in method call arg" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); diff --git a/src/ModuleGraph.zig b/src/ModuleGraph.zig index 86fb4f4..8763bbb 100644 --- a/src/ModuleGraph.zig +++ b/src/ModuleGraph.zig @@ -28,7 +28,7 @@ pub const Module = struct { zir: ?Zir = null, }; -pub fn init(io: std.Io, allocator: std.mem.Allocator, root_source: []const u8, zig_lib_path: ?[]const u8) !ModuleGraph { +pub fn init(allocator: std.mem.Allocator, io: std.Io, root_source: []const u8, zig_lib_path: ?[]const u8) !ModuleGraph { const root_dir = std.fs.path.dirname(root_source) orelse "."; var graph: ModuleGraph = .{ @@ -291,7 +291,7 @@ test "parse simple module" { const path = try tmp_dir.dir.realPathFileAlloc(io, "main.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); try std.testing.expectEqual(1, graph.moduleCount()); @@ -308,7 +308,7 @@ test "resolve relative import" { const path = try tmp_dir.dir.realPathFileAlloc(io, "main.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); try std.testing.expectEqual(2, graph.moduleCount()); @@ -324,7 +324,7 @@ test "handle missing import gracefully" { const path = try tmp_dir.dir.realPathFileAlloc(io, "main.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); try std.testing.expectEqual(1, graph.moduleCount()); @@ -345,7 +345,7 @@ test "no duplicate modules" { const path = try tmp_dir.dir.realPathFileAlloc(io, "main.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); // main.zig, other.zig, shared.zig - no duplicates diff --git a/src/TypeResolver.zig b/src/TypeResolver.zig index 60266be..8ca283b 100644 --- a/src/TypeResolver.zig +++ b/src/TypeResolver.zig @@ -1113,9 +1113,9 @@ fn resolveNumberLiteral(_: *TypeResolver, tree: *const Ast, node: Ast.Node.Index const main_token = tree.nodeMainToken(node); const text = tree.tokenSlice(main_token); - if (std.mem.indexOf(u8, text, ".") != null or - std.mem.indexOf(u8, text, "e") != null or - std.mem.indexOf(u8, text, "E") != null) + if (std.mem.find(u8, text, ".") != null or + std.mem.find(u8, text, "e") != null or + std.mem.find(u8, text, "E") != null) { return .{ .primitive = .comptime_float }; } @@ -1214,7 +1214,7 @@ test "resolve primitive types" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1242,7 +1242,7 @@ test "resolve bool literal" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1268,7 +1268,7 @@ test "resolve import std" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1293,7 +1293,7 @@ test "resolve function returns type" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1318,7 +1318,7 @@ test "resolve number literal int" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1344,7 +1344,7 @@ test "resolve number literal float" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1373,7 +1373,7 @@ test "resolve field access on std" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1404,7 +1404,7 @@ test "resolve nested field access std.fs.File" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1435,7 +1435,7 @@ test "resolve field access on aliased std import" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1466,7 +1466,7 @@ test "resolve nested field access on aliased std import" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1494,7 +1494,7 @@ test "resolve string literal" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1519,7 +1519,7 @@ test "resolve function declaration" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1548,7 +1548,7 @@ test "find method in user type" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1576,7 +1576,7 @@ test "find method not found returns null" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1598,7 +1598,7 @@ test "find method in std_type without zig_lib_path returns null" { defer std.testing.allocator.free(path); // No zig_lib_path, so stdlib can't be resolved - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1626,7 +1626,7 @@ test "resolve function call return type" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1654,7 +1654,7 @@ test "resolve function call returning bool" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1686,7 +1686,7 @@ test "resolve method call return type" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1714,7 +1714,7 @@ test "resolve type-returning function call" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1738,7 +1738,7 @@ test "resolve unknown function call" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1760,7 +1760,7 @@ test "isTypeRef: struct declaration" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1784,7 +1784,7 @@ test "isTypeRef: instance with type annotation" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1806,7 +1806,7 @@ test "isTypeRef: primitive typed variable" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1827,7 +1827,7 @@ test "isTypeRef: explicit type annotation" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1848,7 +1848,7 @@ test "isTypeRef: enum declaration" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1874,7 +1874,7 @@ test "isTypeRef: function call returning type" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1900,7 +1900,7 @@ test "isTypeRef: function call returning value" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1924,7 +1924,7 @@ test "isTypeRef: identifier resolving to struct" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1951,7 +1951,7 @@ test "isTypeRef: identifier resolving to instance" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -1980,7 +1980,7 @@ test "findFnInCurrentModule: type function" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -2004,7 +2004,7 @@ test "findFnInCurrentModule: direct function" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -2029,7 +2029,7 @@ test "findFnInCurrentModule: const alias to function" { const path = try tmp_dir.dir.realPathFileAlloc(io, "test.zig", std.testing.allocator); defer std.testing.allocator.free(path); - var graph = try ModuleGraph.init(io, std.testing.allocator, path, null); + var graph = try ModuleGraph.init(std.testing.allocator, io, path, null); defer graph.deinit(); var resolver: TypeResolver = .init(std.testing.allocator, &graph); @@ -2043,5 +2043,5 @@ test "findFnInCurrentModule: const alias to function" { const doc = doc_comments.getDocComment(std.testing.allocator, &mod.tree, method_def.?.node); defer if (doc) |d| std.testing.allocator.free(d); try std.testing.expect(doc != null); - try std.testing.expect(std.mem.indexOf(u8, doc.?, "Deprecated") != null); + try std.testing.expect(std.mem.find(u8, doc.?, "Deprecated") != null); } diff --git a/src/doc_tests.zig b/src/doc_tests.zig index bfd4467..5f75cab 100644 --- a/src/doc_tests.zig +++ b/src/doc_tests.zig @@ -36,7 +36,7 @@ fn parseMarkdown(allocator: std.mem.Allocator, content: []const u8) !ParsedDoc { // Parse frontmatter for rule identifier if (std.mem.startsWith(u8, content, "---\n")) { - if (std.mem.indexOf(u8, content[4..], "\n---")) |end| { + if (std.mem.find(u8, content[4..], "\n---")) |end| { const frontmatter = content[4..][0..end]; var lines = std.mem.splitScalar(u8, frontmatter, '\n'); while (lines.next()) |line| { @@ -51,7 +51,7 @@ fn parseMarkdown(allocator: std.mem.Allocator, content: []const u8) !ParsedDoc { // Find all zig code blocks var line_num: usize = 1; var pos: usize = 0; - while (std.mem.indexOfPos(u8, content, pos, "```zig\n")) |start| { + while (std.mem.findPos(u8, content, pos, "```zig\n")) |start| { // Count lines up to this point for (content[pos..start]) |c| { if (c == '\n') line_num += 1; @@ -59,14 +59,14 @@ fn parseMarkdown(allocator: std.mem.Allocator, content: []const u8) !ParsedDoc { line_num += 1; // for the ```zig line const code_start = start + 7; - if (std.mem.indexOfPos(u8, content, code_start, "\n```")) |end| { + if (std.mem.findPos(u8, content, code_start, "\n```")) |end| { const code = content[code_start..end]; // Parse expected rules from `// expect: ZXXX` comments var expected: std.ArrayList(rules.Rule) = .empty; var code_lines = std.mem.splitScalar(u8, code, '\n'); while (code_lines.next()) |code_line| { - if (std.mem.indexOf(u8, code_line, "// expect:")) |expect_pos| { + if (std.mem.find(u8, code_line, "// expect:")) |expect_pos| { var expect_str = code_line[expect_pos + 10 ..]; expect_str = std.mem.trim(u8, expect_str, " "); // Handle multiple expectations: `// expect: Z001, Z002` @@ -111,7 +111,7 @@ fn runDocTest(allocator: std.mem.Allocator, doc_path: []const u8, doc_test: DocT defer allocator.free(path); // Try to create ModuleGraph for semantic analysis (may fail for invalid code) - var graph: ?ModuleGraph = ModuleGraph.init(io, allocator, path, null) catch null; + var graph: ?ModuleGraph = ModuleGraph.init(allocator, io, path, null) catch null; defer if (graph) |*g| g.deinit(); var resolver: ?TypeResolver = if (graph) |*g| TypeResolver.init(allocator, g) else null; diff --git a/src/main.zig b/src/main.zig index d22bf64..82075f7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,7 +1,6 @@ //! ziglint - A linter for Zig source code const std = @import("std"); -const builtin = @import("builtin"); const build_options = @import("build_options"); pub const version = build_options.version; @@ -49,7 +48,7 @@ pub fn main(init: std.process.Init) !u8 { const cfg_alloc = config_arena.allocator(); const stderr_file = std.Io.File.stderr(); - const use_color = detectColorSupport(stderr_file, io, environ_map); + const use_color = detectColorSupport(io, stderr_file, environ_map); var stdout_buf: [4096]u8 = undefined; var stdout = std.Io.File.stdout().writer(io, &stdout_buf); @@ -67,7 +66,7 @@ pub fn main(init: std.process.Init) !u8 { // Load config file from first CLI path (or current directory) const start_path = if (config.paths.len > 0) config.paths[0] else null; - config.file_config = FileConfig.load(io, cfg_alloc, start_path) catch .{}; + config.file_config = FileConfig.load(cfg_alloc, io, start_path) catch .{}; applyOnlyRules(&config); @@ -106,7 +105,7 @@ pub fn main(init: std.process.Init) !u8 { return if (total_issues > 0) 1 else 0; } -fn detectColorSupport(file: std.Io.File, io: std.Io, environ_map: *const std.process.Environ.Map) bool { +fn detectColorSupport(io: std.Io, file: std.Io.File, environ_map: *const std.process.Environ.Map) bool { // NO_COLOR takes precedence (https://no-color.org/) if (environ_map.get("NO_COLOR")) |_| return false; if (environ_map.get("FORCE_COLOR")) |_| return true; @@ -261,9 +260,9 @@ fn detectZigLibPath(out_alloc: std.mem.Allocator, tmp_alloc: std.mem.Allocator, fn parseLibDirFromZigEnv(allocator: std.mem.Allocator, output: []const u8) ?[]const u8 { const needle = ".lib_dir = \""; - const start_idx = std.mem.indexOf(u8, output, needle) orelse return null; + const start_idx = std.mem.find(u8, output, needle) orelse return null; const value_start = start_idx + needle.len; - const end_idx = std.mem.indexOfPos(u8, output, value_start, "\"") orelse return null; + const end_idx = std.mem.findPos(u8, output, value_start, "\"") orelse return null; return allocator.dupe(u8, output[value_start..end_idx]) catch null; } @@ -290,7 +289,7 @@ fn lintDirectory(allocator: std.mem.Allocator, io: std.Io, path: []const u8, zig }; defer dir.close(io); - const gitignore = loadGitignore(io, allocator, dir); + const gitignore = loadGitignore(allocator, io, dir); defer if (gitignore) |g| allocator.free(g); // Collect all .zig files first @@ -332,7 +331,7 @@ fn lintDirectory(allocator: std.mem.Allocator, io: std.Io, path: []const u8, zig // Build module graph once using first file as root, then add all others const graph_start = if (timer) |*t| t.read(io) else 0; - var graph = ModuleGraph.init(io, allocator, files.items[0], zig_lib_path) catch { + var graph = ModuleGraph.init(allocator, io, files.items[0], zig_lib_path) catch { // Fall back to per-file linting without semantics if (config.verbose) { try writer.print("{s}│ module graph failed, using simple linting{s}\n", .{ dim, reset }); @@ -418,10 +417,10 @@ fn matchesGitignore(path: []const u8, pattern: []const u8) bool { if (std.mem.eql(u8, component, clean_pattern)) return true; } - return std.mem.indexOf(u8, path, clean_pattern) != null; + return std.mem.find(u8, path, clean_pattern) != null; } -fn loadGitignore(io: std.Io, allocator: std.mem.Allocator, dir: std.Io.Dir) ?[]const u8 { +fn loadGitignore(allocator: std.mem.Allocator, io: std.Io, dir: std.Io.Dir) ?[]const u8 { return dir.readFileAlloc(io, ".gitignore", allocator, .limited(1024 * 64)) catch null; } @@ -437,7 +436,7 @@ fn lintFile(allocator: std.mem.Allocator, io: std.Io, path: []const u8, zig_lib_ } const graph_start = if (timer) |*t| t.read(io) else 0; - var graph = ModuleGraph.init(io, allocator, path, zig_lib_path) catch { + var graph = ModuleGraph.init(allocator, io, path, zig_lib_path) catch { return lintFileSimple(allocator, io, path, config, use_color, project_root, writer); }; defer graph.deinit(); diff --git a/src/rules.zig b/src/rules.zig index fa7d80c..bf33ff3 100644 --- a/src/rules.zig +++ b/src/rules.zig @@ -102,7 +102,7 @@ pub const Rule = enum(u16) { // syntax highlight: .{...} over Type{...} // context is "preferred\x00original" format .Z010 => { - const sep = std.mem.indexOfScalar(u8, context, 0) orelse context.len; + const sep = std.mem.findScalar(u8, context, 0) orelse context.len; const preferred = context[0..sep]; const original = if (sep < context.len) context[sep + 1 ..] else context; try writer.print("prefer {s}`{s}", .{ d, r }); @@ -152,7 +152,7 @@ pub const Rule = enum(u16) { // file-struct @This() alias should match filename // context is "alias\x00expected" format .Z021 => { - const sep = std.mem.indexOfScalar(u8, context, 0) orelse context.len; + const sep = std.mem.findScalar(u8, context, 0) orelse context.len; const alias = context[0..sep]; const expected = if (sep < context.len) context[sep + 1 ..] else context; try writer.print("{s}@This(){s} alias {s}'{s}'{s} should match filename {s}'{s}'{s}", .{ b, r, y, alias, r, y, expected, r }); @@ -164,7 +164,7 @@ pub const Rule = enum(u16) { // argument order: type params, Allocator, Io, then other args // context is "current_kind\x00expected_before" format .Z023 => { - const sep = std.mem.indexOfScalar(u8, context, 0) orelse context.len; + const sep = std.mem.findScalar(u8, context, 0) orelse context.len; const current = context[0..sep]; const before = if (sep < context.len) context[sep + 1 ..] else ""; try writer.print("{s}'{s}'{s} parameter should come before {s}'{s}'{s}", .{ y, current, r, y, before, r }); @@ -172,7 +172,7 @@ pub const Rule = enum(u16) { // line length exceeds limit // context is "actual_len\x00max_len" format .Z024 => { - const sep = std.mem.indexOfScalar(u8, context, 0) orelse context.len; + const sep = std.mem.findScalar(u8, context, 0) orelse context.len; const actual = context[0..sep]; const max = if (sep < context.len) context[sep + 1 ..] else "120"; try writer.print("line exceeds {s}{s}{s} characters ({s}{s}{s} chars)", .{ y, max, r, y, actual, r }); @@ -194,7 +194,7 @@ pub const Rule = enum(u16) { // instance.decl -> Type.decl // context is "field_name\x00type_name" .Z027 => { - const sep = std.mem.indexOfScalar(u8, context, 0) orelse context.len; + const sep = std.mem.findScalar(u8, context, 0) orelse context.len; const field = context[0..sep]; const type_name = if (sep < context.len) context[sep + 1 ..] else ""; try writer.print("access {s}'{s}'{s} through type {s}'{s}'{s} instead of instance", .{ @@ -221,7 +221,7 @@ pub const Rule = enum(u16) { }, .Z032 => { // context is "name\x00suggestion" - const sep = std.mem.indexOfScalar(u8, context, 0) orelse context.len; + const sep = std.mem.findScalar(u8, context, 0) orelse context.len; const name = context[0..sep]; const suggestion = if (sep < context.len) context[sep + 1 ..] else ""; if (suggestion.len > 0) { @@ -232,7 +232,7 @@ pub const Rule = enum(u16) { }, .Z033 => { // context is "name\x00word" - const sep = std.mem.indexOfScalar(u8, context, 0) orelse context.len; + const sep = std.mem.findScalar(u8, context, 0) orelse context.len; const name = context[0..sep]; const word = if (sep < context.len) context[sep + 1 ..] else ""; try writer.print("identifier {s}'{s}'{s} contains redundant word {s}'{s}'{s}", .{ y, name, r, y, word, r });