Skip to content

Commit

Permalink
add basic support for destructuring syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Techatrix committed Sep 16, 2023
1 parent 214dde6 commit f53d9bb
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 16 deletions.
2 changes: 1 addition & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const zls_version = std.SemanticVersion{ .major = 0, .minor = 12, .patch = 0 };
pub fn build(b: *std.build.Builder) !void {
comptime {
const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse("0.12.0-dev.284+cab9da35b") catch unreachable; // Enable FailingAllocator to fail on resize
const min_zig = std.SemanticVersion.parse("0.12.0-dev.391+eac4c149b") catch unreachable; // compiler: implement destructuring syntax
if (current_zig.order(min_zig) == .lt) {
@compileError(std.fmt.comptimePrint("Your Zig version v{} does not meet the minimum build requirement of v{}", .{ current_zig, min_zig }));
}
Expand Down
24 changes: 21 additions & 3 deletions src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4035,9 +4035,27 @@ fn makeScopeAt(

for (statements) |idx| {
try makeScopeInternal(context, tree, idx);
if (tree.fullVarDecl(idx)) |var_decl| {
const name = tree.tokenSlice(var_decl.ast.mut_token + 1);
try context.putVarDecl(scope_index, name, .{ .ast_node = idx });
switch (tags[idx]) {
.global_var_decl,
.local_var_decl,
.aligned_var_decl,
.simple_var_decl,
=> {
const var_decl = tree.fullVarDecl(idx).?;
const name = tree.tokenSlice(var_decl.ast.mut_token + 1);
try context.putVarDecl(scope_index, name, .{ .ast_node = idx });
},
.assign_destructure => {
const lhs_count = tree.extra_data[data[idx].lhs];
const lhs_exprs = tree.extra_data[data[idx].lhs + 1 ..][0..lhs_count];

for (lhs_exprs) |lhs_node| {
const var_decl = tree.fullVarDecl(lhs_node) orelse continue;
const name = tree.tokenSlice(var_decl.ast.mut_token + 1);
try context.putVarDecl(scope_index, name, .{ .ast_node = idx }); // TODO add Declaration representation for destructuring
}
},
else => continue,
}
}
},
Expand Down
25 changes: 15 additions & 10 deletions src/ast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ pub fn lastToken(tree: Ast, node: Ast.Node.Index) Ast.TokenIndex {
.assign_sub_sat,
.assign_shl_sat,
.assign,
.assign_destructure,
.merge_error_sets,
.mul,
.div,
Expand Down Expand Up @@ -616,8 +617,7 @@ pub fn lastToken(tree: Ast, node: Ast.Node.Index) Ast.TokenIndex {
.switch_comma, .@"switch" => {
const lhs = datas[n].lhs;
const l_brace = tree.lastToken(lhs) + 2; //lparen + rbrace
return findMatchingRBrace(token_tags, l_brace)
orelse @intCast(tree.tokens.len - 1);
return findMatchingRBrace(token_tags, l_brace) orelse @intCast(tree.tokens.len - 1);
},
.@"asm" => {
const extra = tree.extraData(datas[n].rhs, Node.Asm);
Expand Down Expand Up @@ -678,25 +678,21 @@ pub fn lastToken(tree: Ast, node: Ast.Node.Index) Ast.TokenIndex {
.block_two_semicolon,
.block_two,
=> {
return findMatchingRBrace(token_tags, main_tokens[n])
orelse @intCast(tree.tokens.len - 1);
return findMatchingRBrace(token_tags, main_tokens[n]) orelse @intCast(tree.tokens.len - 1);
},
.container_decl_trailing,
.container_decl_two_trailing,
.container_decl_two,
=> {
// + 1 for the lbrace
return findMatchingRBrace(token_tags, main_tokens[n] + 1)
orelse @intCast(tree.tokens.len - 1);
return findMatchingRBrace(token_tags, main_tokens[n] + 1) orelse @intCast(tree.tokens.len - 1);
},
.container_decl_arg,
.container_decl_arg_trailing,
=> {
// + 4 for the lparen, identifier, rparen, lbrace
const l_brace = findNextLBrace(token_tags, main_tokens[n])
orelse return @intCast(tree.tokens.len - 1);
return findMatchingRBrace(token_tags, l_brace)
orelse @intCast(tree.tokens.len - 1);
const l_brace = findNextLBrace(token_tags, main_tokens[n]) orelse return @intCast(tree.tokens.len - 1);
return findMatchingRBrace(token_tags, l_brace) orelse @intCast(tree.tokens.len - 1);
},
.array_init_dot_two,
.builtin_call_two,
Expand Down Expand Up @@ -1387,6 +1383,15 @@ pub fn iterateChildren(
try callback(context, tree, var_decl.init_node);
},

.assign_destructure => {
const lhs_count = tree.extra_data[node_data[node].lhs];
const lhs_exprs = tree.extra_data[node_data[node].lhs + 1 ..][0..lhs_count];
for (lhs_exprs) |lhs_node| {
try callback(context, tree, lhs_node);
}
try callback(context, tree, node_data[node].rhs);
},

.array_type_sentinel => {
const array_type = tree.arrayTypeSentinel(node).ast;
try callback(context, tree, array_type.elem_count);
Expand Down
1 change: 1 addition & 0 deletions src/features/code_actions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ fn handleUnusedVariableOrConstant(builder: *Builder, actions: *std.ArrayListUnma
const first_token = tree.firstToken(node);
const last_token = ast.lastToken(tree, node) + 1;

if (last_token >= tree.tokens.len) return;
if (token_tags[last_token] != .semicolon) return;

const new_text = try createDiscardText(builder, identifier_name, token_starts[first_token], false);
Expand Down
11 changes: 11 additions & 0 deletions src/features/semantic_tokens.zig
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,17 @@ fn writeNodeTokens(builder: *Builder, node: Ast.Node.Index) error{OutOfMemory}!v
try writeToken(builder, main_token, token_type);
try writeNodeTokens(builder, node_data[node].rhs);
},
.assign_destructure => {
const lhs_count = tree.extra_data[node_data[node].lhs];
const lhs_exprs = tree.extra_data[node_data[node].lhs + 1 ..][0..lhs_count];

for (lhs_exprs) |lhs_node| {
try writeNodeTokens(builder, lhs_node);
}

try writeToken(builder, main_token, .operator);
try writeNodeTokens(builder, node_data[node].rhs);
},
.array_access,
.error_union,
.switch_range,
Expand Down
5 changes: 3 additions & 2 deletions tests/lsp_features/code_actions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ test "code actions - discard value" {
try testAutofix(
\\test {
\\ var foo = {};
\\ const bar = {};
\\ const bar, var baz = .{ 1, 2 };
\\}
\\
,
\\test {
\\ var foo = {};
\\ _ = foo;
\\ const bar = {};
\\ const bar, var baz = .{ 1, 2 };
\\ _ = baz;
\\ _ = bar;
\\}
\\
Expand Down
19 changes: 19 additions & 0 deletions tests/lsp_features/semantic_tokens.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,25 @@ test "semantic tokens - var decl" {
});
}

test "semantic tokens - var decl destructure" {
try testSemanticTokens(
\\const foo = {
\\ var alpha, var beta = .{ 1, 2 };
\\};
, &.{
.{ "const", .keyword, .{} },
.{ "foo", .variable, .{ .declaration = true } },
.{ "=", .operator, .{} },
.{ "var", .keyword, .{} },
.{ "alpha", .variable, .{ .declaration = true } },
.{ "var", .keyword, .{} },
.{ "beta", .variable, .{ .declaration = true } },
.{ "=", .operator, .{} },
.{ "1", .number, .{} },
.{ "2", .number, .{} },
});
}

test "semantic tokens - local var decl" {
try testSemanticTokens(
\\const alpha = {
Expand Down

0 comments on commit f53d9bb

Please sign in to comment.