Bläddra i källkod

port completion tests to the new thing, remove the old thing

Simon Krajewski 9 år sedan
förälder
incheckning
2d8d0a9b8e

+ 0 - 8
src/macro/interp.ml

@@ -107,7 +107,6 @@ type extern_api = {
 	resolve_type  : Ast.complex_type -> Ast.pos -> t;
 	type_macro_expr : Ast.expr -> Type.texpr;
 	store_typed_expr : Type.texpr -> Ast.expr;
-	get_display : string -> string;
 	allow_package : string -> unit;
 	type_patch : string -> string -> bool -> string option -> unit;
 	meta_patch : string -> string -> string option -> bool -> unit;
@@ -2485,13 +2484,6 @@ let macro_lib =
 			| VString(s),VAbstract(APos p) -> encode_expr ((get_ctx()).curapi.format_string s p)
 			| _ -> VNull
 		);
-		"display", Fun1 (fun v ->
-			match v with
-			| VString s ->
-				VString ((get_ctx()).curapi.get_display s)
-			| _ ->
-				error()
-		);
 		"allow_package", Fun1 (fun v ->
 			match v with
 			| VString s ->

+ 0 - 49
src/typing/typer.ml

@@ -4626,55 +4626,6 @@ let make_macro_api ctx p =
 			let eid = (EConst (Int (string_of_int id))), p in
 			(EMeta ((Meta.StoredTypedExpr,[],p), eid)), p
 		);
-		Interp.get_display = (fun s ->
-			let is_displaying = ctx.com.display <> DMNone in
-			let old_resume = !Parser.resume_display in
-			let old_error = ctx.on_error in
-			let restore () =
-				if not is_displaying then begin
-					ctx.com.defines <- PMap.remove (fst (Define.infos Define.Display)) ctx.com.defines;
-					ctx.com.display <- DMNone
-				end;
-				Parser.resume_display := old_resume;
-				ctx.on_error <- old_error;
-			in
-			(* temporarily enter display mode with a fake position *)
-			if not is_displaying then begin
-				Common.define ctx.com Define.Display;
-				ctx.com.display <- DMDefault;
-			end;
-			Parser.resume_display := {
-				Ast.pfile = "macro";
-				Ast.pmin = 0;
-				Ast.pmax = 0;
-			};
-			ctx.on_error <- (fun ctx msg p -> raise (Error(Custom msg,p)));
-			let str = try
-				let e = parse_expr_string s Ast.null_pos true in
-				let e = Optimizer.optimize_completion_expr e in
-				ignore (type_expr ctx e Value);
-				"NO COMPLETION"
-			with Display.DisplayFields fields ->
-				let pctx = print_context() in
-				String.concat "," (List.map (fun (f,t,_,_) -> f ^ ":" ^ s_type pctx t) fields)
-			| Display.DisplaySignatures tl ->
-				let pctx = print_context() in
-				String.concat "," (List.map (fun (t,_) -> s_type pctx t) tl)
-			| Display.DisplayType (t,_) ->
-				let pctx = print_context() in
-				s_type pctx t
-			| Parser.TypePath (p,sub,_) ->
-				(match sub with
-				| None ->
-					"path(" ^ String.concat "." p ^ ")"
-				| Some (c,_) ->
-					"path(" ^ String.concat "." p ^ ":" ^ c ^ ")")
-			| Typecore.Error (msg,p) ->
-				"error(" ^ error_msg msg ^ ")"
-			in
-			restore();
-			str
-		);
 		Interp.allow_package = (fun v -> Common.allow_package ctx.com v);
 		Interp.type_patch = (fun t f s v ->
 			typing_timer ctx false (fun() ->

+ 1 - 1
tests/display/src/DisplayTestCase.hx

@@ -8,7 +8,7 @@ class DisplayTestCase {
 
 	// api
 	inline function pos(name) return ctx.pos(name);
-	inline function field(pos) return ctx.field(pos);
+	inline function fields(pos) return ctx.fields(pos);
 	inline function toplevel(pos) return ctx.toplevel(pos);
 	inline function type(pos) return ctx.type(pos);
 	inline function position(pos) return ctx.position(pos);

+ 22 - 9
tests/display/src/DisplayTestContext.hx

@@ -27,37 +27,37 @@ class DisplayTestContext {
 		this.markers = markers;
 	}
 
-	public function pos(id:Int):Int {
+	public function pos(id:Int):Position {
 		var r = markers[id];
 		if (r == null) throw "No such marker: " + id;
-		return r;
+		return new Position(r);
 	}
 
 	public function range(pos1:Int, pos2:Int) {
 		return normalizePath(source.formatPosition(pos(pos1), pos(pos2)));
 	}
 
-	public function field(pos:Int):String {
-		return callHaxe('$pos');
+	public function fields(pos:Position):Array<FieldElement> {
+		return extractFields(callHaxe('$pos'));
 	}
 
-	public function toplevel(pos:Int):Array<ToplevelElement> {
+	public function toplevel(pos:Position):Array<ToplevelElement> {
 		return extractToplevel(callHaxe('$pos@toplevel'));
 	}
 
-	public function type(pos:Int):String {
+	public function type(pos:Position):String {
 		return extractType(callHaxe('$pos@type'));
 	}
 
-	public function positions(pos:Int):Array<String> {
+	public function positions(pos:Position):Array<String> {
 		return extractPositions(callHaxe('$pos@position'));
 	}
 
-	public function position(pos:Int):String {
+	public function position(pos:Position):String {
 		return positions(pos)[0];
 	}
 
-	public function usage(pos:Int):Array<String> {
+	public function usage(pos:Position):Array<String> {
 		return extractPositions(callHaxe('$pos@usage'));
 	}
 
@@ -118,6 +118,19 @@ class DisplayTestContext {
 		return ret;
 	}
 
+	static function extractFields(result:String) {
+		var xml = Xml.parse(result);
+		xml = xml.firstElement();
+		if (xml.nodeName != "list") {
+			return null;
+		}
+		var ret = [];
+		for (xml in xml.elementsNamed("i")) {
+			ret.push({name: xml.get("n"), type: xml.firstElement().firstChild().nodeValue});
+		}
+		return ret;
+	}
+
 	static function normalizePath(p:String):String {
 		if (!haxe.io.Path.isAbsolute(p)) {
 			p = Sys.getCwd() + p;

+ 10 - 2
tests/display/src/Macro.hx

@@ -1,6 +1,8 @@
 import haxe.macro.Context;
 import haxe.macro.Expr;
 
+using Lambda;
+
 class Macro {
 	static function buildTestCase():Array<Field> {
 		var fields = Context.getBuildFields();
@@ -13,7 +15,12 @@ class Macro {
 			if (field.doc == null) {
 				continue;
 			}
-			var doc = (c.pack.length > 0 ? "package " + c.pack.join(".") + ";\n" : "") + field.doc;
+			var doc = (c.pack.length > 0 ? "package " + c.pack.join(".") + ";\n" : "");
+			if (field.meta.exists(function(meta) return meta.name == ":funcCode")) {
+				doc += "class Main { static function main() { " + field.doc + "}}";
+			} else {
+				doc += field.doc;
+			}
 			var src = markerRe.map(doc, function(r) {
 				var p = r.matchedPos();
 				var name = r.matched(1);
@@ -22,8 +29,9 @@ class Macro {
 				markers.push(macro $v{Std.parseInt(name)} => $v{pos});
 				return "";
 			});
+			var markers = markers.length > 0 ? macro $a{markers} : macro new Map();
 			testCases.push(macro function() {
-				ctx = new DisplayTestContext($v{Context.getPosInfos(c.pos).file}, $v{field.name}, $v{src}, $a{markers});
+				ctx = new DisplayTestContext($v{Context.getPosInfos(c.pos).file}, $v{field.name}, $v{src}, $markers);
 				$i{field.name}();
 			});
 		}

+ 11 - 0
tests/display/src/Types.hx

@@ -2,3 +2,14 @@ typedef ToplevelElement = {
 	kind: String,
 	name: String
 }
+
+typedef FieldElement = {
+	name: String,
+	type: String
+}
+
+abstract Position(Int) to Int {
+	public inline function new(i:Int) {
+		this = i;
+	}
+}

+ 59 - 0
tests/display/src/cases/Completion.hx

@@ -0,0 +1,59 @@
+package cases;
+
+import Types;
+using Lambda;
+
+class Completion extends DisplayTestCase {
+	/**
+	var s = { foo: 1 };
+	s.{-1-}
+	**/
+	@:funcCode function testHaxeUnitPort1() {
+		eq(true, hasField(fields(pos(1)), "foo", "Int"));
+	}
+
+	/**
+	var s = { foo: 1 };
+	for (k in [s].iterator()) {
+		k.{-1-}
+	}
+	**/
+	@:funcCode function testHaxeUnitPort2() {
+		eq(true, hasField(fields(pos(1)), "foo", "Int"));
+	}
+
+	/**
+	var f = function():Iterator<{foo:Int}> {
+		return [s].iterator();
+	};
+	var s = { foo: 1 };
+	for (k in f()) {
+		k.{-1-}
+	}
+	**/
+	@:funcCode function testHaxeUnitPort3() {
+		eq(true, hasField(fields(pos(1)), "foo", "Int"));
+	}
+
+	/**
+	var x:haxe.macro.{-1-}
+	**/
+	@:funcCode function testHaxeUnitPort4() {
+		eq(true, hasPath(fields(pos(1)), "Expr"));
+	}
+
+	/**
+	var x:haxe.macro.Expr.{-1-}
+	**/
+	@:funcCode function testHaxeUnitPort5() {
+		eq(true, hasPath(fields(pos(1)), "ExprDef"));
+	}
+
+	static function hasField(a:Array<FieldElement>, name:String, type:String):Bool {
+		return a.exists(function(t) return t.type == type && t.name == name);
+	}
+
+	static function hasPath(a:Array<FieldElement>, name:String):Bool {
+		return a.exists(function(t) return t.name == name);
+	}
+}

+ 0 - 42
tests/unit/src/unit/TestType.hx

@@ -44,11 +44,6 @@ class TestType extends Test {
 		};
 	}
 
-	static public macro function complete(e:String) : haxe.macro.Expr.ExprOf<String> {
-		var str = new String(untyped haxe.macro.Context.load("display", 1)(e.__s));
-		return { expr : EConst(CString(str)), pos : haxe.macro.Context.currentPos() };
-	}
-
 	public function testType() {
 		var name = u("unit")+"."+u("MyClass");
 		eq( Type.resolveClass(name), unit.MyClass );
@@ -628,43 +623,6 @@ class TestType extends Test {
 		return a + "foo";
 	}
 
-	function testCompletion() {
-		#if !macro
-		var s = { foo: 1 };
-		eq(complete("s.|"), "foo:Int");
-		eq(complete("var x : haxe.|"), "path(haxe)");
-		eq(complete("var x : haxe.macro.Expr.|"), "path(haxe.macro:Expr)");
-
-		// could be improved by listing sub types
-		eq(complete("haxe.macro.Expr.|"), "error(haxe.macro.Expr is not a value)");
-
-		// know issue : the expr optimization will prevent inferring the array content
-		//eq(complete('{
-			//var a = [];
-			//a.push("");
-			//a[0].|
-		//}'),"Unknown<0>");
-
-		// could be improved : expr optimization assume that variable not in scope is a member
-		// so it will eliminate the assignement that would have forced it into the local context
-		// that would be useful when you want to write some code and add the member variable afterwards
-		eq(complete('{
-			unknownVar = "";
-			unknownVar.|
-		}'),"path(unknownVar)");
-
-
-		for (k in [s].iterator()) {
-			eq(complete("k.|"), "foo:Int");
-		}
-
-		var f = function():Iterator<{foo:Int}> {
-			return [s].iterator();
-		};
-		eq(complete("for (k in f()) k.|"), "foo:Int");
-		#end
-	}
-
 	function testSuperPropAccess() {
 		var c = new ChildSuperProp();
 		eq(c.prop, 2);