| ... | @@ -77,22 +77,11 @@ fn renderExtraNewline(ais: *Ais, tree: ast.Tree, node: ast.Node.Index) Error!voi | ... | @@ -77,22 +77,11 @@ fn renderExtraNewline(ais: *Ais, tree: ast.Tree, node: ast.Node.Index) Error!voi |
| 77 | } | 77 | } |
| 78 | | 78 | |
| 79 | fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, first_token: ast.TokenIndex) Error!void { | 79 | fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, first_token: ast.TokenIndex) Error!void { |
| 80 | @panic("TODO implement renderExtraNewlineToken"); | 80 | if (first_token == 0) return; |
| 81 | //var prev_token = first_token; | 81 | const token_starts = tree.tokens.items(.start); |
| 82 | //if (prev_token == 0) return; | 82 | if (tree.tokenLocation(token_starts[first_token - 1], first_token).line >= 2) { |
| 83 | //const token_tags = tree.tokens.items(.tag); | 83 | return ais.insertNewline(); |
| 84 | //var newline_threshold: usize = 2; | 84 | } |
| 85 | //while (token_tags[prev_token - 1] == .DocComment) { | | |
| 86 | // if (tree.tokenLocation(tree.token_locs[prev_token - 1].end, prev_token).line == 1) { | | |
| 87 | // newline_threshold += 1; | | |
| 88 | // } | | |
| 89 | // prev_token -= 1; | | |
| 90 | //} | | |
| 91 | //const prev_token_end = tree.token_locs[prev_token - 1].end; | | |
| 92 | //const loc = tree.tokenLocation(prev_token_end, first_token); | | |
| 93 | //if (loc.line >= newline_threshold) { | | |
| 94 | // try ais.insertNewline(); | | |
| 95 | //} | | |
| 96 | } | 85 | } |
| 97 | | 86 | |
| 98 | fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void { | 87 | fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void { |
| ... | @@ -101,24 +90,43 @@ fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: S | ... | @@ -101,24 +90,43 @@ fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: S |
| 101 | const datas = tree.nodes.items(.data); | 90 | const datas = tree.nodes.items(.data); |
| 102 | try renderDocComments(ais, tree, tree.firstToken(decl)); | 91 | try renderDocComments(ais, tree, tree.firstToken(decl)); |
| 103 | switch (tree.nodes.items(.tag)[decl]) { | 92 | switch (tree.nodes.items(.tag)[decl]) { |
| 104 | .FnProtoSimple => unreachable, // TODO | 93 | .FnDecl => { |
| 105 | .FnProtoSimpleMulti => unreachable, // TODO | 94 | // Some examples: |
| 106 | .FnProtoOne => unreachable, // TODO | 95 | // pub extern "foo" fn ... |
| 107 | .FnDecl => unreachable, // TODO | 96 | // export fn ... |
| 108 | .FnProto => unreachable, // TODO | 97 | const fn_proto = datas[decl].lhs; |
| 109 | // .FnProto => { | 98 | const fn_token = main_tokens[fn_proto]; |
| 110 | // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); | 99 | // Go back to the first token we should render here. |
| 111 | | 100 | var i = fn_token; |
| 112 | // try renderDocComments(ais, tree, fn_proto, fn_proto.getDocComments()); | 101 | while (i > 0) { |
| 113 | | 102 | i -= 1; |
| 114 | // if (fn_proto.getBodyNode()) |body_node| { | 103 | switch (token_tags[i]) { |
| 115 | // try renderExpression(ais, tree, decl, .Space); | 104 | .Keyword_extern, |
| 116 | // try renderExpression(ais, tree, body_node, space); | 105 | .Keyword_export, |
| 117 | // } else { | 106 | .Keyword_pub, |
| 118 | // try renderExpression(ais, tree, decl, .None); | 107 | .StringLiteral, |
| 119 | // try renderToken(ais, tree, tree.nextToken(decl.lastToken()), space); | 108 | => continue, |
| 120 | // } | 109 | |
| 121 | // }, | 110 | else => { |
| | 111 | i += 1; |
| | 112 | break; |
| | 113 | }, |
| | 114 | } |
| | 115 | } |
| | 116 | while (i < fn_token) : (i += 1) { |
| | 117 | try renderToken(ais, tree, i, .Space); |
| | 118 | } |
| | 119 | try renderExpression(ais, tree, fn_proto, .Space); |
| | 120 | return renderExpression(ais, tree, datas[decl].rhs, space); |
| | 121 | }, |
| | 122 | .FnProtoSimple, |
| | 123 | .FnProtoMulti, |
| | 124 | .FnProtoOne, |
| | 125 | .FnProto, |
| | 126 | => { |
| | 127 | try renderExpression(ais, tree, decl, .None); |
| | 128 | try renderToken(ais, tree, tree.lastToken(decl) + 1, space); // semicolon |
| | 129 | }, |
| 122 | | 130 | |
| 123 | .UsingNamespace => unreachable, // TODO | 131 | .UsingNamespace => unreachable, // TODO |
| 124 | // .Use => { | 132 | // .Use => { |
| ... | @@ -186,90 +194,48 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac | ... | @@ -186,90 +194,48 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 186 | // } | 194 | // } |
| 187 | // return renderToken(ais, tree, any_type.token, space); | 195 | // return renderToken(ais, tree, any_type.token, space); |
| 188 | //}, | 196 | //}, |
| | 197 | .BlockTwo => { |
| | 198 | var statements = [2]ast.Node.Index{ datas[node].lhs, datas[node].rhs }; |
| | 199 | if (datas[node].lhs == 0) { |
| | 200 | return renderBlock(ais, tree, main_tokens[node], statements[0..0], space); |
| | 201 | } else if (datas[node].rhs == 0) { |
| | 202 | return renderBlock(ais, tree, main_tokens[node], statements[0..1], space); |
| | 203 | } else { |
| | 204 | return renderBlock(ais, tree, main_tokens[node], statements[0..2], space); |
| | 205 | } |
| | 206 | }, |
| 189 | .Block => { | 207 | .Block => { |
| 190 | const lbrace = main_tokens[node]; | 208 | const lbrace = main_tokens[node]; |
| 191 | if (token_tags[lbrace - 1] == .Colon and | 209 | const statements = tree.extra_data[datas[node].lhs..datas[node].rhs]; |
| 192 | token_tags[lbrace - 2] == .Identifier) | 210 | return renderBlock(ais, tree, main_tokens[node], statements, space); |
| 193 | { | 211 | }, |
| 194 | try renderToken(ais, tree, lbrace - 2, .None); | | |
| 195 | try renderToken(ais, tree, lbrace - 1, .Space); | | |
| 196 | } | | |
| 197 | const nodes_data = tree.nodes.items(.data); | | |
| 198 | const statements = tree.extra_data[nodes_data[node].lhs..nodes_data[node].rhs]; | | |
| 199 | | 212 | |
| 200 | if (statements.len == 0) { | 213 | .ErrDefer => { |
| 201 | ais.pushIndentNextLine(); | 214 | const defer_token = main_tokens[node]; |
| 202 | try renderToken(ais, tree, lbrace, .None); | 215 | const payload_token = datas[node].lhs; |
| 203 | ais.popIndent(); | 216 | const expr = datas[node].rhs; |
| 204 | const rbrace = lbrace + 1; | | |
| 205 | return renderToken(ais, tree, rbrace, space); | | |
| 206 | } else { | | |
| 207 | ais.pushIndentNextLine(); | | |
| 208 | | | |
| 209 | try renderToken(ais, tree, lbrace, .Newline); | | |
| 210 | | | |
| 211 | for (statements) |stmt, i| { | | |
| 212 | switch (node_tags[stmt]) { | | |
| 213 | .GlobalVarDecl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)), | | |
| 214 | .LocalVarDecl => try renderVarDecl(ais, tree, tree.localVarDecl(stmt)), | | |
| 215 | .SimpleVarDecl => try renderVarDecl(ais, tree, tree.simpleVarDecl(stmt)), | | |
| 216 | .AlignedVarDecl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)), | | |
| 217 | else => { | | |
| 218 | const semicolon = tree.lastToken(stmt) + 1; | | |
| 219 | if (token_tags[semicolon] == .Semicolon) { | | |
| 220 | try renderExpression(ais, tree, stmt, .None); | | |
| 221 | try renderToken(ais, tree, semicolon, .Newline); | | |
| 222 | } else { | | |
| 223 | try renderExpression(ais, tree, stmt, .Newline); | | |
| 224 | } | | |
| 225 | }, | | |
| 226 | } | | |
| 227 | | 217 | |
| 228 | if (i + 1 < statements.len) { | 218 | try renderToken(ais, tree, defer_token, .Space); |
| 229 | try renderExtraNewline(ais, tree, statements[i + 1]); | 219 | if (payload_token != 0) { |
| 230 | } | 220 | try renderToken(ais, tree, payload_token - 1, .None); // | |
| 231 | } | 221 | try renderToken(ais, tree, payload_token, .None); // identifier |
| 232 | ais.popIndent(); | 222 | try renderToken(ais, tree, payload_token + 1, .Space); // | |
| 233 | // The rbrace could be +1 or +2 from the last token of the last | | |
| 234 | // statement in the block because lastToken() does not count semicolons. | | |
| 235 | const maybe_rbrace = tree.lastToken(statements[statements.len - 1]) + 1; | | |
| 236 | if (token_tags[maybe_rbrace] == .RBrace) { | | |
| 237 | return renderToken(ais, tree, maybe_rbrace, space); | | |
| 238 | } else { | | |
| 239 | assert(token_tags[maybe_rbrace + 1] == .RBrace); | | |
| 240 | return renderToken(ais, tree, maybe_rbrace + 1, space); | | |
| 241 | } | | |
| 242 | } | 223 | } |
| | 224 | return renderExpression(ais, tree, expr, space); |
| 243 | }, | 225 | }, |
| 244 | | 226 | |
| 245 | .Defer => unreachable, // TODO | 227 | .Defer => { |
| 246 | .ErrDefer => unreachable, // TODO | 228 | const defer_token = main_tokens[node]; |
| 247 | //.Defer => { | 229 | const expr = datas[node].rhs; |
| 248 | // const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base); | 230 | try renderToken(ais, tree, defer_token, .Space); |
| 249 | | 231 | return renderExpression(ais, tree, expr, space); |
| 250 | // try renderToken(ais, tree, defer_node.defer_token, Space.Space); | 232 | }, |
| 251 | // if (defer_node.payload) |payload| { | 233 | .Comptime, .Nosuspend => { |
| 252 | // try renderExpression(ais, tree, payload, Space.Space); | | |
| 253 | // } | | |
| 254 | // return renderExpression(ais, tree, defer_node.expr, space); | | |
| 255 | //}, | | |
| 256 | .Comptime => { | | |
| 257 | const comptime_token = main_tokens[node]; | 234 | const comptime_token = main_tokens[node]; |
| 258 | const block = datas[node].lhs; | 235 | const block = datas[node].lhs; |
| 259 | try renderToken(ais, tree, comptime_token, .Space); | 236 | try renderToken(ais, tree, comptime_token, .Space); |
| 260 | return renderExpression(ais, tree, block, space); | 237 | return renderExpression(ais, tree, block, space); |
| 261 | }, | 238 | }, |
| 262 | .Nosuspend => unreachable, // TODO | | |
| 263 | //.Nosuspend => { | | |
| 264 | // const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base); | | |
| 265 | // if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) { | | |
| 266 | // // TODO: remove this | | |
| 267 | // try ais.writer().writeAll("nosuspend "); | | |
| 268 | // } else { | | |
| 269 | // try renderToken(ais, tree, nosuspend_node.nosuspend_token, Space.Space); | | |
| 270 | // } | | |
| 271 | // return renderExpression(ais, tree, nosuspend_node.expr, space); | | |
| 272 | //}, | | |
| 273 | | 239 | |
| 274 | .Suspend => unreachable, // TODO | 240 | .Suspend => unreachable, // TODO |
| 275 | //.Suspend => { | 241 | //.Suspend => { |
| ... | @@ -1274,140 +1240,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac | ... | @@ -1274,140 +1240,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 1274 | return renderBuiltinCall(ais, tree, main_tokens[node], params, space); | 1240 | return renderBuiltinCall(ais, tree, main_tokens[node], params, space); |
| 1275 | }, | 1241 | }, |
| 1276 | | 1242 | |
| 1277 | .FnProtoSimple => unreachable, // TODO | 1243 | .FnProtoSimple => { |
| 1278 | .FnProtoSimpleMulti => unreachable, // TODO | 1244 | var params: [1]ast.Node.Index = undefined; |
| 1279 | .FnProtoOne => unreachable, // TODO | 1245 | return renderFnProto(ais, tree, tree.fnProtoSimple(&params, node), space); |
| 1280 | .FnProto => unreachable, // TODO | 1246 | }, |
| 1281 | //.FnProto => { | 1247 | .FnProtoMulti => return renderFnProto(ais, tree, tree.fnProtoMulti(node), space), |
| 1282 | // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); | 1248 | .FnProtoOne => { |
| 1283 | | 1249 | var params: [1]ast.Node.Index = undefined; |
| 1284 | // if (fn_proto.getVisibToken()) |visib_token_index| { | 1250 | return renderFnProto(ais, tree, tree.fnProtoOne(&params, node), space); |
| 1285 | // const visib_token = tree.token_tags[visib_token_index]; | 1251 | }, |
| 1286 | // assert(visib_token == .Keyword_pub or visib_token == .Keyword_export); | 1252 | .FnProto => return renderFnProto(ais, tree, tree.fnProto(node), space), |
| 1287 | | | |
| 1288 | // try renderToken(ais, tree, visib_token_index, Space.Space); // pub | | |
| 1289 | // } | | |
| 1290 | | | |
| 1291 | // if (fn_proto.getExternExportInlineToken()) |extern_export_inline_token| { | | |
| 1292 | // if (fn_proto.getIsExternPrototype() == null) | | |
| 1293 | // try renderToken(ais, tree, extern_export_inline_token, Space.Space); // extern/export/inline | | |
| 1294 | // } | | |
| 1295 | | | |
| 1296 | // if (fn_proto.getLibName()) |lib_name| { | | |
| 1297 | // try renderExpression(ais, tree, lib_name, Space.Space); | | |
| 1298 | // } | | |
| 1299 | | | |
| 1300 | // const lparen = if (fn_proto.getNameToken()) |name_token| blk: { | | |
| 1301 | // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn | | |
| 1302 | // try renderToken(ais, tree, name_token, Space.None); // name | | |
| 1303 | // break :blk tree.nextToken(name_token); | | |
| 1304 | // } else blk: { | | |
| 1305 | // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn | | |
| 1306 | // break :blk tree.nextToken(fn_proto.fn_token); | | |
| 1307 | // }; | | |
| 1308 | // assert(tree.token_tags[lparen] == .LParen); | | |
| 1309 | | | |
| 1310 | // const rparen = tree.prevToken( | | |
| 1311 | // // the first token for the annotation expressions is the left | | |
| 1312 | // // parenthesis, hence the need for two prevToken | | |
| 1313 | // if (fn_proto.getAlignExpr()) |align_expr| | | |
| 1314 | // tree.prevToken(tree.prevToken(align_expr.firstToken())) | | |
| 1315 | // else if (fn_proto.getSectionExpr()) |section_expr| | | |
| 1316 | // tree.prevToken(tree.prevToken(section_expr.firstToken())) | | |
| 1317 | // else if (fn_proto.getCallconvExpr()) |callconv_expr| | | |
| 1318 | // tree.prevToken(tree.prevToken(callconv_expr.firstToken())) | | |
| 1319 | // else switch (fn_proto.return_type) { | | |
| 1320 | // .Explicit => |node| node.firstToken(), | | |
| 1321 | // .InferErrorSet => |node| tree.prevToken(node.firstToken()), | | |
| 1322 | // .Invalid => unreachable, | | |
| 1323 | // }, | | |
| 1324 | // ); | | |
| 1325 | // assert(tree.token_tags[rparen] == .RParen); | | |
| 1326 | | | |
| 1327 | // const src_params_trailing_comma = blk: { | | |
| 1328 | // const maybe_comma = tree.token_tags[rparen - 1]; | | |
| 1329 | // break :blk maybe_comma == .Comma or maybe_comma == .LineComment; | | |
| 1330 | // }; | | |
| 1331 | | | |
| 1332 | // if (!src_params_trailing_comma) { | | |
| 1333 | // try renderToken(ais, tree, lparen, Space.None); // ( | | |
| 1334 | | | |
| 1335 | // // render all on one line, no trailing comma | | |
| 1336 | // for (fn_proto.params()) |param_decl, i| { | | |
| 1337 | // try renderParamDecl(allocator, ais, tree, param_decl, Space.None); | | |
| 1338 | | | |
| 1339 | // if (i + 1 < fn_proto.params_len or fn_proto.getVarArgsToken() != null) { | | |
| 1340 | // const comma = tree.nextToken(param_decl.lastToken()); | | |
| 1341 | // try renderToken(ais, tree, comma, Space.Space); // , | | |
| 1342 | // } | | |
| 1343 | // } | | |
| 1344 | // if (fn_proto.getVarArgsToken()) |var_args_token| { | | |
| 1345 | // try renderToken(ais, tree, var_args_token, Space.None); | | |
| 1346 | // } | | |
| 1347 | // } else { | | |
| 1348 | // // one param per line | | |
| 1349 | // ais.pushIndent(); | | |
| 1350 | // defer ais.popIndent(); | | |
| 1351 | // try renderToken(ais, tree, lparen, Space.Newline); // ( | | |
| 1352 | | | |
| 1353 | // for (fn_proto.params()) |param_decl| { | | |
| 1354 | // try renderParamDecl(allocator, ais, tree, param_decl, Space.Comma); | | |
| 1355 | // } | | |
| 1356 | // if (fn_proto.getVarArgsToken()) |var_args_token| { | | |
| 1357 | // try renderToken(ais, tree, var_args_token, Space.Comma); | | |
| 1358 | // } | | |
| 1359 | // } | | |
| 1360 | | | |
| 1361 | // try renderToken(ais, tree, rparen, Space.Space); // ) | | |
| 1362 | | | |
| 1363 | // if (fn_proto.getAlignExpr()) |align_expr| { | | |
| 1364 | // const align_rparen = tree.nextToken(align_expr.lastToken()); | | |
| 1365 | // const align_lparen = tree.prevToken(align_expr.firstToken()); | | |
| 1366 | // const align_kw = tree.prevToken(align_lparen); | | |
| 1367 | | | |
| 1368 | // try renderToken(ais, tree, align_kw, Space.None); // align | | |
| 1369 | // try renderToken(ais, tree, align_lparen, Space.None); // ( | | |
| 1370 | // try renderExpression(ais, tree, align_expr, Space.None); | | |
| 1371 | // try renderToken(ais, tree, align_rparen, Space.Space); // ) | | |
| 1372 | // } | | |
| 1373 | | | |
| 1374 | // if (fn_proto.getSectionExpr()) |section_expr| { | | |
| 1375 | // const section_rparen = tree.nextToken(section_expr.lastToken()); | | |
| 1376 | // const section_lparen = tree.prevToken(section_expr.firstToken()); | | |
| 1377 | // const section_kw = tree.prevToken(section_lparen); | | |
| 1378 | | | |
| 1379 | // try renderToken(ais, tree, section_kw, Space.None); // section | | |
| 1380 | // try renderToken(ais, tree, section_lparen, Space.None); // ( | | |
| 1381 | // try renderExpression(ais, tree, section_expr, Space.None); | | |
| 1382 | // try renderToken(ais, tree, section_rparen, Space.Space); // ) | | |
| 1383 | // } | | |
| 1384 | | | |
| 1385 | // if (fn_proto.getCallconvExpr()) |callconv_expr| { | | |
| 1386 | // const callconv_rparen = tree.nextToken(callconv_expr.lastToken()); | | |
| 1387 | // const callconv_lparen = tree.prevToken(callconv_expr.firstToken()); | | |
| 1388 | // const callconv_kw = tree.prevToken(callconv_lparen); | | |
| 1389 | | | |
| 1390 | // try renderToken(ais, tree, callconv_kw, Space.None); // callconv | | |
| 1391 | // try renderToken(ais, tree, callconv_lparen, Space.None); // ( | | |
| 1392 | // try renderExpression(ais, tree, callconv_expr, Space.None); | | |
| 1393 | // try renderToken(ais, tree, callconv_rparen, Space.Space); // ) | | |
| 1394 | // } else if (fn_proto.getIsExternPrototype() != null) { | | |
| 1395 | // try ais.writer().writeAll("callconv(.C) "); | | |
| 1396 | // } else if (fn_proto.getIsAsync() != null) { | | |
| 1397 | // try ais.writer().writeAll("callconv(.Async) "); | | |
| 1398 | // } | | |
| 1399 | | | |
| 1400 | // switch (fn_proto.return_type) { | | |
| 1401 | // .Explicit => |node| { | | |
| 1402 | // return renderExpression(ais, tree, node, space); | | |
| 1403 | // }, | | |
| 1404 | // .InferErrorSet => |node| { | | |
| 1405 | // try renderToken(ais, tree, tree.prevToken(node.firstToken()), Space.None); // ! | | |
| 1406 | // return renderExpression(ais, tree, node, space); | | |
| 1407 | // }, | | |
| 1408 | // .Invalid => unreachable, | | |
| 1409 | // } | | |
| 1410 | //}, | | |
| 1411 | | 1253 | |
| 1412 | .AnyFrameType => unreachable, // TODO | 1254 | .AnyFrameType => unreachable, // TODO |
| 1413 | //.AnyFrameType => { | 1255 | //.AnyFrameType => { |
| ... | @@ -2130,30 +1972,6 @@ fn renderContainerField( | ... | @@ -2130,30 +1972,6 @@ fn renderContainerField( |
| 2130 | return renderExpressionComma(ais, tree, field.ast.value_expr, space); // value | 1972 | return renderExpressionComma(ais, tree, field.ast.value_expr, space); // value |
| 2131 | } | 1973 | } |
| 2132 | | 1974 | |
| 2133 | fn renderParamDecl( | | |
| 2134 | allocator: *mem.Allocator, | | |
| 2135 | ais: *Ais, | | |
| 2136 | tree: ast.Tree, | | |
| 2137 | param_decl: ast.Node.FnProto.ParamDecl, | | |
| 2138 | space: Space, | | |
| 2139 | ) Error!void { | | |
| 2140 | try renderDocComments(ais, tree, param_decl, param_decl.doc_comments); | | |
| 2141 | | | |
| 2142 | if (param_decl.comptime_token) |comptime_token| { | | |
| 2143 | try renderToken(ais, tree, comptime_token, Space.Space); | | |
| 2144 | } | | |
| 2145 | if (param_decl.noalias_token) |noalias_token| { | | |
| 2146 | try renderToken(ais, tree, noalias_token, Space.Space); | | |
| 2147 | } | | |
| 2148 | if (param_decl.name_token) |name_token| { | | |
| 2149 | try renderToken(ais, tree, name_token, Space.None); | | |
| 2150 | try renderToken(ais, tree, tree.nextToken(name_token), Space.Space); // : | | |
| 2151 | } | | |
| 2152 | switch (param_decl.param_type) { | | |
| 2153 | .any_type, .type_expr => |node| try renderExpression(ais, tree, node, space), | | |
| 2154 | } | | |
| 2155 | } | | |
| 2156 | | | |
| 2157 | fn renderBuiltinCall( | 1975 | fn renderBuiltinCall( |
| 2158 | ais: *Ais, | 1976 | ais: *Ais, |
| 2159 | tree: ast.Tree, | 1977 | tree: ast.Tree, |
| ... | @@ -2200,6 +2018,239 @@ fn renderBuiltinCall( | ... | @@ -2200,6 +2018,239 @@ fn renderBuiltinCall( |
| 2200 | } | 2018 | } |
| 2201 | } | 2019 | } |
| 2202 | | 2020 | |
| | 2021 | fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.Full.FnProto, space: Space) Error!void { |
| | 2022 | const token_tags = tree.tokens.items(.tag); |
| | 2023 | |
| | 2024 | const after_fn_token = fn_proto.ast.fn_token + 1; |
| | 2025 | const lparen = if (token_tags[after_fn_token] == .Identifier) blk: { |
| | 2026 | try renderToken(ais, tree, fn_proto.ast.fn_token, .Space); // fn |
| | 2027 | try renderToken(ais, tree, after_fn_token, .None); // name |
| | 2028 | break :blk after_fn_token + 1; |
| | 2029 | } else blk: { |
| | 2030 | try renderToken(ais, tree, fn_proto.ast.fn_token, .Space); // fn |
| | 2031 | break :blk fn_proto.ast.fn_token + 1; |
| | 2032 | }; |
| | 2033 | assert(token_tags[lparen] == .LParen); |
| | 2034 | |
| | 2035 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; |
| | 2036 | const rparen = blk: { |
| | 2037 | // The first token for the annotation expressions is the left |
| | 2038 | // parenthesis, hence the need for two previous tokens. |
| | 2039 | if (fn_proto.ast.align_expr != 0) { |
| | 2040 | break :blk tree.firstToken(fn_proto.ast.align_expr) - 3; |
| | 2041 | } |
| | 2042 | if (fn_proto.ast.section_expr != 0) { |
| | 2043 | break :blk tree.firstToken(fn_proto.ast.section_expr) - 3; |
| | 2044 | } |
| | 2045 | if (fn_proto.ast.callconv_expr != 0) { |
| | 2046 | break :blk tree.firstToken(fn_proto.ast.callconv_expr) - 3; |
| | 2047 | } |
| | 2048 | if (token_tags[maybe_bang] == .Bang) { |
| | 2049 | break :blk maybe_bang - 1; |
| | 2050 | } |
| | 2051 | break :blk maybe_bang; |
| | 2052 | }; |
| | 2053 | assert(token_tags[rparen] == .RParen); |
| | 2054 | |
| | 2055 | // The params list is a sparse set that does *not* include anytype or ... parameters. |
| | 2056 | |
| | 2057 | if (token_tags[rparen - 1] != .Comma) { |
| | 2058 | // Render all on one line, no trailing comma. |
| | 2059 | try renderToken(ais, tree, lparen, .None); // ( |
| | 2060 | |
| | 2061 | var param_i: usize = 0; |
| | 2062 | var last_param_token = lparen; |
| | 2063 | while (true) { |
| | 2064 | last_param_token += 1; |
| | 2065 | switch (token_tags[last_param_token]) { |
| | 2066 | .DocComment => { |
| | 2067 | try renderToken(ais, tree, last_param_token, .Newline); |
| | 2068 | continue; |
| | 2069 | }, |
| | 2070 | .Ellipsis3 => { |
| | 2071 | try renderToken(ais, tree, last_param_token, .None); // ... |
| | 2072 | break; |
| | 2073 | }, |
| | 2074 | .Keyword_noalias, .Keyword_comptime => { |
| | 2075 | try renderToken(ais, tree, last_param_token, .Space); |
| | 2076 | last_param_token += 1; |
| | 2077 | }, |
| | 2078 | .Identifier => {}, |
| | 2079 | .Keyword_anytype => { |
| | 2080 | try renderToken(ais, tree, last_param_token, .None); // anytype |
| | 2081 | continue; |
| | 2082 | }, |
| | 2083 | .RParen => break, |
| | 2084 | .Comma => { |
| | 2085 | try renderToken(ais, tree, last_param_token, .Space); // , |
| | 2086 | last_param_token += 1; |
| | 2087 | }, |
| | 2088 | else => unreachable, |
| | 2089 | } |
| | 2090 | if (token_tags[last_param_token] == .Identifier) { |
| | 2091 | try renderToken(ais, tree, last_param_token, .None); // name |
| | 2092 | last_param_token += 1; |
| | 2093 | try renderToken(ais, tree, last_param_token, .Space); // : |
| | 2094 | last_param_token += 1; |
| | 2095 | } |
| | 2096 | if (token_tags[last_param_token] == .Keyword_anytype) { |
| | 2097 | try renderToken(ais, tree, last_param_token, .None); // anytype |
| | 2098 | continue; |
| | 2099 | } |
| | 2100 | const param = fn_proto.ast.params[param_i]; |
| | 2101 | param_i += 1; |
| | 2102 | try renderExpression(ais, tree, param, .None); |
| | 2103 | last_param_token = tree.lastToken(param) + 1; |
| | 2104 | } |
| | 2105 | } else { |
| | 2106 | // One param per line. |
| | 2107 | ais.pushIndent(); |
| | 2108 | try renderToken(ais, tree, lparen, .Newline); // ( |
| | 2109 | |
| | 2110 | var param_i: usize = 0; |
| | 2111 | var last_param_token = lparen; |
| | 2112 | while (true) { |
| | 2113 | last_param_token += 1; |
| | 2114 | switch (token_tags[last_param_token]) { |
| | 2115 | .DocComment => { |
| | 2116 | try renderToken(ais, tree, last_param_token, .Newline); |
| | 2117 | continue; |
| | 2118 | }, |
| | 2119 | .Ellipsis3 => { |
| | 2120 | try renderToken(ais, tree, last_param_token, .Comma); // ... |
| | 2121 | break; |
| | 2122 | }, |
| | 2123 | .Keyword_noalias, .Keyword_comptime => { |
| | 2124 | try renderToken(ais, tree, last_param_token, .Space); |
| | 2125 | last_param_token += 1; |
| | 2126 | }, |
| | 2127 | .Identifier => {}, |
| | 2128 | .Keyword_anytype => { |
| | 2129 | try renderToken(ais, tree, last_param_token, .Comma); // anytype |
| | 2130 | continue; |
| | 2131 | }, |
| | 2132 | .RParen => break, |
| | 2133 | else => unreachable, |
| | 2134 | } |
| | 2135 | if (token_tags[last_param_token] == .Identifier) { |
| | 2136 | try renderToken(ais, tree, last_param_token, .None); // name |
| | 2137 | last_param_token += 1; |
| | 2138 | try renderToken(ais, tree, last_param_token, .Space); // : |
| | 2139 | last_param_token += 1; |
| | 2140 | } |
| | 2141 | if (token_tags[last_param_token] == .Keyword_anytype) { |
| | 2142 | try renderToken(ais, tree, last_param_token, .Comma); // anytype |
| | 2143 | continue; |
| | 2144 | } |
| | 2145 | const param = fn_proto.ast.params[param_i]; |
| | 2146 | param_i += 1; |
| | 2147 | try renderExpression(ais, tree, param, .Comma); |
| | 2148 | last_param_token = tree.lastToken(param) + 2; |
| | 2149 | } |
| | 2150 | ais.popIndent(); |
| | 2151 | } |
| | 2152 | |
| | 2153 | try renderToken(ais, tree, rparen, .Space); // ) |
| | 2154 | |
| | 2155 | if (fn_proto.ast.align_expr != 0) { |
| | 2156 | const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1; |
| | 2157 | const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1; |
| | 2158 | |
| | 2159 | try renderToken(ais, tree, align_lparen - 1, .None); // align |
| | 2160 | try renderToken(ais, tree, align_lparen, .None); // ( |
| | 2161 | try renderExpression(ais, tree, fn_proto.ast.align_expr, .None); |
| | 2162 | try renderToken(ais, tree, align_rparen, .Space); // ) |
| | 2163 | } |
| | 2164 | |
| | 2165 | if (fn_proto.ast.section_expr != 0) { |
| | 2166 | const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1; |
| | 2167 | const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1; |
| | 2168 | |
| | 2169 | try renderToken(ais, tree, section_lparen - 1, .None); // section |
| | 2170 | try renderToken(ais, tree, section_lparen, .None); // ( |
| | 2171 | try renderExpression(ais, tree, fn_proto.ast.section_expr, .None); |
| | 2172 | try renderToken(ais, tree, section_rparen, .Space); // ) |
| | 2173 | } |
| | 2174 | |
| | 2175 | if (fn_proto.ast.callconv_expr != 0) { |
| | 2176 | const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1; |
| | 2177 | const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1; |
| | 2178 | |
| | 2179 | try renderToken(ais, tree, callconv_lparen - 1, .None); // callconv |
| | 2180 | try renderToken(ais, tree, callconv_lparen, .None); // ( |
| | 2181 | try renderExpression(ais, tree, fn_proto.ast.callconv_expr, .None); |
| | 2182 | try renderToken(ais, tree, callconv_rparen, .Space); // ) |
| | 2183 | } |
| | 2184 | |
| | 2185 | if (token_tags[maybe_bang] == .Bang) { |
| | 2186 | try renderToken(ais, tree, maybe_bang, .None); // ! |
| | 2187 | } |
| | 2188 | return renderExpression(ais, tree, fn_proto.ast.return_type, space); |
| | 2189 | } |
| | 2190 | |
| | 2191 | fn renderBlock( |
| | 2192 | ais: *Ais, |
| | 2193 | tree: ast.Tree, |
| | 2194 | lbrace: ast.TokenIndex, |
| | 2195 | statements: []const ast.Node.Index, |
| | 2196 | space: Space, |
| | 2197 | ) Error!void { |
| | 2198 | const token_tags = tree.tokens.items(.tag); |
| | 2199 | const node_tags = tree.nodes.items(.tag); |
| | 2200 | |
| | 2201 | if (token_tags[lbrace - 1] == .Colon and |
| | 2202 | token_tags[lbrace - 2] == .Identifier) |
| | 2203 | { |
| | 2204 | try renderToken(ais, tree, lbrace - 2, .None); |
| | 2205 | try renderToken(ais, tree, lbrace - 1, .Space); |
| | 2206 | } |
| | 2207 | const nodes_data = tree.nodes.items(.data); |
| | 2208 | |
| | 2209 | if (statements.len == 0) { |
| | 2210 | ais.pushIndentNextLine(); |
| | 2211 | try renderToken(ais, tree, lbrace, .None); |
| | 2212 | ais.popIndent(); |
| | 2213 | const rbrace = lbrace + 1; |
| | 2214 | return renderToken(ais, tree, rbrace, space); |
| | 2215 | } else { |
| | 2216 | ais.pushIndentNextLine(); |
| | 2217 | |
| | 2218 | try renderToken(ais, tree, lbrace, .Newline); |
| | 2219 | |
| | 2220 | for (statements) |stmt, i| { |
| | 2221 | switch (node_tags[stmt]) { |
| | 2222 | .GlobalVarDecl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)), |
| | 2223 | .LocalVarDecl => try renderVarDecl(ais, tree, tree.localVarDecl(stmt)), |
| | 2224 | .SimpleVarDecl => try renderVarDecl(ais, tree, tree.simpleVarDecl(stmt)), |
| | 2225 | .AlignedVarDecl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)), |
| | 2226 | else => { |
| | 2227 | const semicolon = tree.lastToken(stmt) + 1; |
| | 2228 | if (token_tags[semicolon] == .Semicolon) { |
| | 2229 | try renderExpression(ais, tree, stmt, .None); |
| | 2230 | try renderToken(ais, tree, semicolon, .Newline); |
| | 2231 | } else { |
| | 2232 | try renderExpression(ais, tree, stmt, .Newline); |
| | 2233 | } |
| | 2234 | }, |
| | 2235 | } |
| | 2236 | |
| | 2237 | if (i + 1 < statements.len) { |
| | 2238 | try renderExtraNewline(ais, tree, statements[i + 1]); |
| | 2239 | } |
| | 2240 | } |
| | 2241 | ais.popIndent(); |
| | 2242 | // The rbrace could be +1 or +2 from the last token of the last |
| | 2243 | // statement in the block because lastToken() does not count semicolons. |
| | 2244 | const maybe_rbrace = tree.lastToken(statements[statements.len - 1]) + 1; |
| | 2245 | if (token_tags[maybe_rbrace] == .RBrace) { |
| | 2246 | return renderToken(ais, tree, maybe_rbrace, space); |
| | 2247 | } else { |
| | 2248 | assert(token_tags[maybe_rbrace + 1] == .RBrace); |
| | 2249 | return renderToken(ais, tree, maybe_rbrace + 1, space); |
| | 2250 | } |
| | 2251 | } |
| | 2252 | } |
| | 2253 | |
| 2203 | /// Render an expression, and the comma that follows it, if it is present in the source. | 2254 | /// Render an expression, and the comma that follows it, if it is present in the source. |
| 2204 | fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void { | 2255 | fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void { |
| 2205 | const token_tags = tree.tokens.items(.tag); | 2256 | const token_tags = tree.tokens.items(.tag); |