-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from calevans/type_hints
Type Hint Sniffs and helpers
- Loading branch information
Showing
32 changed files
with
4,282 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
/** | ||
* @copyright Copyright (c) 2015 Slevomat.cz, s.r.o. | ||
* @license https://github.com/slevomat/coding-standard/blob/master/LICENSE.md MIT Licence | ||
*/ | ||
|
||
namespace NocWorx\Helpers; | ||
|
||
class Annotation | ||
{ | ||
|
||
/** @var string */ | ||
private $name; | ||
|
||
/** @var int */ | ||
private $startPointer; | ||
|
||
/** @var int */ | ||
private $endPointer; | ||
|
||
/** @var string|null */ | ||
private $parameters; | ||
|
||
/** @var string|null */ | ||
private $content; | ||
|
||
public function __construct( | ||
string $name, | ||
int $startPointer, | ||
int $endPointer, | ||
?string $parameters, | ||
?string $content | ||
) | ||
{ | ||
$this->name = $name; | ||
$this->startPointer = $startPointer; | ||
$this->endPointer = $endPointer; | ||
$this->parameters = $parameters; | ||
$this->content = $content; | ||
} | ||
|
||
public function getName(): string | ||
{ | ||
return $this->name; | ||
} | ||
|
||
public function getStartPointer(): int | ||
{ | ||
return $this->startPointer; | ||
} | ||
|
||
public function getEndPointer(): int | ||
{ | ||
return $this->endPointer; | ||
} | ||
|
||
public function getParameters(): ?string | ||
{ | ||
return $this->parameters; | ||
} | ||
|
||
public function getContent(): ?string | ||
{ | ||
return $this->content; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
/** | ||
* @copyright Copyright (c) 2015 Slevomat.cz, s.r.o. | ||
* @license https://github.com/slevomat/coding-standard/blob/master/LICENSE.md MIT Licence | ||
*/ | ||
|
||
namespace NocWorx\Helpers; | ||
|
||
class AnnotationHelper | ||
{ | ||
|
||
/** | ||
* @param \PHP_CodeSniffer\Files\File $codeSnifferFile | ||
* @param int $pointer | ||
* @param string $annotationName | ||
* @return \NocWorx\Helpers\Annotation[] | ||
*/ | ||
public static function getAnnotationsByName(\PHP_CodeSniffer\Files\File $codeSnifferFile, int $pointer, string $annotationName): array | ||
{ | ||
$annotations = self::getAnnotations($codeSnifferFile, $pointer); | ||
if (!array_key_exists($annotationName, $annotations)) { | ||
return []; | ||
} | ||
|
||
return $annotations[$annotationName]; | ||
} | ||
|
||
/** | ||
* @param \PHP_CodeSniffer\Files\File $codeSnifferFile | ||
* @param int $pointer | ||
* @return \NocWorx\Helpers\Annotation[][] | ||
*/ | ||
public static function getAnnotations(\PHP_CodeSniffer\Files\File $codeSnifferFile, int $pointer): array | ||
{ | ||
$annotations = []; | ||
|
||
$docCommentOpenToken = DocCommentHelper::findDocCommentOpenToken($codeSnifferFile, $pointer); | ||
if ($docCommentOpenToken === null) { | ||
return $annotations; | ||
} | ||
$tokens = $codeSnifferFile->getTokens(); | ||
$i = $docCommentOpenToken + 1; | ||
while ($i < $tokens[$docCommentOpenToken]['comment_closer']) { | ||
if ($tokens[$i]['code'] !== T_DOC_COMMENT_TAG) { | ||
$i++; | ||
continue; | ||
} | ||
|
||
$annotationStartPointer = $i; | ||
$annotationEndPointer = $i; | ||
|
||
// Fix for wrong PHPCS parsing | ||
$parenthesesLevel = substr_count($tokens[$i]['content'], '(') - substr_count($tokens[$i]['content'], ')'); | ||
$annotationCode = $tokens[$i]['content']; | ||
|
||
for ($j = $i + 1; $j <= $tokens[$docCommentOpenToken]['comment_closer']; $j++) { | ||
if ($tokens[$j]['code'] === T_DOC_COMMENT_CLOSE_TAG) { | ||
$i = $j; | ||
break; | ||
} | ||
|
||
if ($tokens[$j]['code'] === T_DOC_COMMENT_TAG && $parenthesesLevel === 0) { | ||
$i = $j; | ||
break; | ||
} | ||
|
||
if ($tokens[$j]['code'] === T_DOC_COMMENT_STAR) { | ||
continue; | ||
} | ||
|
||
if (in_array($tokens[$j]['code'], [T_DOC_COMMENT_TAG, T_DOC_COMMENT_STRING], true)) { | ||
$annotationEndPointer = $j; | ||
} elseif ($tokens[$j]['code'] === T_DOC_COMMENT_WHITESPACE) { | ||
if (array_key_exists($j - 1, $tokens) && $tokens[$j - 1]['code'] === T_DOC_COMMENT_STAR) { | ||
continue; | ||
} | ||
if (array_key_exists($j + 1, $tokens) && $tokens[$j + 1]['code'] === T_DOC_COMMENT_STAR) { | ||
continue; | ||
} | ||
} | ||
|
||
$parenthesesLevel += substr_count($tokens[$j]['content'], '(') - substr_count($tokens[$j]['content'], ')'); | ||
$annotationCode .= $tokens[$j]['content']; | ||
} | ||
|
||
$annotationName = $tokens[$annotationStartPointer]['content']; | ||
$annotationParameters = null; | ||
$annotationContent = null; | ||
if (preg_match('~^(@[-a-zA-Z\\\\]+)(?:\((.*)\))?(?:\\s+(.+))?($)~s', trim($annotationCode), $matches)) { | ||
$annotationName = $matches[1]; | ||
$annotationParameters = trim($matches[2]); | ||
if ($annotationParameters === '') { | ||
$annotationParameters = null; | ||
} | ||
$annotationContent = trim($matches[3]); | ||
if ($annotationContent === '') { | ||
$annotationContent = null; | ||
} | ||
} | ||
|
||
$annotations[$annotationName][] = new Annotation($annotationName, $annotationStartPointer, $annotationEndPointer, $annotationParameters, $annotationContent); | ||
} | ||
|
||
return $annotations; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
/** | ||
* @copyright Copyright (c) 2015 Slevomat.cz, s.r.o. | ||
* @license https://github.com/slevomat/coding-standard/blob/master/LICENSE.md MIT Licence | ||
*/ | ||
|
||
namespace NocWorx\Helpers; | ||
|
||
class CatchHelper | ||
{ | ||
|
||
/** | ||
* @param \PHP_CodeSniffer\Files\File $phpcsFile | ||
* @param \NocWorx\Helpers\UseStatement[] $useStatements | ||
* @param mixed[] $catchToken | ||
* @return string[] | ||
*/ | ||
public static function findCatchedTypesInCatch(\PHP_CodeSniffer\Files\File $phpcsFile, array $useStatements, array $catchToken): array | ||
{ | ||
$nameEndPointer = $catchToken['parenthesis_opener']; | ||
$tokens = $phpcsFile->getTokens(); | ||
$catchedTypes = []; | ||
do { | ||
$nameStartPointer = TokenHelper::findNext($phpcsFile, array_merge([T_BITWISE_OR], TokenHelper::$nameTokenCodes), $nameEndPointer + 1, $catchToken['parenthesis_closer']); | ||
if ($nameStartPointer === null) { | ||
break; | ||
} | ||
|
||
if ($tokens[$nameStartPointer]['code'] === T_BITWISE_OR) { | ||
/** @var int $nameStartPointer */ | ||
$nameStartPointer = TokenHelper::findNextEffective($phpcsFile, $nameStartPointer + 1, $catchToken['parenthesis_closer']); | ||
} | ||
|
||
$pointerAfterNameEndPointer = TokenHelper::findNextExcluding($phpcsFile, TokenHelper::$nameTokenCodes, $nameStartPointer + 1); | ||
$nameEndPointer = $pointerAfterNameEndPointer === null ? $nameStartPointer : $pointerAfterNameEndPointer - 1; | ||
|
||
$catchedTypes[] = NamespaceHelper::resolveClassName( | ||
$phpcsFile, | ||
TokenHelper::getContent($phpcsFile, $nameStartPointer, $nameEndPointer), | ||
$useStatements, | ||
$catchToken['parenthesis_opener'] | ||
); | ||
} while (true); | ||
|
||
return $catchedTypes; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
/** | ||
* @copyright Copyright (c) 2015 Slevomat.cz, s.r.o. | ||
* @license https://github.com/slevomat/coding-standard/blob/master/LICENSE.md MIT Licence | ||
*/ | ||
|
||
namespace NocWorx\Helpers; | ||
|
||
class ClassHelper | ||
{ | ||
|
||
public static function getFullyQualifiedName(\PHP_CodeSniffer\Files\File $codeSnifferFile, int $classPointer): string | ||
{ | ||
$name = sprintf('%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, self::getName($codeSnifferFile, $classPointer)); | ||
$namespace = NamespaceHelper::findCurrentNamespaceName($codeSnifferFile, $classPointer); | ||
return $namespace !== null ? sprintf('%s%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $namespace, $name) : $name; | ||
} | ||
|
||
public static function getName(\PHP_CodeSniffer\Files\File $codeSnifferFile, int $classPointer): string | ||
{ | ||
$tokens = $codeSnifferFile->getTokens(); | ||
return $tokens[TokenHelper::findNext($codeSnifferFile, T_STRING, $classPointer + 1, $tokens[$classPointer]['scope_opener'])]['content']; | ||
} | ||
|
||
/** | ||
* @param \PHP_CodeSniffer\Files\File $codeSnifferFile | ||
* @return string[] | ||
*/ | ||
public static function getAllNames(\PHP_CodeSniffer\Files\File $codeSnifferFile): array | ||
{ | ||
$previousClassPointer = 0; | ||
|
||
return array_map( | ||
function (int $classPointer) use ($codeSnifferFile): string { | ||
return self::getName($codeSnifferFile, $classPointer); | ||
}, | ||
iterator_to_array(self::getAllClassPointers($codeSnifferFile, $previousClassPointer)) | ||
); | ||
} | ||
|
||
private static function getAllClassPointers(\PHP_CodeSniffer\Files\File $codeSnifferFile, int &$previousClassPointer): \Generator | ||
{ | ||
do { | ||
$nextClassPointer = TokenHelper::findNext($codeSnifferFile, TokenHelper::$typeKeywordTokenCodes, $previousClassPointer + 1); | ||
if ($nextClassPointer === null) { | ||
break; | ||
} | ||
|
||
$previousClassPointer = $nextClassPointer; | ||
yield $nextClassPointer; | ||
} while (true); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
/** | ||
* @copyright Copyright (c) 2015 Slevomat.cz, s.r.o. | ||
* @license https://github.com/slevomat/coding-standard/blob/master/LICENSE.md MIT Licence | ||
*/ | ||
|
||
namespace NocWorx\Helpers; | ||
|
||
class Comment | ||
{ | ||
|
||
/** @var int */ | ||
private $pointer; | ||
|
||
/** @var string */ | ||
private $content; | ||
|
||
public function __construct(int $pointer, string $content) | ||
{ | ||
$this->pointer = $pointer; | ||
$this->content = $content; | ||
} | ||
|
||
public function getPointer(): int | ||
{ | ||
return $this->pointer; | ||
} | ||
|
||
public function getContent(): string | ||
{ | ||
return $this->content; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
/** | ||
* @copyright Copyright (c) 2015 Slevomat.cz, s.r.o. | ||
* @license https://github.com/slevomat/coding-standard/blob/master/LICENSE.md MIT Licence | ||
*/ | ||
|
||
namespace NocWorx\Helpers; | ||
|
||
class ConstantHelper | ||
{ | ||
|
||
public static function getName(\PHP_CodeSniffer\Files\File $codeSnifferFile, int $constantPointer): string | ||
{ | ||
$tokens = $codeSnifferFile->getTokens(); | ||
return $tokens[TokenHelper::findNext($codeSnifferFile, T_STRING, $constantPointer + 1)]['content']; | ||
} | ||
|
||
public static function getFullyQualifiedName(\PHP_CodeSniffer\Files\File $codeSnifferFile, int $constantPointer): string | ||
{ | ||
$name = self::getName($codeSnifferFile, $constantPointer); | ||
$namespace = NamespaceHelper::findCurrentNamespaceName($codeSnifferFile, $constantPointer); | ||
|
||
return $namespace !== null ? sprintf('%s%s%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $namespace, NamespaceHelper::NAMESPACE_SEPARATOR, $name) : $name; | ||
} | ||
|
||
/** | ||
* @param \PHP_CodeSniffer\Files\File $codeSnifferFile | ||
* @return string[] | ||
*/ | ||
public static function getAllNames(\PHP_CodeSniffer\Files\File $codeSnifferFile): array | ||
{ | ||
$previousConstantPointer = 0; | ||
|
||
return array_map( | ||
function (int $constantPointer) use ($codeSnifferFile): string { | ||
return self::getName($codeSnifferFile, $constantPointer); | ||
}, | ||
array_filter( | ||
iterator_to_array(self::getAllConstantPointers($codeSnifferFile, $previousConstantPointer)), | ||
function (int $constantPointer) use ($codeSnifferFile): bool { | ||
foreach (array_reverse($codeSnifferFile->getTokens()[$constantPointer]['conditions']) as $conditionTokenCode) { | ||
if ($conditionTokenCode === T_NAMESPACE) { | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
) | ||
); | ||
} | ||
|
||
private static function getAllConstantPointers(\PHP_CodeSniffer\Files\File $codeSnifferFile, int &$previousConstantPointer): \Generator | ||
{ | ||
do { | ||
$nextConstantPointer = TokenHelper::findNext($codeSnifferFile, T_CONST, $previousConstantPointer + 1); | ||
if ($nextConstantPointer === null) { | ||
break; | ||
} | ||
|
||
$previousConstantPointer = $nextConstantPointer; | ||
yield $nextConstantPointer; | ||
} while (true); | ||
} | ||
|
||
} |
Oops, something went wrong.