Skip to content

Commit

Permalink
Create generic member in lang.ast.nodes.Signature
Browse files Browse the repository at this point in the history
This will hold generic type components for methods and functions in
the future, e.g.: function swap<T>(T &$a, T &$b) { }
  • Loading branch information
thekid committed Nov 6, 2022
1 parent 8fd27ec commit 600c303
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 600c303

Please sign in to comment.