Merge branch 'master' into intern-pool
This commit is contained in:
commit
5754f362c6
@ -33,7 +33,7 @@ Building `zls` is very easy. You will need [a build of Zig master](https://zigla
|
|||||||
```bash
|
```bash
|
||||||
git clone --recurse-submodules https://github.com/zigtools/zls
|
git clone --recurse-submodules https://github.com/zigtools/zls
|
||||||
cd zls
|
cd zls
|
||||||
zig build -Drelease-safe
|
zig build -Doptimize=ReleaseSafe
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Build Options
|
#### Build Options
|
||||||
|
@ -508,7 +508,7 @@ fn autofix(server: *Server, allocator: std.mem.Allocator, handle: *const Documen
|
|||||||
};
|
};
|
||||||
|
|
||||||
var builder = code_actions.Builder{
|
var builder = code_actions.Builder{
|
||||||
.arena = server.arena,
|
.arena = server.arena.allocator(),
|
||||||
.document_store = &server.document_store,
|
.document_store = &server.document_store,
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
.offset_encoding = server.offset_encoding,
|
.offset_encoding = server.offset_encoding,
|
||||||
@ -652,7 +652,6 @@ fn nodeToCompletion(
|
|||||||
};
|
};
|
||||||
try analysis.iterateSymbolsContainer(
|
try analysis.iterateSymbolsContainer(
|
||||||
&server.document_store,
|
&server.document_store,
|
||||||
server.arena,
|
|
||||||
node_handle,
|
node_handle,
|
||||||
orig_handle,
|
orig_handle,
|
||||||
declToCompletion,
|
declToCompletion,
|
||||||
@ -676,7 +675,7 @@ fn nodeToCompletion(
|
|||||||
const use_snippets = server.config.enable_snippets and server.client_capabilities.supports_snippets;
|
const use_snippets = server.config.enable_snippets and server.client_capabilities.supports_snippets;
|
||||||
const insert_text = if (use_snippets) blk: {
|
const insert_text = if (use_snippets) blk: {
|
||||||
const skip_self_param = !(parent_is_type_val orelse true) and
|
const skip_self_param = !(parent_is_type_val orelse true) and
|
||||||
try analysis.hasSelfParam(server.arena, &server.document_store, handle, func);
|
try analysis.hasSelfParam(&server.document_store, handle, func);
|
||||||
break :blk try analysis.getFunctionSnippet(server.arena.allocator(), tree, func, skip_self_param);
|
break :blk try analysis.getFunctionSnippet(server.arena.allocator(), tree, func, skip_self_param);
|
||||||
} else tree.tokenSlice(func.name_token.?);
|
} else tree.tokenSlice(func.name_token.?);
|
||||||
|
|
||||||
@ -700,7 +699,7 @@ fn nodeToCompletion(
|
|||||||
const var_decl = tree.fullVarDecl(node).?;
|
const var_decl = tree.fullVarDecl(node).?;
|
||||||
const is_const = token_tags[var_decl.ast.mut_token] == .keyword_const;
|
const is_const = token_tags[var_decl.ast.mut_token] == .keyword_const;
|
||||||
|
|
||||||
if (try analysis.resolveVarDeclAlias(&server.document_store, server.arena, node_handle)) |result| {
|
if (try analysis.resolveVarDeclAlias(&server.document_store, node_handle)) |result| {
|
||||||
const context = DeclToCompletionContext{
|
const context = DeclToCompletionContext{
|
||||||
.server = server,
|
.server = server,
|
||||||
.completions = list,
|
.completions = list,
|
||||||
@ -845,7 +844,7 @@ fn gotoDefinitionSymbol(
|
|||||||
const name_token = switch (decl_handle.decl.*) {
|
const name_token = switch (decl_handle.decl.*) {
|
||||||
.ast_node => |node| block: {
|
.ast_node => |node| block: {
|
||||||
if (resolve_alias) {
|
if (resolve_alias) {
|
||||||
if (try analysis.resolveVarDeclAlias(&server.document_store, server.arena, .{ .node = node, .handle = handle })) |result| {
|
if (try analysis.resolveVarDeclAlias(&server.document_store, .{ .node = node, .handle = handle })) |result| {
|
||||||
handle = result.handle;
|
handle = result.handle;
|
||||||
|
|
||||||
break :block result.nameToken();
|
break :block result.nameToken();
|
||||||
@ -875,7 +874,7 @@ fn hoverSymbol(server: *Server, decl_handle: analysis.DeclWithHandle) error{OutO
|
|||||||
|
|
||||||
const def_str = switch (decl_handle.decl.*) {
|
const def_str = switch (decl_handle.decl.*) {
|
||||||
.ast_node => |node| def: {
|
.ast_node => |node| def: {
|
||||||
if (try analysis.resolveVarDeclAlias(&server.document_store, server.arena, .{ .node = node, .handle = handle })) |result| {
|
if (try analysis.resolveVarDeclAlias(&server.document_store, .{ .node = node, .handle = handle })) |result| {
|
||||||
return try server.hoverSymbol(result);
|
return try server.hoverSymbol(result);
|
||||||
}
|
}
|
||||||
doc_str = try analysis.getDocComments(server.arena.allocator(), tree, node, hover_kind);
|
doc_str = try analysis.getDocComments(server.arena.allocator(), tree, node, hover_kind);
|
||||||
@ -915,7 +914,8 @@ fn hoverSymbol(server: *Server, decl_handle: analysis.DeclWithHandle) error{OutO
|
|||||||
};
|
};
|
||||||
|
|
||||||
var bound_type_params = analysis.BoundTypeParams{};
|
var bound_type_params = analysis.BoundTypeParams{};
|
||||||
const resolved_type = try decl_handle.resolveType(&server.document_store, server.arena, &bound_type_params);
|
defer bound_type_params.deinit(server.document_store.allocator);
|
||||||
|
const resolved_type = try decl_handle.resolveType(&server.document_store, &bound_type_params);
|
||||||
|
|
||||||
const resolved_type_str = if (resolved_type) |rt|
|
const resolved_type_str = if (resolved_type) |rt|
|
||||||
if (rt.type.is_type_val) switch (rt.type.data) {
|
if (rt.type.is_type_val) switch (rt.type.data) {
|
||||||
@ -1005,7 +1005,7 @@ fn getSymbolGlobal(
|
|||||||
const name = identifierFromPosition(pos_index, handle.*);
|
const name = identifierFromPosition(pos_index, handle.*);
|
||||||
if (name.len == 0) return null;
|
if (name.len == 0) return null;
|
||||||
|
|
||||||
return try analysis.lookupSymbolGlobal(&server.document_store, server.arena, handle, name, pos_index);
|
return try analysis.lookupSymbolGlobal(&server.document_store, handle, name, pos_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gotoDefinitionLabel(
|
fn gotoDefinitionLabel(
|
||||||
@ -1146,7 +1146,7 @@ fn getSymbolFieldAccess(
|
|||||||
var held_range = try server.arena.allocator().dupeZ(u8, offsets.locToSlice(handle.text, loc));
|
var held_range = try server.arena.allocator().dupeZ(u8, offsets.locToSlice(handle.text, loc));
|
||||||
var tokenizer = std.zig.Tokenizer.init(held_range);
|
var tokenizer = std.zig.Tokenizer.init(held_range);
|
||||||
|
|
||||||
if (try analysis.getFieldAccessType(&server.document_store, server.arena, handle, source_index, &tokenizer)) |result| {
|
if (try analysis.getFieldAccessType(&server.document_store, handle, source_index, &tokenizer)) |result| {
|
||||||
const container_handle = result.unwrapped orelse result.original;
|
const container_handle = result.unwrapped orelse result.original;
|
||||||
const container_handle_node = switch (container_handle.type.data) {
|
const container_handle_node = switch (container_handle.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
@ -1154,7 +1154,6 @@ fn getSymbolFieldAccess(
|
|||||||
};
|
};
|
||||||
return try analysis.lookupSymbolContainer(
|
return try analysis.lookupSymbolContainer(
|
||||||
&server.document_store,
|
&server.document_store,
|
||||||
server.arena,
|
|
||||||
.{ .node = container_handle_node, .handle = container_handle.handle },
|
.{ .node = container_handle_node, .handle = container_handle.handle },
|
||||||
name,
|
name,
|
||||||
true,
|
true,
|
||||||
@ -1381,7 +1380,7 @@ fn completeGlobal(server: *Server, pos_index: usize, handle: *const DocumentStor
|
|||||||
.completions = &completions,
|
.completions = &completions,
|
||||||
.orig_handle = handle,
|
.orig_handle = handle,
|
||||||
};
|
};
|
||||||
try analysis.iterateSymbolsGlobal(&server.document_store, server.arena, handle, pos_index, declToCompletion, context);
|
try analysis.iterateSymbolsGlobal(&server.document_store, handle, pos_index, declToCompletion, context);
|
||||||
try populateSnippedCompletions(server.arena.allocator(), &completions, &snipped_data.generic, server.config.*, null);
|
try populateSnippedCompletions(server.arena.allocator(), &completions, &snipped_data.generic, server.config.*, null);
|
||||||
|
|
||||||
if (server.client_capabilities.label_details_support) {
|
if (server.client_capabilities.label_details_support) {
|
||||||
@ -1404,7 +1403,7 @@ fn completeFieldAccess(server: *Server, handle: *const DocumentStore.Handle, sou
|
|||||||
var held_loc = try allocator.dupeZ(u8, offsets.locToSlice(handle.text, loc));
|
var held_loc = try allocator.dupeZ(u8, offsets.locToSlice(handle.text, loc));
|
||||||
var tokenizer = std.zig.Tokenizer.init(held_loc);
|
var tokenizer = std.zig.Tokenizer.init(held_loc);
|
||||||
|
|
||||||
const result = (try analysis.getFieldAccessType(&server.document_store, server.arena, handle, source_index, &tokenizer)) orelse return null;
|
const result = (try analysis.getFieldAccessType(&server.document_store, handle, source_index, &tokenizer)) orelse return null;
|
||||||
try server.typeToCompletion(&completions, result, handle);
|
try server.typeToCompletion(&completions, result, handle);
|
||||||
if (server.client_capabilities.label_details_support) {
|
if (server.client_capabilities.label_details_support) {
|
||||||
for (completions.items) |*item| {
|
for (completions.items) |*item| {
|
||||||
@ -2466,7 +2465,7 @@ fn generalReferencesHandler(server: *Server, request: GeneralReferencesRequest)
|
|||||||
try references.labelReferences(allocator, decl, server.offset_encoding, include_decl)
|
try references.labelReferences(allocator, decl, server.offset_encoding, include_decl)
|
||||||
else
|
else
|
||||||
try references.symbolReferences(
|
try references.symbolReferences(
|
||||||
server.arena,
|
allocator,
|
||||||
&server.document_store,
|
&server.document_store,
|
||||||
decl,
|
decl,
|
||||||
server.offset_encoding,
|
server.offset_encoding,
|
||||||
@ -2538,7 +2537,7 @@ fn inlayHintHandler(server: *Server, request: types.InlayHintParams) Error!?[]ty
|
|||||||
// we need the regenerate hints when the document itself or its imported documents change
|
// we need the regenerate hints when the document itself or its imported documents change
|
||||||
// with caching it would also make sense to generate all hints instead of only the visible ones
|
// with caching it would also make sense to generate all hints instead of only the visible ones
|
||||||
const hints = try inlay_hints.writeRangeInlayHint(
|
const hints = try inlay_hints.writeRangeInlayHint(
|
||||||
server.arena,
|
server.arena.allocator(),
|
||||||
server.config.*,
|
server.config.*,
|
||||||
&server.document_store,
|
&server.document_store,
|
||||||
handle,
|
handle,
|
||||||
@ -2589,7 +2588,7 @@ fn codeActionHandler(server: *Server, request: types.CodeActionParams) Error!?[]
|
|||||||
const handle = server.document_store.getHandle(request.textDocument.uri) orelse return null;
|
const handle = server.document_store.getHandle(request.textDocument.uri) orelse return null;
|
||||||
|
|
||||||
var builder = code_actions.Builder{
|
var builder = code_actions.Builder{
|
||||||
.arena = server.arena,
|
.arena = server.arena.allocator(),
|
||||||
.document_store = &server.document_store,
|
.document_store = &server.document_store,
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
.offset_encoding = server.offset_encoding,
|
.offset_encoding = server.offset_encoding,
|
||||||
|
180
src/analysis.zig
180
src/analysis.zig
@ -186,7 +186,7 @@ pub fn getFunctionSnippet(allocator: std.mem.Allocator, tree: Ast, func: Ast.ful
|
|||||||
return buffer.toOwnedSlice(allocator);
|
return buffer.toOwnedSlice(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hasSelfParam(arena: *std.heap.ArenaAllocator, document_store: *DocumentStore, handle: *const DocumentStore.Handle, func: Ast.full.FnProto) !bool {
|
pub fn hasSelfParam(document_store: *DocumentStore, handle: *const DocumentStore.Handle, func: Ast.full.FnProto) !bool {
|
||||||
// Non-decl prototypes cannot have a self parameter.
|
// Non-decl prototypes cannot have a self parameter.
|
||||||
if (func.name_token == null) return false;
|
if (func.name_token == null) return false;
|
||||||
if (func.ast.params.len == 0) return false;
|
if (func.ast.params.len == 0) return false;
|
||||||
@ -199,7 +199,7 @@ pub fn hasSelfParam(arena: *std.heap.ArenaAllocator, document_store: *DocumentSt
|
|||||||
const token_starts = tree.tokens.items(.start);
|
const token_starts = tree.tokens.items(.start);
|
||||||
const in_container = innermostContainer(handle, token_starts[func.ast.fn_token]);
|
const in_container = innermostContainer(handle, token_starts[func.ast.fn_token]);
|
||||||
|
|
||||||
if (try resolveTypeOfNode(document_store, arena, .{
|
if (try resolveTypeOfNode(document_store, .{
|
||||||
.node = param.type_expr,
|
.node = param.type_expr,
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
})) |resolved_type| {
|
})) |resolved_type| {
|
||||||
@ -208,7 +208,7 @@ pub fn hasSelfParam(arena: *std.heap.ArenaAllocator, document_store: *DocumentSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ast.fullPtrType(tree, param.type_expr)) |ptr_type| {
|
if (ast.fullPtrType(tree, param.type_expr)) |ptr_type| {
|
||||||
if (try resolveTypeOfNode(document_store, arena, .{
|
if (try resolveTypeOfNode(document_store, .{
|
||||||
.node = ptr_type.ast.child_type,
|
.node = ptr_type.ast.child_type,
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
})) |resolved_prefix_op| {
|
})) |resolved_prefix_op| {
|
||||||
@ -323,7 +323,7 @@ pub fn getDeclName(tree: Ast, node: Ast.Node.Index) ?[]const u8 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, node_handle: NodeWithHandle, root: bool) error{OutOfMemory}!?DeclWithHandle {
|
fn resolveVarDeclAliasInternal(store: *DocumentStore, node_handle: NodeWithHandle, root: bool) error{OutOfMemory}!?DeclWithHandle {
|
||||||
_ = root;
|
_ = root;
|
||||||
const handle = node_handle.handle;
|
const handle = node_handle.handle;
|
||||||
const tree = handle.tree;
|
const tree = handle.tree;
|
||||||
@ -335,7 +335,6 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
|
|||||||
const token = main_tokens[node_handle.node];
|
const token = main_tokens[node_handle.node];
|
||||||
return try lookupSymbolGlobal(
|
return try lookupSymbolGlobal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
handle,
|
handle,
|
||||||
tree.tokenSlice(token),
|
tree.tokenSlice(token),
|
||||||
tree.tokens.items(.start)[token],
|
tree.tokens.items(.start)[token],
|
||||||
@ -350,13 +349,13 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
|
|||||||
if (!std.mem.eql(u8, name, "@import") and !std.mem.eql(u8, name, "@cImport"))
|
if (!std.mem.eql(u8, name, "@import") and !std.mem.eql(u8, name, "@cImport"))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const inner_node = (try resolveTypeOfNode(store, arena, .{ .node = lhs, .handle = handle })) orelse return null;
|
const inner_node = (try resolveTypeOfNode(store, .{ .node = lhs, .handle = handle })) orelse return null;
|
||||||
// assert root node
|
// assert root node
|
||||||
std.debug.assert(inner_node.type.data.other == 0);
|
std.debug.assert(inner_node.type.data.other == 0);
|
||||||
break :block NodeWithHandle{ .node = inner_node.type.data.other, .handle = inner_node.handle };
|
break :block NodeWithHandle{ .node = inner_node.type.data.other, .handle = inner_node.handle };
|
||||||
} else if (try resolveVarDeclAliasInternal(store, arena, .{ .node = lhs, .handle = handle }, false)) |decl_handle| block: {
|
} else if (try resolveVarDeclAliasInternal(store, .{ .node = lhs, .handle = handle }, false)) |decl_handle| block: {
|
||||||
if (decl_handle.decl.* != .ast_node) return null;
|
if (decl_handle.decl.* != .ast_node) return null;
|
||||||
const resolved = (try resolveTypeOfNode(store, arena, .{ .node = decl_handle.decl.ast_node, .handle = decl_handle.handle })) orelse return null;
|
const resolved = (try resolveTypeOfNode(store, .{ .node = decl_handle.decl.ast_node, .handle = decl_handle.handle })) orelse return null;
|
||||||
const resolved_node = switch (resolved.type.data) {
|
const resolved_node = switch (resolved.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
else => return null,
|
else => return null,
|
||||||
@ -365,7 +364,7 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
|
|||||||
break :block NodeWithHandle{ .node = resolved_node, .handle = resolved.handle };
|
break :block NodeWithHandle{ .node = resolved_node, .handle = resolved.handle };
|
||||||
} else return null;
|
} else return null;
|
||||||
|
|
||||||
return try lookupSymbolContainer(store, arena, container_node, tree.tokenSlice(datas[node_handle.node].rhs), false);
|
return try lookupSymbolContainer(store, container_node, tree.tokenSlice(datas[node_handle.node].rhs), false);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -376,7 +375,7 @@ fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllo
|
|||||||
/// const decl = @import("decl-file.zig").decl;
|
/// const decl = @import("decl-file.zig").decl;
|
||||||
/// const other = decl.middle.other;
|
/// const other = decl.middle.other;
|
||||||
///```
|
///```
|
||||||
pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocator, decl_handle: NodeWithHandle) !?DeclWithHandle {
|
pub fn resolveVarDeclAlias(store: *DocumentStore, decl_handle: NodeWithHandle) !?DeclWithHandle {
|
||||||
const decl = decl_handle.node;
|
const decl = decl_handle.node;
|
||||||
const handle = decl_handle.handle;
|
const handle = decl_handle.handle;
|
||||||
const tree = handle.tree;
|
const tree = handle.tree;
|
||||||
@ -393,7 +392,7 @@ pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocato
|
|||||||
if (!std.mem.eql(u8, tree.tokenSlice(var_decl.ast.mut_token + 1), name))
|
if (!std.mem.eql(u8, tree.tokenSlice(var_decl.ast.mut_token + 1), name))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return try resolveVarDeclAliasInternal(store, arena, .{ .node = base_exp, .handle = handle }, true);
|
return try resolveVarDeclAliasInternal(store, .{ .node = base_exp, .handle = handle }, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,7 +440,7 @@ fn findReturnStatement(tree: Ast, fn_decl: Ast.full.FnProto, body: Ast.Node.Inde
|
|||||||
return findReturnStatementInternal(tree, fn_decl, body, &already_found);
|
return findReturnStatementInternal(tree, fn_decl, body, &already_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, fn_decl: Ast.full.FnProto, handle: *const DocumentStore.Handle, bound_type_params: *BoundTypeParams, fn_body: ?Ast.Node.Index) !?TypeWithHandle {
|
pub fn resolveReturnType(store: *DocumentStore, fn_decl: Ast.full.FnProto, handle: *const DocumentStore.Handle, bound_type_params: *BoundTypeParams, fn_body: ?Ast.Node.Index) !?TypeWithHandle {
|
||||||
const tree = handle.tree;
|
const tree = handle.tree;
|
||||||
if (isTypeFunction(tree, fn_decl) and fn_body != null) {
|
if (isTypeFunction(tree, fn_decl) and fn_body != null) {
|
||||||
// If this is a type function and it only contains a single return statement that returns
|
// If this is a type function and it only contains a single return statement that returns
|
||||||
@ -449,7 +448,7 @@ pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
const ret = findReturnStatement(tree, fn_decl, fn_body.?) orelse return null;
|
const ret = findReturnStatement(tree, fn_decl, fn_body.?) orelse return null;
|
||||||
const data = tree.nodes.items(.data)[ret];
|
const data = tree.nodes.items(.data)[ret];
|
||||||
if (data.lhs != 0) {
|
if (data.lhs != 0) {
|
||||||
return try resolveTypeOfNodeInternal(store, arena, .{
|
return try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = data.lhs,
|
.node = data.lhs,
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
}, bound_type_params);
|
}, bound_type_params);
|
||||||
@ -461,7 +460,7 @@ pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
if (fn_decl.ast.return_type == 0) return null;
|
if (fn_decl.ast.return_type == 0) return null;
|
||||||
const return_type = fn_decl.ast.return_type;
|
const return_type = fn_decl.ast.return_type;
|
||||||
const ret = .{ .node = return_type, .handle = handle };
|
const ret = .{ .node = return_type, .handle = handle };
|
||||||
const child_type = (try resolveTypeOfNodeInternal(store, arena, ret, bound_type_params)) orelse
|
const child_type = (try resolveTypeOfNodeInternal(store, ret, bound_type_params)) orelse
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const is_inferred_error = tree.tokens.items(.tag)[tree.firstToken(return_type) - 1] == .bang;
|
const is_inferred_error = tree.tokens.items(.tag)[tree.firstToken(return_type) - 1] == .bang;
|
||||||
@ -478,14 +477,14 @@ pub fn resolveReturnType(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the child type of an optional type
|
/// Resolves the child type of an optional type
|
||||||
fn resolveUnwrapOptionalType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, opt: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
fn resolveUnwrapOptionalType(store: *DocumentStore, opt: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
||||||
const opt_node = switch (opt.type.data) {
|
const opt_node = switch (opt.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
else => return null,
|
else => return null,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (opt.handle.tree.nodes.items(.tag)[opt_node] == .optional_type) {
|
if (opt.handle.tree.nodes.items(.tag)[opt_node] == .optional_type) {
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = opt.handle.tree.nodes.items(.data)[opt_node].lhs,
|
.node = opt.handle.tree.nodes.items(.data)[opt_node].lhs,
|
||||||
.handle = opt.handle,
|
.handle = opt.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
@ -494,7 +493,7 @@ fn resolveUnwrapOptionalType(store: *DocumentStore, arena: *std.heap.ArenaAlloca
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, rhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
fn resolveUnwrapErrorType(store: *DocumentStore, rhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
||||||
const rhs_node = switch (rhs.type.data) {
|
const rhs_node = switch (rhs.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
.error_union => |n| return TypeWithHandle{
|
.error_union => |n| return TypeWithHandle{
|
||||||
@ -505,7 +504,7 @@ fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (rhs.handle.tree.nodes.items(.tag)[rhs_node] == .error_union) {
|
if (rhs.handle.tree.nodes.items(.tag)[rhs_node] == .error_union) {
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = rhs.handle.tree.nodes.items(.data)[rhs_node].rhs,
|
.node = rhs.handle.tree.nodes.items(.data)[rhs_node].rhs,
|
||||||
.handle = rhs.handle,
|
.handle = rhs.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
@ -515,7 +514,7 @@ fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the child type of a deref type
|
/// Resolves the child type of a deref type
|
||||||
fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, deref: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
fn resolveDerefType(store: *DocumentStore, deref: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
||||||
const deref_node = switch (deref.type.data) {
|
const deref_node = switch (deref.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
.pointer => |n| return TypeWithHandle{
|
.pointer => |n| return TypeWithHandle{
|
||||||
@ -534,7 +533,7 @@ fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, dere
|
|||||||
if (ast.fullPtrType(tree, deref_node)) |ptr_type| {
|
if (ast.fullPtrType(tree, deref_node)) |ptr_type| {
|
||||||
switch (token_tag) {
|
switch (token_tag) {
|
||||||
.asterisk => {
|
.asterisk => {
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = ptr_type.ast.child_type,
|
.node = ptr_type.ast.child_type,
|
||||||
.handle = deref.handle,
|
.handle = deref.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
@ -547,7 +546,7 @@ fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, dere
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves slicing and array access
|
/// Resolves slicing and array access
|
||||||
fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, lhs: TypeWithHandle, rhs: enum { Single, Range }, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
fn resolveBracketAccessType(store: *DocumentStore, lhs: TypeWithHandle, rhs: enum { Single, Range }, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
||||||
const lhs_node = switch (lhs.type.data) {
|
const lhs_node = switch (lhs.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
else => return null,
|
else => return null,
|
||||||
@ -560,7 +559,7 @@ fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocat
|
|||||||
|
|
||||||
if (tag == .array_type or tag == .array_type_sentinel) {
|
if (tag == .array_type or tag == .array_type_sentinel) {
|
||||||
if (rhs == .Single)
|
if (rhs == .Single)
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = data.rhs,
|
.node = data.rhs,
|
||||||
.handle = lhs.handle,
|
.handle = lhs.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
@ -571,7 +570,7 @@ fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocat
|
|||||||
} else if (ast.fullPtrType(tree, lhs_node)) |ptr_type| {
|
} else if (ast.fullPtrType(tree, lhs_node)) |ptr_type| {
|
||||||
if (ptr_type.size == .Slice) {
|
if (ptr_type.size == .Slice) {
|
||||||
if (rhs == .Single) {
|
if (rhs == .Single) {
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = ptr_type.ast.child_type,
|
.node = ptr_type.ast.child_type,
|
||||||
.handle = lhs.handle,
|
.handle = lhs.handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
@ -584,8 +583,8 @@ fn resolveBracketAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called to remove one level of pointerness before a field access
|
/// Called to remove one level of pointerness before a field access
|
||||||
pub fn resolveFieldAccessLhsType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, lhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !TypeWithHandle {
|
pub fn resolveFieldAccessLhsType(store: *DocumentStore, lhs: TypeWithHandle, bound_type_params: *BoundTypeParams) !TypeWithHandle {
|
||||||
return (try resolveDerefType(store, arena, lhs, bound_type_params)) orelse lhs;
|
return (try resolveDerefType(store, lhs, bound_type_params)) orelse lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const BoundTypeParams = std.AutoHashMapUnmanaged(Ast.full.FnProto.Param, TypeWithHandle);
|
pub const BoundTypeParams = std.AutoHashMapUnmanaged(Ast.full.FnProto.Param, TypeWithHandle);
|
||||||
@ -623,7 +622,7 @@ pub fn isTypeIdent(text: []const u8) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the type of a node
|
/// Resolves the type of a node
|
||||||
pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, node_handle: NodeWithHandle, bound_type_params: *BoundTypeParams) error{OutOfMemory}!?TypeWithHandle {
|
pub fn resolveTypeOfNodeInternal(store: *DocumentStore, node_handle: NodeWithHandle, bound_type_params: *BoundTypeParams) error{OutOfMemory}!?TypeWithHandle {
|
||||||
// If we were asked to resolve this node before,
|
// If we were asked to resolve this node before,
|
||||||
// it is self-referential and we cannot resolve it.
|
// it is self-referential and we cannot resolve it.
|
||||||
for (resolve_trail.items) |i| {
|
for (resolve_trail.items) |i| {
|
||||||
@ -652,14 +651,14 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
const var_decl = tree.fullVarDecl(node).?;
|
const var_decl = tree.fullVarDecl(node).?;
|
||||||
if (var_decl.ast.type_node != 0) {
|
if (var_decl.ast.type_node != 0) {
|
||||||
const decl_type = .{ .node = var_decl.ast.type_node, .handle = handle };
|
const decl_type = .{ .node = var_decl.ast.type_node, .handle = handle };
|
||||||
if (try resolveTypeOfNodeInternal(store, arena, decl_type, bound_type_params)) |typ|
|
if (try resolveTypeOfNodeInternal(store, decl_type, bound_type_params)) |typ|
|
||||||
return typ.instanceTypeVal();
|
return typ.instanceTypeVal();
|
||||||
}
|
}
|
||||||
if (var_decl.ast.init_node == 0)
|
if (var_decl.ast.init_node == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const value = .{ .node = var_decl.ast.init_node, .handle = handle };
|
const value = .{ .node = var_decl.ast.init_node, .handle = handle };
|
||||||
return try resolveTypeOfNodeInternal(store, arena, value, bound_type_params);
|
return try resolveTypeOfNodeInternal(store, value, bound_type_params);
|
||||||
},
|
},
|
||||||
.identifier => {
|
.identifier => {
|
||||||
const name = offsets.nodeToSlice(tree, node);
|
const name = offsets.nodeToSlice(tree, node);
|
||||||
@ -673,7 +672,6 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
|
|
||||||
if (try lookupSymbolGlobal(
|
if (try lookupSymbolGlobal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
handle,
|
handle,
|
||||||
name,
|
name,
|
||||||
starts[main_tokens[node]],
|
starts[main_tokens[node]],
|
||||||
@ -688,7 +686,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
return try child.resolveType(store, arena, bound_type_params);
|
return try child.resolveType(store, bound_type_params);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@ -705,7 +703,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
const call = tree.fullCall(¶ms, node) orelse unreachable;
|
const call = tree.fullCall(¶ms, node) orelse unreachable;
|
||||||
|
|
||||||
const callee = .{ .node = call.ast.fn_expr, .handle = handle };
|
const callee = .{ .node = call.ast.fn_expr, .handle = handle };
|
||||||
const decl = (try resolveTypeOfNodeInternal(store, arena, callee, bound_type_params)) orelse
|
const decl = (try resolveTypeOfNodeInternal(store, callee, bound_type_params)) orelse
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (decl.type.is_type_val) return null;
|
if (decl.type.is_type_val) return null;
|
||||||
@ -722,7 +720,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
// TODO: Back-parse to extract the self argument?
|
// TODO: Back-parse to extract the self argument?
|
||||||
var it = fn_decl.iterate(&decl.handle.tree);
|
var it = fn_decl.iterate(&decl.handle.tree);
|
||||||
if (token_tags[call.ast.lparen - 2] == .period) {
|
if (token_tags[call.ast.lparen - 2] == .period) {
|
||||||
if (try hasSelfParam(arena, store, decl.handle, fn_decl)) {
|
if (try hasSelfParam(store, decl.handle, fn_decl)) {
|
||||||
_ = ast.nextFnParam(&it);
|
_ = ast.nextFnParam(&it);
|
||||||
expected_params -= 1;
|
expected_params -= 1;
|
||||||
}
|
}
|
||||||
@ -739,19 +737,18 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
const argument = .{ .node = call.ast.params[i], .handle = handle };
|
const argument = .{ .node = call.ast.params[i], .handle = handle };
|
||||||
const argument_type = (try resolveTypeOfNodeInternal(
|
const argument_type = (try resolveTypeOfNodeInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
argument,
|
argument,
|
||||||
bound_type_params,
|
bound_type_params,
|
||||||
)) orelse
|
)) orelse
|
||||||
continue;
|
continue;
|
||||||
if (!argument_type.type.is_type_val) continue;
|
if (!argument_type.type.is_type_val) continue;
|
||||||
|
|
||||||
try bound_type_params.put(arena.allocator(), decl_param, argument_type);
|
try bound_type_params.put(store.allocator, decl_param, argument_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const has_body = decl.handle.tree.nodes.items(.tag)[decl_node] == .fn_decl;
|
const has_body = decl.handle.tree.nodes.items(.tag)[decl_node] == .fn_decl;
|
||||||
const body = decl.handle.tree.nodes.items(.data)[decl_node].rhs;
|
const body = decl.handle.tree.nodes.items(.data)[decl_node].rhs;
|
||||||
if (try resolveReturnType(store, arena, fn_decl, decl.handle, bound_type_params, if (has_body) body else null)) |ret| {
|
if (try resolveReturnType(store, fn_decl, decl.handle, bound_type_params, if (has_body) body else null)) |ret| {
|
||||||
return ret;
|
return ret;
|
||||||
} else if (store.config.use_comptime_interpreter) {
|
} else if (store.config.use_comptime_interpreter) {
|
||||||
// TODO: Better case-by-case; we just use the ComptimeInterpreter when all else fails,
|
// TODO: Better case-by-case; we just use the ComptimeInterpreter when all else fails,
|
||||||
@ -828,7 +825,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
.address_of,
|
.address_of,
|
||||||
=> {
|
=> {
|
||||||
const base = .{ .node = datas[node].lhs, .handle = handle };
|
const base = .{ .node = datas[node].lhs, .handle = handle };
|
||||||
const base_type = (try resolveTypeOfNodeInternal(store, arena, base, bound_type_params)) orelse
|
const base_type = (try resolveTypeOfNodeInternal(store, base, bound_type_params)) orelse
|
||||||
return null;
|
return null;
|
||||||
return switch (node_tags[node]) {
|
return switch (node_tags[node]) {
|
||||||
.@"comptime",
|
.@"comptime",
|
||||||
@ -846,13 +843,13 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
.slice,
|
.slice,
|
||||||
.slice_sentinel,
|
.slice_sentinel,
|
||||||
.slice_open,
|
.slice_open,
|
||||||
=> try resolveBracketAccessType(store, arena, base_type, .Range, bound_type_params),
|
=> try resolveBracketAccessType(store, base_type, .Range, bound_type_params),
|
||||||
.deref => try resolveDerefType(store, arena, base_type, bound_type_params),
|
.deref => try resolveDerefType(store, base_type, bound_type_params),
|
||||||
.unwrap_optional => try resolveUnwrapOptionalType(store, arena, base_type, bound_type_params),
|
.unwrap_optional => try resolveUnwrapOptionalType(store, base_type, bound_type_params),
|
||||||
.array_access => try resolveBracketAccessType(store, arena, base_type, .Single, bound_type_params),
|
.array_access => try resolveBracketAccessType(store, base_type, .Single, bound_type_params),
|
||||||
.@"orelse" => try resolveUnwrapOptionalType(store, arena, base_type, bound_type_params),
|
.@"orelse" => try resolveUnwrapOptionalType(store, base_type, bound_type_params),
|
||||||
.@"catch" => try resolveUnwrapErrorType(store, arena, base_type, bound_type_params),
|
.@"catch" => try resolveUnwrapErrorType(store, base_type, bound_type_params),
|
||||||
.@"try" => try resolveUnwrapErrorType(store, arena, base_type, bound_type_params),
|
.@"try" => try resolveUnwrapErrorType(store, base_type, bound_type_params),
|
||||||
.address_of => {
|
.address_of => {
|
||||||
const lhs_node = switch (base_type.type.data) {
|
const lhs_node = switch (base_type.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
@ -872,8 +869,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
// 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 = try resolveFieldAccessLhsType(
|
const left_type = try resolveFieldAccessLhsType(
|
||||||
store,
|
store,
|
||||||
arena,
|
(try resolveTypeOfNodeInternal(store, .{
|
||||||
(try resolveTypeOfNodeInternal(store, arena, .{
|
|
||||||
.node = datas[node].lhs,
|
.node = datas[node].lhs,
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
}, bound_type_params)) orelse return null,
|
}, bound_type_params)) orelse return null,
|
||||||
@ -887,12 +883,11 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
|
|
||||||
if (try lookupSymbolContainer(
|
if (try lookupSymbolContainer(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = left_type_node, .handle = left_type.handle },
|
.{ .node = left_type_node, .handle = left_type.handle },
|
||||||
tree.tokenSlice(datas[node].rhs),
|
tree.tokenSlice(datas[node].rhs),
|
||||||
!left_type.type.is_type_val,
|
!left_type.type.is_type_val,
|
||||||
)) |child| {
|
)) |child| {
|
||||||
return try child.resolveType(store, arena, bound_type_params);
|
return try child.resolveType(store, bound_type_params);
|
||||||
} else return null;
|
} else return null;
|
||||||
},
|
},
|
||||||
.array_type,
|
.array_type,
|
||||||
@ -946,7 +941,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
});
|
});
|
||||||
if (cast_map.has(call_name)) {
|
if (cast_map.has(call_name)) {
|
||||||
if (params.len < 1) return null;
|
if (params.len < 1) return null;
|
||||||
return ((try resolveTypeOfNodeInternal(store, arena, .{
|
return ((try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = params[0],
|
.node = params[0],
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
}, bound_type_params)) orelse return null).instanceTypeVal();
|
}, bound_type_params)) orelse return null).instanceTypeVal();
|
||||||
@ -956,7 +951,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
// TODO Do peer type resolution, we just keep the first for now.
|
// TODO Do peer type resolution, we just keep the first for now.
|
||||||
if (std.mem.eql(u8, call_name, "@TypeOf")) {
|
if (std.mem.eql(u8, call_name, "@TypeOf")) {
|
||||||
if (params.len < 1) return null;
|
if (params.len < 1) return null;
|
||||||
var resolved_type = (try resolveTypeOfNodeInternal(store, arena, .{
|
var resolved_type = (try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = params[0],
|
.node = params[0],
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
}, bound_type_params)) orelse return null;
|
}, bound_type_params)) orelse return null;
|
||||||
@ -967,12 +962,14 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.eql(u8, call_name, "@typeInfo")) {
|
if (std.mem.eql(u8, call_name, "@typeInfo")) {
|
||||||
const zig_lib_path = try URI.fromPath(arena.allocator(), store.config.zig_lib_path orelse return null);
|
const zig_lib_path = try URI.fromPath(store.allocator, store.config.zig_lib_path orelse return null);
|
||||||
|
defer store.allocator.free(zig_lib_path);
|
||||||
|
|
||||||
const builtin_uri = URI.pathRelative(arena.allocator(), zig_lib_path, "/std/builtin.zig") catch |err| switch (err) {
|
const builtin_uri = URI.pathRelative(store.allocator, zig_lib_path, "/std/builtin.zig") catch |err| switch (err) {
|
||||||
error.OutOfMemory => |e| return e,
|
error.OutOfMemory => |e| return e,
|
||||||
else => return null,
|
else => return null,
|
||||||
};
|
};
|
||||||
|
defer store.allocator.free(builtin_uri);
|
||||||
|
|
||||||
const new_handle = store.getOrLoadHandle(builtin_uri) orelse return null;
|
const new_handle = store.getOrLoadHandle(builtin_uri) orelse return null;
|
||||||
const root_scope_decls = new_handle.document_scope.scopes.items(.decls)[0];
|
const root_scope_decls = new_handle.document_scope.scopes.items(.decls)[0];
|
||||||
@ -996,7 +993,8 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
if (node_tags[import_param] != .string_literal) return null;
|
if (node_tags[import_param] != .string_literal) return null;
|
||||||
|
|
||||||
const import_str = tree.tokenSlice(main_tokens[import_param]);
|
const import_str = tree.tokenSlice(main_tokens[import_param]);
|
||||||
const import_uri = (try store.uriFromImportStr(arena.allocator(), handle.*, import_str[1 .. import_str.len - 1])) orelse return null;
|
const import_uri = (try store.uriFromImportStr(store.allocator, handle.*, import_str[1 .. import_str.len - 1])) orelse return null;
|
||||||
|
defer store.allocator.free(import_uri);
|
||||||
|
|
||||||
const new_handle = store.getOrLoadHandle(import_uri) orelse return null;
|
const new_handle = store.getOrLoadHandle(import_uri) orelse return null;
|
||||||
|
|
||||||
@ -1167,9 +1165,10 @@ pub const TypeWithHandle = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator, node_handle: NodeWithHandle) error{OutOfMemory}!?TypeWithHandle {
|
pub fn resolveTypeOfNode(store: *DocumentStore, node_handle: NodeWithHandle) error{OutOfMemory}!?TypeWithHandle {
|
||||||
var bound_type_params = BoundTypeParams{};
|
var bound_type_params = BoundTypeParams{};
|
||||||
return resolveTypeOfNodeInternal(store, arena, node_handle, &bound_type_params);
|
defer bound_type_params.deinit(store.allocator);
|
||||||
|
return resolveTypeOfNodeInternal(store, node_handle, &bound_type_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collects all `@import`'s we can find into a slice of import paths (without quotes).
|
/// Collects all `@import`'s we can find into a slice of import paths (without quotes).
|
||||||
@ -1235,28 +1234,28 @@ pub const FieldAccessReturn = struct {
|
|||||||
unwrapped: ?TypeWithHandle = null,
|
unwrapped: ?TypeWithHandle = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, source_index: usize, tokenizer: *std.zig.Tokenizer) !?FieldAccessReturn {
|
pub fn getFieldAccessType(store: *DocumentStore, handle: *const DocumentStore.Handle, source_index: usize, tokenizer: *std.zig.Tokenizer) !?FieldAccessReturn {
|
||||||
var current_type: ?TypeWithHandle = null;
|
var current_type: ?TypeWithHandle = null;
|
||||||
|
|
||||||
var bound_type_params = BoundTypeParams{};
|
var bound_type_params = BoundTypeParams{};
|
||||||
|
defer bound_type_params.deinit(store.allocator);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const tok = tokenizer.next();
|
const tok = tokenizer.next();
|
||||||
switch (tok.tag) {
|
switch (tok.tag) {
|
||||||
.eof => return FieldAccessReturn{
|
.eof => return FieldAccessReturn{
|
||||||
.original = current_type orelse return null,
|
.original = current_type orelse return null,
|
||||||
.unwrapped = try resolveDerefType(store, arena, current_type orelse return null, &bound_type_params),
|
.unwrapped = try resolveDerefType(store, current_type orelse return null, &bound_type_params),
|
||||||
},
|
},
|
||||||
.identifier => {
|
.identifier => {
|
||||||
const ct_handle = if (current_type) |c| c.handle else handle;
|
const ct_handle = if (current_type) |c| c.handle else handle;
|
||||||
if (try lookupSymbolGlobal(
|
if (try lookupSymbolGlobal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
ct_handle,
|
ct_handle,
|
||||||
tokenizer.buffer[tok.loc.start..tok.loc.end],
|
tokenizer.buffer[tok.loc.start..tok.loc.end],
|
||||||
source_index,
|
source_index,
|
||||||
)) |child| {
|
)) |child| {
|
||||||
current_type = (try child.resolveType(store, arena, &bound_type_params)) orelse return null;
|
current_type = (try child.resolveType(store, &bound_type_params)) orelse return null;
|
||||||
} else return null;
|
} else return null;
|
||||||
},
|
},
|
||||||
.period => {
|
.period => {
|
||||||
@ -1268,7 +1267,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
if (ct.isFunc()) return null;
|
if (ct.isFunc()) return null;
|
||||||
return FieldAccessReturn{
|
return FieldAccessReturn{
|
||||||
.original = ct,
|
.original = ct,
|
||||||
.unwrapped = try resolveDerefType(store, arena, ct, &bound_type_params),
|
.unwrapped = try resolveDerefType(store, ct, &bound_type_params),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -1279,14 +1278,14 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
if (current_type) |ct| {
|
if (current_type) |ct| {
|
||||||
return FieldAccessReturn{
|
return FieldAccessReturn{
|
||||||
.original = ct,
|
.original = ct,
|
||||||
.unwrapped = try resolveDerefType(store, arena, ct, &bound_type_params),
|
.unwrapped = try resolveDerefType(store, ct, &bound_type_params),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_type = try resolveFieldAccessLhsType(store, arena, current_type orelse return null, &bound_type_params);
|
current_type = try resolveFieldAccessLhsType(store, current_type orelse return null, &bound_type_params);
|
||||||
|
|
||||||
const current_type_node = switch (current_type.?.type.data) {
|
const current_type_node = switch (current_type.?.type.data) {
|
||||||
.other => |n| n,
|
.other => |n| n,
|
||||||
@ -1295,14 +1294,12 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
|
|
||||||
if (try lookupSymbolContainer(
|
if (try lookupSymbolContainer(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = current_type_node, .handle = current_type.?.handle },
|
.{ .node = current_type_node, .handle = current_type.?.handle },
|
||||||
tokenizer.buffer[after_period.loc.start..after_period.loc.end],
|
tokenizer.buffer[after_period.loc.start..after_period.loc.end],
|
||||||
!current_type.?.type.is_type_val,
|
!current_type.?.type.is_type_val,
|
||||||
)) |child| {
|
)) |child| {
|
||||||
current_type.? = (try child.resolveType(
|
current_type.? = (try child.resolveType(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
&bound_type_params,
|
&bound_type_params,
|
||||||
)) orelse return null;
|
)) orelse return null;
|
||||||
} else return null;
|
} else return null;
|
||||||
@ -1310,7 +1307,6 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
.question_mark => {
|
.question_mark => {
|
||||||
current_type = (try resolveUnwrapOptionalType(
|
current_type = (try resolveUnwrapOptionalType(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
current_type orelse return null,
|
current_type orelse return null,
|
||||||
&bound_type_params,
|
&bound_type_params,
|
||||||
)) orelse return null;
|
)) orelse return null;
|
||||||
@ -1324,7 +1320,6 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
.period_asterisk => {
|
.period_asterisk => {
|
||||||
current_type = (try resolveDerefType(
|
current_type = (try resolveDerefType(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
current_type orelse return null,
|
current_type orelse return null,
|
||||||
&bound_type_params,
|
&bound_type_params,
|
||||||
)) orelse return null;
|
)) orelse return null;
|
||||||
@ -1350,7 +1345,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
const body = cur_tree.nodes.items(.data)[current_type_node].rhs;
|
const body = cur_tree.nodes.items(.data)[current_type_node].rhs;
|
||||||
|
|
||||||
// TODO Actually bind params here when calling functions instead of just skipping args.
|
// TODO Actually bind params here when calling functions instead of just skipping args.
|
||||||
if (try resolveReturnType(store, arena, func, current_type.?.handle, &bound_type_params, if (has_body) body else null)) |ret| {
|
if (try resolveReturnType(store, func, current_type.?.handle, &bound_type_params, if (has_body) body else null)) |ret| {
|
||||||
current_type = ret;
|
current_type = ret;
|
||||||
// Skip to the right paren
|
// Skip to the right paren
|
||||||
var paren_count: usize = 1;
|
var paren_count: usize = 1;
|
||||||
@ -1381,7 +1376,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
}
|
}
|
||||||
} else return null;
|
} else return null;
|
||||||
|
|
||||||
current_type = (try resolveBracketAccessType(store, arena, current_type orelse return null, if (is_range) .Range else .Single, &bound_type_params)) orelse return null;
|
current_type = (try resolveBracketAccessType(store, current_type orelse return null, if (is_range) .Range else .Single, &bound_type_params)) orelse return null;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
log.debug("Unimplemented token: {}", .{tok.tag});
|
log.debug("Unimplemented token: {}", .{tok.tag});
|
||||||
@ -1393,7 +1388,7 @@ pub fn getFieldAccessType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
if (current_type) |ct| {
|
if (current_type) |ct| {
|
||||||
return FieldAccessReturn{
|
return FieldAccessReturn{
|
||||||
.original = ct,
|
.original = ct,
|
||||||
.unwrapped = try resolveDerefType(store, arena, ct, &bound_type_params),
|
.unwrapped = try resolveDerefType(store, ct, &bound_type_params),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -2021,14 +2016,13 @@ pub const DeclWithHandle = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolveType(self: DeclWithHandle, store: *DocumentStore, arena: *std.heap.ArenaAllocator, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
pub fn resolveType(self: DeclWithHandle, store: *DocumentStore, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
|
||||||
const tree = self.handle.tree;
|
const tree = self.handle.tree;
|
||||||
const node_tags = tree.nodes.items(.tag);
|
const node_tags = tree.nodes.items(.tag);
|
||||||
const main_tokens = tree.nodes.items(.main_token);
|
const main_tokens = tree.nodes.items(.main_token);
|
||||||
return switch (self.decl.*) {
|
return switch (self.decl.*) {
|
||||||
.ast_node => |node| try resolveTypeOfNodeInternal(
|
.ast_node => |node| try resolveTypeOfNodeInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = node, .handle = self.handle },
|
.{ .node = node, .handle = self.handle },
|
||||||
bound_type_params,
|
bound_type_params,
|
||||||
),
|
),
|
||||||
@ -2048,15 +2042,13 @@ pub const DeclWithHandle = struct {
|
|||||||
}
|
}
|
||||||
return ((try resolveTypeOfNodeInternal(
|
return ((try resolveTypeOfNodeInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = param_decl.type_expr, .handle = self.handle },
|
.{ .node = param_decl.type_expr, .handle = self.handle },
|
||||||
bound_type_params,
|
bound_type_params,
|
||||||
)) orelse return null).instanceTypeVal();
|
)) orelse return null).instanceTypeVal();
|
||||||
},
|
},
|
||||||
.pointer_payload => |pay| try resolveUnwrapOptionalType(
|
.pointer_payload => |pay| try resolveUnwrapOptionalType(
|
||||||
store,
|
store,
|
||||||
arena,
|
(try resolveTypeOfNodeInternal(store, .{
|
||||||
(try resolveTypeOfNodeInternal(store, arena, .{
|
|
||||||
.node = pay.condition,
|
.node = pay.condition,
|
||||||
.handle = self.handle,
|
.handle = self.handle,
|
||||||
}, bound_type_params)) orelse return null,
|
}, bound_type_params)) orelse return null,
|
||||||
@ -2064,8 +2056,7 @@ pub const DeclWithHandle = struct {
|
|||||||
),
|
),
|
||||||
.array_payload => |pay| try resolveBracketAccessType(
|
.array_payload => |pay| try resolveBracketAccessType(
|
||||||
store,
|
store,
|
||||||
arena,
|
(try resolveTypeOfNodeInternal(store, .{
|
||||||
(try resolveTypeOfNodeInternal(store, arena, .{
|
|
||||||
.node = pay.array_expr,
|
.node = pay.array_expr,
|
||||||
.handle = self.handle,
|
.handle = self.handle,
|
||||||
}, bound_type_params)) orelse return null,
|
}, bound_type_params)) orelse return null,
|
||||||
@ -2080,7 +2071,7 @@ pub const DeclWithHandle = struct {
|
|||||||
.switch_payload => |pay| {
|
.switch_payload => |pay| {
|
||||||
if (pay.items.len == 0) return null;
|
if (pay.items.len == 0) return null;
|
||||||
// TODO Peer type resolution, we just use the first item for now.
|
// TODO Peer type resolution, we just use the first item for now.
|
||||||
const switch_expr_type = (try resolveTypeOfNodeInternal(store, arena, .{
|
const switch_expr_type = (try resolveTypeOfNodeInternal(store, .{
|
||||||
.node = pay.switch_expr,
|
.node = pay.switch_expr,
|
||||||
.handle = self.handle,
|
.handle = self.handle,
|
||||||
}, bound_type_params)) orelse return null;
|
}, bound_type_params)) orelse return null;
|
||||||
@ -2100,7 +2091,6 @@ pub const DeclWithHandle = struct {
|
|||||||
if (container_field.ast.type_expr != 0) {
|
if (container_field.ast.type_expr != 0) {
|
||||||
return ((try resolveTypeOfNodeInternal(
|
return ((try resolveTypeOfNodeInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = container_field.ast.type_expr, .handle = switch_expr_type.handle },
|
.{ .node = container_field.ast.type_expr, .handle = switch_expr_type.handle },
|
||||||
bound_type_params,
|
bound_type_params,
|
||||||
)) orelse return null).instanceTypeVal();
|
)) orelse return null).instanceTypeVal();
|
||||||
@ -2132,7 +2122,7 @@ fn findContainerScopeIndex(container_handle: NodeWithHandle) ?usize {
|
|||||||
} else null;
|
} else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
|
fn iterateSymbolsContainerInternal(store: *DocumentStore, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
|
||||||
const container = container_handle.node;
|
const container = container_handle.node;
|
||||||
const handle = container_handle.handle;
|
const handle = container_handle.handle;
|
||||||
|
|
||||||
@ -2179,7 +2169,7 @@ fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.Arena
|
|||||||
try use_trail.append(use);
|
try use_trail.append(use);
|
||||||
|
|
||||||
const lhs = tree.nodes.items(.data)[use].lhs;
|
const lhs = tree.nodes.items(.data)[use].lhs;
|
||||||
const use_expr = (try resolveTypeOfNode(store, arena, .{
|
const use_expr = (try resolveTypeOfNode(store, .{
|
||||||
.node = lhs,
|
.node = lhs,
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
})) orelse continue;
|
})) orelse continue;
|
||||||
@ -2190,7 +2180,6 @@ fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.Arena
|
|||||||
};
|
};
|
||||||
try iterateSymbolsContainerInternal(
|
try iterateSymbolsContainerInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = use_expr_node, .handle = use_expr.handle },
|
.{ .node = use_expr_node, .handle = use_expr.handle },
|
||||||
orig_handle,
|
orig_handle,
|
||||||
callback,
|
callback,
|
||||||
@ -2231,9 +2220,10 @@ pub fn iterateEnclosingScopes(document_scope: DocumentScope, source_index: usize
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterateSymbolsContainer(store: *DocumentStore, arena: *std.heap.ArenaAllocator, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool) error{OutOfMemory}!void {
|
pub fn iterateSymbolsContainer(store: *DocumentStore, container_handle: NodeWithHandle, orig_handle: *const DocumentStore.Handle, comptime callback: anytype, context: anytype, instance_access: bool) error{OutOfMemory}!void {
|
||||||
var use_trail = std.ArrayList(Ast.Node.Index).init(arena.allocator());
|
var use_trail = std.ArrayList(Ast.Node.Index).init(store.allocator);
|
||||||
return try iterateSymbolsContainerInternal(store, arena, container_handle, orig_handle, callback, context, instance_access, &use_trail);
|
defer use_trail.deinit();
|
||||||
|
return try iterateSymbolsContainerInternal(store, container_handle, orig_handle, callback, context, instance_access, &use_trail);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterateLabels(handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
|
pub fn iterateLabels(handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
|
||||||
@ -2252,7 +2242,7 @@ pub fn iterateLabels(handle: *const DocumentStore.Handle, source_index: usize, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
|
fn iterateSymbolsGlobalInternal(store: *DocumentStore, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype, use_trail: *std.ArrayList(Ast.Node.Index)) error{OutOfMemory}!void {
|
||||||
const scope_decls = handle.document_scope.scopes.items(.decls);
|
const scope_decls = handle.document_scope.scopes.items(.decls);
|
||||||
const scope_uses = handle.document_scope.scopes.items(.uses);
|
const scope_uses = handle.document_scope.scopes.items(.uses);
|
||||||
|
|
||||||
@ -2272,7 +2262,6 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
|
|||||||
|
|
||||||
const use_expr = (try resolveTypeOfNode(
|
const use_expr = (try resolveTypeOfNode(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = handle.tree.nodes.items(.data)[use].lhs, .handle = handle },
|
.{ .node = handle.tree.nodes.items(.data)[use].lhs, .handle = handle },
|
||||||
)) orelse continue;
|
)) orelse continue;
|
||||||
const use_expr_node = switch (use_expr.type.data) {
|
const use_expr_node = switch (use_expr.type.data) {
|
||||||
@ -2281,7 +2270,6 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
|
|||||||
};
|
};
|
||||||
try iterateSymbolsContainerInternal(
|
try iterateSymbolsContainerInternal(
|
||||||
store,
|
store,
|
||||||
arena,
|
|
||||||
.{ .node = use_expr_node, .handle = use_expr.handle },
|
.{ .node = use_expr_node, .handle = use_expr.handle },
|
||||||
handle,
|
handle,
|
||||||
callback,
|
callback,
|
||||||
@ -2293,9 +2281,10 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterateSymbolsGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
|
pub fn iterateSymbolsGlobal(store: *DocumentStore, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
|
||||||
var use_trail = std.ArrayList(Ast.Node.Index).init(arena.allocator());
|
var use_trail = std.ArrayList(Ast.Node.Index).init(store.allocator);
|
||||||
return try iterateSymbolsGlobalInternal(store, arena, handle, source_index, callback, context, &use_trail);
|
defer use_trail.deinit();
|
||||||
|
return try iterateSymbolsGlobalInternal(store, handle, source_index, callback, context, &use_trail);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn innermostBlockScopeIndex(handle: DocumentStore.Handle, source_index: usize) usize {
|
pub fn innermostBlockScopeIndex(handle: DocumentStore.Handle, source_index: usize) usize {
|
||||||
@ -2340,7 +2329,7 @@ pub fn innermostContainer(handle: *const DocumentStore.Handle, source_index: usi
|
|||||||
return TypeWithHandle.typeVal(.{ .node = current, .handle = handle });
|
return TypeWithHandle.typeVal(.{ .node = current, .handle = handle });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolveUse(store: *DocumentStore, arena: *std.heap.ArenaAllocator, uses: []const Ast.Node.Index, symbol: []const u8, handle: *const DocumentStore.Handle) error{OutOfMemory}!?DeclWithHandle {
|
fn resolveUse(store: *DocumentStore, uses: []const Ast.Node.Index, symbol: []const u8, handle: *const DocumentStore.Handle) error{OutOfMemory}!?DeclWithHandle {
|
||||||
if (uses.len == 0) return null;
|
if (uses.len == 0) return null;
|
||||||
|
|
||||||
// If we were asked to resolve this symbol before,
|
// If we were asked to resolve this symbol before,
|
||||||
@ -2354,7 +2343,7 @@ fn resolveUse(store: *DocumentStore, arena: *std.heap.ArenaAllocator, uses: []co
|
|||||||
if (handle.tree.nodes.items(.data).len <= index) continue;
|
if (handle.tree.nodes.items(.data).len <= index) continue;
|
||||||
|
|
||||||
const expr = .{ .node = handle.tree.nodes.items(.data)[index].lhs, .handle = handle };
|
const expr = .{ .node = handle.tree.nodes.items(.data)[index].lhs, .handle = handle };
|
||||||
const expr_type_node = (try resolveTypeOfNode(store, arena, expr)) orelse
|
const expr_type_node = (try resolveTypeOfNode(store, expr)) orelse
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const expr_type = .{
|
const expr_type = .{
|
||||||
@ -2365,7 +2354,7 @@ fn resolveUse(store: *DocumentStore, arena: *std.heap.ArenaAllocator, uses: []co
|
|||||||
.handle = expr_type_node.handle,
|
.handle = expr_type_node.handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (try lookupSymbolContainer(store, arena, expr_type, symbol, false)) |candidate| {
|
if (try lookupSymbolContainer(store, expr_type, symbol, false)) |candidate| {
|
||||||
if (candidate.handle == handle or candidate.isPublic()) {
|
if (candidate.handle == handle or candidate.isPublic()) {
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
@ -2393,7 +2382,7 @@ pub fn lookupLabel(handle: *const DocumentStore.Handle, symbol: []const u8, sour
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookupSymbolGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, symbol: []const u8, source_index: usize) error{OutOfMemory}!?DeclWithHandle {
|
pub fn lookupSymbolGlobal(store: *DocumentStore, handle: *const DocumentStore.Handle, symbol: []const u8, source_index: usize) error{OutOfMemory}!?DeclWithHandle {
|
||||||
const innermost_scope_idx = innermostBlockScopeIndex(handle.*, source_index);
|
const innermost_scope_idx = innermostBlockScopeIndex(handle.*, source_index);
|
||||||
|
|
||||||
const scope_locs = handle.document_scope.scopes.items(.loc);
|
const scope_locs = handle.document_scope.scopes.items(.loc);
|
||||||
@ -2417,7 +2406,7 @@ pub fn lookupSymbolGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
.handle = handle,
|
.handle = handle,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (try resolveUse(store, arena, scope_uses[curr].items, symbol, handle)) |result| return result;
|
if (try resolveUse(store, scope_uses[curr].items, symbol, handle)) |result| return result;
|
||||||
}
|
}
|
||||||
if (curr == 0) break;
|
if (curr == 0) break;
|
||||||
}
|
}
|
||||||
@ -2426,7 +2415,6 @@ pub fn lookupSymbolGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
|
|
||||||
pub fn lookupSymbolContainer(
|
pub fn lookupSymbolContainer(
|
||||||
store: *DocumentStore,
|
store: *DocumentStore,
|
||||||
arena: *std.heap.ArenaAllocator,
|
|
||||||
container_handle: NodeWithHandle,
|
container_handle: NodeWithHandle,
|
||||||
symbol: []const u8,
|
symbol: []const u8,
|
||||||
/// If true, we are looking up the symbol like we are accessing through a field access
|
/// If true, we are looking up the symbol like we are accessing through a field access
|
||||||
@ -2459,7 +2447,7 @@ pub fn lookupSymbolContainer(
|
|||||||
return DeclWithHandle{ .decl = candidate.value_ptr, .handle = handle };
|
return DeclWithHandle{ .decl = candidate.value_ptr, .handle = handle };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try resolveUse(store, arena, scope_uses[container_scope_index].items, symbol, handle)) |result| return result;
|
if (try resolveUse(store, scope_uses[container_scope_index].items, symbol, handle)) |result| return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -9,7 +9,7 @@ const types = @import("lsp.zig");
|
|||||||
const offsets = @import("offsets.zig");
|
const offsets = @import("offsets.zig");
|
||||||
|
|
||||||
pub const Builder = struct {
|
pub const Builder = struct {
|
||||||
arena: *std.heap.ArenaAllocator,
|
arena: std.mem.Allocator,
|
||||||
document_store: *DocumentStore,
|
document_store: *DocumentStore,
|
||||||
handle: *const DocumentStore.Handle,
|
handle: *const DocumentStore.Handle,
|
||||||
offset_encoding: offsets.Encoding,
|
offset_encoding: offsets.Encoding,
|
||||||
@ -54,9 +54,8 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn createWorkspaceEdit(self: *Builder, edits: []const types.TextEdit) error{OutOfMemory}!types.WorkspaceEdit {
|
pub fn createWorkspaceEdit(self: *Builder, edits: []const types.TextEdit) error{OutOfMemory}!types.WorkspaceEdit {
|
||||||
const allocator = self.arena.allocator();
|
|
||||||
var workspace_edit = types.WorkspaceEdit{ .changes = .{} };
|
var workspace_edit = types.WorkspaceEdit{ .changes = .{} };
|
||||||
try workspace_edit.changes.?.putNoClobber(allocator, self.handle.uri, try allocator.dupe(types.TextEdit, edits));
|
try workspace_edit.changes.?.putNoClobber(self.arena, self.handle.uri, try self.arena.dupe(types.TextEdit, edits));
|
||||||
|
|
||||||
return workspace_edit;
|
return workspace_edit;
|
||||||
}
|
}
|
||||||
@ -67,7 +66,7 @@ fn handleNonCamelcaseFunction(builder: *Builder, actions: *std.ArrayListUnmanage
|
|||||||
|
|
||||||
if (std.mem.allEqual(u8, identifier_name, '_')) return;
|
if (std.mem.allEqual(u8, identifier_name, '_')) return;
|
||||||
|
|
||||||
const new_text = try createCamelcaseText(builder.arena.allocator(), identifier_name);
|
const new_text = try createCamelcaseText(builder.arena, identifier_name);
|
||||||
|
|
||||||
const action1 = types.CodeAction{
|
const action1 = types.CodeAction{
|
||||||
.title = "make function name camelCase",
|
.title = "make function name camelCase",
|
||||||
@ -76,7 +75,7 @@ fn handleNonCamelcaseFunction(builder: *Builder, actions: *std.ArrayListUnmanage
|
|||||||
.edit = try builder.createWorkspaceEdit(&.{builder.createTextEditLoc(loc, new_text)}),
|
.edit = try builder.createWorkspaceEdit(&.{builder.createTextEditLoc(loc, new_text)}),
|
||||||
};
|
};
|
||||||
|
|
||||||
try actions.append(builder.arena.allocator(), action1);
|
try actions.append(builder.arena, action1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleUnusedFunctionParameter(builder: *Builder, actions: *std.ArrayListUnmanaged(types.CodeAction), loc: offsets.Loc) !void {
|
fn handleUnusedFunctionParameter(builder: *Builder, actions: *std.ArrayListUnmanaged(types.CodeAction), loc: offsets.Loc) !void {
|
||||||
@ -91,7 +90,6 @@ fn handleUnusedFunctionParameter(builder: *Builder, actions: *std.ArrayListUnman
|
|||||||
|
|
||||||
const decl = (try analysis.lookupSymbolGlobal(
|
const decl = (try analysis.lookupSymbolGlobal(
|
||||||
builder.document_store,
|
builder.document_store,
|
||||||
builder.arena,
|
|
||||||
builder.handle,
|
builder.handle,
|
||||||
identifier_name,
|
identifier_name,
|
||||||
loc.start,
|
loc.start,
|
||||||
@ -125,7 +123,7 @@ fn handleUnusedFunctionParameter(builder: *Builder, actions: *std.ArrayListUnman
|
|||||||
.edit = try builder.createWorkspaceEdit(&.{builder.createTextEditLoc(getParamRemovalRange(tree, payload.param), "")}),
|
.edit = try builder.createWorkspaceEdit(&.{builder.createTextEditLoc(getParamRemovalRange(tree, payload.param), "")}),
|
||||||
};
|
};
|
||||||
|
|
||||||
try actions.appendSlice(builder.arena.allocator(), &.{ action1, action2 });
|
try actions.appendSlice(builder.arena, &.{ action1, action2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleUnusedVariableOrConstant(builder: *Builder, actions: *std.ArrayListUnmanaged(types.CodeAction), loc: offsets.Loc) !void {
|
fn handleUnusedVariableOrConstant(builder: *Builder, actions: *std.ArrayListUnmanaged(types.CodeAction), loc: offsets.Loc) !void {
|
||||||
@ -137,7 +135,6 @@ fn handleUnusedVariableOrConstant(builder: *Builder, actions: *std.ArrayListUnma
|
|||||||
|
|
||||||
const decl = (try analysis.lookupSymbolGlobal(
|
const decl = (try analysis.lookupSymbolGlobal(
|
||||||
builder.document_store,
|
builder.document_store,
|
||||||
builder.arena,
|
|
||||||
builder.handle,
|
builder.handle,
|
||||||
identifier_name,
|
identifier_name,
|
||||||
loc.start,
|
loc.start,
|
||||||
@ -157,7 +154,7 @@ fn handleUnusedVariableOrConstant(builder: *Builder, actions: *std.ArrayListUnma
|
|||||||
|
|
||||||
const index = token_starts[last_token] + 1;
|
const index = token_starts[last_token] + 1;
|
||||||
|
|
||||||
try actions.append(builder.arena.allocator(), .{
|
try actions.append(builder.arena, .{
|
||||||
.title = "discard value",
|
.title = "discard value",
|
||||||
.kind = .@"source.fixAll",
|
.kind = .@"source.fixAll",
|
||||||
.isPreferred = true,
|
.isPreferred = true,
|
||||||
@ -174,7 +171,7 @@ fn handleUnusedIndexCapture(builder: *Builder, actions: *std.ArrayListUnmanaged(
|
|||||||
if (is_value_discarded) {
|
if (is_value_discarded) {
|
||||||
// |_, i| ->
|
// |_, i| ->
|
||||||
// TODO fix formatting
|
// TODO fix formatting
|
||||||
try actions.append(builder.arena.allocator(), .{
|
try actions.append(builder.arena, .{
|
||||||
.title = "remove capture",
|
.title = "remove capture",
|
||||||
.kind = .quickfix,
|
.kind = .quickfix,
|
||||||
.isPreferred = true,
|
.isPreferred = true,
|
||||||
@ -183,7 +180,7 @@ fn handleUnusedIndexCapture(builder: *Builder, actions: *std.ArrayListUnmanaged(
|
|||||||
} else {
|
} else {
|
||||||
// |v, i| -> |v|
|
// |v, i| -> |v|
|
||||||
// |v, _| -> |v|
|
// |v, _| -> |v|
|
||||||
try actions.append(builder.arena.allocator(), .{
|
try actions.append(builder.arena, .{
|
||||||
.title = "remove index capture",
|
.title = "remove index capture",
|
||||||
.kind = .quickfix,
|
.kind = .quickfix,
|
||||||
.isPreferred = true,
|
.isPreferred = true,
|
||||||
@ -202,7 +199,7 @@ fn handleUnusedCapture(builder: *Builder, actions: *std.ArrayListUnmanaged(types
|
|||||||
// by adding a discard in the block scope
|
// by adding a discard in the block scope
|
||||||
if (capture_locs.index != null) {
|
if (capture_locs.index != null) {
|
||||||
// |v, i| -> |_, i|
|
// |v, i| -> |_, i|
|
||||||
try actions.append(builder.arena.allocator(), .{
|
try actions.append(builder.arena, .{
|
||||||
.title = "discard capture",
|
.title = "discard capture",
|
||||||
.kind = .quickfix,
|
.kind = .quickfix,
|
||||||
.isPreferred = true,
|
.isPreferred = true,
|
||||||
@ -211,7 +208,7 @@ fn handleUnusedCapture(builder: *Builder, actions: *std.ArrayListUnmanaged(types
|
|||||||
} else {
|
} else {
|
||||||
// |v| ->
|
// |v| ->
|
||||||
// TODO fix formatting
|
// TODO fix formatting
|
||||||
try actions.append(builder.arena.allocator(), .{
|
try actions.append(builder.arena, .{
|
||||||
.title = "remove capture",
|
.title = "remove capture",
|
||||||
.kind = .quickfix,
|
.kind = .quickfix,
|
||||||
.isPreferred = true,
|
.isPreferred = true,
|
||||||
@ -223,7 +220,7 @@ fn handleUnusedCapture(builder: *Builder, actions: *std.ArrayListUnmanaged(types
|
|||||||
fn handlePointlessDiscard(builder: *Builder, actions: *std.ArrayListUnmanaged(types.CodeAction), loc: offsets.Loc) !void {
|
fn handlePointlessDiscard(builder: *Builder, actions: *std.ArrayListUnmanaged(types.CodeAction), loc: offsets.Loc) !void {
|
||||||
const edit_loc = getDiscardLoc(builder.handle.text, loc) orelse return;
|
const edit_loc = getDiscardLoc(builder.handle.text, loc) orelse return;
|
||||||
|
|
||||||
try actions.append(builder.arena.allocator(), .{
|
try actions.append(builder.arena, .{
|
||||||
.title = "remove pointless discard",
|
.title = "remove pointless discard",
|
||||||
.kind = .@"source.fixAll",
|
.kind = .@"source.fixAll",
|
||||||
.isPreferred = true,
|
.isPreferred = true,
|
||||||
@ -300,10 +297,8 @@ fn createDiscardText(builder: *Builder, identifier_name: []const u8, declaration
|
|||||||
};
|
};
|
||||||
const additional_indent = if (add_block_indentation) detectIndentation(builder.handle.text) else "";
|
const additional_indent = if (add_block_indentation) detectIndentation(builder.handle.text) else "";
|
||||||
|
|
||||||
const allocator = builder.arena.allocator();
|
|
||||||
const new_text_len = 1 + indent.len + additional_indent.len + "_ = ;".len + identifier_name.len;
|
const new_text_len = 1 + indent.len + additional_indent.len + "_ = ;".len + identifier_name.len;
|
||||||
var new_text = try std.ArrayListUnmanaged(u8).initCapacity(allocator, new_text_len);
|
var new_text = try std.ArrayListUnmanaged(u8).initCapacity(builder.arena, new_text_len);
|
||||||
errdefer new_text.deinit(allocator);
|
|
||||||
|
|
||||||
new_text.appendAssumeCapacity('\n');
|
new_text.appendAssumeCapacity('\n');
|
||||||
new_text.appendSliceAssumeCapacity(indent);
|
new_text.appendSliceAssumeCapacity(indent);
|
||||||
@ -312,7 +307,7 @@ fn createDiscardText(builder: *Builder, identifier_name: []const u8, declaration
|
|||||||
new_text.appendSliceAssumeCapacity(identifier_name);
|
new_text.appendSliceAssumeCapacity(identifier_name);
|
||||||
new_text.appendAssumeCapacity(';');
|
new_text.appendAssumeCapacity(';');
|
||||||
|
|
||||||
return new_text.toOwnedSlice(allocator);
|
return new_text.toOwnedSlice(builder.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getParamRemovalRange(tree: Ast, param: Ast.full.FnProto.Param) offsets.Loc {
|
fn getParamRemovalRange(tree: Ast, param: Ast.full.FnProto.Param) offsets.Loc {
|
||||||
|
@ -24,7 +24,7 @@ pub const InlayHint = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Builder = struct {
|
const Builder = struct {
|
||||||
arena: *std.heap.ArenaAllocator,
|
arena: std.mem.Allocator,
|
||||||
store: *DocumentStore,
|
store: *DocumentStore,
|
||||||
config: *const Config,
|
config: *const Config,
|
||||||
handle: *const DocumentStore.Handle,
|
handle: *const DocumentStore.Handle,
|
||||||
@ -38,15 +38,15 @@ const Builder = struct {
|
|||||||
const prefix = if (tooltip_noalias) if (tooltip_comptime) "noalias comptime " else "noalias " else if (tooltip_comptime) "comptime " else "";
|
const prefix = if (tooltip_noalias) if (tooltip_comptime) "noalias comptime " else "noalias " else if (tooltip_comptime) "comptime " else "";
|
||||||
|
|
||||||
if (self.hover_kind == .markdown) {
|
if (self.hover_kind == .markdown) {
|
||||||
break :blk try std.fmt.allocPrint(self.arena.allocator(), "```zig\n{s}{s}\n```", .{ prefix, tooltip });
|
break :blk try std.fmt.allocPrint(self.arena, "```zig\n{s}{s}\n```", .{ prefix, tooltip });
|
||||||
}
|
}
|
||||||
|
|
||||||
break :blk try std.fmt.allocPrint(self.arena.allocator(), "{s}{s}", .{ prefix, tooltip });
|
break :blk try std.fmt.allocPrint(self.arena, "{s}{s}", .{ prefix, tooltip });
|
||||||
};
|
};
|
||||||
|
|
||||||
try self.hints.append(self.arena.allocator(), .{
|
try self.hints.append(self.arena, .{
|
||||||
.token_index = token_index,
|
.token_index = token_index,
|
||||||
.label = try std.fmt.allocPrint(self.arena.allocator(), "{s}:", .{label}),
|
.label = try std.fmt.allocPrint(self.arena, "{s}:", .{label}),
|
||||||
.kind = .Parameter,
|
.kind = .Parameter,
|
||||||
.tooltip = .{
|
.tooltip = .{
|
||||||
.kind = self.hover_kind,
|
.kind = self.hover_kind,
|
||||||
@ -56,7 +56,7 @@ const Builder = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn toOwnedSlice(self: *Builder) error{OutOfMemory}![]InlayHint {
|
fn toOwnedSlice(self: *Builder) error{OutOfMemory}![]InlayHint {
|
||||||
return self.hints.toOwnedSlice(self.arena.allocator());
|
return self.hints.toOwnedSlice(self.arena);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ fn writeCallHint(builder: *Builder, call: Ast.full.Call, decl_handle: analysis.D
|
|||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
var it = fn_proto.iterate(&decl_tree);
|
var it = fn_proto.iterate(&decl_tree);
|
||||||
|
|
||||||
if (try analysis.hasSelfParam(builder.arena, builder.store, decl_handle.handle, fn_proto)) {
|
if (try analysis.hasSelfParam(builder.store, decl_handle.handle, fn_proto)) {
|
||||||
_ = ast.nextFnParam(&it);
|
_ = ast.nextFnParam(&it);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ fn writeCallNodeHint(builder: *Builder, call: Ast.full.Call) !void {
|
|||||||
const source_index = offsets.tokenToIndex(tree, main_tokens[call.ast.fn_expr]);
|
const source_index = offsets.tokenToIndex(tree, main_tokens[call.ast.fn_expr]);
|
||||||
const name = offsets.tokenToSlice(tree, main_tokens[call.ast.fn_expr]);
|
const name = offsets.tokenToSlice(tree, main_tokens[call.ast.fn_expr]);
|
||||||
|
|
||||||
if (try analysis.lookupSymbolGlobal(builder.store, builder.arena, handle, name, source_index)) |decl_handle| {
|
if (try analysis.lookupSymbolGlobal(builder.store, handle, name, source_index)) |decl_handle| {
|
||||||
try writeCallHint(builder, call, decl_handle);
|
try writeCallHint(builder, call, decl_handle);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -191,18 +191,17 @@ fn writeCallNodeHint(builder: *Builder, call: Ast.full.Call) !void {
|
|||||||
const start = offsets.tokenToIndex(tree, lhsToken);
|
const start = offsets.tokenToIndex(tree, lhsToken);
|
||||||
const rhs_loc = offsets.tokenToLoc(tree, rhsToken);
|
const rhs_loc = offsets.tokenToLoc(tree, rhsToken);
|
||||||
|
|
||||||
var held_range = try builder.arena.allocator().dupeZ(u8, handle.text[start..rhs_loc.end]);
|
var held_range = try builder.arena.dupeZ(u8, handle.text[start..rhs_loc.end]);
|
||||||
var tokenizer = std.zig.Tokenizer.init(held_range);
|
var tokenizer = std.zig.Tokenizer.init(held_range);
|
||||||
|
|
||||||
// note: we have the ast node, traversing it would probably yield better results
|
// note: we have the ast node, traversing it would probably yield better results
|
||||||
// than trying to re-tokenize and re-parse it
|
// than trying to re-tokenize and re-parse it
|
||||||
if (try analysis.getFieldAccessType(builder.store, builder.arena, handle, rhs_loc.end, &tokenizer)) |result| {
|
if (try analysis.getFieldAccessType(builder.store, handle, rhs_loc.end, &tokenizer)) |result| {
|
||||||
const container_handle = result.unwrapped orelse result.original;
|
const container_handle = result.unwrapped orelse result.original;
|
||||||
switch (container_handle.type.data) {
|
switch (container_handle.type.data) {
|
||||||
.other => |container_handle_node| {
|
.other => |container_handle_node| {
|
||||||
if (try analysis.lookupSymbolContainer(
|
if (try analysis.lookupSymbolContainer(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
.{ .node = container_handle_node, .handle = container_handle.handle },
|
.{ .node = container_handle_node, .handle = container_handle.handle },
|
||||||
tree.tokenSlice(rhsToken),
|
tree.tokenSlice(rhsToken),
|
||||||
true,
|
true,
|
||||||
@ -276,7 +275,7 @@ fn writeNodeInlayHint(
|
|||||||
/// only parameter hints are created
|
/// only parameter hints are created
|
||||||
/// only hints in the given loc are created
|
/// only hints in the given loc are created
|
||||||
pub fn writeRangeInlayHint(
|
pub fn writeRangeInlayHint(
|
||||||
arena: *std.heap.ArenaAllocator,
|
arena: std.mem.Allocator,
|
||||||
config: Config,
|
config: Config,
|
||||||
store: *DocumentStore,
|
store: *DocumentStore,
|
||||||
handle: *const DocumentStore.Handle,
|
handle: *const DocumentStore.Handle,
|
||||||
@ -292,7 +291,7 @@ pub fn writeRangeInlayHint(
|
|||||||
.hover_kind = hover_kind,
|
.hover_kind = hover_kind,
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodes = try ast.nodesAtLoc(arena.allocator(), handle.tree, loc);
|
const nodes = try ast.nodesAtLoc(arena, handle.tree, loc);
|
||||||
|
|
||||||
for (nodes) |child| {
|
for (nodes) |child| {
|
||||||
try writeNodeInlayHint(&builder, child);
|
try writeNodeInlayHint(&builder, child);
|
||||||
|
@ -54,7 +54,7 @@ pub fn labelReferences(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Builder = struct {
|
const Builder = struct {
|
||||||
arena: *std.heap.ArenaAllocator,
|
allocator: std.mem.Allocator,
|
||||||
locations: std.ArrayListUnmanaged(types.Location) = .{},
|
locations: std.ArrayListUnmanaged(types.Location) = .{},
|
||||||
/// this is the declaration we are searching for
|
/// this is the declaration we are searching for
|
||||||
decl_handle: analysis.DeclWithHandle,
|
decl_handle: analysis.DeclWithHandle,
|
||||||
@ -66,8 +66,12 @@ const Builder = struct {
|
|||||||
handle: *const DocumentStore.Handle,
|
handle: *const DocumentStore.Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn deinit(self: *Builder) void {
|
||||||
|
self.locations.deinit(self.allocator);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add(self: *Builder, handle: *const DocumentStore.Handle, token_index: Ast.TokenIndex) error{OutOfMemory}!void {
|
pub fn add(self: *Builder, handle: *const DocumentStore.Handle, token_index: Ast.TokenIndex) error{OutOfMemory}!void {
|
||||||
try self.locations.append(self.arena.allocator(), .{
|
try self.locations.append(self.allocator, .{
|
||||||
.uri = handle.uri,
|
.uri = handle.uri,
|
||||||
.range = offsets.tokenToRange(handle.tree, token_index, self.encoding),
|
.range = offsets.tokenToRange(handle.tree, token_index, self.encoding),
|
||||||
});
|
});
|
||||||
@ -96,7 +100,6 @@ const Builder = struct {
|
|||||||
|
|
||||||
const child = (try analysis.lookupSymbolGlobal(
|
const child = (try analysis.lookupSymbolGlobal(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
handle,
|
handle,
|
||||||
offsets.tokenToSlice(handle.tree, identifier_token),
|
offsets.tokenToSlice(handle.tree, identifier_token),
|
||||||
starts[identifier_token],
|
starts[identifier_token],
|
||||||
@ -108,12 +111,11 @@ const Builder = struct {
|
|||||||
},
|
},
|
||||||
.field_access => {
|
.field_access => {
|
||||||
var bound_type_params = analysis.BoundTypeParams{};
|
var bound_type_params = analysis.BoundTypeParams{};
|
||||||
|
defer bound_type_params.deinit(builder.store.allocator);
|
||||||
const left_type = try analysis.resolveFieldAccessLhsType(
|
const left_type = try analysis.resolveFieldAccessLhsType(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
(try analysis.resolveTypeOfNodeInternal(
|
(try analysis.resolveTypeOfNodeInternal(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
.{ .node = datas[node].lhs, .handle = handle },
|
.{ .node = datas[node].lhs, .handle = handle },
|
||||||
&bound_type_params,
|
&bound_type_params,
|
||||||
)) orelse return,
|
)) orelse return,
|
||||||
@ -127,7 +129,6 @@ const Builder = struct {
|
|||||||
|
|
||||||
const child = (try analysis.lookupSymbolContainer(
|
const child = (try analysis.lookupSymbolContainer(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
.{ .node = left_type_node, .handle = left_type.handle },
|
.{ .node = left_type_node, .handle = left_type.handle },
|
||||||
offsets.tokenToSlice(handle.tree, datas[node].rhs),
|
offsets.tokenToSlice(handle.tree, datas[node].rhs),
|
||||||
!left_type.type.is_type_val,
|
!left_type.type.is_type_val,
|
||||||
@ -143,7 +144,7 @@ const Builder = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn symbolReferences(
|
pub fn symbolReferences(
|
||||||
arena: *std.heap.ArenaAllocator,
|
allocator: std.mem.Allocator,
|
||||||
store: *DocumentStore,
|
store: *DocumentStore,
|
||||||
decl_handle: analysis.DeclWithHandle,
|
decl_handle: analysis.DeclWithHandle,
|
||||||
encoding: offsets.Encoding,
|
encoding: offsets.Encoding,
|
||||||
@ -157,11 +158,12 @@ pub fn symbolReferences(
|
|||||||
std.debug.assert(decl_handle.decl.* != .label_decl); // use `labelReferences` instead
|
std.debug.assert(decl_handle.decl.* != .label_decl); // use `labelReferences` instead
|
||||||
|
|
||||||
var builder = Builder{
|
var builder = Builder{
|
||||||
.arena = arena,
|
.allocator = allocator,
|
||||||
.store = store,
|
.store = store,
|
||||||
.decl_handle = decl_handle,
|
.decl_handle = decl_handle,
|
||||||
.encoding = encoding,
|
.encoding = encoding,
|
||||||
};
|
};
|
||||||
|
errdefer builder.deinit();
|
||||||
|
|
||||||
const curr_handle = decl_handle.handle;
|
const curr_handle = decl_handle.handle;
|
||||||
if (include_decl) try builder.add(curr_handle, decl_handle.nameToken());
|
if (include_decl) try builder.add(curr_handle, decl_handle.nameToken());
|
||||||
@ -178,6 +180,12 @@ pub fn symbolReferences(
|
|||||||
if (decl_handle.decl.* != .ast_node or !workspace) return builder.locations;
|
if (decl_handle.decl.* != .ast_node or !workspace) return builder.locations;
|
||||||
|
|
||||||
var dependencies = std.StringArrayHashMapUnmanaged(void){};
|
var dependencies = std.StringArrayHashMapUnmanaged(void){};
|
||||||
|
defer {
|
||||||
|
for (dependencies.keys()) |uri| {
|
||||||
|
allocator.free(uri);
|
||||||
|
}
|
||||||
|
dependencies.deinit(allocator);
|
||||||
|
}
|
||||||
|
|
||||||
for (store.handles.values()) |handle| {
|
for (store.handles.values()) |handle| {
|
||||||
if (skip_std_references and std.mem.indexOf(u8, handle.uri, "std") != null) {
|
if (skip_std_references and std.mem.indexOf(u8, handle.uri, "std") != null) {
|
||||||
@ -186,10 +194,17 @@ pub fn symbolReferences(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var handle_dependencies = std.ArrayListUnmanaged([]const u8){};
|
var handle_dependencies = std.ArrayListUnmanaged([]const u8){};
|
||||||
try store.collectDependencies(arena.allocator(), handle.*, &handle_dependencies);
|
defer {
|
||||||
|
for (handle_dependencies.items) |uri| {
|
||||||
|
allocator.free(uri);
|
||||||
|
}
|
||||||
|
handle_dependencies.deinit(allocator);
|
||||||
|
}
|
||||||
|
try store.collectDependencies(allocator, handle.*, &handle_dependencies);
|
||||||
|
|
||||||
|
try dependencies.ensureUnusedCapacity(allocator, handle_dependencies.items.len);
|
||||||
for (handle_dependencies.items) |uri| {
|
for (handle_dependencies.items) |uri| {
|
||||||
try dependencies.put(arena.allocator(), uri, {});
|
dependencies.putAssumeCapacity(uri, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ fn writeNodeTokens(builder: *Builder, maybe_node: ?Ast.Node.Index) error{OutOfMe
|
|||||||
try writeToken(builder, var_decl.comptime_token, .keyword);
|
try writeToken(builder, var_decl.comptime_token, .keyword);
|
||||||
try writeToken(builder, var_decl.ast.mut_token, .keyword);
|
try writeToken(builder, var_decl.ast.mut_token, .keyword);
|
||||||
|
|
||||||
if (try analysis.resolveTypeOfNode(builder.store, builder.arena, .{ .node = node, .handle = handle })) |decl_type| {
|
if (try analysis.resolveTypeOfNode(builder.store, .{ .node = node, .handle = handle })) |decl_type| {
|
||||||
try colorIdentifierBasedOnType(builder, decl_type, var_decl.ast.mut_token + 1, .{ .declaration = true });
|
try colorIdentifierBasedOnType(builder, decl_type, var_decl.ast.mut_token + 1, .{ .declaration = true });
|
||||||
} else {
|
} else {
|
||||||
try writeTokenMod(builder, var_decl.ast.mut_token + 1, .variable, .{ .declaration = true });
|
try writeTokenMod(builder, var_decl.ast.mut_token + 1, .variable, .{ .declaration = true });
|
||||||
@ -418,7 +418,6 @@ fn writeNodeTokens(builder: *Builder, maybe_node: ?Ast.Node.Index) error{OutOfMe
|
|||||||
|
|
||||||
if (try analysis.lookupSymbolGlobal(
|
if (try analysis.lookupSymbolGlobal(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
handle,
|
handle,
|
||||||
name,
|
name,
|
||||||
tree.tokens.items(.start)[main_token],
|
tree.tokens.items(.start)[main_token],
|
||||||
@ -427,7 +426,9 @@ fn writeNodeTokens(builder: *Builder, maybe_node: ?Ast.Node.Index) error{OutOfMe
|
|||||||
return try writeToken(builder, main_token, .parameter);
|
return try writeToken(builder, main_token, .parameter);
|
||||||
}
|
}
|
||||||
var bound_type_params = analysis.BoundTypeParams{};
|
var bound_type_params = analysis.BoundTypeParams{};
|
||||||
if (try child.resolveType(builder.store, builder.arena, &bound_type_params)) |decl_type| {
|
defer bound_type_params.deinit(builder.store.allocator);
|
||||||
|
|
||||||
|
if (try child.resolveType(builder.store, &bound_type_params)) |decl_type| {
|
||||||
try colorIdentifierBasedOnType(builder, decl_type, main_token, .{});
|
try colorIdentifierBasedOnType(builder, decl_type, main_token, .{});
|
||||||
} else {
|
} else {
|
||||||
try writeTokenMod(builder, main_token, .variable, .{});
|
try writeTokenMod(builder, main_token, .variable, .{});
|
||||||
@ -628,7 +629,6 @@ fn writeNodeTokens(builder: *Builder, maybe_node: ?Ast.Node.Index) error{OutOfMe
|
|||||||
|
|
||||||
field_token_type = if (try analysis.resolveTypeOfNode(
|
field_token_type = if (try analysis.resolveTypeOfNode(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
.{ .node = struct_init.ast.type_expr, .handle = handle },
|
.{ .node = struct_init.ast.type_expr, .handle = handle },
|
||||||
)) |struct_type| switch (struct_type.type.data) {
|
)) |struct_type| switch (struct_type.type.data) {
|
||||||
.other => |type_node| if (ast.isContainer(struct_type.handle.tree, type_node))
|
.other => |type_node| if (ast.isContainer(struct_type.handle.tree, type_node))
|
||||||
@ -843,12 +843,12 @@ fn writeNodeTokens(builder: *Builder, maybe_node: ?Ast.Node.Index) error{OutOfMe
|
|||||||
// writeToken code.
|
// writeToken code.
|
||||||
// Maybe we can hook into it insead? Also applies to Identifier and VarDecl
|
// Maybe we can hook into it insead? Also applies to Identifier and VarDecl
|
||||||
var bound_type_params = analysis.BoundTypeParams{};
|
var bound_type_params = analysis.BoundTypeParams{};
|
||||||
|
defer bound_type_params.deinit(builder.store.allocator);
|
||||||
|
|
||||||
const lhs_type = try analysis.resolveFieldAccessLhsType(
|
const lhs_type = try analysis.resolveFieldAccessLhsType(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
(try analysis.resolveTypeOfNodeInternal(
|
(try analysis.resolveTypeOfNodeInternal(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
.{ .node = data.lhs, .handle = handle },
|
.{ .node = data.lhs, .handle = handle },
|
||||||
&bound_type_params,
|
&bound_type_params,
|
||||||
)) orelse return,
|
)) orelse return,
|
||||||
@ -860,7 +860,6 @@ fn writeNodeTokens(builder: *Builder, maybe_node: ?Ast.Node.Index) error{OutOfMe
|
|||||||
};
|
};
|
||||||
if (try analysis.lookupSymbolContainer(
|
if (try analysis.lookupSymbolContainer(
|
||||||
builder.store,
|
builder.store,
|
||||||
builder.arena,
|
|
||||||
.{ .node = left_type_node, .handle = lhs_type.handle },
|
.{ .node = left_type_node, .handle = lhs_type.handle },
|
||||||
tree.tokenSlice(data.rhs),
|
tree.tokenSlice(data.rhs),
|
||||||
!lhs_type.type.is_type_val,
|
!lhs_type.type.is_type_val,
|
||||||
@ -884,7 +883,7 @@ fn writeNodeTokens(builder: *Builder, maybe_node: ?Ast.Node.Index) error{OutOfMe
|
|||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try decl_type.resolveType(builder.store, builder.arena, &bound_type_params)) |resolved_type| {
|
if (try decl_type.resolveType(builder.store, &bound_type_params)) |resolved_type| {
|
||||||
try colorIdentifierBasedOnType(builder, resolved_type, data.rhs, .{});
|
try colorIdentifierBasedOnType(builder, resolved_type, data.rhs, .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ fn fnProtoToSignatureInfo(document_store: *DocumentStore, arena: *std.heap.Arena
|
|||||||
const proto_comments = (try analysis.getDocComments(alloc, tree, fn_node, .markdown)) orelse "";
|
const proto_comments = (try analysis.getDocComments(alloc, tree, fn_node, .markdown)) orelse "";
|
||||||
|
|
||||||
const arg_idx = if (skip_self_param) blk: {
|
const arg_idx = if (skip_self_param) blk: {
|
||||||
const has_self_param = try analysis.hasSelfParam(arena, document_store, handle, proto);
|
const has_self_param = try analysis.hasSelfParam(document_store, handle, proto);
|
||||||
break :blk commas + @boolToInt(has_self_param);
|
break :blk commas + @boolToInt(has_self_param);
|
||||||
} else commas;
|
} else commas;
|
||||||
|
|
||||||
@ -260,7 +260,6 @@ pub fn getSignatureInfo(document_store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
var tokenizer = std.zig.Tokenizer.init(held_expr);
|
var tokenizer = std.zig.Tokenizer.init(held_expr);
|
||||||
if (try analysis.getFieldAccessType(
|
if (try analysis.getFieldAccessType(
|
||||||
document_store,
|
document_store,
|
||||||
arena,
|
|
||||||
handle,
|
handle,
|
||||||
expr_start,
|
expr_start,
|
||||||
&tokenizer,
|
&tokenizer,
|
||||||
@ -296,7 +295,6 @@ pub fn getSignatureInfo(document_store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
const skip_self_param = !type_handle.type.is_type_val;
|
const skip_self_param = !type_handle.type.is_type_val;
|
||||||
const decl_handle = (try analysis.lookupSymbolContainer(
|
const decl_handle = (try analysis.lookupSymbolContainer(
|
||||||
document_store,
|
document_store,
|
||||||
arena,
|
|
||||||
.{ .node = node, .handle = type_handle.handle },
|
.{ .node = node, .handle = type_handle.handle },
|
||||||
name,
|
name,
|
||||||
true,
|
true,
|
||||||
@ -315,7 +313,6 @@ pub fn getSignatureInfo(document_store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
|
|
||||||
if (try analysis.resolveVarDeclAlias(
|
if (try analysis.resolveVarDeclAlias(
|
||||||
document_store,
|
document_store,
|
||||||
arena,
|
|
||||||
.{ .node = node, .handle = decl_handle.handle },
|
.{ .node = node, .handle = decl_handle.handle },
|
||||||
)) |resolved| {
|
)) |resolved| {
|
||||||
switch (resolved.decl.*) {
|
switch (resolved.decl.*) {
|
||||||
|
Loading…
Reference in New Issue
Block a user