From 56a65f42bf950f4ad47a7c365ec445a57f6ca0ba Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sat, 26 Nov 2022 19:22:16 +0200 Subject: [PATCH] Added tuple type support, fixed compilation with zig master branch (#786) * Added tuple type support, fixed compilation with zig master branch * Removed unneeded comment * Bumped up minimum zig version required to build zls --- build.zig | 2 +- src/ComptimeInterpreter.zig | 7 ++++++- src/Server.zig | 18 ++++++++++-------- src/analysis.zig | 35 ++++++++++++++++++++++++++++------- src/semantic_tokens.zig | 4 +++- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/build.zig b/build.zig index be88bfb..859a449 100644 --- a/build.zig +++ b/build.zig @@ -6,7 +6,7 @@ const zls_version = std.builtin.Version{ .major = 0, .minor = 11, .patch = 0 }; pub fn build(b: *std.build.Builder) !void { const current_zig = builtin.zig_version; - const min_zig = std.SemanticVersion.parse("0.10.0-dev.4458+b120c819d") catch return; // builtins changed to @min / @max + const min_zig = std.SemanticVersion.parse("0.11.0-dev.323+30eb2a175") catch return; // added tuple declaration support if (current_zig.order(min_zig).compare(.lt)) @panic(b.fmt("Your Zig version v{} does not meet the minimum build requirement of v{}", .{ current_zig, min_zig })); const target = b.standardTargetOptions(.{}); diff --git a/src/ComptimeInterpreter.zig b/src/ComptimeInterpreter.zig index 587ade5..2548793 100644 --- a/src/ComptimeInterpreter.zig +++ b/src/ComptimeInterpreter.zig @@ -285,6 +285,7 @@ pub const ValueData = union(enum) { pub const FieldDefinition = struct { node_idx: Ast.Node.Index, /// Store name so tree doesn't need to be used to access field name + /// When the field is a tuple field, `name` will be an empty slice name: []const u8, @"type": Type, default_value: ?Value, @@ -765,6 +766,7 @@ pub fn interpret( var buffer: [2]Ast.Node.Index = undefined; const members = ast.declMembers(tree, node_idx, &buffer); + var field_idx: usize = 0; for (members) |member| { const maybe_container_field: ?zig.Ast.full.ContainerField = switch (tags[member]) { .container_field => tree.containerField(member), @@ -789,7 +791,9 @@ pub fn interpret( continue; } - const name = tree.tokenSlice(field_info.ast.name_token); + const name = if (field_info.ast.tuple_like) + &[0]u8{} + else tree.tokenSlice(field_info.ast.main_token); const field = FieldDefinition{ .node_idx = member, .name = name, @@ -804,6 +808,7 @@ pub fn interpret( }; try cont_type.getTypeInfoMutable().@"struct".fields.put(interpreter.allocator, name, field); + field_idx += 1; } else { _ = try interpreter.interpret(member, container_scope, options); } diff --git a/src/Server.zig b/src/Server.zig index d39e86b..2b0652f 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -683,14 +683,16 @@ fn nodeToCompletion( .container_field_init, => { const field = ast.containerField(tree, node).?; - try list.append(allocator, .{ - .label = handle.tree.tokenSlice(field.ast.name_token), - .kind = .Field, - .documentation = doc, - .detail = analysis.getContainerFieldSignature(handle.tree, field), - .insertText = tree.tokenSlice(field.ast.name_token), - .insertTextFormat = .PlainText, - }); + if (!field.ast.tuple_like) { + try list.append(allocator, .{ + .label = handle.tree.tokenSlice(field.ast.main_token), + .kind = .Field, + .documentation = doc, + .detail = analysis.getContainerFieldSignature(handle.tree, field), + .insertText = tree.tokenSlice(field.ast.main_token), + .insertTextFormat = .PlainText, + }); + } }, .array_type, .array_type_sentinel, diff --git a/src/analysis.zig b/src/analysis.zig index 8804cba..757d602 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -226,7 +226,7 @@ pub fn getContainerFieldSignature(tree: Ast, field: Ast.full.ContainerField) []c if (field.ast.value_expr == 0 and field.ast.type_expr == 0 and field.ast.align_expr == 0) { return ""; // TODO display the container's type } - const start = offsets.tokenToIndex(tree, field.ast.name_token); + const start = offsets.tokenToIndex(tree, field.ast.main_token); const end_node = if (field.ast.value_expr != 0) field.ast.value_expr else field.ast.type_expr; const end = offsets.tokenToLoc(tree, ast.lastToken(tree, end_node)).end; return tree.source[start..end]; @@ -291,9 +291,21 @@ pub fn getDeclNameToken(tree: Ast, node: Ast.Node.Index) ?Ast.TokenIndex { }, // containers - .container_field => tree.containerField(node).ast.name_token, - .container_field_init => tree.containerFieldInit(node).ast.name_token, - .container_field_align => tree.containerFieldAlign(node).ast.name_token, + .container_field => blk: { + const field = tree.containerField(node); + if (field.ast.tuple_like) break :blk null; + break :blk field.ast.main_token; + }, + .container_field_init => blk: { + const field = tree.containerFieldInit(node); + if (field.ast.tuple_like) break :blk null; + break :blk field.ast.main_token; + }, + .container_field_align => blk: { + const field = tree.containerFieldAlign(node); + if (field.ast.tuple_like) break :blk null; + break :blk field.ast.main_token; + }, .identifier => main_token, .error_value => main_token + 2, // 'error'. @@ -1399,9 +1411,18 @@ pub fn nodeToString(tree: Ast, node: Ast.Node.Index) ?[]const u8 { const main_token = tree.nodes.items(.main_token)[node]; var buf: [1]Ast.Node.Index = undefined; switch (tree.nodes.items(.tag)[node]) { - .container_field => return tree.tokenSlice(tree.containerField(node).ast.name_token), - .container_field_init => return tree.tokenSlice(tree.containerFieldInit(node).ast.name_token), - .container_field_align => return tree.tokenSlice(tree.containerFieldAlign(node).ast.name_token), + .container_field => { + const field = tree.containerField(node).ast; + return if (field.tuple_like) null else tree.tokenSlice(field.main_token); + }, + .container_field_init => { + const field = tree.containerFieldInit(node).ast; + return if (field.tuple_like) null else tree.tokenSlice(field.main_token); + }, + .container_field_align => { + const field = tree.containerFieldAlign(node).ast; + return if (field.tuple_like) null else tree.tokenSlice(field.main_token); + }, .error_value => return tree.tokenSlice(data[node].rhs), .identifier => return tree.tokenSlice(main_token), .fn_proto, diff --git a/src/semantic_tokens.zig b/src/semantic_tokens.zig index b201d4b..2204e6f 100644 --- a/src/semantic_tokens.zig +++ b/src/semantic_tokens.zig @@ -999,7 +999,9 @@ fn writeContainerField(builder: *Builder, node: Ast.Node.Index, field_token_type try writeDocComments(builder, tree, docs); try writeToken(builder, container_field.comptime_token, .keyword); - if (field_token_type) |tok_type| try writeToken(builder, container_field.ast.name_token, tok_type); + if (!container_field.ast.tuple_like) { + if (field_token_type) |tok_type| try writeToken(builder, container_field.ast.main_token, tok_type); + } if (container_field.ast.type_expr != 0) { try callWriteNodeTokens(allocator, .{ builder, container_field.ast.type_expr });