renderFnProto
Function parameters
Parameters
Type definitions in this namespace
Types
Functions in this namespace
Functions
Error sets in this namespace
Error Sets
Source
Implementation
fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
const tree = r.tree;
const ais = r.ais;
const after_fn_token = fn_proto.ast.fn_token + 1;
const lparen = if (tree.tokenTag(after_fn_token) == .identifier) blk: {
try renderToken(r, fn_proto.ast.fn_token, .space); // fn
try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name
break :blk after_fn_token + 1;
} else blk: {
try renderToken(r, fn_proto.ast.fn_token, .space); // fn
break :blk fn_proto.ast.fn_token + 1;
};
assert(tree.tokenTag(lparen) == .l_paren);
const return_type = fn_proto.ast.return_type.unwrap().?;
const maybe_bang = tree.firstToken(return_type) - 1;
const rparen = blk: {
// These may appear in any order, so we have to check the token_starts array
// to find out which is first.
var rparen = if (tree.tokenTag(maybe_bang) == .bang) maybe_bang - 1 else maybe_bang;
var smallest_start = tree.tokenStart(maybe_bang);
if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
const tok = tree.firstToken(align_expr) - 3;
const start = tree.tokenStart(tok);
if (start < smallest_start) {
rparen = tok;
smallest_start = start;
}
}
if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
const tok = tree.firstToken(addrspace_expr) - 3;
const start = tree.tokenStart(tok);
if (start < smallest_start) {
rparen = tok;
smallest_start = start;
}
}
if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
const tok = tree.firstToken(section_expr) - 3;
const start = tree.tokenStart(tok);
if (start < smallest_start) {
rparen = tok;
smallest_start = start;
}
}
if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
const tok = tree.firstToken(callconv_expr) - 3;
const start = tree.tokenStart(tok);
if (start < smallest_start) {
rparen = tok;
smallest_start = start;
}
}
break :blk rparen;
};
assert(tree.tokenTag(rparen) == .r_paren);
// The params list is a sparse set that does *not* include anytype or ... parameters.
const trailing_comma = tree.tokenTag(rparen - 1) == .comma;
if (!trailing_comma and !hasComment(tree, lparen, rparen)) {
// Render all on one line, no trailing comma.
try renderToken(r, lparen, .none); // (
var param_i: usize = 0;
var last_param_token = lparen;
while (true) {
last_param_token += 1;
switch (tree.tokenTag(last_param_token)) {
.doc_comment => {
try renderToken(r, last_param_token, .newline);
continue;
},
.ellipsis3 => {
try renderToken(r, last_param_token, .none); // ...
break;
},
.keyword_noalias, .keyword_comptime => {
try renderToken(r, last_param_token, .space);
last_param_token += 1;
},
.identifier => {},
.keyword_anytype => {
try renderToken(r, last_param_token, .none); // anytype
continue;
},
.r_paren => break,
.comma => {
try renderToken(r, last_param_token, .space); // ,
continue;
},
else => {}, // Parameter type without a name.
}
if (tree.tokenTag(last_param_token) == .identifier and
tree.tokenTag(last_param_token + 1) == .colon)
{
try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
last_param_token = last_param_token + 1;
try renderToken(r, last_param_token, .space); // :
last_param_token += 1;
}
if (tree.tokenTag(last_param_token) == .keyword_anytype) {
try renderToken(r, last_param_token, .none); // anytype
continue;
}
const param = fn_proto.ast.params[param_i];
param_i += 1;
try renderExpression(r, param, .none);
last_param_token = tree.lastToken(param);
}
} else {
// One param per line.
try ais.pushIndent(.normal);
try renderToken(r, lparen, .newline); // (
var param_i: usize = 0;
var last_param_token = lparen;
while (true) {
last_param_token += 1;
switch (tree.tokenTag(last_param_token)) {
.doc_comment => {
try renderToken(r, last_param_token, .newline);
continue;
},
.ellipsis3 => {
try renderToken(r, last_param_token, .comma); // ...
break;
},
.keyword_noalias, .keyword_comptime => {
try renderToken(r, last_param_token, .space);
last_param_token += 1;
},
.identifier => {},
.keyword_anytype => {
try renderToken(r, last_param_token, .comma); // anytype
if (tree.tokenTag(last_param_token + 1) == .comma)
last_param_token += 1;
continue;
},
.r_paren => break,
else => {}, // Parameter type without a name.
}
if (tree.tokenTag(last_param_token) == .identifier and
tree.tokenTag(last_param_token + 1) == .colon)
{
try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
last_param_token += 1;
try renderToken(r, last_param_token, .space); // :
last_param_token += 1;
}
if (tree.tokenTag(last_param_token) == .keyword_anytype) {
try renderToken(r, last_param_token, .comma); // anytype
if (tree.tokenTag(last_param_token + 1) == .comma)
last_param_token += 1;
continue;
}
const param = fn_proto.ast.params[param_i];
param_i += 1;
try ais.pushSpace(.comma);
try renderExpression(r, param, .comma);
ais.popSpace();
last_param_token = tree.lastToken(param);
if (tree.tokenTag(last_param_token + 1) == .comma) last_param_token += 1;
}
ais.popIndent();
}
try renderToken(r, rparen, .space); // )
if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
const align_lparen = tree.firstToken(align_expr) - 1;
const align_rparen = tree.lastToken(align_expr) + 1;
try renderToken(r, align_lparen - 1, .none); // align
try renderToken(r, align_lparen, .none); // (
try renderExpression(r, align_expr, .none);
try renderToken(r, align_rparen, .space); // )
}
if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
const align_lparen = tree.firstToken(addrspace_expr) - 1;
const align_rparen = tree.lastToken(addrspace_expr) + 1;
try renderToken(r, align_lparen - 1, .none); // addrspace
try renderToken(r, align_lparen, .none); // (
try renderExpression(r, addrspace_expr, .none);
try renderToken(r, align_rparen, .space); // )
}
if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
const section_lparen = tree.firstToken(section_expr) - 1;
const section_rparen = tree.lastToken(section_expr) + 1;
try renderToken(r, section_lparen - 1, .none); // section
try renderToken(r, section_lparen, .none); // (
try renderExpression(r, section_expr, .none);
try renderToken(r, section_rparen, .space); // )
}
if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
// Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)));
const is_declaration = fn_proto.name_token != null;
if (!(is_declaration and is_callconv_inline)) {
const callconv_lparen = tree.firstToken(callconv_expr) - 1;
const callconv_rparen = tree.lastToken(callconv_expr) + 1;
try renderToken(r, callconv_lparen - 1, .none); // callconv
try renderToken(r, callconv_lparen, .none); // (
try renderExpression(r, callconv_expr, .none);
try renderToken(r, callconv_rparen, .space); // )
}
}
if (tree.tokenTag(maybe_bang) == .bang) {
try renderToken(r, maybe_bang, .none); // !
}
return renderExpression(r, return_type, space);
}