ソースを参照

Merge branch 'coroutines_2024_server_tests' into coroutines_2024

Simon Krajewski 1 年間 前
コミット
ba7604b94f

+ 0 - 1
src/context/dotGraph.ml

@@ -1,5 +1,4 @@
 open Common
-open Type
 
 let get_dump_path com path name =
 	(dump_path com) :: [platform_name_macro com] @ (fst path) @ [Printf.sprintf "%s.%s" (snd path) name]

+ 0 - 1
src/coro/coroTypes.ml

@@ -1,4 +1,3 @@
-open Common
 open Globals
 open Type
 

+ 1 - 1
tests/RunCi.hx

@@ -37,7 +37,7 @@ class RunCi {
 			infoMsg('test $test');
 			try {
 				changeDirectory(unitDir);
-				haxelibInstallGit("haxe-utest", "utest", "424a7182a93057730fada54b9d27d90b3cb7065c", "--always");
+				haxelibInstallGit("kLabz", "utest", "coro", "--always");
 
 				var args = switch (ci) {
 					case null:

+ 38 - 24
tests/server/src/TestCase.hx

@@ -1,6 +1,7 @@
 import SkipReason;
 import haxe.PosInfos;
 import haxe.Exception;
+import haxe.coro.Coroutine;
 import haxe.display.Position;
 import haxeserver.HaxeServerRequestResult;
 import haxe.display.JsonModuleTypes;
@@ -77,7 +78,8 @@ class TestCase implements ITest implements ITestCase {
 	public function setup(async:utest.Async) {
 		testDir = "test/cases/" + i++;
 		vfs = new Vfs(testDir);
-		runHaxeJson(["--cwd", rootCwd, "--cwd", testDir], Methods.ResetCache, {}, () -> {
+		runHaxeJson.start(["--cwd", rootCwd, "--cwd", testDir], Methods.ResetCache, {}, (_,err) -> {
+			if (err != null) throw err;
 			async.done();
 		});
 	}
@@ -99,42 +101,54 @@ class TestCase implements ITest implements ITestCase {
 		}
 	}
 
-	function runHaxe(args:Array<String>, done:() -> Void) {
+	@:coroutine
+	function runHaxe(args:Array<String>) {
 		messages = [];
 		errorMessages = [];
-		server.rawRequest(args, null, function(result) {
-			handleResult(result);
-			if (result.hasError) {
-				sendErrorMessage(result.stderr);
-			}
-			done();
-		}, sendErrorMessage);
+
+		Coroutine.suspend(cont -> {
+			server.rawRequest(args, null, function(result) {
+				handleResult(result);
+				if (result.hasError) {
+					sendErrorMessage(result.stderr);
+				}
+				cont(null, null);
+			}, err -> {
+				sendErrorMessage(err);
+				cont(null, null);
+			});
+		});
 	}
 
-	function runHaxeJson<TParams, TResponse>(args:Array<String>, method:HaxeRequestMethod<TParams, TResponse>, methodArgs:TParams, done:() -> Void) {
+	@:coroutine
+	function runHaxeJson<TParams, TResponse>(args:Array<String>, method:HaxeRequestMethod<TParams, TResponse>, methodArgs:TParams) {
 		var methodArgs = {method: method, id: 1, params: methodArgs};
 		args = args.concat(['--display', Json.stringify(methodArgs)]);
-		runHaxe(args, done);
+		runHaxe(args);
 	}
 
+	@:coroutine
 	function runHaxeJsonCb<TParams, TResponse>(args:Array<String>, method:HaxeRequestMethod<TParams, Response<TResponse>>, methodArgs:TParams,
-			callback:TResponse->Void, done:() -> Void) {
+			callback:TResponse->Void) {
 		var methodArgs = {method: method, id: 1, params: methodArgs};
 		args = args.concat(['--display', Json.stringify(methodArgs)]);
 		messages = [];
 		errorMessages = [];
-		server.rawRequest(args, null, function(result) {
-			handleResult(result);
-			var json = Json.parse(result.stderr);
-			if (json.result != null) {
-				callback(json.result.result);
-			} else {
-				sendErrorMessage('Error: ' + json.error);
-			}
-			done();
-		}, function(msg) {
-			sendErrorMessage(msg);
-			done();
+
+		Coroutine.suspend(cont -> {
+			server.rawRequest(args, null, function(result) {
+				handleResult(result);
+				var json = Json.parse(result.stderr);
+				if (json.result != null) {
+					callback(json.result.result);
+				} else {
+					sendErrorMessage('Error: ' + json.error);
+				}
+				cont(null, null);
+			}, function(msg) {
+				sendErrorMessage(msg);
+				cont(null, null);
+			});
 		});
 	}
 

+ 11 - 8
tests/server/src/cases/CsSafeTypeBuilding.hx

@@ -12,14 +12,17 @@ class CsSafeTypeBuilding extends TestCase {
 	var originalContent:String;
 
 	override public function setup(async:utest.Async) {
-		super.setup(async);
-
-		originalContent = "";
-		vfs.putContent("Bar.hx", getTemplate("csSafeTypeBuilding/Bar.hx"));
-		vfs.putContent("Baz.hx", getTemplate("csSafeTypeBuilding/Baz.hx"));
-		vfs.putContent("Foo.hx", getTemplate("csSafeTypeBuilding/Foo.hx"));
-		vfs.putContent("Macro.macro.hx", getTemplate("csSafeTypeBuilding/Macro.macro.hx"));
-		vfs.putContent("Main.hx", getTemplate("csSafeTypeBuilding/Main.hx"));
+		super.setup(async.branch());
+
+		async.branch(async -> {
+			originalContent = "";
+			vfs.putContent("Bar.hx", getTemplate("csSafeTypeBuilding/Bar.hx"));
+			vfs.putContent("Baz.hx", getTemplate("csSafeTypeBuilding/Baz.hx"));
+			vfs.putContent("Foo.hx", getTemplate("csSafeTypeBuilding/Foo.hx"));
+			vfs.putContent("Macro.macro.hx", getTemplate("csSafeTypeBuilding/Macro.macro.hx"));
+			vfs.putContent("Main.hx", getTemplate("csSafeTypeBuilding/Main.hx"));
+			async.done();
+		});
 	}
 
 	#if debug

+ 115 - 115
tests/server/src/cases/ReplaceRanges.hx

@@ -7,13 +7,13 @@ import utest.Assert.*;
 
 // TODO: somebody has to clean this up
 class ReplaceRanges extends TestCase {
-	function complete<S, T>(content:String, markerIndex:Int, cb:(response:CompletionResponse<S, T>, markers:Map<Int, Int>) -> Void) {
+	@:coroutine
+	function complete<S, T>(content:String, markerIndex:Int) {
 		var transform = Marker.extractMarkers(content);
 		vfs.putContent("Main.hx", transform.source);
-		runHaxeJson([], DisplayMethods.Completion, {file: new FsPath("Main.hx"), offset: transform.markers[markerIndex], wasAutoTriggered: true}, function() {
-			var result = parseCompletion();
-			cb(result.result, transform.markers);
-		});
+		runHaxeJson([], DisplayMethods.Completion, {file: new FsPath("Main.hx"), offset: transform.markers[markerIndex], wasAutoTriggered: true});
+		var result = parseCompletion();
+		return {response: result.result, markers: transform.markers};
 	}
 
 	function checkReplaceRange<S, T>(markers:Map<Int, Int>, startIndex:Int, endIndex:Int, response:CompletionResponse<S, T>, ?p:PosInfos) {
@@ -22,184 +22,184 @@ class ReplaceRanges extends TestCase {
 	}
 
 	function testType() {
-		complete("{-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("{-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("{-1-}cl{-2-}", 2);
-		equals("cl", response.filterString);
-		checkReplaceRange(markers, 1, 2, response);
+		var result = complete("{-1-}cl{-2-}", 2);
+		equals("cl", result.response.filterString);
+		checkReplaceRange(result.markers, 1, 2, result.response);
 	}
 
 	function testModifier() {
-		complete("extern {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("extern {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("extern {-1-}cl{-2-}", 2);
-		equals("cl", response.filterString);
-		checkReplaceRange(markers, 1, 2, response);
+		var result = complete("extern {-1-}cl{-2-}", 2);
+		equals("cl", result.response.filterString);
+		checkReplaceRange(result.markers, 1, 2, result.response);
 	}
 
 	function testExtends() {
-		complete("class C extends {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("class C extends {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("class C extends {-1-}Cl{-2-}", 2);
-		equals("Cl", response.filterString);
-		checkReplaceRange(markers, 1, 2, response);
+		var result = complete("class C extends {-1-}Cl{-2-}", 2);
+		equals("Cl", result.response.filterString);
+		checkReplaceRange(result.markers, 1, 2, result.response);
 
-		complete("class C {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("class C {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("class C {-1-}ex{-2-}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("ex", response.filterString);
+		var result = complete("class C {-1-}ex{-2-}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("ex", result.response.filterString);
 
-		complete("class C {-1-}ext{-2-} {}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("ext", response.filterString);
+		var result = complete("class C {-1-}ext{-2-} {}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("ext", result.response.filterString);
 	}
 
 	function testImplements() {
-		complete("class C implements {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("class C implements {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("class C implements {-1-}Cl{-2-}", 2);
-		equals("Cl", response.filterString);
-		checkReplaceRange(markers, 1, 2, response);
+		var result = complete("class C implements {-1-}Cl{-2-}", 2);
+		equals("Cl", result.response.filterString);
+		checkReplaceRange(result.markers, 1, 2, result.response);
 
-		complete("class C {-1-} {}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("class C {-1-} {}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("class C {-1-}impl{-2-} {}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("impl", response.filterString);
+		var result = complete("class C {-1-}impl{-2-} {}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("impl", result.response.filterString);
 	}
 
 	function testImport() {
-		complete("import {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("import {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("import {-1-}Cl{-2-}", 2);
-		// equals("Cl", response.filterString);
-		checkReplaceRange(markers, 1, 2, response);
+		var result = complete("import {-1-}Cl{-2-}", 2);
+		// equals("Cl", result.response.filterString);
+		checkReplaceRange(result.markers, 1, 2, result.response);
 	}
 
 	function testUsing() {
-		complete("using {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("using {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("using {-1-}Cl{-2-}", 2);
-		// equals("Cl", response.filterString);
-		checkReplaceRange(markers, 1, 2, response);
+		var result = complete("using {-1-}Cl{-2-}", 2);
+		// equals("Cl", result.response.filterString);
+		checkReplaceRange(result.markers, 1, 2, result.response);
 	}
 
 	function testTo() {
-		complete("abstract A(String) to {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("abstract A(String) to {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("abstract A(String) to {-1-} { }", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("abstract A(String) to {-1-} { }", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("abstract A(String) to {-1-}Cl{-2-}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("abstract A(String) to {-1-}Cl{-2-}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 
-		complete("abstract A(String) to {-1-}Cl{-2-} { }", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("abstract A(String) to {-1-}Cl{-2-} { }", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 	}
 
 	function testFrom() {
-		complete("abstract A(String) from {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("abstract A(String) from {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("abstract A(String) from {-1-} { }", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("abstract A(String) from {-1-} { }", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("abstract A(String) from {-1-}Cl{-2-}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("abstract A(String) from {-1-}Cl{-2-}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 
-		complete("abstract A(String) from {-1-}Cl{-2-} { }", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("abstract A(String) from {-1-}Cl{-2-} { }", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 	}
 
 	function testStructuralExtension() {
-		complete("typedef Main = { } & {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("typedef Main = { } & {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("typedef Main = { } & {-1-}Cl{-2-}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("typedef Main = { } & {-1-}Cl{-2-}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 
-		complete("typedef Main = { > {-1-}", 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete("typedef Main = { > {-1-}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete("typedef Main = { > {-1-}Cl{-2-}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("typedef Main = { > {-1-}Cl{-2-}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 	}
 
 	function testFields() {
-		complete('class Main { static function main() "".{-1-}', 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete('class Main { static function main() "".{-1-}', 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete('class Main { static function main() "".{-1-}char', 1);
-		checkReplaceRange(markers, 1, 1, response);
+		var result = complete('class Main { static function main() "".{-1-}char', 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
 
-		complete('class Main { static function main() "".{-1-}char{-2-}', 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("char", response.filterString);
+		var result = complete('class Main { static function main() "".{-1-}char{-2-}', 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("char", result.response.filterString);
 	}
 
 	function testOverride() {
-		complete("import haxe.io.Bytes; class Main extends Bytes { static function main() { } override {-1-}}", 1);
-		checkReplaceRange(markers, 1, 1, response);
-		equals("", response.filterString);
+		var result = complete("import haxe.io.Bytes; class Main extends Bytes { static function main() { } override {-1-}}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
+		equals("", result.response.filterString);
 
-		complete("import haxe.io.Bytes; class Main extends Bytes { static function main() { } override {-1-}get{-2-}}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("get", response.filterString);
+		var result = complete("import haxe.io.Bytes; class Main extends Bytes { static function main() { } override {-1-}get{-2-}}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("get", result.response.filterString);
 	}
 
 	function testTypedef() {
-		complete("typedef Foo = {-1-}
+		var result = complete("typedef Foo = {-1-}
 		", 1);
-		checkReplaceRange(markers, 1, 1, response);
-		equals("", response.filterString);
+		checkReplaceRange(result.markers, 1, 1, result.response);
+		equals("", result.response.filterString);
 
-		complete("typedef Foo = {-1-}Cl{-2-}
+		var result = complete("typedef Foo = {-1-}Cl{-2-}
 		", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 	}
 
 	function testTypehint() {
-		complete("class Main { static function main() { var t:{-1-} }}", 1);
-		checkReplaceRange(markers, 1, 1, response);
-		equals("", response.filterString);
+		var result = complete("class Main { static function main() { var t:{-1-} }}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
+		equals("", result.response.filterString);
 
-		complete("class Main { static function main() { var t:{-1-}Cl{-2-} }}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("class Main { static function main() { var t:{-1-}Cl{-2-} }}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 
-		complete("class Main { static function main() { var t:{-1-}String{-2-} }}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("String", response.filterString);
+		var result = complete("class Main { static function main() { var t:{-1-}String{-2-} }}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("String", result.response.filterString);
 
-		complete("class Main { static function main() { var t:{-1-}Str{-2-}ing }}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Str", response.filterString);
+		var result = complete("class Main { static function main() { var t:{-1-}Str{-2-}ing }}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Str", result.response.filterString);
 	}
 
 	function testTypeParameter() {
-		complete("class Main { static function main() { var t:{-1-} }}", 1);
-		checkReplaceRange(markers, 1, 1, response);
-		equals("", response.filterString);
+		var result = complete("class Main { static function main() { var t:{-1-} }}", 1);
+		checkReplaceRange(result.markers, 1, 1, result.response);
+		equals("", result.response.filterString);
 
-		complete("class Main { static function main() { var t:{-1-}Cl{-2-} }}", 2);
-		checkReplaceRange(markers, 1, 2, response);
-		equals("Cl", response.filterString);
+		var result = complete("class Main { static function main() { var t:{-1-}Cl{-2-} }}", 2);
+		checkReplaceRange(result.markers, 1, 2, result.response);
+		equals("Cl", result.response.filterString);
 	}
 }

+ 6 - 11
tests/server/src/cases/ServerTests.hx

@@ -488,23 +488,18 @@ class ServerTests extends TestCase {
 		assertSuccess();
 	}
 
-	@:async function testStackOverflow(async:utest.Async) {
+	function testStackOverflow() {
 		vfs.putContent("Empty.hx", getTemplate("Empty.hx"));
 		var args = ["-main", "Empty.hx", "--macro", "allowPackage('sys')", "--interp", "--no-output"];
 		var runs = 0;
 
-		function runLoop() {
-			runHaxeJson(args, DisplayMethods.Diagnostics, {file: new FsPath("Empty.hx")}, () -> {
-				runHaxe(args.concat(["-D", "compile-only-define"]), () -> {
-					if (assertSuccess() && ++runs < 20)
-						runLoop();
-					else
-						async.done();
-				});
-			});
+		@:coroutine function runLoop() {
+			runHaxeJson(args, DisplayMethods.Diagnostics, {file: new FsPath("Empty.hx")});
+			runHaxe(args.concat(["-D", "compile-only-define"]));
+			if (assertSuccess() && ++runs < 20)
+				runLoop();
 		}
 
-		async.setTimeout(20000);
 		runLoop();
 	}
 

+ 5 - 77
tests/server/src/utils/macro/TestBuilder.macro.hx

@@ -22,12 +22,12 @@ class TestBuilder {
 				case FFun(f):
 					var variants = field.meta.filter(m -> m.name == ":variant");
 					if (variants.length == 0) {
-						makeAsyncTest(f, field.pos);
+						makeAsyncTest(field);
 					} else {
 						// TODO: support functions that define their own async arg (not named `_` or `async`)
 						var args = f.args.copy();
 						f.args = [];
-						makeAsyncTest(f, field.pos);
+						makeAsyncTest(field);
 
 						// Ignore original field; generate variants instead
 						removedFields.push(field);
@@ -88,80 +88,8 @@ class TestBuilder {
 		return fields.concat(newFields);
 	}
 
-	static function makeAsyncTest(f:Function, fpos:Position) {
-		var asyncName = switch f.args {
-			case []:
-				var name = "async";
-				f.args.push({
-					name: name,
-					type: macro:utest.Async
-				});
-				name;
-			case [arg]:
-				if (arg.name == "_") {
-					arg.name = "async";
-					arg.type = macro:utest.Async;
-				}
-				arg.name;
-			case _:
-				Context.fatalError('Unexpected amount of test arguments', fpos);
-				"";
-		}
-		switch (f.expr.expr) {
-			case EBlock(el):
-				var posInfos = Context.getPosInfos(f.expr.pos);
-				var pos = Context.makePosition({min: posInfos.max, max: posInfos.max, file: posInfos.file});
-				el.push(macro @:pos(pos) {
-					if ($i{asyncName}.timedOut) Assert.fail("timeout");
-					else $i{asyncName}.done();
-				});
-				f.expr = macro {
-					$i{asyncName}.setTimeout(20000);
-					${transformHaxeCalls(asyncName, el)};
-				}
-			case _:
-				Context.error("Block expression expected", f.expr.pos);
-		}
-	}
-
-	static function transformHaxeCalls(asyncName:String, el:Array<Expr>) {
-		var e0 = el.shift();
-		if (el.length == 0) {
-			return e0;
-		} else {
-			var e = switch e0 {
-				case macro runHaxe($a{args}):
-					var e = transformHaxeCalls(asyncName, el);
-					args.push(macro() -> ${failOnException(asyncName, e)});
-					macro runHaxe($a{args});
-				case macro runHaxeJson($a{args}):
-					var e = transformHaxeCalls(asyncName, el);
-					args.push(macro() -> ${failOnException(asyncName, e)});
-					macro runHaxeJson($a{args});
-				case macro runHaxeJsonCb($a{args}):
-					var e = transformHaxeCalls(asyncName, el);
-					args.push(macro() -> ${failOnException(asyncName, e)});
-					macro runHaxeJsonCb($a{args});
-				case macro complete($a{args}):
-					var e = transformHaxeCalls(asyncName, el);
-					args.push(macro function(response, markers) ${failOnException(asyncName, e)});
-					macro complete($a{args});
-				case _:
-					macro {$e0; ${transformHaxeCalls(asyncName, el)}};
-			}
-			e.pos = e0.pos;
-			return e;
-		}
-	}
-
-	static function failOnException(asyncName:String, e:Expr):Expr {
-		return macro
-			@:pos(e.pos) try {
-				$e;
-			} catch (e) {
-				Assert.fail(e.details());
-				$i{asyncName}.done();
-				return;
-			}
+	static function makeAsyncTest(field:Field) {
+		field.meta.push({name: ":coroutine", params: [], pos: field.pos});
+		field.meta.push({name: ":timeout", params: [macro 20000], pos: field.pos});
 	}
 }