Store trees in handles
This commit is contained in:
parent
fbcf2abfd2
commit
c6fa528af4
@ -262,10 +262,10 @@ fn findReturnStatement(tree: *ast.Tree, fn_decl: *ast.Node.FnProto) ?*ast.Node.C
|
||||
|
||||
/// Resolves the return type of a function
|
||||
fn resolveReturnType(analysis_ctx: *AnalysisContext, fn_decl: *ast.Node.FnProto) ?*ast.Node {
|
||||
if (isTypeFunction(analysis_ctx.tree, fn_decl) and fn_decl.body_node != null) {
|
||||
if (isTypeFunction(analysis_ctx.tree(), fn_decl) and fn_decl.body_node != null) {
|
||||
// If this is a type function and it only contains a single return statement that returns
|
||||
// a container declaration, we will return that declaration.
|
||||
const ret = findReturnStatement(analysis_ctx.tree, fn_decl) orelse return null;
|
||||
const ret = findReturnStatement(analysis_ctx.tree(), fn_decl) orelse return null;
|
||||
if (ret.rhs) |rhs|
|
||||
if (resolveTypeOfNode(analysis_ctx, rhs)) |res_rhs| switch (res_rhs.id) {
|
||||
.ContainerDecl => {
|
||||
@ -293,7 +293,7 @@ pub fn resolveTypeOfNode(analysis_ctx: *AnalysisContext, node: *ast.Node) ?*ast.
|
||||
return resolveTypeOfNode(analysis_ctx, vari.type_node orelse vari.init_node.?) orelse null;
|
||||
},
|
||||
.Identifier => {
|
||||
if (getChildOfSlice(analysis_ctx.tree, analysis_ctx.scope_nodes, analysis_ctx.tree.getNodeSource(node))) |child| {
|
||||
if (getChildOfSlice(analysis_ctx.tree(), analysis_ctx.scope_nodes, analysis_ctx.tree().getNodeSource(node))) |child| {
|
||||
return resolveTypeOfNode(analysis_ctx, child);
|
||||
} else return null;
|
||||
},
|
||||
@ -323,11 +323,11 @@ pub fn resolveTypeOfNode(analysis_ctx: *AnalysisContext, node: *ast.Node) ?*ast.
|
||||
.Period => {
|
||||
// Save the child string from this tree since the tree may switch when processing
|
||||
// an import lhs.
|
||||
var rhs_str = nodeToString(analysis_ctx.tree, infix_op.rhs) orelse return null;
|
||||
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;
|
||||
const left = resolveTypeOfNode(analysis_ctx, infix_op.lhs) orelse return null;
|
||||
const child = getChild(analysis_ctx.tree, left, rhs_str) orelse return null;
|
||||
const child = getChild(analysis_ctx.tree(), left, rhs_str) orelse return null;
|
||||
return resolveTypeOfNode(analysis_ctx, child);
|
||||
},
|
||||
else => {},
|
||||
@ -338,7 +338,7 @@ pub fn resolveTypeOfNode(analysis_ctx: *AnalysisContext, node: *ast.Node) ?*ast.
|
||||
switch (prefix_op.op) {
|
||||
.SliceType, .ArrayType => return node,
|
||||
.PtrType => {
|
||||
const op_token_id = analysis_ctx.tree.token_ids[prefix_op.op_token];
|
||||
const op_token_id = analysis_ctx.tree().token_ids[prefix_op.op_token];
|
||||
switch (op_token_id) {
|
||||
.Asterisk => return resolveTypeOfNode(analysis_ctx, prefix_op.rhs),
|
||||
.LBracket, .AsteriskAsterisk => return null,
|
||||
@ -361,7 +361,7 @@ pub fn resolveTypeOfNode(analysis_ctx: *AnalysisContext, node: *ast.Node) ?*ast.
|
||||
},
|
||||
.BuiltinCall => {
|
||||
const builtin_call = node.cast(ast.Node.BuiltinCall).?;
|
||||
const call_name = analysis_ctx.tree.tokenSlice(builtin_call.builtin_token);
|
||||
const call_name = analysis_ctx.tree().tokenSlice(builtin_call.builtin_token);
|
||||
if (std.mem.eql(u8, call_name, "@This")) {
|
||||
if (builtin_call.params_len != 0) return null;
|
||||
return analysis_ctx.in_container;
|
||||
@ -373,7 +373,7 @@ pub fn resolveTypeOfNode(analysis_ctx: *AnalysisContext, node: *ast.Node) ?*ast.
|
||||
const import_param = builtin_call.paramsConst()[0];
|
||||
if (import_param.id != .StringLiteral) return null;
|
||||
|
||||
const import_str = analysis_ctx.tree.tokenSlice(import_param.cast(ast.Node.StringLiteral).?.token);
|
||||
const import_str = analysis_ctx.tree().tokenSlice(import_param.cast(ast.Node.StringLiteral).?.token);
|
||||
return analysis_ctx.onImport(import_str[1 .. import_str.len - 1]) catch |err| block: {
|
||||
std.debug.warn("Error {} while processing import {}\n", .{ err, import_str });
|
||||
break :block null;
|
||||
@ -442,7 +442,7 @@ pub fn getFieldAccessTypeNode(
|
||||
switch (next.id) {
|
||||
.Eof => return current_node,
|
||||
.Identifier => {
|
||||
if (getChildOfSlice(analysis_ctx.tree, analysis_ctx.scope_nodes, tokenizer.buffer[next.loc.start..next.loc.end])) |child| {
|
||||
if (getChildOfSlice(analysis_ctx.tree(), analysis_ctx.scope_nodes, tokenizer.buffer[next.loc.start..next.loc.end])) |child| {
|
||||
if (resolveTypeOfNode(analysis_ctx, child)) |node_type| {
|
||||
current_node = node_type;
|
||||
} else return null;
|
||||
@ -456,7 +456,7 @@ pub fn getFieldAccessTypeNode(
|
||||
// TODO: This works for now, maybe we should filter based on the partial identifier ourselves?
|
||||
if (after_period.loc.end == line_length) return current_node;
|
||||
|
||||
if (getChild(analysis_ctx.tree, current_node, tokenizer.buffer[after_period.loc.start..after_period.loc.end])) |child| {
|
||||
if (getChild(analysis_ctx.tree(), current_node, tokenizer.buffer[after_period.loc.start..after_period.loc.end])) |child| {
|
||||
if (resolveTypeOfNode(analysis_ctx, child)) |child_type| {
|
||||
current_node = child_type;
|
||||
} else return null;
|
||||
|
@ -9,15 +9,11 @@ pub const Handle = struct {
|
||||
document: types.TextDocument,
|
||||
count: usize,
|
||||
import_uris: std.ArrayList([]const u8),
|
||||
tree: *std.zig.ast.Tree,
|
||||
|
||||
pub fn uri(handle: Handle) []const u8 {
|
||||
return handle.document.uri;
|
||||
}
|
||||
|
||||
/// Returns a zig AST, with all its errors.
|
||||
pub fn tree(handle: Handle, allocator: *std.mem.Allocator) !*std.zig.ast.Tree {
|
||||
return try std.zig.parse(allocator, handle.document.text);
|
||||
}
|
||||
};
|
||||
|
||||
allocator: *std.mem.Allocator,
|
||||
@ -45,9 +41,11 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) !*Handle {
|
||||
.text = text,
|
||||
.mem = text,
|
||||
},
|
||||
.tree = try std.zig.parse(self.allocator, text),
|
||||
};
|
||||
const kv = try self.handles.getOrPutValue(uri, handle);
|
||||
return kv.value;
|
||||
|
||||
try self.handles.putNoClobber(uri, handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
pub fn openDocument(self: *DocumentStore, uri: []const u8, text: []const u8) !*Handle {
|
||||
@ -73,6 +71,8 @@ fn decrementCount(self: *DocumentStore, uri: []const u8) void {
|
||||
return;
|
||||
|
||||
std.debug.warn("Freeing document: {}\n", .{uri});
|
||||
|
||||
entry.value.tree.deinit();
|
||||
self.allocator.free(entry.value.document.mem);
|
||||
|
||||
for (entry.value.import_uris.items) |import_uri| {
|
||||
@ -102,8 +102,11 @@ pub fn getHandle(self: *DocumentStore, uri: []const u8) ?*Handle {
|
||||
}
|
||||
|
||||
// Check if the document text is now sane, move it to sane_text if so.
|
||||
fn removeOldImports(self: *DocumentStore, handle: *Handle, zig_lib_path: ?[]const u8) !void {
|
||||
fn refreshDocument(self: *DocumentStore, handle: *Handle, zig_lib_path: ?[]const u8) !void {
|
||||
std.debug.warn("New text for document {}\n", .{handle.uri()});
|
||||
handle.tree.deinit();
|
||||
handle.tree = try std.zig.parse(self.allocator, handle.document.text);
|
||||
|
||||
// TODO: Better algorithm or data structure?
|
||||
// Removing the imports is costly since they live in an array list
|
||||
// Perhaps we should use an AutoHashMap([]const u8, {}) ?
|
||||
@ -111,14 +114,11 @@ fn removeOldImports(self: *DocumentStore, handle: *Handle, zig_lib_path: ?[]cons
|
||||
// Try to detect removed imports and decrement their counts.
|
||||
if (handle.import_uris.items.len == 0) return;
|
||||
|
||||
const tree = try handle.tree(self.allocator);
|
||||
defer tree.deinit();
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
var import_strs = std.ArrayList([]const u8).init(&arena.allocator);
|
||||
try analysis.collectImports(&import_strs, tree);
|
||||
try analysis.collectImports(&import_strs, handle.tree);
|
||||
|
||||
const still_exist = try arena.allocator.alloc(bool, handle.import_uris.items.len);
|
||||
for (still_exist) |*ex| {
|
||||
@ -150,7 +150,7 @@ fn removeOldImports(self: *DocumentStore, handle: *Handle, zig_lib_path: ?[]cons
|
||||
const uri = handle.import_uris.orderedRemove(idx - offset);
|
||||
offset += 1;
|
||||
|
||||
self.closeDocument(uri);
|
||||
self.decrementCount(uri);
|
||||
self.allocator.free(uri);
|
||||
}
|
||||
}
|
||||
@ -213,7 +213,7 @@ pub fn applyChanges(
|
||||
}
|
||||
}
|
||||
|
||||
try self.removeOldImports(handle, zig_lib_path);
|
||||
try self.refreshDocument(handle, zig_lib_path);
|
||||
}
|
||||
|
||||
pub fn uriFromImportStr(
|
||||
@ -254,16 +254,19 @@ pub const AnalysisContext = struct {
|
||||
// This arena is used for temporary allocations while analyzing,
|
||||
// not for the tree allocations.
|
||||
arena: *std.heap.ArenaAllocator,
|
||||
tree: *std.zig.ast.Tree,
|
||||
scope_nodes: []*std.zig.ast.Node,
|
||||
in_container: *std.zig.ast.Node,
|
||||
std_uri: ?[]const u8,
|
||||
|
||||
pub fn tree(self: AnalysisContext) *std.zig.ast.Tree {
|
||||
return self.handle.tree;
|
||||
}
|
||||
|
||||
fn refreshScopeNodes(self: *AnalysisContext) !void {
|
||||
var scope_nodes = std.ArrayList(*std.zig.ast.Node).init(&self.arena.allocator);
|
||||
try analysis.addChildrenNodes(&scope_nodes, self.tree, &self.tree.root_node.base);
|
||||
try analysis.addChildrenNodes(&scope_nodes, self.tree(), &self.tree().root_node.base);
|
||||
self.scope_nodes = scope_nodes.items;
|
||||
self.in_container = &self.tree.root_node.base;
|
||||
self.in_container = &self.tree().root_node.base;
|
||||
}
|
||||
|
||||
pub fn onContainer(self: *AnalysisContext, container: *std.zig.ast.Node.ContainerDecl) !void {
|
||||
@ -271,7 +274,7 @@ pub const AnalysisContext = struct {
|
||||
self.in_container = &container.base;
|
||||
|
||||
var scope_nodes = std.ArrayList(*std.zig.ast.Node).init(&self.arena.allocator);
|
||||
try analysis.addChildrenNodes(&scope_nodes, self.tree, &container.base);
|
||||
try analysis.addChildrenNodes(&scope_nodes, self.tree(), &container.base);
|
||||
self.scope_nodes = scope_nodes.items;
|
||||
}
|
||||
}
|
||||
@ -295,11 +298,8 @@ pub const AnalysisContext = struct {
|
||||
// If we did, set our new handle and return the parsed tree root node.
|
||||
if (std.mem.eql(u8, uri, final_uri)) {
|
||||
self.handle = self.store.getHandle(final_uri) orelse return null;
|
||||
|
||||
self.tree.deinit();
|
||||
self.tree = try self.handle.tree(allocator);
|
||||
try self.refreshScopeNodes();
|
||||
return &self.tree.root_node.base;
|
||||
return &self.tree().root_node.base;
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,11 +309,8 @@ pub const AnalysisContext = struct {
|
||||
// If it is, increment the count, set our new handle and return the parsed tree root node.
|
||||
new_handle.count += 1;
|
||||
self.handle = new_handle;
|
||||
|
||||
self.tree.deinit();
|
||||
self.tree = try self.handle.tree(allocator);
|
||||
try self.refreshScopeNodes();
|
||||
return &self.tree.root_node.base;
|
||||
return &self.tree().root_node.base;
|
||||
}
|
||||
|
||||
// New document, read the file then call into openDocument.
|
||||
@ -341,38 +338,27 @@ pub const AnalysisContext = struct {
|
||||
try self.handle.import_uris.append(final_uri);
|
||||
consumed_final_uri = true;
|
||||
|
||||
// Swap handles and get new tree.
|
||||
// Swap handles.
|
||||
// This takes ownership of the passed uri and text.
|
||||
const duped_final_uri = try std.mem.dupe(allocator, u8, final_uri);
|
||||
errdefer allocator.free(duped_final_uri);
|
||||
self.handle = try newDocument(self.store, duped_final_uri, file_contents);
|
||||
}
|
||||
|
||||
// Free old tree, add new one if it exists.
|
||||
// If we return null, no one should access the tree.
|
||||
self.tree.deinit();
|
||||
self.tree = try self.handle.tree(allocator);
|
||||
try self.refreshScopeNodes();
|
||||
return &self.tree.root_node.base;
|
||||
return &self.tree().root_node.base;
|
||||
}
|
||||
|
||||
pub fn clone(self: *AnalysisContext) !AnalysisContext {
|
||||
// Create a new tree so it can be destroyed by the cloned AnalysisContext without affecting the original
|
||||
const tree = try self.handle.tree(self.store.allocator);
|
||||
pub fn clone(self: *AnalysisContext) AnalysisContext {
|
||||
return AnalysisContext{
|
||||
.store = self.store,
|
||||
.handle = self.handle,
|
||||
.arena = self.arena,
|
||||
.tree = tree,
|
||||
.scope_nodes = self.scope_nodes,
|
||||
.in_container = self.in_container,
|
||||
.std_uri = self.std_uri,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *AnalysisContext) void {
|
||||
self.tree.deinit();
|
||||
}
|
||||
};
|
||||
|
||||
pub fn stdUriFromLibPath(allocator: *std.mem.Allocator, zig_lib_path: ?[]const u8) !?[]const u8 {
|
||||
@ -399,17 +385,14 @@ pub fn analysisContext(
|
||||
position: usize,
|
||||
zig_lib_path: ?[]const u8,
|
||||
) !AnalysisContext {
|
||||
const tree = try handle.tree(self.allocator);
|
||||
|
||||
var scope_nodes = std.ArrayList(*std.zig.ast.Node).init(&arena.allocator);
|
||||
const in_container = try analysis.declsFromIndex(arena, &scope_nodes, tree, position);
|
||||
const in_container = try analysis.declsFromIndex(arena, &scope_nodes, handle.tree, position);
|
||||
|
||||
const std_uri = try stdUriFromLibPath(&arena.allocator, zig_lib_path);
|
||||
return AnalysisContext{
|
||||
.store = self,
|
||||
.handle = handle,
|
||||
.arena = arena,
|
||||
.tree = tree,
|
||||
.scope_nodes = scope_nodes.items,
|
||||
.in_container = in_container,
|
||||
.std_uri = std_uri,
|
||||
|
45
src/main.zig
45
src/main.zig
@ -91,8 +91,7 @@ fn astLocationToRange(loc: std.zig.ast.Tree.Location) types.Range {
|
||||
}
|
||||
|
||||
fn publishDiagnostics(handle: DocumentStore.Handle, config: Config) !void {
|
||||
const tree = try handle.tree(allocator);
|
||||
defer tree.deinit();
|
||||
const tree = handle.tree;
|
||||
|
||||
// Use an arena for our local memory allocations.
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
@ -179,7 +178,7 @@ fn containerToCompletion(
|
||||
var child_idx: usize = 0;
|
||||
while (container.iterate(child_idx)) |child_node| : (child_idx += 1) {
|
||||
// Declarations in the same file do not need to be public.
|
||||
if (orig_handle == analysis_ctx.handle or analysis.isNodePublic(analysis_ctx.tree, child_node)) {
|
||||
if (orig_handle == analysis_ctx.handle or analysis.isNodePublic(analysis_ctx.tree(), child_node)) {
|
||||
try nodeToCompletion(list, analysis_ctx, orig_handle, child_node, config);
|
||||
}
|
||||
}
|
||||
@ -192,7 +191,7 @@ fn nodeToCompletion(
|
||||
node: *std.zig.ast.Node,
|
||||
config: Config,
|
||||
) error{OutOfMemory}!void {
|
||||
var doc = if (try analysis.getDocComments(list.allocator, analysis_ctx.tree, node)) |doc_comments|
|
||||
var doc = if (try analysis.getDocComments(list.allocator, analysis_ctx.tree(), node)) |doc_comments|
|
||||
types.MarkupContent{
|
||||
.kind = .Markdown,
|
||||
.value = doc_comments,
|
||||
@ -208,17 +207,17 @@ fn nodeToCompletion(
|
||||
const func = node.cast(std.zig.ast.Node.FnProto).?;
|
||||
if (func.name_token) |name_token| {
|
||||
const insert_text = if (config.enable_snippets)
|
||||
try analysis.getFunctionSnippet(list.allocator, analysis_ctx.tree, func)
|
||||
try analysis.getFunctionSnippet(list.allocator, analysis_ctx.tree(), func)
|
||||
else
|
||||
null;
|
||||
|
||||
const is_type_function = analysis.isTypeFunction(analysis_ctx.tree, func);
|
||||
const is_type_function = analysis.isTypeFunction(analysis_ctx.tree(), func);
|
||||
|
||||
try list.append(.{
|
||||
.label = analysis_ctx.tree.tokenSlice(name_token),
|
||||
.label = analysis_ctx.tree().tokenSlice(name_token),
|
||||
.kind = if (is_type_function) .Struct else .Function,
|
||||
.documentation = doc,
|
||||
.detail = analysis.getFunctionSignature(analysis_ctx.tree, func),
|
||||
.detail = analysis.getFunctionSignature(analysis_ctx.tree(), func),
|
||||
.insertText = insert_text,
|
||||
.insertTextFormat = if (config.enable_snippets) .Snippet else .PlainText,
|
||||
});
|
||||
@ -226,14 +225,13 @@ fn nodeToCompletion(
|
||||
},
|
||||
.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 = analysis_ctx.tree().token_ids[var_decl.mut_token] == .Keyword_const;
|
||||
|
||||
var child_analysis_context = try analysis_ctx.clone();
|
||||
defer child_analysis_context.deinit();
|
||||
var child_analysis_context = analysis_ctx.clone();
|
||||
|
||||
const child_node = block: {
|
||||
if (var_decl.type_node) |type_node| {
|
||||
if (std.mem.eql(u8, "type", analysis_ctx.tree.tokenSlice(type_node.firstToken()))) {
|
||||
if (std.mem.eql(u8, "type", analysis_ctx.tree().tokenSlice(type_node.firstToken()))) {
|
||||
break :block var_decl.init_node orelse type_node;
|
||||
}
|
||||
break :block type_node;
|
||||
@ -250,10 +248,10 @@ fn nodeToCompletion(
|
||||
}
|
||||
}
|
||||
try list.append(.{
|
||||
.label = analysis_ctx.tree.tokenSlice(var_decl.name_token),
|
||||
.label = analysis_ctx.tree().tokenSlice(var_decl.name_token),
|
||||
.kind = if (is_const) .Constant else .Variable,
|
||||
.documentation = doc,
|
||||
.detail = analysis.getVariableSignature(analysis_ctx.tree, var_decl),
|
||||
.detail = analysis.getVariableSignature(analysis_ctx.tree(), var_decl),
|
||||
});
|
||||
},
|
||||
.PrefixOp => {
|
||||
@ -272,7 +270,7 @@ fn nodeToCompletion(
|
||||
.kind = .Field,
|
||||
});
|
||||
},
|
||||
else => if (analysis.nodeToString(analysis_ctx.tree, node)) |string| {
|
||||
else => if (analysis.nodeToString(analysis_ctx.tree(), node)) |string| {
|
||||
try list.append(.{
|
||||
.label = string,
|
||||
.kind = .Field,
|
||||
@ -302,8 +300,7 @@ fn identifierFromPosition(pos_index: usize, handle: DocumentStore.Handle) []cons
|
||||
}
|
||||
|
||||
fn gotoDefinitionGlobal(id: i64, pos_index: usize, handle: DocumentStore.Handle) !void {
|
||||
var tree = try handle.tree(allocator);
|
||||
defer tree.deinit();
|
||||
const tree = handle.tree;
|
||||
|
||||
const name = identifierFromPosition(pos_index, handle);
|
||||
if (name.len == 0) return try respondGeneric(id, null_result_response);
|
||||
@ -343,7 +340,6 @@ fn gotoDefinitionFieldAccess(
|
||||
defer arena.deinit();
|
||||
|
||||
var analysis_ctx = try document_store.analysisContext(handle, &arena, try handle.document.positionToIndex(position), config.zig_lib_path);
|
||||
defer analysis_ctx.deinit();
|
||||
|
||||
const line = try handle.document.getLine(@intCast(usize, position.line));
|
||||
var tokenizer = std.zig.Tokenizer.init(line[line_start_idx..]);
|
||||
@ -352,14 +348,14 @@ fn gotoDefinitionFieldAccess(
|
||||
name = try std.mem.dupe(&arena.allocator, u8, name);
|
||||
|
||||
if (analysis.getFieldAccessTypeNode(&analysis_ctx, &tokenizer, line_length)) |container| {
|
||||
const decl = analysis.getChild(analysis_ctx.tree, container, name) orelse return try respondGeneric(id, null_result_response);
|
||||
const name_token = analysis.getDeclNameToken(analysis_ctx.tree, decl) orelse unreachable;
|
||||
const decl = analysis.getChild(analysis_ctx.tree(), container, name) orelse return try respondGeneric(id, null_result_response);
|
||||
const name_token = analysis.getDeclNameToken(analysis_ctx.tree(), decl) orelse unreachable;
|
||||
return try send(types.Response{
|
||||
.id = .{ .Integer = id },
|
||||
.result = .{
|
||||
.Location = .{
|
||||
.uri = analysis_ctx.handle.document.uri,
|
||||
.range = astLocationToRange(analysis_ctx.tree.tokenLocation(0, name_token)),
|
||||
.range = astLocationToRange(analysis_ctx.tree().tokenLocation(0, name_token)),
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -369,8 +365,7 @@ fn gotoDefinitionFieldAccess(
|
||||
}
|
||||
|
||||
fn gotoDefinitionString(id: i64, pos_index: usize, handle: *DocumentStore.Handle, config: Config) !void {
|
||||
var tree = try handle.tree(allocator);
|
||||
defer tree.deinit();
|
||||
const tree = handle.tree;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena.deinit();
|
||||
@ -405,8 +400,6 @@ fn completeGlobal(id: i64, pos_index: usize, handle: *DocumentStore.Handle, conf
|
||||
defer arena.deinit();
|
||||
|
||||
var analysis_ctx = try document_store.analysisContext(handle, &arena, pos_index, config.zig_lib_path);
|
||||
defer analysis_ctx.deinit();
|
||||
|
||||
for (analysis_ctx.scope_nodes) |decl_ptr| {
|
||||
var decl = decl_ptr.*;
|
||||
try nodeToCompletion(&completions, &analysis_ctx, handle, decl_ptr, config);
|
||||
@ -428,8 +421,6 @@ fn completeFieldAccess(id: i64, handle: *DocumentStore.Handle, position: types.P
|
||||
defer arena.deinit();
|
||||
|
||||
var analysis_ctx = try document_store.analysisContext(handle, &arena, try handle.document.positionToIndex(position), config.zig_lib_path);
|
||||
defer analysis_ctx.deinit();
|
||||
|
||||
var completions = std.ArrayList(types.CompletionItem).init(&arena.allocator);
|
||||
|
||||
const line = try handle.document.getLine(@intCast(usize, position.line));
|
||||
|
Loading…
Reference in New Issue
Block a user