From b635068570393a2dc90b946994e222c0a0b3399f Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 4 Jun 2023 11:32:57 +0200 Subject: [PATCH] Move declare() to parent class See https://github.com/xp-framework/compiler/pull/169#discussion_r1216415649 --- .../unittest/emit/AnnotationSupport.class.php | 28 ++++---------- .../ast/unittest/emit/EmittingTest.class.php | 37 ++++++++++++++++++- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/test/php/lang/ast/unittest/emit/AnnotationSupport.class.php b/src/test/php/lang/ast/unittest/emit/AnnotationSupport.class.php index 11295dd6..b46612e4 100755 --- a/src/test/php/lang/ast/unittest/emit/AnnotationSupport.class.php +++ b/src/test/php/lang/ast/unittest/emit/AnnotationSupport.class.php @@ -1,6 +1,6 @@ type( - $declaration.(strstr($declaration, '') ? '' : ' class { }') - )); - } - /** * Returns annotations present in the given type * @@ -127,13 +115,13 @@ public function single_quoted_string_inside_non_constant_expression() { public function has_access_to_class() { Assert::equals( ['Expect' => [true]], - $this->annotations($this->declare('#[Expect(self::SUCCESS)] class { const SUCCESS = true; }')) + $this->annotations($this->declare('#[Expect(self::SUCCESS)] class %T { const SUCCESS = true; }')) ); } #[Test] public function method() { - $t= $this->declare('class { #[Test] public function fixture() { } }'); + $t= $this->declare('class %T { #[Test] public function fixture() { } }'); Assert::equals( ['Test' => []], $this->annotations($t->method('fixture')) @@ -142,7 +130,7 @@ public function method() { #[Test] public function field() { - $t= $this->declare('class { #[Test] public $fixture; }'); + $t= $this->declare('class %T { #[Test] public $fixture; }'); Assert::equals( ['Test' => []], $this->annotations($t->property('fixture')) @@ -151,7 +139,7 @@ public function field() { #[Test] public function param() { - $t= $this->declare('class { public function fixture(#[Test] $param) { } }'); + $t= $this->declare('class %T { public function fixture(#[Test] $param) { } }'); Assert::equals( ['Test' => []], $this->annotations($t->method('fixture')->parameter(0)) @@ -160,7 +148,7 @@ public function param() { #[Test] public function params() { - $t= $this->declare('class { public function fixture(#[Inject(["name" => "a"])] $a, #[Inject] $b) { } }'); + $t= $this->declare('class %T { public function fixture(#[Inject(["name" => "a"])] $a, #[Inject] $b) { } }'); Assert::equals( ['Inject' => [['name' => 'a']]], $this->annotations($t->method('fixture')->parameter(0)) @@ -181,7 +169,7 @@ public function multiple_class_annotations() { #[Test] public function multiple_member_annotations() { - $t= $this->declare('class { #[Test, Values([1, 2, 3])] public function fixture() { } }'); + $t= $this->declare('class %T { #[Test, Values([1, 2, 3])] public function fixture() { } }'); Assert::equals( ['Test' => [], 'Values' => [[1, 2, 3]]], $this->annotations($t->method('fixture')) @@ -195,7 +183,7 @@ public function multiline_annotations() { "Timm", "Mr. Midori", ])] - class { }' + class %T { }' )); Assert::equals(['Authors' => [['Timm', 'Mr. Midori']]], $annotations); } diff --git a/src/test/php/lang/ast/unittest/emit/EmittingTest.class.php b/src/test/php/lang/ast/unittest/emit/EmittingTest.class.php index 1f107045..0b06ae8d 100755 --- a/src/test/php/lang/ast/unittest/emit/EmittingTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/EmittingTest.class.php @@ -1,10 +1,10 @@ cl->loadClass($class); } + /** + * Declare a type with a unique type name (which may be referenced by `%T`) + * and return a reflection instance referencing it. + * + * @param string $code + * @return lang.reflection.Type + */ + protected function declare($code) { + $name= 'T'.(self::$id++); + $declaration= strstr($code, '%T') + ? str_replace('%T', $name, $code) + : $code.' class '.$name.' { }' + ; + + $tree= $this->language->parse(new Tokens($declaration, static::class))->tree(); + if (isset($this->output['ast'])) { + Console::writeLine(); + Console::writeLine('=== ', static::class, ' ==='); + Console::writeLine($tree); + } + + $out= new MemoryOutputStream(); + $this->emitter->emitAll(new GeneratedCode($out, ''), $tree->children()); + if (isset($this->output['code'])) { + Console::writeLine(); + Console::writeLine('=== ', static::class, ' ==='); + Console::writeLine($out->bytes()); + } + + $class= ($package= $tree->scope()->package) ? strtr(substr($package, 1), '\\', '.').'.'.$name : $name; + $this->cl->setClassBytes($class, $out->bytes()); + return Reflection::type($this->cl->loadClass0($class)); + } + /** * Run code *