Open thekid opened 8 months ago
This would break class constants named namespace:
$ xp -w 'class T { const namespace = "ns"; } return T::namespace'
ns
Implementation:
diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php
index fe08e57..6342402 100755
--- a/src/main/php/lang/ast/emit/PHP.class.php
+++ b/src/main/php/lang/ast/emit/PHP.class.php
@@ -1086,17 +1086,17 @@ abstract class PHP extends Emitter {
$result->out->write("{$scope->type}::");
}
- // Rewrite T::member to T::$member for XP enums
- if (
- $scope->member instanceof Literal &&
- is_string($scope->type) &&
- 'class' !== $scope->member->expression &&
- $result->codegen->lookup($scope->type)->rewriteEnumCase($scope->member->expression)
- ) {
- $result->out->write('$'.$scope->member->expression);
- } else {
- $this->emitOne($result, $scope->member);
+ // Rewrite ::class and ::namespace to namespace resolution; T::member to T::$member for XP enums
+ if ($scope->member instanceof Literal) {
+ if ('namespace' === $scope->member->expression || 'class' === $scope->member->expression) {
+ $result->out->write('class');
+ return;
+ } else if (is_string($scope->type) && $result->codegen->lookup($scope->type)->rewriteEnumCase($scope->member->expression)) {
+ $result->out->write('$'.$scope->member->expression);
+ return;
+ }
}
+ $this->emitOne($result, $scope->member);
}
protected function emitInstance($result, $instance) {
diff --git a/src/test/php/lang/ast/unittest/emit/NamespacesTest.class.php b/src/test/php/lang/ast/unittest/emit/NamespacesTest.class.php
index 7fe7dcc..8db6133 100755
--- a/src/test/php/lang/ast/unittest/emit/NamespacesTest.class.php
+++ b/src/test/php/lang/ast/unittest/emit/NamespacesTest.class.php
@@ -84,4 +84,14 @@ class NamespacesTest extends EmittingTest {
}');
Assert::equals(new Date('1977-12-14'), $r);
}
+
+ #[Test]
+ public function namespace_resolution() {
+ $r= $this->run('namespace util; class %T {
+ public function run() {
+ return cmd::namespace;
+ }
+ }');
+ Assert::equals('util\\cmd', $r);
+ }
}
\ No newline at end of file
Someone suggested this to return the namespace name of a class in https://externals.io/message/113269:
use util\cmd\Console;
$ns= Console::namespace; // "util\cmd"
If we introduced this feature as described above, the above would yield "util\cmd\Console". Currently, it yields an error for an undefined class constant.
How about using
::namespace
for namespace resolution just like::class
?Example:
This would simply be emitted as
::class
, which already does everything we want; however, usingapi::class
in this place doesn't convey the intent correctly!