Ghost Exploiter Team Official
Mass Deface
Directory >>
/
var
/
www
/
html
/
back
/
vendor
/
friendsofphp
/
php-cs-fixer
/
src
/
Tokenizer
/
Mass Deface Auto Detect Domain
/*Ubah Ke document_root untuk mass deface*/
File / Folder
Size
Action
.
-
type
file
dir
+File/Dir
Analyzer
--
ren
Processor
--
ren
Transformer
--
ren
AbstractTransformer.php
0.929KB
edt
ren
AbstractTypeTransformer
...
2.889KB
edt
ren
CT.php
3.755KB
edt
ren
FCT.php
2.502KB
edt
ren
Token.php
16.202KB
edt
ren
Tokens.php
52.335KB
edt
ren
TokensAnalyzer.php
28.675KB
edt
ren
TransformerInterface.php
1.991KB
edt
ren
Transformers.php
2.747KB
edt
ren
<?php declare(strict_types=1); /* * This file is part of PHP CS Fixer. * * (c) Fabien Potencier <fabien@symfony.com> * Dariusz Rumiński <dariusz.ruminski@gmail.com> * * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. */ namespace PhpCsFixer\Tokenizer; use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\GotoLabelAnalyzer; /** * Analyzer of Tokens collection. * * Its role is to provide the ability to analyse collection. * * @internal * * @phpstan-type _ClassyElementType 'case'|'const'|'method'|'property'|'promoted_property'|'trait_import' * * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> * @author Gregor Harlan <gharlan@web.de> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise. */ final class TokensAnalyzer { /** * Tokens collection instance. */ private Tokens $tokens; /** * @readonly */ private GotoLabelAnalyzer $gotoLabelAnalyzer; public function __construct(Tokens $tokens) { $this->tokens = $tokens; $this->gotoLabelAnalyzer = new GotoLabelAnalyzer(); } /** * Get indices of methods and properties in classy code (classes, interfaces and traits). * * @return array<int, array{classIndex: int, token: Token, type: _ClassyElementType}> */ public function getClassyElements(): array { $elements = []; for ($index = 1, $count = \count($this->tokens) - 2; $index < $count; ++$index) { if ($this->tokens[$index]->isClassy()) { [$index, $newElements] = $this->findClassyElements($index, $index); $elements += $newElements; } } ksort($elements); return $elements; } /** * Get indices of modifiers of a classy code (classes, interfaces and traits). * * @return array{ * final: null|int, * abstract: null|int, * readonly: null|int * } */ public function getClassyModifiers(int $index): array { if (!$this->tokens[$index]->isClassy()) { throw new \InvalidArgumentException(\sprintf('Not an "classy" at given index %d.', $index)); } $modifiers = ['final' => null, 'abstract' => null, 'readonly' => null]; while (true) { $index = $this->tokens->getPrevMeaningfulToken($index); if ($this->tokens[$index]->isGivenKind(\T_FINAL)) { $modifiers['final'] = $index; } elseif ($this->tokens[$index]->isGivenKind(\T_ABSTRACT)) { $modifiers['abstract'] = $index; } elseif ($this->tokens[$index]->isGivenKind(FCT::T_READONLY)) { $modifiers['readonly'] = $index; } else { // no need to skip attributes as it is not possible on PHP8.2 break; } } return $modifiers; } /** * Get indices of namespace uses. * * @param bool $perNamespace Return namespace uses per namespace * * @return ($perNamespace is true ? array<int, non-empty-list<int>> : list<int>) */ public function getImportUseIndexes(bool $perNamespace = false): array { $tokens = $this->tokens; $uses = []; $namespaceIndex = 0; for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { $token = $tokens[$index]; if ($token->isGivenKind(\T_NAMESPACE)) { $nextTokenIndex = $tokens->getNextTokenOfKind($index, [';', '{']); $nextToken = $tokens[$nextTokenIndex]; if ($nextToken->equals('{')) { $index = $nextTokenIndex; } if ($perNamespace) { ++$namespaceIndex; } continue; } if ($token->isGivenKind(\T_USE)) { $uses[$namespaceIndex][] = $index; } } if (!$perNamespace && isset($uses[$namespaceIndex])) { return $uses[$namespaceIndex]; } return $uses; } /** * Check if there is an array at given index. */ public function isArray(int $index): bool { return $this->tokens[$index]->isGivenKind([\T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN]); } /** * Check if the array at index is multiline. * * This only checks the root-level of the array. */ public function isArrayMultiLine(int $index): bool { if (!$this->isArray($index)) { throw new \InvalidArgumentException(\sprintf('Not an array at given index %d.', $index)); } $tokens = $this->tokens; // Skip only when it's an array, for short arrays we need the brace for correct // level counting if ($tokens[$index]->isGivenKind(\T_ARRAY)) { $index = $tokens->getNextMeaningfulToken($index); } return $this->isBlockMultiline($tokens, $index); } public function isBlockMultiline(Tokens $tokens, int $index): bool { $blockType = Tokens::detectBlockType($tokens[$index]); if (null === $blockType || !$blockType['isStart']) { throw new \InvalidArgumentException(\sprintf('Not an block start at given index %d.', $index)); } $endIndex = $tokens->findBlockEnd($blockType['type'], $index); for (++$index; $index < $endIndex; ++$index) { $token = $tokens[$index]; $blockType = Tokens::detectBlockType($token); if (null !== $blockType && $blockType['isStart']) { $index = $tokens->findBlockEnd($blockType['type'], $index); continue; } if ( $token->isWhitespace() && !$tokens[$index - 1]->isGivenKind(\T_END_HEREDOC) && str_contains($token->getContent(), "\n") ) { return true; } } return false; } /** * @param int $index Index of the T_FUNCTION token * * @return array{visibility: null|T_PRIVATE|T_PROTECTED|T_PUBLIC, static: bool, abstract: bool, final: bool} */ public function getMethodAttributes(int $index): array { if (!$this->tokens[$index]->isGivenKind(\T_FUNCTION)) { throw new \LogicException(\sprintf('No T_FUNCTION at given index %d, got "%s".', $index, $this->tokens[$index]->getName())); } $attributes = [ 'visibility' => null, 'static' => false, 'abstract' => false, 'final' => false, ]; for ($i = $index; $i >= 0; --$i) { $i = $this->tokens->getPrevMeaningfulToken($i); $token = $this->tokens[$i]; if ($token->isGivenKind(\T_STATIC)) { $attributes['static'] = true; continue; } if ($token->isGivenKind(\T_FINAL)) { $attributes['final'] = true; continue; } if ($token->isGivenKind(\T_ABSTRACT)) { $attributes['abstract'] = true; continue; } // visibility if ($token->isGivenKind(\T_PRIVATE)) { $attributes['visibility'] = \T_PRIVATE; continue; } if ($token->isGivenKind(\T_PROTECTED)) { $attributes['visibility'] = \T_PROTECTED; continue; } if ($token->isGivenKind(\T_PUBLIC)) { $attributes['visibility'] = \T_PUBLIC; continue; } // found a meaningful token that is not part of // the function signature; stop looking break; } return $attributes; } /** * Check if there is an anonymous class under given index. */ public function isAnonymousClass(int $index): bool { if (!$this->tokens[$index]->isClassy()) { throw new \LogicException(\sprintf('No classy token at given index %d.', $index)); } if (!$this->tokens[$index]->isGivenKind(\T_CLASS)) { return false; } $index = $this->tokens->getPrevMeaningfulToken($index); if ($this->tokens[$index]->isGivenKind(FCT::T_READONLY)) { $index = $this->tokens->getPrevMeaningfulToken($index); } while ($this->tokens[$index]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { $index = $this->tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); $index = $this->tokens->getPrevMeaningfulToken($index); } return $this->tokens[$index]->isGivenKind(\T_NEW); } /** * Check if the function under given index is a lambda. */ public function isLambda(int $index): bool { if (!$this->tokens[$index]->isGivenKind([\T_FUNCTION, \T_FN])) { throw new \LogicException(\sprintf('No T_FUNCTION or T_FN at given index %d, got "%s".', $index, $this->tokens[$index]->getName())); } $startParenthesisIndex = $this->tokens->getNextMeaningfulToken($index); $startParenthesisToken = $this->tokens[$startParenthesisIndex]; // skip & for `function & () {}` syntax if ($startParenthesisToken->isGivenKind(CT::T_RETURN_REF)) { $startParenthesisIndex = $this->tokens->getNextMeaningfulToken($startParenthesisIndex); $startParenthesisToken = $this->tokens[$startParenthesisIndex]; } return $startParenthesisToken->equals('('); } public function getLastTokenIndexOfArrowFunction(int $index): int { if (!$this->tokens[$index]->isGivenKind(\T_FN)) { throw new \InvalidArgumentException(\sprintf('Not an "arrow function" at given index %d.', $index)); } $stopTokens = [')', ']', ',', ';', [\T_CLOSE_TAG]]; $index = $this->tokens->getNextTokenOfKind($index, [[\T_DOUBLE_ARROW]]); while (true) { $index = $this->tokens->getNextMeaningfulToken($index); if ($this->tokens[$index]->equalsAny($stopTokens)) { break; } $blockType = Tokens::detectBlockType($this->tokens[$index]); if (null === $blockType) { continue; } if ($blockType['isStart']) { $index = $this->tokens->findBlockEnd($blockType['type'], $index); continue; } break; } return $this->tokens->getPrevMeaningfulToken($index); } /** * Check if the T_STRING under given index is a constant invocation. */ public function isConstantInvocation(int $index): bool { if (!$this->tokens[$index]->isGivenKind(\T_STRING)) { throw new \LogicException(\sprintf('No T_STRING at given index %d, got "%s".', $index, $this->tokens[$index]->getName())); } $nextIndex = $this->tokens->getNextMeaningfulToken($index); if ( $this->tokens[$nextIndex]->equalsAny(['(', '{']) || $this->tokens[$nextIndex]->isGivenKind([\T_DOUBLE_COLON, \T_ELLIPSIS, \T_NS_SEPARATOR, CT::T_RETURN_REF, CT::T_TYPE_ALTERNATION, CT::T_TYPE_INTERSECTION, \T_VARIABLE]) ) { return false; } // handle foreach( FOO as $_ ) {} if ($this->tokens[$nextIndex]->isGivenKind(\T_AS)) { $prevIndex = $this->tokens->getPrevMeaningfulToken($index); if (!$this->tokens[$prevIndex]->equals('(')) { return false; } } $prevIndex = $this->tokens->getPrevMeaningfulToken($index); if ($this->tokens[$prevIndex]->isGivenKind(Token::getClassyTokenKinds())) { return false; } if ($this->tokens[$prevIndex]->isGivenKind([\T_AS, \T_CONST, \T_DOUBLE_COLON, \T_FUNCTION, \T_GOTO, CT::T_GROUP_IMPORT_BRACE_OPEN, CT::T_TYPE_COLON, CT::T_TYPE_ALTERNATION, CT::T_TYPE_INTERSECTION]) || $this->tokens[$prevIndex]->isObjectOperator()) { return false; } if ( $this->tokens[$prevIndex]->isGivenKind(\T_CASE) && $this->tokens->isAllTokenKindsFound([FCT::T_ENUM]) ) { $enumSwitchIndex = $this->tokens->getPrevTokenOfKind($index, [[\T_SWITCH], [\T_ENUM]]); if (!$this->tokens[$enumSwitchIndex]->isGivenKind(\T_SWITCH)) { return false; } } while ($this->tokens[$prevIndex]->isGivenKind([CT::T_NAMESPACE_OPERATOR, \T_NS_SEPARATOR, \T_STRING, CT::T_ARRAY_TYPEHINT])) { $prevIndex = $this->tokens->getPrevMeaningfulToken($prevIndex); } if ($this->tokens[$prevIndex]->isGivenKind([CT::T_CONST_IMPORT, \T_EXTENDS, CT::T_FUNCTION_IMPORT, \T_IMPLEMENTS, \T_INSTANCEOF, \T_INSTEADOF, \T_NAMESPACE, \T_NEW, CT::T_NULLABLE_TYPE, CT::T_TYPE_COLON, \T_USE, CT::T_USE_TRAIT, CT::T_TYPE_INTERSECTION, CT::T_TYPE_ALTERNATION, \T_CONST, CT::T_DISJUNCTIVE_NORMAL_FORM_TYPE_PARENTHESIS_CLOSE])) { return false; } // `FOO & $bar` could be: // - function reference parameter: function baz(Foo & $bar) {} // - bit operator: $x = FOO & $bar; if ($this->tokens[$nextIndex]->equals('&') && $this->tokens[$this->tokens->getNextMeaningfulToken($nextIndex)]->isGivenKind(\T_VARIABLE)) { $checkIndex = $this->tokens->getPrevTokenOfKind($prevIndex, [';', '{', '}', [\T_FUNCTION], [\T_OPEN_TAG], [\T_OPEN_TAG_WITH_ECHO]]); if ($this->tokens[$checkIndex]->isGivenKind(\T_FUNCTION)) { return false; } } // check for `extends`/`implements`/`use` list if ($this->tokens[$prevIndex]->equals(',')) { $checkIndex = $prevIndex; while ($this->tokens[$checkIndex]->equalsAny([',', [\T_AS], [CT::T_NAMESPACE_OPERATOR], [\T_NS_SEPARATOR], [\T_STRING]])) { $checkIndex = $this->tokens->getPrevMeaningfulToken($checkIndex); } if ($this->tokens[$checkIndex]->isGivenKind([\T_EXTENDS, CT::T_GROUP_IMPORT_BRACE_OPEN, \T_IMPLEMENTS, \T_USE, CT::T_USE_TRAIT])) { return false; } } // check for array in double quoted string: `"..$foo[bar].."` if ($this->tokens[$prevIndex]->equals('[') && $this->tokens[$nextIndex]->equals(']')) { $checkToken = $this->tokens[$this->tokens->getNextMeaningfulToken($nextIndex)]; if ($checkToken->equals('"') || $checkToken->isGivenKind([\T_CURLY_OPEN, \T_DOLLAR_OPEN_CURLY_BRACES, \T_ENCAPSED_AND_WHITESPACE, \T_VARIABLE])) { return false; } } // check for attribute: `#[Foo]` if (AttributeAnalyzer::isAttribute($this->tokens, $index)) { return false; } // check for goto label if ($this->tokens[$nextIndex]->equals(':')) { if ($this->gotoLabelAnalyzer->belongsToGoToLabel($this->tokens, $nextIndex)) { return false; } } // check for non-capturing catches while ($this->tokens[$prevIndex]->isGivenKind([CT::T_NAMESPACE_OPERATOR, \T_NS_SEPARATOR, \T_STRING, CT::T_TYPE_ALTERNATION])) { $prevIndex = $this->tokens->getPrevMeaningfulToken($prevIndex); } if ($this->tokens[$prevIndex]->equals('(')) { $prevPrevIndex = $this->tokens->getPrevMeaningfulToken($prevIndex); if ($this->tokens[$prevPrevIndex]->isGivenKind(\T_CATCH)) { return false; } } return true; } /** * Checks if there is a unary successor operator under given index. */ public function isUnarySuccessorOperator(int $index): bool { $tokens = $this->tokens; $token = $tokens[$index]; if (!$token->isGivenKind([\T_INC, \T_DEC])) { return false; } $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; return $prevToken->equalsAny([ ']', [\T_STRING], [\T_VARIABLE], [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], [CT::T_DYNAMIC_PROP_BRACE_CLOSE], [CT::T_DYNAMIC_VAR_BRACE_CLOSE], ]); } /** * Checks if there is a unary predecessor operator under given index. */ public function isUnaryPredecessorOperator(int $index): bool { $tokens = $this->tokens; $token = $tokens[$index]; // potential unary successor operator if ($token->isGivenKind([\T_INC, \T_DEC])) { return !$this->isUnarySuccessorOperator($index); } // always unary predecessor operator if ($token->equalsAny(['!', '~', '@', [\T_ELLIPSIS]])) { return true; } // potential binary operator if (!$token->equalsAny(['+', '-', '&', [CT::T_RETURN_REF]])) { return false; } $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; if (!$prevToken->equalsAny([ ']', '}', ')', '"', '`', [CT::T_ARRAY_SQUARE_BRACE_CLOSE], [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], [CT::T_DYNAMIC_PROP_BRACE_CLOSE], [CT::T_DYNAMIC_VAR_BRACE_CLOSE], [\T_CLASS_C], [\T_CONSTANT_ENCAPSED_STRING], [\T_DEC], [\T_DIR], [\T_DNUMBER], [\T_FILE], [\T_FUNC_C], [\T_INC], [\T_LINE], [\T_LNUMBER], [\T_METHOD_C], [\T_NS_C], [\T_STRING], [\T_TRAIT_C], [\T_VARIABLE], ])) { return true; } if (!$token->equals('&') || !$prevToken->isGivenKind(\T_STRING)) { return false; } $prevToken = $tokens[$tokens->getPrevTokenOfKind($index, [ ';', '{', '}', [\T_DOUBLE_ARROW], [\T_FN], [\T_FUNCTION], [\T_OPEN_TAG], [\T_OPEN_TAG_WITH_ECHO], ])]; return $prevToken->isGivenKind([\T_FN, \T_FUNCTION]); } /** * Checks if there is a binary operator under given index. */ public function isBinaryOperator(int $index): bool { $tokens = $this->tokens; $token = $tokens[$index]; if ($token->isGivenKind([\T_INLINE_HTML, \T_ENCAPSED_AND_WHITESPACE, CT::T_TYPE_INTERSECTION])) { return false; } // potential unary predecessor operator if (\in_array($token->getContent(), ['+', '-', '&'], true)) { return !$this->isUnaryPredecessorOperator($index); } if ($token->isArray()) { return \in_array($token->getId(), [ \T_AND_EQUAL, // &= \T_BOOLEAN_AND, // && \T_BOOLEAN_OR, // || \T_CONCAT_EQUAL, // .= \T_DIV_EQUAL, // /= \T_DOUBLE_ARROW, // => \T_IS_EQUAL, // == \T_IS_GREATER_OR_EQUAL, // >= \T_IS_IDENTICAL, // === \T_IS_NOT_EQUAL, // !=, <> \T_IS_NOT_IDENTICAL, // !== \T_IS_SMALLER_OR_EQUAL, // <= \T_LOGICAL_AND, // and \T_LOGICAL_OR, // or \T_LOGICAL_XOR, // xor \T_MINUS_EQUAL, // -= \T_MOD_EQUAL, // %= \T_MUL_EQUAL, // *= \T_OR_EQUAL, // |= \T_PLUS_EQUAL, // += \T_POW, // ** \T_POW_EQUAL, // **= \T_SL, // << \T_SL_EQUAL, // <<= \T_SR, // >> \T_SR_EQUAL, // >>= \T_XOR_EQUAL, // ^= \T_SPACESHIP, // <=> \T_COALESCE, // ?? \T_COALESCE_EQUAL, // ??= ], true); } if (\in_array($token->getContent(), ['=', '*', '/', '%', '<', '>', '|', '^', '.'], true)) { return true; } return false; } /** * Check if `T_WHILE` token at given index is `do { ... } while ();` syntax * and not `while () { ...}`. */ public function isWhilePartOfDoWhile(int $index): bool { $tokens = $this->tokens; $token = $tokens[$index]; if (!$token->isGivenKind(\T_WHILE)) { throw new \LogicException(\sprintf('No T_WHILE at given index %d, got "%s".', $index, $token->getName())); } $endIndex = $tokens->getPrevMeaningfulToken($index); if (!$tokens[$endIndex]->equals('}')) { return false; } $startIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $endIndex); $beforeStartIndex = $tokens->getPrevMeaningfulToken($startIndex); return $tokens[$beforeStartIndex]->isGivenKind(\T_DO); } /** * @throws \LogicException when provided index does not point to token containing T_CASE */ public function isEnumCase(int $caseIndex): bool { $tokens = $this->tokens; $token = $tokens[$caseIndex]; if (!$token->isGivenKind(\T_CASE)) { throw new \LogicException(\sprintf( 'No T_CASE given at index %d, got %s instead.', $caseIndex, $token->getName() ?? $token->getContent(), )); } if (!$tokens->isTokenKindFound(FCT::T_ENUM)) { return false; } $prevIndex = $tokens->getPrevTokenOfKind($caseIndex, [[\T_ENUM], [\T_SWITCH]]); return null !== $prevIndex && $tokens[$prevIndex]->isGivenKind(\T_ENUM); } public function isSuperGlobal(int $index): bool { $token = $this->tokens[$index]; if (!$token->isGivenKind(\T_VARIABLE)) { return false; } return \in_array(strtoupper($token->getContent()), [ '$_COOKIE', '$_ENV', '$_FILES', '$_GET', '$_POST', '$_REQUEST', '$_SERVER', '$_SESSION', '$GLOBALS', ], true); } /** * Find classy elements. * * Searches in tokens from the classy (start) index till the end (index) of the classy. * Returns an array; first value is the index until the method has analysed (int), second the found classy elements (array). * * @param int $classIndex classy index * * @return array{int, array<int, array{classIndex: int, token: Token, type: _ClassyElementType}>} */ private function findClassyElements(int $classIndex, int $index): array { $elements = []; $curlyBracesLevel = 0; $bracesLevel = 0; ++$index; // skip the classy index itself for ($count = \count($this->tokens); $index < $count; ++$index) { $token = $this->tokens[$index]; if ($token->isGivenKind(\T_ENCAPSED_AND_WHITESPACE)) { continue; } if ($token->isGivenKind(\T_CLASS)) { // anonymous class in class // check for nested anonymous classes inside the new call of an anonymous class, // for example `new class(function (){new class(function (){new class(function (){}){};}){};}){};` etc. // if class(XYZ) {} skip till `(` as XYZ might contain functions etc. $nestedClassIndex = $index; $index = $this->tokens->getNextMeaningfulToken($index); if ($this->tokens[$index]->equals('(')) { ++$index; // move after `(` for ($nestedBracesLevel = 1; $index < $count; ++$index) { $token = $this->tokens[$index]; if ($token->equals('(')) { ++$nestedBracesLevel; continue; } if ($token->equals(')')) { --$nestedBracesLevel; if (0 === $nestedBracesLevel) { [$index, $newElements] = $this->findClassyElements($nestedClassIndex, $index); $elements += $newElements; break; } continue; } if ($token->isGivenKind(\T_CLASS)) { // anonymous class in class [$index, $newElements] = $this->findClassyElements($index, $index); $elements += $newElements; } } } else { [$index, $newElements] = $this->findClassyElements($nestedClassIndex, $nestedClassIndex); $elements += $newElements; } continue; } if ($token->equals('(')) { ++$bracesLevel; continue; } if ($token->equals(')')) { --$bracesLevel; continue; } if ($token->equals('{')) { ++$curlyBracesLevel; continue; } if ($token->equals('}')) { --$curlyBracesLevel; if (0 === $curlyBracesLevel) { break; } continue; } if (1 !== $curlyBracesLevel || !$token->isArray()) { continue; } if (0 === $bracesLevel && $token->isGivenKind(\T_VARIABLE)) { $elements[$index] = [ 'classIndex' => $classIndex, 'token' => $token, 'type' => 'property', ]; continue; } if ($token->isGivenKind(CT::T_PROPERTY_HOOK_BRACE_OPEN)) { $index = $this->tokens->getNextTokenOfKind($index, [[CT::T_PROPERTY_HOOK_BRACE_CLOSE]]); continue; } if ($token->isGivenKind(FCT::T_ATTRIBUTE)) { $index = $this->tokens->findBlockEnd(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); continue; } if ($token->isGivenKind(\T_FUNCTION)) { $elements[$index] = [ 'classIndex' => $classIndex, 'token' => $token, 'type' => 'method', ]; $functionNameIndex = $this->tokens->getNextMeaningfulToken($index); if ('__construct' === $this->tokens[$functionNameIndex]->getContent()) { $openParenthesis = $this->tokens->getNextMeaningfulToken($functionNameIndex); $closeParenthesis = $this->tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis); foreach ($this->tokens->findGivenKind([CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, FCT::T_READONLY, \T_FINAL], $openParenthesis, $closeParenthesis) as $kindElements) { foreach (array_keys($kindElements) as $promotedPropertyModifierIndex) { /** @var int $promotedPropertyVariableIndex */ $promotedPropertyVariableIndex = $this->tokens->getNextTokenOfKind($promotedPropertyModifierIndex, [[\T_VARIABLE]]); $elements[$promotedPropertyVariableIndex] = [ 'classIndex' => $classIndex, 'token' => $this->tokens[$promotedPropertyVariableIndex], 'type' => 'promoted_property', ]; } } } } elseif ($token->isGivenKind(\T_CONST)) { $elements[$index] = [ 'classIndex' => $classIndex, 'token' => $token, 'type' => 'const', ]; } elseif ($token->isGivenKind(CT::T_USE_TRAIT)) { $elements[$index] = [ 'classIndex' => $classIndex, 'token' => $token, 'type' => 'trait_import', ]; } elseif ($token->isGivenKind(\T_CASE)) { $elements[$index] = [ 'classIndex' => $classIndex, 'token' => $token, 'type' => 'case', ]; } } return [$index, $elements]; } }