| ... | ... | @@ -369,23 +369,19 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 369 | 369 | while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline); |
| 370 | 370 | |
| 371 | 371 | // dedent the next thing that comes after a multiline string literal |
| 372 | | if (!ais.indentStackEmpty()) { |
| 372 | if (!ais.indentStackEmpty() and |
| 373 | token_tags[i] != .colon and |
| 374 | ((token_tags[i] != .semicolon and token_tags[i] != .comma) or |
| 375 | ais.lastSpaceModeIndent() < ais.currentIndent())) |
| 376 | { |
| 373 | 377 | ais.popIndent(); |
| 374 | 378 | try ais.pushIndent(.normal); |
| 375 | 379 | } |
| 376 | 380 | |
| 377 | 381 | switch (space) { |
| 378 | 382 | .none, .space, .newline, .skip => {}, |
| 379 | | .semicolon => if (token_tags[i] == .semicolon) { |
| 380 | | ais.enableSpaceMode(.semicolon); |
| 381 | | try renderToken(r, i, .newline); |
| 382 | | ais.disableSpaceMode(); |
| 383 | | }, |
| 384 | | .comma => if (token_tags[i] == .comma) { |
| 385 | | ais.enableSpaceMode(.comma); |
| 386 | | try renderToken(r, i, .newline); |
| 387 | | ais.disableSpaceMode(); |
| 388 | | }, |
| 383 | .semicolon => if (token_tags[i] == .semicolon) try renderTokenOverrideSpaceMode(r, i, .newline, .semicolon), |
| 384 | .comma => if (token_tags[i] == .comma) try renderTokenOverrideSpaceMode(r, i, .newline, .comma), |
| 389 | 385 | .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space), |
| 390 | 386 | } |
| 391 | 387 | }, |
| ... | ... | @@ -476,7 +472,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 476 | 472 | const main_token = main_tokens[node]; |
| 477 | 473 | const field_access = datas[node]; |
| 478 | 474 | |
| 479 | | try ais.pushIndent(.normal); |
| 475 | try ais.pushIndent(.field_access); |
| 480 | 476 | try renderExpression(r, field_access.lhs, .none); |
| 481 | 477 | |
| 482 | 478 | // Allow a line break between the lhs and the dot if the lhs and rhs |
| ... | ... | @@ -740,8 +736,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 740 | 736 | }, |
| 741 | 737 | |
| 742 | 738 | .grouped_expression => { |
| 743 | | try renderToken(r, main_tokens[node], .none); // lparen |
| 744 | 739 | try ais.pushIndent(.normal); |
| 740 | try renderToken(r, main_tokens[node], .none); // lparen |
| 745 | 741 | try renderExpression(r, datas[node].lhs, .none); |
| 746 | 742 | ais.popIndent(); |
| 747 | 743 | return renderToken(r, datas[node].rhs, space); // rparen |
| ... | ... | @@ -2444,7 +2440,7 @@ fn renderAsm( |
| 2444 | 2440 | } |
| 2445 | 2441 | |
| 2446 | 2442 | if (asm_node.ast.items.len == 0) { |
| 2447 | | try ais.pushIndent(.normal); |
| 2443 | try ais.forcePushIndent(.normal); |
| 2448 | 2444 | if (asm_node.first_clobber) |first_clobber| { |
| 2449 | 2445 | // asm ("foo" ::: "a", "b") |
| 2450 | 2446 | // asm ("foo" ::: "a", "b",) |
| ... | ... | @@ -2482,7 +2478,7 @@ fn renderAsm( |
| 2482 | 2478 | } |
| 2483 | 2479 | } |
| 2484 | 2480 | |
| 2485 | | try ais.pushIndent(.normal); |
| 2481 | try ais.forcePushIndent(.normal); |
| 2486 | 2482 | try renderExpression(r, asm_node.ast.template, .newline); |
| 2487 | 2483 | ais.setIndentDelta(asm_indent_delta); |
| 2488 | 2484 | const colon1 = tree.lastToken(asm_node.ast.template) + 1; |
| ... | ... | @@ -2493,7 +2489,7 @@ fn renderAsm( |
| 2493 | 2489 | } else colon2: { |
| 2494 | 2490 | try renderToken(r, colon1, .space); // : |
| 2495 | 2491 | |
| 2496 | | try ais.pushIndent(.normal); |
| 2492 | try ais.forcePushIndent(.normal); |
| 2497 | 2493 | for (asm_node.outputs, 0..) |asm_output, i| { |
| 2498 | 2494 | if (i + 1 < asm_node.outputs.len) { |
| 2499 | 2495 | const next_asm_output = asm_node.outputs[i + 1]; |
| ... | ... | @@ -2529,7 +2525,7 @@ fn renderAsm( |
| 2529 | 2525 | break :colon3 colon2 + 1; |
| 2530 | 2526 | } else colon3: { |
| 2531 | 2527 | try renderToken(r, colon2, .space); // : |
| 2532 | | try ais.pushIndent(.normal); |
| 2528 | try ais.forcePushIndent(.normal); |
| 2533 | 2529 | for (asm_node.inputs, 0..) |asm_input, i| { |
| 2534 | 2530 | if (i + 1 < asm_node.inputs.len) { |
| 2535 | 2531 | const next_asm_input = asm_node.inputs[i + 1]; |
| ... | ... | @@ -2568,16 +2564,16 @@ fn renderAsm( |
| 2568 | 2564 | switch (token_tags[tok_i + 1]) { |
| 2569 | 2565 | .r_paren => { |
| 2570 | 2566 | ais.setIndentDelta(indent_delta); |
| 2571 | | ais.popIndent(); |
| 2572 | 2567 | try renderToken(r, tok_i, .newline); |
| 2568 | ais.popIndent(); |
| 2573 | 2569 | return renderToken(r, tok_i + 1, space); |
| 2574 | 2570 | }, |
| 2575 | 2571 | .comma => { |
| 2576 | 2572 | switch (token_tags[tok_i + 2]) { |
| 2577 | 2573 | .r_paren => { |
| 2578 | 2574 | ais.setIndentDelta(indent_delta); |
| 2579 | | ais.popIndent(); |
| 2580 | 2575 | try renderToken(r, tok_i, .newline); |
| 2576 | ais.popIndent(); |
| 2581 | 2577 | return renderToken(r, tok_i + 2, space); |
| 2582 | 2578 | }, |
| 2583 | 2579 | else => { |
| ... | ... | @@ -2644,19 +2640,10 @@ fn renderParamList( |
| 2644 | 2640 | return renderToken(r, after_last_param_tok + 1, space); // ) |
| 2645 | 2641 | } |
| 2646 | 2642 | |
| 2643 | try ais.pushIndent(.normal); |
| 2647 | 2644 | try renderToken(r, lparen, .none); // ( |
| 2648 | | |
| 2649 | 2645 | for (params, 0..) |param_node, i| { |
| 2650 | | const first_param_token = tree.firstToken(param_node); |
| 2651 | | if (token_tags[first_param_token] == .multiline_string_literal_line or |
| 2652 | | hasSameLineComment(tree, first_param_token - 1)) |
| 2653 | | { |
| 2654 | | try ais.pushIndent(.normal); |
| 2655 | | try renderExpression(r, param_node, .none); |
| 2656 | | ais.popIndent(); |
| 2657 | | } else { |
| 2658 | | try renderExpression(r, param_node, .none); |
| 2659 | | } |
| 2646 | try renderExpression(r, param_node, .none); |
| 2660 | 2647 | |
| 2661 | 2648 | if (i + 1 < params.len) { |
| 2662 | 2649 | const comma = tree.lastToken(param_node) + 1; |
| ... | ... | @@ -2666,7 +2653,7 @@ fn renderParamList( |
| 2666 | 2653 | try renderToken(r, comma, comma_space); |
| 2667 | 2654 | } |
| 2668 | 2655 | } |
| 2669 | | |
| 2656 | ais.popIndent(); |
| 2670 | 2657 | return renderToken(r, after_last_param_tok, space); // ) |
| 2671 | 2658 | } |
| 2672 | 2659 | |
| ... | ... | @@ -2741,6 +2728,16 @@ fn renderToken(r: *Render, token_index: Ast.TokenIndex, space: Space) Error!void |
| 2741 | 2728 | try renderSpace(r, token_index, lexeme.len, space); |
| 2742 | 2729 | } |
| 2743 | 2730 | |
| 2731 | fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space: Space, override_space: Space) Error!void { |
| 2732 | const tree = r.tree; |
| 2733 | const ais = r.ais; |
| 2734 | const lexeme = tokenSliceForRender(tree, token_index); |
| 2735 | try ais.writer().writeAll(lexeme); |
| 2736 | ais.enableSpaceMode(override_space); |
| 2737 | defer ais.disableSpaceMode(); |
| 2738 | try renderSpace(r, token_index, lexeme.len, space); |
| 2739 | } |
| 2740 | |
| 2744 | 2741 | fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void { |
| 2745 | 2742 | const tree = r.tree; |
| 2746 | 2743 | const ais = r.ais; |
| ... | ... | @@ -3315,6 +3312,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3315 | 3312 | normal, |
| 3316 | 3313 | after_equals, |
| 3317 | 3314 | binop, |
| 3315 | field_access, |
| 3318 | 3316 | }; |
| 3319 | 3317 | const StackElem = struct { |
| 3320 | 3318 | indent_type: IndentType, |
| ... | ... | @@ -3404,20 +3402,26 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3404 | 3402 | self.current_line_empty = true; |
| 3405 | 3403 | if (self.disable_indent_committing > 0) return; |
| 3406 | 3404 | if (self.indent_stack.items.len > 0) { |
| 3407 | | // Only realize last pushed indent |
| 3408 | | if (!self.indent_stack.items[self.indent_stack.items.len - 1].realized) { |
| 3409 | | if (self.indent_stack.items.len >= 2 and |
| 3410 | | self.indent_stack.items[self.indent_stack.items.len - 2].indent_type == .after_equals and |
| 3411 | | self.indent_stack.items[self.indent_stack.items.len - 2].realized and |
| 3412 | | self.indent_stack.items[self.indent_stack.items.len - 1].indent_type == .binop) |
| 3413 | | { |
| 3414 | | // collapse one level of indentation in binop after equals sign |
| 3415 | | return; |
| 3416 | | } |
| 3405 | var to_realize = self.indent_stack.items.len - 1; |
| 3406 | |
| 3407 | if (self.indent_stack.items.len >= 2 and |
| 3408 | self.indent_stack.items[to_realize - 1].indent_type == .after_equals and |
| 3409 | self.indent_stack.items[to_realize - 1].realized and |
| 3410 | self.indent_stack.items[to_realize].indent_type == .binop) |
| 3411 | { |
| 3412 | // collapse one level of indentation in binop after equals sign |
| 3413 | return; |
| 3414 | } |
| 3417 | 3415 | |
| 3418 | | self.indent_stack.items[self.indent_stack.items.len - 1].realized = true; |
| 3419 | | self.indent_count += 1; |
| 3416 | if (self.indent_stack.items[to_realize].indent_type == .field_access) { |
| 3417 | // only realize topmost field_access in a chain |
| 3418 | while (to_realize > 0 and self.indent_stack.items[to_realize - 1].indent_type == .field_access) |
| 3419 | to_realize -= 1; |
| 3420 | 3420 | } |
| 3421 | |
| 3422 | if (self.indent_stack.items[to_realize].realized) return; |
| 3423 | self.indent_stack.items[to_realize].realized = true; |
| 3424 | self.indent_count += 1; |
| 3421 | 3425 | } |
| 3422 | 3426 | } |
| 3423 | 3427 | |
| ... | ... | @@ -3441,10 +3445,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3441 | 3445 | pub fn enableSpaceMode(self: *Self, space: Space) void { |
| 3442 | 3446 | if (self.space_stack.items.len == 0) return; |
| 3443 | 3447 | const curr = self.space_stack.getLast(); |
| 3444 | | if (curr.space != space) { |
| 3445 | | return; |
| 3446 | | } |
| 3447 | | assert(curr.space == space); |
| 3448 | if (curr.space != space) return; |
| 3448 | 3449 | self.space_mode = curr.indent_count; |
| 3449 | 3450 | } |
| 3450 | 3451 | |
| ... | ... | @@ -3452,6 +3453,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3452 | 3453 | self.space_mode = null; |
| 3453 | 3454 | } |
| 3454 | 3455 | |
| 3456 | pub fn lastSpaceModeIndent(self: *Self) usize { |
| 3457 | if (self.space_stack.items.len == 0) return 0; |
| 3458 | return self.space_stack.getLast().indent_count * self.indent_delta; |
| 3459 | } |
| 3460 | |
| 3455 | 3461 | /// Insert a newline unless the current line is blank |
| 3456 | 3462 | pub fn maybeInsertNewline(self: *Self) WriteError!void { |
| 3457 | 3463 | if (!self.current_line_empty) |
| ... | ... | @@ -3465,6 +3471,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3465 | 3471 | try self.indent_stack.append(.{ .indent_type = indent_type, .realized = false }); |
| 3466 | 3472 | } |
| 3467 | 3473 | |
| 3474 | pub fn forcePushIndent(self: *Self, indent_type: IndentType) !void { |
| 3475 | try self.indent_stack.append(.{ .indent_type = indent_type, .realized = true }); |
| 3476 | self.indent_count += 1; |
| 3477 | } |
| 3478 | |
| 3468 | 3479 | pub fn popIndent(self: *Self) void { |
| 3469 | 3480 | if (self.indent_stack.pop().realized) { |
| 3470 | 3481 | assert(self.indent_count > 0); |