Skip to content

Commit

Permalink
Implement property typehint sniff for private static
Browse files Browse the repository at this point in the history
Issue 12
  • Loading branch information
satrun77 committed Oct 2, 2023
1 parent 9eefb63 commit a833928
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
.vscode/
composer.lock
.phpunit.result.cache
/app
85 changes: 85 additions & 0 deletions src/Sniffs/Property/TypehintPrivateStaticSniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

namespace Silverstripe\Sniffs\Property;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use SlevomatCodingStandard\Helpers\PropertyHelper;
use SlevomatCodingStandard\Helpers\TokenHelper;
use SlevomatCodingStandard\Sniffs\TypeHints\PropertyTypeHintSniff;
use function array_merge;
use const T_CONST;
use const T_FUNCTION;
use const T_PRIVATE;
use const T_PROTECTED;
use const T_PUBLIC;
use const T_STATIC;
use const T_VAR;
use const T_VARIABLE;

class TypehintPrivateStaticSniff implements Sniff
{

public const CODE_USELESS_SUPPRESS = 'UselessSuppress';

private const NAME = 'Silverstripe.Property';

/**
* Returns the token types that this sniff is interested in.
*
* @return array(int)
*/
public function register()
{
return [
T_VAR,
T_PUBLIC,
T_PROTECTED,
T_PRIVATE,
T_STATIC,
];
}

/**
* Processes this sniff, when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being checked.
* @param int $stackPtr The position of the current token in the stack passed in $tokens.
*/
public function process(File $phpcsFile, $stackPtr): void
{
$tokens = $phpcsFile->getTokens();

$propertyPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_CONST, T_VARIABLE], $stackPtr + 1);

if ($propertyPointer === null || $tokens[$propertyPointer]['code'] !== T_VARIABLE) {
return;
}

if (!PropertyHelper::isProperty($phpcsFile, $propertyPointer)) {
return;
}

$previousPointer = TokenHelper::findPreviousExcluding(
$phpcsFile,
array_merge(TokenHelper::$ineffectiveTokenCodes, TokenHelper::getTypeHintTokenCodes(), [T_NULLABLE]),
$propertyPointer - 1
);
$propertyStartPointer = TokenHelper::findPrevious($phpcsFile, [T_PRIVATE], $propertyPointer - 1);

// Skip non-static property
if (!($tokens[$previousPointer]['code'] === T_STATIC && $tokens[$propertyStartPointer]['code'] === T_PRIVATE)) {
return;
}

// Process property type sniff from SlevomatCodingStandard
$sniff = new PropertyTypeHintSniff();
$sniff->enableNativeTypeHint = true;
$sniff->enableIntersectionTypeHint = true;
$sniff->enableMixedTypeHint = true;
$sniff->enableStandaloneNullTrueFalseTypeHints = true;
$sniff->enableUnionTypeHint = true;
$sniff->process($phpcsFile, $stackPtr);
}

}
39 changes: 39 additions & 0 deletions tests/Sniffs/Property/TypehintPrivateStaticSniffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Silverstripe\Sniffs\Property;

use SlevomatCodingStandard\Sniffs\TestCase;
use SlevomatCodingStandard\Sniffs\TypeHints\PropertyTypeHintSniff;

class TypehintPrivateStaticSniffTest extends TestCase
{
public function testNoErrors(): void
{
$report = self::checkFile(
__DIR__ . '/data/TypehintPrivateStaticSniff_NoErrors.php',
);

self::assertNoSniffErrorInFile($report);
}

public function testErrors(): void
{
$report = self::checkFile(
__DIR__ . '/data/TypehintPrivateStaticSniff_Errors.php', [
]);

self::assertSame(7, $report->getErrorCount());

self::assertSniffError($report, 8, PropertyTypeHintSniff::CODE_MISSING_NATIVE_TYPE_HINT);
self::assertSniffError($report, 12, PropertyTypeHintSniff::CODE_MISSING_NATIVE_TYPE_HINT);
self::assertSniffError($report, 16, PropertyTypeHintSniff::CODE_MISSING_NATIVE_TYPE_HINT);
self::assertSniffError($report, 21, PropertyTypeHintSniff::CODE_MISSING_NATIVE_TYPE_HINT);
self::assertSniffError($report, 23, PropertyTypeHintSniff::CODE_MISSING_ANY_TYPE_HINT);
self::assertSniffError($report, 24, PropertyTypeHintSniff::CODE_MISSING_ANY_TYPE_HINT);
self::assertSniffError($report, 25, PropertyTypeHintSniff::CODE_MISSING_ANY_TYPE_HINT);
self::assertNoSniffError($report, 29);
self::assertNoSniffError($report, 31);

self::assertAllFixedInFile($report);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

class SomeClass
{
/**
* @var string[]
*/
private static array $db = [];
private static string $table_name = '';
private static bool $cool_config = true;

private static int $cool_config_2 = 1;

private static $table_name_2 = '';
private static $cool_config_3 = true;
private static $cool_config_4 = 1;
/**
* @var string
*/
private $variable = '';

public function get($var): void {}
}
32 changes: 32 additions & 0 deletions tests/Sniffs/Property/data/TypehintPrivateStaticSniff_Errors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

class SomeClass
{
/**
* @var string[]
*/
private static $db = [];
/**
* @var string
*/
private static $table_name = '';
/**
* @var bool
*/
private static $cool_config = true;

/**
* @var int
*/
private static $cool_config_2 = 1;

private static $table_name_2 = '';
private static $cool_config_3 = true;
private static $cool_config_4 = 1;
/**
* @var string
*/
private $variable = '';

public function get($var): void {}
}
17 changes: 17 additions & 0 deletions tests/Sniffs/Property/data/TypehintPrivateStaticSniff_NoErrors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

class NoErrors
{
/**
* @var string[]
*/
private static array $db = [];
private static string $table_name = '';
private static bool $cool_config = true;

private static int $cool_config_2 = 1;

private $variable = '';

public function get($var): void {}
}

0 comments on commit a833928

Please sign in to comment.