Handle if, while, for, payloads

This commit is contained in:
Alexandros Naskos 2020-05-23 01:03:41 +03:00
parent d4871914ea
commit c3d2aa3434
2 changed files with 91 additions and 12 deletions

View File

@ -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;

View File

@ -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];