Fix TagFixerUpper

This commit is contained in:
Robin Voetter
2020-11-26 14:33:34 +01:00
parent b48fe074f5
commit c4c0279ecc

View File

@@ -106,21 +106,16 @@ const EnumFieldMerger = struct {
}; };
const TagFixerUpper = struct { const TagFixerUpper = struct {
const NameInfo = struct { allocator: *Allocator,
tagged_name: ?[]const u8,
tagless_name_exists: bool,
};
gpa: *Allocator,
registry: *reg.Registry, registry: *reg.Registry,
names: std.StringHashMap(NameInfo), names: std.StringHashMap(void),
id_renderer: *const IdRenderer, id_renderer: *const IdRenderer,
fn init(gpa: *Allocator, registry: *reg.Registry, id_renderer: *const IdRenderer) TagFixerUpper { fn init(allocator: *Allocator, registry: *reg.Registry, id_renderer: *const IdRenderer) TagFixerUpper {
return .{ return .{
.gpa = gpa, .allocator = allocator,
.registry = registry, .registry = registry,
.names = std.StringHashMap(NameInfo).init(gpa), .names = std.StringHashMap(void).init(allocator),
.id_renderer = id_renderer, .id_renderer = id_renderer,
}; };
} }
@@ -131,20 +126,10 @@ const TagFixerUpper = struct {
fn insertName(self: *TagFixerUpper, name: []const u8) !void { fn insertName(self: *TagFixerUpper, name: []const u8) !void {
const tagless = self.id_renderer.stripAuthorTag(name); const tagless = self.id_renderer.stripAuthorTag(name);
const is_tagged = tagless.len != name.len; const result = try self.names.getOrPut(name);
const result = try self.names.getOrPut(tagless);
if (result.found_existing) { if (result.found_existing) {
if (is_tagged) { return error.DuplicateDefinition;
result.entry.value.tagged_name = name;
} else {
result.entry.value.tagless_name_exists = true;
}
} else {
result.entry.value = .{
.tagged_name = if (is_tagged) name else null,
.tagless_name_exists = !is_tagged,
};
} }
} }
@@ -163,16 +148,22 @@ const TagFixerUpper = struct {
} }
} }
fn fixName(self: *TagFixerUpper, name: *[]const u8) !void { fn fixAlias(self: *TagFixerUpper, name: *[]const u8) !void {
const tagless = self.id_renderer.stripAuthorTag(name.*); if (self.names.contains(name.*)) {
const info = self.names.get(tagless) orelse return error.InvalidRegistry; // The alias exists, everything is fine
if (info.tagless_name_exists) { return;
name.* = tagless;
} else if (info.tagged_name) |tagged| {
name.* = tagged;
} else {
return error.InvalidRegistry;
} }
// The alias does not exist, check if the tagless version exists
const tagless = self.id_renderer.stripAuthorTag(name.*);
if (self.names.contains(tagless)) {
// Fix up the name to the tagless version
name.* = tagless;
return;
}
// Neither original nor tagless version exists
return error.InvalidRegistry;
} }
fn fixCommand(self: *TagFixerUpper, command: *reg.Command) !void { fn fixCommand(self: *TagFixerUpper, command: *reg.Command) !void {
@@ -182,17 +173,17 @@ const TagFixerUpper = struct {
try self.fixTypeInfo(command.return_type); try self.fixTypeInfo(command.return_type);
for (command.success_codes) |*code| { for (command.success_codes) |*code| {
try self.fixName(code); try self.fixAlias(code);
} }
for (command.error_codes) |*code| { for (command.error_codes) |*code| {
try self.fixName(code); try self.fixAlias(code);
} }
} }
fn fixTypeInfo(self: *TagFixerUpper, type_info: *reg.TypeInfo) error{InvalidRegistry}!void { fn fixTypeInfo(self: *TagFixerUpper, type_info: *reg.TypeInfo) error{InvalidRegistry}!void {
switch (type_info.*) { switch (type_info.*) {
.name => |*name| try self.fixName(name), .name => |*name| try self.fixAlias(name),
.command_ptr => |*command| try self.fixCommand(command), .command_ptr => |*command| try self.fixCommand(command),
.pointer => |ptr| try self.fixTypeInfo(ptr.child), .pointer => |ptr| try self.fixTypeInfo(ptr.child),
.array => |arr| try self.fixTypeInfo(arr.child), .array => |arr| try self.fixTypeInfo(arr.child),
@@ -210,17 +201,17 @@ const TagFixerUpper = struct {
.enumeration => |*enumeration| { .enumeration => |*enumeration| {
for (enumeration.fields) |*field| { for (enumeration.fields) |*field| {
if (field.value == .alias) { if (field.value == .alias) {
try self.fixName(&field.value.alias.name); try self.fixAlias(&field.value.alias.name);
} }
} }
}, },
.bitmask => |*bitmask| { .bitmask => |*bitmask| {
if (bitmask.bits_enum) |*bits| { if (bitmask.bits_enum) |*bits| {
try self.fixName(bits); try self.fixAlias(bits);
} }
}, },
.command => |*command| try self.fixCommand(command), .command => |*command| try self.fixCommand(command),
.alias => |*alias| try self.fixName(&alias.name), .alias => |*alias| try self.fixAlias(&alias.name),
.typedef => |*type_info| try self.fixTypeInfo(type_info), .typedef => |*type_info| try self.fixTypeInfo(type_info),
else => {}, else => {},
} }
@@ -228,7 +219,10 @@ const TagFixerUpper = struct {
} }
fn fixup(self: *TagFixerUpper) !void { fn fixup(self: *TagFixerUpper) !void {
// Extract all non-aliases
try self.extractNames(); try self.extractNames();
// Fix aliases
try self.fixNames(); try self.fixNames();
} }
}; };