src/Fixers/ClientUpgradeFixer/ClientVar.php (185 lines of code) (raw):

<?php namespace Google\Cloud\Fixers\ClientUpgradeFixer; use PhpCsFixer\Tokenizer\Tokens; use ReflectionMethod; class ClientVar { public $varName; public $className; private $parent; private $startIndex; public function __construct( $varName, $className, $parent = null ) { if ($parent) { $this->parent = $parent; } elseif (str_contains($varName, '->')) { list($this->parent, $varName) = explode('->', $varName); } elseif (str_contains($varName, '::')) { list($this->parent, $varName) = explode('::', $varName); } $this->varName = $varName; $this->className = $className; } public function getClassName(): string { return $this->className; } /** * @param Tokens $tokens * @param int $index * @return bool */ public function isDeclaredAt(Tokens $tokens, int $index): bool { if ($tokens[$index]->getContent() !== $this->varName) { // The token does not contain this client var return false; } $token = $tokens[$index]; if ($token->isGivenKind(T_VARIABLE) || ($token->isGivenKind(T_STRING) && $tokens[$index - 1]->isGivenKind(T_OBJECT_OPERATOR)) ) { if ($this->parent) { // look back to ensure the parent matches if ($tokens[$index - 2]->getContent() !== $this->parent) { return false; } } $this->startIndex = $index; return true; } return false; } public function getNewClassName(): string { return static::getNewClassFromClassname($this->className); } public static function getNewClassFromClassname(string $className): string { $parts = explode('\\', $className); $shortName = array_pop($parts); return implode('\\', $parts) . '\\Client\\' . $shortName; } public function getRpcMethod(string $rpcName): ?RpcMethod { // Get the Request class name $newClientClass = $this->getNewClassname(); if (!method_exists($newClientClass, $rpcName)) { // If the new method doesn't exist, there's nothing we can do return null; } $method = new ReflectionMethod($newClientClass, $rpcName); $parameters = $method->getParameters(); if (!isset($parameters[0]) || !$type = $parameters[0]->getType()) { return null; } if ($type->isBuiltin()) { // If the first parameter is a primitive type, assume this is a helper method return null; } return new RpcMethod($this, $rpcName); } public function getLineStart(Tokens $tokens): int { // determine the indent $indent = ''; $lineStart = $this->startIndex; $i = 1; while ( $this->startIndex - $i >= 0 && false === strpos($tokens[$this->startIndex - $i]->getContent(), "\n") && $tokens[$this->startIndex - $i]->getId() !== T_OPEN_TAG ) { $i++; } return $this->startIndex - $i; } public static function getClientVarsFromNewKeyword(Tokens $tokens, array $clientShortNames): array { $clientVars = []; foreach ($tokens as $index => $token) { // get variables which are set directly if (!$token->isGivenKind(T_NEW)) { continue; } $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; $shortName = $nextToken->getContent(); if (!in_array($shortName, $clientShortNames)) { continue; } if (!$prevIndex = $tokens->getPrevMeaningfulToken($index)) { continue; } if ($tokens[$prevIndex]->getContent() !== '=') { continue; } if (!$prevIndex = $tokens->getPrevMeaningfulToken($prevIndex)) { continue; } if ( $tokens[$prevIndex]->isGivenKind(T_VARIABLE) || ( $tokens[$prevIndex]->isGivenKind(T_STRING) && $tokens[$prevIndex - 1]->isGivenKind(T_OBJECT_OPERATOR) ) ) { // Handle clients set to $var $clientClass = array_search($shortName, $clientShortNames); $varName = $tokens[$prevIndex]->getContent(); $clientVars[$varName] = new ClientVar($varName, $clientClass); } } return $clientVars; } public static function getClientVarsFromVarTypehint(Tokens $tokens, array $clientShortNames): array { $clientVars = []; foreach ($tokens as $index => $token) { // get variables which are set directly if (!$token->isGivenKind(T_DOC_COMMENT)) { continue; } if (false === strpos($token->getContent(), '@var')) { continue; } $varToken = $tokens[$tokens->getNextMeaningfulToken($index)]; if (!$varToken->isGivenKind(T_VARIABLE)) { continue; } $regex = sprintf('/@var (.*) \\%s/', $varToken->getContent()); if (!preg_match($regex, $token->getContent(), $matches)) { continue; } $shortName = $matches[1]; $varName = $varToken->getContent(); if ($clientClass = array_search($shortName, $clientShortNames)) { $clientVars[$varName] = new ClientVar($varName, $clientClass); } } return $clientVars; } public static function getClientVarsFromTypehint(Tokens $tokens, array $clientShortNames): array { $clientVars = []; foreach ($tokens as $index => $token) { // get variables which are set directly if (!in_array($token->getContent(), $clientShortNames)) { continue; } $varToken = $tokens[$tokens->getNextMeaningfulToken($index)]; if (!$varToken->isGivenKind(T_VARIABLE)) { continue; } $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; $varName = $varToken->getContent(); $parent = null; if (in_array($prevToken->getContent(), ['protected', 'private', 'public'])) { $parent = '$this'; $varName = substr($varName, 1); } elseif ($prevToken->getContent() === 'static') { $parent = 'self'; } if ($clientClass = array_search($token->getContent(), $clientShortNames)) { $clientVars[] = new ClientVar($varName, $clientClass, $parent); } } return $clientVars; } public static function getClientVarsFromConfiguration(array $configuration): array { $clientVars = []; if (isset($configuration['clientVars'])) { foreach ($configuration['clientVars'] as $varName => $clientClass) { $clientVars[$varName] = new ClientVar($varName, $clientClass); } } return $clientVars; } }