zig fmt: implement switches
This commit is contained in:
committed by
Andrew Kelley
parent
837cd748a8
commit
d869133a9f
@@ -213,6 +213,7 @@ pub const Tree = struct {
|
||||
.Await,
|
||||
.OptionalType,
|
||||
.Switch,
|
||||
.SwitchComma,
|
||||
.IfSimple,
|
||||
.If,
|
||||
.Suspend,
|
||||
@@ -313,7 +314,6 @@ pub const Tree = struct {
|
||||
.StructInit,
|
||||
.CallOne,
|
||||
.Call,
|
||||
.SwitchCaseOne,
|
||||
.SwitchRange,
|
||||
.FnDecl,
|
||||
.ErrorUnion,
|
||||
@@ -406,7 +406,19 @@ pub const Tree = struct {
|
||||
};
|
||||
},
|
||||
|
||||
.SwitchCaseMulti => unreachable, // TODO
|
||||
.SwitchCaseOne => {
|
||||
if (datas[n].lhs == 0) {
|
||||
return main_tokens[n] - 1; // else token
|
||||
} else {
|
||||
n = datas[n].lhs;
|
||||
}
|
||||
},
|
||||
.SwitchCase => {
|
||||
const extra = tree.extraData(datas[n].lhs, Node.SubRange);
|
||||
assert(extra.end - extra.start > 0);
|
||||
n = extra.start;
|
||||
},
|
||||
|
||||
.WhileSimple => unreachable, // TODO
|
||||
.WhileCont => unreachable, // TODO
|
||||
.While => unreachable, // TODO
|
||||
@@ -494,6 +506,8 @@ pub const Tree = struct {
|
||||
.PtrTypeSentinel,
|
||||
.PtrType,
|
||||
.PtrTypeBitRange,
|
||||
.SwitchCaseOne,
|
||||
.SwitchCase,
|
||||
=> n = datas[n].rhs,
|
||||
|
||||
.FieldAccess,
|
||||
@@ -532,6 +546,16 @@ pub const Tree = struct {
|
||||
}
|
||||
n = tree.extra_data[params.end - 1]; // last parameter
|
||||
},
|
||||
.Switch => {
|
||||
const cases = tree.extraData(datas[n].rhs, Node.SubRange);
|
||||
if (cases.end - cases.start == 0) {
|
||||
end_offset += 3; // rparen, lbrace, rbrace
|
||||
n = datas[n].lhs; // condition expression
|
||||
} else {
|
||||
end_offset += 1; // for the rbrace
|
||||
n = tree.extra_data[cases.end - 1]; // last case
|
||||
}
|
||||
},
|
||||
.ContainerDeclArg => {
|
||||
const members = tree.extraData(datas[n].rhs, Node.SubRange);
|
||||
if (members.end - members.start == 0) {
|
||||
@@ -542,7 +566,9 @@ pub const Tree = struct {
|
||||
n = tree.extra_data[members.end - 1]; // last parameter
|
||||
}
|
||||
},
|
||||
.ContainerDeclArgComma => {
|
||||
.ContainerDeclArgComma,
|
||||
.SwitchComma,
|
||||
=> {
|
||||
const members = tree.extraData(datas[n].rhs, Node.SubRange);
|
||||
assert(members.end - members.start > 0);
|
||||
end_offset += 2; // for the comma + rbrace
|
||||
@@ -737,16 +763,13 @@ pub const Tree = struct {
|
||||
|
||||
.TaggedUnionEnumTag => unreachable, // TODO
|
||||
.TaggedUnionEnumTagComma => unreachable, // TODO
|
||||
.Switch => unreachable, // TODO
|
||||
.If => unreachable, // TODO
|
||||
.Continue => unreachable, // TODO
|
||||
.AsmSimple => unreachable, // TODO
|
||||
.Asm => unreachable, // TODO
|
||||
.SwitchCaseOne => unreachable, // TODO
|
||||
.SwitchRange => unreachable, // TODO
|
||||
.ArrayType => unreachable, // TODO
|
||||
.ArrayTypeSentinel => unreachable, // TODO
|
||||
.SwitchCaseMulti => unreachable, // TODO
|
||||
.WhileCont => unreachable, // TODO
|
||||
.While => unreachable, // TODO
|
||||
.ForSimple => unreachable, // TODO
|
||||
@@ -1202,7 +1225,8 @@ pub const Tree = struct {
|
||||
}
|
||||
|
||||
pub fn containerDeclArg(tree: Tree, node: Node.Index) Full.ContainerDecl {
|
||||
assert(tree.nodes.items(.tag)[node] == .ContainerDeclArg);
|
||||
assert(tree.nodes.items(.tag)[node] == .ContainerDeclArg or
|
||||
tree.nodes.items(.tag)[node] == .ContainerDeclArgComma);
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
const members_range = tree.extraData(data.rhs, Node.SubRange);
|
||||
return tree.fullContainerDecl(.{
|
||||
@@ -1214,7 +1238,8 @@ pub const Tree = struct {
|
||||
}
|
||||
|
||||
pub fn taggedUnionTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.ContainerDecl {
|
||||
assert(tree.nodes.items(.tag)[node] == .TaggedUnionTwo);
|
||||
assert(tree.nodes.items(.tag)[node] == .TaggedUnionTwo or
|
||||
tree.nodes.items(.tag)[node] == .TaggedUnionTwoComma);
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
buffer.* = .{ data.lhs, data.rhs };
|
||||
const members = if (data.rhs != 0)
|
||||
@@ -1233,7 +1258,8 @@ pub const Tree = struct {
|
||||
}
|
||||
|
||||
pub fn taggedUnion(tree: Tree, node: Node.Index) Full.ContainerDecl {
|
||||
assert(tree.nodes.items(.tag)[node] == .TaggedUnion);
|
||||
assert(tree.nodes.items(.tag)[node] == .TaggedUnion or
|
||||
tree.nodes.items(.tag)[node] == .TaggedUnionComma);
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
const main_token = tree.nodes.items(.main_token)[node];
|
||||
return tree.fullContainerDecl(.{
|
||||
@@ -1245,7 +1271,8 @@ pub const Tree = struct {
|
||||
}
|
||||
|
||||
pub fn taggedUnionEnumTag(tree: Tree, node: Node.Index) Full.ContainerDecl {
|
||||
assert(tree.nodes.items(.tag)[node] == .TaggedUnionEnumTag);
|
||||
assert(tree.nodes.items(.tag)[node] == .TaggedUnionEnumTag or
|
||||
tree.nodes.items(.tag)[node] == .TaggedUnionEnumTagComma);
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
const members_range = tree.extraData(data.rhs, Node.SubRange);
|
||||
const main_token = tree.nodes.items(.main_token)[node];
|
||||
@@ -1257,6 +1284,25 @@ pub const Tree = struct {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn switchCaseOne(tree: Tree, node: Node.Index) Full.SwitchCase {
|
||||
const data = &tree.nodes.items(.data)[node];
|
||||
return tree.fullSwitchCase(.{
|
||||
.values = if (data.lhs == 0) &.{} else @ptrCast([*]Node.Index, &data.lhs)[0..1],
|
||||
.arrow_token = tree.nodes.items(.main_token)[node],
|
||||
.target_expr = data.rhs,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn switchCase(tree: Tree, node: Node.Index) Full.SwitchCase {
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
const extra = tree.extraData(data.lhs, Node.SubRange);
|
||||
return tree.fullSwitchCase(.{
|
||||
.values = tree.extra_data[extra.start..extra.end],
|
||||
.arrow_token = tree.nodes.items(.main_token)[node],
|
||||
.target_expr = data.rhs,
|
||||
});
|
||||
}
|
||||
|
||||
fn fullVarDecl(tree: Tree, info: Full.VarDecl.Ast) Full.VarDecl {
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
var result: Full.VarDecl = .{
|
||||
@@ -1407,6 +1453,18 @@ pub const Tree = struct {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn fullSwitchCase(tree: Tree, info: Full.SwitchCase.Ast) Full.SwitchCase {
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
var result: Full.SwitchCase = .{
|
||||
.ast = info,
|
||||
.payload_token = null,
|
||||
};
|
||||
if (token_tags[info.arrow_token + 1] == .Pipe) {
|
||||
result.payload_token = info.arrow_token + 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// Fully assembled AST node information.
|
||||
@@ -1552,6 +1610,20 @@ pub const Full = struct {
|
||||
arg: Node.Index,
|
||||
};
|
||||
};
|
||||
|
||||
pub const SwitchCase = struct {
|
||||
/// Points to the first token after the `|`. Will either be an identifier or
|
||||
/// a `*` (with an identifier immediately after it).
|
||||
payload_token: ?TokenIndex,
|
||||
ast: Ast,
|
||||
|
||||
pub const Ast = struct {
|
||||
/// If empty, this is an else case
|
||||
values: []const Node.Index,
|
||||
arrow_token: TokenIndex,
|
||||
target_expr: Node.Index,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pub const Error = union(enum) {
|
||||
@@ -1996,13 +2068,16 @@ pub const Node = struct {
|
||||
/// `lhs(a, b, c)`. `sub_range_list[rhs]`.
|
||||
/// main_token is the `(`.
|
||||
Call,
|
||||
/// `switch(lhs) {}`. `sub_range_list[rhs]`.
|
||||
/// `switch(lhs) {}`. `SubRange[rhs]`.
|
||||
Switch,
|
||||
/// Same as Switch except there is known to be a trailing comma
|
||||
/// before the final rbrace
|
||||
SwitchComma,
|
||||
/// `lhs => rhs`. If lhs is omitted it means `else`.
|
||||
/// main_token is the `=>`
|
||||
SwitchCaseOne,
|
||||
/// `a, b, c => rhs`. `sub_range_list[lhs]`.
|
||||
SwitchCaseMulti,
|
||||
/// `a, b, c => rhs`. `SubRange[lhs]`.
|
||||
SwitchCase,
|
||||
/// `lhs...rhs`.
|
||||
SwitchRange,
|
||||
/// `while (lhs) rhs`.
|
||||
|
||||
@@ -2887,10 +2887,11 @@ const Parser = struct {
|
||||
_ = try p.expectToken(.RParen);
|
||||
_ = try p.expectToken(.LBrace);
|
||||
const cases = try p.parseSwitchProngList();
|
||||
const trailing_comma = p.token_tags[p.tok_i - 1] == .Comma;
|
||||
_ = try p.expectToken(.RBrace);
|
||||
|
||||
return p.addNode(.{
|
||||
.tag = .Switch,
|
||||
.tag = if (trailing_comma) .SwitchComma else .Switch,
|
||||
.main_token = switch_token,
|
||||
.data = .{
|
||||
.lhs = expr_node,
|
||||
@@ -3208,7 +3209,7 @@ const Parser = struct {
|
||||
const arrow_token = try p.expectToken(.EqualAngleBracketRight);
|
||||
_ = try p.parsePtrPayload();
|
||||
return p.addNode(.{
|
||||
.tag = .SwitchCaseMulti,
|
||||
.tag = .SwitchCase,
|
||||
.main_token = arrow_token,
|
||||
.data = .{
|
||||
.lhs = try p.addExtra(Node.SubRange{
|
||||
|
||||
@@ -1671,32 +1671,32 @@ test "zig fmt: block in slice expression" {
|
||||
// \\
|
||||
// );
|
||||
//}
|
||||
//
|
||||
//test "zig fmt: switch cases trailing comma" {
|
||||
// try testTransform(
|
||||
// \\fn switch_cases(x: i32) void {
|
||||
// \\ switch (x) {
|
||||
// \\ 1,2,3 => {},
|
||||
// \\ 4,5, => {},
|
||||
// \\ 6... 8, => {},
|
||||
// \\ else => {},
|
||||
// \\ }
|
||||
// \\}
|
||||
// ,
|
||||
// \\fn switch_cases(x: i32) void {
|
||||
// \\ switch (x) {
|
||||
// \\ 1, 2, 3 => {},
|
||||
// \\ 4,
|
||||
// \\ 5,
|
||||
// \\ => {},
|
||||
// \\ 6...8 => {},
|
||||
// \\ else => {},
|
||||
// \\ }
|
||||
// \\}
|
||||
// \\
|
||||
// );
|
||||
//}
|
||||
//
|
||||
|
||||
test "zig fmt: switch cases trailing comma" {
|
||||
try testTransform(
|
||||
\\test "switch cases trailing comma"{
|
||||
\\ switch (x) {
|
||||
\\ 1,2,3 => {},
|
||||
\\ 4,5, => {},
|
||||
\\ 6... 8, => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
\\test "switch cases trailing comma" {
|
||||
\\ switch (x) {
|
||||
\\ 1, 2, 3 => {},
|
||||
\\ 4,
|
||||
\\ 5,
|
||||
\\ => {},
|
||||
\\ 6...8 => {},
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
//test "zig fmt: slice align" {
|
||||
// try testCanonical(
|
||||
// \\const A = struct {
|
||||
@@ -1996,16 +1996,16 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {
|
||||
// \\
|
||||
// );
|
||||
//}
|
||||
//
|
||||
//test "zig fmt: switch with empty body" {
|
||||
// try testCanonical(
|
||||
// \\test "" {
|
||||
// \\ foo() catch |err| switch (err) {};
|
||||
// \\}
|
||||
// \\
|
||||
// );
|
||||
//}
|
||||
//
|
||||
|
||||
test "zig fmt: switch with empty body" {
|
||||
try testCanonical(
|
||||
\\test "" {
|
||||
\\ foo() catch |err| switch (err) {};
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
//test "zig fmt: line comments in struct initializer" {
|
||||
// try testCanonical(
|
||||
// \\fn foo() void {
|
||||
@@ -2725,42 +2725,42 @@ test "zig fmt: blocks" {
|
||||
);
|
||||
}
|
||||
|
||||
//test "zig fmt: switch" {
|
||||
// try testCanonical(
|
||||
// \\test "switch" {
|
||||
// \\ switch (0) {
|
||||
// \\ 0 => {},
|
||||
// \\ 1 => unreachable,
|
||||
// \\ 2, 3 => {},
|
||||
// \\ 4...7 => {},
|
||||
// \\ 1 + 4 * 3 + 22 => {},
|
||||
// \\ else => {
|
||||
// \\ const a = 1;
|
||||
// \\ const b = a;
|
||||
// \\ },
|
||||
// \\ }
|
||||
// \\
|
||||
// \\ const res = switch (0) {
|
||||
// \\ 0 => 0,
|
||||
// \\ 1 => 2,
|
||||
// \\ 1 => a = 4,
|
||||
// \\ else => 4,
|
||||
// \\ };
|
||||
// \\
|
||||
// \\ const Union = union(enum) {
|
||||
// \\ Int: i64,
|
||||
// \\ Float: f64,
|
||||
// \\ };
|
||||
// \\
|
||||
// \\ switch (u) {
|
||||
// \\ Union.Int => |int| {},
|
||||
// \\ Union.Float => |*float| unreachable,
|
||||
// \\ }
|
||||
// \\}
|
||||
// \\
|
||||
// );
|
||||
//}
|
||||
//
|
||||
test "zig fmt: switch" {
|
||||
try testCanonical(
|
||||
\\test "switch" {
|
||||
\\ switch (0) {
|
||||
\\ 0 => {},
|
||||
\\ 1 => unreachable,
|
||||
\\ 2, 3 => {},
|
||||
\\ 4...7 => {},
|
||||
\\ 1 + 4 * 3 + 22 => {},
|
||||
\\ else => {
|
||||
\\ const a = 1;
|
||||
\\ const b = a;
|
||||
\\ },
|
||||
\\ }
|
||||
\\
|
||||
\\ const res = switch (0) {
|
||||
\\ 0 => 0,
|
||||
\\ 1 => 2,
|
||||
\\ 1 => a = 4,
|
||||
\\ else => 4,
|
||||
\\ };
|
||||
\\
|
||||
\\ const Union = union(enum) {
|
||||
\\ Int: i64,
|
||||
\\ Float: f64,
|
||||
\\ };
|
||||
\\
|
||||
\\ switch (u) {
|
||||
\\ Union.Int => |int| {},
|
||||
\\ Union.Float => |*float| unreachable,
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
//test "zig fmt: while" {
|
||||
// try testCanonical(
|
||||
// \\test "while" {
|
||||
|
||||
@@ -207,19 +207,18 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
=> {
|
||||
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);
|
||||
return renderBlock(ais, tree, node, statements[0..0], space);
|
||||
} else if (datas[node].rhs == 0) {
|
||||
return renderBlock(ais, tree, main_tokens[node], statements[0..1], space);
|
||||
return renderBlock(ais, tree, node, statements[0..1], space);
|
||||
} else {
|
||||
return renderBlock(ais, tree, main_tokens[node], statements[0..2], space);
|
||||
return renderBlock(ais, tree, node, statements[0..2], space);
|
||||
}
|
||||
},
|
||||
.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);
|
||||
return renderBlock(ais, tree, node, statements, space);
|
||||
},
|
||||
|
||||
.ErrDefer => {
|
||||
@@ -615,81 +614,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
try renderToken(ais, tree, rbrace, space);
|
||||
}
|
||||
},
|
||||
//.ErrorSetDecl => {
|
||||
// const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
|
||||
|
||||
// const lbrace = tree.nextToken(err_set_decl.error_token);
|
||||
|
||||
// if (err_set_decl.decls_len == 0) {
|
||||
// try renderToken(ais, tree, err_set_decl.error_token, Space.None);
|
||||
// try renderToken(ais, tree, lbrace, Space.None);
|
||||
// return renderToken(ais, tree, err_set_decl.rbrace_token, space);
|
||||
// }
|
||||
|
||||
// if (err_set_decl.decls_len == 1) blk: {
|
||||
// const node = err_set_decl.decls()[0];
|
||||
|
||||
// // if there are any doc comments or same line comments
|
||||
// // don't try to put it all on one line
|
||||
// if (node.cast(ast.Node.ErrorTag)) |tag| {
|
||||
// if (tag.doc_comments != null) break :blk;
|
||||
// } else {
|
||||
// break :blk;
|
||||
// }
|
||||
|
||||
// try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
|
||||
// try renderToken(ais, tree, lbrace, Space.None); // lbrace
|
||||
// try renderExpression(ais, tree, node, Space.None);
|
||||
// return renderToken(ais, tree, err_set_decl.rbrace_token, space); // rbrace
|
||||
// }
|
||||
|
||||
// try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
|
||||
|
||||
// const src_has_trailing_comma = blk: {
|
||||
// const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
|
||||
// break :blk tree.token_tags[maybe_comma] == .Comma;
|
||||
// };
|
||||
|
||||
// if (src_has_trailing_comma) {
|
||||
// {
|
||||
// ais.pushIndent();
|
||||
// defer ais.popIndent();
|
||||
|
||||
// try renderToken(ais, tree, lbrace, Space.Newline); // lbrace
|
||||
// const decls = err_set_decl.decls();
|
||||
// for (decls) |node, i| {
|
||||
// if (i + 1 < decls.len) {
|
||||
// try renderExpression(ais, tree, node, Space.None);
|
||||
// try renderToken(ais, tree, tree.nextToken(node.lastToken()), Space.Newline); // ,
|
||||
|
||||
// try renderExtraNewline(ais, tree, decls[i + 1]);
|
||||
// } else {
|
||||
// try renderExpression(ais, tree, node, Space.Comma);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return renderToken(ais, tree, err_set_decl.rbrace_token, space); // rbrace
|
||||
// } else {
|
||||
// try renderToken(ais, tree, lbrace, Space.Space); // lbrace
|
||||
|
||||
// const decls = err_set_decl.decls();
|
||||
// for (decls) |node, i| {
|
||||
// if (i + 1 < decls.len) {
|
||||
// try renderExpression(ais, tree, node, Space.None);
|
||||
|
||||
// const comma_token = tree.nextToken(node.lastToken());
|
||||
// assert(tree.token_tags[comma_token] == .Comma);
|
||||
// try renderToken(ais, tree, comma_token, Space.Space); // ,
|
||||
// try renderExtraNewline(ais, tree, decls[i + 1]);
|
||||
// } else {
|
||||
// try renderExpression(ais, tree, node, Space.Space);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return renderToken(ais, tree, err_set_decl.rbrace_token, space); // rbrace
|
||||
// }
|
||||
//},
|
||||
|
||||
.BuiltinCallTwo, .BuiltinCallTwoComma => {
|
||||
if (datas[node].lhs == 0) {
|
||||
@@ -732,92 +656,38 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
// }
|
||||
//},
|
||||
|
||||
.Switch => unreachable, // TODO
|
||||
//.Switch => {
|
||||
// const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
|
||||
.Switch,
|
||||
.SwitchComma,
|
||||
=> {
|
||||
const switch_token = main_tokens[node];
|
||||
const condition = datas[node].lhs;
|
||||
const extra = tree.extraData(datas[node].rhs, ast.Node.SubRange);
|
||||
const cases = tree.extra_data[extra.start..extra.end];
|
||||
const rparen = tree.lastToken(condition) + 1;
|
||||
|
||||
// try renderToken(ais, tree, switch_node.switch_token, Space.Space); // switch
|
||||
// try renderToken(ais, tree, tree.nextToken(switch_node.switch_token), Space.None); // (
|
||||
try renderToken(ais, tree, switch_token, .Space); // switch keyword
|
||||
try renderToken(ais, tree, switch_token + 1, .None); // lparen
|
||||
try renderExpression(ais, tree, condition, .None); // condtion expression
|
||||
try renderToken(ais, tree, rparen, .Space); // rparen
|
||||
|
||||
// const rparen = tree.nextToken(switch_node.expr.lastToken());
|
||||
// const lbrace = tree.nextToken(rparen);
|
||||
if (cases.len == 0) {
|
||||
try renderToken(ais, tree, rparen + 1, .None); // lbrace
|
||||
try renderToken(ais, tree, rparen + 2, space); // rbrace
|
||||
} else {
|
||||
try renderToken(ais, tree, rparen + 1, .Newline); // lbrace
|
||||
ais.pushIndent();
|
||||
try renderExpression(ais, tree, cases[0], .Comma);
|
||||
for (cases[1..]) |case| {
|
||||
try renderExtraNewline(ais, tree, case);
|
||||
try renderExpression(ais, tree, case, .Comma);
|
||||
}
|
||||
ais.popIndent();
|
||||
try renderToken(ais, tree, tree.lastToken(node), space); // rbrace
|
||||
}
|
||||
},
|
||||
|
||||
// if (switch_node.cases_len == 0) {
|
||||
// try renderExpression(ais, tree, switch_node.expr, Space.None);
|
||||
// try renderToken(ais, tree, rparen, Space.Space); // )
|
||||
// try renderToken(ais, tree, lbrace, Space.None); // lbrace
|
||||
// return renderToken(ais, tree, switch_node.rbrace, space); // rbrace
|
||||
// }
|
||||
|
||||
// try renderExpression(ais, tree, switch_node.expr, Space.None);
|
||||
// try renderToken(ais, tree, rparen, Space.Space); // )
|
||||
|
||||
// {
|
||||
// ais.pushIndentNextLine();
|
||||
// defer ais.popIndent();
|
||||
// try renderToken(ais, tree, lbrace, Space.Newline); // lbrace
|
||||
|
||||
// const cases = switch_node.cases();
|
||||
// for (cases) |node, i| {
|
||||
// try renderExpression(ais, tree, node, Space.Comma);
|
||||
|
||||
// if (i + 1 < cases.len) {
|
||||
// try renderExtraNewline(ais, tree, cases[i + 1]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return renderToken(ais, tree, switch_node.rbrace, space); // rbrace
|
||||
//},
|
||||
|
||||
.SwitchCaseOne => unreachable, // TODO
|
||||
.SwitchCaseMulti => unreachable, // TODO
|
||||
//.SwitchCase => {
|
||||
// const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
|
||||
|
||||
// assert(switch_case.items_len != 0);
|
||||
// const src_has_trailing_comma = blk: {
|
||||
// const last_node = switch_case.items()[switch_case.items_len - 1];
|
||||
// const maybe_comma = tree.nextToken(last_node.lastToken());
|
||||
// break :blk tree.token_tags[maybe_comma] == .Comma;
|
||||
// };
|
||||
|
||||
// if (switch_case.items_len == 1 or !src_has_trailing_comma) {
|
||||
// const items = switch_case.items();
|
||||
// for (items) |node, i| {
|
||||
// if (i + 1 < items.len) {
|
||||
// try renderExpression(ais, tree, node, Space.None);
|
||||
|
||||
// const comma_token = tree.nextToken(node.lastToken());
|
||||
// try renderToken(ais, tree, comma_token, Space.Space); // ,
|
||||
// try renderExtraNewline(ais, tree, items[i + 1]);
|
||||
// } else {
|
||||
// try renderExpression(ais, tree, node, Space.Space);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// const items = switch_case.items();
|
||||
// for (items) |node, i| {
|
||||
// if (i + 1 < items.len) {
|
||||
// try renderExpression(ais, tree, node, Space.None);
|
||||
|
||||
// const comma_token = tree.nextToken(node.lastToken());
|
||||
// try renderToken(ais, tree, comma_token, Space.Newline); // ,
|
||||
// try renderExtraNewline(ais, tree, items[i + 1]);
|
||||
// } else {
|
||||
// try renderExpression(ais, tree, node, Space.Comma);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// try renderToken(ais, tree, switch_case.arrow_token, Space.Space); // =>
|
||||
|
||||
// if (switch_case.payload) |payload| {
|
||||
// try renderExpression(ais, tree, payload, Space.Space);
|
||||
// }
|
||||
|
||||
// return renderExpression(ais, tree, switch_case.expr, space);
|
||||
//},
|
||||
.SwitchCaseOne => try renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),
|
||||
.SwitchCase => try renderSwitchCase(ais, tree, tree.switchCase(node), space),
|
||||
|
||||
.WhileSimple => unreachable, // TODO
|
||||
.WhileCont => unreachable, // TODO
|
||||
@@ -1745,16 +1615,64 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.Full.FnProto, space: S
|
||||
return renderExpression(ais, tree, fn_proto.ast.return_type, space);
|
||||
}
|
||||
|
||||
fn renderSwitchCase(
|
||||
ais: *Ais,
|
||||
tree: ast.Tree,
|
||||
switch_case: ast.Full.SwitchCase,
|
||||
space: Space,
|
||||
) Error!void {
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .Comma;
|
||||
|
||||
// Render everything before the arrow
|
||||
if (switch_case.ast.values.len == 0) {
|
||||
try renderToken(ais, tree, switch_case.ast.arrow_token - 1, .Space); // else keyword
|
||||
} else if (switch_case.ast.values.len == 1) {
|
||||
// render on one line and drop the trailing comma if any
|
||||
try renderExpression(ais, tree, switch_case.ast.values[0], .Space);
|
||||
} else if (trailing_comma) {
|
||||
// Render each value on a new line
|
||||
try renderExpression(ais, tree, switch_case.ast.values[0], .Comma);
|
||||
for (switch_case.ast.values[1..]) |value_expr| {
|
||||
try renderExtraNewline(ais, tree, value_expr);
|
||||
try renderExpression(ais, tree, value_expr, .Comma);
|
||||
}
|
||||
} else {
|
||||
// Render on one line
|
||||
for (switch_case.ast.values) |value_expr| {
|
||||
try renderExpression(ais, tree, value_expr, .CommaSpace);
|
||||
}
|
||||
}
|
||||
|
||||
// Render the arrow and everything after it
|
||||
try renderToken(ais, tree, switch_case.ast.arrow_token, .Space);
|
||||
|
||||
if (switch_case.payload_token) |payload_token| {
|
||||
try renderToken(ais, tree, payload_token - 1, .None); // pipe
|
||||
if (token_tags[payload_token] == .Asterisk) {
|
||||
try renderToken(ais, tree, payload_token, .None); // asterisk
|
||||
try renderToken(ais, tree, payload_token + 1, .None); // identifier
|
||||
try renderToken(ais, tree, payload_token + 2, .Space); // pipe
|
||||
} else {
|
||||
try renderToken(ais, tree, payload_token, .None); // identifier
|
||||
try renderToken(ais, tree, payload_token + 1, .Space); // pipe
|
||||
}
|
||||
}
|
||||
|
||||
try renderExpression(ais, tree, switch_case.ast.target_expr, space);
|
||||
}
|
||||
|
||||
fn renderBlock(
|
||||
ais: *Ais,
|
||||
tree: ast.Tree,
|
||||
lbrace: ast.TokenIndex,
|
||||
block_node: ast.Node.Index,
|
||||
statements: []const ast.Node.Index,
|
||||
space: Space,
|
||||
) Error!void {
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const nodes_data = tree.nodes.items(.data);
|
||||
const lbrace = tree.nodes.items(.main_token)[block_node];
|
||||
|
||||
if (token_tags[lbrace - 1] == .Colon and
|
||||
token_tags[lbrace - 2] == .Identifier)
|
||||
@@ -1783,15 +1701,8 @@ fn renderBlock(
|
||||
}
|
||||
}
|
||||
ais.popIndent();
|
||||
// The rbrace could be +1 or +2 from the last token of the last
|
||||
// statement in the block because lastToken() does not count semicolons.
|
||||
const maybe_rbrace = tree.lastToken(statements[statements.len - 1]) + 1;
|
||||
if (token_tags[maybe_rbrace] == .RBrace) {
|
||||
return renderToken(ais, tree, maybe_rbrace, space);
|
||||
} else {
|
||||
assert(token_tags[maybe_rbrace + 1] == .RBrace);
|
||||
return renderToken(ais, tree, maybe_rbrace + 1, space);
|
||||
}
|
||||
|
||||
try renderToken(ais, tree, tree.lastToken(block_node), space); // rbrace
|
||||
}
|
||||
|
||||
// TODO: handle comments between fields
|
||||
|
||||
Reference in New Issue
Block a user