-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpipeline.zig
131 lines (113 loc) · 5.03 KB
/
pipeline.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
const std = @import("std");
const fs = std.fs;
const jobz = @import("jobz");
const DirOptions = @import("codmod/jobs").files.DirOptions;
const prelude = @import("traits.zig");
const rls = @import("systems/rules.zig");
const trt = @import("systems/traits.zig");
const isu = @import("systems/issues.zig");
const SymbolsProvider = @import("systems/SymbolsProvider.zig");
const Model = @import("parse/Model.zig");
const ParseModel = @import("parse/parse.zig").ParseModel;
const ParseBehavior = @import("parse/issues.zig").ParseBehavior;
const CodegenService = @import("render/service.zig").CodegenService;
const JsonReader = @import("utils/JsonReader.zig");
pub const ScopeTag = enum {
slug,
parse_behavior,
codegen_behavior,
};
pub const PipelineBehavior = struct {
process: isu.IssueBehavior = .abort,
parse: isu.IssueBehavior = .abort,
codegen: isu.IssueBehavior = .abort,
};
pub const PipelineOptions = struct {
traits: ?trt.TraitsRegistry = null,
rules_builtins: rls.BuiltInsRegistry = &.{},
rules_funcs: rls.FunctionsRegistry = &.{},
behavior_service: PipelineBehavior = .{},
behavior_parse: ParseBehavior = .{},
};
pub const PipelineServiceFilterHook = jobz.Task.Hook("Smithy Service Filter", bool, &.{[]const u8});
pub const Pipeline = jobz.Task.Define("Smithy Service Pipeline", smithyTask, .{});
fn smithyTask(self: *const jobz.Delegate, src_dir: fs.Dir, options: PipelineOptions) anyerror!void {
const behavior = options.behavior_service;
try self.defineValue(ParseBehavior, ScopeTag.parse_behavior, options.behavior_parse);
const traits_manager: *trt.TraitsManager = try self.provide(trt.TraitsManager{}, null);
try prelude.registerTraits(self.alloc(), traits_manager);
if (options.traits) |registry| {
try traits_manager.registerAll(self.alloc(), registry);
}
_ = try self.provide(try rls.RulesEngine.init(self.alloc(), options.rules_builtins, options.rules_funcs), null);
var it = src_dir.iterate();
while (try it.next()) |entry| {
if (entry.kind != .file or !std.mem.endsWith(u8, entry.name, ".json")) continue;
processService(self, src_dir, entry.name, behavior) catch |err| switch (behavior.process) {
.abort => {
std.log.err("Processing model '{s}' failed: {s}", .{ entry.name, @errorName(err) });
if (@errorReturnTrace()) |t| std.debug.dumpStackTrace(t.*);
return isu.AbortError;
},
.skip => {
std.log.err("Skipped model '{s}': {s}", .{ entry.name, @errorName(err) });
return;
},
};
}
}
fn processService(self: *const jobz.Delegate, src_dir: fs.Dir, filename: []const u8, behavior: PipelineBehavior) !void {
if (self.hasOverride(PipelineServiceFilterHook)) {
const allowed = try self.evaluate(PipelineServiceFilterHook, .{filename});
if (!allowed) return;
}
try self.evaluate(SmithyService, .{ src_dir, filename, behavior });
}
const SmithyService = jobz.Task.Define("Smithy Service", smithyServiceTask, .{});
fn smithyServiceTask(self: *const jobz.Delegate, src_dir: fs.Dir, json_name: []const u8, behavior: PipelineBehavior) anyerror!void {
std.debug.assert(std.mem.endsWith(u8, json_name, ".json"));
const slug = json_name[0 .. json_name.len - ".json".len];
try self.defineValue([]const u8, ScopeTag.slug, slug);
const issues: *isu.IssuesBag = try self.provide(isu.IssuesBag.init(self.alloc()), null);
var symbols = serviceReadAndParse(self, src_dir, json_name) catch |err| {
return handleIssue(issues, behavior.parse, err, .parse_error, "Parsing failed", @errorReturnTrace());
};
_ = try self.provide(&symbols, null);
self.evaluate(CodegenService, .{ slug, DirOptions{
.create_on_not_found = true,
.delete_on_error = true,
} }) catch |err| {
return handleIssue(issues, behavior.codegen, err, .codegen_error, "Codegen failed", @errorReturnTrace());
};
}
fn serviceReadAndParse(self: *const jobz.Delegate, src_dir: fs.Dir, json_name: []const u8) !SymbolsProvider {
const json_file: fs.File = try src_dir.openFile(json_name, .{});
defer json_file.close();
var reader = try JsonReader.initPersist(self.alloc(), json_file);
defer reader.deinit();
var model: Model = try self.evaluate(ParseModel, .{&reader});
return SymbolsProvider.consumeModel(self.alloc(), &model);
}
fn handleIssue(
issues: *isu.IssuesBag,
behavior: isu.IssueBehavior,
err: anyerror,
comptime tag: anytype,
message: []const u8,
stack_trace: ?*std.builtin.StackTrace,
) !void {
switch (err) {
isu.AbortError => return err,
else => switch (behavior) {
.abort => {
std.log.err("{s}: {s}", .{ message, @errorName(err) });
if (stack_trace) |trace| std.debug.dumpStackTrace(trace.*);
return isu.AbortError;
},
.skip => {
issues.add(@unionInit(isu.Issue, @tagName(tag), err)) catch {};
return;
},
},
}
}