Now builds!
This commit is contained in:
parent
3bdb2ee444
commit
05d75781de
184
src/analysis.zig
184
src/analysis.zig
@ -376,110 +376,81 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
.Call => {
|
.Call => {
|
||||||
const call = node.cast(ast.Node.Call).?;
|
const call = node.cast(ast.Node.Call).?;
|
||||||
|
|
||||||
// @TODO use BoundTypeParams: ParamDecl -> NodeWithHandle or something
|
|
||||||
const decl = (try resolveTypeOfNode(store, arena, .{ .node = call.lhs, .handle = handle })) orelse return null;
|
const decl = (try resolveTypeOfNode(store, arena, .{ .node = call.lhs, .handle = handle })) orelse return null;
|
||||||
if (decl.node.cast(ast.Node.FnProto)) |fn_decl| {
|
if (decl.node.cast(ast.Node.FnProto)) |fn_decl| {
|
||||||
|
// @TODO use BoundTypeParams: ParamDecl -> NodeWithHandle or something
|
||||||
// Add type param values to the scope nodes
|
// Add type param values to the scope nodes
|
||||||
const param_len = std.math.min(call.params_len, fn_decl.params_len);
|
// const param_len = std.math.min(call.params_len, fn_decl.params_len);
|
||||||
var scope_nodes = std.ArrayList(*ast.Node).fromOwnedSlice(&analysis_ctx.arena.allocator, analysis_ctx.scope_nodes);
|
// for (fn_decl.paramsConst()) |decl_param, param_idx| {
|
||||||
var analysis_ctx_clone = analysis_ctx.clone() catch return null;
|
// if (param_idx >= param_len) break;
|
||||||
for (fn_decl.paramsConst()) |decl_param, param_idx| {
|
// if (decl_param.name_token == null) continue;
|
||||||
if (param_idx >= param_len) break;
|
// const type_param = switch (decl_param.param_type) {
|
||||||
if (decl_param.name_token == null) continue;
|
// .type_expr => |type_node| if (type_node.cast(ast.Node.Identifier)) |ident|
|
||||||
|
// std.mem.eql(u8, analysis_ctx.tree().tokenSlice(ident.token), "type")
|
||||||
const type_param = switch (decl_param.param_type) {
|
// else
|
||||||
.type_expr => |type_node| if (type_node.cast(ast.Node.Identifier)) |ident|
|
// false,
|
||||||
std.mem.eql(u8, analysis_ctx.tree().tokenSlice(ident.token), "type")
|
// else => false,
|
||||||
else
|
// };
|
||||||
false,
|
// if (!type_param) continue;
|
||||||
else => false,
|
// const call_param_type = (try resolveTypeOfNode(store, arena, .{ .node = call.paramsConst()[param_idx], .handle = handle })) orelse continue;
|
||||||
};
|
// }
|
||||||
if (!type_param) continue;
|
return try resolveReturnType(store, arena, fn_decl, decl.handle);
|
||||||
|
|
||||||
// TODO Handle errors better
|
|
||||||
// TODO This may invalidate the analysis context so we copy it.
|
|
||||||
// However, if the argument hits an import we just ignore it for now.
|
|
||||||
// Once we return our own types instead of directly using nodes we can fix this.
|
|
||||||
const call_param_type = resolveTypeOfNode(&analysis_ctx_clone, call.paramsConst()[param_idx]) orelse continue;
|
|
||||||
if (analysis_ctx_clone.handle != analysis_ctx.handle) {
|
|
||||||
analysis_ctx_clone = analysis_ctx.clone() catch return null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
scope_nodes.append(makeVarDeclNode(
|
|
||||||
&analysis_ctx.arena.allocator,
|
|
||||||
decl_param.doc_comments,
|
|
||||||
decl_param.comptime_token,
|
|
||||||
decl_param.name_token.?,
|
|
||||||
null,
|
|
||||||
call_param_type,
|
|
||||||
) catch return null) catch return null;
|
|
||||||
analysis_ctx.scope_nodes = scope_nodes.items;
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolveReturnType(analysis_ctx, fn_decl);
|
|
||||||
}
|
}
|
||||||
return decl;
|
return decl;
|
||||||
},
|
},
|
||||||
.StructInitializer => {
|
.StructInitializer => {
|
||||||
const struct_init = node.cast(ast.Node.StructInitializer).?;
|
const struct_init = node.cast(ast.Node.StructInitializer).?;
|
||||||
return resolveTypeOfNode(analysis_ctx, struct_init.lhs);
|
return try resolveTypeOfNode(store, arena, .{ .node = struct_init.lhs, .handle = handle });
|
||||||
},
|
},
|
||||||
.ErrorSetDecl => {
|
.ErrorSetDecl => {
|
||||||
const set = node.cast(ast.Node.ErrorSetDecl).?;
|
const set = node.cast(ast.Node.ErrorSetDecl).?;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (set.iterate(i)) |decl| : (i += 1) {
|
while (set.iterate(i)) |decl| : (i += 1) {
|
||||||
// TODO handle errors better?
|
try store.error_completions.add(handle.tree, decl);
|
||||||
analysis_ctx.error_completions.add(analysis_ctx.tree(), decl) catch {};
|
|
||||||
}
|
}
|
||||||
return node;
|
return node_handle;
|
||||||
},
|
},
|
||||||
.SuffixOp => {
|
.SuffixOp => {
|
||||||
const suffix_op = node.cast(ast.Node.SuffixOp).?;
|
const suffix_op = node.cast(ast.Node.SuffixOp).?;
|
||||||
switch (suffix_op.op) {
|
const left_type = (try resolveTypeOfNode(store, arena, .{ .node = suffix_op.lhs, .handle = handle })) orelse return null;
|
||||||
.UnwrapOptional => {
|
return switch (suffix_op.op) {
|
||||||
const left_type = resolveTypeOfNode(analysis_ctx, suffix_op.lhs) orelse return null;
|
.UnwrapOptional => try resolveUnwrapOptionalType(store, arena, left_type),
|
||||||
return resolveUnwrapOptionalType(analysis_ctx, left_type);
|
.Deref => try resolveDerefType(store, arena, left_type),
|
||||||
},
|
.ArrayAccess => try resolveBracketAccessType(store, arena, left_type, .Single),
|
||||||
.Deref => {
|
.Slice => try resolveBracketAccessType(store, arena, left_type, .Range),
|
||||||
const left_type = resolveTypeOfNode(analysis_ctx, suffix_op.lhs) orelse return null;
|
else => null,
|
||||||
return resolveDerefType(analysis_ctx, left_type);
|
};
|
||||||
},
|
|
||||||
.ArrayAccess => {
|
|
||||||
const left_type = resolveTypeOfNode(analysis_ctx, suffix_op.lhs) orelse return null;
|
|
||||||
return resolveBracketAccessType(analysis_ctx, left_type, .Single);
|
|
||||||
},
|
|
||||||
.Slice => {
|
|
||||||
const left_type = resolveTypeOfNode(analysis_ctx, suffix_op.lhs) orelse return null;
|
|
||||||
return resolveBracketAccessType(analysis_ctx, left_type, .Range);
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
.InfixOp => {
|
.InfixOp => {
|
||||||
const infix_op = node.cast(ast.Node.InfixOp).?;
|
const infix_op = node.cast(ast.Node.InfixOp).?;
|
||||||
switch (infix_op.op) {
|
switch (infix_op.op) {
|
||||||
.Period => {
|
.Period => {
|
||||||
// Save the child string from this tree since the tree may switch when processing
|
const rhs_str = nodeToString(handle.tree, infix_op.rhs) orelse return null;
|
||||||
// an import lhs.
|
|
||||||
var rhs_str = nodeToString(analysis_ctx.tree(), infix_op.rhs) orelse return null;
|
|
||||||
// Use the analysis context temporary arena to store the rhs string.
|
|
||||||
rhs_str = std.mem.dupe(&analysis_ctx.arena.allocator, u8, rhs_str) catch return null;
|
|
||||||
|
|
||||||
// If we are accessing a pointer type, remove one pointerness level :)
|
// If we are accessing a pointer type, remove one pointerness level :)
|
||||||
const left_type = resolveFieldAccessLhsType(
|
const left_type = try resolveFieldAccessLhsType(
|
||||||
analysis_ctx,
|
store,
|
||||||
resolveTypeOfNode(analysis_ctx, infix_op.lhs) orelse return null,
|
arena,
|
||||||
|
(try resolveTypeOfNode(store, arena, .{
|
||||||
|
.node = infix_op.lhs,
|
||||||
|
.handle = handle,
|
||||||
|
})) orelse return null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const child = getChild(analysis_ctx.tree(), left_type, rhs_str) orelse return null;
|
// @TODO Error sets
|
||||||
return resolveTypeOfNode(analysis_ctx, child);
|
if (left_type.node.id != .ContainerDecl and left_type.node.id != .Root) return null;
|
||||||
|
|
||||||
|
if (try lookupSymbolContainer(store, left_type, rhs_str, true)) |child| {
|
||||||
|
return try child.resolveType(store, arena);
|
||||||
|
} else return null;
|
||||||
},
|
},
|
||||||
.UnwrapOptional => {
|
.UnwrapOptional => {
|
||||||
const left_type = resolveTypeOfNode(analysis_ctx, infix_op.lhs) orelse return null;
|
const left_type = (try resolveTypeOfNode(store, arena, .{
|
||||||
return resolveUnwrapOptionalType(analysis_ctx, left_type);
|
.node = infix_op.lhs,
|
||||||
|
.handle = handle,
|
||||||
|
})) orelse return null;
|
||||||
|
return try resolveUnwrapOptionalType(store, arena, left_type);
|
||||||
},
|
},
|
||||||
else => {},
|
else => return null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.PrefixOp => {
|
.PrefixOp => {
|
||||||
@ -489,13 +460,16 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
.ArrayType,
|
.ArrayType,
|
||||||
.OptionalType,
|
.OptionalType,
|
||||||
.PtrType,
|
.PtrType,
|
||||||
=> return node,
|
=> return node_handle,
|
||||||
.Try => {
|
.Try => {
|
||||||
const rhs_type = resolveTypeOfNode(analysis_ctx, prefix_op.rhs) orelse return null;
|
const rhs_type = (try resolveTypeOfNode(store, arena, .{ .node = prefix_op.rhs, .handle = handle })) orelse return null;
|
||||||
switch (rhs_type.id) {
|
switch (rhs_type.node.id) {
|
||||||
.InfixOp => {
|
.InfixOp => {
|
||||||
const infix_op = rhs_type.cast(ast.Node.InfixOp).?;
|
const infix_op = rhs_type.node.cast(ast.Node.InfixOp).?;
|
||||||
if (infix_op.op == .ErrorUnion) return infix_op.rhs;
|
if (infix_op.op == .ErrorUnion) return NodeWithHandle{
|
||||||
|
.node = infix_op.rhs,
|
||||||
|
.handle = rhs_type.handle,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
@ -506,10 +480,10 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
},
|
},
|
||||||
.BuiltinCall => {
|
.BuiltinCall => {
|
||||||
const builtin_call = node.cast(ast.Node.BuiltinCall).?;
|
const builtin_call = node.cast(ast.Node.BuiltinCall).?;
|
||||||
const call_name = analysis_ctx.tree().tokenSlice(builtin_call.builtin_token);
|
const call_name = handle.tree.tokenSlice(builtin_call.builtin_token);
|
||||||
if (std.mem.eql(u8, call_name, "@This")) {
|
if (std.mem.eql(u8, call_name, "@This")) {
|
||||||
if (builtin_call.params_len != 0) return null;
|
if (builtin_call.params_len != 0) return null;
|
||||||
return analysis_ctx.in_container;
|
return innermostContainer(handle, handle.tree.token_locs[builtin_call.firstToken()].start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: https://github.com/ziglang/zig/issues/4335
|
// TODO: https://github.com/ziglang/zig/issues/4335
|
||||||
@ -528,7 +502,7 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
});
|
});
|
||||||
if (cast_map.has(call_name)) {
|
if (cast_map.has(call_name)) {
|
||||||
if (builtin_call.params_len < 1) return null;
|
if (builtin_call.params_len < 1) return null;
|
||||||
return resolveTypeOfNode(analysis_ctx, builtin_call.paramsConst()[0]);
|
return try resolveTypeOfNode(store, arena, .{ .node = builtin_call.paramsConst()[0], .handle = handle });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std.mem.eql(u8, call_name, "@import")) return null;
|
if (!std.mem.eql(u8, call_name, "@import")) return null;
|
||||||
@ -537,31 +511,30 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
const import_param = builtin_call.paramsConst()[0];
|
const import_param = builtin_call.paramsConst()[0];
|
||||||
if (import_param.id != .StringLiteral) return null;
|
if (import_param.id != .StringLiteral) return null;
|
||||||
|
|
||||||
const import_str = analysis_ctx.tree().tokenSlice(import_param.cast(ast.Node.StringLiteral).?.token);
|
const import_str = handle.tree.tokenSlice(import_param.cast(ast.Node.StringLiteral).?.token);
|
||||||
return analysis_ctx.onImport(import_str[1 .. import_str.len - 1]) catch |err| block: {
|
const new_handle = (store.resolveImport(handle, import_str[1 .. import_str.len - 1]) catch |err| block: {
|
||||||
std.debug.warn("Error {} while processing import {}\n", .{ err, import_str });
|
std.debug.warn("Error {} while processing import {}\n", .{ err, import_str });
|
||||||
break :block null;
|
return null;
|
||||||
};
|
}) orelse return null;
|
||||||
|
|
||||||
|
return NodeWithHandle{ .node = &new_handle.tree.root_node.base, .handle = new_handle };
|
||||||
},
|
},
|
||||||
.ContainerDecl => {
|
.ContainerDecl => {
|
||||||
analysis_ctx.onContainer(node) catch return null;
|
|
||||||
|
|
||||||
const container = node.cast(ast.Node.ContainerDecl).?;
|
const container = node.cast(ast.Node.ContainerDecl).?;
|
||||||
const kind = analysis_ctx.tree().token_ids[container.kind_token];
|
const kind = handle.tree.token_ids[container.kind_token];
|
||||||
|
|
||||||
if (kind == .Keyword_struct or (kind == .Keyword_union and container.init_arg_expr == .None)) {
|
if (kind == .Keyword_struct or (kind == .Keyword_union and container.init_arg_expr == .None)) {
|
||||||
return node;
|
return node_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (container.iterate(i)) |decl| : (i += 1) {
|
while (container.iterate(i)) |decl| : (i += 1) {
|
||||||
if (decl.id != .ContainerField) continue;
|
if (decl.id != .ContainerField) continue;
|
||||||
// TODO handle errors better?
|
try store.enum_completions.add(handle.tree, decl);
|
||||||
analysis_ctx.enum_completions.add(analysis_ctx.tree(), decl) catch {};
|
|
||||||
}
|
}
|
||||||
return node;
|
return node_handle;
|
||||||
},
|
},
|
||||||
.MultilineStringLiteral, .StringLiteral, .FnProto => return node,
|
.MultilineStringLiteral, .StringLiteral, .FnProto => return node_handle,
|
||||||
else => std.debug.warn("Type resolution case not implemented; {}\n", .{node.id}),
|
else => std.debug.warn("Type resolution case not implemented; {}\n", .{node.id}),
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -640,6 +613,7 @@ pub fn getFieldAccessTypeNode(
|
|||||||
if (after_period.loc.end == tokenizer.buffer.len) return try resolveFieldAccessLhsType(store, arena, current_node);
|
if (after_period.loc.end == tokenizer.buffer.len) return try resolveFieldAccessLhsType(store, arena, current_node);
|
||||||
|
|
||||||
current_node = try resolveFieldAccessLhsType(store, arena, current_node);
|
current_node = try resolveFieldAccessLhsType(store, arena, current_node);
|
||||||
|
// @TODO Error sets
|
||||||
if (current_node.node.id != .ContainerDecl and current_node.node.id != .Root) {
|
if (current_node.node.id != .ContainerDecl and current_node.node.id != .Root) {
|
||||||
// @TODO Is this ok?
|
// @TODO Is this ok?
|
||||||
return null;
|
return null;
|
||||||
@ -1141,6 +1115,22 @@ pub fn iterateSymbolsGlobal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn innermostContainer(handle: *DocumentStore.Handle, source_index: usize) NodeWithHandle {
|
||||||
|
var current = handle.document_scope.scopes[0].data.container;
|
||||||
|
if (handle.document_scope.scopes.len == 1) return .{ .node = current, .handle = handle };
|
||||||
|
|
||||||
|
for (handle.document_scope.scopes[1..]) |scope| {
|
||||||
|
if (source_index >= scope.range.start and source_index < scope.range.end) {
|
||||||
|
switch (scope.data) {
|
||||||
|
.container => |node| current = node,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scope.range.start > source_index) break;
|
||||||
|
}
|
||||||
|
return .{ .node = current, .handle = handle };
|
||||||
|
}
|
||||||
|
|
||||||
pub fn lookupSymbolGlobal(store: *DocumentStore, handle: *DocumentStore.Handle, symbol: []const u8, source_index: usize) !?DeclWithHandle {
|
pub fn lookupSymbolGlobal(store: *DocumentStore, handle: *DocumentStore.Handle, symbol: []const u8, source_index: usize) !?DeclWithHandle {
|
||||||
for (handle.document_scope.scopes) |scope| {
|
for (handle.document_scope.scopes) |scope| {
|
||||||
if (source_index >= scope.range.start and source_index < scope.range.end) {
|
if (source_index >= scope.range.start and source_index < scope.range.end) {
|
||||||
@ -1162,7 +1152,7 @@ pub fn lookupSymbolGlobal(store: *DocumentStore, handle: *DocumentStore.Handle,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scope.range.start >= source_index) return null;
|
if (scope.range.start > source_index) return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
59
src/main.zig
59
src/main.zig
@ -197,6 +197,7 @@ fn publishDiagnostics(handle: DocumentStore.Handle, config: Config) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn containerToCompletion(
|
fn containerToCompletion(
|
||||||
|
arena: *std.heap.ArenaAllocator,
|
||||||
list: *std.ArrayList(types.CompletionItem),
|
list: *std.ArrayList(types.CompletionItem),
|
||||||
container_handle: analysis.NodeWithHandle,
|
container_handle: analysis.NodeWithHandle,
|
||||||
orig_handle: *DocumentStore.Handle,
|
orig_handle: *DocumentStore.Handle,
|
||||||
@ -211,7 +212,7 @@ fn containerToCompletion(
|
|||||||
while (container.iterate(child_idx)) |child_node| : (child_idx += 1) {
|
while (container.iterate(child_idx)) |child_node| : (child_idx += 1) {
|
||||||
// Declarations in the same file do not need to be public.
|
// Declarations in the same file do not need to be public.
|
||||||
if (orig_handle == handle or analysis.isNodePublic(handle.tree, child_node)) {
|
if (orig_handle == handle or analysis.isNodePublic(handle.tree, child_node)) {
|
||||||
try nodeToCompletion(list, .{ .node = child_node, .handle = handle }, orig_handle, config);
|
try nodeToCompletion(arena, list, .{ .node = child_node, .handle = handle }, orig_handle, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,6 +245,7 @@ fn resolveVarDeclFnAlias(arena: *std.heap.ArenaAllocator, decl_handle: analysis.
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn nodeToCompletion(
|
fn nodeToCompletion(
|
||||||
|
arena: *std.heap.ArenaAllocator,
|
||||||
list: *std.ArrayList(types.CompletionItem),
|
list: *std.ArrayList(types.CompletionItem),
|
||||||
node_handle: analysis.NodeWithHandle,
|
node_handle: analysis.NodeWithHandle,
|
||||||
orig_handle: *DocumentStore.Handle,
|
orig_handle: *DocumentStore.Handle,
|
||||||
@ -262,7 +264,7 @@ fn nodeToCompletion(
|
|||||||
|
|
||||||
switch (node.id) {
|
switch (node.id) {
|
||||||
.ErrorSetDecl, .Root, .ContainerDecl => {
|
.ErrorSetDecl, .Root, .ContainerDecl => {
|
||||||
try containerToCompletion(list, node_handle, orig_handle, config);
|
try containerToCompletion(arena, list, node_handle, orig_handle, config);
|
||||||
},
|
},
|
||||||
.FnProto => {
|
.FnProto => {
|
||||||
const func = node.cast(std.zig.ast.Node.FnProto).?;
|
const func = node.cast(std.zig.ast.Node.FnProto).?;
|
||||||
@ -270,31 +272,32 @@ fn nodeToCompletion(
|
|||||||
const use_snippets = config.enable_snippets and client_capabilities.supports_snippets;
|
const use_snippets = config.enable_snippets and client_capabilities.supports_snippets;
|
||||||
|
|
||||||
const insert_text = if (use_snippets) blk: {
|
const insert_text = if (use_snippets) blk: {
|
||||||
const skip_self_param = if (func.params_len > 0) param_check: {
|
// @TODO Rebuild this.
|
||||||
var child_analysis_ctx = try analysis_ctx.clone();
|
const skip_self_param = false;
|
||||||
break :param_check switch (func.paramsConst()[0].param_type) {
|
// const skip_self_param = if (func.params_len > 0) param_check: {
|
||||||
.type_expr => |type_node| if (analysis_ctx.in_container == analysis.resolveTypeOfNode(&child_analysis_ctx, type_node))
|
// break :param_check switch (func.paramsConst()[0].param_type) {
|
||||||
true
|
// .type_expr => |type_node| if (analysis_ctx.in_container == analysis.resolveTypeOfNode(&child_analysis_ctx, type_node))
|
||||||
else if (type_node.cast(std.zig.ast.Node.PrefixOp)) |prefix_op|
|
// true
|
||||||
prefix_op.op == .PtrType and analysis_ctx.in_container == analysis.resolveTypeOfNode(&child_analysis_ctx, prefix_op.rhs)
|
// else if (type_node.cast(std.zig.ast.Node.PrefixOp)) |prefix_op|
|
||||||
else
|
// prefix_op.op == .PtrType and analysis_ctx.in_container == analysis.resolveTypeOfNode(&child_analysis_ctx, prefix_op.rhs)
|
||||||
false,
|
// else
|
||||||
else => false,
|
// false,
|
||||||
};
|
// else => false,
|
||||||
} else
|
// };
|
||||||
false;
|
// } else
|
||||||
|
// false;
|
||||||
|
|
||||||
break :blk try analysis.getFunctionSnippet(list.allocator, analysis_ctx.tree(), func, skip_self_param);
|
break :blk try analysis.getFunctionSnippet(&arena.allocator, handle.tree, func, skip_self_param);
|
||||||
} else
|
} else
|
||||||
null;
|
null;
|
||||||
|
|
||||||
const is_type_function = analysis.isTypeFunction(analysis_ctx.tree(), func);
|
const is_type_function = analysis.isTypeFunction(handle.tree, func);
|
||||||
|
|
||||||
try list.append(.{
|
try list.append(.{
|
||||||
.label = analysis_ctx.tree().tokenSlice(name_token),
|
.label = handle.tree.tokenSlice(name_token),
|
||||||
.kind = if (is_type_function) .Struct else .Function,
|
.kind = if (is_type_function) .Struct else .Function,
|
||||||
.documentation = doc,
|
.documentation = doc,
|
||||||
.detail = analysis.getFunctionSignature(analysis_ctx.tree(), func),
|
.detail = analysis.getFunctionSignature(handle.tree, func),
|
||||||
.insertText = insert_text,
|
.insertText = insert_text,
|
||||||
.insertTextFormat = if (use_snippets) .Snippet else .PlainText,
|
.insertTextFormat = if (use_snippets) .Snippet else .PlainText,
|
||||||
});
|
});
|
||||||
@ -302,18 +305,18 @@ fn nodeToCompletion(
|
|||||||
},
|
},
|
||||||
.VarDecl => {
|
.VarDecl => {
|
||||||
const var_decl = node.cast(std.zig.ast.Node.VarDecl).?;
|
const var_decl = node.cast(std.zig.ast.Node.VarDecl).?;
|
||||||
const is_const = analysis_ctx.tree().token_ids[var_decl.mut_token] == .Keyword_const;
|
const is_const = handle.tree.token_ids[var_decl.mut_token] == .Keyword_const;
|
||||||
|
|
||||||
var result = try resolveVarDeclFnAlias(analysis_ctx, node);
|
const result = try resolveVarDeclFnAlias(arena, node_handle);
|
||||||
if (result.decl != node) {
|
if (result.node != node) {
|
||||||
return try nodeToCompletion(list, &result.analysis_ctx, orig_handle, result.decl, config);
|
return try nodeToCompletion(arena, list, result, orig_handle, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
try list.append(.{
|
try list.append(.{
|
||||||
.label = analysis_ctx.tree().tokenSlice(var_decl.name_token),
|
.label = handle.tree.tokenSlice(var_decl.name_token),
|
||||||
.kind = if (is_const) .Constant else .Variable,
|
.kind = if (is_const) .Constant else .Variable,
|
||||||
.documentation = doc,
|
.documentation = doc,
|
||||||
.detail = analysis.getVariableSignature(analysis_ctx.tree(), var_decl),
|
.detail = analysis.getVariableSignature(handle.tree, var_decl),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.PrefixOp => {
|
.PrefixOp => {
|
||||||
@ -547,7 +550,7 @@ const DeclToCompletionContext = struct {
|
|||||||
fn decltoCompletion(context: DeclToCompletionContext, decl_handle: analysis.DeclWithHandle) !void {
|
fn decltoCompletion(context: DeclToCompletionContext, decl_handle: analysis.DeclWithHandle) !void {
|
||||||
switch (decl_handle.decl.*) {
|
switch (decl_handle.decl.*) {
|
||||||
.ast_node => |node| {
|
.ast_node => |node| {
|
||||||
try nodeToCompletion(context.completions, .{ .node = node, .handle = decl_handle.handle }, context.orig_handle, context.config.*);
|
try nodeToCompletion(context.arena, context.completions, .{ .node = node, .handle = decl_handle.handle }, context.orig_handle, context.config.*);
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
// @TODO The rest
|
// @TODO The rest
|
||||||
@ -590,7 +593,7 @@ fn completeFieldAccess(id: types.RequestId, handle: *DocumentStore.Handle, posit
|
|||||||
var tokenizer = std.zig.Tokenizer.init(line[range.start..range.end]);
|
var tokenizer = std.zig.Tokenizer.init(line[range.start..range.end]);
|
||||||
|
|
||||||
if (try analysis.getFieldAccessTypeNode(&document_store, &arena, handle, &tokenizer)) |node| {
|
if (try analysis.getFieldAccessTypeNode(&document_store, &arena, handle, &tokenizer)) |node| {
|
||||||
try nodeToCompletion(&completions, node, handle, config);
|
try nodeToCompletion(&arena, &completions, node, handle, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
try send(types.Response{
|
try send(types.Response{
|
||||||
@ -829,7 +832,7 @@ fn processJsonRpc(parser: *std.json.Parser, json: []const u8, config: Config) !v
|
|||||||
}
|
}
|
||||||
// Semantic highlighting
|
// Semantic highlighting
|
||||||
else if (std.mem.eql(u8, method, "textDocument/semanticTokens")) {
|
else if (std.mem.eql(u8, method, "textDocument/semanticTokens")) {
|
||||||
// @TODO Implement this (we dont get here from vscode atm even when we get the client capab.)
|
// TODO Implement this (we dont get here from vscode atm even when we get the client capab.)
|
||||||
return try respondGeneric(id, empty_array_response);
|
return try respondGeneric(id, empty_array_response);
|
||||||
}
|
}
|
||||||
// Autocomplete / Signatures
|
// Autocomplete / Signatures
|
||||||
|
Loading…
Reference in New Issue
Block a user