renderMember
Function parameters
Parameters
Type definitions in this namespace
Types
Functions in this namespace
Functions
Error sets in this namespace
Error Sets
Source
Implementation
fn renderMember(
r: *Render,
container: Container,
decl: Ast.Node.Index,
space: Space,
) Error!void {
const tree = r.tree;
const ais = r.ais;
if (r.fixups.omit_nodes.contains(decl)) return;
try renderDocComments(r, tree.firstToken(decl));
switch (tree.nodeTag(decl)) {
.fn_decl => {
// Some examples:
// pub extern "foo" fn ...
// export fn ...
const fn_proto, const body_node = tree.nodeData(decl).node_and_node;
const fn_token = tree.nodeMainToken(fn_proto);
// Go back to the first token we should render here.
var i = fn_token;
while (i > 0) {
i -= 1;
switch (tree.tokenTag(i)) {
.keyword_extern,
.keyword_export,
.keyword_pub,
.string_literal,
.keyword_inline,
.keyword_noinline,
=> continue,
else => {
i += 1;
break;
},
}
}
while (i < fn_token) : (i += 1) {
try renderToken(r, i, .space);
}
switch (tree.nodeTag(fn_proto)) {
.fn_proto_one, .fn_proto => {
var buf: [1]Ast.Node.Index = undefined;
const opt_callconv_expr = if (tree.nodeTag(fn_proto) == .fn_proto_one)
tree.fnProtoOne(&buf, fn_proto).ast.callconv_expr
else
tree.fnProto(fn_proto).ast.callconv_expr;
// Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE
if (opt_callconv_expr.unwrap()) |callconv_expr| {
if (tree.nodeTag(callconv_expr) == .enum_literal) {
if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) {
try ais.underlying_writer.writeAll("inline ");
}
}
}
},
.fn_proto_simple, .fn_proto_multi => {},
else => unreachable,
}
try renderExpression(r, fn_proto, .space);
if (r.fixups.gut_functions.contains(decl)) {
try ais.pushIndent(.normal);
const lbrace = tree.nodeMainToken(body_node);
try renderToken(r, lbrace, .newline);
try discardAllParams(r, fn_proto);
try ais.writeAll("@trap();");
ais.popIndent();
try ais.insertNewline();
try renderToken(r, tree.lastToken(body_node), space); // rbrace
} else if (r.fixups.unused_var_decls.count() != 0) {
try ais.pushIndent(.normal);
const lbrace = tree.nodeMainToken(body_node);
try renderToken(r, lbrace, .newline);
var fn_proto_buf: [1]Ast.Node.Index = undefined;
const full_fn_proto = tree.fullFnProto(&fn_proto_buf, fn_proto).?;
var it = full_fn_proto.iterate(&tree);
while (it.next()) |param| {
const name_ident = param.name_token.?;
assert(tree.tokenTag(name_ident) == .identifier);
if (r.fixups.unused_var_decls.contains(name_ident)) {
try ais.writeAll("_ = ");
try ais.writeAll(tokenSliceForRender(r.tree, name_ident));
try ais.writeAll(";\n");
}
}
var statements_buf: [2]Ast.Node.Index = undefined;
const statements = tree.blockStatements(&statements_buf, body_node).?;
return finishRenderBlock(r, body_node, statements, space);
} else {
return renderExpression(r, body_node, space);
}
},
.fn_proto_simple,
.fn_proto_multi,
.fn_proto_one,
.fn_proto,
=> {
// Extern function prototypes are parsed as these tags.
// Go back to the first token we should render here.
const fn_token = tree.nodeMainToken(decl);
var i = fn_token;
while (i > 0) {
i -= 1;
switch (tree.tokenTag(i)) {
.keyword_extern,
.keyword_export,
.keyword_pub,
.string_literal,
.keyword_inline,
.keyword_noinline,
=> continue,
else => {
i += 1;
break;
},
}
}
while (i < fn_token) : (i += 1) {
try renderToken(r, i, .space);
}
try renderExpression(r, decl, .none);
return renderToken(r, tree.lastToken(decl) + 1, space); // semicolon
},
.global_var_decl,
.local_var_decl,
.simple_var_decl,
.aligned_var_decl,
=> {
try ais.pushSpace(.semicolon);
try renderVarDecl(r, tree.fullVarDecl(decl).?, false, .semicolon);
ais.popSpace();
},
.test_decl => {
const test_token = tree.nodeMainToken(decl);
const opt_name_token, const block_node = tree.nodeData(decl).opt_token_and_node;
try renderToken(r, test_token, .space);
if (opt_name_token.unwrap()) |name_token| {
switch (tree.tokenTag(name_token)) {
.string_literal => try renderToken(r, name_token, .space),
.identifier => try renderIdentifier(r, name_token, .space, .preserve_when_shadowing),
else => unreachable,
}
}
try renderExpression(r, block_node, space);
},
.container_field_init,
.container_field_align,
.container_field,
=> return renderContainerField(r, container, tree.fullContainerField(decl).?, space),
.@"comptime" => return renderExpression(r, decl, space),
.root => unreachable,
else => unreachable,
}
}