First set of changes to work with new std's ast
This commit is contained in:
parent
a886ecddd9
commit
0133f0d863
443
src/analysis.zig
443
src/analysis.zig
@ -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(¶ms, 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(¶ms, 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,
|
||||||
};
|
};
|
||||||
|
@ -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| {
|
||||||
|
25
src/main.zig
25
src/main.zig
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user