zig fmt: support bodyless function decls

extern function declarations do not have a body, so allow setting
the rhs for FnDecl to 0 to indicate this is the case.
This commit is contained in:
Isaac Freund 2021-02-10 15:19:30 +01:00 committed by Andrew Kelley
parent 80b719d967
commit a524e57090
4 changed files with 52 additions and 14 deletions

View File

@ -521,7 +521,8 @@ pub const Tree = struct {
.IfSimple,
.WhileSimple,
.ForSimple,
.FnDecl,
.FnProtoSimple,
.FnProtoMulti,
.PtrTypeAligned,
.PtrTypeSentinel,
.PtrType,
@ -538,8 +539,6 @@ pub const Tree = struct {
.AsmSimple,
.AsmOutput,
.AsmInput,
.FnProtoSimple,
.FnProtoMulti,
.ErrorValue,
=> return datas[n].rhs + end_offset,
@ -804,6 +803,13 @@ pub const Tree = struct {
return main_tokens[n] + end_offset;
}
},
.FnDecl => {
if (datas[n].rhs != 0) {
n = datas[n].rhs;
} else {
n = datas[n].lhs;
}
},
.FnProtoOne => {
const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne);
// linksection, callconv, align can appear in any order, so we
@ -2520,7 +2526,9 @@ pub const Node = struct {
/// `fn(a: b, c: d) rhs linksection(e) callconv(f)`. `FnProto[lhs]`.
/// anytype and ... parameters are omitted from the AST tree.
FnProto,
/// lhs is the FnProto, rhs is the function body block.
/// lhs is the FnProto.
/// rhs is the function body block if non-zero.
/// if rhs is zero, the funtion decl has no body (e.g. an extern function)
FnDecl,
/// `anyframe->rhs`. main_token is `anyframe`. `lhs` is arrow token index.
AnyFrameType,

View File

@ -516,7 +516,14 @@ const Parser = struct {
.Semicolon => {
const semicolon_token = p.nextToken();
try p.parseAppendedDocComment(semicolon_token);
return fn_proto;
return p.addNode(.{
.tag = .FnDecl,
.main_token = p.nodes.items(.main_token)[fn_proto],
.data = .{
.lhs = fn_proto,
.rhs = 0,
},
});
},
.LBrace => {
const body_block = try p.parseBlock();

View File

@ -298,12 +298,12 @@ test "zig fmt: grouped expressions (parentheses)" {
);
}
//test "zig fmt: c pointer type" {
// try testCanonical(
// \\pub extern fn repro() [*c]const u8;
// \\
// );
//}
test "zig fmt: c pointer type" {
try testCanonical(
\\pub extern fn repro() [*c]const u8;
\\
);
}
test "zig fmt: builtin call with trailing comma" {
try testCanonical(
@ -2339,7 +2339,23 @@ test "zig fmt: alignment" {
// \\
// );
//}
//
test "zig fmt: function attributes" {
try testCanonical(
\\export fn foo() void {}
\\pub export fn foo() void {}
\\extern fn foo() void;
\\pub extern fn foo() void;
\\extern "c" fn foo() void;
\\pub extern "c" fn foo() void;
\\inline fn foo() void {}
\\pub inline fn foo() void {}
\\noinline fn foo() void {}
\\pub noinline fn foo() void {}
\\
);
}
//test "zig fmt: pointer attributes" {
// try testCanonical(
// \\extern fn f1(s: *align(*u8) u8) c_int;

View File

@ -121,6 +121,8 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E
.Keyword_export,
.Keyword_pub,
.StringLiteral,
.Keyword_inline,
.Keyword_noinline,
=> continue,
else => {
@ -132,8 +134,13 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E
while (i < fn_token) : (i += 1) {
try renderToken(ais, tree, i, .Space);
}
try renderExpression(ais, tree, fn_proto, .Space);
return renderExpression(ais, tree, datas[decl].rhs, space);
if (datas[decl].rhs != 0) {
try renderExpression(ais, tree, fn_proto, .Space);
return renderExpression(ais, tree, datas[decl].rhs, space);
} else {
try renderExpression(ais, tree, fn_proto, .None);
return renderToken(ais, tree, tree.lastToken(fn_proto) + 1, space); // semicolon
}
},
.FnProtoSimple,
.FnProtoMulti,