/**
  * @param Node\Stmt\Class_ $node
  *
  * @return Node\Stmt\Class_
  */
 public function resolveConstructor(Node\Stmt\Class_ $node)
 {
     foreach ($node->stmts as $key => $stmt) {
         if ($stmt instanceof Node\Stmt\ClassMethod && $stmt->name === '__construct') {
             // this will make problems we need an layer above which chains the variable resolvers
             // because we need may need more than this resolver
             // skip constructor if is abstract
             if ($stmt->isAbstract()) {
                 return $node;
             }
             // change recursivly the nodes
             $subTraverser = new NodeTraverser();
             foreach ($this->visitors as $visitor) {
                 $subTraverser->addVisitor($visitor);
             }
             // the table switches to a method scope
             // $x = ... will be treated normal
             // $this->x = ... will be stored in the above class scope and is available afterwards
             $this->table->enterScope(new TableScope(TableScope::CLASS_METHOD_SCOPE));
             $subTraverser->traverse($stmt->params);
             $nodes = $subTraverser->traverse($stmt->stmts);
             $this->table->leaveScope();
             //override the old statement
             $stmt->stmts = $nodes;
             // override the classmethod statement in class
             $node->stmts[$key] = $stmt;
             // return the changed node to override it
             return $node;
         }
     }
     // no constructor defined
     return $node;
 }
 /**
  * {@inheritdoc}
  */
 public function resolveVariableType(Node $node)
 {
     if ($node instanceof Node\Param) {
         if ($node->type instanceof Node\Name) {
             $this->table->setSymbol($node->name, $node->type->toString());
         }
     }
 }
 public function leaveNode(Node $node)
 {
     if ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Interface_ || $node instanceof Node\Stmt\Trait_) {
         $this->table->leaveScope();
     }
     if ($node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
         $this->table->leaveScope();
     }
 }
 /**
  * {@inheritdoc}
  */
 public function resolveVariableType(Node $node)
 {
     if ($node instanceof Node\Expr\PropertyFetch) {
         // $this->someProperty
         if ($node->var instanceof Node\Expr\Variable && $node->var->name === 'this') {
             $node->setAttribute('guessedType', $this->table->lookUpClassProperty($node->name)->type());
         }
         // $x->someProperty
     }
 }
 /**
  * @inheritDoc
  */
 public function resolveVariableType(Node $node)
 {
     // $this->call()
     if ($node instanceof Node\Expr\MethodCall && property_exists($node->var, 'name') && null === $node->getAttribute('guessedType', null)) {
         if ('container' == $node->var->name && $this->isController($this->table->lookUp('this')->type())) {
             $context = self::CONTAINER;
         } else {
             $context = $this->table->lookUp($node->var->name)->type();
         }
         $type = $this->getType($context, $node->name, $node);
         if (null !== $type) {
             $node->setAttribute('guessedType', $type);
         }
     }
     // $x = $this->call()
     if ($node instanceof Node\Expr\Assign && $node->var instanceof Node\Expr\Variable && $node->expr instanceof Node\Expr\MethodCall && property_exists($node->expr->var, 'name') && null === $node->getAttribute('guessedType', null)) {
         if ('container' == $node->expr->var->name && $this->isController($this->table->lookUp('this')->type())) {
             $context = self::CONTAINER;
         } else {
             $context = $this->table->lookUp($node->expr->var->name)->type();
         }
         $type = $this->getType($context, $node->expr->name, $node->expr);
         if (null !== $type) {
             $node->var->setAttribute('guessedType', $type);
             $this->table->setSymbol($node->var->name, $type);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function resolveVariableType(Node $node)
 {
     if ($node instanceof Node\Expr\Assign) {
         // $x = ...
         if ($node->var instanceof Node\Expr\Variable) {
             // skips variable names like ${$node->nodeName}
             if (!is_string($node->var->name)) {
                 return;
             }
             // $x = new X();
             if ($node->expr instanceof Node\Expr\New_) {
                 if ($node->expr->class instanceof Node\Name) {
                     $type = $node->expr->class->toString();
                     $this->table->setSymbol($node->var->name, $type);
                     $node->var->setAttribute('guessedType', $type);
                 }
             }
             // $x = $y;
             if ($node->expr instanceof Node\Expr\Variable) {
                 $type = $this->table->lookUp($node->expr->name)->type();
                 $node->var->setAttribute('guessedType', $type);
                 $this->table->setSymbol($node->var->name, $type);
             }
             // $x = $this->x
             if ($node->expr instanceof Node\Expr\PropertyFetch) {
                 $type = $this->table->lookUpClassProperty($node->expr->name)->type();
                 $node->var->setAttribute('guessedType', $type);
                 $this->table->setSymbol($node->var->name, $type);
             }
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function resolveVariableType(Node $node)
 {
     if ($node instanceof Node\Expr\Assign) {
         // $this->x = ...
         // excluding $this->$x = ...
         if ($node->var instanceof Node\Expr\PropertyFetch) {
             // $stub[$key]->x = ... ; if not tested a php notice will occur
             // @TODO change to be able to use all types of properties like $x->x = 10
             if ($node->var->var instanceof Node\Expr\ArrayDimFetch) {
                 return;
             }
             // @TODO change to be able to use all types of properties like $x->x = 10
             if ($node->var->var->name !== 'this' || !is_string($node->var->name)) {
                 return;
             }
             // $this->x = new X();
             if ($node->expr instanceof Node\Expr\New_) {
                 if ($node->expr->class instanceof Node\Name) {
                     $type = $node->expr->class->toString();
                     $node->var->setAttribute('guessedType', $type);
                     $this->table->setClassProperty($node->var->name, $type);
                 }
             }
             // $this->x = $y;
             if ($node->expr instanceof Node\Expr\Variable) {
                 $type = $this->table->lookUp($node->expr->name)->type();
                 $node->var->setAttribute('guessedType', $type);
                 $this->table->setClassProperty($node->var->name, $type);
             }
             // $this->x = $this->y;
             if ($node->expr instanceof Node\Expr\PropertyFetch) {
                 $type = $this->table->lookUpClassProperty($node->expr->name)->type();
                 $node->var->setAttribute('guessedType', $type);
                 $this->table->setClassProperty($node->var->name, $type);
             }
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function resolveVariableType(Node $node)
 {
     if ($node instanceof Node\Expr\Variable) {
         $node->setAttribute('guessedType', $this->table->lookUp($node->name)->type());
     }
 }
 public function testSetClassPropertyThrowsException()
 {
     $this->setExpectedException('Exception', 'Illegal State there is no class scope above');
     $table = new SymbolTable();
     $table->setClassProperty('property', 'type');
 }