Răsfoiți Sursa

Abstract abstract (#10513)

* Abstract abstract

* completion item huh?

* T_T

* Handle generics

* Nah, block

* Revert block again, add display test
RblSb 3 ani în urmă
părinte
comite
43f28cc42c

+ 3 - 0
src/context/display/displayToplevel.ml

@@ -430,6 +430,9 @@ let collect ctx tk with_type sort =
 					| Some(c,tl) -> add (make_ci_literal "super" (tpair (TInst(c,tl)))) (Some "super")
 					| None -> ()
 				end
+			| FunMemberAbstract ->
+				let t = TInst(ctx.curclass,List.map snd ctx.curclass.cl_params) in
+				add (make_ci_literal "abstract" (tpair t)) (Some "abstract");
 			| _ ->
 				()
 		end;

+ 2 - 1
src/syntax/grammar.mly

@@ -1328,6 +1328,7 @@ and expr = parser
 	| [< '(Kwd Final,p1); v = parse_var_decl true >] -> (EVars [v],p1)
 	| [< '(Const c,p); s >] -> expr_next (EConst c,p) s
 	| [< '(Kwd This,p); s >] -> expr_next (EConst (Ident "this"),p) s
+	| [< '(Kwd Abstract,p); s >] -> expr_next (EConst (Ident "abstract"),p) s
 	| [< '(Kwd True,p); s >] -> expr_next (EConst (Ident "true"),p) s
 	| [< '(Kwd False,p); s >] -> expr_next (EConst (Ident "false"),p) s
 	| [< '(Kwd Null,p); s >] -> expr_next (EConst (Ident "null"),p) s
@@ -1682,4 +1683,4 @@ let rec parse_macro_cond s =
 		cond
 	with e ->
 		parsing_macro_cond := false;
-		raise e
+		raise e

+ 12 - 0
src/typing/typer.ml

@@ -281,6 +281,18 @@ let rec type_ident_raise ctx i p mode with_type =
 			AKExpr (get_this ctx p)
 		| (MCall _, KAbstractImpl _) | (MGet, _)-> AKExpr(get_this ctx p)
 		| _ -> AKNo i)
+	| "abstract" ->
+		begin match mode, ctx.curclass.cl_kind with
+			| MSet _, KAbstractImpl ab -> typing_error "Property 'abstract' is read-only" p;
+			| (MGet, KAbstractImpl ab)
+			| (MCall _, KAbstractImpl ab) ->
+				let tl = List.map snd ab.a_params in
+				let e = get_this ctx p in
+				let e = {e with etype = TAbstract (ab,tl)} in
+				AKExpr e
+			| _ ->
+				typing_error "Property 'abstract' is reserved and only available in abstracts" p
+		end
 	| "super" ->
 		let t = (match ctx.curclass.cl_super with
 			| None -> typing_error "Current class does not have a superclass" p

+ 35 - 0
tests/display/src/cases/Abstract.hx

@@ -44,4 +44,39 @@ class Abstract extends DisplayTestCase {
 		eq(false, hasField(fields, "instanceField", "() -> Void"));
 		eq(true, hasField(fields, "staticField", "() -> Void"));
 	}
+
+	/**
+		abstract MyAbstract(String) {
+			public function new() this = "foo";
+
+			public function instanceField():Void {
+				{-1-}
+			}
+			static public function staticField():Void {
+				{-2-}
+			}
+			public function instanceField2():Void {
+				ab{-3-}stract;
+			}
+		}
+		abstract AbGeneric<T>(T) {
+			public function new(a:T) this = a;
+			public function foo() {
+				return ab{-4-}stract.bar();
+			}
+			public function bar() {
+				return th{-5-}is;
+			}
+		}
+	**/
+	function test3():Void {
+		final fields = toplevel(pos(1));
+		eq(true, hasToplevel(fields, "literal", "abstract"));
+		final fields = toplevel(pos(2));
+		eq(false, hasToplevel(fields, "literal", "abstract"));
+		// TODO: improve display hints
+		// eq("cases.MyAbstract", type(pos(3)));
+		// eq("cases.AbGeneric<cases.AbGeneric.T>", type(pos(4)));
+		eq("cases.AbGeneric.T", type(pos(5)));
+	}
 }

+ 7 - 0
tests/misc/projects/Issue10482/Main.hx

@@ -0,0 +1,7 @@
+class Main {
+	static function main() {
+		abstract;
+		abstract();
+		abstract + 1;
+	}
+}

+ 2 - 0
tests/misc/projects/Issue10482/compile-fail.hxml

@@ -0,0 +1,2 @@
+--main Main
+--interp

+ 3 - 0
tests/misc/projects/Issue10482/compile-fail.hxml.stderr

@@ -0,0 +1,3 @@
+Main.hx:3: characters 3-11 : Property 'abstract' is reserved and only available in abstracts
+Main.hx:4: characters 3-11 : Property 'abstract' is reserved and only available in abstracts
+Main.hx:5: characters 3-11 : Property 'abstract' is reserved and only available in abstracts

+ 86 - 0
tests/unit/src/unit/issues/Issue10482.hx

@@ -0,0 +1,86 @@
+package unit.issues;
+
+class Issue10482 extends Test {
+	function test() {
+		final ab = new MyAbstract(1);
+		final arr = ab.foo();
+		eq('plus 2', arr[0]);
+		eq("call", arr[1]);
+		eq("hi", arr[2]);
+
+		eq(1, ab.arr()[0].arr()[0].value());
+		eq("plus 3", ab + 3);
+		eq("call", ab());
+		eq("hi", ab.arr()[0].hi());
+
+		final ab = new MyInlineAbstract(1);
+		final arr = ab.foo();
+		eq('plus 2', arr[0]);
+		eq("call", arr[1]);
+		eq("hi", arr[2]);
+
+		eq(1, ab.arr()[0].arr()[0].value());
+		eq("plus 3", ab + 3);
+		eq("call", ab());
+		eq("hi", ab.arr()[0].hi());
+
+		final ab = new AbGeneric(1.5);
+		eq(1.5, ab.foo());
+	}
+}
+
+abstract MyAbstract(Int) {
+	public function new(a):Void this = a;
+
+	public function foo():Array<String> {
+		return [
+			abstract + 2,
+			abstract(),
+			abstract.hi()
+		];
+	}
+
+	public function hi() return "hi";
+
+	public function arr() return [abstract];
+
+	@:op(a()) function call() return "call";
+
+	@:op(a + b) function plus(b) return 'plus $b';
+
+	public function value():Int return this;
+}
+
+abstract MyInlineAbstract(Int) {
+	public inline function new(a):Void this = a;
+
+	public inline function foo():Array<String> {
+		return [
+			abstract + 2,
+			abstract(),
+			abstract.hi()
+		];
+	}
+
+	public function hi() return "hi";
+
+	public function arr() return [abstract];
+
+	@:op(a()) function call() return "call";
+
+	@:op(a + b) function plus(b) return 'plus $b';
+
+	public function value():Int return this;
+}
+
+abstract AbGeneric<T>(T) {
+	public function new(a:T):Void {
+		this = a;
+	}
+	public function foo() {
+		return abstract.bar();
+	}
+	public function bar() {
+		return this;
+	}
+}