| ... | ... | @@ -567,7 +567,7 @@ fn struct_decl( |
| 567 | 567 | .aligned_var_decl, |
| 568 | 568 | => { |
| 569 | 569 | const decl_index = try w.file.add_decl(member, parent_decl); |
| 570 | | try w.global_var_decl(&namespace.base, decl_index, ast.fullVarDecl(member).?); |
| 570 | try w.global_var_decl(&namespace.base, decl_index, true, ast.fullVarDecl(member).?); |
| 571 | 571 | }, |
| 572 | 572 | |
| 573 | 573 | .@"comptime", |
| ... | ... | @@ -579,6 +579,61 @@ fn struct_decl( |
| 579 | 579 | }; |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | /// Traverses a container decl used as an expression without registering its members |
| 583 | /// as `Decl` entries. This prevents local/test-only helper declarations from |
| 584 | /// leaking into autodoc symbol lists. |
| 585 | fn struct_expr( |
| 586 | w: *Walk, |
| 587 | scope: *Scope, |
| 588 | parent_decl: Decl.Index, |
| 589 | node: Ast.Node.Index, |
| 590 | container_decl: Ast.full.ContainerDecl, |
| 591 | ) Oom!void { |
| 592 | const ast = w.file.get_ast(); |
| 593 | |
| 594 | const namespace = try gpa.create(Scope.Namespace); |
| 595 | namespace.* = .{ |
| 596 | .parent = scope, |
| 597 | .decl_index = parent_decl, |
| 598 | }; |
| 599 | try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base); |
| 600 | try w.scanDecls(namespace, container_decl.ast.members); |
| 601 | |
| 602 | for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) { |
| 603 | .container_field_init, |
| 604 | .container_field_align, |
| 605 | .container_field, |
| 606 | => try w.container_field(&namespace.base, parent_decl, ast.fullContainerField(member).?), |
| 607 | |
| 608 | .fn_proto, |
| 609 | .fn_proto_multi, |
| 610 | .fn_proto_one, |
| 611 | .fn_proto_simple, |
| 612 | .fn_decl, |
| 613 | => { |
| 614 | var buf: [1]Ast.Node.Index = undefined; |
| 615 | const full = ast.fullFnProto(&buf, member).?; |
| 616 | const body = if (ast.nodeTag(member) == .fn_decl) ast.nodeData(member).node_and_node[1].toOptional() else .none; |
| 617 | try w.fn_decl(&namespace.base, parent_decl, body, full); |
| 618 | }, |
| 619 | |
| 620 | .global_var_decl, |
| 621 | .local_var_decl, |
| 622 | .simple_var_decl, |
| 623 | .aligned_var_decl, |
| 624 | => { |
| 625 | // Do not create Decl entries; just walk initializer expressions. |
| 626 | try w.global_var_decl(&namespace.base, parent_decl, false, ast.fullVarDecl(member).?); |
| 627 | }, |
| 628 | |
| 629 | .@"comptime" => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node), |
| 630 | |
| 631 | .test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]), |
| 632 | |
| 633 | else => unreachable, |
| 634 | }; |
| 635 | } |
| 636 | |
| 582 | 637 | fn comptime_decl( |
| 583 | 638 | w: *Walk, |
| 584 | 639 | scope: *Scope, |
| ... | ... | @@ -596,13 +651,38 @@ fn global_var_decl( |
| 596 | 651 | w: *Walk, |
| 597 | 652 | scope: *Scope, |
| 598 | 653 | parent_decl: Decl.Index, |
| 654 | register_container_members: bool, |
| 599 | 655 | full: Ast.full.VarDecl, |
| 600 | 656 | ) Oom!void { |
| 601 | 657 | try w.maybe_expr(scope, parent_decl, full.ast.type_node); |
| 602 | 658 | try w.maybe_expr(scope, parent_decl, full.ast.align_node); |
| 603 | 659 | try w.maybe_expr(scope, parent_decl, full.ast.addrspace_node); |
| 604 | 660 | try w.maybe_expr(scope, parent_decl, full.ast.section_node); |
| 605 | | try w.maybe_expr(scope, parent_decl, full.ast.init_node); |
| 661 | |
| 662 | if (full.ast.init_node.unwrap()) |init_node| { |
| 663 | if (register_container_members) { |
| 664 | switch (w.file.get_ast().nodeTag(init_node)) { |
| 665 | .container_decl, |
| 666 | .container_decl_trailing, |
| 667 | .container_decl_arg, |
| 668 | .container_decl_arg_trailing, |
| 669 | .container_decl_two, |
| 670 | .container_decl_two_trailing, |
| 671 | .tagged_union, |
| 672 | .tagged_union_trailing, |
| 673 | .tagged_union_enum_tag, |
| 674 | .tagged_union_enum_tag_trailing, |
| 675 | .tagged_union_two, |
| 676 | .tagged_union_two_trailing, |
| 677 | => { |
| 678 | var buf: [2]Ast.Node.Index = undefined; |
| 679 | return struct_decl(w, scope, parent_decl, init_node, w.file.get_ast().fullContainerDecl(&buf, init_node).?); |
| 680 | }, |
| 681 | else => {}, |
| 682 | } |
| 683 | } |
| 684 | try w.expr(scope, parent_decl, init_node); |
| 685 | } |
| 606 | 686 | } |
| 607 | 687 | |
| 608 | 688 | fn container_field( |
| ... | ... | @@ -887,7 +967,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 887 | 967 | .tagged_union_two_trailing, |
| 888 | 968 | => { |
| 889 | 969 | var buf: [2]Ast.Node.Index = undefined; |
| 890 | | return struct_decl(w, scope, parent_decl, node, ast.fullContainerDecl(&buf, node).?); |
| 970 | return struct_expr(w, scope, parent_decl, node, ast.fullContainerDecl(&buf, node).?); |
| 891 | 971 | }, |
| 892 | 972 | |
| 893 | 973 | .array_type_sentinel => { |
| ... | ... | @@ -998,7 +1078,7 @@ fn block( |
| 998 | 1078 | .aligned_var_decl, |
| 999 | 1079 | => { |
| 1000 | 1080 | const full = ast.fullVarDecl(node).?; |
| 1001 | | try global_var_decl(w, scope, parent_decl, full); |
| 1081 | try global_var_decl(w, scope, parent_decl, false, full); |
| 1002 | 1082 | const local = try gpa.create(Scope.Local); |
| 1003 | 1083 | local.* = .{ |
| 1004 | 1084 | .parent = scope, |