| ... | ... | @@ -40,27 +40,28 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast) Error!void { |
| 40 | 40 | /// Render all members in the given slice, keeping empty lines where appropriate |
| 41 | 41 | fn renderMembers(gpa: Allocator, ais: *Ais, tree: Ast, members: []const Ast.Node.Index) Error!void { |
| 42 | 42 | if (members.len == 0) return; |
| 43 | | var is_tuple = true; |
| 44 | | for (members) |member| { |
| 45 | | const container_field = tree.fullContainerField(member) orelse continue; |
| 46 | | if (!container_field.ast.tuple_like) { |
| 47 | | is_tuple = false; |
| 48 | | break; |
| 49 | | } |
| 50 | | } |
| 51 | | try renderMember(gpa, ais, tree, members[0], is_tuple, .newline); |
| 43 | const container: Container = for (members) |member| { |
| 44 | if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other; |
| 45 | } else .tuple; |
| 46 | try renderMember(gpa, ais, tree, container, members[0], .newline); |
| 52 | 47 | for (members[1..]) |member| { |
| 53 | 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 | 59 | fn renderMember( |
| 59 | 60 | gpa: Allocator, |
| 60 | 61 | ais: *Ais, |
| 61 | 62 | tree: Ast, |
| 63 | container: Container, |
| 62 | 64 | decl: Ast.Node.Index, |
| 63 | | is_tuple: bool, |
| 64 | 65 | space: Space, |
| 65 | 66 | ) Error!void { |
| 66 | 67 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -180,7 +181,7 @@ fn renderMember( |
| 180 | 181 | .container_field_init, |
| 181 | 182 | .container_field_align, |
| 182 | 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 | 186 | .@"comptime" => return renderExpression(gpa, ais, tree, decl, space), |
| 186 | 187 | |
| ... | ... | @@ -1279,19 +1280,23 @@ fn renderContainerField( |
| 1279 | 1280 | gpa: Allocator, |
| 1280 | 1281 | ais: *Ais, |
| 1281 | 1282 | tree: Ast, |
| 1283 | container: Container, |
| 1282 | 1284 | field_param: Ast.full.ContainerField, |
| 1283 | | is_tuple: bool, |
| 1284 | 1285 | space: Space, |
| 1285 | 1286 | ) Error!void { |
| 1286 | 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 | 1294 | if (field.comptime_token) |t| { |
| 1290 | 1295 | try renderToken(ais, tree, t, .space); // comptime |
| 1291 | 1296 | } |
| 1292 | 1297 | if (field.ast.type_expr == 0 and field.ast.value_expr == 0) { |
| 1293 | 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 | 1300 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; |
| 1296 | 1301 | const align_kw = lparen_token - 1; |
| 1297 | 1302 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; |
| ... | ... | @@ -1300,11 +1305,11 @@ fn renderContainerField( |
| 1300 | 1305 | try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment |
| 1301 | 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 | 1310 | if (field.ast.type_expr != 0 and field.ast.value_expr == 0) { |
| 1306 | 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 | 1313 | try renderToken(ais, tree, field.ast.main_token + 1, .space); // : |
| 1309 | 1314 | } |
| 1310 | 1315 | |
| ... | ... | @@ -1321,7 +1326,7 @@ fn renderContainerField( |
| 1321 | 1326 | } |
| 1322 | 1327 | } |
| 1323 | 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 | 1330 | if (field.ast.align_expr != 0) { |
| 1326 | 1331 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; |
| 1327 | 1332 | const align_kw = lparen_token - 1; |
| ... | ... | @@ -1335,7 +1340,7 @@ fn renderContainerField( |
| 1335 | 1340 | return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value |
| 1336 | 1341 | } |
| 1337 | 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 | 1344 | try renderToken(ais, tree, field.ast.main_token + 1, .space); // : |
| 1340 | 1345 | } |
| 1341 | 1346 | try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type |
| ... | ... | @@ -2054,13 +2059,12 @@ fn renderContainerDecl( |
| 2054 | 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; |
| 2058 | | if (is_tuple) for (container_decl.ast.members) |member| { |
| 2059 | | const container_field = tree.fullContainerField(member) orelse continue; |
| 2060 | | if (!container_field.ast.tuple_like) { |
| 2061 | | is_tuple = false; |
| 2062 | | break; |
| 2063 | | } |
| 2062 | const container: Container = switch (token_tags[container_decl.ast.main_token]) { |
| 2063 | .keyword_enum => .@"enum", |
| 2064 | .keyword_struct => for (container_decl.ast.members) |member| { |
| 2065 | if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other; |
| 2066 | } else .tuple, |
| 2067 | else => .other, |
| 2064 | 2068 | }; |
| 2065 | 2069 | |
| 2066 | 2070 | var lbrace: Ast.TokenIndex = undefined; |
| ... | ... | @@ -2129,7 +2133,7 @@ fn renderContainerDecl( |
| 2129 | 2133 | // Print all the declarations on the same line. |
| 2130 | 2134 | try renderToken(ais, tree, lbrace, .space); // lbrace |
| 2131 | 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 | 2138 | return renderToken(ais, tree, rbrace, space); // rbrace |
| 2135 | 2139 | } |
| ... | ... | @@ -2147,9 +2151,9 @@ fn renderContainerDecl( |
| 2147 | 2151 | .container_field_init, |
| 2148 | 2152 | .container_field_align, |
| 2149 | 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 | 2159 | ais.popIndent(); |
| ... | ... | @@ -2565,6 +2569,7 @@ fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: us |
| 2565 | 2569 | const QuoteBehavior = enum { |
| 2566 | 2570 | preserve_when_shadowing, |
| 2567 | 2571 | eagerly_unquote, |
| 2572 | eagerly_unquote_except_underscore, |
| 2568 | 2573 | }; |
| 2569 | 2574 | |
| 2570 | 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 | 2594 | // Special case for _ which would incorrectly be rejected by isValidId below. |
| 2590 | 2595 | if (contents.len == 1 and contents[0] == '_') switch (quote) { |
| 2591 | 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 | 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 | 2660 | return renderQuotedIdentifier(ais, tree, token_index, space, false); |
| 2654 | 2661 | } |
| 2655 | 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 | 2666 | .preserve_when_shadowing => return renderQuotedIdentifier(ais, tree, token_index, space, false), |
| 2658 | 2667 | }; |
| 2659 | 2668 | } |