From 2511830442fd96d04f578f2c4251b1994f08c994 Mon Sep 17 00:00:00 2001 From: Ian Johnson Date: Sun, 7 Jul 2024 22:12:37 -0400 Subject: [PATCH] Autodoc: only group structs under "namespaces" The old heuristic of checking only for the number of fields has the downside of classifying all opaque types, such as `std.c.FILE`, as "namespaces" rather than "types". --- lib/docs/main.js | 30 +++++++++++----------- lib/docs/wasm/Decl.zig | 4 +-- lib/docs/wasm/Walk.zig | 57 ++++++++++++++++++++++++++---------------- lib/docs/wasm/main.zig | 9 +------ 4 files changed, 53 insertions(+), 47 deletions(-) diff --git a/lib/docs/main.js b/lib/docs/main.js index d9888eac68..49c277b9f5 100644 --- a/lib/docs/main.js +++ b/lib/docs/main.js @@ -1,14 +1,15 @@ (function() { const CAT_namespace = 0; - const CAT_global_variable = 1; - const CAT_function = 2; - const CAT_primitive = 3; - const CAT_error_set = 4; - const CAT_global_const = 5; - const CAT_alias = 6; - const CAT_type = 7; - const CAT_type_type = 8; - const CAT_type_function = 9; + const CAT_container = 1; + const CAT_global_variable = 2; + const CAT_function = 3; + const CAT_primitive = 4; + const CAT_error_set = 5; + const CAT_global_const = 6; + const CAT_alias = 7; + const CAT_type = 8; + const CAT_type_type = 9; + const CAT_type_function = 10; const domDocTestsCode = document.getElementById("docTestsCode"); const domFnErrorsAnyError = document.getElementById("fnErrorsAnyError"); @@ -184,6 +185,7 @@ const category = wasm_exports.categorize_decl(decl_index, 0); switch (category) { case CAT_namespace: + case CAT_container: return renderNamespacePage(decl_index); case CAT_global_variable: case CAT_primitive: @@ -426,16 +428,12 @@ while (true) { const member_category = wasm_exports.categorize_decl(member, 0); switch (member_category) { - case CAT_namespace: - if (wasm_exports.decl_field_count(member) > 0) { - typesList.push({original: original, member: member}); - } else { - namespacesList.push({original: original, member: member}); - } - continue member_loop; case CAT_namespace: namespacesList.push({original: original, member: member}); continue member_loop; + case CAT_container: + typesList.push({original: original, member: member}); + continue member_loop; case CAT_global_variable: varsList.push(member); continue member_loop; diff --git a/lib/docs/wasm/Decl.zig b/lib/docs/wasm/Decl.zig index 1df7790582..0260ce0285 100644 --- a/lib/docs/wasm/Decl.zig +++ b/lib/docs/wasm/Decl.zig @@ -115,7 +115,7 @@ pub fn categorize(decl: *const Decl) Walk.Category { pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index { switch (decl.categorize()) { .alias => |aliasee| return aliasee.get().get_child(name), - .namespace => |node| { + .namespace, .container => |node| { const file = decl.file.get(); const scope = file.scopes.get(node) orelse return null; const child_node = scope.get_child(name) orelse return null; @@ -128,7 +128,7 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index { /// Looks up a decl by name accessible in `decl`'s namespace. pub fn lookup(decl: *const Decl, name: []const u8) ?Decl.Index { const namespace_node = switch (decl.categorize()) { - .namespace => |node| node, + .namespace, .container => |node| node, else => decl.parent.get().ast_node, }; const file = decl.file.get(); diff --git a/lib/docs/wasm/Walk.zig b/lib/docs/wasm/Walk.zig index 3f7ccc4bac..a22da861a8 100644 --- a/lib/docs/wasm/Walk.zig +++ b/lib/docs/wasm/Walk.zig @@ -7,7 +7,10 @@ file: File.Index, /// keep in sync with "CAT_" constants in main.js pub const Category = union(enum(u8)) { + /// A struct type used only to group declarations. namespace: Ast.Node.Index, + /// A container type (struct, union, enum, opaque). + container: Ast.Node.Index, global_variable: Ast.Node.Index, /// A function that has not been detected as returning a type. function: Ast.Node.Index, @@ -45,13 +48,6 @@ pub const File = struct { return file.node_decls.get(decl_node) orelse return .none; } - pub fn field_count(file: *const File, node: Ast.Node.Index) u32 { - const scope = file.scopes.get(node) orelse return 0; - if (scope.tag != .namespace) return 0; - const namespace: *Scope.Namespace = @alignCast(@fieldParentPtr("base", scope)); - return namespace.field_count; - } - pub const Index = enum(u32) { _, @@ -87,7 +83,18 @@ pub const File = struct { const node_tags = ast.nodes.items(.tag); const token_tags = ast.tokens.items(.tag); switch (node_tags[node]) { - .root => return .{ .namespace = node }, + .root => { + for (ast.rootDecls()) |member| { + switch (node_tags[member]) { + .container_field_init, + .container_field_align, + .container_field, + => return .{ .container = node }, + else => {}, + } + } + return .{ .namespace = node }; + }, .global_var_decl, .local_var_decl, @@ -122,7 +129,7 @@ pub const File = struct { full: Ast.full.FnProto, ) Category { return switch (categorize_expr(file_index, full.ast.return_type)) { - .namespace, .error_set, .type_type => .{ .type_function = node }, + .namespace, .container, .error_set, .type_type => .{ .type_function = node }, else => .{ .function = node }, }; } @@ -140,6 +147,7 @@ pub const File = struct { const node_tags = ast.nodes.items(.tag); const node_datas = ast.nodes.items(.data); const main_tokens = ast.nodes.items(.main_token); + const token_tags = ast.tokens.items(.tag); //log.debug("categorize_expr tag {s}", .{@tagName(node_tags[node])}); return switch (node_tags[node]) { .container_decl, @@ -154,7 +162,23 @@ pub const File = struct { .tagged_union_enum_tag_trailing, .tagged_union_two, .tagged_union_two_trailing, - => .{ .namespace = node }, + => { + var buf: [2]Ast.Node.Index = undefined; + const container_decl = ast.fullContainerDecl(&buf, node).?; + if (token_tags[container_decl.ast.main_token] != .keyword_struct) { + return .{ .container = node }; + } + for (container_decl.ast.members) |member| { + switch (node_tags[member]) { + .container_field_init, + .container_field_align, + .container_field, + => return .{ .container = node }, + else => {}, + } + } + return .{ .namespace = node }; + }, .error_set_decl, .merge_error_sets, @@ -240,6 +264,7 @@ pub const File = struct { return .{ .error_set = node }; } else if (then_cat == .type or else_cat == .type or then_cat == .namespace or else_cat == .namespace or + then_cat == .container or else_cat == .container or then_cat == .error_set or else_cat == .error_set or then_cat == .type_function or else_cat == .type_function) { @@ -346,7 +371,7 @@ pub const File = struct { any_type = true; all_type_type = false; }, - .type, .namespace, .type_function => { + .type, .namespace, .container, .type_function => { any_type = true; all_error_set = false; all_type_type = false; @@ -431,7 +456,6 @@ pub const Scope = struct { names: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .{}, doctests: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .{}, decl_index: Decl.Index, - field_count: u32, }; fn getNamespaceDecl(start_scope: *Scope) Decl.Index { @@ -500,7 +524,6 @@ fn struct_decl( namespace.* = .{ .parent = scope, .decl_index = parent_decl, - .field_count = 0, }; try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base); try w.scanDecls(namespace, container_decl.ast.members); @@ -1061,14 +1084,6 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In continue; }, - .container_field_init, - .container_field_align, - .container_field, - => { - namespace.field_count += 1; - continue; - }, - else => continue, }; diff --git a/lib/docs/wasm/main.zig b/lib/docs/wasm/main.zig index 7108b1bd84..f5ce02d7d6 100644 --- a/lib/docs/wasm/main.zig +++ b/lib/docs/wasm/main.zig @@ -274,13 +274,6 @@ export fn fn_error_set_decl(decl_index: Decl.Index, node: Ast.Node.Index) Decl.I }; } -export fn decl_field_count(decl_index: Decl.Index) u32 { - switch (decl_index.get().categorize()) { - .namespace => |node| return decl_index.get().file.get().field_count(node), - else => return 0, - } -} - fn decl_error_set_fallible(decl_index: Decl.Index) Oom![]ErrorIdentifier { error_set_result.clearRetainingCapacity(); try addErrorsFromDecl(decl_index, &error_set_result); @@ -583,7 +576,7 @@ export fn decl_category_name(decl_index: Decl.Index) String { const ast = decl.file.get_ast(); const token_tags = ast.tokens.items(.tag); const name = switch (decl.categorize()) { - .namespace => |node| { + .namespace, .container => |node| { const node_tags = ast.nodes.items(.tag); if (node_tags[decl.ast_node] == .root) return String.init("struct");