Fixed infinite loop with usingnamespace cycles

This commit is contained in:
Alexandros Naskos 2020-06-23 12:43:56 +03:00
parent bdbfea0737
commit a0f1795f2d

View File

@ -1512,7 +1512,7 @@ fn findContainerScope(container_handle: NodeWithHandle) ?*Scope {
return container_scope; return container_scope;
} }
pub fn iterateSymbolsContainer( fn iterateSymbolsContainerInternal(
store: *DocumentStore, store: *DocumentStore,
arena: *std.heap.ArenaAllocator, arena: *std.heap.ArenaAllocator,
container_handle: NodeWithHandle, container_handle: NodeWithHandle,
@ -1520,6 +1520,7 @@ pub fn iterateSymbolsContainer(
comptime callback: var, comptime callback: var,
context: var, context: var,
instance_access: bool, instance_access: bool,
use_trail: *std.ArrayList(*ast.Node.Use),
) error{OutOfMemory}!void { ) error{OutOfMemory}!void {
const container = container_handle.node; const container = container_handle.node;
const handle = container_handle.handle; const handle = container_handle.handle;
@ -1549,16 +1550,30 @@ pub fn iterateSymbolsContainer(
for (container_scope.uses) |use| { for (container_scope.uses) |use| {
if (handle != orig_handle and use.visib_token == null) continue; if (handle != orig_handle and use.visib_token == null) continue;
if (std.mem.indexOfScalar(*ast.Node.Use, use_trail.items, use) != null) continue;
try use_trail.append(use);
const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = use.expr, .handle = handle })) orelse continue; const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = use.expr, .handle = handle })) orelse continue;
const use_expr_node = switch (use_expr.type.data) { const use_expr_node = switch (use_expr.type.data) {
.other => |n| n, .other => |n| n,
else => continue, else => continue,
}; };
try iterateSymbolsContainer(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, orig_handle, callback, context, false); try iterateSymbolsContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, orig_handle, callback, context, false, use_trail);
} }
} }
}
std.debug.warn("Did not find container scope when iterating container {} (name: {})\n", .{ container, getDeclName(handle.tree, container) }); pub fn iterateSymbolsContainer(
store: *DocumentStore,
arena: *std.heap.ArenaAllocator,
container_handle: NodeWithHandle,
orig_handle: *DocumentStore.Handle,
comptime callback: var,
context: var,
instance_access: bool,
) error{OutOfMemory}!void {
var use_trail = std.ArrayList(*ast.Node.Use).init(&arena.allocator);
return try iterateSymbolsContainerInternal(store, arena, container_handle, orig_handle, callback, context, instance_access, &use_trail);
} }
pub fn iterateLabels( pub fn iterateLabels(
@ -1582,13 +1597,14 @@ pub fn iterateLabels(
} }
} }
pub fn iterateSymbolsGlobal( fn iterateSymbolsGlobalInternal(
store: *DocumentStore, store: *DocumentStore,
arena: *std.heap.ArenaAllocator, arena: *std.heap.ArenaAllocator,
handle: *DocumentStore.Handle, handle: *DocumentStore.Handle,
source_index: usize, source_index: usize,
comptime callback: var, comptime callback: var,
context: var, context: var,
use_trail: *std.ArrayList(*ast.Node.Use),
) error{OutOfMemory}!void { ) error{OutOfMemory}!void {
for (handle.document_scope.scopes) |scope| { for (handle.document_scope.scopes) |scope| {
if (source_index >= scope.range.start and source_index < scope.range.end) { if (source_index >= scope.range.start and source_index < scope.range.end) {
@ -1600,12 +1616,15 @@ pub fn iterateSymbolsGlobal(
} }
for (scope.uses) |use| { for (scope.uses) |use| {
if (std.mem.indexOfScalar(*ast.Node.Use, use_trail.items, use) != null) continue;
try use_trail.append(use);
const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = use.expr, .handle = handle })) orelse continue; const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = use.expr, .handle = handle })) orelse continue;
const use_expr_node = switch (use_expr.type.data) { const use_expr_node = switch (use_expr.type.data) {
.other => |n| n, .other => |n| n,
else => continue, else => continue,
}; };
try iterateSymbolsContainer(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, handle, callback, context, false); try iterateSymbolsContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, handle, callback, context, false, use_trail);
} }
} }
@ -1613,6 +1632,18 @@ pub fn iterateSymbolsGlobal(
} }
} }
pub fn iterateSymbolsGlobal(
store: *DocumentStore,
arena: *std.heap.ArenaAllocator,
handle: *DocumentStore.Handle,
source_index: usize,
comptime callback: var,
context: var,
) error{OutOfMemory}!void {
var use_trail = std.ArrayList(*ast.Node.Use).init(&arena.allocator);
return try iterateSymbolsGlobalInternal(store, arena, handle, source_index, callback, context, &use_trail);
}
pub fn innermostContainer(handle: *DocumentStore.Handle, source_index: usize) TypeWithHandle { pub fn innermostContainer(handle: *DocumentStore.Handle, source_index: usize) TypeWithHandle {
var current = handle.document_scope.scopes[0].data.container; var current = handle.document_scope.scopes[0].data.container;
if (handle.document_scope.scopes.len == 1) return TypeWithHandle.typeVal(.{ .node = current, .handle = handle }); if (handle.document_scope.scopes.len == 1) return TypeWithHandle.typeVal(.{ .node = current, .handle = handle });
@ -1635,14 +1666,18 @@ fn resolveUse(
uses: []const *ast.Node.Use, uses: []const *ast.Node.Use,
symbol: []const u8, symbol: []const u8,
handle: *DocumentStore.Handle, handle: *DocumentStore.Handle,
use_trail: *std.ArrayList(*ast.Node.Use),
) error{OutOfMemory}!?DeclWithHandle { ) error{OutOfMemory}!?DeclWithHandle {
for (uses) |use| { for (uses) |use| {
if (std.mem.indexOfScalar(*ast.Node.Use, use_trail.items, use) != null) continue;
try use_trail.append(use);
const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = use.expr, .handle = handle })) orelse continue; const use_expr = (try resolveTypeOfNode(store, arena, .{ .node = use.expr, .handle = handle })) orelse continue;
const use_expr_node = switch (use_expr.type.data) { const use_expr_node = switch (use_expr.type.data) {
.other => |n| n, .other => |n| n,
else => continue, else => continue,
}; };
if (try lookupSymbolContainer(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, symbol, false)) |candidate| { if (try lookupSymbolContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, symbol, false, use_trail)) |candidate| {
if (candidate.handle != handle and !candidate.isPublic()) { if (candidate.handle != handle and !candidate.isPublic()) {
continue; continue;
} }
@ -1675,12 +1710,13 @@ pub fn lookupLabel(
return null; return null;
} }
pub fn lookupSymbolGlobal( fn lookupSymbolGlobalInternal(
store: *DocumentStore, store: *DocumentStore,
arena: *std.heap.ArenaAllocator, arena: *std.heap.ArenaAllocator,
handle: *DocumentStore.Handle, handle: *DocumentStore.Handle,
symbol: []const u8, symbol: []const u8,
source_index: usize, source_index: usize,
use_trail: *std.ArrayList(*ast.Node.Use),
) error{OutOfMemory}!?DeclWithHandle { ) error{OutOfMemory}!?DeclWithHandle {
for (handle.document_scope.scopes) |scope| { for (handle.document_scope.scopes) |scope| {
if (source_index >= scope.range.start and source_index < scope.range.end) { if (source_index >= scope.range.start and source_index < scope.range.end) {
@ -1698,7 +1734,7 @@ pub fn lookupSymbolGlobal(
}; };
} }
if (try resolveUse(store, arena, scope.uses, symbol, handle)) |result| return result; if (try resolveUse(store, arena, scope.uses, symbol, handle, use_trail)) |result| return result;
} }
if (scope.range.start > source_index) return null; if (scope.range.start > source_index) return null;
@ -1707,7 +1743,18 @@ pub fn lookupSymbolGlobal(
return null; return null;
} }
pub fn lookupSymbolContainer( pub fn lookupSymbolGlobal(
store: *DocumentStore,
arena: *std.heap.ArenaAllocator,
handle: *DocumentStore.Handle,
symbol: []const u8,
source_index: usize,
) error{OutOfMemory}!?DeclWithHandle {
var use_trail = std.ArrayList(*ast.Node.Use).init(&arena.allocator);
return try lookupSymbolGlobalInternal(store, arena, handle, symbol, source_index, &use_trail);
}
fn lookupSymbolContainerInternal(
store: *DocumentStore, store: *DocumentStore,
arena: *std.heap.ArenaAllocator, arena: *std.heap.ArenaAllocator,
container_handle: NodeWithHandle, container_handle: NodeWithHandle,
@ -1715,6 +1762,7 @@ pub fn lookupSymbolContainer(
/// 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
/// of an instance of the type, otherwise as a field access of the type value itself. /// of an instance of the type, otherwise as a field access of the type value itself.
instance_access: bool, instance_access: bool,
use_trail: *std.ArrayList(*ast.Node.Use),
) error{OutOfMemory}!?DeclWithHandle { ) error{OutOfMemory}!?DeclWithHandle {
const container = container_handle.node; const container = container_handle.node;
const handle = container_handle.handle; const handle = container_handle.handle;
@ -1739,14 +1787,26 @@ pub fn lookupSymbolContainer(
return DeclWithHandle{ .decl = &candidate.value, .handle = handle }; return DeclWithHandle{ .decl = &candidate.value, .handle = handle };
} }
if (try resolveUse(store, arena, container_scope.uses, symbol, handle)) |result| return result; if (try resolveUse(store, arena, container_scope.uses, symbol, handle, use_trail)) |result| return result;
return null; return null;
} }
// std.debug.warn("Did not find container scope when looking up in container {} (name: {})\n", .{ container, getDeclName(handle.tree, container) });
return null; return null;
} }
pub fn lookupSymbolContainer(
store: *DocumentStore,
arena: *std.heap.ArenaAllocator,
container_handle: NodeWithHandle,
symbol: []const u8,
/// If true, we are looking up the symbol like we are accessing through a field access
/// of an instance of the type, otherwise as a field access of the type value itself.
instance_access: bool,
) error{OutOfMemory}!?DeclWithHandle {
var use_trail = std.ArrayList(*ast.Node.Use).init(&arena.allocator);
return try lookupSymbolContainerInternal(store, arena, container_handle, symbol, instance_access, &use_trail);
}
pub const DocumentScope = struct { pub const DocumentScope = struct {
scopes: []Scope, scopes: []Scope,