private function createVar(LinkedFlowScope $scope, $name, $type) { $type = $this->registry->resolveType($type); $this->functionScope->declareVar($name)->setNameNode($n = new \PHPParser_Node_Expr_Variable($name)); $scope->inferSlotType($name, $type); $n->setAttribute('type', $type); return $n; }
public function testDeclareVar() { $scope = new Scope($this->getMock('PHPParser_Node')); $this->assertNull($scope->getVar('x')); $scope->declareVar('x', $this->registry->getNativeType('integer')); $this->assertNotNull($var = $scope->getVar('x')); $this->assertSame($this->registry->getNativeType('integer'), $var->getType()); $this->assertTrue($var->isTypeInferred()); }
public function testGetSlotFromFunctionScope() { $functionScope = new Scope($this->getMock('PHPParser_Node')); $functionScope->declareVar('x', $this->registry->getNativeType('integer')); $flowScope = LinkedFlowScope::createLatticeElement($functionScope); $this->assertNotNull($var = $flowScope->getSlot('x')); $this->assertSame($this->registry->getNativeType('integer'), $var->getType()); $flowScope = $flowScope->createChildFlowScope(); $this->assertNotNull($var = $flowScope->getSlot('x')); $this->assertSame($this->registry->getNativeType('integer'), $var->getType()); }
/** * Declares a variable. * * @param string $name * @param array $types * @param boolean $typesInferred */ private function declareVar($name, PhpType $type = null, $typeInferred = true, \PHPParser_Node $nameNode = null) { if ($this->scope->isDeclared($name)) { return $this->scope->getVar($name); } $var = $this->scope->declareVar($name, $type, $typeInferred); if ($nameNode) { $var->setNameNode($nameNode); } return $var; }
public function createScope(\PHPParser_Node $node, Scope $parent = null) { $thisType = $this->getThisType($node, $parent); // Constructing the global scope is very different than constructing inner scopes, because only global scopes // can contain named classes that show up in the type registry. $newScope = null; if (null === $parent) { $newScope = new Scope($node, null, $thisType); $builder = new GlobalScopeBuilder($newScope, $this->typeRegistry); NodeTraversal::traverseWithCallback($node, $builder); } else { $newScope = new Scope($node, $parent, $thisType); $builder = new LocalScopeBuilder($newScope, $this->typeRegistry); NodeTraversal::traverseWithCallback($node, $builder); } if (null !== $thisType) { $newScope->declareVar('this', $thisType); } return $newScope; }
private function checkParameterAssignment(\PHPParser_Node_Param $node) { $builder = new UnionTypeBuilder($this->typeRegistry); if (null !== $node->default) { $this->attachLiteralTypes($node->default); $type = $node->default->getAttribute('type'); if ($type) { $builder->addAlternate($type); } } if ('array' === $node->type) { $type = $this->typeRegistry->getNativeType('array'); // If the annotated type also contains the array type, we use the annotated // type as it is potentially more specific, e.g. "array<string>" or "array|null". $annotatedType = $this->commentParser->getTypeFromParamAnnotation($node->getAttribute('parent'), $node->name); if (null !== ($containedArrayType = $this->getContainedArrayType($annotatedType))) { $type = $containedArrayType; } $builder->addAlternate($type); } else { if ($node->type instanceof \PHPParser_Node_Name) { $builder->addAlternate($this->typeRegistry->getClassOrCreate(implode("\\", $node->type->parts))); } } $type = $builder->build(); if ($type->isNoType()) { $type = $this->commentParser->getTypeFromParamAnnotation($node->getAttribute('parent'), $node->name); } else { if ($type->isNullType()) { $commentType = $this->commentParser->getTypeFromParamAnnotation($node->getAttribute('parent'), $node->name); if ($commentType) { $type = $this->typeRegistry->createNullableType($commentType); } else { $type = null; } } else { if ($type->isBooleanType()) { $commentType = $this->commentParser->getTypeFromParamAnnotation($node->getAttribute('parent'), $node->name); if ($commentType) { $type = $this->typeRegistry->createUnionType(array($type, $commentType)); } } } } if (null === $type) { $type = $this->typeRegistry->getNativeType('unknown'); } $node->setAttribute('type', $type); // This could be the case if the same name is used twice as parameter. if (false === $this->scope->isDeclared($node->name)) { $var = $this->scope->declareVar($node->name, $type, null === $type); $var->setNameNode($node); $var->setReference($node->byRef); } else { $var = $this->scope->getVar($node->name); if ($varType = $var->getType()) { $var->setType($this->typeRegistry->createUnionType(array($varType, $type))); } else { if (null !== $type) { $var->setType($type); $var->setTypeInferred(true); } } $var->setReference($node->byRef); } }