Fix Relative class names are not converted to fully-qualified class names (FQCNs) (#1005)

* Fix https://github.com/barryvdh/laravel-ide-helper/issues/627

* Fix codestyle

* Init

* composer fix-style

* Actualize

* Fix

* normalize composer.json

* Fix

* composer fix-style

* Replace NamespaceUses with UsesResolver

* Add UsesResolver tests

* Add MethodTest::testClassAliases

* Fix code style

* Get rid of laravel support helpers

* Make class UsesResolver stateless, update tests for it

* composer fix-style

Co-authored-by: Andrii Savluk <[email protected]>
Co-authored-by: laravel-ide-helper <[email protected]>
Co-authored-by: SavKS <[email protected]>
Co-authored-by: Taras Fomin <[email protected]>
This commit is contained in:
SavKS
2021-03-15 07:45:23 +01:00
committed by GitHub
co-authored by Andrii Savluk laravel-ide-helper SavKS Taras Fomin
parent 6c4dcd9049
commit c5e18beff1
7 changed files with 240 additions and 11 deletions
+10 -6
View File
@@ -40,6 +40,7 @@ class Alias
protected $magicMethods = [];
protected $interfaces = [];
protected $phpdoc = null;
protected $classAliases = [];
/** @var ConfigRepository */
protected $config;
@@ -78,10 +79,11 @@ class Alias
$this->detectExtendsNamespace();
if (!empty($this->namespace)) {
//Create a DocBlock and serializer instance
$this->phpdoc = new DocBlock(new ReflectionClass($alias), new Context($this->namespace));
}
$this->classAliases = (new UsesResolver())->loadFromClass($this->root);
//Create a DocBlock and serializer instance
$this->phpdoc = new DocBlock(new ReflectionClass($alias), new Context($this->namespace, $this->classAliases));
}
if ($facade === '\Illuminate\Database\Eloquent\Model') {
$this->usedMethods = ['decrement', 'increment'];
@@ -330,7 +332,7 @@ class Alias
if (!in_array($magic, $this->usedMethods)) {
if ($class !== $this->root) {
$this->methods[] = new Method($method, $this->alias, $class, $magic, $this->interfaces);
$this->methods[] = new Method($method, $this->alias, $class, $magic, $this->interfaces, $this->classAliases);
}
$this->usedMethods[] = $magic;
}
@@ -359,7 +361,8 @@ class Alias
$this->alias,
$reflection,
$method->name,
$this->interfaces
$this->interfaces,
$this->classAliases
);
}
$this->usedMethods[] = $method->name;
@@ -381,7 +384,8 @@ class Alias
$this->alias,
$reflection,
$macro_name,
$this->interfaces
$this->interfaces,
$this->classAliases
);
$this->usedMethods[] = $macro_name;
}
+4 -2
View File
@@ -17,15 +17,17 @@ class Macro extends Method
* @param \ReflectionClass $class
* @param null $methodName
* @param array $interfaces
* @param array $classAliases
*/
public function __construct(
$method,
$alias,
$class,
$methodName = null,
$interfaces = []
$interfaces = [],
$classAliases = []
) {
parent::__construct($method, $alias, $class, $methodName, $interfaces);
parent::__construct($method, $alias, $class, $methodName, $interfaces, $classAliases);
}
/**
+6 -3
View File
@@ -38,6 +38,7 @@ class Method
protected $real_name;
protected $return = null;
protected $root;
protected $classAliases;
/**
* @param \ReflectionMethod|\ReflectionFunctionAbstract $method
@@ -45,11 +46,13 @@ class Method
* @param \ReflectionClass $class
* @param string|null $methodName
* @param array $interfaces
* @param array $classAliases
*/
public function __construct($method, $alias, $class, $methodName = null, $interfaces = [])
public function __construct($method, $alias, $class, $methodName = null, $interfaces = [], array $classAliases = [])
{
$this->method = $method;
$this->interfaces = $interfaces;
$this->classAliases = $classAliases;
$this->name = $methodName ?: $method->name;
$this->real_name = $method->isClosure() ? $this->name : $method->name;
$this->initClassDefinedProperties($method, $class);
@@ -80,7 +83,7 @@ class Method
*/
protected function initPhpDoc($method)
{
$this->phpdoc = new DocBlock($method, new Context($this->namespace));
$this->phpdoc = new DocBlock($method, new Context($this->namespace, $this->classAliases));
}
/**
@@ -363,7 +366,7 @@ class Method
}
if ($method) {
$namespace = $method->getDeclaringClass()->getNamespaceName();
$phpdoc = new DocBlock($method, new Context($namespace));
$phpdoc = new DocBlock($method, new Context($namespace, $this->classAliases));
if (strpos($phpdoc->getText(), '{@inheritdoc}') !== false) {
//Not at the end yet, try another parent/interface..
+124
View File
@@ -0,0 +1,124 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @copyright 2014 Barry vd. Heuvel / Fruitcake Studio (http://www.fruitcakestudio.nl)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link https://github.com/barryvdh/laravel-ide-helper
*/
namespace Barryvdh\LaravelIdeHelper;
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PhpParser\ParserFactory;
class UsesResolver
{
/**
* @param string $classFQN
* @return array
*/
public function loadFromClass(string $classFQN): array
{
return $this->loadFromFile(
$classFQN,
(new \ReflectionClass($classFQN))->getFileName()
);
}
/**
* @param string $classFQN
* @param string $filename
* @return array
*/
public function loadFromFile(string $classFQN, string $filename): array
{
return $this->loadFromCode(
$classFQN,
file_get_contents(
$filename
)
);
}
/**
* @param string $classFQN
* @param string $code
* @return array
*/
public function loadFromCode(string $classFQN, string $code): array
{
$classFQN = ltrim($classFQN, '\\');
$namespace = rtrim(
preg_replace(
'/([^\\\\]+)$/',
'',
$classFQN
),
'\\'
);
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
$namespaceData = null;
foreach ($parser->parse($code) as $node) {
if ($node instanceof Namespace_ && $node->name->toCodeString() === $namespace) {
$namespaceData = $node;
break;
}
}
if ($namespaceData === null) {
return [];
}
/** @var Namespace_ $namespaceData */
$aliases = [];
foreach ($namespaceData->stmts as $stmt) {
if ($stmt instanceof Use_) {
if ($stmt->type !== Use_::TYPE_NORMAL) {
continue;
}
foreach ($stmt->uses as $use) {
/** @var UseUse $use */
$alias = $use->alias ?
$use->alias->name :
self::classBasename($use->name->toCodeString());
$aliases[$alias] = '\\' . $use->name->toCodeString();
}
} elseif ($stmt instanceof GroupUse) {
foreach ($stmt->uses as $use) {
/** @var UseUse $use */
$alias = $use->alias ?
$use->alias->name :
self::classBasename($use->name->toCodeString());
$aliases[$alias] = '\\' . $stmt->prefix->toCodeString() . '\\' . $use->name->toCodeString();
}
}
}
return $aliases;
}
/**
* @param string $classFQN
* @return string
*/
protected static function classBasename(string $classFQN): string
{
return preg_replace('/^.*\\\\([^\\\\]+)$/', '$1', $classFQN);
}
}