More .
completion
This commit is contained in:
parent
c89431c625
commit
e1d90a1a1b
@ -1513,6 +1513,26 @@ pub fn getFieldAccessType(analyser: *Analyser, handle: *const DocumentStore.Hand
|
|||||||
|
|
||||||
current_type = (try analyser.resolveBracketAccessType(current_type orelse return null, if (is_range) .Range else .Single)) orelse return null;
|
current_type = (try analyser.resolveBracketAccessType(current_type orelse return null, if (is_range) .Range else .Single)) orelse return null;
|
||||||
},
|
},
|
||||||
|
.builtin => {
|
||||||
|
const curr_handle = if (current_type == null) handle else current_type.?.handle;
|
||||||
|
if (std.mem.eql(u8, tokenizer.buffer[tok.loc.start..tok.loc.end], "@import")) {
|
||||||
|
if (tokenizer.next().tag != .l_paren) return null;
|
||||||
|
var import_str_tok = tokenizer.next(); // should be the .string_literal
|
||||||
|
if (import_str_tok.tag != .string_literal) return null;
|
||||||
|
if (import_str_tok.loc.end - import_str_tok.loc.start < 2) return null;
|
||||||
|
var import_str = offsets.locToSlice(tokenizer.buffer, .{
|
||||||
|
.start = import_str_tok.loc.start + 1,
|
||||||
|
.end = import_str_tok.loc.end - 1,
|
||||||
|
});
|
||||||
|
const uri = try analyser.store.uriFromImportStr(analyser.arena, curr_handle.*, import_str) orelse return null;
|
||||||
|
const node_handle = analyser.store.getOrLoadHandle(uri) orelse return null;
|
||||||
|
current_type = TypeWithHandle.typeVal(NodeWithHandle{ .handle = node_handle, .node = 0 });
|
||||||
|
_ = tokenizer.next(); // eat the .r_paren
|
||||||
|
} else {
|
||||||
|
log.debug("Unhandled builtin: {s}", .{offsets.locToSlice(tokenizer.buffer, tok.loc)});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
log.debug("Unimplemented token: {}", .{tok.tag});
|
log.debug("Unimplemented token: {}", .{tok.tag});
|
||||||
return null;
|
return null;
|
||||||
|
@ -728,14 +728,15 @@ fn kindToSortScore(kind: types.CompletionItemKind) ?[]const u8 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a decl that is an ast_node, tag .simple_var_decl, and it's rhs is a container adds the container fields to completions
|
/// Given a root node decl or a .simple_var_decl (const MyStruct = struct {..}) node decl, adds it's `.container_field*`s to completions
|
||||||
pub fn addStructInitNodeFields(server: *Server, decl: Analyser.DeclWithHandle, completions: *std.ArrayListUnmanaged(types.CompletionItem)) error{OutOfMemory}!void {
|
pub fn addStructInitNodeFields(server: *Server, decl: Analyser.DeclWithHandle, completions: *std.ArrayListUnmanaged(types.CompletionItem)) error{OutOfMemory}!void {
|
||||||
const node = switch (decl.decl.*) {
|
const node = switch (decl.decl.*) {
|
||||||
.ast_node => |ast_node| ast_node,
|
.ast_node => |ast_node| ast_node,
|
||||||
else => return,
|
else => return,
|
||||||
};
|
};
|
||||||
const node_tags = decl.handle.tree.nodes.items(.tag);
|
const node_tags = decl.handle.tree.nodes.items(.tag);
|
||||||
if (node_tags[node] != .simple_var_decl) return;
|
switch (node_tags[node]) {
|
||||||
|
.simple_var_decl => {
|
||||||
const node_data = decl.handle.tree.nodes.items(.data)[node];
|
const node_data = decl.handle.tree.nodes.items(.data)[node];
|
||||||
if (node_data.rhs != 0) {
|
if (node_data.rhs != 0) {
|
||||||
var buffer: [2]Ast.Node.Index = undefined;
|
var buffer: [2]Ast.Node.Index = undefined;
|
||||||
@ -751,6 +752,21 @@ pub fn addStructInitNodeFields(server: *Server, decl: Analyser.DeclWithHandle, c
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
.root => {
|
||||||
|
for (decl.handle.tree.rootDecls()) |root_node| {
|
||||||
|
const field = decl.handle.tree.fullContainerField(@intCast(u32, root_node)) orelse continue;
|
||||||
|
try completions.append(server.arena.allocator(), .{
|
||||||
|
.label = decl.handle.tree.tokenSlice(field.ast.main_token),
|
||||||
|
.kind = if (field.ast.tuple_like) .Enum else .Field,
|
||||||
|
.detail = Analyser.getContainerFieldSignature(decl.handle.tree, field),
|
||||||
|
.insertText = decl.handle.tree.tokenSlice(field.ast.main_token),
|
||||||
|
.insertTextFormat = .PlainText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn completeDot(server: *Server, handle: *const DocumentStore.Handle, source_index: usize) error{OutOfMemory}![]types.CompletionItem {
|
fn completeDot(server: *Server, handle: *const DocumentStore.Handle, source_index: usize) error{OutOfMemory}![]types.CompletionItem {
|
||||||
@ -820,7 +836,7 @@ fn completeDot(server: *Server, handle: *const DocumentStore.Handle, source_inde
|
|||||||
|
|
||||||
var completions = std.ArrayListUnmanaged(types.CompletionItem){};
|
var completions = std.ArrayListUnmanaged(types.CompletionItem){};
|
||||||
|
|
||||||
if (identifier_loc.start != identifier_original_start) { // field access
|
if (identifier_loc.start != identifier_original_start) { // path.to.MyStruct{.<cursor> => use field access resolution
|
||||||
const possible_decls = (try server.getSymbolFieldAccesses(handle, identifier_loc.end, identifier_loc));
|
const possible_decls = (try server.getSymbolFieldAccesses(handle, identifier_loc.end, identifier_loc));
|
||||||
if (possible_decls) |decls| {
|
if (possible_decls) |decls| {
|
||||||
for (decls) |decl| {
|
for (decls) |decl| {
|
||||||
@ -836,7 +852,7 @@ fn completeDot(server: *Server, handle: *const DocumentStore.Handle, source_inde
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // var_access, but also field_access if the node's rhs is an alias, eg const MyStruct = path.to.MyStruct;
|
} else { // MyStruct{.<cursor> => use var resolution (supports only one level of indirection)
|
||||||
const maybe_decl = try server.analyser.lookupSymbolGlobal(handle, tree.source[identifier_loc.start..identifier_loc.end], identifier_loc.end);
|
const maybe_decl = try server.analyser.lookupSymbolGlobal(handle, tree.source[identifier_loc.start..identifier_loc.end], identifier_loc.end);
|
||||||
if (maybe_decl) |local_decl| {
|
if (maybe_decl) |local_decl| {
|
||||||
const nodes_tags = handle.tree.nodes.items(.tag);
|
const nodes_tags = handle.tree.nodes.items(.tag);
|
||||||
@ -844,7 +860,29 @@ fn completeDot(server: *Server, handle: *const DocumentStore.Handle, source_inde
|
|||||||
const node_data = nodes_data[local_decl.decl.ast_node];
|
const node_data = nodes_data[local_decl.decl.ast_node];
|
||||||
if (node_data.rhs != 0) {
|
if (node_data.rhs != 0) {
|
||||||
switch (nodes_tags[node_data.rhs]) {
|
switch (nodes_tags[node_data.rhs]) {
|
||||||
.field_access => { // decl is an alias, ie const MyStruct = path.to.MyStruct;
|
// decl is `const Alias = @import("MyStruct.zig");`
|
||||||
|
.builtin_call_two => {
|
||||||
|
var buffer: [2]Ast.Node.Index = undefined;
|
||||||
|
const params = ast.builtinCallParams(tree, node_data.rhs, &buffer).?;
|
||||||
|
|
||||||
|
const main_tokens = tree.nodes.items(.main_token);
|
||||||
|
const call_name = tree.tokenSlice(main_tokens[node_data.rhs]);
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, call_name, "@import")) {
|
||||||
|
if (params.len == 0) break :struct_init;
|
||||||
|
const import_param = params[0];
|
||||||
|
if (nodes_tags[import_param] != .string_literal) break :struct_init;
|
||||||
|
|
||||||
|
const import_str = tree.tokenSlice(main_tokens[import_param]);
|
||||||
|
const import_uri = (try server.document_store.uriFromImportStr(allocator, handle.*, import_str[1 .. import_str.len - 1])) orelse break :struct_init;
|
||||||
|
|
||||||
|
const node_handle = server.document_store.getOrLoadHandle(import_uri) orelse break :struct_init;
|
||||||
|
var decl = Analyser.Declaration{ .ast_node = 0 };
|
||||||
|
try addStructInitNodeFields(server, Analyser.DeclWithHandle{ .handle = node_handle, .decl = &decl }, &completions);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// decl is `const Alias = path.to.MyStruct` or `const Alias = @import("file.zig").MyStruct;`
|
||||||
|
.field_access => {
|
||||||
const node_loc = offsets.nodeToLoc(tree, node_data.rhs);
|
const node_loc = offsets.nodeToLoc(tree, node_data.rhs);
|
||||||
const possible_decls = (try server.getSymbolFieldAccesses(handle, node_loc.end, node_loc));
|
const possible_decls = (try server.getSymbolFieldAccesses(handle, node_loc.end, node_loc));
|
||||||
if (possible_decls) |decls| {
|
if (possible_decls) |decls| {
|
||||||
@ -862,6 +900,9 @@ fn completeDot(server: *Server, handle: *const DocumentStore.Handle, source_inde
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// decl is `const AliasB = AliasA;` (alias of an alias)
|
||||||
|
//.identifier => {},
|
||||||
|
// decl is `const MyStruct = struct {..}` which is a .simple_var_decl (check is in addStructInitNodeFields)
|
||||||
else => try addStructInitNodeFields(server, local_decl, &completions),
|
else => try addStructInitNodeFields(server, local_decl, &completions),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user