Skip to content

Commit 14bddd3

Browse files
committed
Refactor to pass lint document by pointer and to separate analyser (#118)
This avoids confusion around shallow copies and mutability as it was mutating what the pointers in the shallow copies were pointing to. This is breaking in that run accepts a pointer and context is re-introduced. Before: ```zig fn ( self: LintRule, doc: session.LintDocument, gpa: std.mem.Allocator, options: RunOptions, ) error{OutOfMemory}!?results.LintResult ``` After: ```zig fn ( self: LintRule, context: *session.LintContext, doc: *const session.LintDocument, gpa: std.mem.Allocator, options: RunOptions, ) error{OutOfMemory}!?results.LintResult ```
1 parent 3c296b3 commit 14bddd3

30 files changed

+555
-490
lines changed

integration_tests/src/no_cats.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ pub fn buildRule(options: zlinter.rules.RuleOptions) zlinter.rules.LintRule {
1616

1717
fn run(
1818
rule: zlinter.rules.LintRule,
19-
doc: zlinter.session.LintDocument,
19+
_: *zlinter.session.LintContext,
20+
doc: *const zlinter.session.LintDocument,
2021
allocator: std.mem.Allocator,
2122
options: zlinter.rules.RunOptions,
2223
) error{OutOfMemory}!?zlinter.results.LintResult {

src/exe/run_linter.zig

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ fn runLinterRules(
221221
slowest_files.unloadAndPrint("Files", printer);
222222
};
223223

224+
var arena = std.heap.ArenaAllocator.init(gpa);
225+
defer arena.deinit();
226+
224227
var maybe_rule_elapsed_times: ?[rules.len]usize = if (args.verbose)
225228
@splat(0)
226229
else
@@ -238,13 +241,13 @@ fn runLinterRules(
238241
item_timers.unloadAndPrint("Rules", printer);
239242
};
240243

241-
var ctx: zlinter.session.LintContext = undefined;
242-
try ctx.init(.{
244+
var context: zlinter.session.LintContext = undefined;
245+
try context.init(.{
243246
.zig_exe_path = args.zig_exe,
244247
.zig_lib_path = args.zig_lib_directory,
245248
.global_cache_path = args.global_cache_root,
246-
}, gpa);
247-
defer ctx.deinit();
249+
}, gpa, arena.allocator());
250+
defer context.deinit();
248251

249252
var enabled_rules = enabledRules(args.rules);
250253

@@ -260,9 +263,9 @@ fn runLinterRules(
260263
if (rule_config_overrides.get(rules[rule_index].rule_id)) |zon_path| {
261264
inline for (0..rules_configs_types.len) |i| {
262265
if (i == rule_index) {
263-
const arena = config_overrides_arena.allocator();
264-
const config = try arena.create(rules_configs_types[i]);
265-
errdefer arena.destroy(config);
266+
const config_arena = config_overrides_arena.allocator();
267+
const config = try config_arena.create(rules_configs_types[i]);
268+
errdefer config_arena.destroy(config);
266269

267270
var diagnostics: zlinter.zon.Diagnostics = .{};
268271

@@ -271,7 +274,7 @@ fn runLinterRules(
271274
std.fs.cwd(),
272275
zon_path,
273276
&diagnostics,
274-
arena,
277+
config_arena,
275278
) catch |e| {
276279
switch (e) {
277280
error.ParseZon => {
@@ -315,15 +318,16 @@ fn runLinterRules(
315318
}
316319
}
317320

318-
var arena = std.heap.ArenaAllocator.init(gpa);
319-
defer arena.deinit();
320-
const arena_allocator = arena.allocator();
321-
322-
var doc = try ctx.loadDocument(lint_file.pathname, ctx.gpa, arena_allocator) orelse {
323-
printer.println(.err, "Unable to open file: {s}", .{lint_file.pathname});
321+
var doc: zlinter.session.LintDocument = undefined;
322+
context.initDocument(
323+
lint_file.pathname,
324+
context.gpa,
325+
&doc,
326+
) catch |e| {
327+
printer.println(.err, "Unable to open file: {s} ({s})", .{ lint_file.pathname, @errorName(e) });
324328
continue :files;
325329
};
326-
defer doc.deinit(ctx.gpa);
330+
defer doc.deinit(context.gpa);
327331

328332
if (timer.lapMilliseconds()) |ms|
329333
printer.println(.verbose, " - Load document: {d}ms", .{ms})
@@ -370,7 +374,8 @@ fn runLinterRules(
370374
const rule = rules[rule_index];
371375
if (try rule.run(
372376
rule,
373-
doc,
377+
&context,
378+
&doc,
374379
gpa,
375380
.{ .config = rule_configs[rule_index] },
376381
)) |result| {

src/lib/ast.zig

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub const NodeAncestorIterator = struct {
1616
const Self = @This();
1717

1818
current: NodeIndexShim,
19-
lineage: *NodeLineage,
19+
lineage: *const NodeLineage,
2020
done: bool = false,
2121

2222
pub fn next(self: *Self) ?Ast.Node.Index {
@@ -37,7 +37,7 @@ pub const NodeLineageIterator = struct {
3737
const Self = @This();
3838

3939
queue: shims.ArrayList(NodeIndexShim) = .empty,
40-
lineage: *NodeLineage,
40+
lineage: *const NodeLineage,
4141
gpa: std.mem.Allocator,
4242

4343
pub fn deinit(self: *NodeLineageIterator) void {
@@ -121,7 +121,7 @@ pub const DeferBlock = struct {
121121
}
122122
};
123123

124-
pub fn deferBlock(doc: session.LintDocument, node: Ast.Node.Index, allocator: std.mem.Allocator) !?DeferBlock {
124+
pub fn deferBlock(doc: *const session.LintDocument, node: Ast.Node.Index, allocator: std.mem.Allocator) !?DeferBlock {
125125
const tree = doc.handle.tree;
126126

127127
const data = shims.nodeData(tree, node);
@@ -212,21 +212,20 @@ test "deferBlock - has expected children" {
212212

213213
defer _ = arena.reset(.retain_capacity);
214214

215-
var ctx: session.LintContext = undefined;
216-
try ctx.init(.{}, arena.allocator());
217-
defer ctx.deinit();
215+
var context: session.LintContext = undefined;
216+
try context.init(.{}, std.testing.allocator, arena.allocator());
217+
defer context.deinit();
218218

219219
var tmp = std.testing.tmpDir(.{});
220220
defer tmp.cleanup();
221221

222-
var doc = try testing.loadFakeDocument(
223-
&ctx,
222+
const doc = try testing.loadFakeDocument(
223+
&context,
224224
tmp.dir,
225225
"test.zig",
226226
"fn main() void {\n" ++ source ++ "\n}",
227227
arena.allocator(),
228228
);
229-
defer doc.deinit(arena.allocator());
230229

231230
const decl_ref = try deferBlock(
232231
doc,
@@ -608,7 +607,7 @@ test "isEnumLiteral" {
608607
/// Checks whether the current node is a function call or contains one in its
609608
/// children.
610609
pub fn findFnCall(
611-
doc: session.LintDocument,
610+
doc: *const session.LintDocument,
612611
node: Ast.Node.Index,
613612
call_buffer: *[1]Ast.Node.Index,
614613
comptime names: []const []const u8,
@@ -670,7 +669,7 @@ pub const FnCall = struct {
670669
///
671670
/// If names is empty, then it'll match all function names.
672671
pub fn fnCall(
673-
doc: session.LintDocument,
672+
doc: *const session.LintDocument,
674673
node: Ast.Node.Index,
675674
buffer: *[1]Ast.Node.Index,
676675
comptime names: []const []const u8,

src/lib/rules.zig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ pub const LintRule = struct {
33
rule_id: []const u8,
44
run: *const fn (
55
self: LintRule,
6-
doc: session.LintDocument,
7-
allocator: std.mem.Allocator,
6+
context: *session.LintContext,
7+
doc: *const session.LintDocument,
8+
gpa: std.mem.Allocator,
89
options: RunOptions,
910
) error{OutOfMemory}!?results.LintResult,
1011
};

0 commit comments

Comments
 (0)