=> */ private static $extraParenthesesOwners = [ \T_ISSET => \T_ISSET, \T_UNSET => \T_UNSET, \T_EMPTY => \T_EMPTY, \T_EXIT => \T_EXIT, \T_EVAL => \T_EVAL, ]; /** * Get the stack pointer to the parentheses owner of an open/close parenthesis. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of `T_OPEN/CLOSE_PARENTHESIS` token. * * @return int|false Integer stack pointer to the parentheses owner; or `FALSE` if the * parenthesis does not have a (direct) owner or if the token passed * was not a parenthesis. */ public static function getOwner(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if (isset($tokens[$stackPtr]['parenthesis_owner'])) { return $tokens[$stackPtr]['parenthesis_owner']; } /* * As the 'parenthesis_owner' index is only set on parentheses, we didn't need to do any * input validation before, but now we do. */ if (isset($tokens[$stackPtr]) === false || ($tokens[$stackPtr]['code'] !== \T_OPEN_PARENTHESIS && $tokens[$stackPtr]['code'] !== \T_CLOSE_PARENTHESIS) ) { return false; } if ($tokens[$stackPtr]['code'] === \T_CLOSE_PARENTHESIS) { $stackPtr = $tokens[$stackPtr]['parenthesis_opener']; } $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); if ($prevNonEmpty !== false && isset(self::$extraParenthesesOwners[$tokens[$prevNonEmpty]['code']]) === true ) { return $prevNonEmpty; } return false; } /** * Check whether the parenthesis owner of an open/close parenthesis is within a limited * set of valid owners. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of `T_OPEN/CLOSE_PARENTHESIS` token. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return bool `TRUE` if the owner is within the list of `$validOwners`; `FALSE` if not and * if the parenthesis does not have a (direct) owner. */ public static function isOwnerIn(File $phpcsFile, $stackPtr, $validOwners) { $owner = self::getOwner($phpcsFile, $stackPtr); if ($owner === false) { return false; } $tokens = $phpcsFile->getTokens(); $validOwners = (array) $validOwners; return \in_array($tokens[$owner]['code'], $validOwners, true); } /** * Check whether the passed token is nested within parentheses owned by one of the valid owners. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return bool */ public static function hasOwner(File $phpcsFile, $stackPtr, $validOwners) { return (self::nestedParensWalker($phpcsFile, $stackPtr, $validOwners) !== false); } /** * Retrieve the stack pointer to the parentheses opener of the first (outer) set of parentheses * an arbitrary token is wrapped in. * * If the optional `$validOwners` parameter is passed, the stack pointer to the opener to * the first set of parentheses, which has an owner which is in the list of valid owners, * will be returned. This may be a nested set of parentheses. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the parentheses opener; or `FALSE` if the token * does not have parentheses owned by any of the valid owners or if * the token is not nested in parentheses at all. */ public static function getFirstOpener(File $phpcsFile, $stackPtr, $validOwners = []) { return self::nestedParensWalker($phpcsFile, $stackPtr, $validOwners, false); } /** * Retrieve the stack pointer to the parentheses closer of the first (outer) set of parentheses * an arbitrary token is wrapped in. * * If the optional `$validOwners` parameter is passed, the stack pointer to the closer to * the first set of parentheses, which has an owner which is in the list of valid owners, * will be returned. This may be a nested set of parentheses. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the parentheses closer; or `FALSE` if the token * does not have parentheses owned by any of the valid owners or if * the token is not nested in parentheses at all. */ public static function getFirstCloser(File $phpcsFile, $stackPtr, $validOwners = []) { $opener = self::getFirstOpener($phpcsFile, $stackPtr, $validOwners); $tokens = $phpcsFile->getTokens(); if ($opener !== false && isset($tokens[$opener]['parenthesis_closer']) === true) { return $tokens[$opener]['parenthesis_closer']; } return false; } /** * Retrieve the stack pointer to the parentheses owner of the first (outer) set of parentheses * an arbitrary token is wrapped in. * * If the optional `$validOwners` parameter is passed, the stack pointer to the owner of * the first set of parentheses, which has an owner which is in the list of valid owners, * will be returned. This may be a nested set of parentheses. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the parentheses owner; or `FALSE` if the token * does not have parentheses owned by any of the valid owners or if * the token is not nested in parentheses at all. */ public static function getFirstOwner(File $phpcsFile, $stackPtr, $validOwners = []) { $opener = self::getFirstOpener($phpcsFile, $stackPtr, $validOwners); if ($opener !== false) { return self::getOwner($phpcsFile, $opener); } return false; } /** * Retrieve the stack pointer to the parentheses opener of the last (inner) set of parentheses * an arbitrary token is wrapped in. * * If the optional `$validOwners` parameter is passed, the stack pointer to the opener to * the last set of parentheses, which has an owner which is in the list of valid owners, * will be returned. This may be a set of parentheses higher up. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the parentheses opener; or `FALSE` if the token * does not have parentheses owned by any of the valid owners or if * the token is not nested in parentheses at all. */ public static function getLastOpener(File $phpcsFile, $stackPtr, $validOwners = []) { return self::nestedParensWalker($phpcsFile, $stackPtr, $validOwners, true); } /** * Retrieve the stack pointer to the parentheses closer of the last (inner) set of parentheses * an arbitrary token is wrapped in. * * If the optional `$validOwners` parameter is passed, the stack pointer to the closer to * the last set of parentheses, which has an owner which is in the list of valid owners, * will be returned. This may be a set of parentheses higher up. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the parentheses closer; or `FALSE` if the token * does not have parentheses owned by any of the valid owners or if * the token is not nested in parentheses at all. */ public static function getLastCloser(File $phpcsFile, $stackPtr, $validOwners = []) { $opener = self::getLastOpener($phpcsFile, $stackPtr, $validOwners); $tokens = $phpcsFile->getTokens(); if ($opener !== false && isset($tokens[$opener]['parenthesis_closer']) === true) { return $tokens[$opener]['parenthesis_closer']; } return false; } /** * Retrieve the stack pointer to the parentheses owner of the last (inner) set of parentheses * an arbitrary token is wrapped in. * * If the optional `$validOwners` parameter is passed, the stack pointer to the owner of * the last set of parentheses, which has an owner which is in the list of valid owners, * will be returned. This may be a set of parentheses higher up. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the parentheses owner; or `FALSE` if the token * does not have parentheses owned by any of the valid owners or if * the token is not nested in parentheses at all. */ public static function getLastOwner(File $phpcsFile, $stackPtr, $validOwners = []) { $opener = self::getLastOpener($phpcsFile, $stackPtr, $validOwners); if ($opener !== false) { return self::getOwner($phpcsFile, $opener); } return false; } /** * Check whether the owner of the outermost wrapping set of parentheses of an arbitrary token * is within a limited set of acceptable token types. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position in the stack of the * token to verify. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the valid parentheses owner; or `FALSE` if * the token was not wrapped in parentheses or if the outermost set * of parentheses in which the token is wrapped does not have an owner * within the set of owners considered valid. */ public static function firstOwnerIn(File $phpcsFile, $stackPtr, $validOwners) { $opener = self::getFirstOpener($phpcsFile, $stackPtr); if ($opener !== false && self::isOwnerIn($phpcsFile, $opener, $validOwners) === true) { return self::getOwner($phpcsFile, $opener); } return false; } /** * Check whether the owner of the innermost wrapping set of parentheses of an arbitrary token * is within a limited set of acceptable token types. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position in the stack of the * token to verify. * @param int|string|array $validOwners Array of token constants for the owners * which should be considered valid. * * @return int|false Integer stack pointer to the valid parentheses owner; or `FALSE` if * the token was not wrapped in parentheses or if the innermost set * of parentheses in which the token is wrapped does not have an owner * within the set of owners considered valid. */ public static function lastOwnerIn(File $phpcsFile, $stackPtr, $validOwners) { $opener = self::getLastOpener($phpcsFile, $stackPtr); if ($opener !== false && self::isOwnerIn($phpcsFile, $opener, $validOwners) === true) { return self::getOwner($phpcsFile, $opener); } return false; } /** * Helper method. Retrieve the position of a parentheses opener for an arbitrary passed token. * * If no `$validOwners` are specified, the opener to the first set of parentheses surrounding * the token - or if `$reverse = true`, the last set of parentheses - will be returned. * * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. * @param int $stackPtr The position of the token we are checking. * @param int|string|array $validOwners Optional. Array of token constants for the owners * which should be considered valid. * @param bool $reverse Optional. Whether to search for the first/outermost * (`false`) or the last/innermost (`true`) set of * parentheses with the specified owner(s). * * @return int|false Integer stack pointer to the parentheses opener; or `FALSE` if the token * does not have parentheses owned by any of the valid owners or if * the token is not nested in parentheses at all. */ private static function nestedParensWalker(File $phpcsFile, $stackPtr, $validOwners = [], $reverse = false) { $tokens = $phpcsFile->getTokens(); // Check for the existence of the token. if (isset($tokens[$stackPtr]) === false) { return false; } // Make sure the token is nested in parenthesis. if (empty($tokens[$stackPtr]['nested_parenthesis']) === true) { return false; } $validOwners = (array) $validOwners; $parentheses = $tokens[$stackPtr]['nested_parenthesis']; if (empty($validOwners) === true) { // No owners specified, just return the first/last parentheses opener. if ($reverse === true) { \end($parentheses); } else { \reset($parentheses); } return \key($parentheses); } if ($reverse === true) { $parentheses = \array_reverse($parentheses, true); } foreach ($parentheses as $opener => $closer) { if (self::isOwnerIn($phpcsFile, $opener, $validOwners) === true) { // We found a token with a valid owner. return $opener; } } return false; } }