Work on completion for unwrapped slices/optionals in loops/ifs
This commit is contained in:
		
							parent
							
								
									fd6b94bcc9
								
							
						
					
					
						commit
						43ebfc7300
					
				@ -595,6 +595,7 @@ fn resolveBracketAccessType(
 | 
			
		||||
    const tags = tree.nodes.items(.tag);
 | 
			
		||||
    const tag = tags[lhs_node];
 | 
			
		||||
    const data = tree.nodes.items(.data)[lhs_node];
 | 
			
		||||
 | 
			
		||||
    if (tag == .array_type or tag == .array_type_sentinel) {
 | 
			
		||||
        if (rhs == .Single)
 | 
			
		||||
            return ((try resolveTypeOfNodeInternal(store, arena, .{
 | 
			
		||||
@ -605,11 +606,11 @@ fn resolveBracketAccessType(
 | 
			
		||||
            .type = .{ .data = .{ .slice = data.rhs }, .is_type_val = false },
 | 
			
		||||
            .handle = lhs.handle,
 | 
			
		||||
        };
 | 
			
		||||
    } else if (isPtrType(tree, lhs_node)) {
 | 
			
		||||
        if (tags[data.rhs] == .array_type or tags[data.rhs] == .array_type_sentinel) {
 | 
			
		||||
    } else if (ptrType(tree, lhs_node)) |ptr_type| {
 | 
			
		||||
        if (ptr_type.size == .Slice) {
 | 
			
		||||
            if (rhs == .Single) {
 | 
			
		||||
                return ((try resolveTypeOfNodeInternal(store, arena, .{
 | 
			
		||||
                    .node = tree.nodes.items(.data)[data.rhs].rhs,
 | 
			
		||||
                    .node = ptr_type.ast.child_type,
 | 
			
		||||
                    .handle = lhs.handle,
 | 
			
		||||
                }, bound_type_params)) orelse return null).instanceTypeVal();
 | 
			
		||||
            }
 | 
			
		||||
@ -1321,10 +1322,15 @@ pub fn getFieldAccessType(
 | 
			
		||||
 | 
			
		||||
                // Can't call a function type, we need a function type instance.
 | 
			
		||||
                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(tree, current_type_node, &buf)) |func| {
 | 
			
		||||
                    const has_body = tree.nodes.items(.tag)[current_type_node] == .fn_decl;
 | 
			
		||||
                    const body = tree.nodes.items(.data)[current_type_node].rhs;
 | 
			
		||||
                if (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
 | 
			
		||||
                    const has_body = cur_tree.nodes.items(.tag)[current_type_node] == .fn_decl;
 | 
			
		||||
                    const body = cur_tree.nodes.items(.data)[current_type_node].rhs;
 | 
			
		||||
 | 
			
		||||
                    if (try resolveReturnType(store, arena, func, current_type.handle, &bound_type_params, if (has_body) body else null)) |ret| {
 | 
			
		||||
                        current_type = ret;
 | 
			
		||||
                        // Skip to the right paren
 | 
			
		||||
@ -1911,16 +1917,16 @@ pub const Declaration = union(enum) {
 | 
			
		||||
        name: ast.TokenIndex,
 | 
			
		||||
        condition: ast.Node.Index,
 | 
			
		||||
    },
 | 
			
		||||
    // array_payload: struct {
 | 
			
		||||
    //     identifier: *ast.Node,
 | 
			
		||||
    //     array_expr: ast.full.ArrayType,
 | 
			
		||||
    // },
 | 
			
		||||
    array_payload: struct {
 | 
			
		||||
        identifier: ast.TokenIndex,
 | 
			
		||||
        array_expr: ast.Node.Index,
 | 
			
		||||
    },
 | 
			
		||||
    switch_payload: struct {
 | 
			
		||||
        node: ast.TokenIndex,
 | 
			
		||||
        switch_expr: ast.Node.Index,
 | 
			
		||||
        items: []const ast.Node.Index,
 | 
			
		||||
    },
 | 
			
		||||
    label_decl: ast.TokenIndex, // .id is While, For or Block (firstToken will be the label)
 | 
			
		||||
    label_decl: ast.TokenIndex,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub const DeclWithHandle = struct {
 | 
			
		||||
@ -1934,7 +1940,7 @@ pub const DeclWithHandle = struct {
 | 
			
		||||
            .ast_node => |n| getDeclNameToken(tree, n).?,
 | 
			
		||||
            .param_decl => |p| p.name_token.?,
 | 
			
		||||
            .pointer_payload => |pp| pp.name,
 | 
			
		||||
            // .array_payload => |ap| ap.identifier.firstToken(),
 | 
			
		||||
            .array_payload => |ap| ap.identifier,
 | 
			
		||||
            .switch_payload => |sp| sp.node + @boolToInt(token_tags[sp.node] == .asterisk),
 | 
			
		||||
            .label_decl => |ld| ld,
 | 
			
		||||
        };
 | 
			
		||||
@ -1956,9 +1962,13 @@ pub const DeclWithHandle = struct {
 | 
			
		||||
        const tree = self.handle.tree;
 | 
			
		||||
        const node_tags = tree.nodes.items(.tag);
 | 
			
		||||
        const main_tokens = tree.nodes.items(.main_token);
 | 
			
		||||
 | 
			
		||||
        return switch (self.decl.*) {
 | 
			
		||||
            .ast_node => |node| try resolveTypeOfNodeInternal(store, arena, .{ .node = node, .handle = self.handle }, bound_type_params),
 | 
			
		||||
            .ast_node => |node| try resolveTypeOfNodeInternal(
 | 
			
		||||
                store,
 | 
			
		||||
                arena,
 | 
			
		||||
                .{ .node = node, .handle = self.handle },
 | 
			
		||||
                bound_type_params,
 | 
			
		||||
            ),
 | 
			
		||||
            .param_decl => |param_decl| {
 | 
			
		||||
                if (typeIsType(self.handle.tree, param_decl.type_expr)) {
 | 
			
		||||
                    var bound_param_it = bound_type_params.iterator();
 | 
			
		||||
@ -1988,6 +1998,16 @@ pub const DeclWithHandle = struct {
 | 
			
		||||
                }, bound_type_params)) orelse return null,
 | 
			
		||||
                bound_type_params,
 | 
			
		||||
            ),
 | 
			
		||||
            .array_payload => |pay| try resolveBracketAccessType(
 | 
			
		||||
                store,
 | 
			
		||||
                arena,
 | 
			
		||||
                (try resolveTypeOfNodeInternal(store, arena, .{
 | 
			
		||||
                    .node = pay.array_expr,
 | 
			
		||||
                    .handle = self.handle,
 | 
			
		||||
                }, bound_type_params)) orelse return null,
 | 
			
		||||
                .Single,
 | 
			
		||||
                bound_type_params,
 | 
			
		||||
            ),
 | 
			
		||||
            .label_decl => return null,
 | 
			
		||||
            .switch_payload => |pay| {
 | 
			
		||||
                if (pay.items.len == 0) return null;
 | 
			
		||||
@ -2832,7 +2852,7 @@ fn makeScopeInternal(
 | 
			
		||||
        .while_cont,
 | 
			
		||||
        .@"for",
 | 
			
		||||
        .for_simple,
 | 
			
		||||
        => {
 | 
			
		||||
        => |tag| {
 | 
			
		||||
            const while_node: ast.full.While = switch (node) {
 | 
			
		||||
                .@"while" => tree.whileFull(node_idx),
 | 
			
		||||
                .while_simple => tree.whileSimple(node_idx),
 | 
			
		||||
@ -2841,6 +2861,9 @@ fn makeScopeInternal(
 | 
			
		||||
                .for_simple => tree.forSimple(node_idx),
 | 
			
		||||
                else => unreachable,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            const is_for = tag == .@"for" or tag == .for_simple;
 | 
			
		||||
 | 
			
		||||
            if (while_node.label_token) |label| {
 | 
			
		||||
                std.debug.assert(token_tags[label] == .identifier);
 | 
			
		||||
                var scope = try scopes.addOne(allocator);
 | 
			
		||||
@ -2877,12 +2900,29 @@ fn makeScopeInternal(
 | 
			
		||||
                std.debug.assert(token_tags[name_token] == .identifier);
 | 
			
		||||
 | 
			
		||||
                const name = tree.tokenSlice(name_token);
 | 
			
		||||
                try scope.decls.putNoClobber(name, .{
 | 
			
		||||
                try scope.decls.putNoClobber(name, if (is_for)
 | 
			
		||||
                    .{
 | 
			
		||||
                        .array_payload = .{
 | 
			
		||||
                            .identifier = name_token,
 | 
			
		||||
                            .array_expr = while_node.ast.cond_expr,
 | 
			
		||||
                        },
 | 
			
		||||
                    }
 | 
			
		||||
                else
 | 
			
		||||
                    .{
 | 
			
		||||
                        .pointer_payload = .{
 | 
			
		||||
                            .name = name_token,
 | 
			
		||||
                            .condition = while_node.ast.cond_expr,
 | 
			
		||||
                        },
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                // for loop with index as well
 | 
			
		||||
                if (token_tags[name_token + 1] == .comma) {
 | 
			
		||||
                    const index_token = name_token + 2;
 | 
			
		||||
                    std.debug.assert(token_tags[index_token] == .identifier);
 | 
			
		||||
                    if (try scope.decls.fetchPut(tree.tokenSlice(index_token), .{ .label_decl = index_token })) |existing| {
 | 
			
		||||
                        // TODO Record a redefinition error
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, while_node.ast.then_expr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								src/main.zig
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								src/main.zig
									
									
									
									
									
								
							@ -637,10 +637,10 @@ fn hoverSymbol(
 | 
			
		||||
            try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{tree.tokenSlice(payload.name)})
 | 
			
		||||
        else
 | 
			
		||||
            try std.fmt.allocPrint(&arena.allocator, "{s}", .{tree.tokenSlice(payload.name)}),
 | 
			
		||||
        // .array_payload => |payload| if (hover_kind == .Markdown)
 | 
			
		||||
        //     try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{handle.tree.tokenSlice(payload.identifier.firstToken())})
 | 
			
		||||
        // else
 | 
			
		||||
        //     try std.fmt.allocPrint(&arena.allocator, "{s}", .{handle.tree.tokenSlice(payload.identifier.firstToken())}),
 | 
			
		||||
        .array_payload => |payload| if (hover_kind == .Markdown)
 | 
			
		||||
            try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{handle.tree.tokenSlice(payload.identifier)})
 | 
			
		||||
        else
 | 
			
		||||
            try std.fmt.allocPrint(&arena.allocator, "{s}", .{handle.tree.tokenSlice(payload.identifier)}),
 | 
			
		||||
        .switch_payload => |payload| if (hover_kind == .Markdown)
 | 
			
		||||
            try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{tree.tokenSlice(payload.node)})
 | 
			
		||||
        else
 | 
			
		||||
@ -935,9 +935,8 @@ fn declToCompletion(context: DeclToCompletionContext, decl_handle: analysis.Decl
 | 
			
		||||
            const first_token = param.first_doc_comment orelse
 | 
			
		||||
                param.comptime_noalias orelse
 | 
			
		||||
                param.name_token orelse
 | 
			
		||||
                param.anytype_ellipsis3 orelse
 | 
			
		||||
                tree.firstToken(param.type_expr);
 | 
			
		||||
            const last_token = tree.lastToken(param.type_expr);
 | 
			
		||||
            const last_token = param.anytype_ellipsis3 orelse tree.lastToken(param.type_expr);
 | 
			
		||||
 | 
			
		||||
            try context.completions.append(.{
 | 
			
		||||
                .label = tree.tokenSlice(param.name_token.?),
 | 
			
		||||
@ -952,12 +951,12 @@ fn declToCompletion(context: DeclToCompletionContext, decl_handle: analysis.Decl
 | 
			
		||||
                .kind = .Variable,
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
        // .array_payload => |payload| {
 | 
			
		||||
        //     try context.completions.append(.{
 | 
			
		||||
        //         .label = tree.tokenSlice(payload.identifier.firstToken()),
 | 
			
		||||
        //         .kind = .Variable,
 | 
			
		||||
        //     });
 | 
			
		||||
        // },
 | 
			
		||||
        .array_payload => |payload| {
 | 
			
		||||
            try context.completions.append(.{
 | 
			
		||||
                .label = tree.tokenSlice(payload.identifier),
 | 
			
		||||
                .kind = .Variable,
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
        .switch_payload => |payload| {
 | 
			
		||||
            try context.completions.append(.{
 | 
			
		||||
                .label = tree.tokenSlice(tree.firstToken(payload.node)),
 | 
			
		||||
 | 
			
		||||
@ -585,7 +585,7 @@ pub fn symbolReferences(
 | 
			
		||||
                return;
 | 
			
		||||
            };
 | 
			
		||||
        },
 | 
			
		||||
        .pointer_payload, .switch_payload => {
 | 
			
		||||
        .pointer_payload, .switch_payload, .array_payload => {
 | 
			
		||||
            if (include_decl) {
 | 
			
		||||
                try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user