Function lastToken [src]

Prototype

pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex

Parameters

tree: Astnode: Node.Index

Source

pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { var n = node; var end_offset: u32 = 0; while (true) switch (tree.nodeTag(n)) { .root => return @intCast(tree.tokens.len - 1), .@"usingnamespace", .bool_not, .negation, .bit_not, .negation_wrap, .address_of, .@"try", .@"await", .optional_type, .@"suspend", .@"resume", .@"nosuspend", .@"comptime", => n = tree.nodeData(n).node, .@"catch", .equal_equal, .bang_equal, .less_than, .greater_than, .less_or_equal, .greater_or_equal, .assign_mul, .assign_div, .assign_mod, .assign_add, .assign_sub, .assign_shl, .assign_shl_sat, .assign_shr, .assign_bit_and, .assign_bit_xor, .assign_bit_or, .assign_mul_wrap, .assign_add_wrap, .assign_sub_wrap, .assign_mul_sat, .assign_add_sat, .assign_sub_sat, .assign, .merge_error_sets, .mul, .div, .mod, .array_mult, .mul_wrap, .mul_sat, .add, .sub, .array_cat, .add_wrap, .sub_wrap, .add_sat, .sub_sat, .shl, .shl_sat, .shr, .bit_and, .bit_xor, .bit_or, .@"orelse", .bool_and, .bool_or, .error_union, .if_simple, .while_simple, .for_simple, .fn_decl, .array_type, .switch_range, => n = tree.nodeData(n).node_and_node[1], .test_decl, .@"errdefer" => n = tree.nodeData(n).opt_token_and_node[1], .@"defer" => n = tree.nodeData(n).node, .anyframe_type => n = tree.nodeData(n).token_and_node[1], .switch_case_one, .switch_case_inline_one, .ptr_type_aligned, .ptr_type_sentinel, => n = tree.nodeData(n).opt_node_and_node[1], .assign_destructure, .ptr_type, .ptr_type_bit_range, .switch_case, .switch_case_inline, => n = tree.nodeData(n).extra_and_node[1], .fn_proto_simple => n = tree.nodeData(n).opt_node_and_opt_node[1].unwrap().?, .fn_proto_multi, .fn_proto_one, .fn_proto, => n = tree.nodeData(n).extra_and_opt_node[1].unwrap().?, .for_range => { n = tree.nodeData(n).node_and_opt_node[1].unwrap() orelse { return tree.nodeMainToken(n) + end_offset; }; }, .field_access, .unwrap_optional, .asm_simple, => return tree.nodeData(n).node_and_token[1] + end_offset, .grouped_expression, .asm_input => return tree.nodeData(n).node_and_token[1] + end_offset, .multiline_string_literal, .error_set_decl => return tree.nodeData(n).token_and_token[1] + end_offset, .asm_output => return tree.nodeData(n).opt_node_and_token[1] + end_offset, .error_value => return tree.nodeMainToken(n) + 2 + end_offset, .anyframe_literal, .char_literal, .number_literal, .unreachable_literal, .identifier, .deref, .enum_literal, .string_literal, => return tree.nodeMainToken(n) + end_offset, .@"return" => { n = tree.nodeData(n).opt_node.unwrap() orelse { return tree.nodeMainToken(n) + end_offset; }; }, .call, .async_call => { _, const extra_index = tree.nodeData(n).node_and_extra; const params = tree.extraData(extra_index, Node.SubRange); assert(params.start != params.end); end_offset += 1; // for the rparen n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter }, .tagged_union_enum_tag => { const arg, const extra_index = tree.nodeData(n).node_and_extra; const members = tree.extraData(extra_index, Node.SubRange); if (members.start == members.end) { end_offset += 4; // for the rparen + rparen + lbrace + rbrace n = arg; } else { end_offset += 1; // for the rbrace n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter } }, .call_comma, .async_call_comma, .tagged_union_enum_tag_trailing, => { _, const extra_index = tree.nodeData(n).node_and_extra; const params = tree.extraData(extra_index, Node.SubRange); assert(params.start != params.end); end_offset += 2; // for the comma/semicolon + rparen/rbrace n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter }, .@"switch" => { const condition, const extra_index = tree.nodeData(n).node_and_extra; const cases = tree.extraData(extra_index, Node.SubRange); if (cases.start == cases.end) { end_offset += 3; // rparen, lbrace, rbrace n = condition; } else { end_offset += 1; // for the rbrace n = @enumFromInt(tree.extra_data[@intFromEnum(cases.end) - 1]); // last case } }, .container_decl_arg => { const arg, const extra_index = tree.nodeData(n).node_and_extra; const members = tree.extraData(extra_index, Node.SubRange); if (members.end == members.start) { end_offset += 3; // for the rparen + lbrace + rbrace n = arg; } else { end_offset += 1; // for the rbrace n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter } }, .@"asm" => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.Asm); return extra.rparen + end_offset; }, .array_init, .struct_init, => { _, const extra_index = tree.nodeData(n).node_and_extra; const elements = tree.extraData(extra_index, Node.SubRange); assert(elements.start != elements.end); end_offset += 1; // for the rbrace n = @enumFromInt(tree.extra_data[@intFromEnum(elements.end) - 1]); // last element }, .array_init_comma, .struct_init_comma, .container_decl_arg_trailing, .switch_comma, => { _, const extra_index = tree.nodeData(n).node_and_extra; const members = tree.extraData(extra_index, Node.SubRange); assert(members.start != members.end); end_offset += 2; // for the comma + rbrace n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter }, .array_init_dot, .struct_init_dot, .block, .container_decl, .tagged_union, .builtin_call, => { const range = tree.nodeData(n).extra_range; assert(range.start != range.end); end_offset += 1; // for the rbrace n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last statement }, .array_init_dot_comma, .struct_init_dot_comma, .block_semicolon, .container_decl_trailing, .tagged_union_trailing, .builtin_call_comma, => { const range = tree.nodeData(n).extra_range; assert(range.start != range.end); end_offset += 2; // for the comma/semicolon + rbrace/rparen n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member }, .call_one, .async_call_one, => { _, const first_param = tree.nodeData(n).node_and_opt_node; end_offset += 1; // for the rparen n = first_param.unwrap() orelse { return tree.nodeMainToken(n) + end_offset; }; }, .array_init_dot_two, .block_two, .builtin_call_two, .struct_init_dot_two, .container_decl_two, .tagged_union_two, => { const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node; if (opt_rhs.unwrap()) |rhs| { end_offset += 1; // for the rparen/rbrace n = rhs; } else if (opt_lhs.unwrap()) |lhs| { end_offset += 1; // for the rparen/rbrace n = lhs; } else { switch (tree.nodeTag(n)) { .array_init_dot_two, .block_two, .struct_init_dot_two, => end_offset += 1, // rbrace .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace .container_decl_two => { var i: u32 = 2; // lbrace + rbrace while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1; end_offset += i; }, .tagged_union_two => { var i: u32 = 5; // (enum) {} while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1; end_offset += i; }, else => unreachable, } return tree.nodeMainToken(n) + end_offset; } }, .array_init_dot_two_comma, .builtin_call_two_comma, .block_two_semicolon, .struct_init_dot_two_comma, .container_decl_two_trailing, .tagged_union_two_trailing, => { const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node; end_offset += 2; // for the comma/semicolon + rbrace/rparen if (opt_rhs.unwrap()) |rhs| { n = rhs; } else if (opt_lhs.unwrap()) |lhs| { n = lhs; } else { unreachable; } }, .simple_var_decl => { const type_node, const init_node = tree.nodeData(n).opt_node_and_opt_node; if (init_node.unwrap()) |rhs| { n = rhs; } else if (type_node.unwrap()) |lhs| { n = lhs; } else { end_offset += 1; // from mut token to name return tree.nodeMainToken(n) + end_offset; } }, .aligned_var_decl => { const align_node, const init_node = tree.nodeData(n).node_and_opt_node; if (init_node.unwrap()) |rhs| { n = rhs; } else { end_offset += 1; // for the rparen n = align_node; } }, .global_var_decl => { const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node; if (init_node.unwrap()) |rhs| { n = rhs; } else { const extra = tree.extraData(extra_index, Node.GlobalVarDecl); if (extra.section_node.unwrap()) |section_node| { end_offset += 1; // for the rparen n = section_node; } else if (extra.align_node.unwrap()) |align_node| { end_offset += 1; // for the rparen n = align_node; } else if (extra.type_node.unwrap()) |type_node| { n = type_node; } else { end_offset += 1; // from mut token to name return tree.nodeMainToken(n) + end_offset; } } }, .local_var_decl => { const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node; if (init_node.unwrap()) |rhs| { n = rhs; } else { const extra = tree.extraData(extra_index, Node.LocalVarDecl); end_offset += 1; // for the rparen n = extra.align_node; } }, .container_field_init => { const type_expr, const value_expr = tree.nodeData(n).node_and_opt_node; n = value_expr.unwrap() orelse type_expr; }, .array_access, .array_init_one, .container_field_align, => { _, const rhs = tree.nodeData(n).node_and_node; end_offset += 1; // for the rbracket/rbrace/rparen n = rhs; }, .container_field => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.ContainerField); n = extra.value_expr; }, .struct_init_one => { _, const first_field = tree.nodeData(n).node_and_opt_node; end_offset += 1; // rbrace n = first_field.unwrap() orelse { return tree.nodeMainToken(n) + end_offset; }; }, .slice_open => { _, const start_node = tree.nodeData(n).node_and_node; end_offset += 2; // ellipsis2 + rbracket, or comma + rparen n = start_node; }, .array_init_one_comma => { _, const first_element = tree.nodeData(n).node_and_node; end_offset += 2; // comma + rbrace n = first_element; }, .call_one_comma, .async_call_one_comma, .struct_init_one_comma, => { _, const first_field = tree.nodeData(n).node_and_opt_node; end_offset += 2; // ellipsis2 + rbracket, or comma + rparen n = first_field.unwrap().?; }, .slice => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.Slice); end_offset += 1; // rbracket n = extra.end; }, .slice_sentinel => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.SliceSentinel); end_offset += 1; // rbracket n = extra.sentinel; }, .@"continue", .@"break" => { const opt_label, const opt_rhs = tree.nodeData(n).opt_token_and_opt_node; if (opt_rhs.unwrap()) |rhs| { n = rhs; } else if (opt_label.unwrap()) |lhs| { return lhs + end_offset; } else { return tree.nodeMainToken(n) + end_offset; } }, .while_cont => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.WhileCont); n = extra.then_expr; }, .@"while" => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.While); n = extra.else_expr; }, .@"if" => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.If); n = extra.else_expr; }, .@"for" => { const extra_index, const extra = tree.nodeData(n).@"for"; const index = @intFromEnum(extra_index) + extra.inputs + @intFromBool(extra.has_else); n = @enumFromInt(tree.extra_data[index]); }, .array_type_sentinel => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel); n = extra.elem_type; }, }; }