mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 00:08:56 +00:00
add zig fmt fix for async/extern fn
This commit is contained in:
parent
7ada59f873
commit
d0e996405b
@ -880,6 +880,8 @@ pub const Node = struct {
|
||||
align_expr: ?*Node, // populated if align(A) is present
|
||||
section_expr: ?*Node, // populated if linksection(A) is present
|
||||
callconv_expr: ?*Node, // populated if callconv(A) is present
|
||||
is_extern_prototype: bool = false, // TODO: Remove once extern fn rewriting is
|
||||
is_async: bool = false, // TODO: remove once async fn rewriting is
|
||||
|
||||
pub const ParamList = SegmentedList(*Node, 2);
|
||||
|
||||
|
||||
@ -337,7 +337,25 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
|
||||
|
||||
/// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
|
||||
fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||
const fn_token = eatToken(it, .Keyword_fn) orelse return null;
|
||||
// TODO: Remove once extern/async fn rewriting is
|
||||
var is_async = false;
|
||||
var is_extern = false;
|
||||
const cc_token: ?usize = blk: {
|
||||
if (eatToken(it, .Keyword_extern)) |token| {
|
||||
is_extern = true;
|
||||
break :blk token;
|
||||
}
|
||||
if (eatToken(it, .Keyword_async)) |token| {
|
||||
is_async = true;
|
||||
break :blk token;
|
||||
}
|
||||
break :blk null;
|
||||
};
|
||||
const fn_token = eatToken(it, .Keyword_fn) orelse {
|
||||
if (cc_token) |token|
|
||||
putBackToken(it, token);
|
||||
return null;
|
||||
};
|
||||
const name_token = eatToken(it, .Identifier);
|
||||
const lparen = try expectToken(it, tree, .LParen);
|
||||
const params = try parseParamDeclList(arena, it, tree);
|
||||
@ -381,6 +399,8 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||
.align_expr = align_expr,
|
||||
.section_expr = section_expr,
|
||||
.callconv_expr = callconv_expr,
|
||||
.is_extern_prototype = is_extern,
|
||||
.is_async = is_async,
|
||||
};
|
||||
|
||||
return &fn_proto_node.base;
|
||||
@ -1175,6 +1195,16 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||
const maybe_async = eatToken(it, .Keyword_async);
|
||||
if (maybe_async) |async_token| {
|
||||
const token_fn = eatToken(it, .Keyword_fn);
|
||||
if (token_fn != null) {
|
||||
// TODO: remove this hack when async fn rewriting is
|
||||
// HACK: If we see the keyword `fn`, then we assume that
|
||||
// we are parsing an async fn proto, and not a call.
|
||||
// We therefore put back all tokens consumed by the async
|
||||
// prefix...
|
||||
putBackToken(it, token_fn.?);
|
||||
putBackToken(it, async_token);
|
||||
return parsePrimaryTypeExpr(arena, it, tree);
|
||||
}
|
||||
var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, .{
|
||||
.ExpectedPrimaryTypeExpr = .{ .token = it.index },
|
||||
});
|
||||
|
||||
@ -236,10 +236,10 @@ test "zig fmt: anon list literal syntax" {
|
||||
test "zig fmt: async function" {
|
||||
try testCanonical(
|
||||
\\pub const Server = struct {
|
||||
\\ handleRequestFn: async fn (*Server, *const std.net.Address, File) void,
|
||||
\\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void,
|
||||
\\};
|
||||
\\test "hi" {
|
||||
\\ var ptr = @ptrCast(async fn (i32) void, other);
|
||||
\\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
@ -435,15 +435,6 @@ test "zig fmt: aligned struct field" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: preserve space between async fn definitions" {
|
||||
try testCanonical(
|
||||
\\async fn a() void {}
|
||||
\\
|
||||
\\async fn b() void {}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: comment to disable/enable zig fmt first" {
|
||||
try testCanonical(
|
||||
\\// Test trailing comma syntax
|
||||
@ -1499,7 +1490,7 @@ test "zig fmt: line comments in struct initializer" {
|
||||
|
||||
test "zig fmt: first line comment in struct initializer" {
|
||||
try testCanonical(
|
||||
\\pub async fn acquire(self: *Self) HeldLock {
|
||||
\\pub fn acquire(self: *Self) HeldLock {
|
||||
\\ return HeldLock{
|
||||
\\ // guaranteed allocation elision
|
||||
\\ .held = self.lock.acquire(),
|
||||
@ -2461,8 +2452,7 @@ test "zig fmt: fn type" {
|
||||
\\}
|
||||
\\
|
||||
\\const a: fn (u8) u8 = undefined;
|
||||
\\const b: extern fn (u8) u8 = undefined;
|
||||
\\const c: fn (u8) callconv(.Naked) u8 = undefined;
|
||||
\\const b: fn (u8) callconv(.Naked) u8 = undefined;
|
||||
\\const ap: fn (u8) u8 = a;
|
||||
\\
|
||||
);
|
||||
@ -2484,7 +2474,7 @@ test "zig fmt: inline asm" {
|
||||
|
||||
test "zig fmt: async functions" {
|
||||
try testCanonical(
|
||||
\\async fn simpleAsyncFn() void {
|
||||
\\fn simpleAsyncFn() void {
|
||||
\\ const a = async a.b();
|
||||
\\ x += 1;
|
||||
\\ suspend;
|
||||
@ -2920,6 +2910,25 @@ test "zig fmt: noasync to nosuspend" {
|
||||
\\pub fn main() void {
|
||||
\\ nosuspend call();
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: convert async fn into callconv(.Async)" {
|
||||
try testTransform(
|
||||
\\async fn foo() void {}
|
||||
,
|
||||
\\fn foo() callconv(.Async) void {}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: convert extern fn proto into callconv(.C)" {
|
||||
try testTransform(
|
||||
\\extern fn foo0() void {}
|
||||
\\const foo1 = extern fn () void;
|
||||
,
|
||||
\\extern fn foo0() void {}
|
||||
\\const foo1 = fn () callconv(.C) void;
|
||||
\\
|
||||
);
|
||||
}
|
||||
@ -2970,7 +2979,6 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
|
||||
anything_changed.* = try std.zig.render(allocator, buffer.outStream(), tree);
|
||||
return buffer.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn testTransform(source: []const u8, expected_source: []const u8) !void {
|
||||
const needed_alloc_count = x: {
|
||||
// Try it once with unlimited memory, make sure it works
|
||||
@ -3018,11 +3026,9 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn testCanonical(source: []const u8) !void {
|
||||
return testTransform(source, source);
|
||||
}
|
||||
|
||||
fn testError(source: []const u8) !void {
|
||||
const tree = try std.zig.parse(std.testing.allocator, source);
|
||||
defer tree.deinit();
|
||||
|
||||
@ -1414,7 +1414,8 @@ fn renderExpression(
|
||||
}
|
||||
|
||||
if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
|
||||
try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export
|
||||
if (!fn_proto.is_extern_prototype)
|
||||
try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export/inline
|
||||
}
|
||||
|
||||
if (fn_proto.lib_name) |lib_name| {
|
||||
@ -1510,6 +1511,10 @@ fn renderExpression(
|
||||
try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // (
|
||||
try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None);
|
||||
try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // )
|
||||
} else if (fn_proto.is_extern_prototype) {
|
||||
try stream.writeAll("callconv(.C) ");
|
||||
} else if (fn_proto.is_async) {
|
||||
try stream.writeAll("callconv(.Async) ");
|
||||
}
|
||||
|
||||
switch (fn_proto.return_type) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user