Skip to content

Commit

Permalink
Fix up FQCN for property annotations in entity.
Browse files Browse the repository at this point in the history
  • Loading branch information
dereuromark committed Nov 25, 2024
1 parent 083f0fe commit b6c7834
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
36 changes: 35 additions & 1 deletion src/Annotator/EntityAnnotator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use IdeHelper\Annotation\AnnotationFactory;
use IdeHelper\Annotation\PropertyAnnotation;
use IdeHelper\Annotation\PropertyReadAnnotation;
use IdeHelper\Annotator\Traits\UseStatementsTrait;
use IdeHelper\Utility\App;
use IdeHelper\View\Helper\DocBlockHelper;
use PHP_CodeSniffer\Files\File;
Expand All @@ -21,6 +22,8 @@

class EntityAnnotator extends AbstractAnnotator {

use UseStatementsTrait;

/**
* @var array<string, string>|null
*/
Expand Down Expand Up @@ -308,6 +311,8 @@ protected function buildVirtualPropertyHintTypeMap(string $content): array {
return [];
}

$useStatements = null;

$classEndIndex = $tokens[$classIndex]['scope_closer'];

$properties = [];
Expand All @@ -334,7 +339,13 @@ protected function buildVirtualPropertyHintTypeMap(string $content): array {

$property = Inflector::underscore($matches[1]);

$properties[$property] = $this->returnType($file, $tokens, $functionIndex);
$type = $this->returnType($file, $tokens, $functionIndex);
if ($useStatements === null) {
$useStatements = $this->getUseStatements($file);
}
$type = $this->fqcnIfNeeded($type, $useStatements);

$properties[$property] = $type;
}

return $properties;
Expand Down Expand Up @@ -484,4 +495,27 @@ protected function virtualFields(string $name): array {
return $entity->getVirtual();
}

/**
* @param string $type
* @param array<string, array<string, mixed>> $useStatements
* @return string
*/
protected function fqcnIfNeeded(string $type, array $useStatements): string {
$types = explode('|', $type);
foreach ($types as $key => $type) {
$primitive = ['null', 'true', 'false', 'array', 'iterable', 'string', 'bool', 'float', 'int', 'object', 'callable', 'resource', 'mixed'];
if (in_array($type, $primitive, true) || str_starts_with($type, '\\')) {
continue;
}

if (!isset($useStatements[$type])) {
continue;
}

$types[$key] = '\\' . $useStatements[$type]['fullName'];
}

return implode('|', $types);
}

}
93 changes: 93 additions & 0 deletions src/Annotator/Traits/UseStatementsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

namespace IdeHelper\Annotator\Traits;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Tokens;

trait UseStatementsTrait {

/**
* @param \PHP_CodeSniffer\Files\File $phpcsFile
*
* @return array<string, array<string, mixed>>
*/
protected function getUseStatements(File $phpcsFile): array {
$tokens = $phpcsFile->getTokens();

$statements = [];
foreach ($tokens as $index => $token) {
if ($token['code'] !== T_USE || $token['level'] > 0) {
continue;
}

$useStatementStartIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $index + 1, null, true);

// Ignore function () use ($foo) {}
if ($tokens[$useStatementStartIndex]['content'] === '(') {
continue;
}

$semicolonIndex = $phpcsFile->findNext(T_SEMICOLON, $useStatementStartIndex + 1);
$useStatementEndIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, $semicolonIndex - 1, null, true);

$statement = '';
for ($i = $useStatementStartIndex; $i <= $useStatementEndIndex; $i++) {
$statement .= $tokens[$i]['content'];
}

// Another sniff takes care of that, we just ignore then.
if ($this->isMultipleUseStatement($statement)) {
continue;
}

$statementParts = preg_split('/\s+as\s+/i', $statement) ?: [];

if (count($statementParts) === 1) {
$fullName = $statement;
$statementParts = explode('\\', $fullName);
$shortName = end($statementParts);
$alias = null;
} else {
$fullName = $statementParts[0];
$alias = $statementParts[1];
$statementParts = explode('\\', $fullName);
$shortName = end($statementParts);
}

$shortName = trim($shortName);
$fullName = trim($fullName);
$key = $alias ?: $shortName;

$statements[$key] = [
'alias' => $alias,
'end' => $semicolonIndex,
'statement' => $statement,
'fullName' => ltrim($fullName, '\\'),
'shortName' => $shortName,
'start' => $index,
];
}

return $statements;
}

/**
* @param string $statementContent
*
* @return bool
*/
protected function isMultipleUseStatement(string $statementContent): bool {
if (str_contains($statementContent, ',')) {
return true;
}

return false;
}

}

0 comments on commit b6c7834

Please sign in to comment.