Skip to content
This repository has been archived by the owner on Sep 24, 2020. It is now read-only.

[Bug] False positive [language_error] Method in Trait does not exist #318

Open
algo13 opened this issue Jan 30, 2017 · 3 comments
Open

[Bug] False positive [language_error] Method in Trait does not exist #318

algo13 opened this issue Jan 30, 2017 · 3 comments
Assignees
Labels

Comments

@algo13
Copy link
Contributor

algo13 commented Jan 30, 2017

<?php
trait T
{
    public function funcInT(){}
}
class C
{
    use T;
    public function funcInC()
    {
        $this->funcInT(); //< Notice:  Method funcInT() does not exist in C scope [language_error]
    }
}

... Maybe Mismatch between "key of Compiler::$traits" and "Compiler::getTrait() parameter".

@ovr
Copy link
Owner

ovr commented Jan 31, 2017

Should be fixed now, can you try @algo13 ?

@algo13
Copy link
Contributor Author

algo13 commented Jan 31, 2017

@ovr Thanks for comment.

  • It fails when there is no NS.(If there is no NS, key of Compiler::$traits becomes \T)
  • If you want to acquire NS, you can get it with $node->namespacedName->slice(0, -1).(Maybe unnecessary \PHPSA\Compiler\NameResolveVisitor)
  • Node\Stmt\TraitUse::$traits was necessary to reference after NameResolver(resolveClassName in enterNode). (Use other NodeTraverser or leaveNode.)

Proposed amendment:

class Compiler
{
    // snip..
    public function addTrait(TraitDefinition $class)
    {
        $this->traits[(string)\PhpParser\Node\Name::concat($class->getNamespace(), $class->getName()])] = $class;
    }
    // snip..
}
class DefinitionVisitor extends NodeVisitorAbstract
{
    // snip..
    //public function enterNode(Node $node)
    public function leaveNode(Node $node)
    {
        // snip..
    }
    public function prepareTrait(Stmt\Trait_ $statement)
    {
        // snip..
        $namespace = $statement->namespacedName->slice(0, -1);
        if ($namespace !== null) {
            $definition->setNamespace($namespace);
        }
        // snip..
    }
    public function prepareClass(Stmt\Class_ $statement)
    {
        // snip..
            } elseif ($stmt instanceof Node\Stmt\TraitUse) {
                foreach ($stmt->traits as $traitPart) {
                    $traitDefinition = $this->compiler->getTrait((string)$traitPart);
                    if ($traitDefinition) {
                        $definition->mergeTrait($traitDefinition, $stmt->adaptations);
                    }
                }
            } elseif ($stmt instanceof Node\Stmt\ClassConst) {
        // snip..
    }
    // snip..
}

What do you think?

@ovr
Copy link
Owner

ovr commented Feb 8, 2017

Continue working on this problem...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants