533 lines
15 KiB
PHP
533 lines
15 KiB
PHP
|
<?php declare(strict_types = 1);
|
||
|
|
||
|
namespace SlevomatCodingStandard\Helpers;
|
||
|
|
||
|
use PHP_CodeSniffer\Files\File;
|
||
|
use PHP_CodeSniffer\Util\Tokens;
|
||
|
use function array_merge;
|
||
|
use function array_reverse;
|
||
|
use function array_values;
|
||
|
use function count;
|
||
|
use function in_array;
|
||
|
use function is_array;
|
||
|
use function token_get_all;
|
||
|
use const T_ANON_CLASS;
|
||
|
use const T_ARRAY;
|
||
|
use const T_AS;
|
||
|
use const T_ATTRIBUTE;
|
||
|
use const T_BITWISE_AND;
|
||
|
use const T_BITWISE_OR;
|
||
|
use const T_CATCH;
|
||
|
use const T_CLASS;
|
||
|
use const T_CLOSE_PARENTHESIS;
|
||
|
use const T_COLON;
|
||
|
use const T_COMMA;
|
||
|
use const T_CONST;
|
||
|
use const T_DECLARE;
|
||
|
use const T_DOUBLE_COLON;
|
||
|
use const T_DOUBLE_QUOTED_STRING;
|
||
|
use const T_ELLIPSIS;
|
||
|
use const T_ENUM;
|
||
|
use const T_ENUM_CASE;
|
||
|
use const T_EXTENDS;
|
||
|
use const T_FUNCTION;
|
||
|
use const T_GOTO;
|
||
|
use const T_HEREDOC;
|
||
|
use const T_IMPLEMENTS;
|
||
|
use const T_INSTANCEOF;
|
||
|
use const T_NAME_FULLY_QUALIFIED;
|
||
|
use const T_NAME_QUALIFIED;
|
||
|
use const T_NAME_RELATIVE;
|
||
|
use const T_NAMESPACE;
|
||
|
use const T_NEW;
|
||
|
use const T_NS_SEPARATOR;
|
||
|
use const T_NULLABLE;
|
||
|
use const T_NULLSAFE_OBJECT_OPERATOR;
|
||
|
use const T_OBJECT_OPERATOR;
|
||
|
use const T_OPEN_PARENTHESIS;
|
||
|
use const T_OPEN_SHORT_ARRAY;
|
||
|
use const T_OPEN_TAG;
|
||
|
use const T_PARAM_NAME;
|
||
|
use const T_STRING;
|
||
|
use const T_TRAIT;
|
||
|
use const T_TYPE_INTERSECTION;
|
||
|
use const T_TYPE_UNION;
|
||
|
use const T_USE;
|
||
|
use const T_VARIABLE;
|
||
|
use const T_WHITESPACE;
|
||
|
|
||
|
/**
|
||
|
* @internal
|
||
|
*/
|
||
|
class ReferencedNameHelper
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* @return list<ReferencedName>
|
||
|
*/
|
||
|
public static function getAllReferencedNames(File $phpcsFile, int $openTagPointer): array
|
||
|
{
|
||
|
$lazyValue = static function () use ($phpcsFile, $openTagPointer): array {
|
||
|
return self::createAllReferencedNames($phpcsFile, $openTagPointer);
|
||
|
};
|
||
|
|
||
|
return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'references', $lazyValue);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return list<ReferencedName>
|
||
|
*/
|
||
|
public static function getAllReferencedNamesInAttributes(File $phpcsFile, int $openTagPointer): array
|
||
|
{
|
||
|
$lazyValue = static function () use ($phpcsFile, $openTagPointer): array {
|
||
|
return self::createAllReferencedNamesInAttributes($phpcsFile, $openTagPointer);
|
||
|
};
|
||
|
|
||
|
return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'referencesFromAttributes', $lazyValue);
|
||
|
}
|
||
|
|
||
|
public static function getReferenceName(File $phpcsFile, int $nameStartPointer, int $nameEndPointer): string
|
||
|
{
|
||
|
$tokens = $phpcsFile->getTokens();
|
||
|
|
||
|
$referencedName = '';
|
||
|
for ($i = $nameStartPointer; $i <= $nameEndPointer; $i++) {
|
||
|
if (in_array($tokens[$i]['code'], Tokens::$emptyTokens, true)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$referencedName .= $tokens[$i]['content'];
|
||
|
}
|
||
|
|
||
|
return $referencedName;
|
||
|
}
|
||
|
|
||
|
public static function getReferencedNameEndPointer(File $phpcsFile, int $startPointer): int
|
||
|
{
|
||
|
$tokens = $phpcsFile->getTokens();
|
||
|
|
||
|
$nameTokenCodes = TokenHelper::getNameTokenCodes();
|
||
|
|
||
|
$nameTokenCodesWithWhitespace = array_merge($nameTokenCodes, Tokens::$emptyTokens);
|
||
|
|
||
|
$lastNamePointer = $startPointer;
|
||
|
for ($i = $startPointer + 1; $i < count($tokens); $i++) {
|
||
|
if (!in_array($tokens[$i]['code'], $nameTokenCodesWithWhitespace, true)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!in_array($tokens[$i]['code'], $nameTokenCodes, true)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$lastNamePointer = $i;
|
||
|
}
|
||
|
|
||
|
return $lastNamePointer;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return list<ReferencedName>
|
||
|
*/
|
||
|
private static function createAllReferencedNames(File $phpcsFile, int $openTagPointer): array
|
||
|
{
|
||
|
$referencedNames = [];
|
||
|
|
||
|
$beginSearchAtPointer = $openTagPointer + 1;
|
||
|
$nameTokenCodes = TokenHelper::getNameTokenCodes();
|
||
|
$nameTokenCodes[] = T_DOUBLE_QUOTED_STRING;
|
||
|
$nameTokenCodes[] = T_HEREDOC;
|
||
|
|
||
|
$tokens = $phpcsFile->getTokens();
|
||
|
while (true) {
|
||
|
$nameStartPointer = TokenHelper::findNext($phpcsFile, $nameTokenCodes, $beginSearchAtPointer);
|
||
|
if ($nameStartPointer === null) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Find referenced names inside double quotes string
|
||
|
if (self::isNeedParsedContent($tokens[$nameStartPointer]['code'])) {
|
||
|
$content = $tokens[$nameStartPointer]['content'];
|
||
|
$currentPointer = $nameStartPointer + 1;
|
||
|
while (self::isNeedParsedContent($tokens[$currentPointer]['code'])) {
|
||
|
$content .= $tokens[$currentPointer]['content'];
|
||
|
$currentPointer++;
|
||
|
}
|
||
|
|
||
|
$names = self::getReferencedNamesFromString($content);
|
||
|
foreach ($names as $name) {
|
||
|
$referencedNames[] = new ReferencedName($name, $nameStartPointer, $nameStartPointer, ReferencedName::TYPE_CLASS);
|
||
|
}
|
||
|
|
||
|
$beginSearchAtPointer = $currentPointer;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Attributes are parsed in specific method
|
||
|
$attributeStartPointerBefore = TokenHelper::findPrevious($phpcsFile, T_ATTRIBUTE, $nameStartPointer - 1, $beginSearchAtPointer);
|
||
|
if ($attributeStartPointerBefore !== null) {
|
||
|
if ($tokens[$attributeStartPointerBefore]['attribute_closer'] > $nameStartPointer) {
|
||
|
$beginSearchAtPointer = $tokens[$attributeStartPointerBefore]['attribute_closer'] + 1;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!self::isReferencedName($phpcsFile, $nameStartPointer)) {
|
||
|
/** @var int $beginSearchAtPointer */
|
||
|
$beginSearchAtPointer = TokenHelper::findNextExcluding(
|
||
|
$phpcsFile,
|
||
|
array_merge(TokenHelper::$ineffectiveTokenCodes, $nameTokenCodes),
|
||
|
$nameStartPointer + 1
|
||
|
);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$nameEndPointer = self::getReferencedNameEndPointer($phpcsFile, $nameStartPointer);
|
||
|
|
||
|
$referencedNames[] = new ReferencedName(
|
||
|
self::getReferenceName($phpcsFile, $nameStartPointer, $nameEndPointer),
|
||
|
$nameStartPointer,
|
||
|
$nameEndPointer,
|
||
|
self::getReferenceType($phpcsFile, $nameStartPointer, $nameEndPointer)
|
||
|
);
|
||
|
$beginSearchAtPointer = $nameEndPointer + 1;
|
||
|
}
|
||
|
return $referencedNames;
|
||
|
}
|
||
|
|
||
|
private static function getReferenceType(File $phpcsFile, int $nameStartPointer, int $nameEndPointer): string
|
||
|
{
|
||
|
$tokens = $phpcsFile->getTokens();
|
||
|
|
||
|
$nextTokenAfterEndPointer = TokenHelper::findNextEffective($phpcsFile, $nameEndPointer + 1);
|
||
|
$previousTokenBeforeStartPointer = TokenHelper::findPreviousEffective($phpcsFile, $nameStartPointer - 1);
|
||
|
|
||
|
$nameTokenCodes = TokenHelper::getNameTokenCodes();
|
||
|
|
||
|
if ($tokens[$nextTokenAfterEndPointer]['code'] === T_OPEN_PARENTHESIS) {
|
||
|
return $tokens[$previousTokenBeforeStartPointer]['code'] === T_NEW
|
||
|
? ReferencedName::TYPE_CLASS
|
||
|
: ReferencedName::TYPE_FUNCTION;
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
$tokens[$previousTokenBeforeStartPointer]['code'] === T_TYPE_UNION
|
||
|
|| $tokens[$nextTokenAfterEndPointer]['code'] === T_TYPE_UNION
|
||
|
) {
|
||
|
return ReferencedName::TYPE_CLASS;
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
$tokens[$previousTokenBeforeStartPointer]['code'] === T_TYPE_INTERSECTION
|
||
|
|| $tokens[$nextTokenAfterEndPointer]['code'] === T_TYPE_INTERSECTION
|
||
|
) {
|
||
|
return ReferencedName::TYPE_CLASS;
|
||
|
}
|
||
|
|
||
|
if ($tokens[$nextTokenAfterEndPointer]['code'] === T_BITWISE_AND) {
|
||
|
$tokenAfterNextToken = TokenHelper::findNextEffective($phpcsFile, $nextTokenAfterEndPointer + 1);
|
||
|
|
||
|
return in_array($tokens[$tokenAfterNextToken]['code'], [T_VARIABLE, T_ELLIPSIS], true)
|
||
|
? ReferencedName::TYPE_CLASS
|
||
|
: ReferencedName::TYPE_CONSTANT;
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
in_array($tokens[$nextTokenAfterEndPointer]['code'], [
|
||
|
T_VARIABLE,
|
||
|
// Variadic parameter
|
||
|
T_ELLIPSIS,
|
||
|
], true)
|
||
|
) {
|
||
|
return ReferencedName::TYPE_CLASS;
|
||
|
}
|
||
|
|
||
|
if ($tokens[$previousTokenBeforeStartPointer]['code'] === T_COLON) {
|
||
|
$previousTokenPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousTokenBeforeStartPointer - 1);
|
||
|
|
||
|
if (
|
||
|
$tokens[$previousTokenPointer]['code'] === T_PARAM_NAME
|
||
|
&& $tokens[$nextTokenAfterEndPointer]['code'] !== T_DOUBLE_COLON
|
||
|
) {
|
||
|
return ReferencedName::TYPE_CONSTANT;
|
||
|
}
|
||
|
|
||
|
// Return type hint
|
||
|
return ReferencedName::TYPE_CLASS;
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
in_array($tokens[$previousTokenBeforeStartPointer]['code'], [
|
||
|
T_EXTENDS,
|
||
|
T_IMPLEMENTS,
|
||
|
T_INSTANCEOF,
|
||
|
// Trait
|
||
|
T_USE,
|
||
|
T_NEW,
|
||
|
// Nullable type hint
|
||
|
T_NULLABLE,
|
||
|
], true)
|
||
|
|| $tokens[$nextTokenAfterEndPointer]['code'] === T_DOUBLE_COLON
|
||
|
) {
|
||
|
return ReferencedName::TYPE_CLASS;
|
||
|
}
|
||
|
|
||
|
if ($tokens[$previousTokenBeforeStartPointer]['code'] === T_COMMA) {
|
||
|
$previousTokenPointer = TokenHelper::findPreviousExcluding(
|
||
|
$phpcsFile,
|
||
|
array_merge([T_COMMA], $nameTokenCodes, TokenHelper::$ineffectiveTokenCodes),
|
||
|
$previousTokenBeforeStartPointer - 1
|
||
|
);
|
||
|
|
||
|
return in_array($tokens[$previousTokenPointer]['code'], [
|
||
|
T_IMPLEMENTS,
|
||
|
T_EXTENDS,
|
||
|
T_USE,
|
||
|
], true)
|
||
|
? ReferencedName::TYPE_CLASS
|
||
|
: ReferencedName::TYPE_CONSTANT;
|
||
|
}
|
||
|
|
||
|
if (in_array($tokens[$previousTokenBeforeStartPointer]['code'], [T_BITWISE_OR, T_OPEN_PARENTHESIS], true)) {
|
||
|
$catchPointer = TokenHelper::findPreviousExcluding(
|
||
|
$phpcsFile,
|
||
|
array_merge([T_BITWISE_OR, T_OPEN_PARENTHESIS], $nameTokenCodes, TokenHelper::$ineffectiveTokenCodes),
|
||
|
$previousTokenBeforeStartPointer - 1
|
||
|
);
|
||
|
|
||
|
if ($tokens[$catchPointer]['code'] === T_CATCH) {
|
||
|
return ReferencedName::TYPE_CLASS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ReferencedName::TYPE_CONSTANT;
|
||
|
}
|
||
|
|
||
|
private static function isReferencedName(File $phpcsFile, int $startPointer): bool
|
||
|
{
|
||
|
$tokens = $phpcsFile->getTokens();
|
||
|
|
||
|
$nextPointer = TokenHelper::findNextEffective($phpcsFile, $startPointer + 1);
|
||
|
$previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $startPointer - 1);
|
||
|
|
||
|
if ($nextPointer !== null && $tokens[$nextPointer]['code'] === T_DOUBLE_COLON) {
|
||
|
return !in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR], true);
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
count($tokens[$startPointer]['conditions']) > 0
|
||
|
&& array_values(array_reverse($tokens[$startPointer]['conditions']))[0] === T_USE
|
||
|
) {
|
||
|
// Method imported from trait
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$previousToken = $tokens[$previousPointer];
|
||
|
|
||
|
$skipTokenCodes = [
|
||
|
T_FUNCTION,
|
||
|
T_AS,
|
||
|
T_DOUBLE_COLON,
|
||
|
T_OBJECT_OPERATOR,
|
||
|
T_NULLSAFE_OBJECT_OPERATOR,
|
||
|
T_NAMESPACE,
|
||
|
T_CONST,
|
||
|
T_ENUM_CASE,
|
||
|
];
|
||
|
|
||
|
if ($previousToken['code'] === T_USE) {
|
||
|
$classPointer = TokenHelper::findPrevious($phpcsFile, [T_CLASS, T_TRAIT, T_ANON_CLASS, T_ENUM], $startPointer - 1);
|
||
|
if ($classPointer !== null) {
|
||
|
$classToken = $tokens[$classPointer];
|
||
|
return $startPointer > $classToken['scope_opener'] && $startPointer < $classToken['scope_closer'];
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
$previousToken['code'] === T_OPEN_PARENTHESIS
|
||
|
&& isset($previousToken['parenthesis_owner'])
|
||
|
&& $tokens[$previousToken['parenthesis_owner']]['code'] === T_DECLARE
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
$previousToken['code'] === T_COMMA
|
||
|
&& TokenHelper::findPreviousLocal($phpcsFile, T_DECLARE, $previousPointer - 1) !== null
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ($previousToken['code'] === T_COMMA) {
|
||
|
$constPointer = TokenHelper::findPreviousLocal($phpcsFile, T_CONST, $previousPointer - 1);
|
||
|
if (
|
||
|
$constPointer !== null
|
||
|
&& TokenHelper::findNext($phpcsFile, [T_OPEN_SHORT_ARRAY, T_ARRAY], $constPointer + 1, $startPointer) === null
|
||
|
) {
|
||
|
return false;
|
||
|
}
|
||
|
} elseif ($previousToken['code'] === T_BITWISE_AND) {
|
||
|
$pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1);
|
||
|
$isFunctionPointerBefore = TokenHelper::findPreviousLocal($phpcsFile, T_FUNCTION, $previousPointer - 1) !== null;
|
||
|
|
||
|
if ($tokens[$pointerBefore]['code'] !== T_VARIABLE && $isFunctionPointerBefore) {
|
||
|
return false;
|
||
|
}
|
||
|
} elseif ($previousToken['code'] === T_GOTO) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$isProbablyReferencedName = !in_array(
|
||
|
$previousToken['code'],
|
||
|
array_merge($skipTokenCodes, TokenHelper::$typeKeywordTokenCodes),
|
||
|
true
|
||
|
);
|
||
|
|
||
|
if (!$isProbablyReferencedName) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$endPointer = self::getReferencedNameEndPointer($phpcsFile, $startPointer);
|
||
|
$referencedName = self::getReferenceName($phpcsFile, $startPointer, $endPointer);
|
||
|
|
||
|
if (TypeHintHelper::isSimpleTypeHint($referencedName) || $referencedName === 'object') {
|
||
|
return $tokens[$nextPointer]['code'] === T_OPEN_PARENTHESIS;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return list<ReferencedName>
|
||
|
*/
|
||
|
private static function createAllReferencedNamesInAttributes(File $phpcsFile, int $openTagPointer): array
|
||
|
{
|
||
|
$referencedNames = [];
|
||
|
|
||
|
$tokens = $phpcsFile->getTokens();
|
||
|
|
||
|
$attributePointers = TokenHelper::findNextAll($phpcsFile, T_ATTRIBUTE, $openTagPointer + 1);
|
||
|
|
||
|
foreach ($attributePointers as $attributeStartPointer) {
|
||
|
$searchStartPointer = $attributeStartPointer + 1;
|
||
|
$searchEndPointer = $tokens[$attributeStartPointer]['attribute_closer'];
|
||
|
|
||
|
$searchPointer = $searchStartPointer;
|
||
|
$searchTokens = array_merge(TokenHelper::getNameTokenCodes(), [T_OPEN_PARENTHESIS, T_CLOSE_PARENTHESIS]);
|
||
|
$level = 0;
|
||
|
do {
|
||
|
$pointer = TokenHelper::findNext($phpcsFile, $searchTokens, $searchPointer, $searchEndPointer);
|
||
|
|
||
|
if ($pointer === null) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ($tokens[$pointer]['code'] === T_OPEN_PARENTHESIS) {
|
||
|
$level++;
|
||
|
$searchPointer = $pointer + 1;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ($tokens[$pointer]['code'] === T_CLOSE_PARENTHESIS) {
|
||
|
$level--;
|
||
|
$searchPointer = $pointer + 1;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$referencedNameEndPointer = self::getReferencedNameEndPointer($phpcsFile, $pointer);
|
||
|
|
||
|
$pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1);
|
||
|
|
||
|
if (in_array($tokens[$pointerBefore]['code'], [T_OPEN_TAG, T_ATTRIBUTE], true)) {
|
||
|
$referenceType = ReferencedName::TYPE_CLASS;
|
||
|
} elseif ($tokens[$pointerBefore]['code'] === T_COMMA && $level === 0) {
|
||
|
$referenceType = ReferencedName::TYPE_CLASS;
|
||
|
} elseif (self::isReferencedName($phpcsFile, $pointer)) {
|
||
|
$referenceType = self::getReferenceType($phpcsFile, $pointer, $referencedNameEndPointer);
|
||
|
} else {
|
||
|
$searchPointer = $pointer + 1;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$referencedName = self::getReferenceName($phpcsFile, $pointer, $referencedNameEndPointer);
|
||
|
|
||
|
$referencedNames[] = new ReferencedName(
|
||
|
$referencedName,
|
||
|
$attributeStartPointer,
|
||
|
$tokens[$attributeStartPointer]['attribute_closer'],
|
||
|
$referenceType
|
||
|
);
|
||
|
|
||
|
$searchPointer = $referencedNameEndPointer + 1;
|
||
|
|
||
|
} while (true);
|
||
|
}
|
||
|
|
||
|
return $referencedNames;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int|string $code
|
||
|
*/
|
||
|
private static function isNeedParsedContent($code): bool
|
||
|
{
|
||
|
return in_array($code, [T_DOUBLE_QUOTED_STRING, T_HEREDOC], true);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return list<string>
|
||
|
*/
|
||
|
private static function getReferencedNamesFromString(string $content): array
|
||
|
{
|
||
|
$referencedNames = [];
|
||
|
$subTokens = token_get_all('<?php ' . $content);
|
||
|
|
||
|
foreach ($subTokens as $position => $token) {
|
||
|
if (is_array($token) && $token[0] === T_DOUBLE_COLON) {
|
||
|
$referencedName = '';
|
||
|
$tmpPosition = $position - 1;
|
||
|
while (true) {
|
||
|
if (!is_array($subTokens[$tmpPosition]) || !in_array($subTokens[$tmpPosition][0], [T_NS_SEPARATOR, T_STRING], true)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
$referencedName = $subTokens[$tmpPosition][1] . $referencedName;
|
||
|
$tmpPosition--;
|
||
|
}
|
||
|
|
||
|
$referencedNames[] = $referencedName;
|
||
|
} elseif (is_array($token) && $token[0] === T_NEW) {
|
||
|
$referencedName = '';
|
||
|
$tmpPosition = $position + 1;
|
||
|
while (true) {
|
||
|
if (!is_array($subTokens[$tmpPosition])) {
|
||
|
break;
|
||
|
}
|
||
|
if ($subTokens[$tmpPosition][0] === T_WHITESPACE) {
|
||
|
$tmpPosition++;
|
||
|
continue;
|
||
|
}
|
||
|
if (!in_array(
|
||
|
$subTokens[$tmpPosition][0],
|
||
|
[T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED, T_NAME_RELATIVE],
|
||
|
true
|
||
|
)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
$referencedName .= $subTokens[$tmpPosition][1];
|
||
|
$tmpPosition++;
|
||
|
}
|
||
|
if ($referencedName !== '') {
|
||
|
$referencedNames[] = $referencedName;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $referencedNames;
|
||
|
}
|
||
|
|
||
|
}
|