public function getGoToLocations($offset, $nodes) { $this->run(); $name = null; $node = null; if (count($nodes) >= 2 && $nodes[0] instanceof Name) { $name = Type::nameToString($nodes[0]); $node = $nodes[1]; } $locations = []; if ($node !== null && ($node instanceof Expr\Instanceof_ || $node instanceof Expr\New_ || $node instanceof Stmt\Catch_ || $node instanceof Stmt\Function_ || $node instanceof Stmt\ClassMethod || $node instanceof Expr\Closure || $node instanceof Param || $node instanceof Stmt\Class_ || $node instanceof Stmt\Interface_ || $node instanceof Stmt\TraitUse || $node instanceof Stmt\TraitUseAdaptation)) { foreach ($this->reflection->findClass($name) as $class) { if ($class->getLocation() !== null) { $locations[] = $class->getLocation(); } } } return $locations; }
public function enterNode(Node $node) { array_push($this->nodePathFromTop, $node); $classes = []; if ($node instanceof Expr\Instanceof_ || $node instanceof Expr\New_ || $node instanceof Expr\ClassConstFetch || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\StaticCall) { $classes[] = $node->class; } elseif ($node instanceof Stmt\Catch_ || $node instanceof Param) { $classes[] = $node->type; } elseif ($node instanceof Stmt\Function_ || $node instanceof Stmt\ClassMethod || $node instanceof Expr\Closure) { $classes[] = $node->returnType; } elseif ($node instanceof Stmt\Class_) { $classes[] = $node->extends; $classes = array_merge($classes, $node->implements); } elseif ($node instanceof Stmt\Interface_) { $classes = array_merge($classes, $node->extends); } elseif ($node instanceof Stmt\TraitUse) { $classes = array_merge($classes, $node->traits); } elseif ($node instanceof Stmt\TraitUseAdaptation) { $classes[] = $node->trait; } foreach ($classes as $class) { if (is_object($class) && $class instanceof Name) { $name = Type::nameToString($class); if (!in_array(strtolower($name), ['self', 'parent', 'static']) && empty($this->reflection->findClass($name))) { $range = Range::fromNode($class, $this->file->getPath()); $fixes = []; if ($this->namespaceReflection !== null && $class->isUnqualified()) { foreach ($this->namespaceReflection->findFullyQualifiedClasses($class->toString()) as $fqname) { //$fixes[] = new Fix([new FixChunk($range, $fqname)], $fqname); $fixes[] = $this->getFix($fqname); } } $this->diagnostics[] = new Diagnostic([$range], 'Undefined class', $fixes); } } } }
public function enterNode(Node $node) { if (!$node instanceof Stmt\Property) { $annotations = []; if ($node->hasAttribute('annotations')) { $annotations = $node->getAttribute('annotations'); } if (!empty($annotations['var'])) { foreach ($annotations['var'] as $varTag) { $name = $varTag->getIdentifier(); if (empty($name)) { $var = $node; if ($var instanceof Stmt\Foreach_) { $var = $var->valueVar; } elseif ($var instanceof Stmt\For_) { $var = $var->init; } elseif ($var instanceof Stmt\Global_ && count($var->vars) === 1) { $var = $var->vars[0]; } if ($var instanceof Expr\Assign || $var instanceof Expr\AssignRef || $var instanceof Expr\AssignOp) { $var = $var->var; } if ($var instanceof Expr\Variable && is_string($var->name)) { $name = '$' . $var->name; } } if (!empty($name)) { $this->getCurrentFunctionScope()[$name] = $varTag->getType(); } } } } if ($node instanceof Name) { $self = $this->getCurrentClass(); if (!empty($self) && !empty($self->getClass())) { $resolved = null; // Treating `static` as `self` is the best we can do here. if ($node->toString() === 'self' || $node->toString() === 'static') { $resolved = $self->getClass(); } elseif ($node->toString() === 'parent') { $selfClass = $this->reflection->findClass($self->getClass()); if (!empty($selfClass) && $selfClass[0] instanceof Class_ && !empty($selfClass[0]->getExtends())) { $resolved = $selfClass[0]->getExtends(); } } if (!empty($resolved)) { $node->setAttribute('resolved', new Name\FullyQualified(ltrim($resolved, '\\'), $node->getAttributes())); } } } elseif ($node instanceof Stmt\Function_) { $scope = []; $functions = $this->reflection->findFunction($node->hasAttribute('namespacedName') ? Type::nameToString($node->getAttribute('namespacedName')) : $node->name); if (!empty($functions)) { foreach ($functions[0]->getParams() as $param) { $scope[$param->getName()] = $param->getDocType(); } } $this->functionScopeStack[] = $scope; } elseif ($node instanceof Stmt\ClassMethod) { $scope = []; $class = $this->getCurrentClass(); if (!empty($class) && !empty($class->getClass())) { $method = $this->reflection->findMethod($class->getClass(), $node->name); if (!empty($method)) { foreach ($method->getParams() as $param) { $scope[$param->getName()] = $param->getDocType(); } } } $this->functionScopeStack[] = $scope; } elseif ($node instanceof Expr\Closure) { $scope = []; $parentScope =& $this->getCurrentFunctionScope(); foreach ($node->uses as $use) { if (array_key_exists('$' . $use->var, $parentScope)) { $scope['$' . $use->var] = $parentScope['$' . $use->var]; } } foreach ($node->params as $param) { $scope['$' . $param->name] = Type::fromString(Type::nameToString($param->type)); } $this->functionScopeStack[] = $scope; } elseif ($node instanceof Stmt\ClassLike) { $className = $node->hasAttribute('namespacedName') ? Type::nameToString($node->getAttribute('namespacedName')) : $node->name; $this->classStack[] = Type::object_($className); // for isolation, in case of illegal statements in class def: $this->functionScopeStack[] = []; } }