zig fmt: implement Tree.lastToken() for array init

This commit is contained in:
Isaac Freund 2021-02-10 18:17:50 +01:00 committed by Andrew Kelley
parent 3110a73486
commit 928f6f48a6
4 changed files with 117 additions and 48 deletions

View File

@ -255,6 +255,7 @@ pub const Tree = struct {
=> return main_tokens[n] - end_offset,
.ArrayInitDot,
.ArrayInitDotComma,
.ArrayInitDotTwo,
.ArrayInitDotTwoComma,
.StructInitDot,
@ -311,7 +312,9 @@ pub const Tree = struct {
.Deref,
.ArrayAccess,
.ArrayInitOne,
.ArrayInitOneComma,
.ArrayInit,
.ArrayInitComma,
.StructInitOne,
.StructInit,
.CallOne,
@ -604,6 +607,13 @@ pub const Tree = struct {
const extra = tree.extraData(datas[n].rhs, Node.Asm);
return extra.rparen + end_offset;
},
.ArrayInit => {
const elements = tree.extraData(datas[n].rhs, Node.SubRange);
assert(elements.end - elements.start > 0);
end_offset += 1; // for the rbrace
n = tree.extra_data[elements.end - 1]; // last element
},
.ArrayInitComma,
.ContainerDeclArgComma,
.SwitchComma,
=> {
@ -612,6 +622,7 @@ pub const Tree = struct {
end_offset += 2; // for the comma + rbrace
n = tree.extra_data[members.end - 1]; // last parameter
},
.ArrayInitDot,
.Block,
.ContainerDecl,
.TaggedUnion,
@ -621,6 +632,7 @@ pub const Tree = struct {
end_offset += 1; // for the rbrace
n = tree.extra_data[datas[n].rhs - 1]; // last statement
},
.ArrayInitDotComma,
.BlockSemicolon,
.ContainerDeclComma,
.TaggedUnionComma,
@ -772,7 +784,16 @@ pub const Tree = struct {
}
},
.SliceOpen, .CallOneComma, .AsyncCallOneComma => {
.ArrayInitOne => {
end_offset += 1; // rbrace
n = datas[n].rhs;
assert(n != 0);
},
.SliceOpen,
.CallOneComma,
.AsyncCallOneComma,
.ArrayInitOneComma,
=> {
end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
n = datas[n].rhs;
assert(n != 0);
@ -912,9 +933,6 @@ pub const Tree = struct {
// require recursion due to the optional comma followed by rbrace.
// TODO follow the pattern set by StructInitDotTwoComma which will allow
// lastToken to work for all of these.
.ArrayInit => unreachable, // TODO
.ArrayInitOne => unreachable, // TODO
.ArrayInitDot => unreachable, // TODO
.StructInit => unreachable, // TODO
.StructInitOne => unreachable, // TODO
.StructInitDot => unreachable, // TODO
@ -1151,7 +1169,8 @@ pub const Tree = struct {
}
pub fn arrayInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {
assert(tree.nodes.items(.tag)[node] == .ArrayInitOne);
assert(tree.nodes.items(.tag)[node] == .ArrayInitOne or
tree.nodes.items(.tag)[node] == .ArrayInitOneComma);
const data = tree.nodes.items(.data)[node];
buffer[0] = data.rhs;
const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
@ -1185,7 +1204,8 @@ pub const Tree = struct {
}
pub fn arrayInitDot(tree: Tree, node: Node.Index) full.ArrayInit {
assert(tree.nodes.items(.tag)[node] == .ArrayInitDot);
assert(tree.nodes.items(.tag)[node] == .ArrayInitDot or
tree.nodes.items(.tag)[node] == .ArrayInitDotComma);
const data = tree.nodes.items(.data)[node];
return .{
.ast = .{
@ -1197,7 +1217,8 @@ pub const Tree = struct {
}
pub fn arrayInit(tree: Tree, node: Node.Index) full.ArrayInit {
assert(tree.nodes.items(.tag)[node] == .ArrayInit);
assert(tree.nodes.items(.tag)[node] == .ArrayInit or
tree.nodes.items(.tag)[node] == .ArrayInitComma);
const data = tree.nodes.items(.data)[node];
const elem_range = tree.extraData(data.rhs, Node.SubRange);
return .{
@ -2436,6 +2457,8 @@ pub const Node = struct {
ArrayAccess,
/// `lhs{rhs}`. rhs can be omitted.
ArrayInitOne,
/// `lhs{rhs,}`. rhs can *not* be omitted
ArrayInitOneComma,
/// `.{lhs, rhs}`. lhs and rhs can be omitted.
ArrayInitDotTwo,
/// Same as `ArrayInitDotTwo` except there is known to be a trailing comma
@ -2443,8 +2466,14 @@ pub const Node = struct {
ArrayInitDotTwoComma,
/// `.{a, b}`. `sub_list[lhs..rhs]`.
ArrayInitDot,
/// Same as `ArrayInitDot` except there is known to be a trailing comma
/// before the final rbrace.
ArrayInitDotComma,
/// `lhs{a, b}`. `sub_range_list[rhs]`. lhs can be omitted which means `.{a, b}`.
ArrayInit,
/// Same as `ArrayInit` except there is known to be a trailing comma
/// before the final rbrace.
ArrayInitComma,
/// `lhs{.a = rhs}`. rhs can be omitted making it empty.
/// main_token is the lbrace.
StructInitOne,

View File

@ -2205,9 +2205,10 @@ const Parser = struct {
}
const elem_init = try p.expectExpr();
const comma_one = p.eatToken(.Comma);
if (p.eatToken(.RBrace)) |_| {
return p.addNode(.{
.tag = .ArrayInitOne,
.tag = if (comma_one != null) .ArrayInitOneComma else .ArrayInitOne,
.main_token = lbrace,
.data = .{
.lhs = lhs,
@ -2215,21 +2216,30 @@ const Parser = struct {
},
});
}
if (comma_one == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
});
}
var init_list = std.ArrayList(Node.Index).init(p.gpa);
defer init_list.deinit();
try init_list.append(elem_init);
while (p.eatToken(.Comma)) |_| {
const next = try p.parseExpr();
if (next == 0) break;
var trailing_comma = true;
var next = try p.parseExpr();
while (next != 0) : (next = try p.parseExpr()) {
try init_list.append(next);
if (p.eatToken(.Comma) == null) {
trailing_comma = false;
break;
}
}
_ = try p.expectToken(.RBrace);
const span = try p.listToSpan(init_list.items);
return p.addNode(.{
.tag = .ArrayInit,
.tag = if (trailing_comma) .ArrayInitComma else .ArrayInit,
.main_token = lbrace,
.data = .{
.lhs = lhs,
@ -2805,7 +2815,7 @@ const Parser = struct {
const comma_two = p.eatToken(.Comma);
if (p.eatToken(.RBrace)) |_| {
return p.addNode(.{
.tag = if (comma_one != null) .ArrayInitDotTwoComma else .ArrayInitDotTwo,
.tag = if (comma_two != null) .ArrayInitDotTwoComma else .ArrayInitDotTwo,
.main_token = lbrace,
.data = .{
.lhs = elem_init_one,
@ -2855,7 +2865,7 @@ const Parser = struct {
}
const span = try p.listToSpan(init_list.items);
return p.addNode(.{
.tag = .ArrayInitDot,
.tag = if (p.token_tags[p.tok_i - 2] == .Comma) .ArrayInitDotComma else .ArrayInitDot,
.main_token = lbrace,
.data = .{
.lhs = span.start,

View File

@ -568,109 +568,135 @@ test "zig fmt: struct literal 3 element comma" {
test "zig fmt: anon list literal 1 element" {
try testCanonical(
\\const x = .{a};
\\test {
\\ const x = .{a};
\\}
\\
);
}
test "zig fmt: anon list literal 1 element comma" {
try testCanonical(
\\const x = .{
\\ a,
\\};
\\test {
\\ const x = .{
\\ a,
\\ };
\\}
\\
);
}
test "zig fmt: anon list literal 2 element" {
try testCanonical(
\\const x = .{ a, b };
\\test {
\\ const x = .{ a, b };
\\}
\\
);
}
test "zig fmt: anon list literal 2 element comma" {
try testCanonical(
\\const x = .{
\\ a,
\\ b,
\\};
\\test {
\\ const x = .{
\\ a,
\\ b,
\\ };
\\}
\\
);
}
test "zig fmt: anon list literal 3 element" {
try testCanonical(
\\const x = .{ a, b, c };
\\test {
\\ const x = .{ a, b, c };
\\}
\\
);
}
test "zig fmt: anon list literal 3 element comma" {
try testCanonical(
\\const x = .{
\\ a,
\\ b,
\\ c,
\\};
\\test {
\\ const x = .{
\\ a,
\\ b,
\\ c,
\\ };
\\}
\\
);
}
test "zig fmt: array literal 1 element" {
try testCanonical(
\\const x = [_]u32{a};
\\test {
\\ const x = [_]u32{a};
\\}
\\
);
}
test "zig fmt: array literal 1 element comma" {
try testCanonical(
\\const x = [1]u32{
\\ a,
\\};
\\test {
\\ const x = [1]u32{
\\ a,
\\ };
\\}
\\
);
}
test "zig fmt: array literal 2 element" {
try testCanonical(
\\const x = [_]u32{ a, b };
\\test {
\\ const x = [_]u32{ a, b };
\\}
\\
);
}
test "zig fmt: array literal 2 element comma" {
try testCanonical(
\\const x = [2]u32{
\\ a,
\\ b,
\\};
\\test {
\\ const x = [2]u32{
\\ a,
\\ b,
\\ };
\\}
\\
);
}
test "zig fmt: array literal 3 element" {
try testCanonical(
\\const x = [_]u32{ a, b, c };
\\test {
\\ const x = [_]u32{ a, b, c };
\\}
\\
);
}
test "zig fmt: array literal 3 element comma" {
try testCanonical(
\\const x = [3]u32{
\\ a,
\\ b,
\\ c,
\\};
\\test {
\\ const x = [3]u32{
\\ a,
\\ b,
\\ c,
\\ };
\\}
\\
);
}
test "zig fmt: sentinel array literal 1 element" {
try testCanonical(
\\const x = [_:9000]u32{a};
\\test {
\\ const x = [_:9000]u32{a};
\\}
\\
);
}

View File

@ -390,7 +390,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
.PtrType => return renderPtrType(ais, tree, tree.ptrType(node), space),
.PtrTypeBitRange => return renderPtrType(ais, tree, tree.ptrTypeBitRange(node), space),
.ArrayInitOne => {
.ArrayInitOne, .ArrayInitOneComma => {
var elements: [1]ast.Node.Index = undefined;
return renderArrayInit(ais, tree, tree.arrayInitOne(&elements, node), space);
},
@ -398,8 +398,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
var elements: [2]ast.Node.Index = undefined;
return renderArrayInit(ais, tree, tree.arrayInitDotTwo(&elements, node), space);
},
.ArrayInitDot => return renderArrayInit(ais, tree, tree.arrayInitDot(node), space),
.ArrayInit => return renderArrayInit(ais, tree, tree.arrayInit(node), space),
.ArrayInitDot,
.ArrayInitDotComma,
=> return renderArrayInit(ais, tree, tree.arrayInitDot(node), space),
.ArrayInit,
.ArrayInitComma,
=> return renderArrayInit(ais, tree, tree.arrayInit(node), space),
.StructInitOne => {
var fields: [1]ast.Node.Index = undefined;