From c3d2aa3434702fe97dffb9abcbc382eb688b8187 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sat, 23 May 2020 01:03:41 +0300 Subject: [PATCH] Handle if, while, for, payloads --- src/analysis.zig | 95 +++++++++++++++++++++++++++++++++++++++++++----- src/main.zig | 8 ++-- 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/analysis.zig b/src/analysis.zig index 750681b..16d3429 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -513,26 +513,97 @@ pub fn nodeToString(tree: *ast.Tree, node: *ast.Node) ?[]const u8 { return null; } -pub fn declsFromIndexInternal(decls: *std.ArrayList(*ast.Node), tree: *ast.Tree, node: *ast.Node) error{OutOfMemory}!void { +pub fn declsFromIndexInternal(decls: *std.ArrayList(*ast.Node), tree: *ast.Tree, node: *ast.Node, source_index: usize) error{OutOfMemory}!void { switch (node.id) { .FnProto => { const func = node.cast(ast.Node.FnProto).?; var param_index: usize = 0; while (param_index < func.params.len) : (param_index += 1) - try declsFromIndexInternal(decls, tree, func.params.at(param_index).*); + try declsFromIndexInternal(decls, tree, func.params.at(param_index).*, source_index); - if (func.body_node) |body_node| - try declsFromIndexInternal(decls, tree, body_node); + if (func.body_node) |body_node| { + if (!nodeContainsSourceIndex(tree, body_node, source_index)) return; + try declsFromIndexInternal(decls, tree, body_node, source_index); + } }, .TestDecl => { const test_decl = node.cast(ast.Node.TestDecl).?; - try declsFromIndexInternal(decls, tree, test_decl.body_node); + if (!nodeContainsSourceIndex(tree, test_decl.body_node, source_index)) return; + try declsFromIndexInternal(decls, tree, test_decl.body_node, source_index); }, .Block => { var index: usize = 0; while (node.iterate(index)) |inode| : (index += 1) { - try declsFromIndexInternal(decls, tree, inode); + if (nodeComesAfterSourceIndex(tree, inode, source_index)) return; + try declsFromIndexInternal(decls, tree, inode, source_index); + } + }, + .Comptime => { + const comptime_stmt = node.cast(ast.Node.Comptime).?; + if (nodeComesAfterSourceIndex(tree, comptime_stmt.expr, source_index)) return; + try declsFromIndexInternal(decls, tree, comptime_stmt.expr, source_index); + }, + .If => { + const if_node = node.cast(ast.Node.If).?; + if (nodeContainsSourceIndex(tree, if_node.body, source_index)) { + if (if_node.payload) |payload| { + try declsFromIndexInternal(decls, tree, payload, source_index); + } + return try declsFromIndexInternal(decls, tree, if_node.body, source_index); + } + + if (if_node.@"else") |else_node| { + if (nodeContainsSourceIndex(tree, else_node.body, source_index)) { + if (else_node.payload) |payload| { + try declsFromIndexInternal(decls, tree, payload, source_index); + } + return try declsFromIndexInternal(decls, tree, else_node.body, source_index); + } + } + }, + .While => { + const while_node = node.cast(ast.Node.While).?; + if (nodeContainsSourceIndex(tree, while_node.body, source_index)) { + if (while_node.payload) |payload| { + try declsFromIndexInternal(decls, tree, payload, source_index); + } + return try declsFromIndexInternal(decls, tree, while_node.body, source_index); + } + + if (while_node.@"else") |else_node| { + if (nodeContainsSourceIndex(tree, else_node.body, source_index)) { + if (else_node.payload) |payload| { + try declsFromIndexInternal(decls, tree, payload, source_index); + } + return try declsFromIndexInternal(decls, tree, else_node.body, source_index); + } + } + }, + .For => { + const for_node = node.cast(ast.Node.For).?; + if (nodeContainsSourceIndex(tree, for_node.body, source_index)) { + try declsFromIndexInternal(decls, tree, for_node.payload, source_index); + return try declsFromIndexInternal(decls, tree, for_node.body, source_index); + } + + if (for_node.@"else") |else_node| { + if (nodeContainsSourceIndex(tree, else_node.body, source_index)) { + if (else_node.payload) |payload| { + try declsFromIndexInternal(decls, tree, payload, source_index); + } + return try declsFromIndexInternal(decls, tree, else_node.body, source_index); + } + } + }, + // TODO: These convey no type information... + .Payload => try decls.append(node.cast(ast.Node.Payload).?.error_symbol), + .PointerPayload => try decls.append(node.cast(ast.Node.PointerPayload).?.value_symbol), + .PointerIndexPayload => { + const payload = node.cast(ast.Node.PointerIndexPayload).?; + try decls.append(payload.value_symbol); + if (payload.index_symbol) |idx| { + try decls.append(idx); } }, .VarDecl, .ParamDecl => try decls.append(node), @@ -547,14 +618,14 @@ pub fn addChildrenNodes(decls: *std.ArrayList(*ast.Node), tree: *ast.Tree, node: } } -pub fn declsFromIndex(decls: *std.ArrayList(*ast.Node), tree: *ast.Tree, index: usize) !void { +pub fn declsFromIndex(decls: *std.ArrayList(*ast.Node), tree: *ast.Tree, source_index: usize) !void { var node = &tree.root_node.base; try addChildrenNodes(decls, tree, node); var node_index: usize = 0; while (node.iterate(node_index)) |inode| : (node_index += 1) { - if (nodeContainsSourceIndex(tree, inode, index)) { - try declsFromIndexInternal(decls, tree, inode); + if (nodeContainsSourceIndex(tree, inode, source_index)) { + try declsFromIndexInternal(decls, tree, inode, source_index); } } } @@ -565,6 +636,12 @@ fn nodeContainsSourceIndex(tree: *ast.Tree, node: *ast.Node, source_index: usize return source_index >= first_token.start and source_index <= last_token.end; } +fn nodeComesAfterSourceIndex(tree: *ast.Tree, node: *ast.Node, source_index: usize) bool { + const first_token = tree.tokens.at(node.firstToken()); + const last_token = tree.tokens.at(node.lastToken()); + return source_index < first_token.start; +} + pub fn getImportStr(tree: *ast.Tree, source_index: usize) ?[]const u8 { var node = &tree.root_node.base; var index: usize = 0; diff --git a/src/main.zig b/src/main.zig index 643e7cd..9be2a09 100644 --- a/src/main.zig +++ b/src/main.zig @@ -283,16 +283,18 @@ fn nodeToCompletion(list: *std.ArrayList(types.CompletionItem), analysis_ctx: *D } fn identifierFromPosition(pos_index: usize, handle: DocumentStore.Handle) []const u8 { - if (pos_index + 1 >= handle.document.text.len) return &[0]u8{}; + const text = handle.document.text; + + if (pos_index + 1 >= text.len) return &[0]u8{}; var start_idx = pos_index; while (start_idx > 0 and - (std.ascii.isAlNum(handle.document.text[start_idx]) or handle.document.text[start_idx] == '_')) : (start_idx -= 1) + (std.ascii.isAlNum(text[start_idx]) or text[start_idx] == '_')) : (start_idx -= 1) {} var end_idx = pos_index; while (end_idx < handle.document.text.len - 1 and - (std.ascii.isAlNum(handle.document.text[end_idx]) or handle.document.text[end_idx] == '_')) : (end_idx += 1) + (std.ascii.isAlNum(text[end_idx]) or text[end_idx] == '_')) : (end_idx += 1) {} return handle.document.text[start_idx + 1 .. end_idx];