Removed all zig.ast.Tree methods that call lastToken with our own versions
This commit is contained in:
		
							parent
							
								
									5a88f26980
								
							
						
					
					
						commit
						2415e7ca6d
					
				
							
								
								
									
										111
									
								
								src/analysis.zig
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								src/analysis.zig
									
									
									
									
									
								
							@ -726,7 +726,13 @@ pub fn resolveTypeOfNodeInternal(
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (try lookupSymbolGlobal(store, arena, handle, tree.getNodeSource(node), starts[main_tokens[node]])) |child| {
 | 
			
		||||
            if (try lookupSymbolGlobal(
 | 
			
		||||
                store,
 | 
			
		||||
                arena,
 | 
			
		||||
                handle,
 | 
			
		||||
                tree.getNodeSource(node),
 | 
			
		||||
                starts[main_tokens[node]],
 | 
			
		||||
            )) |child| {
 | 
			
		||||
                switch (child.decl.*) {
 | 
			
		||||
                    .ast_node => |n| {
 | 
			
		||||
                        if (n == node) return null;
 | 
			
		||||
@ -1443,28 +1449,6 @@ fn nodeContainsSourceIndex(tree: ast.Tree, node: ast.Node.Index, source_index: u
 | 
			
		||||
    return source_index >= first_token and source_index <= last_token;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn isBuiltinCall(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .builtin_call,
 | 
			
		||||
        .builtin_call_comma,
 | 
			
		||||
        .builtin_call_two,
 | 
			
		||||
        .builtin_call_two_comma,
 | 
			
		||||
        => true,
 | 
			
		||||
        else => false,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn fnProto(tree: ast.Tree, node: ast.Node.Index, buf: *[1]ast.Node.Index) ?ast.full.FnProto {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .fn_proto => tree.fnProto(node),
 | 
			
		||||
        .fn_proto_multi => tree.fnProtoMulti(node),
 | 
			
		||||
        .fn_proto_one => tree.fnProtoOne(buf, node),
 | 
			
		||||
        .fn_proto_simple => tree.fnProtoSimple(buf, node),
 | 
			
		||||
        .fn_decl => fnProto(tree, tree.nodes.items(.data)[node].lhs, buf),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn getImportStr(tree: ast.Tree, node: ast.Node.Index, source_index: usize) ?[]const u8 {
 | 
			
		||||
    const node_tags = tree.nodes.items(.tag);
 | 
			
		||||
    var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
@ -2058,25 +2042,6 @@ pub const DeclWithHandle = struct {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub fn containerField(tree: ast.Tree, node: ast.Node.Index) ?ast.full.ContainerField {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .container_field => tree.containerField(node),
 | 
			
		||||
        .container_field_init => tree.containerFieldInit(node),
 | 
			
		||||
        .container_field_align => tree.containerFieldAlign(node),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ptrType(tree: ast.Tree, node: ast.Node.Index) ?ast.full.PtrType {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .ptr_type => tree.ptrType(node),
 | 
			
		||||
        .ptr_type_aligned => tree.ptrTypeAligned(node),
 | 
			
		||||
        .ptr_type_bit_range => tree.ptrTypeBitRange(node),
 | 
			
		||||
        .ptr_type_sentinel => tree.ptrTypeSentinel(node),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn findContainerScope(container_handle: NodeWithHandle) ?*Scope {
 | 
			
		||||
    const container = container_handle.node;
 | 
			
		||||
    const handle = container_handle.handle;
 | 
			
		||||
@ -2551,56 +2516,6 @@ fn nodeSourceRange(tree: ast.Tree, node: ast.Node.Index) SourceRange {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isContainer(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .container_decl,
 | 
			
		||||
        .container_decl_trailing,
 | 
			
		||||
        .container_decl_arg,
 | 
			
		||||
        .container_decl_arg_trailing,
 | 
			
		||||
        .container_decl_two,
 | 
			
		||||
        .container_decl_two_trailing,
 | 
			
		||||
        .tagged_union,
 | 
			
		||||
        .tagged_union_trailing,
 | 
			
		||||
        .tagged_union_two,
 | 
			
		||||
        .tagged_union_two_trailing,
 | 
			
		||||
        .tagged_union_enum_tag,
 | 
			
		||||
        .tagged_union_enum_tag_trailing,
 | 
			
		||||
        .root,
 | 
			
		||||
        .error_set_decl,
 | 
			
		||||
        => true,
 | 
			
		||||
        else => false,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns the member indices of a given declaration container.
 | 
			
		||||
/// Asserts given `tag` is a container node
 | 
			
		||||
pub fn declMembers(tree: ast.Tree, node_idx: ast.Node.Index, buffer: *[2]ast.Node.Index) []const ast.Node.Index {
 | 
			
		||||
    std.debug.assert(isContainer(tree, node_idx));
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node_idx]) {
 | 
			
		||||
        .container_decl, .container_decl_trailing => tree.containerDecl(node_idx).ast.members,
 | 
			
		||||
        .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx).ast.members,
 | 
			
		||||
        .container_decl_two, .container_decl_two_trailing => tree.containerDeclTwo(buffer, node_idx).ast.members,
 | 
			
		||||
        .tagged_union, .tagged_union_trailing => tree.taggedUnion(node_idx).ast.members,
 | 
			
		||||
        .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(node_idx).ast.members,
 | 
			
		||||
        .tagged_union_two, .tagged_union_two_trailing => tree.taggedUnionTwo(buffer, node_idx).ast.members,
 | 
			
		||||
        .root => tree.rootDecls(),
 | 
			
		||||
        .error_set_decl => &[_]ast.Node.Index{},
 | 
			
		||||
        else => unreachable,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns an `ast.full.VarDecl` for a given node index.
 | 
			
		||||
/// Returns null if the tag doesn't match
 | 
			
		||||
pub fn varDecl(tree: ast.Tree, node_idx: ast.Node.Index) ?ast.full.VarDecl {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node_idx]) {
 | 
			
		||||
        .global_var_decl => tree.globalVarDecl(node_idx),
 | 
			
		||||
        .local_var_decl => tree.localVarDecl(node_idx),
 | 
			
		||||
        .aligned_var_decl => tree.alignedVarDecl(node_idx),
 | 
			
		||||
        .simple_var_decl => tree.simpleVarDecl(node_idx),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO Possibly collect all imports to diff them on changes
 | 
			
		||||
//      as well
 | 
			
		||||
fn makeScopeInternal(
 | 
			
		||||
@ -2890,7 +2805,7 @@ fn makeScopeInternal(
 | 
			
		||||
            const if_node: ast.full.If = if (node_tag == .@"if")
 | 
			
		||||
                ifFull(tree, node_idx)
 | 
			
		||||
            else
 | 
			
		||||
                tree.ifSimple(node_idx);
 | 
			
		||||
                ifSimple(tree, node_idx);
 | 
			
		||||
 | 
			
		||||
            if (if_node.payload_token) |payload| {
 | 
			
		||||
                var scope = try scopes.addOne(allocator);
 | 
			
		||||
@ -2962,15 +2877,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .@"for",
 | 
			
		||||
        .for_simple,
 | 
			
		||||
        => {
 | 
			
		||||
            const while_node: ast.full.While = switch (node_tag) {
 | 
			
		||||
                .@"while" => tree.whileFull(node_idx),
 | 
			
		||||
                .while_simple => tree.whileSimple(node_idx),
 | 
			
		||||
                .while_cont => tree.whileCont(node_idx),
 | 
			
		||||
                .@"for" => tree.forFull(node_idx),
 | 
			
		||||
                .for_simple => tree.forSimple(node_idx),
 | 
			
		||||
                else => unreachable,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            const while_node = whileAst(tree, node_idx).?;
 | 
			
		||||
            const is_for = node_tag == .@"for" or node_tag == .for_simple;
 | 
			
		||||
 | 
			
		||||
            if (while_node.label_token) |label| {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										309
									
								
								src/ast.zig
									
									
									
									
									
								
							
							
						
						
									
										309
									
								
								src/ast.zig
									
									
									
									
									
								
							@ -9,6 +9,109 @@ const Node = ast.Node;
 | 
			
		||||
const full = ast.full;
 | 
			
		||||
const assert = std.debug.assert;
 | 
			
		||||
 | 
			
		||||
fn fullPtrType(tree: Tree, info: full.PtrType.Ast) full.PtrType {
 | 
			
		||||
    const token_tags = tree.tokens.items(.tag);
 | 
			
		||||
    // TODO: looks like stage1 isn't quite smart enough to handle enum
 | 
			
		||||
    // literals in some places here
 | 
			
		||||
    const Size = std.builtin.TypeInfo.Pointer.Size;
 | 
			
		||||
    const size: Size = switch (token_tags[info.main_token]) {
 | 
			
		||||
        .asterisk,
 | 
			
		||||
        .asterisk_asterisk,
 | 
			
		||||
        => switch (token_tags[info.main_token + 1]) {
 | 
			
		||||
            .r_bracket, .colon => .Many,
 | 
			
		||||
            .identifier => if (token_tags[info.main_token - 1] == .l_bracket) Size.C else .One,
 | 
			
		||||
            else => .One,
 | 
			
		||||
        },
 | 
			
		||||
        .l_bracket => Size.Slice,
 | 
			
		||||
        else => unreachable,
 | 
			
		||||
    };
 | 
			
		||||
    var result: full.PtrType = .{
 | 
			
		||||
        .size = size,
 | 
			
		||||
        .allowzero_token = null,
 | 
			
		||||
        .const_token = null,
 | 
			
		||||
        .volatile_token = null,
 | 
			
		||||
        .ast = info,
 | 
			
		||||
    };
 | 
			
		||||
    // We need to be careful that we don't iterate over any sub-expressions
 | 
			
		||||
    // here while looking for modifiers as that could result in false
 | 
			
		||||
    // positives. Therefore, start after a sentinel if there is one and
 | 
			
		||||
    // skip over any align node and bit range nodes.
 | 
			
		||||
    var i = if (info.sentinel != 0) lastToken(tree, info.sentinel) + 1 else info.main_token;
 | 
			
		||||
    const end = tree.firstToken(info.child_type);
 | 
			
		||||
    while (i < end) : (i += 1) {
 | 
			
		||||
        switch (token_tags[i]) {
 | 
			
		||||
            .keyword_allowzero => result.allowzero_token = i,
 | 
			
		||||
            .keyword_const => result.const_token = i,
 | 
			
		||||
            .keyword_volatile => result.volatile_token = i,
 | 
			
		||||
            .keyword_align => {
 | 
			
		||||
                assert(info.align_node != 0);
 | 
			
		||||
                if (info.bit_range_end != 0) {
 | 
			
		||||
                    assert(info.bit_range_start != 0);
 | 
			
		||||
                    i = lastToken(tree, info.bit_range_end) + 1;
 | 
			
		||||
                } else {
 | 
			
		||||
                    i = lastToken(tree, info.align_node) + 1;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            else => {},
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ptrTypeSimple(tree: Tree, node: Node.Index) full.PtrType {
 | 
			
		||||
    assert(tree.nodes.items(.tag)[node] == .ptr_type);
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    const extra = tree.extraData(data.lhs, Node.PtrType);
 | 
			
		||||
    return fullPtrType(tree, .{
 | 
			
		||||
        .main_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .align_node = extra.align_node,
 | 
			
		||||
        .sentinel = extra.sentinel,
 | 
			
		||||
        .bit_range_start = 0,
 | 
			
		||||
        .bit_range_end = 0,
 | 
			
		||||
        .child_type = data.rhs,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ptrTypeSentinel(tree: Tree, node: Node.Index) full.PtrType {
 | 
			
		||||
    assert(tree.nodes.items(.tag)[node] == .ptr_type_sentinel);
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    return fullPtrType(tree, .{
 | 
			
		||||
        .main_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .align_node = 0,
 | 
			
		||||
        .sentinel = data.lhs,
 | 
			
		||||
        .bit_range_start = 0,
 | 
			
		||||
        .bit_range_end = 0,
 | 
			
		||||
        .child_type = data.rhs,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ptrTypeAligned(tree: Tree, node: Node.Index) full.PtrType {
 | 
			
		||||
    assert(tree.nodes.items(.tag)[node] == .ptr_type_aligned);
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    return fullPtrType(tree, .{
 | 
			
		||||
        .main_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .align_node = data.lhs,
 | 
			
		||||
        .sentinel = 0,
 | 
			
		||||
        .bit_range_start = 0,
 | 
			
		||||
        .bit_range_end = 0,
 | 
			
		||||
        .child_type = data.rhs,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) full.PtrType {
 | 
			
		||||
    assert(tree.nodes.items(.tag)[node] == .ptr_type_bit_range);
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange);
 | 
			
		||||
    return fullPtrType(tree, .{
 | 
			
		||||
        .main_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .align_node = extra.align_node,
 | 
			
		||||
        .sentinel = extra.sentinel,
 | 
			
		||||
        .bit_range_start = extra.bit_range_start,
 | 
			
		||||
        .bit_range_end = extra.bit_range_end,
 | 
			
		||||
        .child_type = data.rhs,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn fullIf(tree: Tree, info: full.If.Ast) full.If {
 | 
			
		||||
    const token_tags = tree.tokens.items(.tag);
 | 
			
		||||
    var result: full.If = .{
 | 
			
		||||
@ -46,6 +149,110 @@ pub fn ifFull(tree: Tree, node: Node.Index) full.If {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ifSimple(tree: Tree, node: Node.Index) full.If {
 | 
			
		||||
    assert(tree.nodes.items(.tag)[node] == .if_simple);
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    return fullIf(tree, .{
 | 
			
		||||
        .cond_expr = data.lhs,
 | 
			
		||||
        .then_expr = data.rhs,
 | 
			
		||||
        .else_expr = 0,
 | 
			
		||||
        .if_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn fullWhile(tree: Tree, info: full.While.Ast) full.While {
 | 
			
		||||
    const token_tags = tree.tokens.items(.tag);
 | 
			
		||||
    var result: full.While = .{
 | 
			
		||||
        .ast = info,
 | 
			
		||||
        .inline_token = null,
 | 
			
		||||
        .label_token = null,
 | 
			
		||||
        .payload_token = null,
 | 
			
		||||
        .else_token = undefined,
 | 
			
		||||
        .error_token = null,
 | 
			
		||||
    };
 | 
			
		||||
    var tok_i = info.while_token - 1;
 | 
			
		||||
    if (token_tags[tok_i] == .keyword_inline) {
 | 
			
		||||
        result.inline_token = tok_i;
 | 
			
		||||
        tok_i -= 1;
 | 
			
		||||
    }
 | 
			
		||||
    if (token_tags[tok_i] == .colon and
 | 
			
		||||
        token_tags[tok_i - 1] == .identifier)
 | 
			
		||||
    {
 | 
			
		||||
        result.label_token = tok_i - 1;
 | 
			
		||||
    }
 | 
			
		||||
    const last_cond_token = lastToken(tree, info.cond_expr);
 | 
			
		||||
    if (token_tags[last_cond_token + 2] == .pipe) {
 | 
			
		||||
        result.payload_token = last_cond_token + 3;
 | 
			
		||||
    }
 | 
			
		||||
    if (info.else_expr != 0) {
 | 
			
		||||
        // then_expr else |x|
 | 
			
		||||
        //           ^    ^
 | 
			
		||||
        result.else_token = lastToken(tree, info.then_expr) + 1;
 | 
			
		||||
        if (token_tags[result.else_token + 1] == .pipe) {
 | 
			
		||||
            result.error_token = result.else_token + 2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn whileSimple(tree: Tree, node: Node.Index) full.While {
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    return fullWhile(tree, .{
 | 
			
		||||
        .while_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .cond_expr = data.lhs,
 | 
			
		||||
        .cont_expr = 0,
 | 
			
		||||
        .then_expr = data.rhs,
 | 
			
		||||
        .else_expr = 0,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn whileCont(tree: Tree, node: Node.Index) full.While {
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    const extra = tree.extraData(data.rhs, Node.WhileCont);
 | 
			
		||||
    return fullWhile(tree, .{
 | 
			
		||||
        .while_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .cond_expr = data.lhs,
 | 
			
		||||
        .cont_expr = extra.cont_expr,
 | 
			
		||||
        .then_expr = extra.then_expr,
 | 
			
		||||
        .else_expr = 0,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn whileFull(tree: Tree, node: Node.Index) full.While {
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    const extra = tree.extraData(data.rhs, Node.While);
 | 
			
		||||
    return fullWhile(tree, .{
 | 
			
		||||
        .while_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .cond_expr = data.lhs,
 | 
			
		||||
        .cont_expr = extra.cont_expr,
 | 
			
		||||
        .then_expr = extra.then_expr,
 | 
			
		||||
        .else_expr = extra.else_expr,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn forSimple(tree: Tree, node: Node.Index) full.While {
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    return fullWhile(tree, .{
 | 
			
		||||
        .while_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .cond_expr = data.lhs,
 | 
			
		||||
        .cont_expr = 0,
 | 
			
		||||
        .then_expr = data.rhs,
 | 
			
		||||
        .else_expr = 0,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn forFull(tree: Tree, node: Node.Index) full.While {
 | 
			
		||||
    const data = tree.nodes.items(.data)[node];
 | 
			
		||||
    const extra = tree.extraData(data.rhs, Node.If);
 | 
			
		||||
    return fullWhile(tree, .{
 | 
			
		||||
        .while_token = tree.nodes.items(.main_token)[node],
 | 
			
		||||
        .cond_expr = data.lhs,
 | 
			
		||||
        .cont_expr = 0,
 | 
			
		||||
        .then_expr = extra.then_expr,
 | 
			
		||||
        .else_expr = extra.else_expr,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn lastToken(tree: ast.Tree, node: ast.Node.Index) ast.TokenIndex {
 | 
			
		||||
    const TokenIndex = ast.TokenIndex;
 | 
			
		||||
    const tags = tree.nodes.items(.tag);
 | 
			
		||||
@ -558,3 +765,105 @@ pub fn lastToken(tree: ast.Tree, node: ast.Node.Index) ast.TokenIndex {
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn containerField(tree: ast.Tree, node: ast.Node.Index) ?ast.full.ContainerField {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .container_field => tree.containerField(node),
 | 
			
		||||
        .container_field_init => tree.containerFieldInit(node),
 | 
			
		||||
        .container_field_align => tree.containerFieldAlign(node),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ptrType(tree: ast.Tree, node: ast.Node.Index) ?ast.full.PtrType {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .ptr_type => ptrTypeSimple(tree, node),
 | 
			
		||||
        .ptr_type_aligned => ptrTypeAligned(tree, node),
 | 
			
		||||
        .ptr_type_bit_range => ptrTypeBitRange(tree, node),
 | 
			
		||||
        .ptr_type_sentinel => ptrTypeSentinel(tree, node),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn whileAst(tree: ast.Tree, node: ast.Node.Index) ?ast.full.While {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .@"while" => whileFull(tree, node),
 | 
			
		||||
        .while_simple => whileSimple(tree, node),
 | 
			
		||||
        .while_cont => whileCont(tree, node),
 | 
			
		||||
        .@"for" => forFull(tree, node),
 | 
			
		||||
        .for_simple => forSimple(tree, node),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isContainer(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .container_decl,
 | 
			
		||||
        .container_decl_trailing,
 | 
			
		||||
        .container_decl_arg,
 | 
			
		||||
        .container_decl_arg_trailing,
 | 
			
		||||
        .container_decl_two,
 | 
			
		||||
        .container_decl_two_trailing,
 | 
			
		||||
        .tagged_union,
 | 
			
		||||
        .tagged_union_trailing,
 | 
			
		||||
        .tagged_union_two,
 | 
			
		||||
        .tagged_union_two_trailing,
 | 
			
		||||
        .tagged_union_enum_tag,
 | 
			
		||||
        .tagged_union_enum_tag_trailing,
 | 
			
		||||
        .root,
 | 
			
		||||
        .error_set_decl,
 | 
			
		||||
        => true,
 | 
			
		||||
        else => false,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns the member indices of a given declaration container.
 | 
			
		||||
/// Asserts given `tag` is a container node
 | 
			
		||||
pub fn declMembers(tree: ast.Tree, node_idx: ast.Node.Index, buffer: *[2]ast.Node.Index) []const ast.Node.Index {
 | 
			
		||||
    std.debug.assert(isContainer(tree, node_idx));
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node_idx]) {
 | 
			
		||||
        .container_decl, .container_decl_trailing => tree.containerDecl(node_idx).ast.members,
 | 
			
		||||
        .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx).ast.members,
 | 
			
		||||
        .container_decl_two, .container_decl_two_trailing => tree.containerDeclTwo(buffer, node_idx).ast.members,
 | 
			
		||||
        .tagged_union, .tagged_union_trailing => tree.taggedUnion(node_idx).ast.members,
 | 
			
		||||
        .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(node_idx).ast.members,
 | 
			
		||||
        .tagged_union_two, .tagged_union_two_trailing => tree.taggedUnionTwo(buffer, node_idx).ast.members,
 | 
			
		||||
        .root => tree.rootDecls(),
 | 
			
		||||
        .error_set_decl => &[_]ast.Node.Index{},
 | 
			
		||||
        else => unreachable,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns an `ast.full.VarDecl` for a given node index.
 | 
			
		||||
/// Returns null if the tag doesn't match
 | 
			
		||||
pub fn varDecl(tree: ast.Tree, node_idx: ast.Node.Index) ?ast.full.VarDecl {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node_idx]) {
 | 
			
		||||
        .global_var_decl => tree.globalVarDecl(node_idx),
 | 
			
		||||
        .local_var_decl => tree.localVarDecl(node_idx),
 | 
			
		||||
        .aligned_var_decl => tree.alignedVarDecl(node_idx),
 | 
			
		||||
        .simple_var_decl => tree.simpleVarDecl(node_idx),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isBuiltinCall(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .builtin_call,
 | 
			
		||||
        .builtin_call_comma,
 | 
			
		||||
        .builtin_call_two,
 | 
			
		||||
        .builtin_call_two_comma,
 | 
			
		||||
        => true,
 | 
			
		||||
        else => false,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn fnProto(tree: ast.Tree, node: ast.Node.Index, buf: *[1]ast.Node.Index) ?ast.full.FnProto {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .fn_proto => tree.fnProto(node),
 | 
			
		||||
        .fn_proto_multi => tree.fnProtoMulti(node),
 | 
			
		||||
        .fn_proto_one => tree.fnProtoOne(buf, node),
 | 
			
		||||
        .fn_proto_simple => tree.fnProtoSimple(buf, node),
 | 
			
		||||
        .fn_decl => fnProto(tree, tree.nodes.items(.data)[node].lhs, buf),
 | 
			
		||||
        else => null,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1106,7 +1106,13 @@ fn completeBuiltin(arena: *std.heap.ArenaAllocator, id: types.RequestId, config:
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn completeGlobal(arena: *std.heap.ArenaAllocator, id: types.RequestId, pos_index: usize, handle: *DocumentStore.Handle, config: Config) !void {
 | 
			
		||||
fn completeGlobal(
 | 
			
		||||
    arena: *std.heap.ArenaAllocator,
 | 
			
		||||
    id: types.RequestId,
 | 
			
		||||
    pos_index: usize,
 | 
			
		||||
    handle: *DocumentStore.Handle,
 | 
			
		||||
    config: Config,
 | 
			
		||||
) !void {
 | 
			
		||||
    var completions = std.ArrayList(types.CompletionItem).init(&arena.allocator);
 | 
			
		||||
 | 
			
		||||
    const context = DeclToCompletionContext{
 | 
			
		||||
 | 
			
		||||
@ -120,7 +120,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .error_set_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
            for (analysis.declMembers(tree, node, &buf)) |member|
 | 
			
		||||
            for (declMembers(tree, node, &buf)) |member|
 | 
			
		||||
                try symbolReferencesInternal(arena, store, .{ .node = member, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
        },
 | 
			
		||||
        .global_var_decl,
 | 
			
		||||
@ -128,7 +128,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .simple_var_decl,
 | 
			
		||||
        .aligned_var_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            const var_decl = analysis.varDecl(tree, node).?;
 | 
			
		||||
            const var_decl = varDecl(tree, node).?;
 | 
			
		||||
            if (var_decl.ast.type_node != 0) {
 | 
			
		||||
                try symbolReferencesInternal(arena, store, .{ .node = var_decl.ast.type_node, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
            }
 | 
			
		||||
@ -143,7 +143,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .container_field_align,
 | 
			
		||||
        .container_field_init,
 | 
			
		||||
        => {
 | 
			
		||||
            const field = analysis.containerField(tree, node).?;
 | 
			
		||||
            const field = containerField(tree, node).?;
 | 
			
		||||
            if (field.ast.type_expr != 0) {
 | 
			
		||||
                try symbolReferencesInternal(arena, store, .{ .node = field.ast.type_expr, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
            }
 | 
			
		||||
@ -165,7 +165,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const fn_proto = analysis.fnProto(tree, node, &buf).?;
 | 
			
		||||
            const fn_proto = fnProto(tree, node, &buf).?;
 | 
			
		||||
            var it = fn_proto.iterate(tree);
 | 
			
		||||
            while (it.next()) |param| {
 | 
			
		||||
                if (param.type_expr != 0)
 | 
			
		||||
@ -231,14 +231,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .for_simple,
 | 
			
		||||
        .@"for",
 | 
			
		||||
        => {
 | 
			
		||||
            const loop: ast.full.While = switch (node_tags[node]) {
 | 
			
		||||
                .@"while" => tree.whileFull(node),
 | 
			
		||||
                .while_simple => tree.whileSimple(node),
 | 
			
		||||
                .while_cont => tree.whileCont(node),
 | 
			
		||||
                .for_simple => tree.forSimple(node),
 | 
			
		||||
                .@"for" => tree.forFull(node),
 | 
			
		||||
                else => unreachable,
 | 
			
		||||
            };
 | 
			
		||||
            const loop = whileAst(tree, node).?;
 | 
			
		||||
            try symbolReferencesInternal(arena, store, .{ .node = loop.ast.cond_expr, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
            if (loop.ast.cont_expr != 0) {
 | 
			
		||||
                try symbolReferencesInternal(arena, store, .{ .node = loop.ast.cont_expr, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
@ -251,7 +244,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .@"if",
 | 
			
		||||
        .if_simple,
 | 
			
		||||
        => {
 | 
			
		||||
            const if_node: ast.full.If = if (node_tags[node] == .@"if") ifFull(tree, node) else tree.ifSimple(node);
 | 
			
		||||
            const if_node: ast.full.If = if (node_tags[node] == .@"if") ifFull(tree, node) else ifSimple(tree, node);
 | 
			
		||||
 | 
			
		||||
            try symbolReferencesInternal(arena, store, .{ .node = if_node.ast.cond_expr, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
            try symbolReferencesInternal(arena, store, .{ .node = if_node.ast.then_expr, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
@ -270,7 +263,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .ptr_type_bit_range,
 | 
			
		||||
        .ptr_type_sentinel,
 | 
			
		||||
        => {
 | 
			
		||||
            const ptr_type = analysis.ptrType(tree, node).?;
 | 
			
		||||
            const ptr_type = ptrType(tree, node).?;
 | 
			
		||||
 | 
			
		||||
            if (ptr_type.ast.align_node != 0) {
 | 
			
		||||
                try symbolReferencesInternal(arena, store, .{ .node = ptr_type.ast.align_node, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
@ -582,7 +575,7 @@ pub fn symbolReferences(
 | 
			
		||||
                switch (scope.data) {
 | 
			
		||||
                    .function => |proto| {
 | 
			
		||||
                        var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
                        const fn_proto = analysis.fnProto(curr_handle.tree, proto, &buf).?;
 | 
			
		||||
                        const fn_proto = fnProto(curr_handle.tree, proto, &buf).?;
 | 
			
		||||
                        var it = fn_proto.iterate(curr_handle.tree);
 | 
			
		||||
                        while (it.next()) |candidate| {
 | 
			
		||||
                            if (std.meta.eql(candidate, param)) {
 | 
			
		||||
 | 
			
		||||
@ -329,7 +329,7 @@ fn writeContainerField(
 | 
			
		||||
    field_token_type: ?TokenType,
 | 
			
		||||
    child_frame: anytype,
 | 
			
		||||
) !void {
 | 
			
		||||
    const container_field = analysis.containerField(builder.handle.tree, node).?;
 | 
			
		||||
    const container_field = containerField(builder.handle.tree, node).?;
 | 
			
		||||
    if (analysis.getDocCommentTokenIndex(builder.handle.tree, node)) |docs|
 | 
			
		||||
        try writeDocComments(builder, builder.handle.tree, docs);
 | 
			
		||||
 | 
			
		||||
@ -443,7 +443,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .simple_var_decl,
 | 
			
		||||
        .aligned_var_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            const var_decl = analysis.varDecl(tree, node).?;
 | 
			
		||||
            const var_decl = varDecl(tree, node).?;
 | 
			
		||||
            if (analysis.getDocCommentTokenIndex(tree, node)) |comment_idx|
 | 
			
		||||
                try writeDocComments(builder, handle.tree, comment_idx);
 | 
			
		||||
 | 
			
		||||
@ -558,7 +558,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const fn_proto: ast.full.FnProto = analysis.fnProto(tree, node, &buf).?;
 | 
			
		||||
            const fn_proto: ast.full.FnProto = fnProto(tree, node, &buf).?;
 | 
			
		||||
            if (analysis.getDocCommentTokenIndex(tree, node)) |docs|
 | 
			
		||||
                try writeDocComments(builder, handle.tree, docs);
 | 
			
		||||
 | 
			
		||||
@ -657,15 +657,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .for_simple,
 | 
			
		||||
        .@"for",
 | 
			
		||||
        => {
 | 
			
		||||
            const while_node: ast.full.While = switch (tag) {
 | 
			
		||||
                .@"while" => tree.whileFull(node),
 | 
			
		||||
                .while_simple => tree.whileSimple(node),
 | 
			
		||||
                .while_cont => tree.whileCont(node),
 | 
			
		||||
                .@"for" => tree.forFull(node),
 | 
			
		||||
                .for_simple => tree.forSimple(node),
 | 
			
		||||
                else => unreachable,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            const while_node = whileAst(tree, node).?;
 | 
			
		||||
            try writeToken(builder, while_node.label_token, .label);
 | 
			
		||||
            try writeToken(builder, while_node.inline_token, .keyword);
 | 
			
		||||
            try writeToken(builder, while_node.ast.while_token, .keyword);
 | 
			
		||||
@ -700,7 +692,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .@"if",
 | 
			
		||||
        .if_simple,
 | 
			
		||||
        => {
 | 
			
		||||
            const if_node: ast.full.If = if (tag == .@"if") ifFull(tree, node) else tree.ifSimple(node);
 | 
			
		||||
            const if_node: ast.full.If = if (tag == .@"if") ifFull(tree, node) else ifSimple(tree, node);
 | 
			
		||||
 | 
			
		||||
            try writeToken(builder, if_node.ast.if_token, .keyword);
 | 
			
		||||
            try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, if_node.ast.cond_expr });
 | 
			
		||||
@ -773,7 +765,7 @@ fn writeNodeTokens(
 | 
			
		||||
                    .node = struct_init.ast.type_expr,
 | 
			
		||||
                    .handle = handle,
 | 
			
		||||
                })) |struct_type| switch (struct_type.type.data) {
 | 
			
		||||
                    .other => |type_node| if (analysis.isContainer(struct_type.handle.tree, type_node))
 | 
			
		||||
                    .other => |type_node| if (isContainer(struct_type.handle.tree, type_node))
 | 
			
		||||
                        fieldTokenType(type_node, struct_type.handle)
 | 
			
		||||
                    else
 | 
			
		||||
                        null,
 | 
			
		||||
@ -1039,7 +1031,7 @@ fn writeNodeTokens(
 | 
			
		||||
                switch (decl_type.decl.*) {
 | 
			
		||||
                    .ast_node => |decl_node| {
 | 
			
		||||
                        if (decl_type.handle.tree.nodes.items(.tag)[decl_node].isContainerField()) {
 | 
			
		||||
                            const tok_type: ?TokenType = if (analysis.isContainer(lhs_type.handle.tree, left_type_node))
 | 
			
		||||
                            const tok_type: ?TokenType = if (isContainer(lhs_type.handle.tree, left_type_node))
 | 
			
		||||
                                fieldTokenType(decl_node, lhs_type.handle)
 | 
			
		||||
                            else if (left_type_node == 0)
 | 
			
		||||
                                TokenType.field
 | 
			
		||||
@ -1065,7 +1057,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .ptr_type_bit_range,
 | 
			
		||||
        .ptr_type_sentinel,
 | 
			
		||||
        => {
 | 
			
		||||
            const ptr_type = analysis.ptrType(tree, node).?;
 | 
			
		||||
            const ptr_type = ptrType(tree, node).?;
 | 
			
		||||
 | 
			
		||||
            if (ptr_type.size == .One and token_tags[main_token] == .asterisk_asterisk and
 | 
			
		||||
                main_token == main_tokens[ptr_type.ast.child_type])
 | 
			
		||||
@ -1150,7 +1142,7 @@ pub fn writeAllSemanticTokens(arena: *std.heap.ArenaAllocator, store: *DocumentS
 | 
			
		||||
    var gap_highlighter = GapHighlighter.init(&builder, 0);
 | 
			
		||||
 | 
			
		||||
    var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
    for (analysis.declMembers(handle.tree, 0, &buf)) |child| {
 | 
			
		||||
    for (declMembers(handle.tree, 0, &buf)) |child| {
 | 
			
		||||
        try gap_highlighter.next(child);
 | 
			
		||||
        try writeNodeTokens(&builder, arena, store, child);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user