Merge pull request #582 from Techatrix/refactor-ast-helper

Refactor Ast helper functions
This commit is contained in:
Auguste Rame 2022-08-18 20:14:53 +02:00 committed by GitHub
commit a04de8a8a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 118 additions and 223 deletions

View File

@ -299,17 +299,8 @@ fn publishDiagnostics(server: *Server, writer: anytype, handle: DocumentStore.Ha
if (!std.mem.eql(u8, call_name, "@import")) continue;
const node_data = tree.nodes.items(.data)[node];
const params = switch (tree.nodes.items(.tag)[node]) {
.builtin_call, .builtin_call_comma => tree.extra_data[node_data.lhs..node_data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (node_data.lhs == 0)
&[_]Ast.Node.Index{}
else if (node_data.rhs == 0)
&[_]Ast.Node.Index{node_data.lhs}
else
&[_]Ast.Node.Index{ node_data.lhs, node_data.rhs },
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const params = ast.builtinCallParams(tree, node, &buffer).?;
if (params.len != 1) continue;

View File

@ -203,7 +203,7 @@ pub fn hasSelfParam(arena: *std.heap.ArenaAllocator, document_store: *DocumentSt
return true;
}
if (isPtrType(tree, param.type_expr)) {
if (ast.isPtrType(tree, param.type_expr)) {
if (try resolveTypeOfNode(document_store, arena, .{
.node = token_data[param.type_expr].rhs,
.handle = handle,
@ -311,13 +311,6 @@ fn getDeclName(tree: Ast, node: Ast.Node.Index) ?[]const u8 {
};
}
fn isContainerDecl(decl_handle: DeclWithHandle) bool {
return switch (decl_handle.decl.*) {
.ast_node => |inner_node| ast.isContainer(decl_handle.handle.tree.nodes.items(.tag)[inner_node]),
else => false,
};
}
fn resolveVarDeclAliasInternal(store: *DocumentStore, arena: *std.heap.ArenaAllocator, node_handle: NodeWithHandle, root: bool) error{OutOfMemory}!?DeclWithHandle {
_ = root;
const handle = node_handle.handle;
@ -394,39 +387,14 @@ pub fn resolveVarDeclAlias(store: *DocumentStore, arena: *std.heap.ArenaAllocato
return null;
}
fn isBlock(tree: Ast, node: Ast.Node.Index) bool {
return switch (tree.nodes.items(.tag)[node]) {
.block,
.block_semicolon,
.block_two,
.block_two_semicolon,
=> true,
else => false,
};
}
fn findReturnStatementInternal(tree: Ast, fn_decl: Ast.full.FnProto, body: Ast.Node.Index, already_found: *bool) ?Ast.Node.Index {
var result: ?Ast.Node.Index = null;
const node_tags = tree.nodes.items(.tag);
const datas = tree.nodes.items(.data);
if (!isBlock(tree, body)) return null;
const statements: []const Ast.Node.Index = switch (node_tags[body]) {
.block, .block_semicolon => tree.extra_data[datas[body].lhs..datas[body].rhs],
.block_two, .block_two_semicolon => blk: {
const statements = &[_]Ast.Node.Index{ datas[body].lhs, datas[body].rhs };
const len: usize = if (datas[body].lhs == 0)
@as(usize, 0)
else if (datas[body].rhs == 0)
@as(usize, 1)
else
@as(usize, 2);
break :blk statements[0..len];
},
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const statements = ast.blockStatements(tree, body, &buffer) orelse return null;
for (statements) |child_idx| {
if (node_tags[child_idx] == .@"return") {
@ -532,17 +500,6 @@ fn resolveUnwrapErrorType(store: *DocumentStore, arena: *std.heap.ArenaAllocator
return null;
}
pub fn isPtrType(tree: Ast, node: Ast.Node.Index) bool {
return switch (tree.nodes.items(.tag)[node]) {
.ptr_type,
.ptr_type_aligned,
.ptr_type_bit_range,
.ptr_type_sentinel,
=> true,
else => false,
};
}
/// Resolves the child type of a deref type
fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, deref: TypeWithHandle, bound_type_params: *BoundTypeParams) !?TypeWithHandle {
const deref_node = switch (deref.type.data) {
@ -560,7 +517,7 @@ fn resolveDerefType(store: *DocumentStore, arena: *std.heap.ArenaAllocator, dere
const main_token = tree.nodes.items(.main_token)[deref_node];
const token_tag = tree.tokens.items(.tag)[main_token];
if (isPtrType(tree, deref_node)) {
if (ast.isPtrType(tree, deref_node)) {
const ptr_type = ast.ptrType(tree, deref_node).?;
switch (token_tag) {
.asterisk => {
@ -900,17 +857,8 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
.builtin_call_two,
.builtin_call_two_comma,
=> {
const data = datas[node];
const params = switch (node_tags[node]) {
.builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (data.lhs == 0)
&[_]Ast.Node.Index{}
else if (data.rhs == 0)
&[_]Ast.Node.Index{data.lhs}
else
&[_]Ast.Node.Index{ data.lhs, data.rhs },
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const params = ast.builtinCallParams(tree, node, &buffer).?;
const call_name = tree.tokenSlice(main_tokens[node]);
if (std.mem.eql(u8, call_name, "@This")) {
@ -1399,17 +1347,9 @@ pub fn getImportStr(tree: Ast, node: Ast.Node.Index, source_index: usize) ?[]con
const call_name = tree.tokenSlice(builtin_token);
if (!std.mem.eql(u8, call_name, "@import")) return null;
const data = tree.nodes.items(.data)[node];
const params = switch (node_tags[node]) {
.builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (data.lhs == 0)
&[_]Ast.Node.Index{}
else if (data.rhs == 0)
&[_]Ast.Node.Index{data.lhs}
else
&[_]Ast.Node.Index{ data.lhs, data.rhs },
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const params = ast.builtinCallParams(tree, node, &buffer).?;
if (params.len != 1) return null;
@ -2522,21 +2462,8 @@ fn makeInnerScope(allocator: std.mem.Allocator, context: ScopeContext, node_idx:
}
}
const container_decl = switch (node_tag) {
.container_decl, .container_decl_trailing => tree.containerDecl(node_idx),
.container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx),
.container_decl_two, .container_decl_two_trailing => blk: {
var buffer: [2]Ast.Node.Index = undefined;
break :blk tree.containerDeclTwo(&buffer, node_idx);
},
.tagged_union, .tagged_union_trailing => tree.taggedUnion(node_idx),
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(node_idx),
.tagged_union_two, .tagged_union_two_trailing => blk: {
var buffer: [2]Ast.Node.Index = undefined;
break :blk tree.taggedUnionTwo(&buffer, node_idx);
},
else => null,
};
var buffer: [2]Ast.Node.Index = undefined;
const container_decl = ast.containerDecl(tree, node_idx, &buffer);
// Only tagged unions and enums should pass this
const can_have_enum_completions = if (container_decl) |container| blk: {
@ -2717,20 +2644,8 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
uses.deinit();
}
const statements: []const Ast.Node.Index = switch (node_tag) {
.block, .block_semicolon => tree.extra_data[data[node_idx].lhs..data[node_idx].rhs],
.block_two, .block_two_semicolon => blk: {
const statements = &[_]Ast.Node.Index{ data[node_idx].lhs, data[node_idx].rhs };
const len: usize = if (data[node_idx].lhs == 0)
@as(usize, 0)
else if (data[node_idx].rhs == 0)
@as(usize, 1)
else
@as(usize, 2);
break :blk statements[0..len];
},
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const statements = ast.blockStatements(tree, node_idx, &buffer).?;
for (statements) |idx| {
if (tags[idx] == .@"usingnamespace") {
@ -3058,17 +2973,8 @@ fn makeScopeInternal(allocator: std.mem.Allocator, context: ScopeContext, node_i
.builtin_call_two,
.builtin_call_two_comma,
=> {
const b_data = data[node_idx];
const params = switch (node_tag) {
.builtin_call, .builtin_call_comma => tree.extra_data[b_data.lhs..b_data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (b_data.lhs == 0)
&[_]Ast.Node.Index{}
else if (b_data.rhs == 0)
&[_]Ast.Node.Index{b_data.lhs}
else
&[_]Ast.Node.Index{ b_data.lhs, b_data.rhs },
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const params = ast.builtinCallParams(tree, node_idx, &buffer).?;
for (params) |param| {
try makeScopeInternal(allocator, context, param);

View File

@ -948,6 +948,18 @@ pub fn isContainer(tree: Ast, node: Ast.Node.Index) bool {
};
}
pub fn containerDecl(tree: Ast, node_idx: Ast.Node.Index, buffer: *[2]Ast.Node.Index) ?full.ContainerDecl {
return switch (tree.nodes.items(.tag)[node_idx]) {
.container_decl, .container_decl_trailing => tree.containerDecl(node_idx),
.container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node_idx),
.container_decl_two, .container_decl_two_trailing => tree.containerDeclTwo(buffer, node_idx),
.tagged_union, .tagged_union_trailing => tree.taggedUnion(node_idx),
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(node_idx),
.tagged_union_two, .tagged_union_two_trailing => tree.taggedUnionTwo(buffer, node_idx),
else => null,
};
}
/// Returns the member indices of a given declaration container.
/// Asserts given `tag` is a container node
pub fn declMembers(tree: Ast, node_idx: Ast.Node.Index, buffer: *[2]Ast.Node.Index) []const Ast.Node.Index {
@ -977,6 +989,17 @@ pub fn varDecl(tree: Ast, node_idx: Ast.Node.Index) ?Ast.full.VarDecl {
};
}
pub fn isPtrType(tree: Ast, node: Ast.Node.Index) bool {
return switch (tree.nodes.items(.tag)[node]) {
.ptr_type,
.ptr_type_aligned,
.ptr_type_bit_range,
.ptr_type_sentinel,
=> true,
else => false,
};
}
pub fn isBuiltinCall(tree: Ast, node: Ast.Node.Index) bool {
return switch (tree.nodes.items(.tag)[node]) {
.builtin_call,
@ -1003,6 +1026,17 @@ pub fn isCall(tree: Ast, node: Ast.Node.Index) bool {
};
}
pub fn isBlock(tree: Ast, node: Ast.Node.Index) bool {
return switch (tree.nodes.items(.tag)[node]) {
.block_two,
.block_two_semicolon,
.block,
.block_semicolon,
=> true,
else => false,
};
}
pub fn fnProto(tree: Ast, node: Ast.Node.Index, buf: *[1]Ast.Node.Index) ?Ast.full.FnProto {
return switch (tree.nodes.items(.tag)[node]) {
.fn_proto => tree.fnProto(node),
@ -1029,3 +1063,47 @@ pub fn callFull(tree: Ast, node: Ast.Node.Index, buf: *[1]Ast.Node.Index) ?Ast.f
else => null,
};
}
/// returns a list of parameters
pub fn builtinCallParams(tree: Ast, node: Ast.Node.Index, buf: *[2]Ast.Node.Index) ?[]const Node.Index {
const node_data = tree.nodes.items(.data);
return switch (tree.nodes.items(.tag)[node]) {
.builtin_call_two, .builtin_call_two_comma => {
buf[0] = node_data[node].lhs;
buf[1] = node_data[node].rhs;
if (node_data[node].lhs == 0) {
return buf[0..0];
} else if (node_data[node].rhs == 0) {
return buf[0..1];
} else {
return buf[0..2];
}
},
.builtin_call,
.builtin_call_comma,
=> tree.extra_data[node_data[node].lhs..node_data[node].rhs],
else => return null,
};
}
/// returns a list of statements
pub fn blockStatements(tree: Ast, node: Ast.Node.Index, buf: *[2]Ast.Node.Index) ?[]const Node.Index {
const node_data = tree.nodes.items(.data);
return switch (tree.nodes.items(.tag)[node]) {
.block_two, .block_two_semicolon => {
buf[0] = node_data[node].lhs;
buf[1] = node_data[node].rhs;
if (node_data[node].lhs == 0) {
return buf[0..0];
} else if (node_data[node].rhs == 0) {
return buf[0..1];
} else {
return buf[0..2];
}
},
.block,
.block_semicolon,
=> tree.extra_data[node_data[node].lhs..node_data[node].rhs],
else => return null,
};
}

View File

@ -133,7 +133,7 @@ fn writeCallHint(builder: *Builder, arena: *std.heap.ArenaAllocator, store: *Doc
}
/// takes parameter nodes from the ast and function parameter names from `Builtin.arguments` and writes parameter hints into `builder.hints`
fn writeBuiltinHint(builder: *Builder, parameters: []Ast.Node.Index, arguments: []const []const u8) !void {
fn writeBuiltinHint(builder: *Builder, parameters: []const Ast.Node.Index, arguments: []const []const u8) !void {
if (parameters.len == 0) return;
const handle = builder.handle;
@ -290,25 +290,9 @@ fn writeNodeInlayHint(builder: *Builder, arena: *std.heap.ArenaAllocator, store:
.builtin_call_comma,
=> {
var buffer: [2]Ast.Node.Index = undefined;
const parameters: []Ast.Node.Index = switch (tag) {
.builtin_call_two, .builtin_call_two_comma => blk: {
buffer[0] = node_data[node].lhs;
buffer[1] = node_data[node].rhs;
const params = ast.builtinCallParams(tree, node, &buffer).?;
var size: usize = 0;
if (node_data[node].rhs != 0) {
size = 2;
} else if (node_data[node].lhs != 0) {
size = 1;
}
break :blk buffer[0..size];
},
.builtin_call, .builtin_call_comma => tree.extra_data[node_data[node].lhs..node_data[node].rhs],
else => unreachable,
};
if (builder.config.inlay_hints_show_builtin and parameters.len > 1) {
if (builder.config.inlay_hints_show_builtin and params.len > 1) {
const name = tree.tokenSlice(main_tokens[node]);
outer: for (data.builtins) |builtin| {
@ -318,12 +302,12 @@ fn writeNodeInlayHint(builder: *Builder, arena: *std.heap.ArenaAllocator, store:
if (std.mem.eql(u8, builtin_name, name)) break :outer;
}
try writeBuiltinHint(builder, parameters, builtin.arguments);
try writeBuiltinHint(builder, params, builtin.arguments);
}
}
for (parameters) |param| {
if (parameters.len > inlay_hints_max_inline_children) {
for (params) |param| {
if (params.len > inlay_hints_max_inline_children) {
if (!isNodeInRange(tree, param, range)) continue;
}
@ -623,15 +607,7 @@ fn writeNodeInlayHint(builder: *Builder, arena: *std.heap.ArenaAllocator, store:
.tagged_union_enum_tag_trailing,
=> {
var buffer: [2]Ast.Node.Index = undefined;
const decl: Ast.full.ContainerDecl = switch (tag) {
.container_decl, .container_decl_trailing => tree.containerDecl(node),
.container_decl_two, .container_decl_two_trailing => tree.containerDeclTwo(&buffer, node),
.container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),
.tagged_union, .tagged_union_trailing => tree.taggedUnion(node),
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(node),
.tagged_union_two, .tagged_union_two_trailing => tree.taggedUnionTwo(&buffer, node),
else => unreachable,
};
const decl: Ast.full.ContainerDecl = ast.containerDecl(tree, node, &buffer).?;
try await @asyncCall(child_frame, {}, writeNodeInlayHint, .{ builder, arena, store, decl.ast.arg, range });

View File

@ -67,20 +67,9 @@ fn symbolReferencesInternal(arena: *std.heap.ArenaAllocator, store: *DocumentSto
switch (node_tags[node]) {
.block, .block_semicolon, .block_two, .block_two_semicolon => {
const statements: []const Ast.Node.Index = switch (node_tags[node]) {
.block, .block_semicolon => tree.extra_data[datas[node].lhs..datas[node].rhs],
.block_two, .block_two_semicolon => blk: {
const statements = &[_]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };
const len: usize = if (datas[node].lhs == 0)
@as(usize, 0)
else if (datas[node].rhs == 0)
@as(usize, 1)
else
@as(usize, 2);
break :blk statements[0..len];
},
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const statements = ast.blockStatements(tree, node, &buffer).?;
for (statements) |stmt|
try symbolReferencesInternal(arena, store, .{ .node = stmt, .handle = handle }, decl, encoding, context, handler);
},
@ -319,13 +308,10 @@ fn symbolReferencesInternal(arena: *std.heap.ArenaAllocator, store: *DocumentSto
.async_call_comma,
.async_call_one,
.async_call_one_comma,
=> |c| {
=> {
var buf: [1]Ast.Node.Index = undefined;
const call: Ast.full.Call = switch (c) {
.call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
.call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&buf, node),
else => unreachable,
};
const call = ast.callFull(tree, node, &buf).?;
if (call.ast.fn_expr != 0)
try symbolReferencesInternal(arena, store, .{ .node = call.ast.fn_expr, .handle = handle }, decl, encoding, context, handler);
@ -380,18 +366,9 @@ fn symbolReferencesInternal(arena: *std.heap.ArenaAllocator, store: *DocumentSto
.builtin_call_comma,
.builtin_call_two,
.builtin_call_two_comma,
=> |builtin_tag| {
const data = datas[node];
const params = switch (builtin_tag) {
.builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (data.lhs == 0)
&[_]Ast.Node.Index{}
else if (data.rhs == 0)
&[_]Ast.Node.Index{data.lhs}
else
&[_]Ast.Node.Index{ data.lhs, data.rhs },
else => unreachable,
};
=> {
var buffer: [2]Ast.Node.Index = undefined;
const params = ast.builtinCallParams(tree, node, &buffer).?;
for (params) |param|
try symbolReferencesInternal(arena, store, .{ .node = param, .handle = handle }, decl, encoding, context, handler);

View File

@ -317,20 +317,8 @@ fn writeNodeTokens(builder: *Builder, arena: *std.heap.ArenaAllocator, store: *D
try writeToken(builder, main_token - 2, .label);
}
const statements: []const Ast.Node.Index = switch (tag) {
.block, .block_semicolon => tree.extra_data[node_data[node].lhs..node_data[node].rhs],
.block_two, .block_two_semicolon => blk: {
const statements = &[_]Ast.Node.Index{ node_data[node].lhs, node_data[node].rhs };
const len: usize = if (node_data[node].lhs == 0)
@as(usize, 0)
else if (node_data[node].rhs == 0)
@as(usize, 1)
else
@as(usize, 2);
break :blk statements[0..len];
},
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const statements = ast.blockStatements(tree, node, &buffer).?;
for (statements) |child| {
if (node_tags[child].isContainerField()) {
@ -390,15 +378,7 @@ fn writeNodeTokens(builder: *Builder, arena: *std.heap.ArenaAllocator, store: *D
.tagged_union_two_trailing,
=> {
var buf: [2]Ast.Node.Index = undefined;
const decl: Ast.full.ContainerDecl = switch (tag) {
.container_decl, .container_decl_trailing => tree.containerDecl(node),
.container_decl_two, .container_decl_two_trailing => tree.containerDeclTwo(&buf, node),
.container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),
.tagged_union, .tagged_union_trailing => tree.taggedUnion(node),
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => tree.taggedUnionEnumTag(node),
.tagged_union_two, .tagged_union_two_trailing => tree.taggedUnionTwo(&buf, node),
else => unreachable,
};
const decl: Ast.full.ContainerDecl = ast.containerDecl(tree, node, &buf).?;
try writeToken(builder, decl.layout_token, .keyword);
try writeToken(builder, decl.ast.main_token, .keyword);
@ -427,7 +407,7 @@ fn writeNodeTokens(builder: *Builder, arena: *std.heap.ArenaAllocator, store: *D
.identifier => {
const name = tree.getNodeSource(node);
if(std.mem.eql(u8,name, "undefined")) {
if (std.mem.eql(u8, name, "undefined")) {
return try writeToken(builder, main_token, .keywordLiteral);
} else if (analysis.isTypeIdent(name)) {
return try writeToken(builder, main_token, .type);
@ -682,11 +662,7 @@ fn writeNodeTokens(builder: *Builder, arena: *std.heap.ArenaAllocator, store: *D
.async_call_one_comma,
=> {
var params: [1]Ast.Node.Index = undefined;
const call: Ast.full.Call = switch (tag) {
.call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
.call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&params, node),
else => unreachable,
};
const call = ast.callFull(tree, node, &params).?;
try writeToken(builder, call.async_token, .keyword);
try await @asyncCall(child_frame, {}, writeNodeTokens, .{ builder, arena, store, call.ast.fn_expr });
@ -757,17 +733,8 @@ fn writeNodeTokens(builder: *Builder, arena: *std.heap.ArenaAllocator, store: *D
.builtin_call_two,
.builtin_call_two_comma,
=> {
const data = node_data[node];
const params = switch (tag) {
.builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
.builtin_call_two, .builtin_call_two_comma => if (data.lhs == 0)
&[_]Ast.Node.Index{}
else if (data.rhs == 0)
&[_]Ast.Node.Index{data.lhs}
else
&[_]Ast.Node.Index{ data.lhs, data.rhs },
else => unreachable,
};
var buffer: [2]Ast.Node.Index = undefined;
const params = ast.builtinCallParams(tree, node, &buffer).?;
try writeToken(builder, main_token, .builtin);
for (params) |param|