replace ArrayList with MultiArrayList in DocumentScope (#938)
This commit is contained in:
parent
ed9cf06d5f
commit
d2586f79a1
293
src/analysis.zig
293
src/analysis.zig
@ -975,8 +975,8 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
};
|
};
|
||||||
|
|
||||||
const new_handle = store.getOrLoadHandle(builtin_uri) orelse return null;
|
const new_handle = store.getOrLoadHandle(builtin_uri) orelse return null;
|
||||||
const root_scope = new_handle.document_scope.scopes.items[0];
|
const root_scope_decls = new_handle.document_scope.scopes.items(.decls)[0];
|
||||||
const decl = root_scope.decls.get("Type") orelse return null;
|
const decl = root_scope_decls.get("Type") orelse return null;
|
||||||
if (decl != .ast_node) return null;
|
if (decl != .ast_node) return null;
|
||||||
|
|
||||||
const var_decl = ast.varDecl(new_handle.tree, decl.ast_node) orelse return null;
|
const var_decl = ast.varDecl(new_handle.tree, decl.ast_node) orelse return null;
|
||||||
@ -2089,9 +2089,13 @@ pub const DeclWithHandle = struct {
|
|||||||
if (!switch_expr_type.isUnionType())
|
if (!switch_expr_type.isUnionType())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (node_tags[pay.items[0]] == .enum_literal) {
|
if (node_tags[pay.items[0]] != .enum_literal) return null;
|
||||||
const scope = findContainerScope(.{ .node = switch_expr_type.type.data.other, .handle = switch_expr_type.handle }) orelse return null;
|
|
||||||
if (scope.decls.getEntry(tree.tokenSlice(main_tokens[pay.items[0]]))) |candidate| {
|
const scope_index = findContainerScopeIndex(.{ .node = switch_expr_type.type.data.other, .handle = switch_expr_type.handle }) orelse return null;
|
||||||
|
const scope_decls = switch_expr_type.handle.document_scope.scopes.items(.decls);
|
||||||
|
|
||||||
|
const candidate = scope_decls[scope_index].getEntry(tree.tokenSlice(main_tokens[pay.items[0]])) orelse return null;
|
||||||
|
|
||||||
switch (candidate.value_ptr.*) {
|
switch (candidate.value_ptr.*) {
|
||||||
.ast_node => |node| {
|
.ast_node => |node| {
|
||||||
if (ast.containerField(switch_expr_type.handle.tree, node)) |container_field| {
|
if (ast.containerField(switch_expr_type.handle.tree, node)) |container_field| {
|
||||||
@ -2108,26 +2112,22 @@ pub const DeclWithHandle = struct {
|
|||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
.error_token => return null,
|
.error_token => return null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn findContainerScope(container_handle: NodeWithHandle) ?*Scope {
|
fn findContainerScopeIndex(container_handle: NodeWithHandle) ?usize {
|
||||||
const container = container_handle.node;
|
const container = container_handle.node;
|
||||||
const handle = container_handle.handle;
|
const handle = container_handle.handle;
|
||||||
|
|
||||||
if (!ast.isContainer(handle.tree, container)) return null;
|
if (!ast.isContainer(handle.tree, container)) return null;
|
||||||
|
|
||||||
// Find the container scope.
|
return for (handle.document_scope.scopes.items(.data)) |data, scope_index| {
|
||||||
return for (handle.document_scope.scopes.items) |*scope| {
|
switch (data) {
|
||||||
switch (scope.data) {
|
|
||||||
.container => |node| if (node == container) {
|
.container => |node| if (node == container) {
|
||||||
break scope;
|
break scope_index;
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
@ -2145,9 +2145,11 @@ fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.Arena
|
|||||||
|
|
||||||
const is_enum = token_tags[main_token] == .keyword_enum;
|
const is_enum = token_tags[main_token] == .keyword_enum;
|
||||||
|
|
||||||
const container_scope = findContainerScope(container_handle) orelse return;
|
const scope_decls = handle.document_scope.scopes.items(.decls);
|
||||||
|
const scope_uses = handle.document_scope.scopes.items(.uses);
|
||||||
|
const container_scope_index = findContainerScopeIndex(container_handle) orelse return;
|
||||||
|
|
||||||
var decl_it = container_scope.decls.iterator();
|
var decl_it = scope_decls[container_scope_index].iterator();
|
||||||
while (decl_it.next()) |entry| {
|
while (decl_it.next()) |entry| {
|
||||||
switch (entry.value_ptr.*) {
|
switch (entry.value_ptr.*) {
|
||||||
.ast_node => |node| {
|
.ast_node => |node| {
|
||||||
@ -2171,7 +2173,7 @@ fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.Arena
|
|||||||
try callback(context, decl);
|
try callback(context, decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (container_scope.uses.items) |use| {
|
for (scope_uses[container_scope_index].items) |use| {
|
||||||
const use_token = tree.nodes.items(.main_token)[use];
|
const use_token = tree.nodes.items(.main_token)[use];
|
||||||
const is_pub = use_token > 0 and token_tags[use_token - 1] == .keyword_pub;
|
const is_pub = use_token > 0 and token_tags[use_token - 1] == .keyword_pub;
|
||||||
if (handle != orig_handle and !is_pub) continue;
|
if (handle != orig_handle and !is_pub) continue;
|
||||||
@ -2201,15 +2203,47 @@ fn iterateSymbolsContainerInternal(store: *DocumentStore, arena: *std.heap.Arena
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const EnclosingScopeIterator = struct {
|
||||||
|
scope_locs: []offsets.Loc,
|
||||||
|
current_scope: usize,
|
||||||
|
source_index: usize,
|
||||||
|
|
||||||
|
pub fn next(self: *EnclosingScopeIterator) ?usize {
|
||||||
|
while (self.current_scope < self.scope_locs.len) : (self.current_scope += 1) {
|
||||||
|
const scope_loc = self.scope_locs[self.current_scope];
|
||||||
|
|
||||||
|
if (self.source_index >= scope_loc.start and self.source_index <= scope_loc.end) {
|
||||||
|
defer self.current_scope += 1;
|
||||||
|
return self.current_scope;
|
||||||
|
}
|
||||||
|
if (scope_loc.start >= self.source_index) {
|
||||||
|
self.current_scope = self.scope_locs.len;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn iterateEnclosingScopes(document_scope: DocumentScope, source_index: usize) EnclosingScopeIterator {
|
||||||
|
return .{
|
||||||
|
.scope_locs = document_scope.scopes.items(.loc),
|
||||||
|
.current_scope = 0,
|
||||||
|
.source_index = source_index,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
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, arena: *std.heap.ArenaAllocator, 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(arena.allocator());
|
||||||
return try iterateSymbolsContainerInternal(store, arena, container_handle, orig_handle, callback, context, instance_access, &use_trail);
|
return try iterateSymbolsContainerInternal(store, arena, 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 {
|
||||||
for (handle.document_scope.scopes.items) |scope| {
|
const scope_decls = handle.document_scope.scopes.items(.decls);
|
||||||
if (source_index >= scope.loc.start and source_index < scope.loc.end) {
|
|
||||||
var decl_it = scope.decls.iterator();
|
var scope_iterator = iterateEnclosingScopes(handle.document_scope, source_index);
|
||||||
|
while (scope_iterator.next()) |scope_index| {
|
||||||
|
var decl_it = scope_decls[scope_index].iterator();
|
||||||
while (decl_it.next()) |entry| {
|
while (decl_it.next()) |entry| {
|
||||||
switch (entry.value_ptr.*) {
|
switch (entry.value_ptr.*) {
|
||||||
.label_decl => {},
|
.label_decl => {},
|
||||||
@ -2218,14 +2252,15 @@ pub fn iterateLabels(handle: *const DocumentStore.Handle, source_index: usize, c
|
|||||||
try callback(context, DeclWithHandle{ .decl = entry.value_ptr, .handle = handle });
|
try callback(context, DeclWithHandle{ .decl = entry.value_ptr, .handle = handle });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scope.loc.start >= source_index) return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, 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 {
|
||||||
for (handle.document_scope.scopes.items) |scope| {
|
const scope_decls = handle.document_scope.scopes.items(.decls);
|
||||||
if (source_index >= scope.loc.start and source_index <= scope.loc.end) {
|
const scope_uses = handle.document_scope.scopes.items(.uses);
|
||||||
var decl_it = scope.decls.iterator();
|
|
||||||
|
var scope_iterator = iterateEnclosingScopes(handle.document_scope, source_index);
|
||||||
|
while (scope_iterator.next()) |scope_index| {
|
||||||
|
var decl_it = scope_decls[scope_index].iterator();
|
||||||
while (decl_it.next()) |entry| {
|
while (decl_it.next()) |entry| {
|
||||||
if (entry.value_ptr.* == .ast_node and
|
if (entry.value_ptr.* == .ast_node and
|
||||||
handle.tree.nodes.items(.tag)[entry.value_ptr.*.ast_node].isContainerField()) continue;
|
handle.tree.nodes.items(.tag)[entry.value_ptr.*.ast_node].isContainerField()) continue;
|
||||||
@ -2233,7 +2268,7 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
|
|||||||
try callback(context, DeclWithHandle{ .decl = entry.value_ptr, .handle = handle });
|
try callback(context, DeclWithHandle{ .decl = entry.value_ptr, .handle = handle });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (scope.uses.items) |use| {
|
for (scope_uses[scope_index].items) |use| {
|
||||||
if (std.mem.indexOfScalar(Ast.Node.Index, use_trail.items, use) != null) continue;
|
if (std.mem.indexOfScalar(Ast.Node.Index, use_trail.items, use) != null) continue;
|
||||||
try use_trail.append(use);
|
try use_trail.append(use);
|
||||||
|
|
||||||
@ -2258,9 +2293,6 @@ fn iterateSymbolsGlobalInternal(store: *DocumentStore, arena: *std.heap.ArenaAll
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scope.loc.start >= source_index) return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, arena: *std.heap.ArenaAllocator, handle: *const DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
|
||||||
@ -2269,42 +2301,50 @@ pub fn iterateSymbolsGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocat
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn innermostBlockScopeIndex(handle: DocumentStore.Handle, source_index: usize) usize {
|
pub fn innermostBlockScopeIndex(handle: DocumentStore.Handle, source_index: usize) usize {
|
||||||
if (handle.document_scope.scopes.items.len == 1) return 0;
|
if (handle.document_scope.scopes.len == 1) return 0;
|
||||||
|
|
||||||
var current: usize = 0;
|
const scope_locs = handle.document_scope.scopes.items(.loc);
|
||||||
for (handle.document_scope.scopes.items[1..]) |*scope, idx| {
|
const scope_datas = handle.document_scope.scopes.items(.data);
|
||||||
if (source_index >= scope.loc.start and source_index <= scope.loc.end) {
|
|
||||||
switch (scope.data) {
|
var innermost: usize = 0;
|
||||||
.container, .function, .block => current = idx + 1,
|
var scope_index: usize = 1;
|
||||||
|
while (scope_index < handle.document_scope.scopes.len) : (scope_index += 1) {
|
||||||
|
const scope_loc = scope_locs[scope_index];
|
||||||
|
if (source_index >= scope_loc.start and source_index <= scope_loc.end) {
|
||||||
|
switch (scope_datas[scope_index]) {
|
||||||
|
.container, .function, .block => innermost = scope_index,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scope.loc.start > source_index) break;
|
if (scope_loc.start > source_index) break;
|
||||||
}
|
}
|
||||||
return current;
|
return innermost;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn innermostBlockScope(handle: DocumentStore.Handle, source_index: usize) Ast.Node.Index {
|
pub fn innermostBlockScope(handle: DocumentStore.Handle, source_index: usize) Ast.Node.Index {
|
||||||
return handle.document_scope.scopes.items[innermostBlockScopeIndex(handle, source_index)].toNodeIndex().?;
|
const scope_index = innermostBlockScopeIndex(handle, source_index);
|
||||||
|
return handle.document_scope.scopes.items(.data)[scope_index].toNodeIndex().?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn innermostContainer(handle: *const DocumentStore.Handle, source_index: usize) TypeWithHandle {
|
pub fn innermostContainer(handle: *const DocumentStore.Handle, source_index: usize) TypeWithHandle {
|
||||||
var current = handle.document_scope.scopes.items[0].data.container;
|
const scope_datas = handle.document_scope.scopes.items(.data);
|
||||||
if (handle.document_scope.scopes.items.len == 1) return TypeWithHandle.typeVal(.{ .node = current, .handle = handle });
|
|
||||||
|
|
||||||
for (handle.document_scope.scopes.items[1..]) |scope| {
|
var current = scope_datas[0].container;
|
||||||
if (source_index >= scope.loc.start and source_index <= scope.loc.end) {
|
if (handle.document_scope.scopes.len == 1) return TypeWithHandle.typeVal(.{ .node = current, .handle = handle });
|
||||||
switch (scope.data) {
|
|
||||||
|
var scope_iterator = iterateEnclosingScopes(handle.document_scope, source_index);
|
||||||
|
while (scope_iterator.next()) |scope_index| {
|
||||||
|
switch (scope_datas[scope_index]) {
|
||||||
.container => |node| current = node,
|
.container => |node| current = node,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scope.loc.start > source_index) break;
|
|
||||||
}
|
|
||||||
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, arena: *std.heap.ArenaAllocator, uses: []const Ast.Node.Index, symbol: []const u8, handle: *const DocumentStore.Handle) error{OutOfMemory}!?DeclWithHandle {
|
||||||
|
if (uses.len == 0) return null;
|
||||||
|
|
||||||
// If we were asked to resolve this symbol before,
|
// If we were asked to resolve this symbol before,
|
||||||
// it is self-referential and we cannot resolve it.
|
// it is self-referential and we cannot resolve it.
|
||||||
if (std.mem.indexOfScalar([*]const u8, using_trail.items, symbol.ptr) != null)
|
if (std.mem.indexOfScalar([*]const u8, using_trail.items, symbol.ptr) != null)
|
||||||
@ -2337,9 +2377,12 @@ fn resolveUse(store: *DocumentStore, arena: *std.heap.ArenaAllocator, uses: []co
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookupLabel(handle: *const DocumentStore.Handle, symbol: []const u8, source_index: usize) error{OutOfMemory}!?DeclWithHandle {
|
pub fn lookupLabel(handle: *const DocumentStore.Handle, symbol: []const u8, source_index: usize) error{OutOfMemory}!?DeclWithHandle {
|
||||||
for (handle.document_scope.scopes.items) |scope| {
|
const scope_decls = handle.document_scope.scopes.items(.decls);
|
||||||
if (source_index >= scope.loc.start and source_index < scope.loc.end) {
|
|
||||||
if (scope.decls.getEntry(symbol)) |candidate| {
|
var scope_iterator = iterateEnclosingScopes(handle.document_scope, source_index);
|
||||||
|
while (scope_iterator.next()) |scope_index| {
|
||||||
|
const candidate = scope_decls[scope_index].getEntry(symbol) orelse continue;
|
||||||
|
|
||||||
switch (candidate.value_ptr.*) {
|
switch (candidate.value_ptr.*) {
|
||||||
.label_decl => {},
|
.label_decl => {},
|
||||||
else => continue,
|
else => continue,
|
||||||
@ -2349,20 +2392,21 @@ pub fn lookupLabel(handle: *const DocumentStore.Handle, symbol: []const u8, sour
|
|||||||
.handle = handle,
|
.handle = handle,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (scope.loc.start > source_index) return null;
|
|
||||||
}
|
|
||||||
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, arena: *std.heap.ArenaAllocator, 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_decls = handle.document_scope.scopes.items(.decls);
|
||||||
|
const scope_uses = handle.document_scope.scopes.items(.uses);
|
||||||
|
|
||||||
var curr = innermost_scope_idx;
|
var curr = innermost_scope_idx;
|
||||||
while (curr >= 0) : (curr -= 1) {
|
while (curr >= 0) : (curr -= 1) {
|
||||||
const scope = &handle.document_scope.scopes.items[curr];
|
const scope_loc = scope_locs[curr];
|
||||||
if (source_index >= scope.loc.start and source_index <= scope.loc.end) blk: {
|
if (source_index >= scope_loc.start and source_index <= scope_loc.end) blk: {
|
||||||
if (scope.decls.getEntry(symbol)) |candidate| {
|
if (scope_decls[curr].getEntry(symbol)) |candidate| {
|
||||||
switch (candidate.value_ptr.*) {
|
switch (candidate.value_ptr.*) {
|
||||||
.ast_node => |node| {
|
.ast_node => |node| {
|
||||||
if (handle.tree.nodes.items(.tag)[node].isContainerField()) break :blk;
|
if (handle.tree.nodes.items(.tag)[node].isContainerField()) break :blk;
|
||||||
@ -2375,7 +2419,7 @@ pub fn lookupSymbolGlobal(store: *DocumentStore, arena: *std.heap.ArenaAllocator
|
|||||||
.handle = handle,
|
.handle = handle,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (try resolveUse(store, arena, scope.uses.items, symbol, handle)) |result| return result;
|
if (try resolveUse(store, arena, scope_uses[curr].items, symbol, handle)) |result| return result;
|
||||||
}
|
}
|
||||||
if (curr == 0) break;
|
if (curr == 0) break;
|
||||||
}
|
}
|
||||||
@ -2399,9 +2443,11 @@ pub fn lookupSymbolContainer(
|
|||||||
const main_token = tree.nodes.items(.main_token)[container];
|
const main_token = tree.nodes.items(.main_token)[container];
|
||||||
|
|
||||||
const is_enum = token_tags[main_token] == .keyword_enum;
|
const is_enum = token_tags[main_token] == .keyword_enum;
|
||||||
|
const scope_decls = handle.document_scope.scopes.items(.decls);
|
||||||
|
const scope_uses = handle.document_scope.scopes.items(.uses);
|
||||||
|
|
||||||
if (findContainerScope(container_handle)) |container_scope| {
|
if (findContainerScopeIndex(container_handle)) |container_scope_index| {
|
||||||
if (container_scope.decls.getEntry(symbol)) |candidate| {
|
if (scope_decls[container_scope_index].getEntry(symbol)) |candidate| {
|
||||||
switch (candidate.value_ptr.*) {
|
switch (candidate.value_ptr.*) {
|
||||||
.ast_node => |node| {
|
.ast_node => |node| {
|
||||||
if (node_tags[node].isContainerField()) {
|
if (node_tags[node].isContainerField()) {
|
||||||
@ -2415,8 +2461,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, container_scope.uses.items, symbol, handle)) |result| return result;
|
if (try resolveUse(store, arena, scope_uses[container_scope_index].items, symbol, handle)) |result| return result;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -2446,15 +2491,19 @@ comptime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const DocumentScope = struct {
|
pub const DocumentScope = struct {
|
||||||
scopes: std.ArrayListUnmanaged(Scope),
|
scopes: std.MultiArrayList(Scope),
|
||||||
error_completions: CompletionSet,
|
error_completions: CompletionSet,
|
||||||
enum_completions: CompletionSet,
|
enum_completions: CompletionSet,
|
||||||
|
|
||||||
pub fn deinit(self: *DocumentScope, allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *DocumentScope, allocator: std.mem.Allocator) void {
|
||||||
for (self.scopes.items) |*scope| {
|
var i: usize = 0;
|
||||||
scope.deinit(allocator);
|
while (i < self.scopes.len) : (i += 1) {
|
||||||
|
self.scopes.items(.decls)[i].deinit(allocator);
|
||||||
|
self.scopes.items(.tests)[i].deinit(allocator);
|
||||||
|
self.scopes.items(.uses)[i].deinit(allocator);
|
||||||
}
|
}
|
||||||
self.scopes.deinit(allocator);
|
self.scopes.deinit(allocator);
|
||||||
|
|
||||||
for (self.error_completions.entries.items(.key)) |item| {
|
for (self.error_completions.entries.items(.key)) |item| {
|
||||||
if (item.detail) |detail| allocator.free(detail);
|
if (item.detail) |detail| allocator.free(detail);
|
||||||
switch (item.documentation orelse continue) {
|
switch (item.documentation orelse continue) {
|
||||||
@ -2480,6 +2529,13 @@ pub const Scope = struct {
|
|||||||
function: Ast.Node.Index, // .tag is FnProto
|
function: Ast.Node.Index, // .tag is FnProto
|
||||||
block: Ast.Node.Index, // .tag is Block
|
block: Ast.Node.Index, // .tag is Block
|
||||||
other,
|
other,
|
||||||
|
|
||||||
|
pub fn toNodeIndex(self: Data) ?Ast.Node.Index {
|
||||||
|
return switch (self) {
|
||||||
|
.container, .function, .block => |idx| idx,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
loc: offsets.Loc,
|
loc: offsets.Loc,
|
||||||
@ -2487,19 +2543,6 @@ pub const Scope = struct {
|
|||||||
tests: std.ArrayListUnmanaged(Ast.Node.Index) = .{},
|
tests: std.ArrayListUnmanaged(Ast.Node.Index) = .{},
|
||||||
uses: std.ArrayListUnmanaged(Ast.Node.Index) = .{},
|
uses: std.ArrayListUnmanaged(Ast.Node.Index) = .{},
|
||||||
data: Data,
|
data: Data,
|
||||||
|
|
||||||
pub fn deinit(self: *Scope, allocator: std.mem.Allocator) void {
|
|
||||||
self.decls.deinit(allocator);
|
|
||||||
self.tests.deinit(allocator);
|
|
||||||
self.uses.deinit(allocator);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn toNodeIndex(self: Scope) ?Ast.Node.Index {
|
|
||||||
return switch (self.data) {
|
|
||||||
.container, .function, .block => |idx| idx,
|
|
||||||
else => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn makeDocumentScope(allocator: std.mem.Allocator, tree: Ast) !DocumentScope {
|
pub fn makeDocumentScope(allocator: std.mem.Allocator, tree: Ast) !DocumentScope {
|
||||||
@ -2523,7 +2566,7 @@ pub fn makeDocumentScope(allocator: std.mem.Allocator, tree: Ast) !DocumentScope
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ScopeContext = struct {
|
const ScopeContext = struct {
|
||||||
scopes: *std.ArrayListUnmanaged(Scope),
|
scopes: *std.MultiArrayList(Scope),
|
||||||
enums: *CompletionSet,
|
enums: *CompletionSet,
|
||||||
errors: *CompletionSet,
|
errors: *CompletionSet,
|
||||||
tree: Ast,
|
tree: Ast,
|
||||||
@ -2538,12 +2581,11 @@ fn makeInnerScope(allocator: std.mem.Allocator, context: ScopeContext, node_idx:
|
|||||||
const main_tokens = tree.nodes.items(.main_token);
|
const main_tokens = tree.nodes.items(.main_token);
|
||||||
const node_tag = tags[node_idx];
|
const node_tag = tags[node_idx];
|
||||||
|
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = offsets.nodeToLoc(tree, node_idx),
|
.loc = offsets.nodeToLoc(tree, node_idx),
|
||||||
.data = .{ .container = node_idx },
|
.data = .{ .container = node_idx },
|
||||||
};
|
});
|
||||||
const scope_idx = scopes.items.len - 1;
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
if (node_tag == .error_set_decl) {
|
if (node_tag == .error_set_decl) {
|
||||||
// All identifiers in main_token..data.lhs are error fields.
|
// All identifiers in main_token..data.lhs are error fields.
|
||||||
@ -2551,7 +2593,7 @@ fn makeInnerScope(allocator: std.mem.Allocator, context: ScopeContext, node_idx:
|
|||||||
while (i < data[node_idx].rhs) : (i += 1) {
|
while (i < data[node_idx].rhs) : (i += 1) {
|
||||||
if (token_tags[i] == .identifier) {
|
if (token_tags[i] == .identifier) {
|
||||||
const name = offsets.tokenToSlice(tree, i);
|
const name = offsets.tokenToSlice(tree, i);
|
||||||
if (try scopes.items[scope_idx].decls.fetchPut(allocator, name, .{ .error_token = i })) |_| {
|
if (try scopes.items(.decls)[scope_index].fetchPut(allocator, name, .{ .error_token = i })) |_| {
|
||||||
// TODO Record a redefinition error.
|
// TODO Record a redefinition error.
|
||||||
}
|
}
|
||||||
const gop = try context.errors.getOrPut(allocator, .{
|
const gop = try context.errors.getOrPut(allocator, .{
|
||||||
@ -2572,7 +2614,7 @@ fn makeInnerScope(allocator: std.mem.Allocator, context: ScopeContext, node_idx:
|
|||||||
const ast_decls = ast.declMembers(tree, node_idx, &buf);
|
const ast_decls = ast.declMembers(tree, node_idx, &buf);
|
||||||
for (ast_decls) |decl| {
|
for (ast_decls) |decl| {
|
||||||
if (tags[decl] == .@"usingnamespace") {
|
if (tags[decl] == .@"usingnamespace") {
|
||||||
try scopes.items[scope_idx].uses.append(allocator, decl);
|
try scopes.items(.uses)[scope_index].append(allocator, decl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2580,10 +2622,10 @@ fn makeInnerScope(allocator: std.mem.Allocator, context: ScopeContext, node_idx:
|
|||||||
const name = getDeclName(tree, decl) orelse continue;
|
const name = getDeclName(tree, decl) orelse continue;
|
||||||
|
|
||||||
if (tags[decl] == .test_decl) {
|
if (tags[decl] == .test_decl) {
|
||||||
try scopes.items[scope_idx].tests.append(allocator, decl);
|
try scopes.items(.tests)[scope_index].append(allocator, decl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (try scopes.items[scope_idx].decls.fetchPut(allocator, name, .{ .ast_node = decl })) |existing| {
|
if (try scopes.items(.decls)[scope_index].fetchPut(allocator, name, .{ .ast_node = decl })) |existing| {
|
||||||
_ = existing;
|
_ = existing;
|
||||||
// TODO Record a redefinition error.
|
// TODO Record a redefinition error.
|
||||||
}
|
}
|
||||||
@ -2663,13 +2705,13 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
.loc = offsets.nodeToLoc(tree, node_idx),
|
.loc = offsets.nodeToLoc(tree, node_idx),
|
||||||
.data = .{ .function = node_idx },
|
.data = .{ .function = node_idx },
|
||||||
});
|
});
|
||||||
const scope_idx = scopes.items.len - 1;
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
var it = func.iterate(&tree);
|
var it = func.iterate(&tree);
|
||||||
while (ast.nextFnParam(&it)) |param| {
|
while (ast.nextFnParam(&it)) |param| {
|
||||||
// Add parameter decls
|
// Add parameter decls
|
||||||
if (param.name_token) |name_token| {
|
if (param.name_token) |name_token| {
|
||||||
if (try scopes.items[scope_idx].decls.fetchPut(
|
if (try scopes.items(.decls)[scope_index].fetchPut(
|
||||||
allocator,
|
allocator,
|
||||||
tree.tokenSlice(name_token),
|
tree.tokenSlice(name_token),
|
||||||
.{ .param_payload = .{ .param = param, .func = node_idx } },
|
.{ .param_payload = .{ .param = param, .func = node_idx } },
|
||||||
@ -2707,15 +2749,15 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
|
|
||||||
// if labeled block
|
// if labeled block
|
||||||
if (token_tags[first_token] == .identifier) {
|
if (token_tags[first_token] == .identifier) {
|
||||||
const scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, main_tokens[node_idx]),
|
.start = offsets.tokenToIndex(tree, main_tokens[node_idx]),
|
||||||
.end = offsets.tokenToLoc(tree, last_token).start,
|
.end = offsets.tokenToLoc(tree, last_token).start,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
try scope.decls.putNoClobber(allocator, tree.tokenSlice(first_token), .{ .label_decl = .{
|
const scope_index = scopes.len - 1;
|
||||||
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, tree.tokenSlice(first_token), .{ .label_decl = .{
|
||||||
.label = first_token,
|
.label = first_token,
|
||||||
.block = node_idx,
|
.block = node_idx,
|
||||||
} });
|
} });
|
||||||
@ -2725,21 +2767,21 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
.loc = offsets.nodeToLoc(tree, node_idx),
|
.loc = offsets.nodeToLoc(tree, node_idx),
|
||||||
.data = .{ .container = node_idx },
|
.data = .{ .container = node_idx },
|
||||||
});
|
});
|
||||||
const scope_idx = scopes.items.len - 1;
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
var buffer: [2]Ast.Node.Index = undefined;
|
var buffer: [2]Ast.Node.Index = undefined;
|
||||||
const statements = ast.blockStatements(tree, node_idx, &buffer).?;
|
const statements = ast.blockStatements(tree, node_idx, &buffer).?;
|
||||||
|
|
||||||
for (statements) |idx| {
|
for (statements) |idx| {
|
||||||
if (tags[idx] == .@"usingnamespace") {
|
if (tags[idx] == .@"usingnamespace") {
|
||||||
try scopes.items[scope_idx].uses.append(allocator, idx);
|
try scopes.items(.uses)[scope_index].append(allocator, idx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try makeScopeInternal(allocator, context, idx);
|
try makeScopeInternal(allocator, context, idx);
|
||||||
if (ast.varDecl(tree, idx)) |var_decl| {
|
if (ast.varDecl(tree, idx)) |var_decl| {
|
||||||
const name = tree.tokenSlice(var_decl.ast.mut_token + 1);
|
const name = tree.tokenSlice(var_decl.ast.mut_token + 1);
|
||||||
if (try scopes.items[scope_idx].decls.fetchPut(allocator, name, .{ .ast_node = idx })) |existing| {
|
if (try scopes.items(.decls)[scope_index].fetchPut(allocator, name, .{ .ast_node = idx })) |existing| {
|
||||||
_ = existing;
|
_ = existing;
|
||||||
// TODO record a redefinition error.
|
// TODO record a redefinition error.
|
||||||
}
|
}
|
||||||
@ -2754,20 +2796,20 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
const if_node = ast.ifFull(tree, node_idx);
|
const if_node = ast.ifFull(tree, node_idx);
|
||||||
|
|
||||||
if (if_node.payload_token) |payload| {
|
if (if_node.payload_token) |payload| {
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, payload),
|
.start = offsets.tokenToIndex(tree, payload),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, if_node.ast.then_expr)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, if_node.ast.then_expr)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
const name_token = payload + @boolToInt(token_tags[payload] == .asterisk);
|
const name_token = payload + @boolToInt(token_tags[payload] == .asterisk);
|
||||||
std.debug.assert(token_tags[name_token] == .identifier);
|
std.debug.assert(token_tags[name_token] == .identifier);
|
||||||
|
|
||||||
const name = tree.tokenSlice(name_token);
|
const name = tree.tokenSlice(name_token);
|
||||||
try scope.decls.putNoClobber(allocator, name, .{
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, name, .{
|
||||||
.pointer_payload = .{
|
.pointer_payload = .{
|
||||||
.name = name_token,
|
.name = name_token,
|
||||||
.condition = if_node.ast.cond_expr,
|
.condition = if_node.ast.cond_expr,
|
||||||
@ -2780,17 +2822,17 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
if (if_node.ast.else_expr != 0) {
|
if (if_node.ast.else_expr != 0) {
|
||||||
if (if_node.error_token) |err_token| {
|
if (if_node.error_token) |err_token| {
|
||||||
std.debug.assert(token_tags[err_token] == .identifier);
|
std.debug.assert(token_tags[err_token] == .identifier);
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, err_token),
|
.start = offsets.tokenToIndex(tree, err_token),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, if_node.ast.else_expr)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, if_node.ast.else_expr)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
const name = tree.tokenSlice(err_token);
|
const name = tree.tokenSlice(err_token);
|
||||||
try scope.decls.putNoClobber(allocator, name, .{ .ast_node = if_node.ast.else_expr });
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, name, .{ .ast_node = if_node.ast.else_expr });
|
||||||
}
|
}
|
||||||
try makeScopeInternal(allocator, context, if_node.ast.else_expr);
|
try makeScopeInternal(allocator, context, if_node.ast.else_expr);
|
||||||
}
|
}
|
||||||
@ -2801,21 +2843,21 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
const catch_token = main_tokens[node_idx];
|
const catch_token = main_tokens[node_idx];
|
||||||
const catch_expr = data[node_idx].rhs;
|
const catch_expr = data[node_idx].rhs;
|
||||||
|
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, tree.firstToken(catch_expr)),
|
.start = offsets.tokenToIndex(tree, tree.firstToken(catch_expr)),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, catch_expr)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, catch_expr)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
if (token_tags.len > catch_token + 2 and
|
if (token_tags.len > catch_token + 2 and
|
||||||
token_tags[catch_token + 1] == .pipe and
|
token_tags[catch_token + 1] == .pipe and
|
||||||
token_tags[catch_token + 2] == .identifier)
|
token_tags[catch_token + 2] == .identifier)
|
||||||
{
|
{
|
||||||
const name = tree.tokenSlice(catch_token + 2);
|
const name = tree.tokenSlice(catch_token + 2);
|
||||||
try scope.decls.putNoClobber(allocator, name, .{ .ast_node = catch_expr });
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, name, .{ .ast_node = catch_expr });
|
||||||
}
|
}
|
||||||
try makeScopeInternal(allocator, context, catch_expr);
|
try makeScopeInternal(allocator, context, catch_expr);
|
||||||
},
|
},
|
||||||
@ -2830,36 +2872,36 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
|
|
||||||
if (while_node.label_token) |label| {
|
if (while_node.label_token) |label| {
|
||||||
std.debug.assert(token_tags[label] == .identifier);
|
std.debug.assert(token_tags[label] == .identifier);
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, while_node.ast.while_token),
|
.start = offsets.tokenToIndex(tree, while_node.ast.while_token),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, node_idx)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, node_idx)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
try scope.decls.putNoClobber(allocator, tree.tokenSlice(label), .{ .label_decl = .{
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, tree.tokenSlice(label), .{ .label_decl = .{
|
||||||
.label = label,
|
.label = label,
|
||||||
.block = while_node.ast.then_expr,
|
.block = while_node.ast.then_expr,
|
||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (while_node.payload_token) |payload| {
|
if (while_node.payload_token) |payload| {
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, payload),
|
.start = offsets.tokenToIndex(tree, payload),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, while_node.ast.then_expr)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, while_node.ast.then_expr)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
const name_token = payload + @boolToInt(token_tags[payload] == .asterisk);
|
const name_token = payload + @boolToInt(token_tags[payload] == .asterisk);
|
||||||
std.debug.assert(token_tags[name_token] == .identifier);
|
std.debug.assert(token_tags[name_token] == .identifier);
|
||||||
|
|
||||||
const name = tree.tokenSlice(name_token);
|
const name = tree.tokenSlice(name_token);
|
||||||
try scope.decls.putNoClobber(allocator, name, if (is_for) .{
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, name, if (is_for) .{
|
||||||
.array_payload = .{
|
.array_payload = .{
|
||||||
.identifier = name_token,
|
.identifier = name_token,
|
||||||
.array_expr = while_node.ast.cond_expr,
|
.array_expr = while_node.ast.cond_expr,
|
||||||
@ -2875,7 +2917,7 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
if (token_tags[name_token + 1] == .comma) {
|
if (token_tags[name_token + 1] == .comma) {
|
||||||
const index_token = name_token + 2;
|
const index_token = name_token + 2;
|
||||||
std.debug.assert(token_tags[index_token] == .identifier);
|
std.debug.assert(token_tags[index_token] == .identifier);
|
||||||
if (try scope.decls.fetchPut(
|
if (try scopes.items(.decls)[scope_index].fetchPut(
|
||||||
allocator,
|
allocator,
|
||||||
tree.tokenSlice(index_token),
|
tree.tokenSlice(index_token),
|
||||||
.{ .array_index = index_token },
|
.{ .array_index = index_token },
|
||||||
@ -2890,17 +2932,17 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
if (while_node.ast.else_expr != 0) {
|
if (while_node.ast.else_expr != 0) {
|
||||||
if (while_node.error_token) |err_token| {
|
if (while_node.error_token) |err_token| {
|
||||||
std.debug.assert(token_tags[err_token] == .identifier);
|
std.debug.assert(token_tags[err_token] == .identifier);
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, err_token),
|
.start = offsets.tokenToIndex(tree, err_token),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, while_node.ast.else_expr)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, while_node.ast.else_expr)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
const name = tree.tokenSlice(err_token);
|
const name = tree.tokenSlice(err_token);
|
||||||
try scope.decls.putNoClobber(allocator, name, .{ .ast_node = while_node.ast.else_expr });
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, name, .{ .ast_node = while_node.ast.else_expr });
|
||||||
}
|
}
|
||||||
try makeScopeInternal(allocator, context, while_node.ast.else_expr);
|
try makeScopeInternal(allocator, context, while_node.ast.else_expr);
|
||||||
}
|
}
|
||||||
@ -2920,20 +2962,20 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (switch_case.payload_token) |payload| {
|
if (switch_case.payload_token) |payload| {
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, payload),
|
.start = offsets.tokenToIndex(tree, payload),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, switch_case.ast.target_expr)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, switch_case.ast.target_expr)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
// if payload is *name than get next token
|
// if payload is *name than get next token
|
||||||
const name_token = payload + @boolToInt(token_tags[payload] == .asterisk);
|
const name_token = payload + @boolToInt(token_tags[payload] == .asterisk);
|
||||||
const name = tree.tokenSlice(name_token);
|
const name = tree.tokenSlice(name_token);
|
||||||
|
|
||||||
try scope.decls.putNoClobber(allocator, name, .{
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, name, .{
|
||||||
.switch_payload = .{
|
.switch_payload = .{
|
||||||
.node = name_token,
|
.node = name_token,
|
||||||
.switch_expr = cond,
|
.switch_expr = cond,
|
||||||
@ -3084,18 +3126,17 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
|
|||||||
const expr = data[node_idx].rhs;
|
const expr = data[node_idx].rhs;
|
||||||
if (data[node_idx].lhs != 0) {
|
if (data[node_idx].lhs != 0) {
|
||||||
const payload_token = data[node_idx].lhs;
|
const payload_token = data[node_idx].lhs;
|
||||||
var scope = try scopes.addOne(allocator);
|
try scopes.append(allocator, .{
|
||||||
scope.* = .{
|
|
||||||
.loc = .{
|
.loc = .{
|
||||||
.start = offsets.tokenToIndex(tree, payload_token),
|
.start = offsets.tokenToIndex(tree, payload_token),
|
||||||
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, expr)).end,
|
.end = offsets.tokenToLoc(tree, ast.lastToken(tree, expr)).end,
|
||||||
},
|
},
|
||||||
.data = .other,
|
.data = .other,
|
||||||
};
|
});
|
||||||
errdefer scope.decls.deinit(allocator);
|
const scope_index = scopes.len - 1;
|
||||||
|
|
||||||
const name = tree.tokenSlice(payload_token);
|
const name = tree.tokenSlice(payload_token);
|
||||||
try scope.decls.putNoClobber(allocator, name, .{ .ast_node = expr });
|
try scopes.items(.decls)[scope_index].putNoClobber(allocator, name, .{ .ast_node = expr });
|
||||||
}
|
}
|
||||||
|
|
||||||
try makeScopeInternal(allocator, context, expr);
|
try makeScopeInternal(allocator, context, expr);
|
||||||
|
@ -43,8 +43,10 @@ pub fn printTree(tree: std.zig.Ast) void {
|
|||||||
pub fn printDocumentScope(doc_scope: analysis.DocumentScope) void {
|
pub fn printDocumentScope(doc_scope: analysis.DocumentScope) void {
|
||||||
if (!std.debug.runtime_safety) @compileError("this function should only be used in debug mode!");
|
if (!std.debug.runtime_safety) @compileError("this function should only be used in debug mode!");
|
||||||
|
|
||||||
for (doc_scope.scopes.items) |scope, i| {
|
var index: usize = 0;
|
||||||
if (i != 0) std.debug.print("\n\n", .{});
|
while(index < doc_scope.scopes.len) : (index += 1) {
|
||||||
|
const scope = doc_scope.scopes.get(index);
|
||||||
|
if (index != 0) std.debug.print("\n\n", .{});
|
||||||
std.debug.print(
|
std.debug.print(
|
||||||
\\[{d}, {d}] {}
|
\\[{d}, {d}] {}
|
||||||
\\usingnamespaces: {d}
|
\\usingnamespaces: {d}
|
||||||
|
@ -514,10 +514,10 @@ pub fn symbolReferences(
|
|||||||
.param_payload => |pay| blk: {
|
.param_payload => |pay| blk: {
|
||||||
// Rename the param tok.
|
// Rename the param tok.
|
||||||
const param = pay.param;
|
const param = pay.param;
|
||||||
for (curr_handle.document_scope.scopes.items) |scope| {
|
for (curr_handle.document_scope.scopes.items(.data)) |scope_data| {
|
||||||
if (scope.data != .function) continue;
|
if (scope_data != .function) continue;
|
||||||
|
|
||||||
const proto = scope.data.function;
|
const proto = scope_data.function;
|
||||||
|
|
||||||
var buf: [1]Ast.Node.Index = undefined;
|
var buf: [1]Ast.Node.Index = undefined;
|
||||||
const fn_proto = ast.fnProto(curr_handle.tree, proto, &buf).?;
|
const fn_proto = ast.fnProto(curr_handle.tree, proto, &buf).?;
|
||||||
|
Loading…
Reference in New Issue
Block a user