| ... | @@ -40,27 +40,28 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast) Error!void { | ... | @@ -40,27 +40,28 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast) Error!void { |
| 40 | /// Render all members in the given slice, keeping empty lines where appropriate | 40 | /// Render all members in the given slice, keeping empty lines where appropriate |
| 41 | fn renderMembers(gpa: Allocator, ais: *Ais, tree: Ast, members: []const Ast.Node.Index) Error!void { | 41 | fn renderMembers(gpa: Allocator, ais: *Ais, tree: Ast, members: []const Ast.Node.Index) Error!void { |
| 42 | if (members.len == 0) return; | 42 | if (members.len == 0) return; |
| 43 | var is_tuple = true; | 43 | const container: Container = for (members) |member| { |
| 44 | for (members) |member| { | 44 | if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other; |
| 45 | const container_field = tree.fullContainerField(member) orelse continue; | 45 | } else .tuple; |
| 46 | if (!container_field.ast.tuple_like) { | 46 | try renderMember(gpa, ais, tree, container, members[0], .newline); |
| 47 | is_tuple = false; | | |
| 48 | break; | | |
| 49 | } | | |
| 50 | } | | |
| 51 | try renderMember(gpa, ais, tree, members[0], is_tuple, .newline); | | |
| 52 | for (members[1..]) |member| { | 47 | for (members[1..]) |member| { |
| 53 | try renderExtraNewline(ais, tree, member); | 48 | try renderExtraNewline(ais, tree, member); |
| 54 | try renderMember(gpa, ais, tree, member, is_tuple, .newline); | 49 | try renderMember(gpa, ais, tree, container, member, .newline); |
| 55 | } | 50 | } |
| 56 | } | 51 | } |
| 57 | | 52 | |
| | 53 | const Container = enum { |
| | 54 | @"enum", |
| | 55 | tuple, |
| | 56 | other, |
| | 57 | }; |
| | 58 | |
| 58 | fn renderMember( | 59 | fn renderMember( |
| 59 | gpa: Allocator, | 60 | gpa: Allocator, |
| 60 | ais: *Ais, | 61 | ais: *Ais, |
| 61 | tree: Ast, | 62 | tree: Ast, |
| | 63 | container: Container, |
| 62 | decl: Ast.Node.Index, | 64 | decl: Ast.Node.Index, |
| 63 | is_tuple: bool, | | |
| 64 | space: Space, | 65 | space: Space, |
| 65 | ) Error!void { | 66 | ) Error!void { |
| 66 | const token_tags = tree.tokens.items(.tag); | 67 | const token_tags = tree.tokens.items(.tag); |
| ... | @@ -180,7 +181,7 @@ fn renderMember( | ... | @@ -180,7 +181,7 @@ fn renderMember( |
| 180 | .container_field_init, | 181 | .container_field_init, |
| 181 | .container_field_align, | 182 | .container_field_align, |
| 182 | .container_field, | 183 | .container_field, |
| 183 | => return renderContainerField(gpa, ais, tree, tree.fullContainerField(decl).?, is_tuple, space), | 184 | => return renderContainerField(gpa, ais, tree, container, tree.fullContainerField(decl).?, space), |
| 184 | | 185 | |
| 185 | .@"comptime" => return renderExpression(gpa, ais, tree, decl, space), | 186 | .@"comptime" => return renderExpression(gpa, ais, tree, decl, space), |
| 186 | | 187 | |
| ... | @@ -1279,19 +1280,23 @@ fn renderContainerField( | ... | @@ -1279,19 +1280,23 @@ fn renderContainerField( |
| 1279 | gpa: Allocator, | 1280 | gpa: Allocator, |
| 1280 | ais: *Ais, | 1281 | ais: *Ais, |
| 1281 | tree: Ast, | 1282 | tree: Ast, |
| | 1283 | container: Container, |
| 1282 | field_param: Ast.full.ContainerField, | 1284 | field_param: Ast.full.ContainerField, |
| 1283 | is_tuple: bool, | | |
| 1284 | space: Space, | 1285 | space: Space, |
| 1285 | ) Error!void { | 1286 | ) Error!void { |
| 1286 | var field = field_param; | 1287 | var field = field_param; |
| 1287 | if (!is_tuple) field.convertToNonTupleLike(tree.nodes); | 1288 | if (container != .tuple) field.convertToNonTupleLike(tree.nodes); |
| | 1289 | const quote: QuoteBehavior = switch (container) { |
| | 1290 | .@"enum" => .eagerly_unquote_except_underscore, |
| | 1291 | .tuple, .other => .eagerly_unquote, |
| | 1292 | }; |
| 1288 | | 1293 | |
| 1289 | if (field.comptime_token) |t| { | 1294 | if (field.comptime_token) |t| { |
| 1290 | try renderToken(ais, tree, t, .space); // comptime | 1295 | try renderToken(ais, tree, t, .space); // comptime |
| 1291 | } | 1296 | } |
| 1292 | if (field.ast.type_expr == 0 and field.ast.value_expr == 0) { | 1297 | if (field.ast.type_expr == 0 and field.ast.value_expr == 0) { |
| 1293 | if (field.ast.align_expr != 0) { | 1298 | if (field.ast.align_expr != 0) { |
| 1294 | try renderIdentifier(ais, tree, field.ast.main_token, .space, .eagerly_unquote); // name | 1299 | try renderIdentifier(ais, tree, field.ast.main_token, .space, quote); // name |
| 1295 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | 1300 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; |
| 1296 | const align_kw = lparen_token - 1; | 1301 | const align_kw = lparen_token - 1; |
| 1297 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; | 1302 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; |
| ... | @@ -1300,11 +1305,11 @@ fn renderContainerField( | ... | @@ -1300,11 +1305,11 @@ fn renderContainerField( |
| 1300 | try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment | 1305 | try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment |
| 1301 | return renderToken(ais, tree, rparen_token, .space); // ) | 1306 | return renderToken(ais, tree, rparen_token, .space); // ) |
| 1302 | } | 1307 | } |
| 1303 | return renderIdentifierComma(ais, tree, field.ast.main_token, space, .eagerly_unquote); // name | 1308 | return renderIdentifierComma(ais, tree, field.ast.main_token, space, quote); // name |
| 1304 | } | 1309 | } |
| 1305 | if (field.ast.type_expr != 0 and field.ast.value_expr == 0) { | 1310 | if (field.ast.type_expr != 0 and field.ast.value_expr == 0) { |
| 1306 | if (!field.ast.tuple_like) { | 1311 | if (!field.ast.tuple_like) { |
| 1307 | try renderIdentifier(ais, tree, field.ast.main_token, .none, .eagerly_unquote); // name | 1312 | try renderIdentifier(ais, tree, field.ast.main_token, .none, quote); // name |
| 1308 | try renderToken(ais, tree, field.ast.main_token + 1, .space); // : | 1313 | try renderToken(ais, tree, field.ast.main_token + 1, .space); // : |
| 1309 | } | 1314 | } |
| 1310 | | 1315 | |
| ... | @@ -1321,7 +1326,7 @@ fn renderContainerField( | ... | @@ -1321,7 +1326,7 @@ fn renderContainerField( |
| 1321 | } | 1326 | } |
| 1322 | } | 1327 | } |
| 1323 | if (field.ast.type_expr == 0 and field.ast.value_expr != 0) { | 1328 | if (field.ast.type_expr == 0 and field.ast.value_expr != 0) { |
| 1324 | try renderIdentifier(ais, tree, field.ast.main_token, .space, .eagerly_unquote); // name | 1329 | try renderIdentifier(ais, tree, field.ast.main_token, .space, quote); // name |
| 1325 | if (field.ast.align_expr != 0) { | 1330 | if (field.ast.align_expr != 0) { |
| 1326 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | 1331 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; |
| 1327 | const align_kw = lparen_token - 1; | 1332 | const align_kw = lparen_token - 1; |
| ... | @@ -1335,7 +1340,7 @@ fn renderContainerField( | ... | @@ -1335,7 +1340,7 @@ fn renderContainerField( |
| 1335 | return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value | 1340 | return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value |
| 1336 | } | 1341 | } |
| 1337 | if (!field.ast.tuple_like) { | 1342 | if (!field.ast.tuple_like) { |
| 1338 | try renderIdentifier(ais, tree, field.ast.main_token, .none, .eagerly_unquote); // name | 1343 | try renderIdentifier(ais, tree, field.ast.main_token, .none, quote); // name |
| 1339 | try renderToken(ais, tree, field.ast.main_token + 1, .space); // : | 1344 | try renderToken(ais, tree, field.ast.main_token + 1, .space); // : |
| 1340 | } | 1345 | } |
| 1341 | try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type | 1346 | try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type |
| ... | @@ -2054,13 +2059,12 @@ fn renderContainerDecl( | ... | @@ -2054,13 +2059,12 @@ fn renderContainerDecl( |
| 2054 | try renderToken(ais, tree, layout_token, .space); | 2059 | try renderToken(ais, tree, layout_token, .space); |
| 2055 | } | 2060 | } |
| 2056 | | 2061 | |
| 2057 | var is_tuple = token_tags[container_decl.ast.main_token] == .keyword_struct; | 2062 | const container: Container = switch (token_tags[container_decl.ast.main_token]) { |
| 2058 | if (is_tuple) for (container_decl.ast.members) |member| { | 2063 | .keyword_enum => .@"enum", |
| 2059 | const container_field = tree.fullContainerField(member) orelse continue; | 2064 | .keyword_struct => for (container_decl.ast.members) |member| { |
| 2060 | if (!container_field.ast.tuple_like) { | 2065 | if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other; |
| 2061 | is_tuple = false; | 2066 | } else .tuple, |
| 2062 | break; | 2067 | else => .other, |
| 2063 | } | | |
| 2064 | }; | 2068 | }; |
| 2065 | | 2069 | |
| 2066 | var lbrace: Ast.TokenIndex = undefined; | 2070 | var lbrace: Ast.TokenIndex = undefined; |
| ... | @@ -2129,7 +2133,7 @@ fn renderContainerDecl( | ... | @@ -2129,7 +2133,7 @@ fn renderContainerDecl( |
| 2129 | // Print all the declarations on the same line. | 2133 | // Print all the declarations on the same line. |
| 2130 | try renderToken(ais, tree, lbrace, .space); // lbrace | 2134 | try renderToken(ais, tree, lbrace, .space); // lbrace |
| 2131 | for (container_decl.ast.members) |member| { | 2135 | for (container_decl.ast.members) |member| { |
| 2132 | try renderMember(gpa, ais, tree, member, is_tuple, .space); | 2136 | try renderMember(gpa, ais, tree, container, member, .space); |
| 2133 | } | 2137 | } |
| 2134 | return renderToken(ais, tree, rbrace, space); // rbrace | 2138 | return renderToken(ais, tree, rbrace, space); // rbrace |
| 2135 | } | 2139 | } |
| ... | @@ -2147,9 +2151,9 @@ fn renderContainerDecl( | ... | @@ -2147,9 +2151,9 @@ fn renderContainerDecl( |
| 2147 | .container_field_init, | 2151 | .container_field_init, |
| 2148 | .container_field_align, | 2152 | .container_field_align, |
| 2149 | .container_field, | 2153 | .container_field, |
| 2150 | => try renderMember(gpa, ais, tree, member, is_tuple, .comma), | 2154 | => try renderMember(gpa, ais, tree, container, member, .comma), |
| 2151 | | 2155 | |
| 2152 | else => try renderMember(gpa, ais, tree, member, is_tuple, .newline), | 2156 | else => try renderMember(gpa, ais, tree, container, member, .newline), |
| 2153 | } | 2157 | } |
| 2154 | } | 2158 | } |
| 2155 | ais.popIndent(); | 2159 | ais.popIndent(); |
| ... | @@ -2565,6 +2569,7 @@ fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: us | ... | @@ -2565,6 +2569,7 @@ fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: us |
| 2565 | const QuoteBehavior = enum { | 2569 | const QuoteBehavior = enum { |
| 2566 | preserve_when_shadowing, | 2570 | preserve_when_shadowing, |
| 2567 | eagerly_unquote, | 2571 | eagerly_unquote, |
| | 2572 | eagerly_unquote_except_underscore, |
| 2568 | }; | 2573 | }; |
| 2569 | | 2574 | |
| 2570 | fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void { | 2575 | fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void { |
| ... | @@ -2589,7 +2594,9 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp | ... | @@ -2589,7 +2594,9 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp |
| 2589 | // Special case for _ which would incorrectly be rejected by isValidId below. | 2594 | // Special case for _ which would incorrectly be rejected by isValidId below. |
| 2590 | if (contents.len == 1 and contents[0] == '_') switch (quote) { | 2595 | if (contents.len == 1 and contents[0] == '_') switch (quote) { |
| 2591 | .eagerly_unquote => return renderQuotedIdentifier(ais, tree, token_index, space, true), | 2596 | .eagerly_unquote => return renderQuotedIdentifier(ais, tree, token_index, space, true), |
| 2592 | .preserve_when_shadowing => return renderQuotedIdentifier(ais, tree, token_index, space, false), | 2597 | .eagerly_unquote_except_underscore, |
| | 2598 | .preserve_when_shadowing, |
| | 2599 | => return renderQuotedIdentifier(ais, tree, token_index, space, false), |
| 2593 | }; | 2600 | }; |
| 2594 | | 2601 | |
| 2595 | // Scan the entire name for characters that would (after un-escaping) be illegal in a symbol, | 2602 | // Scan the entire name for characters that would (after un-escaping) be illegal in a symbol, |
| ... | @@ -2653,7 +2660,9 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp | ... | @@ -2653,7 +2660,9 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp |
| 2653 | return renderQuotedIdentifier(ais, tree, token_index, space, false); | 2660 | return renderQuotedIdentifier(ais, tree, token_index, space, false); |
| 2654 | } | 2661 | } |
| 2655 | if (primitives.isPrimitive(buf[0..buf_i])) switch (quote) { | 2662 | if (primitives.isPrimitive(buf[0..buf_i])) switch (quote) { |
| 2656 | .eagerly_unquote => return renderQuotedIdentifier(ais, tree, token_index, space, true), | 2663 | .eagerly_unquote, |
| | 2664 | .eagerly_unquote_except_underscore, |
| | 2665 | => return renderQuotedIdentifier(ais, tree, token_index, space, true), |
| 2657 | .preserve_when_shadowing => return renderQuotedIdentifier(ais, tree, token_index, space, false), | 2666 | .preserve_when_shadowing => return renderQuotedIdentifier(ais, tree, token_index, space, false), |
| 2658 | }; | 2667 | }; |
| 2659 | } | 2668 | } |