std/zig/ast: fix Tree.lastToken() for blocks
The fact that blocks may end in a semicolon but this semicolon is not counted by recursive lastToken() evaluation on the sub expression causes off-by-one errors for lastToken() on blocks currently. To fix this, introduce BlockSemicolon and BlockTwoSemicolon following the pattern used for trailing commas in e.g. builtin function arguments.
This commit is contained in:
committed by
Andrew Kelley
parent
0e38362d24
commit
57cec38e61
@@ -357,7 +357,9 @@ pub const Tree = struct {
|
||||
},
|
||||
|
||||
.Block,
|
||||
.BlockSemicolon,
|
||||
.BlockTwo,
|
||||
.BlockTwoSemicolon,
|
||||
=> {
|
||||
// Look for a label.
|
||||
const lbrace = main_tokens[n];
|
||||
@@ -552,18 +554,17 @@ pub const Tree = struct {
|
||||
.TaggedUnion,
|
||||
.BuiltinCall,
|
||||
=> {
|
||||
assert(datas[n].rhs - datas[n].lhs > 0);
|
||||
end_offset += 1; // for the rbrace
|
||||
if (datas[n].rhs - datas[n].lhs == 0) {
|
||||
return main_tokens[n] + end_offset;
|
||||
}
|
||||
n = tree.extra_data[datas[n].rhs - 1]; // last statement
|
||||
},
|
||||
.BlockSemicolon,
|
||||
.ContainerDeclComma,
|
||||
.TaggedUnionComma,
|
||||
.BuiltinCallComma,
|
||||
=> {
|
||||
assert(datas[n].rhs - datas[n].lhs > 0);
|
||||
end_offset += 2; // for the comma + rbrace/rparen
|
||||
end_offset += 2; // for the comma/semicolon + rbrace/rparen
|
||||
n = tree.extra_data[datas[n].rhs - 1]; // last member
|
||||
},
|
||||
.CallOne,
|
||||
@@ -594,11 +595,12 @@ pub const Tree = struct {
|
||||
},
|
||||
.ArrayInitDotTwoComma,
|
||||
.BuiltinCallTwoComma,
|
||||
.BlockTwoSemicolon,
|
||||
.StructInitDotTwoComma,
|
||||
.ContainerDeclTwoComma,
|
||||
.TaggedUnionTwoComma,
|
||||
=> {
|
||||
end_offset += 2; // for the comma + rbrace/rparen
|
||||
end_offset += 2; // for the comma/semicolon + rbrace/rparen
|
||||
if (datas[n].rhs != 0) {
|
||||
n = datas[n].rhs;
|
||||
} else if (datas[n].lhs != 0) {
|
||||
@@ -2137,12 +2139,16 @@ pub const Node = struct {
|
||||
Comptime,
|
||||
/// `nosuspend lhs`. rhs unused.
|
||||
Nosuspend,
|
||||
/// `{lhs; rhs;}`. rhs or lhs can be omitted.
|
||||
/// `{lhs rhs}`. rhs or lhs can be omitted.
|
||||
/// main_token points at the lbrace.
|
||||
BlockTwo,
|
||||
/// Same as BlockTwo but there is known to be a semicolon before the rbrace.
|
||||
BlockTwoSemicolon,
|
||||
/// `{}`. `sub_list[lhs..rhs]`.
|
||||
/// main_token points at the lbrace.
|
||||
Block,
|
||||
/// Same as BlockTwo but there is known to be a semicolon before the rbrace.
|
||||
BlockSemicolon,
|
||||
/// `asm(lhs)`. rhs unused.
|
||||
AsmSimple,
|
||||
/// `asm(lhs, a)`. `sub_range_list[rhs]`.
|
||||
|
||||
@@ -1984,8 +1984,9 @@ const Parser = struct {
|
||||
|
||||
const stmt_one = try p.expectStatementRecoverable();
|
||||
if (p.eatToken(.RBrace)) |_| {
|
||||
const semicolon = p.token_tags[p.tok_i - 2] == .Semicolon;
|
||||
return p.addNode(.{
|
||||
.tag = .BlockTwo,
|
||||
.tag = if (semicolon) .BlockTwoSemicolon else .BlockTwo,
|
||||
.main_token = lbrace,
|
||||
.data = .{
|
||||
.lhs = stmt_one,
|
||||
@@ -1995,8 +1996,9 @@ const Parser = struct {
|
||||
}
|
||||
const stmt_two = try p.expectStatementRecoverable();
|
||||
if (p.eatToken(.RBrace)) |_| {
|
||||
const semicolon = p.token_tags[p.tok_i - 2] == .Semicolon;
|
||||
return p.addNode(.{
|
||||
.tag = .BlockTwo,
|
||||
.tag = if (semicolon) .BlockTwoSemicolon else .BlockTwo,
|
||||
.main_token = lbrace,
|
||||
.data = .{
|
||||
.lhs = stmt_one,
|
||||
@@ -2017,9 +2019,10 @@ const Parser = struct {
|
||||
if (p.token_tags[p.tok_i] == .RBrace) break;
|
||||
}
|
||||
_ = try p.expectToken(.RBrace);
|
||||
const semicolon = p.token_tags[p.tok_i - 2] == .Semicolon;
|
||||
const statements_span = try p.listToSpan(statements.items);
|
||||
return p.addNode(.{
|
||||
.tag = .Block,
|
||||
.tag = if (semicolon) .BlockSemicolon else .Block,
|
||||
.main_token = lbrace,
|
||||
.data = .{
|
||||
.lhs = statements_span.start,
|
||||
|
||||
@@ -655,6 +655,24 @@ test "zig fmt: slices with spaces in bounds" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: block in slice expression" {
|
||||
try testCanonical(
|
||||
\\const a = b[{
|
||||
\\ _ = x;
|
||||
\\}..];
|
||||
\\const c = d[0..{
|
||||
\\ _ = x;
|
||||
\\ _ = y;
|
||||
\\}];
|
||||
\\const e = f[0..1 :{
|
||||
\\ _ = x;
|
||||
\\ _ = y;
|
||||
\\ _ = z;
|
||||
\\}];
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
//test "zig fmt: async function" {
|
||||
// try testCanonical(
|
||||
// \\pub const Server = struct {
|
||||
|
||||
@@ -202,7 +202,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
// }
|
||||
// return renderToken(ais, tree, any_type.token, space);
|
||||
//},
|
||||
.BlockTwo => {
|
||||
.BlockTwo,
|
||||
.BlockTwoSemicolon,
|
||||
=> {
|
||||
const statements = [2]ast.Node.Index{ datas[node].lhs, datas[node].rhs };
|
||||
if (datas[node].lhs == 0) {
|
||||
return renderBlock(ais, tree, main_tokens[node], statements[0..0], space);
|
||||
@@ -212,7 +214,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
return renderBlock(ais, tree, main_tokens[node], statements[0..2], space);
|
||||
}
|
||||
},
|
||||
.Block => {
|
||||
.Block,
|
||||
.BlockSemicolon,
|
||||
=> {
|
||||
const lbrace = main_tokens[node];
|
||||
const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];
|
||||
return renderBlock(ais, tree, main_tokens[node], statements, space);
|
||||
|
||||
Reference in New Issue
Block a user