First set of changes to work with new std's ast

This commit is contained in:
Luuk de Gram 2021-02-26 21:26:52 +01:00
parent a886ecddd9
commit 0133f0d863
No known key found for this signature in database
GPG Key ID: A002B174963DBB7D
5 changed files with 267 additions and 229 deletions

View File

@ -6,7 +6,7 @@ const offsets = @import("offsets.zig");
const log = std.log.scoped(.analysis); const log = std.log.scoped(.analysis);
/// Get a declaration's doc comment node /// Get a declaration's doc comment node
pub fn getDocCommentNode(tree: *ast.Tree, node: *ast.Node) ?*ast.Node.DocComment { pub fn getDocCommentNode(tree: ast.Tree, node: *ast.Node) ?*ast.Node.DocComment {
if (node.castTag(.FnProto)) |func| { if (node.castTag(.FnProto)) |func| {
return func.getDocComments(); return func.getDocComments();
} else if (node.castTag(.VarDecl)) |var_decl| { } else if (node.castTag(.VarDecl)) |var_decl| {
@ -27,7 +27,7 @@ pub fn getDocCommentNode(tree: *ast.Tree, node: *ast.Node) ?*ast.Node.DocComment
///``` ///```
pub fn getDocComments( pub fn getDocComments(
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
tree: *ast.Tree, tree: ast.Tree,
node: *ast.Node, node: *ast.Node,
format: types.MarkupContent.Kind, format: types.MarkupContent.Kind,
) !?[]const u8 { ) !?[]const u8 {
@ -39,7 +39,7 @@ pub fn getDocComments(
pub fn collectDocComments( pub fn collectDocComments(
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
tree: *ast.Tree, tree: ast.Tree,
doc_comments: *ast.Node.DocComment, doc_comments: *ast.Node.DocComment,
format: types.MarkupContent.Kind, format: types.MarkupContent.Kind,
) ![]const u8 { ) ![]const u8 {
@ -61,17 +61,19 @@ pub fn collectDocComments(
} }
/// Gets a function signature (keywords, name, return value) /// Gets a function signature (keywords, name, return value)
pub fn getFunctionSignature(tree: *ast.Tree, func: *ast.Node.FnProto) []const u8 { pub fn getFunctionSignature(tree: ast.Tree, func: *ast.Node.FnProto) []const u8 {
const start = tree.token_locs[func.firstToken()].start; const start = tree.token_locs[func.firstToken()].start;
const end = tree.token_locs[switch (func.return_type) { const end = tree.token_locs[
switch (func.return_type) {
.Explicit, .InferErrorSet => |node| node.lastToken(), .Explicit, .InferErrorSet => |node| node.lastToken(),
.Invalid => |r_paren| r_paren, .Invalid => |r_paren| r_paren,
}].end; }
].end;
return tree.source[start..end]; return tree.source[start..end];
} }
/// Gets a function snippet insert text /// Gets a function snippet insert text
pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: *ast.Tree, func: *ast.Node.FnProto, skip_self_param: bool) ![]const u8 { pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: ast.Tree, func: *ast.Node.FnProto, skip_self_param: bool) ![]const u8 {
const name_tok = func.getNameToken() orelse unreachable; const name_tok = func.getNameToken() orelse unreachable;
var buffer = std.ArrayList(u8).init(allocator); var buffer = std.ArrayList(u8).init(allocator);
@ -126,37 +128,36 @@ pub fn getFunctionSnippet(allocator: *std.mem.Allocator, tree: *ast.Tree, func:
} }
/// Gets a function signature (keywords, name, return value) /// Gets a function signature (keywords, name, return value)
pub fn getVariableSignature(tree: *ast.Tree, var_decl: *ast.Node.VarDecl) []const u8 { pub fn getVariableSignature(tree: ast.Tree, var_decl: *ast.Node.VarDecl) []const u8 {
const start = tree.token_locs[var_decl.firstToken()].start; const start = tree.token_locs[var_decl.firstToken()].start;
const end = tree.token_locs[var_decl.semicolon_token].start; const end = tree.token_locs[var_decl.semicolon_token].start;
return tree.source[start..end]; return tree.source[start..end];
} }
// analysis.getContainerFieldSignature(handle.tree, field) // analysis.getContainerFieldSignature(handle.tree, field)
pub fn getContainerFieldSignature(tree: *ast.Tree, field: *ast.Node.ContainerField) []const u8 { pub fn getContainerFieldSignature(tree: ast.Tree, field: *ast.Node.ContainerField) []const u8 {
const start = tree.token_locs[field.firstToken()].start; const start = tree.token_locs[field.firstToken()].start;
const end = tree.token_locs[field.lastToken()].end; const end = tree.token_locs[field.lastToken()].end;
return tree.source[start..end]; return tree.source[start..end];
} }
/// The type node is "type" /// The type node is "type"
fn typeIsType(tree: *ast.Tree, node: *ast.Node) bool { fn typeIsType(tree: ast.Tree, node: ast.Node.Index) bool {
if (node.castTag(.Identifier)) |ident| { if (tree.nodes.items(.tag)[node] == .identifier) {
return std.mem.eql(u8, tree.tokenSlice(ident.token), "type"); return std.mem.eql(u8, tree.tokenSlice(node), "type");
} }
return false; return false;
} }
pub fn isTypeFunction(tree: *ast.Tree, func: *ast.Node.FnProto) bool { pub fn isTypeFunction(tree: ast.Tree, func: ast.full.FnProto) bool {
switch (func.return_type) { return typeIsType(func.ast.return_type);
.Explicit => |node| return typeIsType(tree, node),
.InferErrorSet, .Invalid => return false,
}
} }
pub fn isGenericFunction(tree: *ast.Tree, func: *ast.Node.FnProto) bool { pub fn isGenericFunction(tree: ast.Tree, func: *ast.full.FnProto) bool {
for (func.paramsConst()) |param| { var it = func.iterate();
if (param.param_type == .any_type or param.comptime_token != null) { var slice = tree.nodes.items(.tag);
while (it.next()) |param| {
if (param.anytype_ellipsis3 != null or param.comptime_noalias != null) {
return true; return true;
} }
} }
@ -174,43 +175,50 @@ pub fn isPascalCase(name: []const u8) bool {
// ANALYSIS ENGINE // ANALYSIS ENGINE
pub fn getDeclNameToken(tree: *ast.Tree, node: *ast.Node) ?ast.TokenIndex { pub fn getDeclNameToken(tree: ast.Tree, node: ast.Node.Index) ?ast.TokenIndex {
switch (node.tag) { const tags = tree.nodes.items(.tag);
.VarDecl => { switch (tags[node]) {
const vari = node.castTag(.VarDecl).?; // regular declaration names. + 1 to mut token because name comes after 'const'/'var'
return vari.name_token; .local_var_decl => return tree.localVarDecl(node).ast.mut_token + 1,
.global_var_decl => return tree.globalVarDecl(node).ast.mut_token + 1,
.simple_var_decl => return tree.simpleVarDecl(node).ast.mut_token + 1,
.aligned_var_decl => return tree.alignedVarDecl(node).ast.mut_token + 1,
// function declaration names
.fn_proto => return tree.fnProto(node).name_token,
.fn_proto_simple => {
var params: [1]ast.Node.Index = undefined;
return tree.fnProtoSimple(&params, node).name_token;
}, },
.FnProto => { .fn_proto_one => {
const func = node.castTag(.FnProto).?; var params: [1]ast.Node.Index = undefined;
return func.getNameToken(); return tree.fnProtoOne(&params, node).name_token;
},
.ContainerField => {
const field = node.castTag(.ContainerField).?;
return field.name_token;
},
.ErrorTag => {
const tag = node.castTag(.ErrorTag).?;
return tag.name_token;
},
// We need identifier for captures and error set tags
.Identifier => {
const ident = node.castTag(.Identifier).?;
return ident.token;
},
.TestDecl => {
const decl = node.castTag(.TestDecl).?;
return ((decl.name orelse return null).castTag(.StringLiteral) orelse return null).token;
}, },
.fn_proto_multi => return tree.fnProtoMulti(node).name_token,
// containers
.container_field => return tree.containerField(node).ast.name_token,
.container_field_init => return tree.containerFieldInit(node).ast.name_token,
.container_field_align => return tree.containerFieldAlign(node).ast.name_token,
// @TODO: Errors
// .error_=> {
// const tag = node.castTag(.ErrorTag).?;
// return tag.name_token;
// },
// lhs of main token is name token, so use `node` - 1
.test_decl => return getDeclNameToken(tree, node - 1),
else => {}, else => {},
} }
return null; return null;
} }
fn getDeclName(tree: *ast.Tree, node: *ast.Node) ?[]const u8 { fn getDeclName(tree: ast.Tree, node: ast.Node.Index) ?[]const u8 {
const name = tree.tokenSlice(getDeclNameToken(tree, node) orelse return null); const name = tree.tokenSlice(getDeclNameToken(tree, node) orelse return null);
return switch (node.tag) { return switch (tree.nodes.items(.tag)[node]) {
.TestDecl => name[1 .. name.len - 1], .test_decl => name[1 .. name.len - 1],
else => name, else => name,
}; };
} }
@ -290,7 +298,7 @@ pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocato
} }
fn findReturnStatementInternal( fn findReturnStatementInternal(
tree: *ast.Tree, tree: ast.Tree,
fn_decl: *ast.Node.FnProto, fn_decl: *ast.Node.FnProto,
base_node: *ast.Node, base_node: *ast.Node,
already_found: *bool, already_found: *bool,
@ -321,7 +329,7 @@ fn findReturnStatementInternal(
return result; return result;
} }
fn findReturnStatement(tree: *ast.Tree, fn_decl: *ast.Node.FnProto) ?*ast.Node.ControlFlowExpression { fn findReturnStatement(tree: ast.Tree, fn_decl: *ast.Node.FnProto) ?*ast.Node.ControlFlowExpression {
var already_found = false; var already_found = false;
return findReturnStatementInternal(tree, fn_decl, fn_decl.getBodyNode().?, &already_found); return findReturnStatementInternal(tree, fn_decl, fn_decl.getBodyNode().?, &already_found);
} }
@ -510,7 +518,7 @@ fn allDigits(str: []const u8) bool {
return true; return true;
} }
pub fn isTypeIdent(tree: *ast.Tree, token_idx: ast.TokenIndex) bool { pub fn isTypeIdent(tree: ast.Tree, token_idx: ast.TokenIndex) bool {
const PrimitiveTypes = std.ComptimeStringMap(void, .{ const PrimitiveTypes = std.ComptimeStringMap(void, .{
.{"isize"}, .{"usize"}, .{"isize"}, .{"usize"},
.{"c_short"}, .{"c_ushort"}, .{"c_short"}, .{"c_ushort"},
@ -963,37 +971,49 @@ pub fn resolveTypeOfNode(store: *DocumentStore, arena: *std.heap.ArenaAllocator,
return resolveTypeOfNodeInternal(store, arena, node_handle, &bound_type_params); return resolveTypeOfNodeInternal(store, arena, node_handle, &bound_type_params);
} }
fn maybeCollectImport(tree: *ast.Tree, builtin_call: *ast.Node.BuiltinCall, arr: *std.ArrayList([]const u8)) !void { fn maybeCollectImport(tree: ast.Tree, builtin_call: ast.Node.Index, arr: *std.ArrayList([]const u8)) !void {
if (!std.mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@import")) return; const tags = tree.nodes.items(.tag);
if (builtin_call.params_len > 1) return; const datas = tree.nodes.items(.data);
const import_param = builtin_call.paramsConst()[0]; const builtin_tag = tags[builtin_call];
if (import_param.tag != .StringLiteral) return; const builtin_data = datas[builtin_call];
const import_str = tree.tokenSlice(import_param.castTag(.StringLiteral).?.token); std.debug.assert(builtin_tag == .builtin_call);
if (!std.mem.eql(u8, tree.tokenSlice(builtin_call), "@import")) return;
const params = tree.extra_data[builtin_data.lhs..builtin_data.rhs];
if (params.len > 1) return;
if (tags[params[0]] != .string_literal) return;
const import_str = tree.tokenSlice(params[0]);
try arr.append(import_str[1 .. import_str.len - 1]); try arr.append(import_str[1 .. import_str.len - 1]);
} }
/// Collects all imports we can find into a slice of import paths (without quotes). /// Collects all imports we can find into a slice of import paths (without quotes).
/// The import paths are valid as long as the tree is. /// The import paths are valid as long as the tree is.
pub fn collectImports(import_arr: *std.ArrayList([]const u8), tree: *ast.Tree) !void { pub fn collectImports(import_arr: *std.ArrayList([]const u8), tree: ast.Tree) !void {
// TODO: Currently only detects `const smth = @import("string literal")<.SomeThing>;` // TODO: Currently only detects `const smth = @import("string literal")<.SomeThing>;`
for (tree.root_node.decls()) |decl| { const tags = tree.nodes.items(.tag);
if (decl.tag != .VarDecl) continue; for (tree.rootDecls()) |decl_idx| {
const var_decl = decl.castTag(.VarDecl).?; const var_decl_maybe: ?ast.full.VarDecl = switch (tags[decl_idx]) {
const init_node = var_decl.getInitNode() orelse continue; .global_var_decl => tree.globalVarDecl(decl_idx),
.local_var_decl => tree.localVarDecl(decl_idx),
.simple_var_decl => tree.simpleVarDecl(decl_idx),
else => null,
};
const var_decl = var_decl_maybe orelse continue;
switch (init_node.tag) { const init_node = var_decl.ast.init_node;
.BuiltinCall => { const init_node_tag = tags[init_node];
const builtin_call = init_node.castTag(.BuiltinCall).?; switch (init_node_tag) {
try maybeCollectImport(tree, builtin_call, import_arr); .builtin_call => try maybeCollectImport(tree, init_node, import_arr),
}, // @TODO: FIX ME what is the syntax to support for imports using dot notation?
.Period => { // .Period => {
const infix_op = init_node.cast(ast.Node.SimpleInfixOp).?; // const infix_op = init_node.cast(ast.Node.SimpleInfixOp).?;
if (infix_op.lhs.tag != .BuiltinCall) continue; // if (infix_op.lhs.tag != .BuiltinCall) continue;
try maybeCollectImport(tree, infix_op.lhs.castTag(.BuiltinCall).?, import_arr); // try maybeCollectImport(tree, infix_op.lhs.castTag(.BuiltinCall).?, import_arr);
}, // },
else => {}, else => {},
} }
} }
@ -1134,7 +1154,7 @@ pub fn getFieldAccessType(
}; };
} }
pub fn isNodePublic(tree: *ast.Tree, node: *ast.Node) bool { pub fn isNodePublic(tree: ast.Tree, node: *ast.Node) bool {
switch (node.tag) { switch (node.tag) {
.VarDecl => { .VarDecl => {
const var_decl = node.castTag(.VarDecl).?; const var_decl = node.castTag(.VarDecl).?;
@ -1148,7 +1168,7 @@ pub fn isNodePublic(tree: *ast.Tree, node: *ast.Node) bool {
} }
} }
pub fn nodeToString(tree: *ast.Tree, node: *ast.Node) ?[]const u8 { pub fn nodeToString(tree: ast.Tree, node: *ast.Node) ?[]const u8 {
switch (node.tag) { switch (node.tag) {
.ContainerField => { .ContainerField => {
const field = node.castTag(.ContainerField).?; const field = node.castTag(.ContainerField).?;
@ -1176,13 +1196,13 @@ pub fn nodeToString(tree: *ast.Tree, node: *ast.Node) ?[]const u8 {
return null; return null;
} }
fn nodeContainsSourceIndex(tree: *ast.Tree, node: *ast.Node, source_index: usize) bool { fn nodeContainsSourceIndex(tree: ast.Tree, node: *ast.Node, source_index: usize) bool {
const first_token = tree.token_locs[node.firstToken()]; const first_token = tree.token_locs[node.firstToken()];
const last_token = tree.token_locs[node.lastToken()]; const last_token = tree.token_locs[node.lastToken()];
return source_index >= first_token.start and source_index <= last_token.end; return source_index >= first_token.start and source_index <= last_token.end;
} }
pub fn getImportStr(tree: *ast.Tree, source_index: usize) ?[]const u8 { pub fn getImportStr(tree: ast.Tree, source_index: usize) ?[]const u8 {
var node = &tree.root_node.base; var node = &tree.root_node.base;
var child_idx: usize = 0; var child_idx: usize = 0;
@ -1269,8 +1289,8 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.
while (true) { while (true) {
const tok = tokenizer.next(); const tok = tokenizer.next();
// Early exits. // Early exits.
switch (tok.id) { switch (tok.tag) {
.Invalid, .Invalid_ampersands => { .invalid, .invalid_ampersands => {
// Single '@' do not return a builtin token so we check this on our own. // Single '@' do not return a builtin token so we check this on our own.
if (line[doc_position.line_index - 1] == '@') { if (line[doc_position.line_index - 1] == '@') {
return PositionContext{ return PositionContext{
@ -1282,16 +1302,16 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.
} }
return .other; return .other;
}, },
.LineComment, .DocComment, .ContainerDocComment => return .comment, .line_comment, .doc_comment, .container_doc_comment => return .comment,
.Eof => break, .eof => break,
else => {}, else => {},
} }
// State changes // State changes
var curr_ctx = try peek(&stack); var curr_ctx = try peek(&stack);
switch (tok.id) { switch (tok.tag) {
.StringLiteral, .MultilineStringLiteralLine => curr_ctx.ctx = .{ .string_literal = tok.loc }, .string_literal, .multiline_string_literal_line => curr_ctx.ctx = .{ .string_literal = tok.loc },
.Identifier => switch (curr_ctx.ctx) { .identifier => switch (curr_ctx.ctx) {
.empty, .pre_label => curr_ctx.ctx = .{ .var_access = tok.loc }, .empty, .pre_label => curr_ctx.ctx = .{ .var_access = tok.loc },
.label => |filled| if (!filled) { .label => |filled| if (!filled) {
curr_ctx.ctx = .{ .label = true }; curr_ctx.ctx = .{ .label = true };
@ -1300,11 +1320,11 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.
}, },
else => {}, else => {},
}, },
.Builtin => switch (curr_ctx.ctx) { .builtin => switch (curr_ctx.ctx) {
.empty, .pre_label => curr_ctx.ctx = .{ .builtin = tok.loc }, .empty, .pre_label => curr_ctx.ctx = .{ .builtin = tok.loc },
else => {}, else => {},
}, },
.Period, .PeriodAsterisk => switch (curr_ctx.ctx) { .period, .period_asterisk => switch (curr_ctx.ctx) {
.empty, .pre_label => curr_ctx.ctx = .enum_literal, .empty, .pre_label => curr_ctx.ctx = .enum_literal,
.enum_literal => curr_ctx.ctx = .empty, .enum_literal => curr_ctx.ctx = .empty,
.field_access => {}, .field_access => {},
@ -1314,31 +1334,31 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.
.field_access = tokenRangeAppend(curr_ctx.ctx.range().?, tok), .field_access = tokenRangeAppend(curr_ctx.ctx.range().?, tok),
}, },
}, },
.Keyword_break, .Keyword_continue => curr_ctx.ctx = .pre_label, .keyword_break, .keyword_continue => curr_ctx.ctx = .pre_label,
.Colon => if (curr_ctx.ctx == .pre_label) { .colon => if (curr_ctx.ctx == .pre_label) {
curr_ctx.ctx = .{ .label = false }; curr_ctx.ctx = .{ .label = false };
} else { } else {
curr_ctx.ctx = .empty; curr_ctx.ctx = .empty;
}, },
.QuestionMark => switch (curr_ctx.ctx) { .question_mark => switch (curr_ctx.ctx) {
.field_access => {}, .field_access => {},
else => curr_ctx.ctx = .empty, else => curr_ctx.ctx = .empty,
}, },
.LParen => try stack.append(.{ .ctx = .empty, .stack_id = .Paren }), .l_paren => try stack.append(.{ .ctx = .empty, .stack_id = .Paren }),
.LBracket => try stack.append(.{ .ctx = .empty, .stack_id = .Bracket }), .l_bracket => try stack.append(.{ .ctx = .empty, .stack_id = .Bracket }),
.RParen => { .r_paren => {
_ = stack.pop(); _ = stack.pop();
if (curr_ctx.stack_id != .Paren) { if (curr_ctx.stack_id != .Paren) {
(try peek(&stack)).ctx = .empty; (try peek(&stack)).ctx = .empty;
} }
}, },
.RBracket => { .r_bracket => {
_ = stack.pop(); _ = stack.pop();
if (curr_ctx.stack_id != .Bracket) { if (curr_ctx.stack_id != .Bracket) {
(try peek(&stack)).ctx = .empty; (try peek(&stack)).ctx = .empty;
} }
}, },
.Keyword_error => curr_ctx.ctx = .global_error_set, .keyword_error => curr_ctx.ctx = .global_error_set,
else => curr_ctx.ctx = .empty, else => curr_ctx.ctx = .empty,
} }
@ -1356,8 +1376,8 @@ pub fn documentPositionContext(arena: *std.heap.ArenaAllocator, document: types.
}; };
} }
fn addOutlineNodes(allocator: *std.mem.Allocator, tree: *ast.Tree, child: *ast.Node, context: *GetDocumentSymbolsContext) anyerror!void { fn addOutlineNodes(allocator: *std.mem.Allocator, tree: ast.Tree, parent: ast.Node.Index, context: *GetDocumentSymbolsContext) anyerror!void {
switch (child.tag) { switch (tree.nodes.items(.tag)[parent]) {
.StringLiteral, .StringLiteral,
.IntegerLiteral, .IntegerLiteral,
.BuiltinCall, .BuiltinCall,
@ -1471,13 +1491,13 @@ const GetDocumentSymbolsContext = struct {
encoding: offsets.Encoding, encoding: offsets.Encoding,
}; };
fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, node: *ast.Node, context: *GetDocumentSymbolsContext) anyerror!void { fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: ast.Tree, node: ast.Node.Index, context: *GetDocumentSymbolsContext) anyerror!void {
const name = getDeclName(tree, node) orelse return; const name = getDeclName(tree, node) orelse return;
if (name.len == 0) if (name.len == 0)
return; return;
const start_loc = context.prev_loc.add(try offsets.tokenRelativeLocation(tree, context.prev_loc.offset, node.firstToken(), context.encoding)); const start_loc = context.prev_loc.add(try offsets.tokenRelativeLocation(tree, context.prev_loc.offset, tree.firstToken(node), context.encoding));
const end_loc = start_loc.add(try offsets.tokenRelativeLocation(tree, start_loc.offset, node.lastToken(), context.encoding)); const end_loc = start_loc.add(try offsets.tokenRelativeLocation(tree, start_loc.offset, tree.lastToken(node), context.encoding));
context.prev_loc = end_loc; context.prev_loc = end_loc;
const range = types.Range{ const range = types.Range{
.start = .{ .start = .{
@ -1490,12 +1510,24 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, no
}, },
}; };
const tags = tree.nodes.items(.tag);
(try context.symbols.addOne()).* = .{ (try context.symbols.addOne()).* = .{
.name = name, .name = name,
.kind = switch (node.tag) { .kind = switch (tags[node]) {
.FnProto => .Function, .fn_proto,
.VarDecl => .Variable, .fn_proto_simple,
.ContainerField => .Field, .fn_proto_multi,
.fn_proto_one,
=> .Function,
.local_var_decl,
.global_var_decl,
.aligned_var_decl,
.simple_var_decl,
=> .Variable,
.container_field,
.container_field_align,
.container_field_init,
=> .Field,
else => .Variable, else => .Variable,
}, },
.range = range, .range = range,
@ -1511,43 +1543,45 @@ fn getDocumentSymbolsInternal(allocator: *std.mem.Allocator, tree: *ast.Tree, no
}; };
var index: usize = 0; var index: usize = 0;
while (node.iterate(index)) |child| : (index += 1) { try addOutlineNodes(allocator, tree, node, &child_context);
try addOutlineNodes(allocator, tree, child, &child_context);
} // while (node.iterate(index)) |child| : (index += 1) {
// try addOutlineNodes(allocator, tree, child, &child_context);
// }
break :ch children.items; break :ch children.items;
}, },
}; };
} }
pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: *ast.Tree, encoding: offsets.Encoding) ![]types.DocumentSymbol { pub fn getDocumentSymbols(allocator: *std.mem.Allocator, tree: ast.Tree, encoding: offsets.Encoding) ![]types.DocumentSymbol {
var symbols = try std.ArrayList(types.DocumentSymbol).initCapacity(allocator, tree.root_node.decls_len); var symbols = try std.ArrayList(types.DocumentSymbol).initCapacity(allocator, tree.rootDecls().len);
var context = GetDocumentSymbolsContext{ var context = GetDocumentSymbolsContext{
.symbols = &symbols, .symbols = &symbols,
.encoding = encoding, .encoding = encoding,
}; };
for (tree.root_node.decls()) |node| { for (tree.rootDecls()) |idx| {
try getDocumentSymbolsInternal(allocator, tree, node, &context); try getDocumentSymbolsInternal(allocator, tree, idx, &context);
} }
return symbols.items; return symbols.items;
} }
pub const Declaration = union(enum) { pub const Declaration = union(enum) {
ast_node: *ast.Node, ast_node: ast.Node,
param_decl: *ast.Node.FnProto.ParamDecl, param_decl: ast.full.FnProto.Param,
pointer_payload: struct { pointer_payload: struct {
node: *ast.Node.PointerPayload, node: ast.full.PtrType,
condition: *ast.Node, condition: *ast.Node,
}, },
array_payload: struct { array_payload: struct {
identifier: *ast.Node, identifier: *ast.Node,
array_expr: *ast.Node, array_expr: ast.full.ArrayType,
}, },
switch_payload: struct { switch_payload: struct {
node: *ast.Node.PointerPayload, node: ast.full.PtrType,
switch_expr: *ast.Node, switch_expr: *ast.Node,
items: []const *ast.Node, items: []const *ast.Node,
}, },
@ -1723,18 +1757,18 @@ fn iterateSymbolsContainerInternal(
try callback(context, decl); try callback(context, decl);
} }
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; // if (std.mem.indexOfScalar(*ast.Node.Use, use_trail.items, use) != null) continue;
try use_trail.append(use); // 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 iterateSymbolsContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, orig_handle, callback, context, false, use_trail); // try iterateSymbolsContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, orig_handle, callback, context, false, use_trail);
} // }
} }
} }
@ -1790,17 +1824,17 @@ fn iterateSymbolsGlobalInternal(
try callback(context, DeclWithHandle{ .decl = &entry.value, .handle = handle }); try callback(context, DeclWithHandle{ .decl = &entry.value, .handle = handle });
} }
for (scope.uses) |use| { // for (scope.uses) |use| {
if (std.mem.indexOfScalar(*ast.Node.Use, use_trail.items, use) != null) continue; // if (std.mem.indexOfScalar(*ast.Node.Use, use_trail.items, use) != null) continue;
try use_trail.append(use); // 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 iterateSymbolsContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, handle, callback, context, false, use_trail); // try iterateSymbolsContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, handle, callback, context, false, use_trail);
} // }
} }
if (scope.range.start >= source_index) return; if (scope.range.start >= source_index) return;
@ -1838,27 +1872,27 @@ pub fn innermostContainer(handle: *DocumentStore.Handle, source_index: usize) Ty
fn resolveUse( fn resolveUse(
store: *DocumentStore, store: *DocumentStore,
arena: *std.heap.ArenaAllocator, arena: *std.heap.ArenaAllocator,
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), 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; // if (std.mem.indexOfScalar(*ast.Node.Use, use_trail.items, use) != null) continue;
try use_trail.append(use); // 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 lookupSymbolContainerInternal(store, arena, .{ .node = use_expr_node, .handle = use_expr.handle }, symbol, false, use_trail)) |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;
} // }
return candidate; // return candidate;
} // }
} // }
return null; return null;
} }
@ -1909,7 +1943,7 @@ fn lookupSymbolGlobalInternal(
}; };
} }
if (try resolveUse(store, arena, scope.uses, symbol, handle, use_trail)) |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;
@ -1962,7 +1996,7 @@ fn lookupSymbolContainerInternal(
return DeclWithHandle{ .decl = &candidate.value, .handle = handle }; return DeclWithHandle{ .decl = &candidate.value, .handle = handle };
} }
if (try resolveUse(store, arena, container_scope.uses, symbol, handle, use_trail)) |result| return result; // if (try resolveUse(store, arena, container_scope.uses, symbol, handle, use_trail)) |result| return result;
return null; return null;
} }
@ -1998,7 +2032,8 @@ pub const DocumentScope = struct {
scope.data, scope.data,
scope.range.start, scope.range.start,
scope.range.end, scope.range.end,
scope.uses.len, {},
// scope.uses.len,
}); });
var decl_it = scope.decls.iterator(); var decl_it = scope.decls.iterator();
@ -2014,7 +2049,7 @@ pub const DocumentScope = struct {
pub fn deinit(self: DocumentScope, allocator: *std.mem.Allocator) void { pub fn deinit(self: DocumentScope, allocator: *std.mem.Allocator) void {
for (self.scopes) |*scope| { for (self.scopes) |*scope| {
scope.decls.deinit(); scope.decls.deinit();
allocator.free(scope.uses); // allocator.free(scope.uses);
allocator.free(scope.tests); allocator.free(scope.tests);
} }
allocator.free(self.scopes); allocator.free(self.scopes);
@ -2036,12 +2071,12 @@ pub const Scope = struct {
range: SourceRange, range: SourceRange,
decls: std.StringHashMap(Declaration), decls: std.StringHashMap(Declaration),
tests: []const *ast.Node, tests: []const *ast.Node,
uses: []const *ast.Node.Use, // uses: []const *ast.Node.Data,
data: Data, data: Data,
}; };
pub fn makeDocumentScope(allocator: *std.mem.Allocator, tree: *ast.Tree) !DocumentScope { pub fn makeDocumentScope(allocator: *std.mem.Allocator, tree: ast.Tree) !DocumentScope {
var scopes = std.ArrayListUnmanaged(Scope){}; var scopes = std.ArrayListUnmanaged(Scope){};
var error_completions = std.ArrayListUnmanaged(types.CompletionItem){}; var error_completions = std.ArrayListUnmanaged(types.CompletionItem){};
var enum_completions = std.ArrayListUnmanaged(types.CompletionItem){}; var enum_completions = std.ArrayListUnmanaged(types.CompletionItem){};
@ -2054,7 +2089,7 @@ pub fn makeDocumentScope(allocator: *std.mem.Allocator, tree: *ast.Tree) !Docume
enum_completions.deinit(allocator); enum_completions.deinit(allocator);
} }
try makeScopeInternal(allocator, &scopes, &error_completions, &enum_completions, tree, &tree.root_node.base); try makeScopeInternal(allocator, &scopes, &error_completions, &enum_completions, tree);
return DocumentScope{ return DocumentScope{
.scopes = scopes.toOwnedSlice(allocator), .scopes = scopes.toOwnedSlice(allocator),
.error_completions = error_completions.toOwnedSlice(allocator), .error_completions = error_completions.toOwnedSlice(allocator),
@ -2062,10 +2097,11 @@ pub fn makeDocumentScope(allocator: *std.mem.Allocator, tree: *ast.Tree) !Docume
}; };
} }
fn nodeSourceRange(tree: *ast.Tree, node: *ast.Node) SourceRange { fn nodeSourceRange(tree: ast.Tree, node: ast.Node.Index) SourceRange {
const loc = tree.tokenLocation(0, tree.firstToken(node));
return SourceRange{ return SourceRange{
.start = tree.token_locs[node.firstToken()].start, .start = loc.line_start,
.end = tree.token_locs[node.lastToken()].end, .end = loc.line_end,
}; };
} }
@ -2076,39 +2112,42 @@ fn makeScopeInternal(
scopes: *std.ArrayListUnmanaged(Scope), scopes: *std.ArrayListUnmanaged(Scope),
error_completions: *std.ArrayListUnmanaged(types.CompletionItem), error_completions: *std.ArrayListUnmanaged(types.CompletionItem),
enum_completions: *std.ArrayListUnmanaged(types.CompletionItem), enum_completions: *std.ArrayListUnmanaged(types.CompletionItem),
tree: *ast.Tree, tree: ast.Tree,
node: *ast.Node, node_idx: ast.Node.Index,
) error{OutOfMemory}!void { ) error{OutOfMemory}!void {
if (node.tag == .Root or node.tag == .ContainerDecl or node.tag == .ErrorSetDecl) { const nodes = tree.nodes.items(.tag);
const ast_decls = switch (node.tag) { const node = nodes[node_idx];
.ContainerDecl => node.castTag(.ContainerDecl).?.fieldsAndDeclsConst(), if (node == .root or node == .container_decl or node == .error_set_decl) {
.Root => node.castTag(.Root).?.declsConst(), const ast_decls = switch (node) {
.ErrorSetDecl => node.castTag(.ErrorSetDecl).?.declsConst(), .container_decl => tree.containerDecl(node_idx).ast.members,
.root => tree.rootDecls(),
// @TODO: Fix error set declarations
// .error_set_decl => node.castTag(.ErrorSetDecl).?.declsConst(),
else => unreachable, else => unreachable,
}; };
(try scopes.addOne(allocator)).* = .{ (try scopes.addOne(allocator)).* = .{
.range = nodeSourceRange(tree, node), .range = nodeSourceRange(tree, node),
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .{ .container = node }, .data = .{ .container = node },
}; };
const scope_idx = scopes.items.len - 1; const scope_idx = scopes.items.len - 1;
var uses = std.ArrayList(*ast.Node.Use).init(allocator); // var uses = std.ArrayList(*ast.Node.Use).init(allocator);
var tests = std.ArrayList(*ast.Node).init(allocator); var tests = std.ArrayList(*ast.Node).init(allocator);
errdefer { errdefer {
scopes.items[scope_idx].decls.deinit(); scopes.items[scope_idx].decls.deinit();
uses.deinit(); // uses.deinit();
tests.deinit(); tests.deinit();
} }
for (ast_decls) |decl| { for (ast_decls) |decl| {
if (decl.castTag(.Use)) |use| { // if (decl.castTag(.Use)) |use| {
try uses.append(use); // try uses.append(use);
continue; // continue;
} // }
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, decl); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, decl);
const name = getDeclName(tree, decl) orelse continue; const name = getDeclName(tree, decl) orelse continue;
@ -2159,7 +2198,7 @@ fn makeScopeInternal(
} }
scopes.items[scope_idx].tests = tests.toOwnedSlice(); scopes.items[scope_idx].tests = tests.toOwnedSlice();
scopes.items[scope_idx].uses = uses.toOwnedSlice(); // scopes.items[scope_idx].uses = uses.toOwnedSlice();
return; return;
} }
@ -2170,7 +2209,7 @@ fn makeScopeInternal(
(try scopes.addOne(allocator)).* = .{ (try scopes.addOne(allocator)).* = .{
.range = nodeSourceRange(tree, node), .range = nodeSourceRange(tree, node),
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .{ .function = node }, .data = .{ .function = node },
}; };
@ -2204,7 +2243,7 @@ fn makeScopeInternal(
.end = tree.token_locs[block.rbrace].end, .end = tree.token_locs[block.rbrace].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2217,24 +2256,24 @@ fn makeScopeInternal(
(try scopes.addOne(allocator)).* = .{ (try scopes.addOne(allocator)).* = .{
.range = nodeSourceRange(tree, node), .range = nodeSourceRange(tree, node),
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .{ .block = node }, .data = .{ .block = node },
}; };
var scope_idx = scopes.items.len - 1; var scope_idx = scopes.items.len - 1;
var uses = std.ArrayList(*ast.Node.Use).init(allocator); // var uses = std.ArrayList(*ast.Node.Use).init(allocator);
errdefer { errdefer {
scopes.items[scope_idx].decls.deinit(); scopes.items[scope_idx].decls.deinit();
uses.deinit(); // uses.deinit();
} }
var child_idx: usize = 0; var child_idx: usize = 0;
while (node.iterate(child_idx)) |child_node| : (child_idx += 1) { while (node.iterate(child_idx)) |child_node| : (child_idx += 1) {
if (child_node.castTag(.Use)) |use| { // if (child_node.castTag(.Use)) |use| {
try uses.append(use); // try uses.append(use);
continue; // continue;
} // }
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, child_node); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, child_node);
if (child_node.castTag(.VarDecl)) |var_decl| { if (child_node.castTag(.VarDecl)) |var_decl| {
@ -2245,7 +2284,7 @@ fn makeScopeInternal(
} }
} }
scopes.items[scope_idx].uses = uses.toOwnedSlice(); // scopes.items[scope_idx].uses = uses.toOwnedSlice();
return; return;
}, },
.Block => { .Block => {
@ -2254,24 +2293,24 @@ fn makeScopeInternal(
(try scopes.addOne(allocator)).* = .{ (try scopes.addOne(allocator)).* = .{
.range = nodeSourceRange(tree, node), .range = nodeSourceRange(tree, node),
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .{ .block = node }, .data = .{ .block = node },
}; };
var scope_idx = scopes.items.len - 1; var scope_idx = scopes.items.len - 1;
var uses = std.ArrayList(*ast.Node.Use).init(allocator); // var uses = std.ArrayList(*ast.Node.Use).init(allocator);
errdefer { errdefer {
scopes.items[scope_idx].decls.deinit(); scopes.items[scope_idx].decls.deinit();
uses.deinit(); // uses.deinit();
} }
var child_idx: usize = 0; var child_idx: usize = 0;
while (node.iterate(child_idx)) |child_node| : (child_idx += 1) { while (node.iterate(child_idx)) |child_node| : (child_idx += 1) {
if (child_node.castTag(.Use)) |use| { // if (child_node.castTag(.Use)) |use| {
try uses.append(use); // try uses.append(use);
continue; // continue;
} // }
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, child_node); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, child_node);
if (child_node.castTag(.VarDecl)) |var_decl| { if (child_node.castTag(.VarDecl)) |var_decl| {
@ -2282,7 +2321,7 @@ fn makeScopeInternal(
} }
} }
scopes.items[scope_idx].uses = uses.toOwnedSlice(); // scopes.items[scope_idx].uses = uses.toOwnedSlice();
return; return;
}, },
.Comptime => { .Comptime => {
@ -2300,7 +2339,7 @@ fn makeScopeInternal(
.end = tree.token_locs[if_node.body.lastToken()].end, .end = tree.token_locs[if_node.body.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2328,7 +2367,7 @@ fn makeScopeInternal(
.end = tree.token_locs[else_node.body.lastToken()].end, .end = tree.token_locs[else_node.body.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2353,7 +2392,7 @@ fn makeScopeInternal(
.end = tree.token_locs[while_node.lastToken()].end, .end = tree.token_locs[while_node.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2373,7 +2412,7 @@ fn makeScopeInternal(
.end = tree.token_locs[while_node.body.lastToken()].end, .end = tree.token_locs[while_node.body.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2401,7 +2440,7 @@ fn makeScopeInternal(
.end = tree.token_locs[else_node.body.lastToken()].end, .end = tree.token_locs[else_node.body.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2426,7 +2465,7 @@ fn makeScopeInternal(
.end = tree.token_locs[for_node.lastToken()].end, .end = tree.token_locs[for_node.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2448,7 +2487,7 @@ fn makeScopeInternal(
.end = tree.token_locs[for_node.body.lastToken()].end, .end = tree.token_locs[for_node.body.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };
@ -2489,7 +2528,7 @@ fn makeScopeInternal(
.end = tree.token_locs[case_node.expr.lastToken()].end, .end = tree.token_locs[case_node.expr.lastToken()].end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
.uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &[0]*ast.Node{},
.data = .other, .data = .other,
}; };

View File

@ -22,7 +22,7 @@ pub const Handle = struct {
document: types.TextDocument, document: types.TextDocument,
count: usize, count: usize,
import_uris: std.ArrayList([]const u8), import_uris: std.ArrayList([]const u8),
tree: *std.zig.ast.Tree, tree: std.zig.ast.Tree,
document_scope: analysis.DocumentScope, document_scope: analysis.DocumentScope,
associated_build_file: ?*BuildFile, associated_build_file: ?*BuildFile,
@ -143,8 +143,8 @@ fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) anyerror!*Hand
var handle = try self.allocator.create(Handle); var handle = try self.allocator.create(Handle);
errdefer self.allocator.destroy(handle); errdefer self.allocator.destroy(handle);
const tree = try std.zig.parse(self.allocator, text); var tree = try std.zig.parse(self.allocator, text);
errdefer tree.deinit(); errdefer tree.deinit(self.allocator);
const document_scope = try analysis.makeDocumentScope(self.allocator, tree); const document_scope = try analysis.makeDocumentScope(self.allocator, tree);
errdefer document_scope.deinit(self.allocator); errdefer document_scope.deinit(self.allocator);
@ -326,7 +326,7 @@ fn decrementCount(self: *DocumentStore, uri: []const u8) void {
self.decrementBuildFileRefs(build_file); self.decrementBuildFileRefs(build_file);
} }
entry.value.tree.deinit(); entry.value.tree.deinit(self.allocator);
self.allocator.free(entry.value.document.mem); self.allocator.free(entry.value.document.mem);
for (entry.value.import_uris.items) |import_uri| { for (entry.value.import_uris.items) |import_uri| {
@ -354,7 +354,7 @@ pub fn getHandle(self: *DocumentStore, uri: []const u8) ?*Handle {
// Check if the document text is now sane, move it to sane_text if so. // Check if the document text is now sane, move it to sane_text if so.
fn refreshDocument(self: *DocumentStore, handle: *Handle, zig_lib_path: ?[]const u8) !void { fn refreshDocument(self: *DocumentStore, handle: *Handle, zig_lib_path: ?[]const u8) !void {
log.debug("New text for document {s}", .{handle.uri()}); log.debug("New text for document {s}", .{handle.uri()});
handle.tree.deinit(); handle.tree.deinit(self.allocator);
handle.tree = try std.zig.parse(self.allocator, handle.document.text); handle.tree = try std.zig.parse(self.allocator, handle.document.text);
handle.document_scope.deinit(self.allocator); handle.document_scope.deinit(self.allocator);
@ -613,7 +613,7 @@ pub fn deinit(self: *DocumentStore) void {
var entry_iterator = self.handles.iterator(); var entry_iterator = self.handles.iterator();
while (entry_iterator.next()) |entry| { while (entry_iterator.next()) |entry| {
entry.value.document_scope.deinit(self.allocator); entry.value.document_scope.deinit(self.allocator);
entry.value.tree.deinit(); entry.value.tree.deinit(self.allocator);
self.allocator.free(entry.value.document.mem); self.allocator.free(entry.value.document.mem);
for (entry.value.import_uris.items) |uri| { for (entry.value.import_uris.items) |uri| {

View File

@ -199,8 +199,8 @@ fn publishDiagnostics(arena: *std.heap.ArenaAllocator, handle: DocumentStore.Han
var diagnostics = std.ArrayList(types.Diagnostic).init(&arena.allocator); var diagnostics = std.ArrayList(types.Diagnostic).init(&arena.allocator);
for (tree.errors) |*err| { for (tree.errors) |err| {
const loc = tree.tokenLocation(0, err.loc()); const loc = tree.tokenLocation(0, err.token);
var mem_buffer: [256]u8 = undefined; var mem_buffer: [256]u8 = undefined;
var fbs = std.io.fixedBufferStream(&mem_buffer); var fbs = std.io.fixedBufferStream(&mem_buffer);
@ -209,7 +209,7 @@ fn publishDiagnostics(arena: *std.heap.ArenaAllocator, handle: DocumentStore.Han
try diagnostics.append(.{ try diagnostics.append(.{
.range = astLocationToRange(loc), .range = astLocationToRange(loc),
.severity = .Error, .severity = .Error,
.code = @tagName(err.*), .code = @tagName(err.tag),
.source = "zls", .source = "zls",
.message = try std.mem.dupe(&arena.allocator, u8, fbs.getWritten()), .message = try std.mem.dupe(&arena.allocator, u8, fbs.getWritten()),
// .relatedInformation = undefined // .relatedInformation = undefined
@ -217,16 +217,17 @@ fn publishDiagnostics(arena: *std.heap.ArenaAllocator, handle: DocumentStore.Han
} }
if (tree.errors.len == 0) { if (tree.errors.len == 0) {
for (tree.root_node.decls()) |decl| { for (tree.rootDecls()) |decl_idx| {
switch (decl.tag) { const decl = tree.nodes.items(.tag)[decl_idx];
.FnProto => blk: { switch (decl) {
const func = decl.cast(std.zig.ast.Node.FnProto).?; .fn_proto => blk: {
const is_extern = func.getExternExportInlineToken() != null; const func = tree.fnProto(decl_idx);
const is_extern = func.extern_export_token != null;
if (is_extern) if (is_extern)
break :blk; break :blk;
if (config.warn_style) { if (config.warn_style) {
if (func.getNameToken()) |name_token| { if (func.name_token) |name_token| {
const loc = tree.tokenLocation(0, name_token); const loc = tree.tokenLocation(0, name_token);
const is_type_function = analysis.isTypeFunction(tree, func); const is_type_function = analysis.isTypeFunction(tree, func);
@ -397,12 +398,10 @@ fn nodeToCompletion(
}, },
else => break :param_check false, else => break :param_check false,
} }
} else } else false;
false;
break :blk try analysis.getFunctionSnippet(&arena.allocator, handle.tree, func, skip_self_param); break :blk try analysis.getFunctionSnippet(&arena.allocator, handle.tree, func, skip_self_param);
} else } else null;
null;
const is_type_function = analysis.isTypeFunction(handle.tree, func); const is_type_function = analysis.isTypeFunction(handle.tree, func);

View File

@ -70,15 +70,15 @@ pub const TokenLocation = struct {
} }
}; };
pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token: std.zig.ast.TokenIndex, encoding: Encoding) !TokenLocation { pub fn tokenRelativeLocation(tree: std.zig.ast.Tree, start_index: usize, token: std.zig.ast.TokenIndex, encoding: Encoding) !TokenLocation {
const token_loc = tree.token_locs[token]; const token_loc = tree.tokenLocation(@truncate(u32, start_index), token);
var loc = TokenLocation{ var loc = TokenLocation{
.line = 0, .line = 0,
.column = 0, .column = 0,
.offset = 0, .offset = 0,
}; };
const token_start = token_loc.start; const token_start = token_loc.line_start;
const source = tree.source[start_index..]; const source = tree.source[start_index..];
var i: usize = 0; var i: usize = 0;
while (i + start_index < token_start) { while (i + start_index < token_start) {
@ -108,10 +108,10 @@ pub fn tokenRelativeLocation(tree: *std.zig.ast.Tree, start_index: usize, token:
} }
/// Asserts the token is comprised of valid utf8 /// Asserts the token is comprised of valid utf8
pub fn tokenLength(tree: *std.zig.ast.Tree, token: std.zig.ast.TokenIndex, encoding: Encoding) usize { pub fn tokenLength(tree: std.zig.ast.Tree, token: std.zig.ast.TokenIndex, encoding: Encoding) usize {
const token_loc = tree.token_locs[token]; const token_loc = tree.tokenLocation(0, token);
if (encoding == .utf8) if (encoding == .utf8)
return token_loc.end - token_loc.start; return token_loc.line_end - token_loc.line_start;
var i: usize = token_loc.start; var i: usize = token_loc.start;
var utf16_len: usize = 0; var utf16_len: usize = 0;

View File

@ -65,11 +65,11 @@ const Builder = struct {
fn add(self: *Builder, token: ast.TokenIndex, token_type: TokenType, token_modifiers: TokenModifiers) !void { fn add(self: *Builder, token: ast.TokenIndex, token_type: TokenType, token_modifiers: TokenModifiers) !void {
const start_idx = if (self.current_token) |current_token| const start_idx = if (self.current_token) |current_token|
self.handle.tree.token_locs[current_token].start self.handle.tree.tokenLocation[current_token].line_start
else else
0; 0;
if (start_idx > self.handle.tree.token_locs[token].start) if (start_idx > self.handle.tree.tokenLocation[token].line_start)
return; return;
const delta_loc = offsets.tokenRelativeLocation(self.handle.tree, start_idx, token, self.encoding) catch return; const delta_loc = offsets.tokenRelativeLocation(self.handle.tree, start_idx, token, self.encoding) catch return;