mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 14:55:25 +00:00
zig fmt: while loops
This commit is contained in:
parent
bcafc51e58
commit
1c79eea125
@ -760,6 +760,13 @@ pub const Tree = struct {
|
||||
n = extra.sentinel;
|
||||
},
|
||||
|
||||
.Continue => {
|
||||
if (datas[n].lhs != 0) {
|
||||
return datas[n].lhs + end_offset;
|
||||
} else {
|
||||
return main_tokens[n] + end_offset;
|
||||
}
|
||||
},
|
||||
.Break => {
|
||||
if (datas[n].rhs != 0) {
|
||||
n = datas[n].rhs;
|
||||
@ -837,6 +844,21 @@ pub const Tree = struct {
|
||||
n = max_node;
|
||||
end_offset += max_offset;
|
||||
},
|
||||
.WhileCont => {
|
||||
const extra = tree.extraData(datas[n].rhs, Node.WhileCont);
|
||||
assert(extra.then_expr != 0);
|
||||
n = extra.then_expr;
|
||||
},
|
||||
.While => {
|
||||
const extra = tree.extraData(datas[n].rhs, Node.While);
|
||||
assert(extra.else_expr != 0);
|
||||
n = extra.else_expr;
|
||||
},
|
||||
.If => {
|
||||
const extra = tree.extraData(datas[n].rhs, Node.If);
|
||||
assert(extra.else_expr != 0);
|
||||
n = extra.else_expr;
|
||||
},
|
||||
|
||||
// These are not supported by lastToken() because implementation would
|
||||
// require recursion due to the optional comma followed by rbrace.
|
||||
@ -851,13 +873,9 @@ pub const Tree = struct {
|
||||
|
||||
.TaggedUnionEnumTag => unreachable, // TODO
|
||||
.TaggedUnionEnumTagComma => unreachable, // TODO
|
||||
.If => unreachable, // TODO
|
||||
.Continue => unreachable, // TODO
|
||||
.SwitchRange => unreachable, // TODO
|
||||
.ArrayType => unreachable, // TODO
|
||||
.ArrayTypeSentinel => unreachable, // TODO
|
||||
.WhileCont => unreachable, // TODO
|
||||
.While => unreachable, // TODO
|
||||
.ForSimple => unreachable, // TODO
|
||||
.For => unreachable, // TODO
|
||||
.ErrorValue => unreachable, // TODO
|
||||
@ -1404,6 +1422,41 @@ pub const Tree = struct {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn whileSimple(tree: Tree, node: Node.Index) full.While {
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
return tree.fullWhile(.{
|
||||
.while_token = tree.nodes.items(.main_token)[node],
|
||||
.cond_expr = data.lhs,
|
||||
.cont_expr = 0,
|
||||
.then_expr = data.rhs,
|
||||
.else_expr = 0,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn whileCont(tree: Tree, node: Node.Index) full.While {
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
const extra = tree.extraData(data.rhs, Node.WhileCont);
|
||||
return tree.fullWhile(.{
|
||||
.while_token = tree.nodes.items(.main_token)[node],
|
||||
.cond_expr = data.lhs,
|
||||
.cont_expr = extra.cont_expr,
|
||||
.then_expr = extra.then_expr,
|
||||
.else_expr = 0,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn whileFull(tree: Tree, node: Node.Index) full.While {
|
||||
const data = tree.nodes.items(.data)[node];
|
||||
const extra = tree.extraData(data.rhs, Node.While);
|
||||
return tree.fullWhile(.{
|
||||
.while_token = tree.nodes.items(.main_token)[node],
|
||||
.cond_expr = data.lhs,
|
||||
.cont_expr = extra.cont_expr,
|
||||
.then_expr = extra.then_expr,
|
||||
.else_expr = extra.else_expr,
|
||||
});
|
||||
}
|
||||
|
||||
fn fullVarDecl(tree: Tree, info: full.VarDecl.Ast) full.VarDecl {
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
var result: full.VarDecl = .{
|
||||
@ -1623,6 +1676,41 @@ pub const Tree = struct {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn fullWhile(tree: Tree, info: full.While.Ast) full.While {
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
var result: full.While = .{
|
||||
.ast = info,
|
||||
.inline_token = null,
|
||||
.label_token = null,
|
||||
.payload_token = null,
|
||||
.else_token = undefined,
|
||||
.error_token = null,
|
||||
};
|
||||
var tok_i = info.while_token - 1;
|
||||
if (token_tags[tok_i] == .Keyword_inline) {
|
||||
result.inline_token = tok_i;
|
||||
tok_i -= 1;
|
||||
}
|
||||
if (token_tags[tok_i] == .Colon and
|
||||
token_tags[tok_i - 1] == .Identifier)
|
||||
{
|
||||
result.label_token = tok_i - 1;
|
||||
}
|
||||
const last_cond_token = tree.lastToken(info.cond_expr);
|
||||
if (token_tags[last_cond_token + 2] == .Pipe) {
|
||||
result.payload_token = last_cond_token + 3;
|
||||
}
|
||||
if (info.else_expr != 0) {
|
||||
// then_expr else |x|
|
||||
// ^ ^
|
||||
result.else_token = tree.lastToken(info.then_expr) + 1;
|
||||
if (token_tags[result.else_token + 1] == .Pipe) {
|
||||
result.error_token = result.else_token + 2;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// Fully assembled AST node information.
|
||||
@ -1645,12 +1733,12 @@ pub const full = struct {
|
||||
};
|
||||
|
||||
pub const If = struct {
|
||||
// Points to the first token after the `|`. Will either be an identifier or
|
||||
// a `*` (with an identifier immediately after it).
|
||||
/// Points to the first token after the `|`. Will either be an identifier or
|
||||
/// a `*` (with an identifier immediately after it).
|
||||
payload_token: ?TokenIndex,
|
||||
// Points to the identifier after the `|`.
|
||||
/// Points to the identifier after the `|`.
|
||||
error_token: ?TokenIndex,
|
||||
// Populated only if else_expr != 0.
|
||||
/// Populated only if else_expr != 0.
|
||||
else_token: TokenIndex,
|
||||
ast: Ast,
|
||||
|
||||
@ -1662,6 +1750,24 @@ pub const full = struct {
|
||||
};
|
||||
};
|
||||
|
||||
pub const While = struct {
|
||||
ast: Ast,
|
||||
inline_token: ?TokenIndex,
|
||||
label_token: ?TokenIndex,
|
||||
payload_token: ?TokenIndex,
|
||||
error_token: ?TokenIndex,
|
||||
/// Populated only if else_expr != 0.
|
||||
else_token: TokenIndex,
|
||||
|
||||
pub const Ast = struct {
|
||||
while_token: TokenIndex,
|
||||
cond_expr: Node.Index,
|
||||
cont_expr: Node.Index,
|
||||
then_expr: Node.Index,
|
||||
else_expr: Node.Index,
|
||||
};
|
||||
};
|
||||
|
||||
pub const ContainerField = struct {
|
||||
comptime_token: ?TokenIndex,
|
||||
ast: Ast,
|
||||
@ -2270,9 +2376,9 @@ pub const Node = struct {
|
||||
/// `if (lhs) rhs`.
|
||||
/// `if (lhs) |a| rhs`.
|
||||
IfSimple,
|
||||
/// `if (lhs) a else b`. `if_list[rhs]`.
|
||||
/// `if (lhs) |x| a else b`. `if_list[rhs]`.
|
||||
/// `if (lhs) |x| a else |y| b`. `if_list[rhs]`.
|
||||
/// `if (lhs) a else b`. `If[rhs]`.
|
||||
/// `if (lhs) |x| a else b`. `If[rhs]`.
|
||||
/// `if (lhs) |x| a else |y| b`. `If[rhs]`.
|
||||
If,
|
||||
/// `suspend lhs`. lhs can be omitted. rhs is unused.
|
||||
Suspend,
|
||||
@ -2497,13 +2603,13 @@ pub const Node = struct {
|
||||
};
|
||||
|
||||
pub const While = struct {
|
||||
continue_expr: Index,
|
||||
cont_expr: Index,
|
||||
then_expr: Index,
|
||||
else_expr: Index,
|
||||
};
|
||||
|
||||
pub const WhileCont = struct {
|
||||
continue_expr: Index,
|
||||
cont_expr: Index,
|
||||
then_expr: Index,
|
||||
};
|
||||
|
||||
|
||||
@ -1085,7 +1085,7 @@ const Parser = struct {
|
||||
const condition = try p.expectExpr();
|
||||
_ = try p.expectToken(.RParen);
|
||||
const then_payload = try p.parsePtrPayload();
|
||||
const continue_expr = try p.parseWhileContinueExpr();
|
||||
const cont_expr = try p.parseWhileContinueExpr();
|
||||
|
||||
// TODO propose to change the syntax so that semicolons are always required
|
||||
// inside while statements, even if there is an `else`.
|
||||
@ -1098,7 +1098,7 @@ const Parser = struct {
|
||||
return p.fail(.{ .ExpectedBlockOrAssignment = .{ .token = p.tok_i } });
|
||||
}
|
||||
if (p.eatToken(.Semicolon)) |_| {
|
||||
if (continue_expr == 0) {
|
||||
if (cont_expr == 0) {
|
||||
return p.addNode(.{
|
||||
.tag = .WhileSimple,
|
||||
.main_token = while_token,
|
||||
@ -1114,7 +1114,7 @@ const Parser = struct {
|
||||
.data = .{
|
||||
.lhs = condition,
|
||||
.rhs = try p.addExtra(Node.WhileCont{
|
||||
.continue_expr = continue_expr,
|
||||
.cont_expr = cont_expr,
|
||||
.then_expr = assign_expr,
|
||||
}),
|
||||
},
|
||||
@ -1128,7 +1128,7 @@ const Parser = struct {
|
||||
if (else_required) {
|
||||
return p.fail(.{ .ExpectedSemiOrElse = .{ .token = p.tok_i } });
|
||||
}
|
||||
if (continue_expr == 0) {
|
||||
if (cont_expr == 0) {
|
||||
return p.addNode(.{
|
||||
.tag = .WhileSimple,
|
||||
.main_token = while_token,
|
||||
@ -1144,7 +1144,7 @@ const Parser = struct {
|
||||
.data = .{
|
||||
.lhs = condition,
|
||||
.rhs = try p.addExtra(Node.WhileCont{
|
||||
.continue_expr = continue_expr,
|
||||
.cont_expr = cont_expr,
|
||||
.then_expr = then_expr,
|
||||
}),
|
||||
},
|
||||
@ -1159,7 +1159,7 @@ const Parser = struct {
|
||||
.data = .{
|
||||
.lhs = condition,
|
||||
.rhs = try p.addExtra(Node.While{
|
||||
.continue_expr = continue_expr,
|
||||
.cont_expr = cont_expr,
|
||||
.then_expr = then_expr,
|
||||
.else_expr = else_expr,
|
||||
}),
|
||||
@ -2073,11 +2073,11 @@ const Parser = struct {
|
||||
const condition = try p.expectExpr();
|
||||
_ = try p.expectToken(.RParen);
|
||||
const then_payload = try p.parsePtrPayload();
|
||||
const continue_expr = try p.parseWhileContinueExpr();
|
||||
const cont_expr = try p.parseWhileContinueExpr();
|
||||
|
||||
const then_expr = try p.expectExpr();
|
||||
const else_token = p.eatToken(.Keyword_else) orelse {
|
||||
if (continue_expr == 0) {
|
||||
if (cont_expr == 0) {
|
||||
return p.addNode(.{
|
||||
.tag = .WhileSimple,
|
||||
.main_token = while_token,
|
||||
@ -2093,7 +2093,7 @@ const Parser = struct {
|
||||
.data = .{
|
||||
.lhs = condition,
|
||||
.rhs = try p.addExtra(Node.WhileCont{
|
||||
.continue_expr = continue_expr,
|
||||
.cont_expr = cont_expr,
|
||||
.then_expr = then_expr,
|
||||
}),
|
||||
},
|
||||
@ -2108,7 +2108,7 @@ const Parser = struct {
|
||||
.data = .{
|
||||
.lhs = condition,
|
||||
.rhs = try p.addExtra(Node.While{
|
||||
.continue_expr = continue_expr,
|
||||
.cont_expr = cont_expr,
|
||||
.then_expr = then_expr,
|
||||
.else_expr = else_expr,
|
||||
}),
|
||||
@ -2836,11 +2836,11 @@ const Parser = struct {
|
||||
const condition = try p.expectExpr();
|
||||
_ = try p.expectToken(.RParen);
|
||||
const then_payload = try p.parsePtrPayload();
|
||||
const continue_expr = try p.parseWhileContinueExpr();
|
||||
const cont_expr = try p.parseWhileContinueExpr();
|
||||
|
||||
const then_expr = try p.expectTypeExpr();
|
||||
const else_token = p.eatToken(.Keyword_else) orelse {
|
||||
if (continue_expr == 0) {
|
||||
if (cont_expr == 0) {
|
||||
return p.addNode(.{
|
||||
.tag = .WhileSimple,
|
||||
.main_token = while_token,
|
||||
@ -2856,7 +2856,7 @@ const Parser = struct {
|
||||
.data = .{
|
||||
.lhs = condition,
|
||||
.rhs = try p.addExtra(Node.WhileCont{
|
||||
.continue_expr = continue_expr,
|
||||
.cont_expr = cont_expr,
|
||||
.then_expr = then_expr,
|
||||
}),
|
||||
},
|
||||
@ -2871,7 +2871,7 @@ const Parser = struct {
|
||||
.data = .{
|
||||
.lhs = condition,
|
||||
.rhs = try p.addExtra(Node.While{
|
||||
.continue_expr = continue_expr,
|
||||
.cont_expr = cont_expr,
|
||||
.then_expr = then_expr,
|
||||
.else_expr = else_expr,
|
||||
}),
|
||||
|
||||
@ -714,19 +714,19 @@ test "zig fmt: async function" {
|
||||
// \\
|
||||
// );
|
||||
//}
|
||||
//
|
||||
//test "zig fmt: while else err prong with no block" {
|
||||
// try testCanonical(
|
||||
// \\test "" {
|
||||
// \\ const result = while (returnError()) |value| {
|
||||
// \\ break value;
|
||||
// \\ } else |err| @as(i32, 2);
|
||||
// \\ expect(result == 2);
|
||||
// \\}
|
||||
// \\
|
||||
// );
|
||||
//}
|
||||
//
|
||||
|
||||
test "zig fmt: while else err prong with no block" {
|
||||
try testCanonical(
|
||||
\\test "" {
|
||||
\\ const result = while (returnError()) |value| {
|
||||
\\ break value;
|
||||
\\ } else |err| @as(i32, 2);
|
||||
\\ expect(result == 2);
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
//test "zig fmt: tagged union with enum values" {
|
||||
// try testCanonical(
|
||||
// \\const MultipleChoice2 = union(enum(u32)) {
|
||||
|
||||
@ -567,13 +567,13 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
if (lbrace + 1 == rbrace) {
|
||||
// There is nothing between the braces so render condensed: `error{}`
|
||||
try renderToken(ais, tree, lbrace, .None);
|
||||
try renderToken(ais, tree, rbrace, space);
|
||||
return renderToken(ais, tree, rbrace, space);
|
||||
} else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .Identifier) {
|
||||
// There is exactly one member and no trailing comma or
|
||||
// comments, so render without surrounding spaces: `error{Foo}`
|
||||
try renderToken(ais, tree, lbrace, .None);
|
||||
try renderToken(ais, tree, lbrace + 1, .None); // identifier
|
||||
try renderToken(ais, tree, rbrace, space);
|
||||
return renderToken(ais, tree, rbrace, space);
|
||||
} else if (token_tags[rbrace - 1] == .Comma) {
|
||||
// There is a trailing comma so render each member on a new line.
|
||||
try renderToken(ais, tree, lbrace, .Newline);
|
||||
@ -589,7 +589,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
}
|
||||
}
|
||||
ais.popIndent();
|
||||
try renderToken(ais, tree, rbrace, space);
|
||||
return renderToken(ais, tree, rbrace, space);
|
||||
} else {
|
||||
// There is no trailing comma so render everything on one line.
|
||||
try renderToken(ais, tree, lbrace, .Space);
|
||||
@ -602,7 +602,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
try renderToken(ais, tree, rbrace, space);
|
||||
return renderToken(ais, tree, rbrace, space);
|
||||
}
|
||||
},
|
||||
|
||||
@ -663,7 +663,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
|
||||
if (cases.len == 0) {
|
||||
try renderToken(ais, tree, rparen + 1, .None); // lbrace
|
||||
try renderToken(ais, tree, rparen + 2, space); // rbrace
|
||||
return renderToken(ais, tree, rparen + 2, space); // rbrace
|
||||
} else {
|
||||
try renderToken(ais, tree, rparen + 1, .Newline); // lbrace
|
||||
ais.pushIndent();
|
||||
@ -673,83 +673,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
|
||||
try renderExpression(ais, tree, case, .Comma);
|
||||
}
|
||||
ais.popIndent();
|
||||
try renderToken(ais, tree, tree.lastToken(node), space); // rbrace
|
||||
return renderToken(ais, tree, tree.lastToken(node), space); // rbrace
|
||||
}
|
||||
},
|
||||
|
||||
.SwitchCaseOne => try renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),
|
||||
.SwitchCase => try renderSwitchCase(ais, tree, tree.switchCase(node), space),
|
||||
.SwitchCaseOne => return renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),
|
||||
.SwitchCase => return renderSwitchCase(ais, tree, tree.switchCase(node), space),
|
||||
|
||||
.WhileSimple => unreachable, // TODO
|
||||
.WhileCont => unreachable, // TODO
|
||||
.While => unreachable, // TODO
|
||||
//.While => {
|
||||
// const while_node = @fieldParentPtr(ast.Node.While, "base", base);
|
||||
|
||||
// if (while_node.label) |label| {
|
||||
// try renderToken(ais, tree, label, Space.None); // label
|
||||
// try renderToken(ais, tree, tree.nextToken(label), Space.Space); // :
|
||||
// }
|
||||
|
||||
// if (while_node.inline_token) |inline_token| {
|
||||
// try renderToken(ais, tree, inline_token, Space.Space); // inline
|
||||
// }
|
||||
|
||||
// try renderToken(ais, tree, while_node.while_token, Space.Space); // while
|
||||
// try renderToken(ais, tree, tree.nextToken(while_node.while_token), Space.None); // (
|
||||
// try renderExpression(ais, tree, while_node.condition, Space.None);
|
||||
|
||||
// const cond_rparen = tree.nextToken(while_node.condition.lastToken());
|
||||
|
||||
// const body_is_block = nodeIsBlock(while_node.body);
|
||||
|
||||
// var block_start_space: Space = undefined;
|
||||
// var after_body_space: Space = undefined;
|
||||
|
||||
// if (body_is_block) {
|
||||
// block_start_space = Space.BlockStart;
|
||||
// after_body_space = if (while_node.@"else" == null) space else Space.Space;
|
||||
// } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
|
||||
// block_start_space = Space.Space;
|
||||
// after_body_space = if (while_node.@"else" == null) space else Space.Space;
|
||||
// } else {
|
||||
// block_start_space = Space.Newline;
|
||||
// after_body_space = if (while_node.@"else" == null) space else Space.Newline;
|
||||
// }
|
||||
|
||||
// {
|
||||
// const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
|
||||
// try renderToken(ais, tree, cond_rparen, rparen_space); // )
|
||||
// }
|
||||
|
||||
// if (while_node.payload) |payload| {
|
||||
// const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
|
||||
// try renderExpression(ais, tree, payload, payload_space);
|
||||
// }
|
||||
|
||||
// if (while_node.continue_expr) |continue_expr| {
|
||||
// const rparen = tree.nextToken(continue_expr.lastToken());
|
||||
// const lparen = tree.prevToken(continue_expr.firstToken());
|
||||
// const colon = tree.prevToken(lparen);
|
||||
|
||||
// try renderToken(ais, tree, colon, Space.Space); // :
|
||||
// try renderToken(ais, tree, lparen, Space.None); // (
|
||||
|
||||
// try renderExpression(ais, tree, continue_expr, Space.None);
|
||||
|
||||
// try renderToken(ais, tree, rparen, block_start_space); // )
|
||||
// }
|
||||
|
||||
// {
|
||||
// if (!body_is_block) ais.pushIndent();
|
||||
// defer if (!body_is_block) ais.popIndent();
|
||||
// try renderExpression(ais, tree, while_node.body, after_body_space);
|
||||
// }
|
||||
|
||||
// if (while_node.@"else") |@"else"| {
|
||||
// return renderExpression(ais, tree, &@"else".base, space);
|
||||
// }
|
||||
//},
|
||||
.WhileSimple => return renderWhile(ais, tree, tree.whileSimple(node), space),
|
||||
.WhileCont => return renderWhile(ais, tree, tree.whileCont(node), space),
|
||||
.While => return renderWhile(ais, tree, tree.whileFull(node), space),
|
||||
|
||||
.ForSimple => unreachable, // TODO
|
||||
.For => unreachable, // TODO
|
||||
@ -1092,105 +1025,142 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo
|
||||
}
|
||||
|
||||
fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error!void {
|
||||
return renderWhile(ais, tree, .{
|
||||
.ast = .{
|
||||
.while_token = if_node.ast.if_token,
|
||||
.cond_expr = if_node.ast.cond_expr,
|
||||
.cont_expr = 0,
|
||||
.then_expr = if_node.ast.then_expr,
|
||||
.else_expr = if_node.ast.else_expr,
|
||||
},
|
||||
.inline_token = null,
|
||||
.label_token = null,
|
||||
.payload_token = if_node.payload_token,
|
||||
.else_token = if_node.else_token,
|
||||
.error_token = if_node.error_token,
|
||||
}, space);
|
||||
}
|
||||
|
||||
/// Note that this function is additionally used to render if expressions, with
|
||||
/// respective values set to null.
|
||||
fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Space) Error!void {
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
try renderToken(ais, tree, if_node.ast.if_token, .Space); // if
|
||||
|
||||
const lparen = if_node.ast.if_token + 1;
|
||||
|
||||
try renderToken(ais, tree, lparen, .None); // (
|
||||
try renderExpression(ais, tree, if_node.ast.cond_expr, .None); // condition
|
||||
|
||||
switch (node_tags[if_node.ast.then_expr]) {
|
||||
.If, .IfSimple => {
|
||||
try renderExtraNewline(ais, tree, if_node.ast.then_expr);
|
||||
},
|
||||
.Block, .For, .ForSimple, .While, .WhileSimple, .Switch => {
|
||||
if (if_node.payload_token) |payload_token| {
|
||||
try renderToken(ais, tree, payload_token - 2, .Space); // )
|
||||
try renderToken(ais, tree, payload_token - 1, .None); // |
|
||||
if (token_tags[payload_token] == .Asterisk) {
|
||||
try renderToken(ais, tree, payload_token, .None); // *
|
||||
try renderToken(ais, tree, payload_token + 1, .None); // identifier
|
||||
try renderToken(ais, tree, payload_token + 2, .BlockStart); // |
|
||||
} else {
|
||||
try renderToken(ais, tree, payload_token, .None); // identifier
|
||||
try renderToken(ais, tree, payload_token + 1, .BlockStart); // |
|
||||
}
|
||||
} else {
|
||||
const rparen = tree.lastToken(if_node.ast.cond_expr) + 1;
|
||||
try renderToken(ais, tree, rparen, .BlockStart); // )
|
||||
}
|
||||
if (if_node.ast.else_expr != 0) {
|
||||
try renderExpression(ais, tree, if_node.ast.then_expr, Space.Space);
|
||||
try renderToken(ais, tree, if_node.else_token, .Space); // else
|
||||
if (if_node.error_token) |error_token| {
|
||||
try renderToken(ais, tree, error_token - 1, .None); // |
|
||||
try renderToken(ais, tree, error_token, .None); // identifier
|
||||
try renderToken(ais, tree, error_token + 1, .Space); // |
|
||||
}
|
||||
return renderExpression(ais, tree, if_node.ast.else_expr, space);
|
||||
} else {
|
||||
return renderExpression(ais, tree, if_node.ast.then_expr, space);
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
if (while_node.label_token) |label| {
|
||||
try renderToken(ais, tree, label, .None); // label
|
||||
try renderToken(ais, tree, label + 1, .Space); // :
|
||||
}
|
||||
|
||||
const rparen = tree.lastToken(if_node.ast.cond_expr) + 1;
|
||||
const last_then_token = tree.lastToken(if_node.ast.then_expr);
|
||||
if (while_node.inline_token) |inline_token| {
|
||||
try renderToken(ais, tree, inline_token, .Space); // inline
|
||||
}
|
||||
|
||||
try renderToken(ais, tree, while_node.ast.while_token, .Space); // if
|
||||
try renderToken(ais, tree, while_node.ast.while_token + 1, .None); // (
|
||||
try renderExpression(ais, tree, while_node.ast.cond_expr, .None); // condition
|
||||
|
||||
if (nodeIsBlock(node_tags[while_node.ast.then_expr])) {
|
||||
const payload_space: Space = if (while_node.ast.cont_expr != 0) .Space else .BlockStart;
|
||||
if (while_node.payload_token) |payload_token| {
|
||||
try renderToken(ais, tree, payload_token - 2, .Space); // )
|
||||
try renderToken(ais, tree, payload_token - 1, .None); // |
|
||||
if (token_tags[payload_token] == .Asterisk) {
|
||||
try renderToken(ais, tree, payload_token, .None); // *
|
||||
try renderToken(ais, tree, payload_token + 1, .None); // identifier
|
||||
try renderToken(ais, tree, payload_token + 2, payload_space); // |
|
||||
} else {
|
||||
try renderToken(ais, tree, payload_token, .None); // identifier
|
||||
try renderToken(ais, tree, payload_token + 1, payload_space); // |
|
||||
}
|
||||
} else {
|
||||
const rparen = tree.lastToken(while_node.ast.cond_expr) + 1;
|
||||
try renderToken(ais, tree, rparen, payload_space); // )
|
||||
}
|
||||
if (while_node.ast.cont_expr != 0) {
|
||||
const rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
|
||||
const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
|
||||
try renderToken(ais, tree, lparen - 1, .Space); // :
|
||||
try renderToken(ais, tree, lparen, .None); // lparen
|
||||
try renderExpression(ais, tree, while_node.ast.cont_expr, .None);
|
||||
try renderToken(ais, tree, rparen, .BlockStart); // rparen
|
||||
}
|
||||
if (while_node.ast.else_expr != 0) {
|
||||
try renderExpression(ais, tree, while_node.ast.then_expr, Space.Space);
|
||||
try renderToken(ais, tree, while_node.else_token, .Space); // else
|
||||
if (while_node.error_token) |error_token| {
|
||||
try renderToken(ais, tree, error_token - 1, .None); // |
|
||||
try renderToken(ais, tree, error_token, .None); // identifier
|
||||
try renderToken(ais, tree, error_token + 1, .Space); // |
|
||||
}
|
||||
return renderExpression(ais, tree, while_node.ast.else_expr, space);
|
||||
} else {
|
||||
return renderExpression(ais, tree, while_node.ast.then_expr, space);
|
||||
}
|
||||
}
|
||||
|
||||
const rparen = tree.lastToken(while_node.ast.cond_expr) + 1;
|
||||
const last_then_token = tree.lastToken(while_node.ast.then_expr);
|
||||
const src_has_newline = !tree.tokensOnSameLine(rparen, last_then_token);
|
||||
|
||||
if (src_has_newline) {
|
||||
if (if_node.payload_token) |payload_token| {
|
||||
const payload_space: Space = if (while_node.ast.cont_expr != 0) .Space else .Newline;
|
||||
if (while_node.payload_token) |payload_token| {
|
||||
try renderToken(ais, tree, payload_token - 2, .Space); // )
|
||||
try renderToken(ais, tree, payload_token - 1, .None); // |
|
||||
try renderToken(ais, tree, payload_token, .None); // identifier
|
||||
try renderToken(ais, tree, payload_token + 1, .Newline); // |
|
||||
try renderToken(ais, tree, payload_token + 1, payload_space); // |
|
||||
} else {
|
||||
ais.pushIndent();
|
||||
try renderToken(ais, tree, rparen, .Newline); // )
|
||||
try renderToken(ais, tree, rparen, payload_space); // )
|
||||
ais.popIndent();
|
||||
}
|
||||
if (if_node.ast.else_expr != 0) {
|
||||
if (while_node.ast.cont_expr != 0) {
|
||||
const cont_rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
|
||||
const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
|
||||
try renderToken(ais, tree, cont_lparen - 1, .Space); // :
|
||||
try renderToken(ais, tree, cont_lparen, .None); // lparen
|
||||
try renderExpression(ais, tree, while_node.ast.cont_expr, .None);
|
||||
try renderToken(ais, tree, cont_rparen, .Newline); // rparen
|
||||
}
|
||||
if (while_node.ast.else_expr != 0) {
|
||||
ais.pushIndent();
|
||||
try renderExpression(ais, tree, if_node.ast.then_expr, Space.Newline);
|
||||
try renderExpression(ais, tree, while_node.ast.then_expr, Space.Newline);
|
||||
ais.popIndent();
|
||||
const else_is_block = nodeIsBlock(node_tags[if_node.ast.else_expr]);
|
||||
const else_is_block = nodeIsBlock(node_tags[while_node.ast.else_expr]);
|
||||
if (else_is_block) {
|
||||
try renderToken(ais, tree, if_node.else_token, .Space); // else
|
||||
if (if_node.error_token) |error_token| {
|
||||
try renderToken(ais, tree, while_node.else_token, .Space); // else
|
||||
if (while_node.error_token) |error_token| {
|
||||
try renderToken(ais, tree, error_token - 1, .None); // |
|
||||
try renderToken(ais, tree, error_token, .None); // identifier
|
||||
try renderToken(ais, tree, error_token + 1, .Space); // |
|
||||
}
|
||||
return renderExpression(ais, tree, if_node.ast.else_expr, space);
|
||||
return renderExpression(ais, tree, while_node.ast.else_expr, space);
|
||||
} else {
|
||||
if (if_node.error_token) |error_token| {
|
||||
try renderToken(ais, tree, if_node.else_token, .Space); // else
|
||||
if (while_node.error_token) |error_token| {
|
||||
try renderToken(ais, tree, while_node.else_token, .Space); // else
|
||||
try renderToken(ais, tree, error_token - 1, .None); // |
|
||||
try renderToken(ais, tree, error_token, .None); // identifier
|
||||
try renderToken(ais, tree, error_token + 1, .Space); // |
|
||||
} else {
|
||||
try renderToken(ais, tree, if_node.else_token, .Newline); // else
|
||||
try renderToken(ais, tree, while_node.else_token, .Newline); // else
|
||||
}
|
||||
ais.pushIndent();
|
||||
try renderExpression(ais, tree, if_node.ast.else_expr, space);
|
||||
try renderExpression(ais, tree, while_node.ast.else_expr, space);
|
||||
ais.popIndent();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ais.pushIndent();
|
||||
try renderExpression(ais, tree, if_node.ast.then_expr, space);
|
||||
try renderExpression(ais, tree, while_node.ast.then_expr, space);
|
||||
ais.popIndent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Single line if statement.
|
||||
// Render everything on a single line.
|
||||
|
||||
if (if_node.payload_token) |payload_token| {
|
||||
if (while_node.payload_token) |payload_token| {
|
||||
assert(payload_token - 2 == rparen);
|
||||
try renderToken(ais, tree, payload_token - 2, .Space); // )
|
||||
try renderToken(ais, tree, payload_token - 1, .None); // |
|
||||
@ -1206,19 +1176,28 @@ fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error
|
||||
try renderToken(ais, tree, rparen, .Space); // )
|
||||
}
|
||||
|
||||
if (if_node.ast.else_expr != 0) {
|
||||
try renderExpression(ais, tree, if_node.ast.then_expr, .Space);
|
||||
try renderToken(ais, tree, if_node.else_token, .Space); // else
|
||||
if (while_node.ast.cont_expr != 0) {
|
||||
const cont_rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
|
||||
const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
|
||||
try renderToken(ais, tree, cont_lparen - 1, .Space); // :
|
||||
try renderToken(ais, tree, cont_lparen, .None); // lparen
|
||||
try renderExpression(ais, tree, while_node.ast.cont_expr, .None);
|
||||
try renderToken(ais, tree, cont_rparen, .Space); // rparen
|
||||
}
|
||||
|
||||
if (if_node.error_token) |error_token| {
|
||||
if (while_node.ast.else_expr != 0) {
|
||||
try renderExpression(ais, tree, while_node.ast.then_expr, .Space);
|
||||
try renderToken(ais, tree, while_node.else_token, .Space); // else
|
||||
|
||||
if (while_node.error_token) |error_token| {
|
||||
try renderToken(ais, tree, error_token - 1, .None); // |
|
||||
try renderToken(ais, tree, error_token, .None); // identifier
|
||||
try renderToken(ais, tree, error_token + 1, .Space); // |
|
||||
}
|
||||
|
||||
return renderExpression(ais, tree, if_node.ast.else_expr, space);
|
||||
return renderExpression(ais, tree, while_node.ast.else_expr, space);
|
||||
} else {
|
||||
return renderExpression(ais, tree, if_node.ast.then_expr, space);
|
||||
return renderExpression(ais, tree, while_node.ast.then_expr, space);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2079,12 +2058,16 @@ fn renderDocComments(ais: *Ais, tree: ast.Tree, end_token: ast.TokenIndex) Error
|
||||
fn nodeIsBlock(tag: ast.Node.Tag) bool {
|
||||
return switch (tag) {
|
||||
.Block,
|
||||
.BlockSemicolon,
|
||||
.BlockTwo,
|
||||
.BlockTwoSemicolon,
|
||||
.If,
|
||||
.IfSimple,
|
||||
.For,
|
||||
.ForSimple,
|
||||
.While,
|
||||
.WhileSimple,
|
||||
.WhileCont,
|
||||
.Switch,
|
||||
=> true,
|
||||
else => false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user