usingnamespace semantics update
+ Ast changes adjustments
This commit is contained in:
		
							parent
							
								
									e472fca3be
								
							
						
					
					
						commit
						fed1c4c2c6
					
				
							
								
								
									
										171
									
								
								src/analysis.zig
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								src/analysis.zig
									
									
									
									
									
								
							@ -1,9 +1,10 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const DocumentStore = @import("document_store.zig");
 | 
			
		||||
const ast = std.zig.ast;
 | 
			
		||||
const ast = std.zig.Ast;
 | 
			
		||||
const types = @import("types.zig");
 | 
			
		||||
const offsets = @import("offsets.zig");
 | 
			
		||||
const log = std.log.scoped(.analysis);
 | 
			
		||||
const Analysis = @This();
 | 
			
		||||
usingnamespace @import("ast.zig");
 | 
			
		||||
 | 
			
		||||
var using_trail: std.ArrayList([*]const u8) = undefined;
 | 
			
		||||
@ -20,7 +21,7 @@ pub fn deinit() void {
 | 
			
		||||
/// Gets a declaration's doc comments. Caller owns returned memory.
 | 
			
		||||
pub fn getDocComments(
 | 
			
		||||
    allocator: *std.mem.Allocator,
 | 
			
		||||
    tree: ast.Tree,
 | 
			
		||||
    tree: Analysis.Tree,
 | 
			
		||||
    node: ast.Node.Index,
 | 
			
		||||
    format: types.MarkupContent.Kind,
 | 
			
		||||
) !?[]const u8 {
 | 
			
		||||
@ -73,7 +74,7 @@ pub fn getDocCommentTokenIndex(tokens: []std.zig.Token.Tag, base_token: ast.Toke
 | 
			
		||||
 | 
			
		||||
pub fn collectDocComments(
 | 
			
		||||
    allocator: *std.mem.Allocator,
 | 
			
		||||
    tree: ast.Tree,
 | 
			
		||||
    tree: Analysis.Tree,
 | 
			
		||||
    doc_comments: ast.TokenIndex,
 | 
			
		||||
    format: types.MarkupContent.Kind,
 | 
			
		||||
    container_doc: bool,
 | 
			
		||||
@ -94,11 +95,11 @@ pub fn collectDocComments(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Gets a function's keyword, name, arguments and return value.
 | 
			
		||||
pub fn getFunctionSignature(tree: ast.Tree, func: ast.full.FnProto) []const u8 {
 | 
			
		||||
pub fn getFunctionSignature(tree: Analysis.Tree, func: ast.full.FnProto) []const u8 {
 | 
			
		||||
    const start = offsets.tokenLocation(tree, func.ast.fn_token);
 | 
			
		||||
 | 
			
		||||
    const end = if (func.ast.return_type != 0)
 | 
			
		||||
        offsets.tokenLocation(tree, lastToken(tree, func.ast.return_type))
 | 
			
		||||
        offsets.tokenLocation(tree, Analysis.lastToken(tree, func.ast.return_type))
 | 
			
		||||
    else
 | 
			
		||||
        start;
 | 
			
		||||
    return tree.source[start.start..end.end];
 | 
			
		||||
@ -107,7 +108,7 @@ pub fn getFunctionSignature(tree: ast.Tree, func: ast.full.FnProto) []const u8 {
 | 
			
		||||
/// Creates snippet insert text for a function. Caller owns returned memory.
 | 
			
		||||
pub fn getFunctionSnippet(
 | 
			
		||||
    allocator: *std.mem.Allocator,
 | 
			
		||||
    tree: ast.Tree,
 | 
			
		||||
    tree: Analysis.Tree,
 | 
			
		||||
    func: ast.full.FnProto,
 | 
			
		||||
    skip_self_param: bool,
 | 
			
		||||
) ![]const u8 {
 | 
			
		||||
@ -153,7 +154,7 @@ pub fn getFunctionSnippet(
 | 
			
		||||
                try buffer.appendSlice("...");
 | 
			
		||||
        } else if (param.type_expr != 0) {
 | 
			
		||||
            var curr_token = tree.firstToken(param.type_expr);
 | 
			
		||||
            var end_token = lastToken(tree, param.type_expr);
 | 
			
		||||
            var end_token = Analysis.lastToken(tree, param.type_expr);
 | 
			
		||||
            while (curr_token <= end_token) : (curr_token += 1) {
 | 
			
		||||
                const tag = token_tags[curr_token];
 | 
			
		||||
                const is_comma = tag == .comma;
 | 
			
		||||
@ -210,32 +211,32 @@ pub fn hasSelfParam(
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn getVariableSignature(tree: ast.Tree, var_decl: ast.full.VarDecl) []const u8 {
 | 
			
		||||
pub fn getVariableSignature(tree: Analysis.Tree, var_decl: ast.full.VarDecl) []const u8 {
 | 
			
		||||
    const start = offsets.tokenLocation(tree, var_decl.ast.mut_token).start;
 | 
			
		||||
    const end = offsets.tokenLocation(tree, lastToken(tree, var_decl.ast.init_node)).end;
 | 
			
		||||
    const end = offsets.tokenLocation(tree, Analysis.lastToken(tree, var_decl.ast.init_node)).end;
 | 
			
		||||
    return tree.source[start..end];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn getContainerFieldSignature(tree: ast.Tree, field: ast.full.ContainerField) []const u8 {
 | 
			
		||||
pub fn getContainerFieldSignature(tree: Analysis.Tree, field: ast.full.ContainerField) []const u8 {
 | 
			
		||||
    const start = offsets.tokenLocation(tree, field.ast.name_token).start;
 | 
			
		||||
    const end_node = if (field.ast.value_expr != 0) field.ast.value_expr else field.ast.type_expr;
 | 
			
		||||
    const end = offsets.tokenLocation(tree, lastToken(tree, end_node)).end;
 | 
			
		||||
    const end = offsets.tokenLocation(tree, Analysis.lastToken(tree, end_node)).end;
 | 
			
		||||
    return tree.source[start..end];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The node is the meta-type `type`
 | 
			
		||||
fn isMetaType(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
fn isMetaType(tree: Analysis.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    if (tree.nodes.items(.tag)[node] == .identifier) {
 | 
			
		||||
        return std.mem.eql(u8, tree.tokenSlice(tree.nodes.items(.main_token)[node]), "type");
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isTypeFunction(tree: ast.Tree, func: ast.full.FnProto) bool {
 | 
			
		||||
pub fn isTypeFunction(tree: Analysis.Tree, func: ast.full.FnProto) bool {
 | 
			
		||||
    return isMetaType(tree, func.ast.return_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isGenericFunction(tree: ast.Tree, func: ast.full.FnProto) bool {
 | 
			
		||||
pub fn isGenericFunction(tree: Analysis.Tree, func: ast.full.FnProto) bool {
 | 
			
		||||
    var it = func.iterate(tree);
 | 
			
		||||
    while (it.next()) |param| {
 | 
			
		||||
        if (param.anytype_ellipsis3 != null or param.comptime_noalias != null) {
 | 
			
		||||
@ -261,7 +262,7 @@ pub fn isSnakeCase(name: []const u8) bool {
 | 
			
		||||
 | 
			
		||||
// ANALYSIS ENGINE
 | 
			
		||||
 | 
			
		||||
pub fn getDeclNameToken(tree: ast.Tree, node: ast.Node.Index) ?ast.TokenIndex {
 | 
			
		||||
pub fn getDeclNameToken(tree: Analysis.Tree, node: ast.Node.Index) ?ast.TokenIndex {
 | 
			
		||||
    const tags = tree.nodes.items(.tag);
 | 
			
		||||
    const main_token = tree.nodes.items(.main_token)[node];
 | 
			
		||||
    return switch (tags[node]) {
 | 
			
		||||
@ -278,7 +279,7 @@ pub fn getDeclNameToken(tree: ast.Tree, node: ast.Node.Index) ?ast.TokenIndex {
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => blk: {
 | 
			
		||||
            var params: [1]ast.Node.Index = undefined;
 | 
			
		||||
            break :blk fnProto(tree, node, ¶ms).?.name_token;
 | 
			
		||||
            break :blk Analysis.fnProto(tree, node, ¶ms).?.name_token;
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        // containers
 | 
			
		||||
@ -298,7 +299,7 @@ pub fn getDeclNameToken(tree: ast.Tree, node: ast.Node.Index) ?ast.TokenIndex {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn getDeclName(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
 | 
			
		||||
fn getDeclName(tree: Analysis.Tree, node: ast.Node.Index) ?[]const u8 {
 | 
			
		||||
    const name = tree.tokenSlice(getDeclNameToken(tree, node) orelse return null);
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .test_decl => name[1 .. name.len - 1],
 | 
			
		||||
@ -308,7 +309,7 @@ fn getDeclName(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
 | 
			
		||||
 | 
			
		||||
fn isContainerDecl(decl_handle: DeclWithHandle) bool {
 | 
			
		||||
    return switch (decl_handle.decl.*) {
 | 
			
		||||
        .ast_node => |inner_node| isContainer(decl_handle.handle.tree.nodes.items(.tag)[inner_node]),
 | 
			
		||||
        .ast_node => |inner_node| Analysis.isContainer(decl_handle.handle.tree.nodes.items(.tag)[inner_node]),
 | 
			
		||||
        else => false,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@ -340,7 +341,7 @@ fn resolveVarDeclAliasInternal(
 | 
			
		||||
    if (node_tags[node_handle.node] == .field_access) {
 | 
			
		||||
        const lhs = datas[node_handle.node].lhs;
 | 
			
		||||
 | 
			
		||||
        const container_node = if (isBuiltinCall(tree, lhs)) block: {
 | 
			
		||||
        const container_node = if (Analysis.isBuiltinCall(tree, lhs)) block: {
 | 
			
		||||
            if (!std.mem.eql(u8, tree.tokenSlice(main_tokens[lhs]), "@import"))
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
@ -355,7 +356,7 @@ fn resolveVarDeclAliasInternal(
 | 
			
		||||
                .other => |n| n,
 | 
			
		||||
                else => return null,
 | 
			
		||||
            };
 | 
			
		||||
            if (!isContainer(resolved.handle.tree, resolved_node)) return null;
 | 
			
		||||
            if (!Analysis.isContainer(resolved.handle.tree, resolved_node)) return null;
 | 
			
		||||
            break :block NodeWithHandle{ .node = resolved_node, .handle = resolved.handle };
 | 
			
		||||
        } else return null;
 | 
			
		||||
 | 
			
		||||
@ -377,7 +378,7 @@ pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocato
 | 
			
		||||
    const token_tags = tree.tokens.items(.tag);
 | 
			
		||||
    const node_tags = tree.nodes.items(.tag);
 | 
			
		||||
 | 
			
		||||
    if (varDecl(handle.tree, decl)) |var_decl| {
 | 
			
		||||
    if (Analysis.varDecl(handle.tree, decl)) |var_decl| {
 | 
			
		||||
        if (var_decl.ast.init_node == 0) return null;
 | 
			
		||||
        const base_exp = var_decl.ast.init_node;
 | 
			
		||||
        if (token_tags[var_decl.ast.mut_token] != .keyword_const) return null;
 | 
			
		||||
@ -394,7 +395,7 @@ pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocato
 | 
			
		||||
    return null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn isBlock(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
fn isBlock(tree: Analysis.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .block,
 | 
			
		||||
        .block_semicolon,
 | 
			
		||||
@ -406,7 +407,7 @@ fn isBlock(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn findReturnStatementInternal(
 | 
			
		||||
    tree: ast.Tree,
 | 
			
		||||
    tree: Analysis.Tree,
 | 
			
		||||
    fn_decl: ast.full.FnProto,
 | 
			
		||||
    body: ast.Node.Index,
 | 
			
		||||
    already_found: *bool,
 | 
			
		||||
@ -437,7 +438,7 @@ fn findReturnStatementInternal(
 | 
			
		||||
        if (node_tags[child_idx] == .@"return") {
 | 
			
		||||
            if (datas[child_idx].lhs != 0) {
 | 
			
		||||
                const lhs = datas[child_idx].lhs;
 | 
			
		||||
                if (isCall(tree, lhs)) {
 | 
			
		||||
                if (Analysis.isCall(tree, lhs)) {
 | 
			
		||||
                    const call_name = getDeclName(tree, datas[lhs].lhs);
 | 
			
		||||
                    if (call_name) |name| {
 | 
			
		||||
                        if (std.mem.eql(u8, name, tree.tokenSlice(fn_decl.name_token.?))) {
 | 
			
		||||
@ -459,7 +460,7 @@ fn findReturnStatementInternal(
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn findReturnStatement(tree: ast.Tree, fn_decl: ast.full.FnProto, body: ast.Node.Index) ?ast.Node.Index {
 | 
			
		||||
fn findReturnStatement(tree: Analysis.Tree, fn_decl: ast.full.FnProto, body: ast.Node.Index) ?ast.Node.Index {
 | 
			
		||||
    var already_found = false;
 | 
			
		||||
    return findReturnStatementInternal(tree, fn_decl, body, &already_found);
 | 
			
		||||
}
 | 
			
		||||
@ -554,7 +555,7 @@ fn resolveUnwrapErrorType(
 | 
			
		||||
    return null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isPtrType(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
pub fn isPtrType(tree: Analysis.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .ptr_type,
 | 
			
		||||
        .ptr_type_aligned,
 | 
			
		||||
@ -588,7 +589,7 @@ fn resolveDerefType(
 | 
			
		||||
    const token_tag = tree.tokens.items(.tag)[main_token];
 | 
			
		||||
 | 
			
		||||
    if (isPtrType(tree, deref_node)) {
 | 
			
		||||
        const ptr_type = ptrType(tree, deref_node).?;
 | 
			
		||||
        const ptr_type = Analysis.ptrType(tree, deref_node).?;
 | 
			
		||||
        switch (token_tag) {
 | 
			
		||||
            .asterisk => {
 | 
			
		||||
                return ((try resolveTypeOfNodeInternal(store, arena, .{
 | 
			
		||||
@ -631,7 +632,7 @@ fn resolveBracketAccessType(
 | 
			
		||||
            .type = .{ .data = .{ .slice = data.rhs }, .is_type_val = false },
 | 
			
		||||
            .handle = lhs.handle,
 | 
			
		||||
        };
 | 
			
		||||
    } else if (ptrType(tree, lhs_node)) |ptr_type| {
 | 
			
		||||
    } else if (Analysis.ptrType(tree, lhs_node)) |ptr_type| {
 | 
			
		||||
        if (ptr_type.size == .Slice) {
 | 
			
		||||
            if (rhs == .Single) {
 | 
			
		||||
                return ((try resolveTypeOfNodeInternal(store, arena, .{
 | 
			
		||||
@ -665,7 +666,7 @@ fn allDigits(str: []const u8) bool {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isTypeIdent(tree: ast.Tree, token_idx: ast.TokenIndex) bool {
 | 
			
		||||
pub fn isTypeIdent(tree: Analysis.Tree, token_idx: ast.TokenIndex) bool {
 | 
			
		||||
    const PrimitiveTypes = std.ComptimeStringMap(void, .{
 | 
			
		||||
        .{"isize"},          .{"usize"},
 | 
			
		||||
        .{"c_short"},        .{"c_ushort"},
 | 
			
		||||
@ -721,7 +722,7 @@ pub fn resolveTypeOfNodeInternal(
 | 
			
		||||
        .simple_var_decl,
 | 
			
		||||
        .aligned_var_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            const var_decl = varDecl(tree, node).?;
 | 
			
		||||
            const var_decl = Analysis.varDecl(tree, node).?;
 | 
			
		||||
            if (var_decl.ast.type_node != 0) {
 | 
			
		||||
                const decl_type = .{ .node = var_decl.ast.type_node, .handle = handle };
 | 
			
		||||
                if (try resolveTypeOfNodeInternal(store, arena, decl_type, bound_type_params)) |typ|
 | 
			
		||||
@ -751,7 +752,7 @@ pub fn resolveTypeOfNodeInternal(
 | 
			
		||||
                switch (child.decl.*) {
 | 
			
		||||
                    .ast_node => |n| {
 | 
			
		||||
                        if (n == node) return null;
 | 
			
		||||
                        if (varDecl(child.handle.tree, n)) |var_decl| {
 | 
			
		||||
                        if (Analysis.varDecl(child.handle.tree, n)) |var_decl| {
 | 
			
		||||
                            if (var_decl.ast.init_node == node)
 | 
			
		||||
                                return null;
 | 
			
		||||
                        }
 | 
			
		||||
@ -772,7 +773,7 @@ pub fn resolveTypeOfNodeInternal(
 | 
			
		||||
        .async_call_one_comma,
 | 
			
		||||
        => {
 | 
			
		||||
            var params: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const call = callFull(tree, node, ¶ms) orelse unreachable;
 | 
			
		||||
            const call = Analysis.callFull(tree, node, ¶ms) orelse unreachable;
 | 
			
		||||
 | 
			
		||||
            const callee = .{ .node = call.ast.fn_expr, .handle = handle };
 | 
			
		||||
            const decl = (try resolveTypeOfNodeInternal(store, arena, callee, bound_type_params)) orelse
 | 
			
		||||
@ -784,7 +785,7 @@ pub fn resolveTypeOfNodeInternal(
 | 
			
		||||
                else => return null,
 | 
			
		||||
            };
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const func_maybe = fnProto(decl.handle.tree, decl_node, &buf);
 | 
			
		||||
            const func_maybe = Analysis.fnProto(decl.handle.tree, decl_node, &buf);
 | 
			
		||||
 | 
			
		||||
            if (func_maybe) |fn_decl| {
 | 
			
		||||
                var expected_params = fn_decl.ast.params.len;
 | 
			
		||||
@ -1015,7 +1016,7 @@ pub fn resolveTypeOfNodeInternal(
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            // This is a function type
 | 
			
		||||
            if (fnProto(tree, node, &buf).?.name_token == null) {
 | 
			
		||||
            if (Analysis.fnProto(tree, node, &buf).?.name_token == null) {
 | 
			
		||||
                return TypeWithHandle.typeVal(node_handle);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -1098,9 +1099,9 @@ pub const TypeWithHandle = struct {
 | 
			
		||||
        const tree = self.handle.tree;
 | 
			
		||||
        const node = self.type.data.other;
 | 
			
		||||
        const tags = tree.nodes.items(.tag);
 | 
			
		||||
        if (isContainer(tree, node)) {
 | 
			
		||||
        if (Analysis.isContainer(tree, node)) {
 | 
			
		||||
            var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
            for (declMembers(tree, node, &buf)) |child| {
 | 
			
		||||
            for (Analysis.declMembers(tree, node, &buf)) |child| {
 | 
			
		||||
                if (tags[child].isContainerField()) return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -1123,7 +1124,7 @@ pub const TypeWithHandle = struct {
 | 
			
		||||
        var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
        const tree = self.handle.tree;
 | 
			
		||||
        return switch (self.type.data) {
 | 
			
		||||
            .other => |n| if (fnProto(tree, n, &buf)) |fn_proto| blk: {
 | 
			
		||||
            .other => |n| if (Analysis.fnProto(tree, n, &buf)) |fn_proto| blk: {
 | 
			
		||||
                break :blk isTypeFunction(tree, fn_proto);
 | 
			
		||||
            } else false,
 | 
			
		||||
            else => false,
 | 
			
		||||
@ -1134,7 +1135,7 @@ pub const TypeWithHandle = struct {
 | 
			
		||||
        var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
        const tree = self.handle.tree;
 | 
			
		||||
        return switch (self.type.data) {
 | 
			
		||||
            .other => |n| if (fnProto(tree, n, &buf)) |fn_proto| blk: {
 | 
			
		||||
            .other => |n| if (Analysis.fnProto(tree, n, &buf)) |fn_proto| blk: {
 | 
			
		||||
                break :blk isGenericFunction(tree, fn_proto);
 | 
			
		||||
            } else false,
 | 
			
		||||
            else => false,
 | 
			
		||||
@ -1165,7 +1166,7 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Collects all imports we can find into a slice of import paths (without quotes).
 | 
			
		||||
pub fn collectImports(import_arr: *std.ArrayList([]const u8), tree: ast.Tree) !void {
 | 
			
		||||
pub fn collectImports(import_arr: *std.ArrayList([]const u8), tree: Analysis.Tree) !void {
 | 
			
		||||
    const tags = tree.tokens.items(.tag);
 | 
			
		||||
 | 
			
		||||
    var i: usize = 0;
 | 
			
		||||
@ -1303,7 +1304,7 @@ pub fn getFieldAccessType(
 | 
			
		||||
                if (current_type.type.is_type_val) return null;
 | 
			
		||||
                const cur_tree = current_type.handle.tree;
 | 
			
		||||
                var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
                if (fnProto(cur_tree, current_type_node, &buf)) |func| {
 | 
			
		||||
                if (Analysis.fnProto(cur_tree, current_type_node, &buf)) |func| {
 | 
			
		||||
                    // Check if the function has a body and if so, pass it
 | 
			
		||||
                    // so the type can be resolved if it's a generic function returning
 | 
			
		||||
                    // an anonymous struct
 | 
			
		||||
@ -1357,25 +1358,25 @@ pub fn getFieldAccessType(
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isNodePublic(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
pub fn isNodePublic(tree: Analysis.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .global_var_decl,
 | 
			
		||||
        .local_var_decl,
 | 
			
		||||
        .simple_var_decl,
 | 
			
		||||
        .aligned_var_decl,
 | 
			
		||||
        => varDecl(tree, node).?.visib_token != null,
 | 
			
		||||
        => Analysis.varDecl(tree, node).?.visib_token != null,
 | 
			
		||||
        .fn_proto,
 | 
			
		||||
        .fn_proto_multi,
 | 
			
		||||
        .fn_proto_one,
 | 
			
		||||
        .fn_proto_simple,
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => fnProto(tree, node, &buf).?.visib_token != null,
 | 
			
		||||
        => Analysis.fnProto(tree, node, &buf).?.visib_token != null,
 | 
			
		||||
        else => true,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn nodeToString(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
 | 
			
		||||
pub fn nodeToString(tree: Analysis.Tree, node: ast.Node.Index) ?[]const u8 {
 | 
			
		||||
    const data = tree.nodes.items(.data);
 | 
			
		||||
    const main_token = tree.nodes.items(.main_token)[node];
 | 
			
		||||
    var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
@ -1390,7 +1391,7 @@ pub fn nodeToString(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
 | 
			
		||||
        .fn_proto_one,
 | 
			
		||||
        .fn_proto_simple,
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => if (fnProto(tree, node, &buf).?.name_token) |name|
 | 
			
		||||
        => if (Analysis.fnProto(tree, node, &buf).?.name_token) |name|
 | 
			
		||||
            return tree.tokenSlice(name),
 | 
			
		||||
        .field_access => return tree.tokenSlice(data[node].rhs),
 | 
			
		||||
        .call,
 | 
			
		||||
@ -1411,24 +1412,24 @@ pub fn nodeToString(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
 | 
			
		||||
    return null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn nodeContainsSourceIndex(tree: ast.Tree, node: ast.Node.Index, source_index: usize) bool {
 | 
			
		||||
fn nodeContainsSourceIndex(tree: Analysis.Tree, node: ast.Node.Index, source_index: usize) bool {
 | 
			
		||||
    const first_token = offsets.tokenLocation(tree, tree.firstToken(node)).start;
 | 
			
		||||
    const last_token = offsets.tokenLocation(tree, lastToken(tree, node)).end;
 | 
			
		||||
    const last_token = offsets.tokenLocation(tree, Analysis.lastToken(tree, node)).end;
 | 
			
		||||
    return source_index >= first_token and source_index <= last_token;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn getImportStr(tree: ast.Tree, node: ast.Node.Index, source_index: usize) ?[]const u8 {
 | 
			
		||||
pub fn getImportStr(tree: Analysis.Tree, node: ast.Node.Index, source_index: usize) ?[]const u8 {
 | 
			
		||||
    const node_tags = tree.nodes.items(.tag);
 | 
			
		||||
    var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
    if (isContainer(tree, node)) {
 | 
			
		||||
        const decls = declMembers(tree, node, &buf);
 | 
			
		||||
    if (Analysis.isContainer(tree, node)) {
 | 
			
		||||
        const decls = Analysis.declMembers(tree, node, &buf);
 | 
			
		||||
        for (decls) |decl_idx| {
 | 
			
		||||
            if (getImportStr(tree, decl_idx, source_index)) |name| {
 | 
			
		||||
                return name;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    } else if (varDecl(tree, node)) |var_decl| {
 | 
			
		||||
    } else if (Analysis.varDecl(tree, node)) |var_decl| {
 | 
			
		||||
        return getImportStr(tree, var_decl.ast.init_node, source_index);
 | 
			
		||||
    } else if (node_tags[node] == .@"usingnamespace") {
 | 
			
		||||
        return getImportStr(tree, tree.nodes.items(.data)[node].lhs, source_index);
 | 
			
		||||
@ -1438,7 +1439,7 @@ pub fn getImportStr(tree: ast.Tree, node: ast.Node.Index, source_index: usize) ?
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isBuiltinCall(tree, node)) {
 | 
			
		||||
    if (Analysis.isBuiltinCall(tree, node)) {
 | 
			
		||||
        const builtin_token = tree.nodes.items(.main_token)[node];
 | 
			
		||||
        const call_name = tree.tokenSlice(builtin_token);
 | 
			
		||||
 | 
			
		||||
@ -1656,7 +1657,7 @@ pub fn documentPositionContext(
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn addOutlineNodes(allocator: *std.mem.Allocator, tree: ast.Tree, child: ast.Node.Index, context: *GetDocumentSymbolsContext) anyerror!void {
 | 
			
		||||
fn addOutlineNodes(allocator: *std.mem.Allocator, tree: Analysis.Tree, child: ast.Node.Index, context: *GetDocumentSymbolsContext) anyerror!void {
 | 
			
		||||
    switch (tree.nodes.items(.tag)[child]) {
 | 
			
		||||
        .string_literal,
 | 
			
		||||
        .integer_literal,
 | 
			
		||||
@ -1788,7 +1789,7 @@ fn addOutlineNodes(allocator: *std.mem.Allocator, tree: ast.Tree, child: ast.Nod
 | 
			
		||||
        .tagged_union_two_trailing,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
            for (declMembers(tree, child, &buf)) |member|
 | 
			
		||||
            for (Analysis.declMembers(tree, child, &buf)) |member|
 | 
			
		||||
                try addOutlineNodes(allocator, tree, member, context);
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
@ -1809,7 +1810,7 @@ const GetDocumentSymbolsContext = struct {
 | 
			
		||||
 | 
			
		||||
fn getDocumentSymbolsInternal(
 | 
			
		||||
    allocator: *std.mem.Allocator,
 | 
			
		||||
    tree: ast.Tree,
 | 
			
		||||
    tree: Analysis.Tree,
 | 
			
		||||
    node: ast.Node.Index,
 | 
			
		||||
    context: *GetDocumentSymbolsContext,
 | 
			
		||||
) anyerror!void {
 | 
			
		||||
@ -1827,7 +1828,7 @@ fn getDocumentSymbolsInternal(
 | 
			
		||||
    const end_loc = start_loc.add(try offsets.tokenRelativeLocation(
 | 
			
		||||
        tree,
 | 
			
		||||
        start_loc.offset,
 | 
			
		||||
        starts[lastToken(tree, node)],
 | 
			
		||||
        starts[Analysis.lastToken(tree, node)],
 | 
			
		||||
        context.encoding,
 | 
			
		||||
    ));
 | 
			
		||||
    context.prev_loc = end_loc;
 | 
			
		||||
@ -1881,13 +1882,13 @@ fn getDocumentSymbolsInternal(
 | 
			
		||||
                .encoding = context.encoding,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if (isContainer(tree, node)) {
 | 
			
		||||
            if (Analysis.isContainer(tree, node)) {
 | 
			
		||||
                var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
                for (declMembers(tree, node, &buf)) |child|
 | 
			
		||||
                for (Analysis.declMembers(tree, node, &buf)) |child|
 | 
			
		||||
                    try addOutlineNodes(allocator, tree, child, &child_context);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (varDecl(tree, node)) |var_decl| {
 | 
			
		||||
            if (Analysis.varDecl(tree, node)) |var_decl| {
 | 
			
		||||
                if (var_decl.ast.init_node != 0)
 | 
			
		||||
                    try addOutlineNodes(allocator, tree, var_decl.ast.init_node, &child_context);
 | 
			
		||||
            }
 | 
			
		||||
@ -1896,7 +1897,7 @@ fn getDocumentSymbolsInternal(
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: ast.Tree, encoding: offsets.Encoding) ![]types.DocumentSymbol {
 | 
			
		||||
pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: Analysis.Tree, encoding: offsets.Encoding) ![]types.DocumentSymbol {
 | 
			
		||||
    var symbols = try std.ArrayList(types.DocumentSymbol).initCapacity(allocator, tree.rootDecls().len);
 | 
			
		||||
 | 
			
		||||
    var context = GetDocumentSymbolsContext{
 | 
			
		||||
@ -2032,7 +2033,7 @@ pub const DeclWithHandle = struct {
 | 
			
		||||
                    if (scope.decls.getEntry(tree.tokenSlice(main_tokens[pay.items[0]]))) |candidate| {
 | 
			
		||||
                        switch (candidate.value_ptr.*) {
 | 
			
		||||
                            .ast_node => |node| {
 | 
			
		||||
                                if (containerField(switch_expr_type.handle.tree, node)) |container_field| {
 | 
			
		||||
                                if (Analysis.containerField(switch_expr_type.handle.tree, node)) |container_field| {
 | 
			
		||||
                                    if (container_field.ast.type_expr != 0) {
 | 
			
		||||
                                        return ((try resolveTypeOfNodeInternal(
 | 
			
		||||
                                            store,
 | 
			
		||||
@ -2058,7 +2059,7 @@ fn findContainerScope(container_handle: NodeWithHandle) ?*Scope {
 | 
			
		||||
    const container = container_handle.node;
 | 
			
		||||
    const handle = container_handle.handle;
 | 
			
		||||
 | 
			
		||||
    if (!isContainer(handle.tree, container)) return null;
 | 
			
		||||
    if (!Analysis.isContainer(handle.tree, container)) return null;
 | 
			
		||||
 | 
			
		||||
    // Find the container scope.
 | 
			
		||||
    return for (handle.document_scope.scopes) |*scope| {
 | 
			
		||||
@ -2460,7 +2461,7 @@ pub const DocumentScope = struct {
 | 
			
		||||
            while (decl_it.next()) |_| : (idx += 1) {
 | 
			
		||||
                if (idx != 0) log.debug(", ", .{});
 | 
			
		||||
            }
 | 
			
		||||
            log.debug("{s}", .{name_decl.key});
 | 
			
		||||
            // log.debug("{s}", .{name_decl.key});
 | 
			
		||||
            log.debug("\n--------------------------\n", .{});
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -2506,7 +2507,7 @@ pub const Scope = struct {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub fn makeDocumentScope(allocator: *std.mem.Allocator, tree: ast.Tree) !DocumentScope {
 | 
			
		||||
pub fn makeDocumentScope(allocator: *std.mem.Allocator, tree: Analysis.Tree) !DocumentScope {
 | 
			
		||||
    var scopes = std.ArrayListUnmanaged(Scope){};
 | 
			
		||||
    var error_completions = CompletionSet{};
 | 
			
		||||
    var enum_completions = CompletionSet{};
 | 
			
		||||
@ -2537,9 +2538,9 @@ pub fn makeDocumentScope(allocator: *std.mem.Allocator, tree: ast.Tree) !Documen
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn nodeSourceRange(tree: ast.Tree, node: ast.Node.Index) SourceRange {
 | 
			
		||||
fn nodeSourceRange(tree: Analysis.Tree, node: ast.Node.Index) SourceRange {
 | 
			
		||||
    const loc_start = offsets.tokenLocation(tree, tree.firstToken(node));
 | 
			
		||||
    const loc_end = offsets.tokenLocation(tree, lastToken(tree, node));
 | 
			
		||||
    const loc_end = offsets.tokenLocation(tree, Analysis.lastToken(tree, node));
 | 
			
		||||
 | 
			
		||||
    return SourceRange{
 | 
			
		||||
        .start = loc_start.start,
 | 
			
		||||
@ -2551,7 +2552,7 @@ const ScopeContext = struct {
 | 
			
		||||
    scopes: *std.ArrayListUnmanaged(Scope),
 | 
			
		||||
    enums: *CompletionSet,
 | 
			
		||||
    errors: *CompletionSet,
 | 
			
		||||
    tree: ast.Tree,
 | 
			
		||||
    tree: Analysis.Tree,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
fn makeInnerScope(
 | 
			
		||||
@ -2568,7 +2569,7 @@ fn makeInnerScope(
 | 
			
		||||
    const node_tag = tags[node_idx];
 | 
			
		||||
 | 
			
		||||
    var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
    const ast_decls = declMembers(tree, node_idx, &buf);
 | 
			
		||||
    const ast_decls = Analysis.declMembers(tree, node_idx, &buf);
 | 
			
		||||
 | 
			
		||||
    (try scopes.addOne(allocator)).* = .{
 | 
			
		||||
        .range = nodeSourceRange(tree, node_idx),
 | 
			
		||||
@ -2723,7 +2724,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => |fn_tag| {
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const func = fnProto(tree, node_idx, &buf).?;
 | 
			
		||||
            const func = Analysis.fnProto(tree, node_idx, &buf).?;
 | 
			
		||||
 | 
			
		||||
            (try scopes.addOne(allocator)).* = .{
 | 
			
		||||
                .range = nodeSourceRange(tree, node_idx),
 | 
			
		||||
@ -2770,7 +2771,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .block_two_semicolon,
 | 
			
		||||
        => {
 | 
			
		||||
            const first_token = tree.firstToken(node_idx);
 | 
			
		||||
            const last_token = lastToken(tree, node_idx);
 | 
			
		||||
            const last_token = Analysis.lastToken(tree, node_idx);
 | 
			
		||||
 | 
			
		||||
            // if labeled block
 | 
			
		||||
            if (token_tags[first_token] == .identifier) {
 | 
			
		||||
@ -2823,7 +2824,7 @@ fn makeScopeInternal(
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                try makeScopeInternal(allocator, context, idx);
 | 
			
		||||
                if (varDecl(tree, idx)) |var_decl| {
 | 
			
		||||
                if (Analysis.varDecl(tree, idx)) |var_decl| {
 | 
			
		||||
                    const name = tree.tokenSlice(var_decl.ast.mut_token + 1);
 | 
			
		||||
                    if (try scopes.items[scope_idx].decls.fetchPut(name, .{ .ast_node = idx })) |existing| {
 | 
			
		||||
                        _ = existing;
 | 
			
		||||
@ -2838,14 +2839,14 @@ fn makeScopeInternal(
 | 
			
		||||
        .@"if",
 | 
			
		||||
        .if_simple,
 | 
			
		||||
        => {
 | 
			
		||||
            const if_node = ifFull(tree, node_idx);
 | 
			
		||||
            const if_node = Analysis.ifFull(tree, node_idx);
 | 
			
		||||
 | 
			
		||||
            if (if_node.payload_token) |payload| {
 | 
			
		||||
                var scope = try scopes.addOne(allocator);
 | 
			
		||||
                scope.* = .{
 | 
			
		||||
                    .range = .{
 | 
			
		||||
                        .start = offsets.tokenLocation(tree, payload).start,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, lastToken(tree, if_node.ast.then_expr)).end,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, if_node.ast.then_expr)).end,
 | 
			
		||||
                    },
 | 
			
		||||
                    .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                    .data = .other,
 | 
			
		||||
@ -2873,7 +2874,7 @@ fn makeScopeInternal(
 | 
			
		||||
                    scope.* = .{
 | 
			
		||||
                        .range = .{
 | 
			
		||||
                            .start = offsets.tokenLocation(tree, err_token).start,
 | 
			
		||||
                            .end = offsets.tokenLocation(tree, lastToken(tree, if_node.ast.else_expr)).end,
 | 
			
		||||
                            .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, if_node.ast.else_expr)).end,
 | 
			
		||||
                        },
 | 
			
		||||
                        .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                        .data = .other,
 | 
			
		||||
@ -2896,7 +2897,7 @@ fn makeScopeInternal(
 | 
			
		||||
            scope.* = .{
 | 
			
		||||
                .range = .{
 | 
			
		||||
                    .start = offsets.tokenLocation(tree, tree.firstToken(catch_expr)).start,
 | 
			
		||||
                    .end = offsets.tokenLocation(tree, lastToken(tree, catch_expr)).end,
 | 
			
		||||
                    .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, catch_expr)).end,
 | 
			
		||||
                },
 | 
			
		||||
                .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                .data = .other,
 | 
			
		||||
@ -2918,7 +2919,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .@"for",
 | 
			
		||||
        .for_simple,
 | 
			
		||||
        => {
 | 
			
		||||
            const while_node = whileAst(tree, node_idx).?;
 | 
			
		||||
            const while_node = Analysis.whileAst(tree, node_idx).?;
 | 
			
		||||
            const is_for = node_tag == .@"for" or node_tag == .for_simple;
 | 
			
		||||
 | 
			
		||||
            if (while_node.label_token) |label| {
 | 
			
		||||
@ -2927,7 +2928,7 @@ fn makeScopeInternal(
 | 
			
		||||
                scope.* = .{
 | 
			
		||||
                    .range = .{
 | 
			
		||||
                        .start = offsets.tokenLocation(tree, while_node.ast.while_token).start,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, lastToken(tree, node_idx)).end,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, node_idx)).end,
 | 
			
		||||
                    },
 | 
			
		||||
                    .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                    .data = .other,
 | 
			
		||||
@ -2942,7 +2943,7 @@ fn makeScopeInternal(
 | 
			
		||||
                scope.* = .{
 | 
			
		||||
                    .range = .{
 | 
			
		||||
                        .start = offsets.tokenLocation(tree, payload).start,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, lastToken(tree, while_node.ast.then_expr)).end,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, while_node.ast.then_expr)).end,
 | 
			
		||||
                    },
 | 
			
		||||
                    .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                    .data = .other,
 | 
			
		||||
@ -2987,7 +2988,7 @@ fn makeScopeInternal(
 | 
			
		||||
                    scope.* = .{
 | 
			
		||||
                        .range = .{
 | 
			
		||||
                            .start = offsets.tokenLocation(tree, err_token).start,
 | 
			
		||||
                            .end = offsets.tokenLocation(tree, lastToken(tree, while_node.ast.else_expr)).end,
 | 
			
		||||
                            .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, while_node.ast.else_expr)).end,
 | 
			
		||||
                        },
 | 
			
		||||
                        .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                        .data = .other,
 | 
			
		||||
@ -3019,7 +3020,7 @@ fn makeScopeInternal(
 | 
			
		||||
                    scope.* = .{
 | 
			
		||||
                        .range = .{
 | 
			
		||||
                            .start = offsets.tokenLocation(tree, payload).start,
 | 
			
		||||
                            .end = offsets.tokenLocation(tree, lastToken(tree, switch_case.ast.target_expr)).end,
 | 
			
		||||
                            .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, switch_case.ast.target_expr)).end,
 | 
			
		||||
                        },
 | 
			
		||||
                        .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                        .data = .other,
 | 
			
		||||
@ -3053,7 +3054,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .aligned_var_decl,
 | 
			
		||||
        .simple_var_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            const var_decl = varDecl(tree, node_idx).?;
 | 
			
		||||
            const var_decl = Analysis.varDecl(tree, node_idx).?;
 | 
			
		||||
            if (var_decl.ast.type_node != 0) {
 | 
			
		||||
                try makeScopeInternal(allocator, context, var_decl.ast.type_node);
 | 
			
		||||
            }
 | 
			
		||||
@ -3072,7 +3073,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .async_call_one_comma,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const call = callFull(tree, node_idx, &buf).?;
 | 
			
		||||
            const call = Analysis.callFull(tree, node_idx, &buf).?;
 | 
			
		||||
 | 
			
		||||
            try makeScopeInternal(allocator, context, call.ast.fn_expr);
 | 
			
		||||
            for (call.ast.params) |param|
 | 
			
		||||
@ -3131,7 +3132,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .container_field_align,
 | 
			
		||||
        .container_field_init,
 | 
			
		||||
        => {
 | 
			
		||||
            const field = containerField(tree, node_idx).?;
 | 
			
		||||
            const field = Analysis.containerField(tree, node_idx).?;
 | 
			
		||||
 | 
			
		||||
            try makeScopeInternal(allocator, context, field.ast.type_expr);
 | 
			
		||||
            try makeScopeInternal(allocator, context, field.ast.align_expr);
 | 
			
		||||
@ -3163,7 +3164,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .ptr_type_bit_range,
 | 
			
		||||
        .ptr_type_sentinel,
 | 
			
		||||
        => {
 | 
			
		||||
            const ptr_type: ast.full.PtrType = ptrType(tree, node_idx).?;
 | 
			
		||||
            const ptr_type: ast.full.PtrType = Analysis.ptrType(tree, node_idx).?;
 | 
			
		||||
 | 
			
		||||
            try makeScopeInternal(allocator, context, ptr_type.ast.sentinel);
 | 
			
		||||
            try makeScopeInternal(allocator, context, ptr_type.ast.align_node);
 | 
			
		||||
@ -3192,7 +3193,7 @@ fn makeScopeInternal(
 | 
			
		||||
                scope.* = .{
 | 
			
		||||
                    .range = .{
 | 
			
		||||
                        .start = offsets.tokenLocation(tree, payload_token).start,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, lastToken(tree, expr)).end,
 | 
			
		||||
                        .end = offsets.tokenLocation(tree, Analysis.lastToken(tree, expr)).end,
 | 
			
		||||
                    },
 | 
			
		||||
                    .decls = std.StringHashMap(Declaration).init(allocator),
 | 
			
		||||
                    .data = .other,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								src/ast.zig
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								src/ast.zig
									
									
									
									
									
								
							@ -3,13 +3,13 @@
 | 
			
		||||
//! when there are parser errors.
 | 
			
		||||
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const ast = std.zig.ast;
 | 
			
		||||
const Tree = ast.Tree;
 | 
			
		||||
const ast = std.zig.Ast;
 | 
			
		||||
pub const Tree = ast;
 | 
			
		||||
const Node = ast.Node;
 | 
			
		||||
const full = ast.full;
 | 
			
		||||
const assert = std.debug.assert;
 | 
			
		||||
 | 
			
		||||
fn fullPtrType(tree: Tree, info: full.PtrType.Ast) full.PtrType {
 | 
			
		||||
fn fullPtrType(tree: Tree, info: full.PtrType.Components) 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
 | 
			
		||||
@ -112,7 +112,7 @@ pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) full.PtrType {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn fullIf(tree: Tree, info: full.If.Ast) full.If {
 | 
			
		||||
fn fullIf(tree: Tree, info: full.If.Components) full.If {
 | 
			
		||||
    const token_tags = tree.tokens.items(.tag);
 | 
			
		||||
    var result: full.If = .{
 | 
			
		||||
        .ast = info,
 | 
			
		||||
@ -158,7 +158,7 @@ pub fn ifFull(tree: Tree, node: Node.Index) full.If {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn fullWhile(tree: Tree, info: full.While.Ast) full.While {
 | 
			
		||||
fn fullWhile(tree: Tree, info: full.While.Components) full.While {
 | 
			
		||||
    const token_tags = tree.tokens.items(.tag);
 | 
			
		||||
    var result: full.While = .{
 | 
			
		||||
        .ast = info,
 | 
			
		||||
@ -251,7 +251,7 @@ pub fn forFull(tree: Tree, node: Node.Index) full.While {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn lastToken(tree: ast.Tree, node: ast.Node.Index) ast.TokenIndex {
 | 
			
		||||
pub fn lastToken(tree: Tree, node: ast.Node.Index) ast.TokenIndex {
 | 
			
		||||
    const TokenIndex = ast.TokenIndex;
 | 
			
		||||
    const tags = tree.nodes.items(.tag);
 | 
			
		||||
    const datas = tree.nodes.items(.data);
 | 
			
		||||
@ -863,7 +863,7 @@ 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 {
 | 
			
		||||
pub fn containerField(tree: 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),
 | 
			
		||||
@ -872,7 +872,7 @@ pub fn containerField(tree: ast.Tree, node: ast.Node.Index) ?ast.full.ContainerF
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn ptrType(tree: ast.Tree, node: ast.Node.Index) ?ast.full.PtrType {
 | 
			
		||||
pub fn ptrType(tree: 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),
 | 
			
		||||
@ -882,7 +882,7 @@ pub fn ptrType(tree: ast.Tree, node: ast.Node.Index) ?ast.full.PtrType {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn whileAst(tree: ast.Tree, node: ast.Node.Index) ?ast.full.While {
 | 
			
		||||
pub fn whileAst(tree: Tree, node: ast.Node.Index) ?ast.full.While {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .@"while" => whileFull(tree, node),
 | 
			
		||||
        .while_simple => whileSimple(tree, node),
 | 
			
		||||
@ -893,7 +893,7 @@ pub fn whileAst(tree: ast.Tree, node: ast.Node.Index) ?ast.full.While {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isContainer(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
pub fn isContainer(tree: Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .container_decl,
 | 
			
		||||
        .container_decl_trailing,
 | 
			
		||||
@ -916,7 +916,7 @@ pub fn isContainer(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
 | 
			
		||||
/// 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 {
 | 
			
		||||
pub fn declMembers(tree: 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,
 | 
			
		||||
@ -933,7 +933,7 @@ pub fn declMembers(tree: ast.Tree, node_idx: ast.Node.Index, buffer: *[2]ast.Nod
 | 
			
		||||
 | 
			
		||||
/// 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 {
 | 
			
		||||
pub fn varDecl(tree: 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),
 | 
			
		||||
@ -943,7 +943,7 @@ pub fn varDecl(tree: ast.Tree, node_idx: ast.Node.Index) ?ast.full.VarDecl {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isBuiltinCall(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
pub fn isBuiltinCall(tree: Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .builtin_call,
 | 
			
		||||
        .builtin_call_comma,
 | 
			
		||||
@ -954,7 +954,7 @@ pub fn isBuiltinCall(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn isCall(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
pub fn isCall(tree: Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .call,
 | 
			
		||||
        .call_comma,
 | 
			
		||||
@ -969,7 +969,7 @@ pub fn isCall(tree: ast.Tree, node: ast.Node.Index) bool {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn fnProto(tree: ast.Tree, node: ast.Node.Index, buf: *[1]ast.Node.Index) ?ast.full.FnProto {
 | 
			
		||||
pub fn fnProto(tree: 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),
 | 
			
		||||
@ -980,7 +980,7 @@ pub fn fnProto(tree: ast.Tree, node: ast.Node.Index, buf: *[1]ast.Node.Index) ?a
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn callFull(tree: ast.Tree, node: ast.Node.Index, buf: *[1]ast.Node.Index) ?ast.full.Call {
 | 
			
		||||
pub fn callFull(tree: Tree, node: ast.Node.Index, buf: *[1]ast.Node.Index) ?ast.full.Call {
 | 
			
		||||
    return switch (tree.nodes.items(.tag)[node]) {
 | 
			
		||||
        .call,
 | 
			
		||||
        .call_comma,
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ const URI = @import("uri.zig");
 | 
			
		||||
const analysis = @import("analysis.zig");
 | 
			
		||||
const offsets = @import("offsets.zig");
 | 
			
		||||
const log = std.log.scoped(.doc_store);
 | 
			
		||||
const Tree = std.zig.Ast;
 | 
			
		||||
const BuildAssociatedConfig = @import("build_associated_config.zig");
 | 
			
		||||
 | 
			
		||||
const DocumentStore = @This();
 | 
			
		||||
@ -33,7 +34,7 @@ pub const Handle = struct {
 | 
			
		||||
    import_uris: []const []const u8,
 | 
			
		||||
    /// Items in this array list come from `import_uris`
 | 
			
		||||
    imports_used: std.ArrayListUnmanaged([]const u8),
 | 
			
		||||
    tree: std.zig.ast.Tree,
 | 
			
		||||
    tree: Tree,
 | 
			
		||||
    document_scope: analysis.DocumentScope,
 | 
			
		||||
 | 
			
		||||
    associated_build_file: ?*BuildFile,
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@ const rename = @import("rename.zig");
 | 
			
		||||
const offsets = @import("offsets.zig");
 | 
			
		||||
const setup = @import("setup.zig");
 | 
			
		||||
const semantic_tokens = @import("semantic_tokens.zig");
 | 
			
		||||
const ast = std.zig.Ast;
 | 
			
		||||
const known_folders = @import("known-folders");
 | 
			
		||||
const data = blk: {
 | 
			
		||||
    if (std.mem.eql(u8, build_options.data_version, "0.7.0")) break :blk @import("data/0.7.0.zig");
 | 
			
		||||
@ -200,7 +201,7 @@ fn showMessage(message_type: types.MessageType, message: []const u8) !void {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Is this correct or can we get a better end?
 | 
			
		||||
fn astLocationToRange(loc: std.zig.ast.Tree.Location) types.Range {
 | 
			
		||||
fn astLocationToRange(loc: ast.Location) types.Range {
 | 
			
		||||
    return .{
 | 
			
		||||
        .start = .{
 | 
			
		||||
            .line = @intCast(i64, loc.line),
 | 
			
		||||
@ -246,7 +247,7 @@ fn publishDiagnostics(arena: *std.heap.ArenaAllocator, handle: DocumentStore.Han
 | 
			
		||||
                .fn_proto_simple,
 | 
			
		||||
                .fn_decl,
 | 
			
		||||
                => blk: {
 | 
			
		||||
                    var buf: [1]std.zig.ast.Node.Index = undefined;
 | 
			
		||||
                    var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
                    const func = analysis.fnProto(tree, decl_idx, &buf).?;
 | 
			
		||||
                    if (func.extern_export_inline_token != null) break :blk;
 | 
			
		||||
 | 
			
		||||
@ -415,7 +416,7 @@ fn nodeToCompletion(
 | 
			
		||||
        .fn_proto_simple,
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [1]std.zig.ast.Node.Index = undefined;
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const func = analysis.fnProto(tree, node, &buf).?;
 | 
			
		||||
            if (func.name_token) |name_token| {
 | 
			
		||||
                const use_snippets = config.enable_snippets and client_capabilities.supports_snippets;
 | 
			
		||||
@ -637,7 +638,7 @@ fn hoverSymbol(
 | 
			
		||||
            }
 | 
			
		||||
            doc_str = try analysis.getDocComments(&arena.allocator, tree, node, hover_kind);
 | 
			
		||||
 | 
			
		||||
            var buf: [1]std.zig.ast.Node.Index = undefined;
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
 | 
			
		||||
            if (analysis.varDecl(tree, node)) |var_decl| {
 | 
			
		||||
                break :def analysis.getVariableSignature(tree, var_decl);
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const types = @import("types.zig");
 | 
			
		||||
const ast = std.zig.ast;
 | 
			
		||||
const ast = std.zig.Ast;
 | 
			
		||||
const Tree = ast;
 | 
			
		||||
 | 
			
		||||
pub const Encoding = enum {
 | 
			
		||||
    utf8,
 | 
			
		||||
@ -62,7 +63,7 @@ pub fn documentPosition(doc: types.TextDocument, position: types.Position, encod
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn lineSectionLength(tree: ast.Tree, start_index: usize, end_index: usize, encoding: Encoding) !usize {
 | 
			
		||||
pub fn lineSectionLength(tree: Tree, start_index: usize, end_index: usize, encoding: Encoding) !usize {
 | 
			
		||||
    const source = tree.source[start_index..];
 | 
			
		||||
    std.debug.assert(end_index >= start_index and source.len >= end_index - start_index);
 | 
			
		||||
    if (encoding == .utf8) {
 | 
			
		||||
@ -103,7 +104,7 @@ pub const TokenLocation = struct {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub fn tokenRelativeLocation(tree: ast.Tree, start_index: usize, token_start: usize, encoding: Encoding) !TokenLocation {
 | 
			
		||||
pub fn tokenRelativeLocation(tree: Tree, start_index: usize, token_start: usize, encoding: Encoding) !TokenLocation {
 | 
			
		||||
    std.debug.assert(token_start >= start_index);
 | 
			
		||||
    var loc = TokenLocation{
 | 
			
		||||
        .line = 0,
 | 
			
		||||
@ -139,7 +140,7 @@ pub fn tokenRelativeLocation(tree: ast.Tree, start_index: usize, token_start: us
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Asserts the token is comprised of valid utf8
 | 
			
		||||
pub fn tokenLength(tree: ast.Tree, token: ast.TokenIndex, encoding: Encoding) usize {
 | 
			
		||||
pub fn tokenLength(tree: Tree, token: ast.TokenIndex, encoding: Encoding) usize {
 | 
			
		||||
    const token_loc = tokenLocation(tree, token);
 | 
			
		||||
    if (encoding == .utf8)
 | 
			
		||||
        return token_loc.end - token_loc.start;
 | 
			
		||||
@ -165,7 +166,7 @@ pub const Loc = struct {
 | 
			
		||||
    end: usize,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub fn tokenLocation(tree: ast.Tree, token_index: ast.TokenIndex) Loc {
 | 
			
		||||
pub fn tokenLocation(tree: Tree, token_index: ast.TokenIndex) Loc {
 | 
			
		||||
    const start = tree.tokens.items(.start)[token_index];
 | 
			
		||||
    const tag = tree.tokens.items(.tag)[token_index];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,10 @@ const analysis = @import("analysis.zig");
 | 
			
		||||
const types = @import("types.zig");
 | 
			
		||||
const offsets = @import("offsets.zig");
 | 
			
		||||
const log = std.log.scoped(.references);
 | 
			
		||||
const Reference = @This();
 | 
			
		||||
usingnamespace @import("ast.zig");
 | 
			
		||||
 | 
			
		||||
const ast = std.zig.ast;
 | 
			
		||||
const ast = std.zig.Ast;
 | 
			
		||||
 | 
			
		||||
fn tokenReference(
 | 
			
		||||
    handle: *DocumentStore.Handle,
 | 
			
		||||
@ -122,7 +123,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .error_set_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
            for (declMembers(tree, node, &buf)) |member|
 | 
			
		||||
            for (Reference.declMembers(tree, node, &buf)) |member|
 | 
			
		||||
                try symbolReferencesInternal(arena, store, .{ .node = member, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
        },
 | 
			
		||||
        .global_var_decl,
 | 
			
		||||
@ -130,7 +131,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .simple_var_decl,
 | 
			
		||||
        .aligned_var_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            const var_decl = varDecl(tree, node).?;
 | 
			
		||||
            const var_decl = Reference.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);
 | 
			
		||||
            }
 | 
			
		||||
@ -145,7 +146,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .container_field_align,
 | 
			
		||||
        .container_field_init,
 | 
			
		||||
        => {
 | 
			
		||||
            const field = containerField(tree, node).?;
 | 
			
		||||
            const field = Reference.containerField(tree, node).?;
 | 
			
		||||
            if (field.ast.type_expr != 0) {
 | 
			
		||||
                try symbolReferencesInternal(arena, store, .{ .node = field.ast.type_expr, .handle = handle }, decl, encoding, context, handler);
 | 
			
		||||
            }
 | 
			
		||||
@ -167,7 +168,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const fn_proto = fnProto(tree, node, &buf).?;
 | 
			
		||||
            const fn_proto = Reference.fnProto(tree, node, &buf).?;
 | 
			
		||||
            var it = fn_proto.iterate(tree);
 | 
			
		||||
            while (it.next()) |param| {
 | 
			
		||||
                if (param.type_expr != 0)
 | 
			
		||||
@ -233,7 +234,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .for_simple,
 | 
			
		||||
        .@"for",
 | 
			
		||||
        => {
 | 
			
		||||
            const loop = whileAst(tree, node).?;
 | 
			
		||||
            const loop = Reference.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);
 | 
			
		||||
@ -246,7 +247,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .@"if",
 | 
			
		||||
        .if_simple,
 | 
			
		||||
        => {
 | 
			
		||||
            const if_node = ifFull(tree, node);
 | 
			
		||||
            const if_node = Reference.ifFull(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);
 | 
			
		||||
@ -265,7 +266,7 @@ fn symbolReferencesInternal(
 | 
			
		||||
        .ptr_type_bit_range,
 | 
			
		||||
        .ptr_type_sentinel,
 | 
			
		||||
        => {
 | 
			
		||||
            const ptr_type = ptrType(tree, node).?;
 | 
			
		||||
            const ptr_type = Reference.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);
 | 
			
		||||
@ -577,7 +578,7 @@ pub fn symbolReferences(
 | 
			
		||||
                switch (scope.data) {
 | 
			
		||||
                    .function => |proto| {
 | 
			
		||||
                        var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
                        const fn_proto = fnProto(curr_handle.tree, proto, &buf).?;
 | 
			
		||||
                        const fn_proto = Reference.fnProto(curr_handle.tree, proto, &buf).?;
 | 
			
		||||
                        var it = fn_proto.iterate(curr_handle.tree);
 | 
			
		||||
                        while (it.next()) |candidate| {
 | 
			
		||||
                            if (std.meta.eql(candidate, param)) {
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,9 @@ const std = @import("std");
 | 
			
		||||
const offsets = @import("offsets.zig");
 | 
			
		||||
const DocumentStore = @import("document_store.zig");
 | 
			
		||||
const analysis = @import("analysis.zig");
 | 
			
		||||
const ast = std.zig.ast;
 | 
			
		||||
const ast = std.zig.Ast;
 | 
			
		||||
const log = std.log.scoped(.semantic_tokens);
 | 
			
		||||
const SemanticToken = @This();
 | 
			
		||||
usingnamespace @import("ast.zig");
 | 
			
		||||
 | 
			
		||||
pub const TokenType = enum(u32) {
 | 
			
		||||
@ -195,7 +196,7 @@ inline fn writeTokenMod(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn writeDocComments(builder: *Builder, tree: ast.Tree, doc: ast.TokenIndex) !void {
 | 
			
		||||
fn writeDocComments(builder: *Builder, tree: SemanticToken.Tree, doc: ast.TokenIndex) !void {
 | 
			
		||||
    const token_tags = tree.tokens.items(.tag);
 | 
			
		||||
    var tok_idx = doc;
 | 
			
		||||
    while (token_tags[tok_idx] == .doc_comment or
 | 
			
		||||
@ -335,7 +336,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .simple_var_decl,
 | 
			
		||||
        .aligned_var_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            const var_decl = varDecl(tree, node).?;
 | 
			
		||||
            const var_decl = SemanticToken.varDecl(tree, node).?;
 | 
			
		||||
            if (analysis.getDocCommentTokenIndex(token_tags, main_token)) |comment_idx|
 | 
			
		||||
                try writeDocComments(builder, tree, comment_idx);
 | 
			
		||||
 | 
			
		||||
@ -444,7 +445,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .fn_decl,
 | 
			
		||||
        => {
 | 
			
		||||
            var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
            const fn_proto: ast.full.FnProto = fnProto(tree, node, &buf).?;
 | 
			
		||||
            const fn_proto: ast.full.FnProto = SemanticToken.fnProto(tree, node, &buf).?;
 | 
			
		||||
            if (analysis.getDocCommentTokenIndex(token_tags, main_token)) |docs|
 | 
			
		||||
                try writeDocComments(builder, tree, docs);
 | 
			
		||||
 | 
			
		||||
@ -536,7 +537,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .for_simple,
 | 
			
		||||
        .@"for",
 | 
			
		||||
        => {
 | 
			
		||||
            const while_node = whileAst(tree, node).?;
 | 
			
		||||
            const while_node = SemanticToken.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);
 | 
			
		||||
@ -570,7 +571,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .@"if",
 | 
			
		||||
        .if_simple,
 | 
			
		||||
        => {
 | 
			
		||||
            const if_node = ifFull(tree, node);
 | 
			
		||||
            const if_node = SemanticToken.ifFull(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 });
 | 
			
		||||
@ -642,7 +643,7 @@ fn writeNodeTokens(
 | 
			
		||||
                    .node = struct_init.ast.type_expr,
 | 
			
		||||
                    .handle = handle,
 | 
			
		||||
                })) |struct_type| switch (struct_type.type.data) {
 | 
			
		||||
                    .other => |type_node| if (isContainer(struct_type.handle.tree, type_node))
 | 
			
		||||
                    .other => |type_node| if (SemanticToken.isContainer(struct_type.handle.tree, type_node))
 | 
			
		||||
                        fieldTokenType(type_node, struct_type.handle)
 | 
			
		||||
                    else
 | 
			
		||||
                        null,
 | 
			
		||||
@ -678,8 +679,8 @@ fn writeNodeTokens(
 | 
			
		||||
            try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, call.ast.fn_expr });
 | 
			
		||||
 | 
			
		||||
            if (builder.previous_token) |prev| {
 | 
			
		||||
                if (prev != lastToken(tree, call.ast.fn_expr) and token_tags[lastToken(tree, call.ast.fn_expr)] == .identifier) {
 | 
			
		||||
                    try writeToken(builder, lastToken(tree, call.ast.fn_expr), .function);
 | 
			
		||||
                if (prev != SemanticToken.lastToken(tree, call.ast.fn_expr) and token_tags[SemanticToken.lastToken(tree, call.ast.fn_expr)] == .identifier) {
 | 
			
		||||
                    try writeToken(builder, SemanticToken.lastToken(tree, call.ast.fn_expr), .function);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for (call.ast.params) |param| try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, param });
 | 
			
		||||
@ -697,7 +698,7 @@ fn writeNodeTokens(
 | 
			
		||||
 | 
			
		||||
            try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, slice.ast.sliced });
 | 
			
		||||
            try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, slice.ast.start });
 | 
			
		||||
            try writeToken(builder, lastToken(tree, slice.ast.start) + 1, .operator);
 | 
			
		||||
            try writeToken(builder, SemanticToken.lastToken(tree, slice.ast.start) + 1, .operator);
 | 
			
		||||
 | 
			
		||||
            try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, slice.ast.end });
 | 
			
		||||
            try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, slice.ast.sentinel });
 | 
			
		||||
@ -894,7 +895,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 (isContainer(lhs_type.handle.tree, left_type_node))
 | 
			
		||||
                            const tok_type: ?TokenType = if (SemanticToken.isContainer(lhs_type.handle.tree, left_type_node))
 | 
			
		||||
                                fieldTokenType(decl_node, lhs_type.handle)
 | 
			
		||||
                            else if (left_type_node == 0)
 | 
			
		||||
                                TokenType.field
 | 
			
		||||
@ -920,7 +921,7 @@ fn writeNodeTokens(
 | 
			
		||||
        .ptr_type_bit_range,
 | 
			
		||||
        .ptr_type_sentinel,
 | 
			
		||||
        => {
 | 
			
		||||
            const ptr_type = ptrType(tree, node).?;
 | 
			
		||||
            const ptr_type = SemanticToken.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])
 | 
			
		||||
@ -995,7 +996,7 @@ fn writeContainerField(
 | 
			
		||||
    child_frame: anytype,
 | 
			
		||||
) !void {
 | 
			
		||||
    const tree = builder.handle.tree;
 | 
			
		||||
    const container_field = containerField(tree, node).?;
 | 
			
		||||
    const container_field = SemanticToken.containerField(tree, node).?;
 | 
			
		||||
    const base = tree.nodes.items(.main_token)[node];
 | 
			
		||||
    const tokens = tree.tokens.items(.tag);
 | 
			
		||||
 | 
			
		||||
@ -1015,9 +1016,9 @@ fn writeContainerField(
 | 
			
		||||
 | 
			
		||||
    if (container_field.ast.value_expr != 0) block: {
 | 
			
		||||
        const eq_tok: ast.TokenIndex = if (container_field.ast.align_expr != 0)
 | 
			
		||||
            lastToken(tree, container_field.ast.align_expr) + 2
 | 
			
		||||
            SemanticToken.lastToken(tree, container_field.ast.align_expr) + 2
 | 
			
		||||
        else if (container_field.ast.type_expr != 0)
 | 
			
		||||
            lastToken(tree, container_field.ast.type_expr) + 1
 | 
			
		||||
            SemanticToken.lastToken(tree, container_field.ast.type_expr) + 1
 | 
			
		||||
        else
 | 
			
		||||
            break :block;
 | 
			
		||||
 | 
			
		||||
@ -1038,7 +1039,7 @@ pub fn writeAllSemanticTokens(
 | 
			
		||||
 | 
			
		||||
    // reverse the ast from the root declarations
 | 
			
		||||
    var buf: [2]ast.Node.Index = undefined;
 | 
			
		||||
    for (declMembers(handle.tree, 0, &buf)) |child| {
 | 
			
		||||
    for (SemanticToken.declMembers(handle.tree, 0, &buf)) |child| {
 | 
			
		||||
        writeNodeTokens(&builder, arena, store, child) catch |err| switch (err) {
 | 
			
		||||
            error.MovedBackwards => break,
 | 
			
		||||
            else => |e| return e,
 | 
			
		||||
 | 
			
		||||
@ -3,9 +3,10 @@ const analysis = @import("analysis.zig");
 | 
			
		||||
const offsets = @import("offsets.zig");
 | 
			
		||||
const DocumentStore = @import("document_store.zig");
 | 
			
		||||
const types = @import("types.zig");
 | 
			
		||||
const ast = std.zig.ast;
 | 
			
		||||
const ast = std.zig.Ast;
 | 
			
		||||
const Token = std.zig.Token;
 | 
			
		||||
const identifierFromPosition = @import("main.zig").identifierFromPosition;
 | 
			
		||||
const SignatureHelp = @This();
 | 
			
		||||
usingnamespace @import("ast.zig");
 | 
			
		||||
 | 
			
		||||
fn fnProtoToSignatureInfo(
 | 
			
		||||
@ -58,7 +59,7 @@ fn fnProtoToSignatureInfo(
 | 
			
		||||
            if (param_label_start == 0)
 | 
			
		||||
                param_label_start = token_starts[tree.firstToken(param.type_expr)];
 | 
			
		||||
 | 
			
		||||
            const last_param_tok = lastToken(tree, param.type_expr);
 | 
			
		||||
            const last_param_tok = SignatureHelp.lastToken(tree, param.type_expr);
 | 
			
		||||
            param_label_end = token_starts[last_param_tok] + tree.tokenSlice(last_param_tok).len;
 | 
			
		||||
        }
 | 
			
		||||
        const param_label = tree.source[param_label_start..param_label_end];
 | 
			
		||||
@ -287,7 +288,7 @@ pub fn getSignatureInfo(
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    var buf: [1]ast.Node.Index = undefined;
 | 
			
		||||
                    if (fnProto(type_handle.handle.tree, node, &buf)) |proto| {
 | 
			
		||||
                    if (SignatureHelp.fnProto(type_handle.handle.tree, node, &buf)) |proto| {
 | 
			
		||||
                        return try fnProtoToSignatureInfo(
 | 
			
		||||
                            document_store,
 | 
			
		||||
                            arena,
 | 
			
		||||
@ -339,7 +340,7 @@ pub fn getSignatureInfo(
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (fnProto(res_handle.tree, node, &buf)) |proto| {
 | 
			
		||||
                    if (SignatureHelp.fnProto(res_handle.tree, node, &buf)) |proto| {
 | 
			
		||||
                        return try fnProtoToSignatureInfo(
 | 
			
		||||
                            document_store,
 | 
			
		||||
                            arena,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user