| ... | ... | @@ -24,51 +24,21 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: ast.Tree) Error!void { |
| 24 | 24 | const ais = &auto_indenting_stream; |
| 25 | 25 | |
| 26 | 26 | // Render all the line comments at the beginning of the file. |
| 27 | | const src_start: usize = if (mem.startsWith(u8, tree.source, "\xEF\xBB\xBF")) 3 else 0; |
| 28 | 27 | const comment_end_loc: usize = tree.tokens.items(.start)[0]; |
| 29 | | _ = try renderCommentsAndNewlines(ais, tree, src_start, comment_end_loc); |
| 28 | _ = try renderComments(ais, tree, 0, comment_end_loc); |
| 30 | 29 | |
| 31 | | for (tree.rootDecls()) |decl| { |
| 32 | | try renderMember(ais, tree, decl, .newline); |
| 33 | | } |
| 30 | try renderMembers(ais, tree, tree.rootDecls()); |
| 34 | 31 | } |
| 35 | 32 | |
| 36 | | /// Assumes that start is the first byte past the previous token and |
| 37 | | /// that end is the last byte before the next token. |
| 38 | | fn renderCommentsAndNewlines(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!bool { |
| 39 | | var index: usize = start; |
| 40 | | while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| { |
| 41 | | const comment_start = index + offset; |
| 42 | | const newline = comment_start + |
| 43 | | mem.indexOfScalar(u8, tree.source[comment_start..end], '\n').?; |
| 44 | | const untrimmed_comment = tree.source[comment_start..newline]; |
| 45 | | const trimmed_comment = mem.trimRight(u8, untrimmed_comment, " \r\t"); |
| 46 | | |
| 47 | | // Leave up to one empty line before the comment |
| 48 | | if (index == start and mem.containsAtLeast(u8, tree.source[index..comment_start], 2, "\n")) { |
| 49 | | try ais.insertNewline(); |
| 50 | | try ais.insertNewline(); |
| 51 | | } else if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) { |
| 52 | | // Respect the newline directly before the comment. This allows an |
| 53 | | // empty line between comments |
| 54 | | try ais.insertNewline(); |
| 55 | | } else if (index == start and start != 0) { |
| 56 | | // If the comment is on the same line as the token before it, |
| 57 | | // prefix it with a single space |
| 58 | | try ais.writer().writeByte(' '); |
| 59 | | } |
| 60 | | |
| 61 | | try ais.writer().print("{s}\n", .{trimmed_comment}); |
| 62 | | index = newline + 1; |
| 63 | | } |
| 64 | | |
| 65 | | // Leave up to one empty line if present in the source |
| 66 | | if (index > start) index -= 1; |
| 67 | | if (end != tree.source.len and mem.containsAtLeast(u8, tree.source[index..end], 2, "\n")) { |
| 68 | | try ais.insertNewline(); |
| 33 | /// Render all members in the given slice, keeping empty lines where appropriate |
| 34 | fn renderMembers(ais: *Ais, tree: ast.Tree, members: []const ast.Node.Index) Error!void { |
| 35 | if (members.len == 0) return; |
| 36 | //try renderExtraNewline(ais, tree, members[0]); |
| 37 | try renderMember(ais, tree, members[0], .newline); |
| 38 | for (members[1..]) |member| { |
| 39 | try renderExtraNewline(ais, tree, member); |
| 40 | try renderMember(ais, tree, member, .newline); |
| 69 | 41 | } |
| 70 | | |
| 71 | | return index != start; |
| 72 | 42 | } |
| 73 | 43 | |
| 74 | 44 | fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void { |
| ... | ... | @@ -157,6 +127,16 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E |
| 157 | 127 | } |
| 158 | 128 | } |
| 159 | 129 | |
| 130 | /// Render all expressions in the slice, keeping empty lines where appropriate |
| 131 | fn renderExpressions(ais: *Ais, tree: ast.Tree, expressions: []const ast.Node.Index, space: Space) Error!void { |
| 132 | if (expressions.len == 0) return; |
| 133 | try renderExpression(ais, tree, expressions[0], space); |
| 134 | for (expressions[1..]) |expression| { |
| 135 | try renderExtraNewline(ais, tree, expression); |
| 136 | try renderExpression(ais, tree, expression, space); |
| 137 | } |
| 138 | } |
| 139 | |
| 160 | 140 | fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void { |
| 161 | 141 | const token_tags = tree.tokens.items(.tag); |
| 162 | 142 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -501,7 +481,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 501 | 481 | .tagged_union_enum_tag_comma, |
| 502 | 482 | => return renderContainerDecl(ais, tree, tree.taggedUnionEnumTag(node), space), |
| 503 | 483 | |
| 504 | | // TODO: handle comments properly |
| 505 | 484 | .error_set_decl => { |
| 506 | 485 | const error_token = main_tokens[node]; |
| 507 | 486 | const lbrace = error_token + 1; |
| ... | ... | @@ -521,10 +500,11 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 521 | 500 | return renderToken(ais, tree, rbrace, space); |
| 522 | 501 | } else if (token_tags[rbrace - 1] == .comma) { |
| 523 | 502 | // There is a trailing comma so render each member on a new line. |
| 503 | ais.pushIndentNextLine(); |
| 524 | 504 | try renderToken(ais, tree, lbrace, .newline); |
| 525 | | ais.pushIndent(); |
| 526 | 505 | var i = lbrace + 1; |
| 527 | 506 | while (i < rbrace) : (i += 1) { |
| 507 | if (i > lbrace + 1) try renderExtraNewlineToken(ais, tree, i); |
| 528 | 508 | switch (token_tags[i]) { |
| 529 | 509 | .doc_comment => try renderToken(ais, tree, i, .newline), |
| 530 | 510 | .identifier => try renderToken(ais, tree, i, .comma), |
| ... | ... | @@ -603,14 +583,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 603 | 583 | try renderExpression(ais, tree, condition, .none); // condtion expression |
| 604 | 584 | try renderToken(ais, tree, rparen, .space); // rparen |
| 605 | 585 | |
| 586 | ais.pushIndentNextLine(); |
| 606 | 587 | if (cases.len == 0) { |
| 607 | 588 | try renderToken(ais, tree, rparen + 1, .none); // lbrace |
| 608 | | return renderToken(ais, tree, rparen + 2, space); // rbrace |
| 609 | | } |
| 610 | | ais.pushIndentNextLine(); |
| 611 | | try renderToken(ais, tree, rparen + 1, .newline); // lbrace |
| 612 | | for (cases) |case| { |
| 613 | | try renderExpression(ais, tree, case, .comma); |
| 589 | } else { |
| 590 | try renderToken(ais, tree, rparen + 1, .newline); // lbrace |
| 591 | try renderExpressions(ais, tree, cases, .comma); |
| 614 | 592 | } |
| 615 | 593 | ais.popIndent(); |
| 616 | 594 | return renderToken(ais, tree, tree.lastToken(node), space); // rbrace |
| ... | ... | @@ -1439,9 +1417,7 @@ fn renderSwitchCase( |
| 1439 | 1417 | try renderExpression(ais, tree, switch_case.ast.values[0], .space); |
| 1440 | 1418 | } else if (trailing_comma) { |
| 1441 | 1419 | // Render each value on a new line |
| 1442 | | for (switch_case.ast.values) |value_expr| { |
| 1443 | | try renderExpression(ais, tree, value_expr, .comma); |
| 1444 | | } |
| 1420 | try renderExpressions(ais, tree, switch_case.ast.values, .comma); |
| 1445 | 1421 | } else { |
| 1446 | 1422 | // Render on one line |
| 1447 | 1423 | for (switch_case.ast.values) |value_expr| { |
| ... | ... | @@ -1486,22 +1462,20 @@ fn renderBlock( |
| 1486 | 1462 | try renderToken(ais, tree, lbrace - 1, .space); |
| 1487 | 1463 | } |
| 1488 | 1464 | |
| 1465 | ais.pushIndentNextLine(); |
| 1489 | 1466 | if (statements.len == 0) { |
| 1490 | | ais.pushIndentNextLine(); |
| 1491 | 1467 | try renderToken(ais, tree, lbrace, .none); |
| 1492 | | ais.popIndent(); |
| 1493 | | return renderToken(ais, tree, lbrace + 1, space); // rbrace |
| 1494 | | } |
| 1495 | | |
| 1496 | | ais.pushIndentNextLine(); |
| 1497 | | try renderToken(ais, tree, lbrace, .newline); |
| 1498 | | for (statements) |stmt, i| { |
| 1499 | | switch (node_tags[stmt]) { |
| 1500 | | .global_var_decl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)), |
| 1501 | | .local_var_decl => try renderVarDecl(ais, tree, tree.localVarDecl(stmt)), |
| 1502 | | .simple_var_decl => try renderVarDecl(ais, tree, tree.simpleVarDecl(stmt)), |
| 1503 | | .aligned_var_decl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)), |
| 1504 | | else => try renderExpression(ais, tree, stmt, .semicolon), |
| 1468 | } else { |
| 1469 | try renderToken(ais, tree, lbrace, .newline); |
| 1470 | for (statements) |stmt, i| { |
| 1471 | if (i != 0) try renderExtraNewline(ais, tree, stmt); |
| 1472 | switch (node_tags[stmt]) { |
| 1473 | .global_var_decl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)), |
| 1474 | .local_var_decl => try renderVarDecl(ais, tree, tree.localVarDecl(stmt)), |
| 1475 | .simple_var_decl => try renderVarDecl(ais, tree, tree.simpleVarDecl(stmt)), |
| 1476 | .aligned_var_decl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)), |
| 1477 | else => try renderExpression(ais, tree, stmt, .semicolon), |
| 1478 | } |
| 1505 | 1479 | } |
| 1506 | 1480 | } |
| 1507 | 1481 | ais.popIndent(); |
| ... | ... | @@ -1530,11 +1504,17 @@ fn renderStructInit( |
| 1530 | 1504 | const last_field_token = tree.lastToken(last_field); |
| 1531 | 1505 | if (token_tags[last_field_token + 1] == .comma) { |
| 1532 | 1506 | // Render one field init per line. |
| 1533 | | ais.pushIndent(); |
| 1507 | ais.pushIndentNextLine(); |
| 1534 | 1508 | try renderToken(ais, tree, struct_init.ast.lbrace, .newline); |
| 1535 | 1509 | |
| 1536 | | for (struct_init.ast.fields) |field_init| { |
| 1510 | try renderToken(ais, tree, struct_init.ast.lbrace + 1, .none); // . |
| 1511 | try renderToken(ais, tree, struct_init.ast.lbrace + 2, .space); // name |
| 1512 | try renderToken(ais, tree, struct_init.ast.lbrace + 3, .space); // = |
| 1513 | try renderExpression(ais, tree, struct_init.ast.fields[0], .comma); |
| 1514 | |
| 1515 | for (struct_init.ast.fields[1..]) |field_init| { |
| 1537 | 1516 | const init_token = tree.firstToken(field_init); |
| 1517 | try renderExtraNewlineToken(ais, tree, init_token - 3); |
| 1538 | 1518 | try renderToken(ais, tree, init_token - 3, .none); // . |
| 1539 | 1519 | try renderToken(ais, tree, init_token - 2, .space); // name |
| 1540 | 1520 | try renderToken(ais, tree, init_token - 1, .space); // = |
| ... | ... | @@ -1573,20 +1553,18 @@ fn renderArrayInit( |
| 1573 | 1553 | try renderExpression(ais, tree, array_init.ast.type_expr, .none); // T |
| 1574 | 1554 | } |
| 1575 | 1555 | if (array_init.ast.elements.len == 0) { |
| 1556 | ais.pushIndentNextLine(); |
| 1576 | 1557 | try renderToken(ais, tree, array_init.ast.lbrace, .none); // lbrace |
| 1558 | ais.popIndent(); |
| 1577 | 1559 | return renderToken(ais, tree, array_init.ast.lbrace + 1, space); // rbrace |
| 1578 | 1560 | } |
| 1579 | 1561 | const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1]; |
| 1580 | 1562 | const last_elem_token = tree.lastToken(last_elem); |
| 1581 | 1563 | if (token_tags[last_elem_token + 1] == .comma) { |
| 1582 | 1564 | // Render one element per line. |
| 1583 | | ais.pushIndent(); |
| 1565 | ais.pushIndentNextLine(); |
| 1584 | 1566 | try renderToken(ais, tree, array_init.ast.lbrace, .newline); |
| 1585 | | |
| 1586 | | for (array_init.ast.elements) |elem| { |
| 1587 | | try renderExpression(ais, tree, elem, .comma); |
| 1588 | | } |
| 1589 | | |
| 1567 | try renderExpressions(ais, tree, array_init.ast.elements, .comma); |
| 1590 | 1568 | ais.popIndent(); |
| 1591 | 1569 | return renderToken(ais, tree, last_elem_token + 2, space); // rbrace |
| 1592 | 1570 | } else { |
| ... | ... | @@ -1679,11 +1657,9 @@ fn renderContainerDecl( |
| 1679 | 1657 | } |
| 1680 | 1658 | |
| 1681 | 1659 | // One member per line. |
| 1682 | | ais.pushIndent(); |
| 1660 | ais.pushIndentNextLine(); |
| 1683 | 1661 | try renderToken(ais, tree, lbrace, .newline); // lbrace |
| 1684 | | for (container_decl.ast.members) |member| { |
| 1685 | | try renderMember(ais, tree, member, .newline); |
| 1686 | | } |
| 1662 | try renderMembers(ais, tree, container_decl.ast.members); |
| 1687 | 1663 | ais.popIndent(); |
| 1688 | 1664 | |
| 1689 | 1665 | return renderToken(ais, tree, rbrace, space); // rbrace |
| ... | ... | @@ -1745,6 +1721,7 @@ fn renderAsm( |
| 1745 | 1721 | |
| 1746 | 1722 | const comma = tree.firstToken(next_asm_output) - 1; |
| 1747 | 1723 | try renderToken(ais, tree, comma, .newline); // , |
| 1724 | try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output)); |
| 1748 | 1725 | } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) { |
| 1749 | 1726 | try renderAsmOutput(ais, tree, asm_output, .newline); |
| 1750 | 1727 | ais.popIndent(); |
| ... | ... | @@ -1776,6 +1753,7 @@ fn renderAsm( |
| 1776 | 1753 | |
| 1777 | 1754 | const first_token = tree.firstToken(next_asm_input); |
| 1778 | 1755 | try renderToken(ais, tree, first_token - 1, .newline); // , |
| 1756 | try renderExtraNewlineToken(ais, tree, first_token); |
| 1779 | 1757 | } else if (asm_node.first_clobber == null) { |
| 1780 | 1758 | try renderAsmInput(ais, tree, asm_input, .newline); |
| 1781 | 1759 | ais.popIndent(); |
| ... | ... | @@ -1834,7 +1812,9 @@ fn renderCall( |
| 1834 | 1812 | const lparen = call.ast.lparen; |
| 1835 | 1813 | const params = call.ast.params; |
| 1836 | 1814 | if (params.len == 0) { |
| 1815 | ais.pushIndentNextLine(); |
| 1837 | 1816 | try renderToken(ais, tree, lparen, .none); |
| 1817 | ais.popIndent(); |
| 1838 | 1818 | return renderToken(ais, tree, lparen + 1, space); // ) |
| 1839 | 1819 | } |
| 1840 | 1820 | |
| ... | ... | @@ -1856,6 +1836,8 @@ fn renderCall( |
| 1856 | 1836 | try renderToken(ais, tree, comma, Space.newline); // , |
| 1857 | 1837 | |
| 1858 | 1838 | if (is_multiline_string) ais.pushIndent(); |
| 1839 | |
| 1840 | try renderExtraNewline(ais, tree, params[i + 1]); |
| 1859 | 1841 | } else { |
| 1860 | 1842 | try renderExpression(ais, tree, param_node, Space.comma); |
| 1861 | 1843 | } |
| ... | ... | @@ -1928,44 +1910,100 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp |
| 1928 | 1910 | const lexeme = tree.tokenSlice(token_index); |
| 1929 | 1911 | try ais.writer().writeAll(lexeme); |
| 1930 | 1912 | |
| 1913 | if (space == .no_comment) return; |
| 1914 | |
| 1915 | const comment = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]); |
| 1931 | 1916 | switch (space) { |
| 1932 | | .no_comment => {}, |
| 1933 | | .none => _ = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]), |
| 1934 | | .comma => { |
| 1935 | | const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]); |
| 1936 | | if (token_tags[token_index + 1] == .comma) { |
| 1937 | | return renderToken(ais, tree, token_index + 1, .newline); |
| 1938 | | } else if (!comment) { |
| 1939 | | return ais.insertNewline(); |
| 1940 | | } |
| 1941 | | }, |
| 1942 | | .comma_space => { |
| 1943 | | const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]); |
| 1944 | | if (token_tags[token_index + 1] == .comma) { |
| 1945 | | return renderToken(ais, tree, token_index + 1, .space); |
| 1946 | | } else if (!comment) { |
| 1947 | | return ais.writer().writeByte(' '); |
| 1948 | | } |
| 1917 | .none => {}, |
| 1918 | .space => if (!comment) try ais.writer().writeByte(' '), |
| 1919 | .newline => if (!comment) try ais.insertNewline(), |
| 1920 | |
| 1921 | .comma => if (token_tags[token_index + 1] == .comma) { |
| 1922 | try renderToken(ais, tree, token_index + 1, .newline); |
| 1923 | } else if (!comment) { |
| 1924 | try ais.insertNewline(); |
| 1949 | 1925 | }, |
| 1950 | | .semicolon => { |
| 1951 | | const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]); |
| 1952 | | if (token_tags[token_index + 1] == .semicolon) { |
| 1953 | | return renderToken(ais, tree, token_index + 1, .newline); |
| 1954 | | } else if (!comment) { |
| 1955 | | return ais.insertNewline(); |
| 1956 | | } |
| 1926 | |
| 1927 | .comma_space => if (token_tags[token_index + 1] == .comma) { |
| 1928 | try renderToken(ais, tree, token_index + 1, .space); |
| 1929 | } else if (!comment) { |
| 1930 | try ais.writer().writeByte(' '); |
| 1957 | 1931 | }, |
| 1958 | | .space => { |
| 1959 | | const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]); |
| 1960 | | if (!comment) { |
| 1961 | | return ais.writer().writeByte(' '); |
| 1962 | | } |
| 1932 | |
| 1933 | .semicolon => if (token_tags[token_index + 1] == .semicolon) { |
| 1934 | try renderToken(ais, tree, token_index + 1, .newline); |
| 1935 | } else if (!comment) { |
| 1936 | try ais.insertNewline(); |
| 1963 | 1937 | }, |
| 1964 | | .newline => { |
| 1965 | | if (!try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1])) { |
| 1938 | |
| 1939 | .no_comment => unreachable, |
| 1940 | } |
| 1941 | } |
| 1942 | |
| 1943 | /// Assumes that start is the first byte past the previous token and |
| 1944 | /// that end is the last byte before the next token. |
| 1945 | fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!bool { |
| 1946 | var index: usize = start; |
| 1947 | while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| { |
| 1948 | const comment_start = index + offset; |
| 1949 | const newline = comment_start + |
| 1950 | mem.indexOfScalar(u8, tree.source[comment_start..end], '\n').?; |
| 1951 | const untrimmed_comment = tree.source[comment_start..newline]; |
| 1952 | const trimmed_comment = mem.trimRight(u8, untrimmed_comment, &std.ascii.spaces); |
| 1953 | |
| 1954 | // Don't leave any whitespace at the start of the file |
| 1955 | if (index != 0) { |
| 1956 | if (index == start and mem.containsAtLeast(u8, tree.source[index..comment_start], 2, "\n")) { |
| 1957 | // Leave up to one empty line before the first comment |
| 1958 | try ais.insertNewline(); |
| 1966 | 1959 | try ais.insertNewline(); |
| 1960 | } else if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) { |
| 1961 | // Respect the newline directly before the comment. |
| 1962 | // Note: This allows an empty line between comments |
| 1963 | try ais.insertNewline(); |
| 1964 | } else if (index == start) { |
| 1965 | // Otherwise if the first comment is on the same line as |
| 1966 | // the token before it, prefix it with a single space. |
| 1967 | try ais.writer().writeByte(' '); |
| 1967 | 1968 | } |
| 1968 | | }, |
| 1969 | } |
| 1970 | |
| 1971 | try ais.writer().print("{s}\n", .{trimmed_comment}); |
| 1972 | index = newline + 1; |
| 1973 | } |
| 1974 | |
| 1975 | if (index != start and mem.containsAtLeast(u8, tree.source[index - 1 .. end], 2, "\n")) { |
| 1976 | try ais.insertNewline(); |
| 1977 | } |
| 1978 | |
| 1979 | return index != start; |
| 1980 | } |
| 1981 | |
| 1982 | fn renderExtraNewline(ais: *Ais, tree: ast.Tree, node: ast.Node.Index) Error!void { |
| 1983 | return renderExtraNewlineToken(ais, tree, tree.firstToken(node)); |
| 1984 | } |
| 1985 | |
| 1986 | /// Check if there is an empty line immediately before the given token. If so, render it. |
| 1987 | fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex) Error!void { |
| 1988 | const token_starts = tree.tokens.items(.start); |
| 1989 | const token_start = token_starts[token_index]; |
| 1990 | if (token_start == 0) return; |
| 1991 | const prev_token_end = if (token_index == 0) |
| 1992 | 0 |
| 1993 | else |
| 1994 | token_starts[token_index - 1] + tree.tokenSlice(token_index - 1).len; |
| 1995 | |
| 1996 | // If there is a comment present, it will handle the empty line |
| 1997 | if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return; |
| 1998 | |
| 1999 | // Iterate backwards to the end of the previous token, stopping if a |
| 2000 | // non-whitespace character is encountered or two newlines have been found. |
| 2001 | var i = token_start - 1; |
| 2002 | var newlines: u2 = 0; |
| 2003 | while (std.ascii.isSpace(tree.source[i])) : (i -= 1) { |
| 2004 | if (tree.source[i] == '\n') newlines += 1; |
| 2005 | if (newlines == 2) return ais.insertNewline(); |
| 2006 | if (i == prev_token_end) break; |
| 1969 | 2007 | } |
| 1970 | 2008 | } |
| 1971 | 2009 | |
| ... | ... | @@ -1983,19 +2021,15 @@ fn renderDocComments(ais: *Ais, tree: ast.Tree, end_token: ast.TokenIndex) Error |
| 1983 | 2021 | tok += 1; |
| 1984 | 2022 | } |
| 1985 | 2023 | const first_tok = tok; |
| 1986 | | if (tok == end_token) return; |
| 2024 | if (first_tok == end_token) return; |
| 2025 | try renderExtraNewlineToken(ais, tree, first_tok); |
| 1987 | 2026 | |
| 1988 | | while (true) : (tok += 1) { |
| 1989 | | switch (token_tags[tok]) { |
| 1990 | | .doc_comment => { |
| 1991 | | if (first_tok < end_token) { |
| 1992 | | try renderToken(ais, tree, tok, .newline); |
| 1993 | | } else { |
| 1994 | | try renderToken(ais, tree, tok, .no_comment); |
| 1995 | | try ais.insertNewline(); |
| 1996 | | } |
| 1997 | | }, |
| 1998 | | else => break, |
| 2027 | while (token_tags[tok] == .doc_comment) : (tok += 1) { |
| 2028 | if (first_tok < end_token) { |
| 2029 | try renderToken(ais, tree, tok, .newline); |
| 2030 | } else { |
| 2031 | try renderToken(ais, tree, tok, .no_comment); |
| 2032 | try ais.insertNewline(); |
| 1999 | 2033 | } |
| 2000 | 2034 | } |
| 2001 | 2035 | } |