| ... | ... | @@ -1018,170 +1018,95 @@ fn renderWhile(gpa: *Allocator, ais: *Ais, tree: ast.Tree, while_node: ast.full. |
| 1018 | 1018 | try renderToken(ais, tree, inline_token, .space); // inline |
| 1019 | 1019 | } |
| 1020 | 1020 | |
| 1021 | | try renderToken(ais, tree, while_node.ast.while_token, .space); // if |
| 1021 | try renderToken(ais, tree, while_node.ast.while_token, .space); // if/for/while |
| 1022 | 1022 | try renderToken(ais, tree, while_node.ast.while_token + 1, .none); // lparen |
| 1023 | 1023 | try renderExpression(gpa, ais, tree, while_node.ast.cond_expr, .none); // condition |
| 1024 | 1024 | |
| 1025 | | const then_tag = node_tags[while_node.ast.then_expr]; |
| 1026 | | if (nodeIsBlock(then_tag) and !nodeIsIf(then_tag)) { |
| 1027 | | if (while_node.payload_token) |payload_token| { |
| 1028 | | const brace_space = if (while_node.ast.cont_expr == 0 and ais.isLineOverIndented()) |
| 1029 | | Space.newline |
| 1030 | | else |
| 1031 | | Space.space; |
| 1032 | | try renderWhilePayload(gpa, ais, tree, payload_token, brace_space); |
| 1033 | | } else { |
| 1034 | | const rparen = tree.lastToken(while_node.ast.cond_expr) + 1; |
| 1035 | | const brace_space = if (while_node.ast.cont_expr == 0 and ais.isLineOverIndented()) |
| 1036 | | Space.newline |
| 1037 | | else |
| 1038 | | Space.space; |
| 1039 | | try renderToken(ais, tree, rparen, brace_space); // rparen |
| 1040 | | } |
| 1041 | | if (while_node.ast.cont_expr != 0) { |
| 1042 | | const rparen = tree.lastToken(while_node.ast.cont_expr) + 1; |
| 1043 | | const lparen = tree.firstToken(while_node.ast.cont_expr) - 1; |
| 1044 | | try renderToken(ais, tree, lparen - 1, .space); // : |
| 1045 | | try renderToken(ais, tree, lparen, .none); // lparen |
| 1046 | | try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none); |
| 1047 | | const brace_space: Space = if (ais.isLineOverIndented()) .newline else .space; |
| 1048 | | try renderToken(ais, tree, rparen, brace_space); // rparen |
| 1049 | | } |
| 1050 | | if (while_node.ast.else_expr != 0) { |
| 1051 | | try renderExpression(gpa, ais, tree, while_node.ast.then_expr, Space.space); |
| 1052 | | try renderToken(ais, tree, while_node.else_token, .space); // else |
| 1053 | | if (while_node.error_token) |error_token| { |
| 1054 | | try renderToken(ais, tree, error_token - 1, .none); // | |
| 1055 | | try renderToken(ais, tree, error_token, .none); // identifier |
| 1056 | | try renderToken(ais, tree, error_token + 1, .space); // | |
| 1057 | | } |
| 1058 | | return renderExpression(gpa, ais, tree, while_node.ast.else_expr, space); |
| 1059 | | } else { |
| 1060 | | return renderExpression(gpa, ais, tree, while_node.ast.then_expr, space); |
| 1061 | | } |
| 1062 | | } |
| 1063 | | |
| 1064 | | const rparen = tree.lastToken(while_node.ast.cond_expr) + 1; |
| 1065 | | const first_then_token = tree.firstToken(while_node.ast.then_expr); |
| 1066 | | const last_then_token = tree.lastToken(while_node.ast.then_expr); |
| 1067 | | const src_has_newline = !tree.tokensOnSameLine(rparen, last_then_token); |
| 1025 | var last_prefix_token = tree.lastToken(while_node.ast.cond_expr) + 1; // rparen |
| 1068 | 1026 | |
| 1069 | | if (src_has_newline) { |
| 1070 | | const newline_before_then_token = !tree.tokensOnSameLine(rparen, first_then_token); |
| 1071 | | const space_before_then_token: Space = if (newline_before_then_token) .newline else .space; |
| 1072 | | const indent_expression = !nodeIsIf(then_tag) or newline_before_then_token; |
| 1073 | | |
| 1074 | | if (while_node.payload_token) |payload_token| { |
| 1075 | | const after_space: Space = if (while_node.ast.cont_expr != 0) .space else space_before_then_token; |
| 1076 | | try renderWhilePayload(gpa, ais, tree, payload_token, after_space); |
| 1077 | | } else { |
| 1078 | | if (indent_expression) ais.pushIndent(); |
| 1079 | | const after_space: Space = if (while_node.ast.cont_expr != 0) .space else space_before_then_token; |
| 1080 | | try renderToken(ais, tree, rparen, after_space); // rparen |
| 1081 | | if (indent_expression) ais.popIndent(); |
| 1082 | | } |
| 1083 | | if (while_node.ast.cont_expr != 0) { |
| 1084 | | const cont_rparen = tree.lastToken(while_node.ast.cont_expr) + 1; |
| 1085 | | const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1; |
| 1086 | | try renderToken(ais, tree, cont_lparen - 1, .space); // : |
| 1087 | | try renderToken(ais, tree, cont_lparen, .none); // lparen |
| 1088 | | try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none); |
| 1089 | | try renderToken(ais, tree, cont_rparen, space_before_then_token); // rparen |
| 1090 | | } |
| 1091 | | if (while_node.ast.else_expr != 0) { |
| 1092 | | if (indent_expression) ais.pushIndent(); |
| 1093 | | try renderExpression(gpa, ais, tree, while_node.ast.then_expr, .newline); |
| 1094 | | if (indent_expression) ais.popIndent(); |
| 1095 | | const else_is_block = nodeIsBlock(node_tags[while_node.ast.else_expr]); |
| 1096 | | if (else_is_block) { |
| 1097 | | try renderToken(ais, tree, while_node.else_token, .space); // else |
| 1098 | | if (while_node.error_token) |error_token| { |
| 1099 | | try renderToken(ais, tree, error_token - 1, .none); // | |
| 1100 | | try renderToken(ais, tree, error_token, .none); // identifier |
| 1101 | | try renderToken(ais, tree, error_token + 1, .space); // | |
| 1102 | | } |
| 1103 | | return renderExpression(gpa, ais, tree, while_node.ast.else_expr, space); |
| 1027 | if (while_node.payload_token) |payload_token| { |
| 1028 | try renderToken(ais, tree, last_prefix_token, .space); |
| 1029 | try renderToken(ais, tree, payload_token - 1, .none); // | |
| 1030 | const ident = blk: { |
| 1031 | if (token_tags[payload_token] == .asterisk) { |
| 1032 | try renderToken(ais, tree, payload_token, .none); // * |
| 1033 | break :blk payload_token + 1; |
| 1104 | 1034 | } else { |
| 1105 | | if (while_node.error_token) |error_token| { |
| 1106 | | try renderToken(ais, tree, while_node.else_token, .space); // else |
| 1107 | | try renderToken(ais, tree, error_token - 1, .none); // | |
| 1108 | | try renderToken(ais, tree, error_token, .none); // identifier |
| 1109 | | try renderToken(ais, tree, error_token + 1, .space); // | |
| 1110 | | } else { |
| 1111 | | try renderToken(ais, tree, while_node.else_token, .newline); // else |
| 1112 | | } |
| 1113 | | if (indent_expression) { |
| 1114 | | return renderExpressionIndented(gpa, ais, tree, while_node.ast.else_expr, space); |
| 1115 | | } else { |
| 1116 | | return renderExpression(gpa, ais, tree, while_node.ast.else_expr, space); |
| 1117 | | } |
| 1035 | break :blk payload_token; |
| 1118 | 1036 | } |
| 1119 | | } else { |
| 1120 | | if (indent_expression) { |
| 1121 | | return renderExpressionIndented(gpa, ais, tree, while_node.ast.then_expr, space); |
| 1037 | }; |
| 1038 | try renderToken(ais, tree, ident, .none); // identifier |
| 1039 | const pipe = blk: { |
| 1040 | if (token_tags[ident + 1] == .comma) { |
| 1041 | try renderToken(ais, tree, ident + 1, .space); // , |
| 1042 | try renderToken(ais, tree, ident + 2, .none); // index |
| 1043 | break :blk ident + 3; |
| 1122 | 1044 | } else { |
| 1123 | | return renderExpression(gpa, ais, tree, while_node.ast.then_expr, space); |
| 1045 | break :blk ident + 1; |
| 1124 | 1046 | } |
| 1125 | | } |
| 1126 | | } |
| 1127 | | |
| 1128 | | // Render everything on a single line. |
| 1129 | | |
| 1130 | | if (while_node.payload_token) |payload_token| { |
| 1131 | | assert(payload_token - 2 == rparen); |
| 1132 | | try renderWhilePayload(gpa, ais, tree, payload_token, .space); |
| 1133 | | } else { |
| 1134 | | try renderToken(ais, tree, rparen, .space); // ) |
| 1047 | }; |
| 1048 | last_prefix_token = pipe; |
| 1135 | 1049 | } |
| 1136 | 1050 | |
| 1137 | 1051 | if (while_node.ast.cont_expr != 0) { |
| 1138 | | const cont_rparen = tree.lastToken(while_node.ast.cont_expr) + 1; |
| 1139 | | const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1; |
| 1140 | | try renderToken(ais, tree, cont_lparen - 1, .space); // : |
| 1141 | | try renderToken(ais, tree, cont_lparen, .none); // lparen |
| 1052 | try renderToken(ais, tree, last_prefix_token, .space); |
| 1053 | const lparen = tree.firstToken(while_node.ast.cont_expr) - 1; |
| 1054 | try renderToken(ais, tree, lparen - 1, .space); // : |
| 1055 | try renderToken(ais, tree, lparen, .none); // lparen |
| 1142 | 1056 | try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none); |
| 1143 | | try renderToken(ais, tree, cont_rparen, .space); // rparen |
| 1057 | last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen |
| 1058 | } |
| 1059 | |
| 1060 | const then_expr_is_block = nodeIsBlock(node_tags[while_node.ast.then_expr]); |
| 1061 | const indent_then_expr = !then_expr_is_block and |
| 1062 | !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(while_node.ast.then_expr)); |
| 1063 | if (indent_then_expr or (then_expr_is_block and ais.isLineOverIndented())) { |
| 1064 | ais.pushIndentNextLine(); |
| 1065 | try renderToken(ais, tree, last_prefix_token, .newline); |
| 1066 | ais.popIndent(); |
| 1067 | } else { |
| 1068 | try renderToken(ais, tree, last_prefix_token, .space); |
| 1144 | 1069 | } |
| 1145 | 1070 | |
| 1146 | 1071 | if (while_node.ast.else_expr != 0) { |
| 1147 | | try renderExpression(gpa, ais, tree, while_node.ast.then_expr, .space); |
| 1148 | | try renderToken(ais, tree, while_node.else_token, .space); // else |
| 1072 | const first_else_expr_tok = tree.firstToken(while_node.ast.else_expr); |
| 1073 | |
| 1074 | if (indent_then_expr) { |
| 1075 | ais.pushIndent(); |
| 1076 | try renderExpression(gpa, ais, tree, while_node.ast.then_expr, .newline); |
| 1077 | ais.popIndent(); |
| 1078 | } else { |
| 1079 | try renderExpression(gpa, ais, tree, while_node.ast.then_expr, .space); |
| 1080 | } |
| 1081 | |
| 1082 | var last_else_token = while_node.else_token; |
| 1149 | 1083 | |
| 1150 | 1084 | if (while_node.error_token) |error_token| { |
| 1085 | try renderToken(ais, tree, while_node.else_token, .space); // else |
| 1151 | 1086 | try renderToken(ais, tree, error_token - 1, .none); // | |
| 1152 | 1087 | try renderToken(ais, tree, error_token, .none); // identifier |
| 1153 | | try renderToken(ais, tree, error_token + 1, .space); // | |
| 1088 | last_else_token = error_token + 1; // | |
| 1154 | 1089 | } |
| 1155 | 1090 | |
| 1156 | | return renderExpression(gpa, ais, tree, while_node.ast.else_expr, space); |
| 1157 | | } else { |
| 1158 | | return renderExpression(gpa, ais, tree, while_node.ast.then_expr, space); |
| 1159 | | } |
| 1160 | | } |
| 1161 | | |
| 1162 | | fn renderWhilePayload(gpa: *Allocator, ais: *Ais, tree: ast.Tree, payload_token: ast.TokenIndex, space: Space) Error!void { |
| 1163 | | const token_tags = tree.tokens.items(.tag); |
| 1164 | | try renderToken(ais, tree, payload_token - 2, .space); // rparen |
| 1165 | | try renderToken(ais, tree, payload_token - 1, .none); // | |
| 1166 | | const ident = blk: { |
| 1167 | | if (token_tags[payload_token] == .asterisk) { |
| 1168 | | try renderToken(ais, tree, payload_token, .none); // * |
| 1169 | | break :blk payload_token + 1; |
| 1091 | const indent_else_expr = indent_then_expr and |
| 1092 | !nodeIsBlock(node_tags[while_node.ast.else_expr]) and |
| 1093 | !nodeIsIfForWhileSwitch(node_tags[while_node.ast.else_expr]); |
| 1094 | if (indent_else_expr) { |
| 1095 | ais.pushIndentNextLine(); |
| 1096 | try renderToken(ais, tree, last_else_token, .newline); |
| 1097 | ais.popIndent(); |
| 1098 | try renderExpressionIndented(gpa, ais, tree, while_node.ast.else_expr, space); |
| 1170 | 1099 | } else { |
| 1171 | | break :blk payload_token; |
| 1100 | try renderToken(ais, tree, last_else_token, .space); |
| 1101 | try renderExpression(gpa, ais, tree, while_node.ast.else_expr, space); |
| 1172 | 1102 | } |
| 1173 | | }; |
| 1174 | | try renderToken(ais, tree, ident, .none); // identifier |
| 1175 | | const pipe = blk: { |
| 1176 | | if (token_tags[ident + 1] == .comma) { |
| 1177 | | try renderToken(ais, tree, ident + 1, .space); // , |
| 1178 | | try renderToken(ais, tree, ident + 2, .none); // index |
| 1179 | | break :blk ident + 3; |
| 1103 | } else { |
| 1104 | if (indent_then_expr) { |
| 1105 | try renderExpressionIndented(gpa, ais, tree, while_node.ast.then_expr, space); |
| 1180 | 1106 | } else { |
| 1181 | | break :blk ident + 1; |
| 1107 | try renderExpression(gpa, ais, tree, while_node.ast.then_expr, space); |
| 1182 | 1108 | } |
| 1183 | | }; |
| 1184 | | try renderToken(ais, tree, pipe, space); // | |
| 1109 | } |
| 1185 | 1110 | } |
| 1186 | 1111 | |
| 1187 | 1112 | fn renderContainerField( |
| ... | ... | @@ -2469,6 +2394,21 @@ fn nodeIsBlock(tag: ast.Node.Tag) bool { |
| 2469 | 2394 | .block_semicolon, |
| 2470 | 2395 | .block_two, |
| 2471 | 2396 | .block_two_semicolon, |
| 2397 | .struct_init_dot, |
| 2398 | .struct_init_dot_comma, |
| 2399 | .struct_init_dot_two, |
| 2400 | .struct_init_dot_two_comma, |
| 2401 | .array_init_dot, |
| 2402 | .array_init_dot_comma, |
| 2403 | .array_init_dot_two, |
| 2404 | .array_init_dot_two_comma, |
| 2405 | => true, |
| 2406 | else => false, |
| 2407 | }; |
| 2408 | } |
| 2409 | |
| 2410 | fn nodeIsIfForWhileSwitch(tag: ast.Node.Tag) bool { |
| 2411 | return switch (tag) { |
| 2472 | 2412 | .@"if", |
| 2473 | 2413 | .if_simple, |
| 2474 | 2414 | .@"for", |
| ... | ... | @@ -2483,13 +2423,6 @@ fn nodeIsBlock(tag: ast.Node.Tag) bool { |
| 2483 | 2423 | }; |
| 2484 | 2424 | } |
| 2485 | 2425 | |
| 2486 | | fn nodeIsIf(tag: ast.Node.Tag) bool { |
| 2487 | | return switch (tag) { |
| 2488 | | .@"if", .if_simple => true, |
| 2489 | | else => false, |
| 2490 | | }; |
| 2491 | | } |
| 2492 | | |
| 2493 | 2426 | fn nodeCausesSliceOpSpace(tag: ast.Node.Tag) bool { |
| 2494 | 2427 | return switch (tag) { |
| 2495 | 2428 | .@"catch", |