| author | |
| committer | |
| log | 5a313192e668501f7ab04b2f1d55b92a3cf33a0e |
| tree | 1a5c5cfca3c5386b0cde33f0c5e8df8b96700eb1 |
| parent | d2e70ef84a912947f6485f6fc480030c2d6a8c8f |
2 files changed, 114 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 | 130 | const child_node = scope.get_child(name) orelse return null; |
| 131 | 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 | 204 | else => return null, |
| 134 | 205 | } |
| 135 | 206 | } |
lib/docs/wasm/main.zig+43-4| ... | ... | @@ -380,16 +380,48 @@ export fn decl_params(decl_index: Decl.Index) Slice(Ast.Node.Index) { |
| 380 | 380 | } |
| 381 | 381 | |
| 382 | 382 | fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { |
| 383 | const decl = decl_index.get(); | |
| 384 | const ast = decl.file.get_ast(); | |
| 385 | ||
| 386 | switch (decl.categorize()) { | |
| 387 | .type_function => { | |
| 388 | const node_tags = ast.nodes.items(.tag); | |
| 389 | ||
| 390 | // Find the return statement | |
| 391 | if (decl.get_type_fn_return_expr()) |return_expr| { | |
| 392 | switch (node_tags[return_expr]) { | |
| 393 | .call, .call_comma, .call_one, .call_one_comma => { | |
| 394 | const node_data = ast.nodes.items(.data); | |
| 395 | const function = node_data[return_expr].lhs; | |
| 396 | const token = ast.nodes.items(.main_token)[function]; | |
| 397 | const name = ast.tokenSlice(token); | |
| 398 | if (decl.lookup(name)) |function_decl| { | |
| 399 | return decl_fields_fallible(function_decl); | |
| 400 | } | |
| 401 | }, | |
| 402 | .container_decl, .container_decl_trailing, .container_decl_two, .container_decl_two_trailing, .container_decl_arg, .container_decl_arg_trailing => { | |
| 403 | return ast_decl_fields_fallible(ast, return_expr); | |
| 404 | }, | |
| 405 | else => {}, | |
| 406 | } | |
| 407 | } | |
| 408 | return &.{}; | |
| 409 | }, | |
| 410 | else => { | |
| 411 | const value_node = decl.value_node() orelse return &.{}; | |
| 412 | return ast_decl_fields_fallible(ast, value_node); | |
| 413 | }, | |
| 414 | } | |
| 415 | } | |
| 416 | ||
| 417 | fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.Index { | |
| 383 | 418 | const g = struct { |
| 384 | 419 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; |
| 385 | 420 | }; |
| 386 | 421 | g.result.clearRetainingCapacity(); |
| 387 | const decl = decl_index.get(); | |
| 388 | const ast = decl.file.get_ast(); | |
| 389 | 422 | const node_tags = ast.nodes.items(.tag); |
| 390 | const value_node = decl.value_node() orelse return &.{}; | |
| 391 | 423 | var buf: [2]Ast.Node.Index = undefined; |
| 392 | const container_decl = ast.fullContainerDecl(&buf, value_node) orelse return &.{}; | |
| 424 | const container_decl = ast.fullContainerDecl(&buf, ast_index) orelse return &.{}; | |
| 393 | 425 | for (container_decl.ast.members) |member_node| switch (node_tags[member_node]) { |
| 394 | 426 | .container_field_init, |
| 395 | 427 | .container_field_align, |
| ... | ... | @@ -883,6 +915,13 @@ export fn categorize_decl(decl_index: Decl.Index, resolve_alias_count: usize) Wa |
| 883 | 915 | } |
| 884 | 916 | |
| 885 | 917 | export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) { |
| 918 | const decl = parent.get(); | |
| 919 | ||
| 920 | // If the type function returns another type function, get the members of that function | |
| 921 | if (decl.get_type_fn_return_type_fn()) |function_decl| { | |
| 922 | return namespace_members(function_decl, include_private); | |
| 923 | } | |
| 924 | ||
| 886 | 925 | return namespace_members(parent, include_private); |
| 887 | 926 | } |
| 888 | 927 |