fix(trait): preserve nested namespace context, fix gh-38

master
韩天峰 2 days ago
parent f56b209d5c
commit 8d745d89be
  1. 8
      src/Translator.php
  2. 49
      tests/compiler/trait/nested-trait-import-context.phpt
  3. 28
      tests/compiler/trait/nested-trait-namespace-context.phpt

@ -3107,8 +3107,12 @@ CODE;
/** @var Node\Stmt\Trait_ $traitAst */
$traitAst = $this->cloneAstNode($traitDef->trait);
// Recursively flatten traits used by this trait before copying
// its members into the final class.
$this->composeTraitAst($traitAst, new Node\Name($traitFullName));
// its members into the final class. The nested TraitUse nodes
// must be resolved in the lexical context of the trait being
// expanded, not in the context of its eventual consumer.
$this->withTraitNameContext($traitFullName, function () use ($traitAst, $traitFullName): void {
$this->composeTraitAst($traitAst, new Node\Name($traitFullName));
});
$traitStmts = $traitAst->stmts;
$aliasStmts = [];
foreach ($traitStmts as $k1 => $traitStmt) {

@ -0,0 +1,49 @@
--TEST--
Nested trait uses retain import aliases through multiple composition levels
--FILE--
<?php
namespace Issue38\Library {
trait Greeting {
public function hello(): string {
return 'imported';
}
}
}
namespace Issue38\Template {
use Issue38\Library\Greeting as ImportedGreeting;
trait InnerWrapper {
use ImportedGreeting {
hello as protected importedHello;
}
public function wrapped(): string {
return '[' . $this->importedHello() . ']';
}
}
trait OuterWrapper {
use InnerWrapper;
}
}
namespace Issue38\Consumer {
use Issue38\Template\OuterWrapper as ImportedWrapper;
class Example {
use ImportedWrapper;
}
}
namespace {
function main(): void {
$example = new Issue38\Consumer\Example();
echo $example->hello(), "\n";
echo $example->wrapped(), "\n";
}
}
?>
--EXPECT--
imported
[imported]

@ -0,0 +1,28 @@
--TEST--
Nested trait uses resolve unqualified names in the declaring namespace
--FILE--
<?php
namespace Issue38\SameNamespace {
trait Greeting {
public function hello(): string {
return 'hi';
}
}
trait GreetingWrapper {
use Greeting;
}
class Example {
use GreetingWrapper;
}
}
namespace {
function main(): void {
echo (new Issue38\SameNamespace\Example())->hello(), "\n";
}
}
?>
--EXPECT--
hi
Loading…
Cancel
Save