/** * @param \Funivan\PhpTokenizer\Collection $collection * @param int $currentIndex * @return int|null */ public function process(\Funivan\PhpTokenizer\Collection $collection, $currentIndex) { $this->requireQueries(); $result = new StrategyResult(); $token = $collection->offsetGet($currentIndex); if (empty($token) or $this->startQuery->isValid($token) === false) { return $result; } $blockEndFlag = null; $startIndex = null; foreach ($collection as $tokenIndex => $token) { if ($tokenIndex < $currentIndex) { continue; } if ($this->startQuery->isValid($token)) { $blockEndFlag++; if ($blockEndFlag == 1) { $startIndex = $tokenIndex; } } elseif ($startIndex !== null and $this->endQuery->isValid($token)) { $blockEndFlag--; } if ($blockEndFlag === 0) { $endIndex = $tokenIndex; break; } } if (isset($startIndex) and isset($endIndex)) { $result = new StrategyResult(); $result->setValid(true); $result->setNexTokenIndex(++$endIndex); $result->setToken($token); } return $result; }
/** * @param Collection $collection * @return Token */ protected function getLastInvalidToken(Collection $collection) { $lastToken = $collection->getLast(); if ($lastToken and preg_match('![ ]+\\n*$!', $lastToken->getValue())) { return $lastToken; } return null; }
/** * @inheritdoc */ public function process(\Funivan\PhpTokenizer\Collection $collection, $currentIndex) { $result = new StrategyResult(); $result->setValid(true); $token = $collection->offsetGet($currentIndex); if ($token and $this->isValid($token)) { $result->setToken($token); ++$currentIndex; } $result->setNexTokenIndex($currentIndex); return $result; }
/** * @param \Funivan\PhpTokenizer\Collection $collection * @return \Funivan\PhpTokenizer\Collection */ protected function findTags(Collection $collection) { $query = new Query(); $query->typeIs(T_OPEN_TAG); if ($this->useShortTags()) { $query->valueLike('!^<\\?php\\s+!'); // long php tag contains also spaces } else { $query->valueIs('<?'); } return $collection->find($query); }
/** * @param File $file * @param Report $report */ public function process(File $file, Report $report) { $collection = Collection::createFromString($file->getContent()->get()); (new PatternMatcher($collection))->apply(function (QuerySequence $q) { $any = Strict::create()->valueLike('!.+!'); $q->strict('function'); $q->strict(T_WHITESPACE); $q->strict($any); $q->possible(T_WHITESPACE); $q->section('(', ')'); // return type $beforeSpace = $q->possible(T_WHITESPACE); $identifier = $q->strict(':'); $afterSpace = $q->possible(T_WHITESPACE); $q->strict($any); $q->search(Search::create()->valueLike('!^\\{|\\;$!')); if ($q->isValid()) { $beforeSpace->remove(); $identifier->prependToValue($this->before); // add symbol before $identifier->appendToValue($this->after); // add symbol after $afterSpace->remove(); } }); $file->getContent()->set((string) $collection); }
/** * @inheritdoc */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $stripTokens = $this->findTokens($collection); $invalidTokensNum = $stripTokens->count(); $lastInvalidToken = $this->getLastInvalidToken($collection); if (null !== $lastInvalidToken) { $invalidTokensNum++; } if ($invalidTokensNum === 0) { return; } $report->addMessage($file, $this, 'Find empty lines with spaces: ' . $invalidTokensNum); foreach ($stripTokens as $token) { $value = $token->getValue(); $token->setValue($this->replaceEmptyLines($value)); } if (null !== $lastInvalidToken) { $value = $lastInvalidToken->getValue(); $value = $this->replaceEmptyLines($value); $value = preg_replace('![ ]+(\\n*)$!', '$1', $value); $value = preg_replace('!^[ ]+!', '', $value); $lastInvalidToken->setValue($value); } $file->getContent()->set($collection->assemble()); }
/** * @inheritdoc */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $tokens = $collection->find($this->getFindQuery()); foreach ($tokens as $token) { $report->addMessage($file, $this, 'Expect only LF line ending', $token->getLine()); } }
/** * @inheritdoc */ public function process(File $file, Report $report) { $tokens = Collection::createFromString($file->getContent()->get()); $closedTags = (new TokenFinder($tokens))->find((new Query())->typeIs(T_CLOSE_TAG)); foreach ($closedTags as $token) { $report->addMessage($file, $this, 'File contains closing tag', $token->getLine()); } }
/** * @param callable $pattern * @param Collection $collection * @return Collection[] * @throws Exception */ protected function iterateOverCollections(callable $pattern, Collection $collection) { $result = []; $collection->rewind(); foreach ($collection as $index => $token) { $querySequence = new QuerySequence($collection, $index); $patternResult = $pattern($querySequence); if ($patternResult === null) { continue; } if (!$patternResult instanceof Collection) { throw new Exception('Invalid result from pattern callback. Expect Collection. Given:' . gettype($patternResult)); } $result[] = $patternResult; } return $result; }
/** * @param File $file * @param Report $report * @void */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $tokens = $this->getInvalidTokens($collection); foreach ($tokens as $token) { $report->addMessage($file, $this, 'Expect one empty line before class end', $token->getLine()); } }
/** * If $constant is the start of the constant defining $key, updat its value to $value * * @param Collection $tokens * @param Token $constant * @param string $key * @param mixed $value */ private function handleConstant(Collection $tokens, Token $constant, $key, $value) { $lineEnd = false; $found = false; $index = $constant->getIndex(); $tokens->rewind(); while ($lineEnd === false && ($constantToken = $tokens->getNext($index))) { if ($constantToken->getValue() === ';') { $lineEnd = true; } if ($constantToken->getType() === T_STRING && $constantToken->getValue() === $key) { $found = true; } elseif ($found === true) { $this->attemptUpdate($constantToken, $value); } $index++; } }
/** * @param File $file * @param Report $report */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $items = $this->getInvalidStartTokens($collection); if (count($items) === 0) { return; } foreach ($items as $lineTokenData) { $report->addMessage($file, $this, 'Expect at one empty line after php open tag', $lineTokenData->getToken()->getLine()); } }
/** * @param File $file * @param Report $report */ public function process(File $file, Report $report) { $collection = Collection::createFromString($file->getContent()->get()); $invalidProperties = InvalidPropertyFinder::find($collection); if (count($invalidProperties) === 0) { return; } foreach ($invalidProperties as $property) { $variable = $property->getVariable(); $report->addMessage($file, $this, 'Invalid property. Redundant NULL value for the property: ' . $variable->getValue(), $variable->getLine()); } }
/** * @param File $file * @param Report $report * @void */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $tokens = $this->getInvalidTokens($collection); $emptyLines = "\n" . str_repeat("\n", $this->getLinesNum()); foreach ($tokens as $token) { $report->addMessage($file, $this, 'Set one line before closing tag', $token->getLine()); $newValue = $this->getTokenNewValue($token, $emptyLines); $token->setValue($newValue); } $file->getContent()->set($collection->assemble()); }
/** * @param Collection $collection * @return LineTokenData[] */ protected function getInvalidStartTokens(Collection $collection) { $data = []; foreach ($collection as $tag) { if (T_OPEN_TAG !== $tag->getType()) { continue; } $value = $tag->getValue(); $next = $collection->getNext(); $whitespaceToken = null; if ($next->getType() === T_WHITESPACE) { $value = $value . $next->getValue(); $whitespaceToken = $next; } $num = count(explode("\n", $value)); if ($num !== 3) { $data[] = new LineTokenData($num, $tag, $whitespaceToken); } } return $data; }
/** * @param File $file * @param Report $report * @void */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $tokens = $collection->find($this->getFindQuery()); foreach ($tokens as $token) { $value = $token->getValue(); $value = preg_replace(self::REGEX, "\n", $value); $token->setValue($value); $report->addMessage($file, $this, 'Replace invalid line ending', $token->getLine()); } $file->getContent()->set($collection->assemble()); }
/** * @inheritdoc */ public function process(\Funivan\PhpTokenizer\Collection $collection, $currentIndex) { $result = new StrategyResult(); # getProcessor while we can check toke $index = $currentIndex; $searchForward = $this->direction === static::FORWARD; do { $token = $collection->offsetGet($index); if ($token === null) { return $result; } $index = $searchForward ? ++$index : --$index; if ($this->isValid($token)) { $result->setNexTokenIndex($index); $result->setValid(true); $result->setToken($token); break; } } while (!empty($token)); return $result; }
/** * @inheritdoc */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $tags = $this->findTags($collection); if ($tags->count() === 0) { return; } $type = $this->useFullTags() ? 'long' : 'short'; $message = 'You should use only ' . $type . ' php tags'; foreach ($tags as $tag) { $report->addMessage($file, $this, $message, $tag->getLine()); } }
/** * @param File $file * @param Report $report */ public function process(File $file, Report $report) { $collection = Collection::createFromString($file->getContent()->get()); $invalidProperties = InvalidPropertyFinder::find($collection); if (count($invalidProperties) === 0) { return; } foreach ($invalidProperties as $property) { $report->addMessage($file, $this, 'Replace redundant NULL value', $property->getVariable()->getLine()); foreach ($property->getTokensToReplace() as $token) { $token->remove(); } } $file->getContent()->set($collection->assemble()); }
/** * @param string $start * @param string $end * @return Collection */ public function section($start, $end) { $token = $this->search($start); if (!$token->isValid()) { # cant find start position return new Collection(); } $this->moveToToken($token); $section = new \Funivan\PhpTokenizer\Strategy\Section(); $section->setDelimiters($start, $end); $lastToken = $this->process($section); if (!$lastToken->isValid()) { return new Collection(); } return $this->collection->extractByTokens($token, $lastToken); }
/** * @inheritdoc */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $tags = $this->findTags($collection); if ($tags->count() === 0) { return; } $type = $this->useFullTags() ? 'long' : 'short'; $message = 'Detect ' . $type . ' php tag'; $newTag = $this->useShortTags() ? '<?' : '<?php'; foreach ($tags as $tag) { $report->addMessage($file, $this, $message, $tag->getLine()); $spaces = preg_replace('!^(\\S+)(\\s)!', '$2', $tag->getValue()); if ($spaces === $tag->getValue()) { $spaces = ''; } $tag->setValue($newTag . $spaces); } $file->getContent()->set($collection->assemble()); }
/** * @inheritdoc */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $tokens = $this->findTokens($collection); $lastInvalidToken = $this->getLastInvalidToken($collection); if (null !== $lastInvalidToken) { $tokens->append($lastInvalidToken); } if ($tokens->count() === 0) { return; } $lines = []; foreach ($tokens as $token) { $line = $token->getLine(); $line++; # Our token start in previous line if (isset($lines[$line])) { continue; } $lines[$line] = true; $report->addMessage($file, $this, 'File contains empty lines with spaces.', $line); } }
/** * @param File $file * @param Report $report * @void */ public function process(File $file, Report $report) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); $items = $this->getInvalidStartTokens($collection); if (count($items) === 0) { return; } foreach ($items as $tokenInfo) { /** @var Token $token */ $whitespace = $tokenInfo->getWhitespace(); $token = $tokenInfo->getToken(); $tokenValue = $token->getValue(); $whitespaceValue = $whitespace->getValue() ? $whitespace->getValue() : ''; $whitespace->remove(); preg_match('!([ ]+)$!', $whitespaceValue, $endSpaces); $whitespaceValue = !empty($endSpaces[1]) ? $endSpaces[1] : ''; $lines = explode("\n", $tokenValue); $tokenValue = reset($lines); $append = $tokenValue . "\n\n" . $whitespaceValue; $token->setValue($append); $report->addMessage($file, $this, 'Set one empty line after php open tag', $token->getLine()); } $file->getContent()->set($collection->assemble()); }
/** * @param Collection $collection * @return Collection */ protected function getInvalidTokens(Collection $collection) { $resultCollection = new Collection(); $classBody = (new PatternMatcher($collection))->apply(new ClassPattern())->getCollections(); if (empty($classBody)) { return $resultCollection; } foreach ($classBody as $body) { if ($body->count() === 0) { continue; } $resultCollection->append($body->getLast()); } foreach ($resultCollection as $index => $token) { if ($this->isValidBodyEndToken($token)) { $resultCollection->offsetUnset($index); } } $resultCollection->rewind(); return $resultCollection; }
/** * @return bool */ public function isChanged() { return $this->collection->isChanged(); }
/** * @param File $file * @return \Funivan\PhpTokenizer\Collection */ protected function getInvalidStartTokens(File $file) { $collection = \Funivan\PhpTokenizer\Collection::createFromString($file->getContent()->get()); return $collection->find($this->getFindQuery()); }
/** * @param Token $tokenStart * @param Token $tokenEnd * @return Collection */ public function extractByTokens(Token $tokenStart, Token $tokenEnd) { $collection = new Collection(); $startIndex = $tokenStart->getIndex(); $endIndex = $tokenEnd->getIndex(); foreach ($this->getItems() as $token) { if ($token->getIndex() >= $startIndex and $token->getIndex() <= $endIndex) { $collection->append($token); } } return $collection; }
/** * @param $code */ public function __construct($code) { $this->collection = Collection::createFromString($code); }