Completion for index label in for loops and fix for function snippets

This commit is contained in:
Luuk de Gram 2021-03-09 19:53:59 +01:00
parent 858f3cb282
commit 3ac6c82b9a
No known key found for this signature in database
GPG Key ID: A002B174963DBB7D
3 changed files with 44 additions and 15 deletions

View File

@ -104,7 +104,12 @@ pub fn getFunctionSignature(tree: ast.Tree, func: ast.full.FnProto) []const u8 {
} }
/// Gets a function snippet insert text /// Gets a function snippet insert text
pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: ast.Tree, func: ast.full.FnProto, skip_self_param: bool) ![]const u8 { pub fn getFunctionSnippet(
allocator: *std.mem.Allocator,
tree: ast.Tree,
func: ast.full.FnProto,
skip_self_param: bool,
) ![]const u8 {
const name_index = func.name_token orelse unreachable; const name_index = func.name_token orelse unreachable;
var buffer = std.ArrayList(u8).init(allocator); var buffer = std.ArrayList(u8).init(allocator);
@ -118,11 +123,15 @@ pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: ast.Tree, func: a
const token_tags = tree.tokens.items(.tag); const token_tags = tree.tokens.items(.tag);
var it = func.iterate(tree); var it = func.iterate(tree);
while (it.next()) |param| { var i: usize = 0;
if (skip_self_param and it.param_i - 1 == 0) continue; while (it.next()) |param| : (i += 1) {
if (it.param_i - 1 != @boolToInt(skip_self_param)) try buffer.appendSlice(", ${") else try buffer.appendSlice("${"); if (skip_self_param and i == 0) continue;
if (i != @boolToInt(skip_self_param))
try buffer.appendSlice(", ${")
else
try buffer.appendSlice("${");
try buf_stream.print("{d}:", .{it.param_i}); try buf_stream.print("{d}:", .{i + 1});
if (param.comptime_noalias) |token_index| { if (param.comptime_noalias) |token_index| {
if (token_tags[token_index] == .keyword_comptime) if (token_tags[token_index] == .keyword_comptime)
@ -141,7 +150,7 @@ pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: ast.Tree, func: a
try buffer.appendSlice("anytype") try buffer.appendSlice("anytype")
else else
try buffer.appendSlice("..."); try buffer.appendSlice("...");
} else { } else if (param.type_expr != 0) {
var curr_token = tree.firstToken(param.type_expr); var curr_token = tree.firstToken(param.type_expr);
var end_token = tree.lastToken(param.type_expr); var end_token = tree.lastToken(param.type_expr);
while (curr_token <= end_token) : (curr_token += 1) { while (curr_token <= end_token) : (curr_token += 1) {
@ -152,7 +161,8 @@ pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: ast.Tree, func: a
try buffer.appendSlice(tree.tokenSlice(curr_token)); try buffer.appendSlice(tree.tokenSlice(curr_token));
if (is_comma or tag == .keyword_const) try buffer.append(' '); if (is_comma or tag == .keyword_const) try buffer.append(' ');
} }
} } else unreachable;
try buffer.append('}'); try buffer.append('}');
} }
try buffer.append(')'); try buffer.append(')');
@ -780,13 +790,14 @@ pub fn resolveTypeOfNodeInternal(
// Bind type params to the expressions passed in txhe calls. // Bind type params to the expressions passed in txhe calls.
const param_len = std.math.min(call.ast.params.len + @boolToInt(has_self_param), fn_decl.ast.params.len); const param_len = std.math.min(call.ast.params.len + @boolToInt(has_self_param), fn_decl.ast.params.len);
while (it.next()) |decl_param| { var i: usize = 0;
if (it.param_i - 1 == 0 and has_self_param) continue; while (it.next()) |decl_param| : (i += 1) {
if (it.param_i - 1 >= param_len) break; if (i == 0 and has_self_param) continue;
if (i >= param_len) break;
if (!typeIsType(decl.handle.tree, decl_param.type_expr)) continue; if (!typeIsType(decl.handle.tree, decl_param.type_expr)) continue;
const call_param_type = (try resolveTypeOfNodeInternal(store, arena, .{ const call_param_type = (try resolveTypeOfNodeInternal(store, arena, .{
.node = call.ast.params[it.param_i - 1 - @boolToInt(has_self_param)], .node = call.ast.params[i - @boolToInt(has_self_param)],
.handle = handle, .handle = handle,
}, bound_type_params)) orelse continue; }, bound_type_params)) orelse continue;
if (!call_param_type.type.is_type_val) continue; if (!call_param_type.type.is_type_val) continue;
@ -1921,6 +1932,7 @@ pub const Declaration = union(enum) {
identifier: ast.TokenIndex, identifier: ast.TokenIndex,
array_expr: ast.Node.Index, array_expr: ast.Node.Index,
}, },
array_index: ast.TokenIndex,
switch_payload: struct { switch_payload: struct {
node: ast.TokenIndex, node: ast.TokenIndex,
switch_expr: ast.Node.Index, switch_expr: ast.Node.Index,
@ -1941,6 +1953,7 @@ pub const DeclWithHandle = struct {
.param_decl => |p| p.name_token.?, .param_decl => |p| p.name_token.?,
.pointer_payload => |pp| pp.name, .pointer_payload => |pp| pp.name,
.array_payload => |ap| ap.identifier, .array_payload => |ap| ap.identifier,
.array_index => |ai| ai,
.switch_payload => |sp| sp.node, .switch_payload => |sp| sp.node,
.label_decl => |ld| ld, .label_decl => |ld| ld,
}; };
@ -2008,6 +2021,10 @@ pub const DeclWithHandle = struct {
.Single, .Single,
bound_type_params, bound_type_params,
), ),
.array_index => TypeWithHandle{
.type = .{ .data = .primitive, .is_type_val = true },
.handle = self.handle,
},
.label_decl => return null, .label_decl => return null,
.switch_payload => |pay| { .switch_payload => |pay| {
if (pay.items.len == 0) return null; if (pay.items.len == 0) return null;
@ -2024,7 +2041,7 @@ pub const DeclWithHandle = struct {
if (scope.decls.getEntry(tree.tokenSlice(main_tokens[pay.items[0]]))) |candidate| { if (scope.decls.getEntry(tree.tokenSlice(main_tokens[pay.items[0]]))) |candidate| {
switch (candidate.value) { switch (candidate.value) {
.ast_node => |node| { .ast_node => |node| {
if (containerField(tree, node)) |container_field| { if (containerField(switch_expr_type.handle.tree, node)) |container_field| {
if (container_field.ast.type_expr != 0) { if (container_field.ast.type_expr != 0) {
return ((try resolveTypeOfNodeInternal( return ((try resolveTypeOfNodeInternal(
store, store,
@ -2919,7 +2936,7 @@ fn makeScopeInternal(
if (token_tags[name_token + 1] == .comma) { if (token_tags[name_token + 1] == .comma) {
const index_token = name_token + 2; const index_token = name_token + 2;
std.debug.assert(token_tags[index_token] == .identifier); std.debug.assert(token_tags[index_token] == .identifier);
if (try scope.decls.fetchPut(tree.tokenSlice(index_token), .{ .label_decl = index_token })) |existing| { if (try scope.decls.fetchPut(tree.tokenSlice(index_token), .{ .array_index = index_token })) |existing| {
// TODO Record a redefinition error // TODO Record a redefinition error
} }
} }
@ -2955,7 +2972,7 @@ fn makeScopeInternal(
const extra = tree.extraData(data[node_idx].rhs, ast.Node.SubRange); const extra = tree.extraData(data[node_idx].rhs, ast.Node.SubRange);
const cases = tree.extra_data[extra.start..extra.end]; const cases = tree.extra_data[extra.start..extra.end];
for(cases)|case| { for (cases) |case| {
const switch_case: ast.full.SwitchCase = switch (tags[case]) { const switch_case: ast.full.SwitchCase = switch (tags[case]) {
.switch_case => tree.switchCase(case), .switch_case => tree.switchCase(case),
.switch_case_one => tree.switchCaseOne(case), .switch_case_one => tree.switchCaseOne(case),

View File

@ -391,6 +391,8 @@ fn nodeToCompletion(
var it = func.iterate(tree); var it = func.iterate(tree);
const param = it.next().?; const param = it.next().?;
if (param.type_expr == 0) break :param_check false;
if (try analysis.resolveTypeOfNode(&document_store, arena, .{ if (try analysis.resolveTypeOfNode(&document_store, arena, .{
.node = param.type_expr, .node = param.type_expr,
.handle = handle, .handle = handle,
@ -641,6 +643,10 @@ fn hoverSymbol(
try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{handle.tree.tokenSlice(payload.identifier)}) try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{handle.tree.tokenSlice(payload.identifier)})
else else
try std.fmt.allocPrint(&arena.allocator, "{s}", .{handle.tree.tokenSlice(payload.identifier)}), try std.fmt.allocPrint(&arena.allocator, "{s}", .{handle.tree.tokenSlice(payload.identifier)}),
.array_index => |payload| if (hover_kind == .Markdown)
try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{handle.tree.tokenSlice(payload)})
else
try std.fmt.allocPrint(&arena.allocator, "{s}", .{handle.tree.tokenSlice(payload)}),
.switch_payload => |payload| if (hover_kind == .Markdown) .switch_payload => |payload| if (hover_kind == .Markdown)
try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{tree.tokenSlice(payload.node)}) try std.fmt.allocPrint(&arena.allocator, "```zig\n{s}\n```", .{tree.tokenSlice(payload.node)})
else else
@ -957,6 +963,12 @@ fn declToCompletion(context: DeclToCompletionContext, decl_handle: analysis.Decl
.kind = .Variable, .kind = .Variable,
}); });
}, },
.array_index => |payload| {
try context.completions.append(.{
.label = tree.tokenSlice(payload),
.kind = .Variable,
});
},
.switch_payload => |payload| { .switch_payload => |payload| {
try context.completions.append(.{ try context.completions.append(.{
.label = tree.tokenSlice(payload.node), .label = tree.tokenSlice(payload.node),

View File

@ -585,7 +585,7 @@ pub fn symbolReferences(
return; return;
}; };
}, },
.pointer_payload, .switch_payload, .array_payload => { .pointer_payload, .switch_payload, .array_payload, .array_index => {
if (include_decl) { if (include_decl) {
try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler); try tokenReference(curr_handle, decl_handle.nameToken(), encoding, context, handler);
} }