mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
zig fmt: fix many bugs with multiline string literals
Adds two new space modes maybe_space and comma_maybe_space which only render the space when the next token is not a multiline string literal. This is used in a lot of places to avoid a trailing space on lines caused by multiline string literals forcing newlines. Fixes places where the node tag is compared to be a multiline string literal to instead check if the first token is a multiline string literal line. This fixes cases like `\\ ++ text`. This commit also rewrites quite a bit of code to be clearer / deduplicated.
This commit is contained in:
parent
fcc0c1a8a9
commit
be288f8b6a
2 changed files with 586 additions and 308 deletions
|
|
@ -346,20 +346,27 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
const next_token_tag = tree.tokenTag(next_token);
|
||||
|
||||
// dedent the next thing that comes after a multiline string literal
|
||||
if (!ais.indentStackEmpty() and
|
||||
next_token_tag != .colon and
|
||||
((next_token_tag != .semicolon and next_token_tag != .comma) or
|
||||
ais.lastSpaceModeIndent() < ais.currentIndent()))
|
||||
if (next_token_tag != .colon and
|
||||
!ais.indentStackEmpty() and
|
||||
ais.lastSpaceModeIndent() < ais.currentIndent())
|
||||
{
|
||||
ais.popIndent();
|
||||
try ais.pushIndent(.normal);
|
||||
const indent_top = &ais.indent_stack.items[ais.indent_stack.items.len - 1];
|
||||
if (indent_top.realized) {
|
||||
indent_top.realized = false;
|
||||
ais.indent_count -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (space) {
|
||||
.none, .space, .newline, .skip => {},
|
||||
.semicolon => if (next_token_tag == .semicolon) try renderTokenOverrideSpaceMode(r, next_token, .newline, .semicolon),
|
||||
.comma => if (next_token_tag == .comma) try renderTokenOverrideSpaceMode(r, next_token, .newline, .comma),
|
||||
.comma_space => if (next_token_tag == .comma) try renderToken(r, next_token, .space),
|
||||
.none, .space, .newline, .maybe_space, .skip => {},
|
||||
.semicolon => if (next_token_tag == .semicolon)
|
||||
try renderTokenOverrideSpaceMode(r, next_token, .newline, .semicolon),
|
||||
.comma => if (next_token_tag == .comma)
|
||||
try renderTokenOverrideSpaceMode(r, next_token, .newline, .comma),
|
||||
.comma_space => if (next_token_tag == .comma)
|
||||
try renderToken(r, next_token, .space),
|
||||
.comma_maybe_space => if (next_token_tag == .comma)
|
||||
try renderToken(r, next_token, .maybe_space),
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -384,11 +391,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
const defer_token = tree.nodeMainToken(node);
|
||||
const maybe_payload_token, const expr = tree.nodeData(node).opt_token_and_node;
|
||||
|
||||
try renderToken(r, defer_token, .space);
|
||||
try renderToken(r, defer_token, .maybe_space);
|
||||
if (maybe_payload_token.unwrap()) |payload_token| {
|
||||
try renderToken(r, payload_token - 1, .none); // |
|
||||
try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
|
||||
try renderToken(r, payload_token + 1, .space); // |
|
||||
try renderToken(r, payload_token + 1, .maybe_space); // |
|
||||
}
|
||||
return renderExpression(r, expr, space);
|
||||
},
|
||||
|
|
@ -400,7 +407,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
=> {
|
||||
const main_token = tree.nodeMainToken(node);
|
||||
const item = tree.nodeData(node).node;
|
||||
try renderToken(r, main_token, .space);
|
||||
try renderToken(r, main_token, .maybe_space);
|
||||
return renderExpression(r, item, space);
|
||||
},
|
||||
|
||||
|
|
@ -409,8 +416,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
const lhs, const rhs = tree.nodeData(node).node_and_node;
|
||||
const fallback_first = tree.firstToken(rhs);
|
||||
|
||||
const same_line = tree.tokensOnSameLine(main_token, fallback_first);
|
||||
const after_op_space = if (same_line) Space.space else Space.newline;
|
||||
const seperate_line = !tree.tokensOnSameLine(main_token, fallback_first) or
|
||||
tree.tokenTag(fallback_first) == .multiline_string_literal_line;
|
||||
const after_op_space: Space = if (seperate_line) .newline else .space;
|
||||
|
||||
try renderExpression(r, lhs, .space); // target
|
||||
|
||||
|
|
@ -489,11 +497,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
try renderExpression(r, lhs, .space);
|
||||
const op_token = tree.nodeMainToken(node);
|
||||
try ais.pushIndent(.after_equals);
|
||||
if (tree.tokensOnSameLine(op_token, op_token + 1)) {
|
||||
try renderToken(r, op_token, .space);
|
||||
} else {
|
||||
try renderToken(r, op_token, .newline);
|
||||
}
|
||||
const rhs_seperate_line = !tree.tokensOnSameLine(op_token, op_token + 1) or
|
||||
tree.tokenTag(op_token + 1) == .multiline_string_literal_line;
|
||||
try renderToken(r, op_token, if (rhs_seperate_line) .newline else .space);
|
||||
try renderExpression(r, rhs, space);
|
||||
ais.popIndent();
|
||||
},
|
||||
|
|
@ -532,11 +538,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
try renderExpression(r, lhs, .space);
|
||||
const op_token = tree.nodeMainToken(node);
|
||||
try ais.pushIndent(.binop);
|
||||
if (tree.tokensOnSameLine(op_token, op_token + 1)) {
|
||||
try renderToken(r, op_token, .space);
|
||||
} else {
|
||||
try renderToken(r, op_token, .newline);
|
||||
}
|
||||
const rhs_seperate_line = !tree.tokensOnSameLine(op_token, op_token + 1) or
|
||||
tree.tokenTag(op_token + 1) == .multiline_string_literal_line;
|
||||
try renderToken(r, op_token, if (rhs_seperate_line) .newline else .space);
|
||||
try renderExpression(r, rhs, space);
|
||||
ais.popIndent();
|
||||
},
|
||||
|
|
@ -544,11 +548,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
.assign_destructure => {
|
||||
const full = tree.assignDestructure(node);
|
||||
if (full.comptime_token) |comptime_token| {
|
||||
try renderToken(r, comptime_token, .space);
|
||||
try renderToken(r, comptime_token, .maybe_space);
|
||||
}
|
||||
|
||||
for (full.ast.variables, 0..) |variable_node, i| {
|
||||
const variable_space: Space = if (i == full.ast.variables.len - 1) .space else .comma_space;
|
||||
const variable_space: Space = if (i == full.ast.variables.len - 1) .maybe_space else .comma_maybe_space;
|
||||
switch (tree.nodeTag(variable_node)) {
|
||||
.global_var_decl,
|
||||
.local_var_decl,
|
||||
|
|
@ -561,11 +565,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
}
|
||||
}
|
||||
try ais.pushIndent(.after_equals);
|
||||
if (tree.tokensOnSameLine(full.ast.equal_token, full.ast.equal_token + 1)) {
|
||||
try renderToken(r, full.ast.equal_token, .space);
|
||||
} else {
|
||||
try renderToken(r, full.ast.equal_token, .newline);
|
||||
}
|
||||
const expr_seperate_line =
|
||||
!tree.tokensOnSameLine(full.ast.equal_token, full.ast.equal_token + 1) or
|
||||
tree.tokenTag(full.ast.equal_token + 1) == .multiline_string_literal_line;
|
||||
try renderToken(r, full.ast.equal_token, if (expr_seperate_line) .newline else .space);
|
||||
try renderExpression(r, full.ast.value_expr, space);
|
||||
ais.popIndent();
|
||||
},
|
||||
|
|
@ -584,7 +587,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
.@"try",
|
||||
.@"resume",
|
||||
=> {
|
||||
try renderToken(r, tree.nodeMainToken(node), .space);
|
||||
try renderToken(r, tree.nodeMainToken(node), .maybe_space);
|
||||
return renderExpression(r, tree.nodeData(node).node, space);
|
||||
},
|
||||
|
||||
|
|
@ -668,30 +671,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||
.@"break", .@"continue" => {
|
||||
const main_token = tree.nodeMainToken(node);
|
||||
const opt_label_token, const opt_target = tree.nodeData(node).opt_token_and_opt_node;
|
||||
if (opt_label_token == .none and opt_target == .none) {
|
||||
try renderToken(r, main_token, space); // break/continue
|
||||
} else if (opt_label_token == .none and opt_target != .none) {
|
||||
const target = opt_target.unwrap().?;
|
||||
try renderToken(r, main_token, .space); // break/continue
|
||||
try renderExpression(r, target, space);
|
||||
} else if (opt_label_token != .none and opt_target == .none) {
|
||||
const label_token = opt_label_token.unwrap().?;
|
||||
try renderToken(r, main_token, .space); // break/continue
|
||||
|
||||
const before_target_space: Space = if (opt_target != .none) .maybe_space else space;
|
||||
const before_label_space: Space = if (opt_label_token != .none) .space else before_target_space;
|
||||
|
||||
try renderToken(r, main_token, before_label_space);
|
||||
if (opt_label_token.unwrap()) |label_token| {
|
||||
try renderToken(r, label_token - 1, .none); // :
|
||||
try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier
|
||||
} else if (opt_label_token != .none and opt_target != .none) {
|
||||
const label_token = opt_label_token.unwrap().?;
|
||||
const target = opt_target.unwrap().?;
|
||||
try renderToken(r, main_token, .space); // break/continue
|
||||
try renderToken(r, label_token - 1, .none); // :
|
||||
try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier
|
||||
try renderIdentifier(r, label_token, before_target_space, .eagerly_unquote); // identifier
|
||||
}
|
||||
if (opt_target.unwrap()) |target| {
|
||||
try renderExpression(r, target, space);
|
||||
} else unreachable;
|
||||
}
|
||||
},
|
||||
|
||||
.@"return" => {
|
||||
if (tree.nodeData(node).opt_node.unwrap()) |expr| {
|
||||
try renderToken(r, tree.nodeMainToken(node), .space);
|
||||
try renderToken(r, tree.nodeMainToken(node), .maybe_space);
|
||||
try renderExpression(r, expr, space);
|
||||
} else {
|
||||
try renderToken(r, tree.nodeMainToken(node), space);
|
||||
|
|
@ -954,6 +950,7 @@ fn renderArrayType(
|
|||
fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
|
||||
const tree = r.tree;
|
||||
const main_token = ptr_type.ast.main_token;
|
||||
|
||||
switch (ptr_type.size) {
|
||||
.one => {
|
||||
// Since ** tokens exist and the same token is shared by two
|
||||
|
|
@ -1000,11 +997,36 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
|
|||
},
|
||||
}
|
||||
|
||||
// .maybe_space cannot be used at the end of each qualifier since they may be reordered
|
||||
const final_qual: enum {
|
||||
@"volatile",
|
||||
@"const",
|
||||
@"addrspace",
|
||||
@"align",
|
||||
@"allowzero",
|
||||
none,
|
||||
} = if (ptr_type.volatile_token != null)
|
||||
.@"volatile"
|
||||
else if (ptr_type.const_token != null)
|
||||
.@"const"
|
||||
else if (ptr_type.ast.addrspace_node != .none)
|
||||
.@"addrspace"
|
||||
else if (ptr_type.ast.align_node != .none)
|
||||
.@"align"
|
||||
else if (ptr_type.allowzero_token != null)
|
||||
.@"allowzero"
|
||||
else
|
||||
.none;
|
||||
const final_qual_space: Space = if (tree.tokenTag(tree.firstToken(ptr_type.ast.child_type)) !=
|
||||
.multiline_string_literal_line) .space else .none;
|
||||
|
||||
if (ptr_type.allowzero_token) |allowzero_token| {
|
||||
try renderToken(r, allowzero_token, .space);
|
||||
const this_space: Space = if (final_qual == .@"allowzero") final_qual_space else .space;
|
||||
try renderToken(r, allowzero_token, this_space);
|
||||
}
|
||||
|
||||
if (ptr_type.ast.align_node.unwrap()) |align_node| {
|
||||
const this_space: Space = if (final_qual == .@"align") final_qual_space else .space;
|
||||
const align_first = tree.firstToken(align_node);
|
||||
try renderToken(r, align_first - 2, .none); // align
|
||||
try renderToken(r, align_first - 1, .none); // lparen
|
||||
|
|
@ -1015,26 +1037,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
|
|||
try renderExpression(r, bit_range_start, .none);
|
||||
try renderToken(r, tree.firstToken(bit_range_end) - 1, .none); // colon
|
||||
try renderExpression(r, bit_range_end, .none);
|
||||
try renderToken(r, tree.lastToken(bit_range_end) + 1, .space); // rparen
|
||||
try renderToken(r, tree.lastToken(bit_range_end) + 1, this_space); // rparen
|
||||
} else {
|
||||
try renderToken(r, tree.lastToken(align_node) + 1, .space); // rparen
|
||||
try renderToken(r, tree.lastToken(align_node) + 1, this_space); // rparen
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr_type.ast.addrspace_node.unwrap()) |addrspace_node| {
|
||||
const this_space: Space = if (final_qual == .@"addrspace") final_qual_space else .space;
|
||||
const addrspace_first = tree.firstToken(addrspace_node);
|
||||
try renderToken(r, addrspace_first - 2, .none); // addrspace
|
||||
try renderToken(r, addrspace_first - 1, .none); // lparen
|
||||
try renderExpression(r, addrspace_node, .none);
|
||||
try renderToken(r, tree.lastToken(addrspace_node) + 1, .space); // rparen
|
||||
try renderToken(r, tree.lastToken(addrspace_node) + 1, this_space); // rparen
|
||||
}
|
||||
|
||||
if (ptr_type.const_token) |const_token| {
|
||||
try renderToken(r, const_token, .space);
|
||||
const this_space: Space = if (final_qual == .@"const") final_qual_space else .space;
|
||||
try renderToken(r, const_token, this_space);
|
||||
}
|
||||
|
||||
if (ptr_type.volatile_token) |volatile_token| {
|
||||
try renderToken(r, volatile_token, .space);
|
||||
const this_space: Space = if (final_qual == .@"volatile") final_qual_space else unreachable;
|
||||
try renderToken(r, volatile_token, this_space);
|
||||
}
|
||||
|
||||
try renderExpression(r, ptr_type.ast.child_type, space);
|
||||
|
|
@ -1047,12 +1072,14 @@ fn renderSlice(
|
|||
space: Space,
|
||||
) Error!void {
|
||||
const tree = r.tree;
|
||||
const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
|
||||
const space_around_dots = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
|
||||
if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false;
|
||||
const after_start_space = if (after_start_space_bool) Space.space else Space.none;
|
||||
const after_dots_space = if (slice.ast.end != .none)
|
||||
after_start_space
|
||||
else if (slice.ast.sentinel != .none) Space.space else Space.none;
|
||||
const after_start_space: Space = if (space_around_dots) .space else .none;
|
||||
const before_sentinel_space: Space = if (slice.ast.sentinel != .none) .space else .none;
|
||||
const after_dots_space: Space = if (slice.ast.end != .none)
|
||||
if (space_around_dots) .maybe_space else .none
|
||||
else
|
||||
before_sentinel_space;
|
||||
|
||||
try renderExpression(r, slice.ast.sliced, .none);
|
||||
try renderToken(r, slice.ast.lbracket, .none); // lbracket
|
||||
|
|
@ -1062,8 +1089,7 @@ fn renderSlice(
|
|||
try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")
|
||||
|
||||
if (slice.ast.end.unwrap()) |end| {
|
||||
const after_end_space = if (slice.ast.sentinel != .none) Space.space else Space.none;
|
||||
try renderExpression(r, end, after_end_space);
|
||||
try renderExpression(r, end, before_sentinel_space);
|
||||
}
|
||||
|
||||
if (slice.ast.sentinel.unwrap()) |sentinel| {
|
||||
|
|
@ -1091,7 +1117,7 @@ fn renderAsmOutput(
|
|||
|
||||
if (tree.tokenTag(symbolic_name + 4) == .arrow) {
|
||||
const type_expr, const rparen = tree.nodeData(asm_output).opt_node_and_token;
|
||||
try renderToken(r, symbolic_name + 4, .space); // ->
|
||||
try renderToken(r, symbolic_name + 4, .maybe_space); // ->
|
||||
try renderExpression(r, type_expr.unwrap().?, Space.none);
|
||||
return renderToken(r, rparen, space);
|
||||
} else {
|
||||
|
|
@ -1172,33 +1198,38 @@ fn renderVarDeclWithoutFixups(
|
|||
|
||||
try renderToken(r, var_decl.ast.mut_token, .space); // var
|
||||
|
||||
if (var_decl.ast.type_node != .none or var_decl.ast.align_node != .none or
|
||||
var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
|
||||
var_decl.ast.init_node != .none)
|
||||
{
|
||||
const name_space = if (var_decl.ast.type_node == .none and
|
||||
(var_decl.ast.align_node != .none or
|
||||
var_decl.ast.addrspace_node != .none or
|
||||
var_decl.ast.section_node != .none or
|
||||
var_decl.ast.init_node != .none))
|
||||
Space.space
|
||||
else
|
||||
Space.none;
|
||||
const last_component: enum {
|
||||
value,
|
||||
@"linksection",
|
||||
@"addrspace",
|
||||
@"align",
|
||||
type,
|
||||
identifier,
|
||||
} = if (var_decl.ast.init_node != .none)
|
||||
.value
|
||||
else if (var_decl.ast.section_node != .none)
|
||||
.@"linksection"
|
||||
else if (var_decl.ast.addrspace_node != .none)
|
||||
.@"addrspace"
|
||||
else if (var_decl.ast.align_node != .none)
|
||||
.@"align"
|
||||
else if (var_decl.ast.type_node != .none)
|
||||
.type
|
||||
else
|
||||
.identifier;
|
||||
|
||||
try renderIdentifier(r, var_decl.ast.mut_token + 1, name_space, .preserve_when_shadowing); // name
|
||||
} else {
|
||||
return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
|
||||
if (last_component == .identifier) {
|
||||
return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing);
|
||||
}
|
||||
const after_ident_space: Space = if (var_decl.ast.type_node != .none) .none else .space;
|
||||
try renderIdentifier(r, var_decl.ast.mut_token + 1, after_ident_space, .preserve_when_shadowing);
|
||||
|
||||
if (var_decl.ast.type_node.unwrap()) |type_node| {
|
||||
try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :
|
||||
if (var_decl.ast.align_node != .none or var_decl.ast.addrspace_node != .none or
|
||||
var_decl.ast.section_node != .none or var_decl.ast.init_node != .none)
|
||||
{
|
||||
try renderExpression(r, type_node, .space);
|
||||
} else {
|
||||
try renderToken(r, var_decl.ast.mut_token + 2, .maybe_space); // :
|
||||
if (last_component == .type) {
|
||||
return renderExpression(r, type_node, space);
|
||||
}
|
||||
try renderExpression(r, type_node, .space);
|
||||
}
|
||||
|
||||
if (var_decl.ast.align_node.unwrap()) |align_node| {
|
||||
|
|
@ -1208,13 +1239,10 @@ fn renderVarDeclWithoutFixups(
|
|||
try renderToken(r, align_kw, Space.none); // align
|
||||
try renderToken(r, lparen, Space.none); // (
|
||||
try renderExpression(r, align_node, Space.none);
|
||||
if (var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
|
||||
var_decl.ast.init_node != .none)
|
||||
{
|
||||
try renderToken(r, rparen, .space); // )
|
||||
} else {
|
||||
if (last_component == .@"align") {
|
||||
return renderToken(r, rparen, space); // )
|
||||
}
|
||||
try renderToken(r, rparen, .space); // )
|
||||
}
|
||||
|
||||
if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
|
||||
|
|
@ -1224,12 +1252,10 @@ fn renderVarDeclWithoutFixups(
|
|||
try renderToken(r, addrspace_kw, Space.none); // addrspace
|
||||
try renderToken(r, lparen, Space.none); // (
|
||||
try renderExpression(r, addrspace_node, Space.none);
|
||||
if (var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) {
|
||||
try renderToken(r, rparen, .space); // )
|
||||
} else {
|
||||
try renderToken(r, rparen, .none); // )
|
||||
return renderToken(r, rparen + 1, Space.newline); // ;
|
||||
if (last_component == .@"addrspace") {
|
||||
return renderToken(r, rparen, space); // )
|
||||
}
|
||||
try renderToken(r, rparen, .space); // )
|
||||
}
|
||||
|
||||
if (var_decl.ast.section_node.unwrap()) |section_node| {
|
||||
|
|
@ -1239,17 +1265,19 @@ fn renderVarDeclWithoutFixups(
|
|||
try renderToken(r, section_kw, Space.none); // linksection
|
||||
try renderToken(r, lparen, Space.none); // (
|
||||
try renderExpression(r, section_node, Space.none);
|
||||
if (var_decl.ast.init_node != .none) {
|
||||
try renderToken(r, rparen, .space); // )
|
||||
} else {
|
||||
if (last_component == .@"linksection") {
|
||||
return renderToken(r, rparen, space); // )
|
||||
}
|
||||
try renderToken(r, rparen, .space); // )
|
||||
}
|
||||
|
||||
assert(last_component == .value);
|
||||
const init_node = var_decl.ast.init_node.unwrap().?;
|
||||
|
||||
const eq_token = tree.firstToken(init_node) - 1;
|
||||
const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
|
||||
const rhs_seperate_line = !tree.tokensOnSameLine(eq_token, eq_token + 1) or
|
||||
tree.tokenTag(eq_token + 1) == .multiline_string_literal_line;
|
||||
const eq_space: Space = if (rhs_seperate_line) .newline else .space;
|
||||
try ais.pushIndent(.after_equals);
|
||||
try renderToken(r, eq_token, eq_space); // =
|
||||
try renderExpression(r, init_node, space); // ;
|
||||
|
|
@ -1349,8 +1377,10 @@ fn renderThenElse(
|
|||
const tree = r.tree;
|
||||
const ais = r.ais;
|
||||
const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr));
|
||||
const then_expr_first_token = tree.firstToken(then_expr);
|
||||
const indent_then_expr = !then_expr_is_block and
|
||||
!tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));
|
||||
(!tree.tokensOnSameLine(last_prefix_token, then_expr_first_token) or
|
||||
tree.tokenTag(then_expr_first_token) == .multiline_string_literal_line);
|
||||
|
||||
if (indent_then_expr) try ais.pushIndent(.normal);
|
||||
|
||||
|
|
@ -1384,7 +1414,9 @@ fn renderThenElse(
|
|||
|
||||
const indent_else_expr = indent_then_expr and
|
||||
!nodeIsBlock(tree.nodeTag(else_expr)) and
|
||||
!nodeIsIfForWhileSwitch(tree.nodeTag(else_expr));
|
||||
!nodeIsIfForWhileSwitch(tree.nodeTag(else_expr)) or
|
||||
tree.tokenTag(tree.firstToken(else_expr)) ==
|
||||
.multiline_string_literal_line;
|
||||
if (indent_else_expr) {
|
||||
try ais.pushIndent(.normal);
|
||||
try renderToken(r, last_else_token, .newline);
|
||||
|
|
@ -1420,44 +1452,29 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
|
|||
try renderParamList(r, lparen, for_node.ast.inputs, .space);
|
||||
|
||||
var cur = for_node.payload_token;
|
||||
const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;
|
||||
if (tree.tokenTag(@intCast(pipe - 1)) == .comma) {
|
||||
const pipe = std.mem.indexOfScalarPos(Token.Tag, token_tags, cur, .pipe).?;
|
||||
const capture_trailing_comma = token_tags[@intCast(pipe - 1)] == .comma;
|
||||
|
||||
if (capture_trailing_comma)
|
||||
try ais.pushIndent(.normal);
|
||||
try renderToken(r, cur - 1, .newline); // |
|
||||
while (true) {
|
||||
if (tree.tokenTag(cur) == .asterisk) {
|
||||
try renderToken(r, cur, .none); // *
|
||||
cur += 1;
|
||||
}
|
||||
try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
|
||||
try renderToken(r, cur - 1, if (capture_trailing_comma) .newline else .none); // |
|
||||
while (true) {
|
||||
if (token_tags[cur] == .asterisk) {
|
||||
try renderToken(r, cur, .none); // *
|
||||
cur += 1;
|
||||
if (tree.tokenTag(cur) == .comma) {
|
||||
try renderToken(r, cur, .newline); // ,
|
||||
cur += 1;
|
||||
}
|
||||
if (tree.tokenTag(cur) == .pipe) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ais.popIndent();
|
||||
} else {
|
||||
try renderToken(r, cur - 1, .none); // |
|
||||
while (true) {
|
||||
if (tree.tokenTag(cur) == .asterisk) {
|
||||
try renderToken(r, cur, .none); // *
|
||||
cur += 1;
|
||||
}
|
||||
try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
|
||||
try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
|
||||
cur += 1;
|
||||
if (token_tags[cur] == .comma) {
|
||||
try renderToken(r, cur, if (capture_trailing_comma) .newline else .space); // ,
|
||||
cur += 1;
|
||||
if (tree.tokenTag(cur) == .comma) {
|
||||
try renderToken(r, cur, .space); // ,
|
||||
cur += 1;
|
||||
}
|
||||
if (tree.tokenTag(cur) == .pipe) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (token_tags[cur] == .pipe) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (capture_trailing_comma)
|
||||
ais.popIndent();
|
||||
|
||||
try renderThenElse(
|
||||
r,
|
||||
|
|
@ -1486,97 +1503,80 @@ fn renderContainerField(
|
|||
};
|
||||
|
||||
if (field.comptime_token) |t| {
|
||||
try renderToken(r, t, .space); // comptime
|
||||
try renderToken(r, t, .maybe_space); // comptime
|
||||
}
|
||||
if (field.ast.type_expr == .none and field.ast.value_expr == .none) {
|
||||
if (field.ast.align_expr.unwrap()) |align_expr| {
|
||||
try renderIdentifier(r, field.ast.main_token, .space, quote); // name
|
||||
const lparen_token = tree.firstToken(align_expr) - 1;
|
||||
const align_kw = lparen_token - 1;
|
||||
const rparen_token = tree.lastToken(align_expr) + 1;
|
||||
try renderToken(r, align_kw, .none); // align
|
||||
try renderToken(r, lparen_token, .none); // (
|
||||
try renderExpression(r, align_expr, .none); // alignment
|
||||
return renderToken(r, rparen_token, .space); // )
|
||||
|
||||
const last_component: enum {
|
||||
value,
|
||||
@"align",
|
||||
type,
|
||||
identifier,
|
||||
} = if (field.ast.value_expr != .none)
|
||||
.value
|
||||
else if (field.ast.align_expr != .none)
|
||||
.@"align"
|
||||
else if (field.ast.type_expr != .none)
|
||||
.type
|
||||
else if (!field.ast.tuple_like)
|
||||
.identifier
|
||||
else
|
||||
unreachable;
|
||||
|
||||
if (!field.ast.tuple_like) {
|
||||
if (last_component == .identifier) {
|
||||
return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
|
||||
}
|
||||
return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
|
||||
const this_space: Space = if (field.ast.type_expr != .none) .none else .space;
|
||||
try renderIdentifier(r, field.ast.main_token, this_space, quote); // name
|
||||
}
|
||||
if (field.ast.type_expr != .none and field.ast.value_expr == .none) {
|
||||
const type_expr = field.ast.type_expr.unwrap().?;
|
||||
|
||||
if (field.ast.type_expr.unwrap()) |type_expr| {
|
||||
if (!field.ast.tuple_like) {
|
||||
try renderIdentifier(r, field.ast.main_token, .none, quote); // name
|
||||
try renderToken(r, field.ast.main_token + 1, .space); // :
|
||||
try renderToken(r, field.ast.main_token + 1, .maybe_space); // :
|
||||
}
|
||||
|
||||
if (field.ast.align_expr.unwrap()) |align_expr| {
|
||||
try renderExpression(r, type_expr, .space); // type
|
||||
const align_token = tree.firstToken(align_expr) - 2;
|
||||
try renderToken(r, align_token, .none); // align
|
||||
try renderToken(r, align_token + 1, .none); // (
|
||||
try renderExpression(r, align_expr, .none); // alignment
|
||||
const rparen = tree.lastToken(align_expr) + 1;
|
||||
return renderTokenComma(r, rparen, space); // )
|
||||
} else {
|
||||
if (last_component == .type) {
|
||||
return renderExpressionComma(r, type_expr, space); // type
|
||||
}
|
||||
try renderExpression(r, type_expr, .space); // type
|
||||
}
|
||||
if (field.ast.type_expr == .none and field.ast.value_expr != .none) {
|
||||
const value_expr = field.ast.value_expr.unwrap().?;
|
||||
|
||||
try renderIdentifier(r, field.ast.main_token, .space, quote); // name
|
||||
if (field.ast.align_expr.unwrap()) |align_expr| {
|
||||
const lparen_token = tree.firstToken(align_expr) - 1;
|
||||
const align_kw = lparen_token - 1;
|
||||
const rparen_token = tree.lastToken(align_expr) + 1;
|
||||
try renderToken(r, align_kw, .none); // align
|
||||
try renderToken(r, lparen_token, .none); // (
|
||||
try renderExpression(r, align_expr, .none); // alignment
|
||||
try renderToken(r, rparen_token, .space); // )
|
||||
}
|
||||
try renderToken(r, field.ast.main_token + 1, .space); // =
|
||||
return renderExpressionComma(r, value_expr, space); // value
|
||||
}
|
||||
if (!field.ast.tuple_like) {
|
||||
try renderIdentifier(r, field.ast.main_token, .none, quote); // name
|
||||
try renderToken(r, field.ast.main_token + 1, .space); // :
|
||||
}
|
||||
|
||||
const type_expr = field.ast.type_expr.unwrap().?;
|
||||
const value_expr = field.ast.value_expr.unwrap().?;
|
||||
|
||||
try renderExpression(r, type_expr, .space); // type
|
||||
|
||||
if (field.ast.align_expr.unwrap()) |align_expr| {
|
||||
const lparen_token = tree.firstToken(align_expr) - 1;
|
||||
const align_kw = lparen_token - 1;
|
||||
const rparen_token = tree.lastToken(align_expr) + 1;
|
||||
try renderToken(r, align_kw, .none); // align
|
||||
try renderToken(r, lparen_token, .none); // (
|
||||
const align_token = tree.firstToken(align_expr) - 2;
|
||||
try renderToken(r, align_token, .none); // align
|
||||
try renderToken(r, align_token + 1, .none); // (
|
||||
try renderExpression(r, align_expr, .none); // alignment
|
||||
try renderToken(r, rparen_token, .space); // )
|
||||
}
|
||||
const eq_token = tree.firstToken(value_expr) - 1;
|
||||
const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
|
||||
|
||||
try ais.pushIndent(.after_equals);
|
||||
try renderToken(r, eq_token, eq_space); // =
|
||||
|
||||
if (eq_space == .space) {
|
||||
ais.popIndent();
|
||||
try renderExpressionComma(r, value_expr, space); // value
|
||||
return;
|
||||
const rparen = tree.lastToken(align_expr) + 1;
|
||||
if (last_component == .@"align") {
|
||||
return renderTokenComma(r, rparen, space); // )
|
||||
}
|
||||
try renderToken(r, rparen, .space);
|
||||
}
|
||||
|
||||
const maybe_comma = tree.lastToken(value_expr) + 1;
|
||||
if (field.ast.value_expr.unwrap()) |value_expr| {
|
||||
assert(last_component == .value);
|
||||
const eq_token = tree.firstToken(value_expr) - 1;
|
||||
const seperate_line = !tree.tokensOnSameLine(eq_token, eq_token + 1) or
|
||||
tree.tokenTag(eq_token + 1) == .multiline_string_literal_line;
|
||||
const eq_space: Space = if (seperate_line) .newline else .space;
|
||||
|
||||
if (tree.tokenTag(maybe_comma) == .comma) {
|
||||
try renderExpression(r, value_expr, .none); // value
|
||||
ais.popIndent();
|
||||
try renderToken(r, maybe_comma, .newline);
|
||||
} else {
|
||||
try renderExpression(r, value_expr, space); // value
|
||||
ais.popIndent();
|
||||
}
|
||||
try ais.pushIndent(.after_equals);
|
||||
try renderToken(r, eq_token, eq_space); // =
|
||||
if (eq_space == .space) {
|
||||
ais.popIndent();
|
||||
return renderExpressionComma(r, value_expr, space); // value
|
||||
}
|
||||
|
||||
const maybe_comma = tree.lastToken(value_expr) + 1;
|
||||
if (tree.tokenTag(maybe_comma) == .comma) {
|
||||
try renderExpression(r, value_expr, .none); // value
|
||||
ais.popIndent();
|
||||
try renderToken(r, maybe_comma, .newline);
|
||||
} else {
|
||||
try renderExpression(r, value_expr, space); // value
|
||||
ais.popIndent();
|
||||
}
|
||||
} else unreachable;
|
||||
}
|
||||
|
||||
fn renderBuiltinCall(
|
||||
|
|
@ -1590,14 +1590,9 @@ fn renderBuiltinCall(
|
|||
|
||||
try renderToken(r, builtin_token, .none); // @name
|
||||
|
||||
if (params.len == 0) {
|
||||
try renderToken(r, builtin_token + 1, .none); // (
|
||||
return renderToken(r, builtin_token + 2, space); // )
|
||||
}
|
||||
|
||||
if (r.fixups.rebase_imported_paths) |prefix| {
|
||||
const slice = tree.tokenSlice(builtin_token);
|
||||
if (mem.eql(u8, slice, "@import")) f: {
|
||||
if (params.len != 0 and mem.eql(u8, slice, "@import")) f: {
|
||||
const param = params[0];
|
||||
const str_lit_token = tree.nodeMainToken(param);
|
||||
assert(tree.tokenTag(str_lit_token) == .string_literal);
|
||||
|
|
@ -1616,45 +1611,7 @@ fn renderBuiltinCall(
|
|||
}
|
||||
}
|
||||
|
||||
const last_param = params[params.len - 1];
|
||||
const after_last_param_token = tree.lastToken(last_param) + 1;
|
||||
|
||||
if (tree.tokenTag(after_last_param_token) != .comma) {
|
||||
// Render all on one line, no trailing comma.
|
||||
try renderToken(r, builtin_token + 1, .none); // (
|
||||
|
||||
for (params, 0..) |param_node, i| {
|
||||
const first_param_token = tree.firstToken(param_node);
|
||||
if (tree.tokenTag(first_param_token) == .multiline_string_literal_line or
|
||||
hasSameLineComment(tree, first_param_token - 1))
|
||||
{
|
||||
try ais.pushIndent(.normal);
|
||||
try renderExpression(r, param_node, .none);
|
||||
ais.popIndent();
|
||||
} else {
|
||||
try renderExpression(r, param_node, .none);
|
||||
}
|
||||
|
||||
if (i + 1 < params.len) {
|
||||
const comma_token = tree.lastToken(param_node) + 1;
|
||||
try renderToken(r, comma_token, .space); // ,
|
||||
}
|
||||
}
|
||||
return renderToken(r, after_last_param_token, space); // )
|
||||
} else {
|
||||
// Render one param per line.
|
||||
try ais.pushIndent(.normal);
|
||||
try renderToken(r, builtin_token + 1, Space.newline); // (
|
||||
|
||||
for (params) |param_node| {
|
||||
try ais.pushSpace(.comma);
|
||||
try renderExpression(r, param_node, .comma);
|
||||
ais.popSpace();
|
||||
}
|
||||
ais.popIndent();
|
||||
|
||||
return renderToken(r, after_last_param_token + 1, space); // )
|
||||
}
|
||||
return renderParamList(r, builtin_token + 1, params, space);
|
||||
}
|
||||
|
||||
fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
|
||||
|
|
@ -1746,7 +1703,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
|
|||
},
|
||||
.r_paren => break,
|
||||
.comma => {
|
||||
try renderToken(r, last_param_token, .space); // ,
|
||||
try renderToken(r, last_param_token, .maybe_space); // ,
|
||||
continue;
|
||||
},
|
||||
else => {}, // Parameter type without a name.
|
||||
|
|
@ -1756,7 +1713,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
|
|||
{
|
||||
try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
|
||||
last_param_token = last_param_token + 1;
|
||||
try renderToken(r, last_param_token, .space); // :
|
||||
try renderToken(r, last_param_token, .maybe_space); // :
|
||||
last_param_token += 1;
|
||||
}
|
||||
if (tree.tokenTag(last_param_token) == .keyword_anytype) {
|
||||
|
|
@ -1825,7 +1782,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
|
|||
ais.popIndent();
|
||||
}
|
||||
|
||||
try renderToken(r, rparen, .space); // )
|
||||
try renderToken(r, rparen, .maybe_space); // )
|
||||
|
||||
if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
|
||||
const align_lparen = tree.firstToken(align_expr) - 1;
|
||||
|
|
@ -1834,7 +1791,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
|
|||
try renderToken(r, align_lparen - 1, .none); // align
|
||||
try renderToken(r, align_lparen, .none); // (
|
||||
try renderExpression(r, align_expr, .none);
|
||||
try renderToken(r, align_rparen, .space); // )
|
||||
try renderToken(r, align_rparen, .maybe_space); // )
|
||||
}
|
||||
|
||||
if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
|
||||
|
|
@ -1844,7 +1801,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
|
|||
try renderToken(r, align_lparen - 1, .none); // addrspace
|
||||
try renderToken(r, align_lparen, .none); // (
|
||||
try renderExpression(r, addrspace_expr, .none);
|
||||
try renderToken(r, align_rparen, .space); // )
|
||||
try renderToken(r, align_rparen, .maybe_space); // )
|
||||
}
|
||||
|
||||
if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
|
||||
|
|
@ -1854,7 +1811,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
|
|||
try renderToken(r, section_lparen - 1, .none); // section
|
||||
try renderToken(r, section_lparen, .none); // (
|
||||
try renderExpression(r, section_expr, .none);
|
||||
try renderToken(r, section_rparen, .space); // )
|
||||
try renderToken(r, section_rparen, .maybe_space); // )
|
||||
}
|
||||
|
||||
if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
|
||||
|
|
@ -1868,7 +1825,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
|
|||
try renderToken(r, callconv_lparen - 1, .none); // callconv
|
||||
try renderToken(r, callconv_lparen, .none); // (
|
||||
try renderExpression(r, callconv_expr, .none);
|
||||
try renderToken(r, callconv_rparen, .space); // )
|
||||
try renderToken(r, callconv_rparen, .maybe_space); // )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1893,7 +1850,7 @@ fn renderSwitchCase(
|
|||
|
||||
// render inline keyword
|
||||
if (switch_case.inline_token) |some| {
|
||||
try renderToken(r, some, .space);
|
||||
try renderToken(r, some, .maybe_space);
|
||||
}
|
||||
|
||||
// Render everything before the arrow
|
||||
|
|
@ -1907,33 +1864,26 @@ fn renderSwitchCase(
|
|||
} else {
|
||||
// Render on one line
|
||||
for (switch_case.ast.values) |value_expr| {
|
||||
try renderExpression(r, value_expr, .comma_space);
|
||||
try renderExpression(r, value_expr, .comma_maybe_space);
|
||||
}
|
||||
}
|
||||
|
||||
// Render the arrow and everything after it
|
||||
const pre_target_space = if (tree.nodeTag(switch_case.ast.target_expr) == .multiline_string_literal)
|
||||
// Newline gets inserted when rendering the target expr.
|
||||
Space.none
|
||||
else
|
||||
Space.space;
|
||||
const after_arrow_space: Space = if (switch_case.payload_token == null) pre_target_space else .space;
|
||||
try renderToken(r, switch_case.ast.arrow_token, after_arrow_space); // =>
|
||||
try renderToken(r, switch_case.ast.arrow_token, .maybe_space); // =>
|
||||
|
||||
if (switch_case.payload_token) |payload_token| {
|
||||
try renderToken(r, payload_token - 1, .none); // pipe
|
||||
const ident = payload_token + @intFromBool(tree.tokenTag(payload_token) == .asterisk);
|
||||
if (tree.tokenTag(payload_token) == .asterisk) {
|
||||
var ident = payload_token;
|
||||
if (tree.tokenTag(ident) == .asterisk) {
|
||||
try renderToken(r, payload_token, .none); // asterisk
|
||||
ident += 1;
|
||||
}
|
||||
try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
|
||||
if (tree.tokenTag(ident + 1) == .comma) {
|
||||
try renderToken(r, ident + 1, .space); // ,
|
||||
try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier
|
||||
try renderToken(r, ident + 3, pre_target_space); // pipe
|
||||
} else {
|
||||
try renderToken(r, ident + 1, pre_target_space); // pipe
|
||||
ident += 2;
|
||||
try renderToken(r, ident - 1, .space); // ,
|
||||
try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
|
||||
}
|
||||
try renderToken(r, ident + 1, .maybe_space); // pipe
|
||||
}
|
||||
|
||||
try renderExpression(r, switch_case.ast.target_expr, space);
|
||||
|
|
@ -2021,26 +1971,13 @@ fn renderStructInit(
|
|||
try ais.pushIndent(.normal);
|
||||
try renderToken(r, struct_init.ast.lbrace, .newline);
|
||||
|
||||
try renderToken(r, struct_init.ast.lbrace + 1, .none); // .
|
||||
try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
|
||||
// Don't output a space after the = if expression is a multiline string,
|
||||
// since then it will start on the next line.
|
||||
const field_node = struct_init.ast.fields[0];
|
||||
const expr = tree.nodeTag(field_node);
|
||||
var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;
|
||||
try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
|
||||
|
||||
try ais.pushSpace(.comma);
|
||||
try renderExpressionFixup(r, field_node, .comma);
|
||||
ais.popSpace();
|
||||
|
||||
for (struct_init.ast.fields[1..]) |field_init| {
|
||||
for (0.., struct_init.ast.fields) |i, field_init| {
|
||||
const init_token = tree.firstToken(field_init);
|
||||
try renderExtraNewlineToken(r, init_token - 3);
|
||||
if (i != 0)
|
||||
try renderExtraNewlineToken(r, init_token - 3);
|
||||
try renderToken(r, init_token - 3, .none); // .
|
||||
try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
|
||||
space_after_equal = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space;
|
||||
try renderToken(r, init_token - 1, space_after_equal); // =
|
||||
try renderToken(r, init_token - 1, .maybe_space); // =
|
||||
|
||||
try ais.pushSpace(.comma);
|
||||
try renderExpressionFixup(r, field_init, .comma);
|
||||
|
|
@ -2056,8 +1993,7 @@ fn renderStructInit(
|
|||
const init_token = tree.firstToken(field_init);
|
||||
try renderToken(r, init_token - 3, .none); // .
|
||||
try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
|
||||
const space_after_equal: Space = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space;
|
||||
try renderToken(r, init_token - 1, space_after_equal); // =
|
||||
try renderToken(r, init_token - 1, .maybe_space); // =
|
||||
try renderExpressionFixup(r, field_init, .comma_space);
|
||||
}
|
||||
}
|
||||
|
|
@ -2475,6 +2411,9 @@ fn renderAsmLegacy(
|
|||
|
||||
try ais.forcePushIndent(.normal);
|
||||
try renderExpression(r, asm_node.ast.template, .newline);
|
||||
ais.forceLastIndent(); // Might have been dedented by a multiline string literal
|
||||
assert(ais.current_line_empty);
|
||||
|
||||
ais.setIndentDelta(asm_indent_delta);
|
||||
const colon1 = tree.lastToken(asm_node.ast.template) + 1;
|
||||
|
||||
|
|
@ -2618,7 +2557,7 @@ fn renderAsm(
|
|||
const first_clobber = tree.firstToken(clobbers);
|
||||
try renderToken(r, first_clobber - 3, .none);
|
||||
try renderToken(r, first_clobber - 2, .none);
|
||||
try renderToken(r, first_clobber - 1, .space);
|
||||
try renderToken(r, first_clobber - 1, .maybe_space);
|
||||
try renderExpression(r, clobbers, .none);
|
||||
ais.popIndent();
|
||||
return renderToken(r, asm_node.ast.rparen, space); // rparen
|
||||
|
|
@ -2632,6 +2571,9 @@ fn renderAsm(
|
|||
|
||||
try ais.forcePushIndent(.normal);
|
||||
try renderExpression(r, asm_node.ast.template, .newline);
|
||||
ais.forceLastIndent(); // Might have been dedented by a multiline string literal
|
||||
assert(ais.current_line_empty);
|
||||
|
||||
ais.setIndentDelta(asm_indent_delta);
|
||||
const colon1 = tree.lastToken(asm_node.ast.template) + 1;
|
||||
|
||||
|
|
@ -2709,9 +2651,10 @@ fn renderAsm(
|
|||
unreachable;
|
||||
};
|
||||
|
||||
try renderToken(r, colon3, .space); // :
|
||||
try renderToken(r, colon3, .maybe_space); // :
|
||||
const clobbers = asm_node.ast.clobbers.unwrap().?;
|
||||
try renderExpression(r, clobbers, .none);
|
||||
ais.forceLastIndent(); // Might have been dedented by a multiline string literal
|
||||
ais.setIndentDelta(indent_delta);
|
||||
ais.popIndent();
|
||||
return renderToken(r, asm_node.ast.rparen, space); // rparen
|
||||
|
|
@ -2737,7 +2680,7 @@ fn renderParamList(
|
|||
|
||||
if (params.len == 0) {
|
||||
try ais.pushIndent(.normal);
|
||||
try renderToken(r, lparen, .none);
|
||||
try renderToken(r, lparen, .none); // (
|
||||
ais.popIndent();
|
||||
return renderToken(r, lparen + 1, space); // )
|
||||
}
|
||||
|
|
@ -2772,10 +2715,7 @@ fn renderParamList(
|
|||
|
||||
if (i + 1 < params.len) {
|
||||
const comma = tree.lastToken(param_node) + 1;
|
||||
const next_multiline_string =
|
||||
tree.tokenTag(tree.firstToken(params[i + 1])) == .multiline_string_literal_line;
|
||||
const comma_space: Space = if (next_multiline_string) .none else .space;
|
||||
try renderToken(r, comma, comma_space);
|
||||
try renderToken(r, comma, .maybe_space);
|
||||
}
|
||||
}
|
||||
ais.popIndent();
|
||||
|
|
@ -2837,6 +2777,13 @@ const Space = enum {
|
|||
/// Additionally consume the next token if it is a semicolon.
|
||||
/// In either case, a newline will be inserted afterwards.
|
||||
semicolon,
|
||||
/// If the next token is not a multiline string literal, this acts as .space,
|
||||
/// otherwise this acts as .none.
|
||||
maybe_space,
|
||||
/// Additionally consume the next token if it is a comma.
|
||||
/// In either case, a space will be inserted afterwards
|
||||
/// if the following token is not a multiline string literal.
|
||||
comma_maybe_space,
|
||||
/// Skip rendering whitespace and comments. If this is used, the caller
|
||||
/// *must* handle whitespace and comments manually.
|
||||
skip,
|
||||
|
|
@ -2901,6 +2848,16 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
|
|||
try ais.insertNewline();
|
||||
},
|
||||
|
||||
.maybe_space => if (!comment and next_token_tag != .multiline_string_literal_line) {
|
||||
try ais.writeByte(' ');
|
||||
},
|
||||
|
||||
.comma_maybe_space => if (next_token_tag == .comma) {
|
||||
try renderToken(r, token_index + 1, .maybe_space);
|
||||
} else if (!comment) {
|
||||
try ais.writeByte(' ');
|
||||
},
|
||||
|
||||
.skip => unreachable,
|
||||
}
|
||||
}
|
||||
|
|
@ -2909,9 +2866,9 @@ fn renderOnlySpace(r: *Render, space: Space) Error!void {
|
|||
const ais = r.ais;
|
||||
switch (space) {
|
||||
.none => {},
|
||||
.space => try ais.writeByte(' '),
|
||||
.space, .maybe_space => try ais.writeByte(' '),
|
||||
.newline => try ais.insertNewline(),
|
||||
.comma => try ais.writeAll(",\n"),
|
||||
.comma, .comma_maybe_space => try ais.writeAll(",\n"),
|
||||
.comma_space => try ais.writeAll(", "),
|
||||
.semicolon => try ais.writeAll(";\n"),
|
||||
.skip => unreachable,
|
||||
|
|
@ -3659,11 +3616,19 @@ const AutoIndentingStream = struct {
|
|||
|
||||
pub fn popIndent(ais: *AutoIndentingStream) void {
|
||||
if (ais.indent_stack.pop().?.realized) {
|
||||
assert(ais.indent_count > 0);
|
||||
ais.indent_count -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Forces the last pushed indent to be realized
|
||||
pub fn forceLastIndent(ais: *AutoIndentingStream) void {
|
||||
const top = &ais.indent_stack.items[ais.indent_stack.items.len - 1];
|
||||
if (!top.realized) {
|
||||
top.realized = true;
|
||||
ais.indent_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indentStackEmpty(ais: *AutoIndentingStream) bool {
|
||||
return ais.indent_stack.items.len == 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2606,6 +2606,19 @@ test "zig fmt: first line comment in struct initializer" {
|
|||
);
|
||||
}
|
||||
|
||||
test "zig fmt: multiline string literals in struct initializer" {
|
||||
try testTransform(
|
||||
\\const a = .{ .a = \\
|
||||
\\+ 1};
|
||||
\\
|
||||
,
|
||||
\\const a = .{ .a =
|
||||
\\ \\
|
||||
\\+ 1 };
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: doc comments before struct field" {
|
||||
try testCanonical(
|
||||
\\pub const Allocator = struct {
|
||||
|
|
@ -4079,6 +4092,18 @@ test "zig fmt: multiline string in array" {
|
|||
\\}
|
||||
\\
|
||||
);
|
||||
|
||||
try testTransform(
|
||||
\\const a = .{ k, \\
|
||||
\\};
|
||||
\\
|
||||
,
|
||||
\\const a = .{
|
||||
\\ k,
|
||||
\\ \\
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: if type expr" {
|
||||
|
|
@ -6095,6 +6120,294 @@ test "zig fmt: extern addrspace in struct" {
|
|||
);
|
||||
}
|
||||
|
||||
test "zig fmt: whitespace with multiline strings" {
|
||||
try testCanonical(
|
||||
\\const a = .{
|
||||
\\ .b =
|
||||
\\ \\
|
||||
\\ ++ "",
|
||||
\\};
|
||||
\\const b = switch (a) {
|
||||
\\ a =>
|
||||
\\ \\
|
||||
\\ ++ "",
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
|
||||
try testTransform(
|
||||
\\test {
|
||||
\\ a = \\
|
||||
\\ ;
|
||||
\\ b = \\
|
||||
\\ ();
|
||||
\\ c = x ++ \\
|
||||
\\ ;
|
||||
\\ d = x catch \\
|
||||
\\ ;
|
||||
\\ comptime \\
|
||||
\\ , \\
|
||||
\\ , \\
|
||||
\\ = \\
|
||||
\\ ;
|
||||
\\ e = if (x) \\
|
||||
\\ else y;
|
||||
\\ f = if (x) y else
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ comptime \\
|
||||
\\ ;
|
||||
\\ errdefer \\
|
||||
\\ ;
|
||||
\\ try \\
|
||||
\\ ;
|
||||
\\ return \\
|
||||
\\ ;
|
||||
\\ const a = asm (\\
|
||||
\\ ++ "": [a] "" (-> \\
|
||||
\\ ) :: \\
|
||||
\\ );
|
||||
\\ const a2 = asm ("" ::: \\
|
||||
\\ );
|
||||
\\ const b = x[1 + 1 .. \\
|
||||
\\ ];
|
||||
\\}
|
||||
\\/// tuple type
|
||||
\\comptime \\
|
||||
\\,
|
||||
\\a: \\
|
||||
\\align(\\
|
||||
\\)
|
||||
\\= \\
|
||||
\\,
|
||||
\\const A = .{
|
||||
\\ *volatile \\
|
||||
\\ ,
|
||||
\\ *const \\
|
||||
\\ ,
|
||||
\\ *addrspace( \\
|
||||
\\ ) \\
|
||||
\\ ,
|
||||
\\ *align( \\
|
||||
\\ : \\
|
||||
\\ : \\
|
||||
\\ ) \\
|
||||
\\ ,
|
||||
\\ *allowzero \\
|
||||
\\ ,
|
||||
\\ *\\
|
||||
\\ ,
|
||||
\\ **\\
|
||||
\\ ,
|
||||
\\ [*]\\
|
||||
\\ ,
|
||||
\\ [*: \\
|
||||
\\ ]\\
|
||||
\\ ,
|
||||
\\ [*c]\\
|
||||
\\ ,
|
||||
\\ []\\
|
||||
\\ ,
|
||||
\\ [: \\
|
||||
\\ ]\\
|
||||
\\ ,
|
||||
\\ *addrspace(a) align(a) \\
|
||||
\\ ,
|
||||
\\};
|
||||
\\const a = blk: {
|
||||
\\ break \\
|
||||
\\ ;
|
||||
\\ break :blk \\
|
||||
\\ ;
|
||||
\\ continue \\
|
||||
\\ ;
|
||||
\\ continue :blk \\
|
||||
\\ ;
|
||||
\\};
|
||||
\\const b = a(a, \\
|
||||
\\++ "");
|
||||
\\const c = @a(a, \\
|
||||
\\++ "");
|
||||
\\extern fn a(T,\\
|
||||
\\) \\
|
||||
\\;
|
||||
\\extern fn b(a: \\
|
||||
\\) align(a) callconv(a) \\
|
||||
\\;
|
||||
\\const d = switch (a) { \\
|
||||
\\ , 1,
|
||||
\\ \\
|
||||
\\ => {},
|
||||
\\ inline \\
|
||||
\\ => {},
|
||||
\\};
|
||||
\\
|
||||
,
|
||||
\\test {
|
||||
\\ a =
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ b =
|
||||
\\ \\
|
||||
\\ ();
|
||||
\\ c = x ++
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ d = x catch
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ comptime
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ \\
|
||||
\\ =
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ e = if (x)
|
||||
\\ \\
|
||||
\\ else
|
||||
\\ y;
|
||||
\\ f = if (x) y else
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ comptime
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ errdefer
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ try
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ return
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ const a = asm (
|
||||
\\ \\
|
||||
\\ ++ ""
|
||||
\\ : [a] "" (->
|
||||
\\ \\
|
||||
\\ ),
|
||||
\\ :
|
||||
\\ :
|
||||
\\ \\
|
||||
\\ );
|
||||
\\ const a2 = asm ("" :::
|
||||
\\ \\
|
||||
\\ );
|
||||
\\ const b = x[1 + 1 ..
|
||||
\\ \\
|
||||
\\ ];
|
||||
\\}
|
||||
\\/// tuple type
|
||||
\\comptime
|
||||
\\\\
|
||||
\\,
|
||||
\\a:
|
||||
\\\\
|
||||
\\align(
|
||||
\\\\
|
||||
\\) =
|
||||
\\ \\
|
||||
\\,
|
||||
\\const A = .{
|
||||
\\ *volatile
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ *const
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ *addrspace(
|
||||
\\ \\
|
||||
\\ )
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ *align(
|
||||
\\ \\
|
||||
\\ :
|
||||
\\ \\
|
||||
\\ :
|
||||
\\ \\
|
||||
\\ )
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ *allowzero
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ *
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ **
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ [*]
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ [*:
|
||||
\\ \\
|
||||
\\ ]
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ [*c]
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ []
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ [:
|
||||
\\ \\
|
||||
\\ ]
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\ *align(a) addrspace(a)
|
||||
\\ \\
|
||||
\\ ,
|
||||
\\};
|
||||
\\const a = blk: {
|
||||
\\ break
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ break :blk
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ continue
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\ continue :blk
|
||||
\\ \\
|
||||
\\ ;
|
||||
\\};
|
||||
\\const b = a(a,
|
||||
\\ \\
|
||||
\\++ "");
|
||||
\\const c = @a(a,
|
||||
\\ \\
|
||||
\\++ "");
|
||||
\\extern fn a(T,
|
||||
\\\\
|
||||
\\)
|
||||
\\\\
|
||||
\\;
|
||||
\\extern fn b(a:
|
||||
\\\\
|
||||
\\) align(a) callconv(a)
|
||||
\\\\
|
||||
\\;
|
||||
\\const d = switch (a) {
|
||||
\\ \\
|
||||
\\ , 1,
|
||||
\\ \\
|
||||
\\ => {},
|
||||
\\ inline
|
||||
\\ \\
|
||||
\\ => {},
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "recovery: top level" {
|
||||
try testError(
|
||||
\\test "" {inline}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue