list
This commit is contained in:
@@ -547,6 +547,23 @@ pub const Parser = struct {
|
||||
return try params.toOwnedSlice(self.allocator);
|
||||
}
|
||||
|
||||
/// Recursively find all generic type names ($T) in a type expression tree.
|
||||
fn collectGenericNames(node: *Node, list: *std.ArrayList([]const u8), allocator: std.mem.Allocator) void {
|
||||
switch (node.data) {
|
||||
.type_expr => |te| {
|
||||
if (te.is_generic) list.append(allocator, te.name) catch {};
|
||||
},
|
||||
.pointer_type_expr => |pte| collectGenericNames(pte.pointee_type, list, allocator),
|
||||
.many_pointer_type_expr => |mpte| collectGenericNames(mpte.element_type, list, allocator),
|
||||
.slice_type_expr => |ste| collectGenericNames(ste.element_type, list, allocator),
|
||||
.array_type_expr => |ate| collectGenericNames(ate.element_type, list, allocator),
|
||||
.parameterized_type_expr => |pte| {
|
||||
for (pte.args) |arg| collectGenericNames(arg, list, allocator);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect generic type params and comptime value params from parameter annotations.
|
||||
fn collectTypeParams(self: *Parser, params: []const ast.Param) ![]const ast.StructTypeParam {
|
||||
var type_params = std.ArrayList(ast.StructTypeParam).empty;
|
||||
@@ -563,25 +580,20 @@ pub const Parser = struct {
|
||||
try type_params.append(self.allocator, .{ .name = param.name, .constraint = param.type_expr });
|
||||
}
|
||||
} else {
|
||||
// Check for generic type param: direct $T or nested inside []$T
|
||||
const generic_type_expr: ?*Node = if (param.type_expr.data == .type_expr and param.type_expr.data.type_expr.is_generic)
|
||||
param.type_expr
|
||||
else if (param.type_expr.data == .slice_type_expr) blk: {
|
||||
const elem = param.type_expr.data.slice_type_expr.element_type;
|
||||
break :blk if (elem.data == .type_expr and elem.data.type_expr.is_generic) elem else null;
|
||||
} else null;
|
||||
|
||||
if (generic_type_expr) |gte| {
|
||||
// Collect all generic type params found anywhere in the type expression
|
||||
var generic_names = std.ArrayList([]const u8).empty;
|
||||
collectGenericNames(param.type_expr, &generic_names, self.allocator);
|
||||
for (generic_names.items) |gen_name| {
|
||||
var found = false;
|
||||
for (type_params.items) |existing| {
|
||||
if (std.mem.eql(u8, existing.name, gte.data.type_expr.name)) {
|
||||
if (std.mem.eql(u8, existing.name, gen_name)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
const type_constraint = try self.createNode(param.type_expr.span.start, .{ .type_expr = .{ .name = "Type" } });
|
||||
try type_params.append(self.allocator, .{ .name = gte.data.type_expr.name, .constraint = type_constraint });
|
||||
const type_constraint = self.createNode(param.type_expr.span.start, .{ .type_expr = .{ .name = "Type" } }) catch continue;
|
||||
type_params.append(self.allocator, .{ .name = gen_name, .constraint = type_constraint }) catch {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user