| author | |
| committer | |
| log | 42438ce8b226d9c7421ef4a73414a32fcc6e6264 |
| tree | 1e23f666d5403c9631aeaedbfd521555b4629815 |
| parent | 0dcba03b67af0aee612b51191a8110d91a55019e |
| parent | 9e925a7acce05a69a26fe186acffb47dca326a11 |
| signature |
Autodoc: Improve documentation for common types declared as type functions2 files changed, 109 insertions(+), 4 deletions(-)
lib/docs/wasm/Decl.zig+71| ... | @@ -130,6 +130,77 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index { | ... | @@ -130,6 +130,77 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index { |
| 130 | const child_node = scope.get_child(name) orelse return null; | 130 | const child_node = scope.get_child(name) orelse return null; |
| 131 | return file.node_decls.get(child_node); | 131 | return file.node_decls.get(child_node); |
| 132 | }, | 132 | }, |
| 133 | .type_function => { | ||
| 134 | // Find a decl with this function as the parent, with a name matching `name` | ||
| 135 | for (Walk.decls.items, 0..) |*candidate, i| { | ||
| 136 | if (candidate.parent != .none and candidate.parent.get() == decl and std.mem.eql(u8, candidate.extra_info().name, name)) { | ||
| 137 | return @enumFromInt(i); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | return null; | ||
| 142 | }, | ||
| 143 | else => return null, | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | /// If the type function returns another type function, return the index of that type function. | ||
| 148 | pub fn get_type_fn_return_type_fn(decl: *const Decl) ?Decl.Index { | ||
| 149 | if (decl.get_type_fn_return_expr()) |return_expr| { | ||
| 150 | const ast = decl.file.get_ast(); | ||
| 151 | const node_tags = ast.nodes.items(.tag); | ||
| 152 | |||
| 153 | switch (node_tags[return_expr]) { | ||
| 154 | .call, .call_comma, .call_one, .call_one_comma => { | ||
| 155 | const node_data = ast.nodes.items(.data); | ||
| 156 | const function = node_data[return_expr].lhs; | ||
| 157 | const token = ast.nodes.items(.main_token)[function]; | ||
| 158 | const name = ast.tokenSlice(token); | ||
| 159 | if (decl.lookup(name)) |function_decl| { | ||
| 160 | return function_decl; | ||
| 161 | } | ||
| 162 | }, | ||
| 163 | else => {}, | ||
| 164 | } | ||
| 165 | } | ||
| 166 | return null; | ||
| 167 | } | ||
| 168 | |||
| 169 | /// Gets the expression after the `return` keyword in a type function declaration. | ||
| 170 | pub fn get_type_fn_return_expr(decl: *const Decl) ?Ast.Node.Index { | ||
| 171 | switch (decl.categorize()) { | ||
| 172 | .type_function => { | ||
| 173 | const ast = decl.file.get_ast(); | ||
| 174 | const node_tags = ast.nodes.items(.tag); | ||
| 175 | const node_data = ast.nodes.items(.data); | ||
| 176 | const body_node = node_data[decl.ast_node].rhs; | ||
| 177 | if (body_node == 0) return null; | ||
| 178 | |||
| 179 | switch (node_tags[body_node]) { | ||
| 180 | .block, .block_semicolon => { | ||
| 181 | const statements = ast.extra_data[node_data[body_node].lhs..node_data[body_node].rhs]; | ||
| 182 | // Look for the return statement | ||
| 183 | for (statements) |stmt| { | ||
| 184 | if (node_tags[stmt] == .@"return") { | ||
| 185 | return node_data[stmt].lhs; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | return null; | ||
| 189 | }, | ||
| 190 | .block_two, .block_two_semicolon => { | ||
| 191 | if (node_tags[node_data[body_node].lhs] == .@"return") { | ||
| 192 | return node_data[node_data[body_node].lhs].lhs; | ||
| 193 | } | ||
| 194 | if (node_data[body_node].rhs != 0 and | ||
| 195 | node_tags[node_data[body_node].rhs] == .@"return") | ||
| 196 | { | ||
| 197 | return node_data[node_data[body_node].rhs].lhs; | ||
| 198 | } | ||
| 199 | return null; | ||
| 200 | }, | ||
| 201 | else => return null, | ||
| 202 | } | ||
| 203 | }, | ||
| 133 | else => return null, | 204 | else => return null, |
| 134 | } | 205 | } |
| 135 | } | 206 | } |
lib/docs/wasm/main.zig+38-4| ... | @@ -386,16 +386,43 @@ export fn decl_params(decl_index: Decl.Index) Slice(Ast.Node.Index) { | ... | @@ -386,16 +386,43 @@ export fn decl_params(decl_index: Decl.Index) Slice(Ast.Node.Index) { |
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { | 388 | fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { |
| 389 | const decl = decl_index.get(); | ||
| 390 | const ast = decl.file.get_ast(); | ||
| 391 | |||
| 392 | switch (decl.categorize()) { | ||
| 393 | .type_function => { | ||
| 394 | const node_tags = ast.nodes.items(.tag); | ||
| 395 | |||
| 396 | // If the type function returns a reference to another type function, get the fields from there | ||
| 397 | if (decl.get_type_fn_return_type_fn()) |function_decl| { | ||
| 398 | return decl_fields_fallible(function_decl); | ||
| 399 | } | ||
| 400 | // If the type function returns a container, such as a `struct`, read that container's fields | ||
| 401 | if (decl.get_type_fn_return_expr()) |return_expr| { | ||
| 402 | switch (node_tags[return_expr]) { | ||
| 403 | .container_decl, .container_decl_trailing, .container_decl_two, .container_decl_two_trailing, .container_decl_arg, .container_decl_arg_trailing => { | ||
| 404 | return ast_decl_fields_fallible(ast, return_expr); | ||
| 405 | }, | ||
| 406 | else => {}, | ||
| 407 | } | ||
| 408 | } | ||
| 409 | return &.{}; | ||
| 410 | }, | ||
| 411 | else => { | ||
| 412 | const value_node = decl.value_node() orelse return &.{}; | ||
| 413 | return ast_decl_fields_fallible(ast, value_node); | ||
| 414 | }, | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.Index { | ||
| 389 | const g = struct { | 419 | const g = struct { |
| 390 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; | 420 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; |
| 391 | }; | 421 | }; |
| 392 | g.result.clearRetainingCapacity(); | 422 | g.result.clearRetainingCapacity(); |
| 393 | const decl = decl_index.get(); | ||
| 394 | const ast = decl.file.get_ast(); | ||
| 395 | const node_tags = ast.nodes.items(.tag); | 423 | const node_tags = ast.nodes.items(.tag); |
| 396 | const value_node = decl.value_node() orelse return &.{}; | ||
| 397 | var buf: [2]Ast.Node.Index = undefined; | 424 | var buf: [2]Ast.Node.Index = undefined; |
| 398 | const container_decl = ast.fullContainerDecl(&buf, value_node) orelse return &.{}; | 425 | const container_decl = ast.fullContainerDecl(&buf, ast_index) orelse return &.{}; |
| 399 | for (container_decl.ast.members) |member_node| switch (node_tags[member_node]) { | 426 | for (container_decl.ast.members) |member_node| switch (node_tags[member_node]) { |
| 400 | .container_field_init, | 427 | .container_field_init, |
| 401 | .container_field_align, | 428 | .container_field_align, |
| ... | @@ -880,6 +907,13 @@ export fn categorize_decl(decl_index: Decl.Index, resolve_alias_count: usize) Wa | ... | @@ -880,6 +907,13 @@ export fn categorize_decl(decl_index: Decl.Index, resolve_alias_count: usize) Wa |
| 880 | } | 907 | } |
| 881 | 908 | ||
| 882 | export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) { | 909 | export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) { |
| 910 | const decl = parent.get(); | ||
| 911 | |||
| 912 | // If the type function returns another type function, get the members of that function | ||
| 913 | if (decl.get_type_fn_return_type_fn()) |function_decl| { | ||
| 914 | return namespace_members(function_decl, include_private); | ||
| 915 | } | ||
| 916 | |||
| 883 | return namespace_members(parent, include_private); | 917 | return namespace_members(parent, include_private); |
| 884 | } | 918 | } |
| 885 | 919 |