From 600c303b15c6b7d828897900bed9aeb02be356cc Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 6 Nov 2022 22:36:10 +0100 Subject: [PATCH] Create generic member in lang.ast.nodes.Signature This will hold generic type components for methods and functions in the future, e.g.: function swap(T &$a, T &$b) { } --- .../php/lang/ast/nodes/Signature.class.php | 5 ++- src/main/php/lang/ast/syntax/PHP.class.php | 2 +- .../ast/unittest/parse/ClosuresTest.class.php | 14 +++--- .../ast/unittest/parse/CommentTest.class.php | 2 +- .../unittest/parse/FunctionsTest.class.php | 44 +++++++++---------- .../ast/unittest/parse/LambdasTest.class.php | 8 ++-- .../ast/unittest/parse/MembersTest.class.php | 12 ++--- 7 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/main/php/lang/ast/nodes/Signature.class.php b/src/main/php/lang/ast/nodes/Signature.class.php index 46df25d..8626cb8 100755 --- a/src/main/php/lang/ast/nodes/Signature.class.php +++ b/src/main/php/lang/ast/nodes/Signature.class.php @@ -4,11 +4,12 @@ class Signature extends Node { public $kind= 'signature'; - public $parameters, $returns; + public $parameters, $returns, $generic; - public function __construct($parameters= [], $returns= null, $line= -1) { + public function __construct($parameters= [], $returns= null, $generic= null, $line= -1) { $this->parameters= $parameters; $this->returns= $returns; + $this->generic= $generic; $this->line= $line; } diff --git a/src/main/php/lang/ast/syntax/PHP.class.php b/src/main/php/lang/ast/syntax/PHP.class.php index c84f3c4..03ab931 100755 --- a/src/main/php/lang/ast/syntax/PHP.class.php +++ b/src/main/php/lang/ast/syntax/PHP.class.php @@ -1417,7 +1417,7 @@ public function signature($parse) { $return= null; } - return new Signature($parameters, $return, $line); + return new Signature($parameters, $return, null, $line); } public function closure($parse, $static) { diff --git a/src/test/php/lang/ast/unittest/parse/ClosuresTest.class.php b/src/test/php/lang/ast/unittest/parse/ClosuresTest.class.php index d0f6596..30717e5 100755 --- a/src/test/php/lang/ast/unittest/parse/ClosuresTest.class.php +++ b/src/test/php/lang/ast/unittest/parse/ClosuresTest.class.php @@ -23,7 +23,7 @@ public function returns() { #[Test] public function with_body() { $this->assertParsed( - [new ClosureExpression(new Signature([], null, self::LINE), null, [$this->returns], false, self::LINE)], + [new ClosureExpression(new Signature([], null, null, self::LINE), null, [$this->returns], false, self::LINE)], 'function() { return $a + 1; };' ); } @@ -32,7 +32,7 @@ public function with_body() { public function with_param() { $params= [new Parameter('a', null, null, false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new ClosureExpression(new Signature($params, null, self::LINE), null, [$this->returns], false, self::LINE)], + [new ClosureExpression(new Signature($params, null, null, self::LINE), null, [$this->returns], false, self::LINE)], 'function($a) { return $a + 1; };' ); } @@ -40,7 +40,7 @@ public function with_param() { #[Test] public function with_use_by_value() { $this->assertParsed( - [new ClosureExpression(new Signature([], null, self::LINE), ['$a', '$b'], [$this->returns], false, self::LINE)], + [new ClosureExpression(new Signature([], null, null, self::LINE), ['$a', '$b'], [$this->returns], false, self::LINE)], 'function() use($a, $b) { return $a + 1; };' ); } @@ -48,7 +48,7 @@ public function with_use_by_value() { #[Test] public function with_use_by_reference() { $this->assertParsed( - [new ClosureExpression(new Signature([], null, self::LINE), ['$a', '&$b'], [$this->returns], false, self::LINE)], + [new ClosureExpression(new Signature([], null, null, self::LINE), ['$a', '&$b'], [$this->returns], false, self::LINE)], 'function() use($a, &$b) { return $a + 1; };' ); } @@ -56,7 +56,7 @@ public function with_use_by_reference() { #[Test] public function with_return_type() { $this->assertParsed( - [new ClosureExpression(new Signature([], new Type('int'), self::LINE), null, [$this->returns], false, self::LINE)], + [new ClosureExpression(new Signature([], new Type('int'), null, self::LINE), null, [$this->returns], false, self::LINE)], 'function(): int { return $a + 1; };' ); } @@ -64,7 +64,7 @@ public function with_return_type() { #[Test] public function with_nullable_return_type() { $this->assertParsed( - [new ClosureExpression(new Signature([], new Type('?int'), self::LINE), null, [$this->returns], false, self::LINE)], + [new ClosureExpression(new Signature([], new Type('?int'), null, self::LINE), null, [$this->returns], false, self::LINE)], 'function(): ?int { return $a + 1; };' ); } @@ -72,7 +72,7 @@ public function with_nullable_return_type() { #[Test] public function static_function() { $this->assertParsed( - [new ClosureExpression(new Signature([], null, self::LINE), null, [$this->returns], true, self::LINE)], + [new ClosureExpression(new Signature([], null, null, self::LINE), null, [$this->returns], true, self::LINE)], 'static function() { return $a + 1; };' ); } diff --git a/src/test/php/lang/ast/unittest/parse/CommentTest.class.php b/src/test/php/lang/ast/unittest/parse/CommentTest.class.php index d57329b..13737b7 100755 --- a/src/test/php/lang/ast/unittest/parse/CommentTest.class.php +++ b/src/test/php/lang/ast/unittest/parse/CommentTest.class.php @@ -146,7 +146,7 @@ class T { #[Test] public function apidoc_comment_attached_to_next_method() { $class= new ClassDeclaration([], new IsValue('\\T'), null, [], [], null, null, 2); - $class->declare(new Method(['public'], '__construct', new Signature([], null, 4), [], null, new Comment('/** @api */', 3), 4)); + $class->declare(new Method(['public'], '__construct', new Signature([], null, null, 4), [], null, new Comment('/** @api */', 3), 4)); $this->assertParsed([$class], ' class T { diff --git a/src/test/php/lang/ast/unittest/parse/FunctionsTest.class.php b/src/test/php/lang/ast/unittest/parse/FunctionsTest.class.php index f5a7141..90a6221 100755 --- a/src/test/php/lang/ast/unittest/parse/FunctionsTest.class.php +++ b/src/test/php/lang/ast/unittest/parse/FunctionsTest.class.php @@ -36,7 +36,7 @@ private function types() { #[Test] public function empty_function_without_parameters() { $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [], self::LINE)], 'function a() { }' ); } @@ -45,8 +45,8 @@ public function empty_function_without_parameters() { public function two_functions() { $this->assertParsed( [ - new FunctionDeclaration('a', new Signature([], null, self::LINE), [], self::LINE), - new FunctionDeclaration('b', new Signature([], null, self::LINE), [], self::LINE) + new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [], self::LINE), + new FunctionDeclaration('b', new Signature([], null, null, self::LINE), [], self::LINE) ], 'function a() { } function b() { }' ); @@ -56,7 +56,7 @@ public function two_functions() { public function with_parameter($name) { $params= [new Parameter($name, null, null, false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a($'.$name.') { }' ); } @@ -65,7 +65,7 @@ public function with_parameter($name) { public function with_reference_parameter() { $params= [new Parameter('param', null, null, true, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a(&$param) { }' ); } @@ -74,7 +74,7 @@ public function with_reference_parameter() { public function dangling_comma_in_parameter_lists() { $params= [new Parameter('param', null, null, false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a($param, ) { }' ); } @@ -83,7 +83,7 @@ public function dangling_comma_in_parameter_lists() { public function with_typed_parameter($declaration, $expected) { $params= [new Parameter('param', $expected, null, false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a('.$declaration.' $param) { }' ); } @@ -92,7 +92,7 @@ public function with_typed_parameter($declaration, $expected) { public function with_nullable_typed_parameter() { $params= [new Parameter('param', new IsNullable(new IsLiteral('string')), null, false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a(?string $param) { }' ); } @@ -101,7 +101,7 @@ public function with_nullable_typed_parameter() { public function with_variadic_parameter() { $params= [new Parameter('param', null, null, false, true, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a(... $param) { }' ); } @@ -110,7 +110,7 @@ public function with_variadic_parameter() { public function with_optional_parameter() { $params= [new Parameter('param', null, new Literal('null', self::LINE), false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a($param= null) { }' ); } @@ -119,7 +119,7 @@ public function with_optional_parameter() { public function with_parameter_named_function() { $params= [new Parameter('function', null, null, false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a($function, ) { }' ); } @@ -128,7 +128,7 @@ public function with_parameter_named_function() { public function with_typed_parameter_named_function() { $params= [new Parameter('function', new IsFunction([], new IsLiteral('void')), null, false, false, null, null, null, self::LINE)]; $this->assertParsed( - [new FunctionDeclaration('a', new Signature($params, null, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature($params, null, null, self::LINE), [], self::LINE)], 'function a((function(): void) $function) { }' ); } @@ -136,7 +136,7 @@ public function with_typed_parameter_named_function() { #[Test, Values('types')] public function with_return_type($declaration, $expected) { $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], $expected, self::LINE), [], self::LINE)], + [new FunctionDeclaration('a', new Signature([], $expected, null, self::LINE), [], self::LINE)], 'function a(): '.$declaration.' { }' ); } @@ -145,7 +145,7 @@ public function with_return_type($declaration, $expected) { public function generator() { $yield= new YieldExpression(null, null, self::LINE); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], 'function a() { yield; }' ); } @@ -154,7 +154,7 @@ public function generator() { public function generator_with_value() { $yield= new YieldExpression(null, new Literal('1', self::LINE), self::LINE); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], 'function a() { yield 1; }' ); } @@ -163,7 +163,7 @@ public function generator_with_value() { public function generator_with_key_and_value() { $yield= new YieldExpression(new Literal('"number"', self::LINE), new Literal('1', self::LINE), self::LINE); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], 'function a() { yield "number" => 1; }' ); } @@ -172,7 +172,7 @@ public function generator_with_key_and_value() { public function generator_delegation() { $yield= new YieldFromExpression(new ArrayLiteral([], self::LINE), self::LINE); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], 'function a() { yield from []; }' ); } @@ -186,7 +186,7 @@ public function assign_to_yield() { self::LINE ); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], 'function a() { $value= yield; }' ); } @@ -200,7 +200,7 @@ public function assign_to_yield_with_braced() { self::LINE ); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], 'function a() { $value= yield (1); }' ); } @@ -215,7 +215,7 @@ public function assign_to_yield_in_braces() { self::LINE ); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], 'function a() { $value= (yield); }' ); } @@ -229,7 +229,7 @@ public function assign_to_yield_in_array($declaration) { self::LINE ); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], $declaration ); } @@ -243,7 +243,7 @@ public function assign_to_yield_in_map($declaration) { self::LINE ); $this->assertParsed( - [new FunctionDeclaration('a', new Signature([], null, self::LINE), [$yield], self::LINE)], + [new FunctionDeclaration('a', new Signature([], null, null, self::LINE), [$yield], self::LINE)], $declaration ); } diff --git a/src/test/php/lang/ast/unittest/parse/LambdasTest.class.php b/src/test/php/lang/ast/unittest/parse/LambdasTest.class.php index 0fe41c5..d784779 100755 --- a/src/test/php/lang/ast/unittest/parse/LambdasTest.class.php +++ b/src/test/php/lang/ast/unittest/parse/LambdasTest.class.php @@ -15,7 +15,7 @@ public function expression() { #[Test] public function short_closure() { $this->assertParsed( - [new LambdaExpression(new Signature([$this->parameter], null, self::LINE), $this->expression, false, self::LINE)], + [new LambdaExpression(new Signature([$this->parameter], null, null, self::LINE), $this->expression, false, self::LINE)], 'fn($a) => $a + 1;' ); } @@ -23,7 +23,7 @@ public function short_closure() { #[Test] public function static_closure() { $this->assertParsed( - [new LambdaExpression(new Signature([$this->parameter], null, self::LINE), $this->expression, true, self::LINE)], + [new LambdaExpression(new Signature([$this->parameter], null, null, self::LINE), $this->expression, true, self::LINE)], 'static fn($a) => $a + 1;' ); } @@ -33,7 +33,7 @@ public function short_closure_as_arg() { $this->assertParsed( [new InvokeExpression( new Literal('execute', self::LINE), - [new LambdaExpression(new Signature([$this->parameter], null, self::LINE), $this->expression, false, self::LINE)], + [new LambdaExpression(new Signature([$this->parameter], null, null, self::LINE), $this->expression, false, self::LINE)], self::LINE )], 'execute(fn($a) => $a + 1);' @@ -44,7 +44,7 @@ public function short_closure_as_arg() { public function short_closure_with_block() { $this->assertParsed( [new LambdaExpression( - new Signature([$this->parameter], null, self::LINE), + new Signature([$this->parameter], null, null, self::LINE), new Block([new ReturnStatement($this->expression, self::LINE)], self::LINE), false, self::LINE diff --git a/src/test/php/lang/ast/unittest/parse/MembersTest.class.php b/src/test/php/lang/ast/unittest/parse/MembersTest.class.php index 866a1f5..b1a2d01 100755 --- a/src/test/php/lang/ast/unittest/parse/MembersTest.class.php +++ b/src/test/php/lang/ast/unittest/parse/MembersTest.class.php @@ -54,7 +54,7 @@ public function private_instance_properties() { #[Test] public function private_instance_method() { $class= new ClassDeclaration([], new IsValue('\\A'), null, [], [], null, null, self::LINE); - $class->declare(new Method(['private'], 'a', new Signature([], null, self::LINE), [], null, null, self::LINE)); + $class->declare(new Method(['private'], 'a', new Signature([], null, null, self::LINE), [], null, null, self::LINE)); $this->assertParsed([$class], 'class A { private function a() { } }'); } @@ -62,7 +62,7 @@ public function private_instance_method() { #[Test] public function private_static_method() { $class= new ClassDeclaration([], new IsValue('\\A'), null, [], [], null, null, self::LINE); - $class->declare(new Method(['private', 'static'], 'a', new Signature([], null, self::LINE), [], null, null, self::LINE)); + $class->declare(new Method(['private', 'static'], 'a', new Signature([], null, null, self::LINE), [], null, null, self::LINE)); $this->assertParsed([$class], 'class A { private static function a() { } }'); } @@ -96,7 +96,7 @@ public function private_class_constant() { public function method_with_typed_parameter($declaration, $expected) { $class= new ClassDeclaration([], new IsValue('\\A'), null, [], [], null, null, self::LINE); $params= [new Parameter('param', $expected, null, false, false, null, null, null, self::LINE)]; - $class->declare(new Method(['public'], 'a', new Signature($params, null, self::LINE), [], null, null, self::LINE)); + $class->declare(new Method(['public'], 'a', new Signature($params, null, null, self::LINE), [], null, null, self::LINE)); $this->assertParsed([$class], 'class A { public function a('.$declaration.' $param) { } }'); } @@ -104,7 +104,7 @@ public function method_with_typed_parameter($declaration, $expected) { #[Test, Values('types')] public function method_with_return_type($declaration, $expected) { $class= new ClassDeclaration([], new IsValue('\\A'), null, [], [], null, null, self::LINE); - $class->declare(new Method(['public'], 'a', new Signature([], $expected, self::LINE), [], null, null, self::LINE)); + $class->declare(new Method(['public'], 'a', new Signature([], $expected, null, self::LINE), [], null, null, self::LINE)); $this->assertParsed([$class], 'class A { public function a(): '.$declaration.' { } }'); } @@ -113,7 +113,7 @@ public function method_with_return_type($declaration, $expected) { public function method_with_annotation() { $annotations= new Annotations(['Test' => []], self::LINE); $class= new ClassDeclaration([], new IsValue('\\A'), null, [], [], null, null, self::LINE); - $class->declare(new Method(['public'], 'a', new Signature([], null, self::LINE), [], $annotations, null, self::LINE)); + $class->declare(new Method(['public'], 'a', new Signature([], null, null, self::LINE), [], $annotations, null, self::LINE)); $this->assertParsed([$class], 'class A { #[Test] public function a() { } }'); } @@ -122,7 +122,7 @@ public function method_with_annotation() { public function method_with_annotations() { $annotations= new Annotations(['Test' => [], 'Ignore' => [new Literal('"Not implemented"', self::LINE)]], self::LINE); $class= new ClassDeclaration([], new IsValue('\\A'), null, [], [], null, null, self::LINE); - $class->declare(new Method(['public'], 'a', new Signature([], null, self::LINE), [], $annotations, null, self::LINE)); + $class->declare(new Method(['public'], 'a', new Signature([], null, null, self::LINE), [], $annotations, null, self::LINE)); $this->assertParsed([$class], 'class A { #[Test, Ignore("Not implemented")] public function a() { } }'); }