Skip to content

Commit

Permalink
Merge pull request #40 from xp-framework/refactor/generic-signature
Browse files Browse the repository at this point in the history
Create generic member in lang.ast.nodes.Signature
  • Loading branch information
thekid authored Nov 6, 2022
2 parents 8fd27ec + 600c303 commit f40a57a
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 43 deletions.
5 changes: 3 additions & 2 deletions src/main/php/lang/ast/nodes/Signature.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/php/lang/ast/syntax/PHP.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 7 additions & 7 deletions src/test/php/lang/ast/unittest/parse/ClosuresTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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; };'
);
}
Expand All @@ -32,47 +32,47 @@ 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; };'
);
}

#[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; };'
);
}

#[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; };'
);
}

#[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; };'
);
}

#[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; };'
);
}

#[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; };'
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/php/lang/ast/unittest/parse/CommentTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
44 changes: 22 additions & 22 deletions src/test/php/lang/ast/unittest/parse/FunctionsTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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() { }'
);
}
Expand All @@ -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() { }'
);
Expand All @@ -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.') { }'
);
}
Expand All @@ -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) { }'
);
}
Expand All @@ -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, ) { }'
);
}
Expand All @@ -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) { }'
);
}
Expand All @@ -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) { }'
);
}
Expand All @@ -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) { }'
);
}
Expand All @@ -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) { }'
);
}
Expand All @@ -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, ) { }'
);
}
Expand All @@ -128,15 +128,15 @@ 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) { }'
);
}

#[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.' { }'
);
}
Expand All @@ -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; }'
);
}
Expand All @@ -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; }'
);
}
Expand All @@ -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; }'
);
}
Expand All @@ -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 []; }'
);
}
Expand All @@ -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; }'
);
}
Expand All @@ -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); }'
);
}
Expand All @@ -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); }'
);
}
Expand All @@ -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
);
}
Expand All @@ -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
);
}
Expand Down
8 changes: 4 additions & 4 deletions src/test/php/lang/ast/unittest/parse/LambdasTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ 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;'
);
}

#[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;'
);
}
Expand All @@ -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);'
Expand All @@ -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
Expand Down
12 changes: 6 additions & 6 deletions src/test/php/lang/ast/unittest/parse/MembersTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ 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() { } }');
}

#[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() { } }');
}
Expand Down Expand Up @@ -96,15 +96,15 @@ 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) { } }');
}

#[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.' { } }');
}
Expand All @@ -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() { } }');
}
Expand All @@ -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() { } }');
}
Expand Down

0 comments on commit f40a57a

Please sign in to comment.