|
1 | 1 | const std = @import("std"); |
2 | 2 | const jinja = @import("jinja.zig"); |
| 3 | +const resolve = @import("resolve.zig"); |
3 | 4 | const types = @import("types.zig"); |
4 | 5 | const util = @import("util.zig"); |
5 | 6 |
|
6 | 7 | const JsonScalar = types.JsonScalar; |
7 | 8 | const GenericTestDef = types.GenericTestDef; |
8 | 9 | const Graph = types.Graph; |
| 10 | +const MacroArgument = types.MacroArgument; |
9 | 11 | const RefDep = types.RefDep; |
10 | 12 | const dupTrimmedScalar = util.dupTrimmedScalar; |
11 | 13 | const findMatchingParen = jinja.findMatchingParen; |
12 | 14 | const parseLiteralArgs = jinja.parseLiteralArgs; |
| 15 | +const findMacroIndexByPackageAndName = resolve.findMacroIndexByPackageAndName; |
13 | 16 |
|
14 | 17 | pub fn parseBool(value: []const u8) !bool { |
15 | 18 | const trimmed = std.mem.trim(u8, value, " \t\r"); |
@@ -101,6 +104,32 @@ pub fn appendGenericTestDefClone(graph: *Graph, tests: *std.ArrayList(GenericTes |
101 | 104 | try tests.append(graph.allocator, cloned); |
102 | 105 | } |
103 | 106 |
|
| 107 | +pub fn applyMacroProperties(graph: *Graph) !void { |
| 108 | + for (graph.macro_properties.items) |property| { |
| 109 | + const macro_index = findMacroIndexByPackageAndName(graph, property.package_name, property.name) orelse { |
| 110 | + try graph.unmatched_macro_properties.append(graph.allocator, .{ .name = property.name, .patch_path = property.patch_path }); |
| 111 | + continue; |
| 112 | + }; |
| 113 | + var macro = &graph.macros.items[macro_index]; |
| 114 | + macro.patch_path = property.patch_path; |
| 115 | + if (property.description.len != 0) macro.description = property.description; |
| 116 | + for (property.arguments.items) |argument| { |
| 117 | + try appendMacroArgumentClone(graph, ¯o.arguments, argument); |
| 118 | + } |
| 119 | + } |
| 120 | +} |
| 121 | + |
| 122 | +fn appendMacroArgumentClone(graph: *Graph, arguments: *std.ArrayList(MacroArgument), source: MacroArgument) !void { |
| 123 | + for (arguments.items) |*existing| { |
| 124 | + if (std.mem.eql(u8, existing.name, source.name)) { |
| 125 | + if (source.type.len != 0) existing.type = source.type; |
| 126 | + if (source.description.len != 0) existing.description = source.description; |
| 127 | + return; |
| 128 | + } |
| 129 | + } |
| 130 | + try arguments.append(graph.allocator, source); |
| 131 | +} |
| 132 | + |
104 | 133 | pub fn refDepFromValue(allocator: std.mem.Allocator, value: []const u8) !RefDep { |
105 | 134 | const trimmed = std.mem.trim(u8, value, " \t\r"); |
106 | 135 | if (std.mem.startsWith(u8, trimmed, "ref(")) { |
@@ -368,6 +397,78 @@ test "appendGenericTestDefClone copies nested accepted values list" { |
368 | 397 | try std.testing.expectEqualStrings("returned", clones.items[0].accepted_values.items[1]); |
369 | 398 | } |
370 | 399 |
|
| 400 | +test "applyMacroProperties applies descriptions patch paths and merges arguments" { |
| 401 | + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); |
| 402 | + defer arena.deinit(); |
| 403 | + const allocator = arena.allocator(); |
| 404 | + |
| 405 | + var graph = Graph{ .allocator = allocator, .project_name = "demo" }; |
| 406 | + defer graph.deinit(); |
| 407 | + |
| 408 | + try graph.macros.append(allocator, .{ |
| 409 | + .unique_id = "macro.demo.format_id", |
| 410 | + .package_name = "demo", |
| 411 | + .name = "format_id", |
| 412 | + .path = "macros/format_id.sql", |
| 413 | + .original_file_path = "macros/format_id.sql", |
| 414 | + .macro_sql = "", |
| 415 | + }); |
| 416 | + try graph.macros.items[0].arguments.append(allocator, .{ |
| 417 | + .name = "column_name", |
| 418 | + .type = "string", |
| 419 | + .description = "", |
| 420 | + }); |
| 421 | + |
| 422 | + try graph.macro_properties.append(allocator, .{ |
| 423 | + .package_name = "demo", |
| 424 | + .name = "format_id", |
| 425 | + .patch_path = "macros/schema.yml", |
| 426 | + .description = "Formats an identifier.", |
| 427 | + }); |
| 428 | + try graph.macro_properties.items[0].arguments.append(allocator, .{ |
| 429 | + .name = "column_name", |
| 430 | + .type = "", |
| 431 | + .description = "Identifier expression.", |
| 432 | + }); |
| 433 | + try graph.macro_properties.items[0].arguments.append(allocator, .{ |
| 434 | + .name = "quote", |
| 435 | + .type = "bool", |
| 436 | + .description = "Whether to quote.", |
| 437 | + }); |
| 438 | + |
| 439 | + try applyMacroProperties(&graph); |
| 440 | + |
| 441 | + try std.testing.expectEqualStrings("macros/schema.yml", graph.macros.items[0].patch_path.?); |
| 442 | + try std.testing.expectEqualStrings("Formats an identifier.", graph.macros.items[0].description); |
| 443 | + try std.testing.expectEqual(@as(usize, 2), graph.macros.items[0].arguments.items.len); |
| 444 | + try std.testing.expectEqualStrings("column_name", graph.macros.items[0].arguments.items[0].name); |
| 445 | + try std.testing.expectEqualStrings("string", graph.macros.items[0].arguments.items[0].type); |
| 446 | + try std.testing.expectEqualStrings("Identifier expression.", graph.macros.items[0].arguments.items[0].description); |
| 447 | + try std.testing.expectEqualStrings("quote", graph.macros.items[0].arguments.items[1].name); |
| 448 | + try std.testing.expectEqualStrings("bool", graph.macros.items[0].arguments.items[1].type); |
| 449 | +} |
| 450 | + |
| 451 | +test "applyMacroProperties records unmatched macro properties" { |
| 452 | + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); |
| 453 | + defer arena.deinit(); |
| 454 | + const allocator = arena.allocator(); |
| 455 | + |
| 456 | + var graph = Graph{ .allocator = allocator, .project_name = "demo" }; |
| 457 | + defer graph.deinit(); |
| 458 | + |
| 459 | + try graph.macro_properties.append(allocator, .{ |
| 460 | + .package_name = "demo", |
| 461 | + .name = "missing_macro", |
| 462 | + .patch_path = "macros/schema.yml", |
| 463 | + }); |
| 464 | + |
| 465 | + try applyMacroProperties(&graph); |
| 466 | + |
| 467 | + try std.testing.expectEqual(@as(usize, 1), graph.unmatched_macro_properties.items.len); |
| 468 | + try std.testing.expectEqualStrings("missing_macro", graph.unmatched_macro_properties.items[0].name); |
| 469 | + try std.testing.expectEqualStrings("macros/schema.yml", graph.unmatched_macro_properties.items[0].patch_path); |
| 470 | +} |
| 471 | + |
371 | 472 | test "refDepFromValue parses relationship target refs and raw model names" { |
372 | 473 | var arena = std.heap.ArenaAllocator.init(std.testing.allocator); |
373 | 474 | defer arena.deinit(); |
|
0 commit comments