1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
<?php
/**
* Tests the backfill for the PHP >= 8.0 nullsafe object operator.
*
* @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl>
* @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600)
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
*/
namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP;
use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase;
use PHP_CodeSniffer\Util\Tokens;
final class NullsafeObjectOperatorTest extends AbstractTokenizerTestCase
{
/**
* Tokens to search for.
*
* @var array<int|string>
*/
protected $find = [
T_NULLSAFE_OBJECT_OPERATOR,
T_OBJECT_OPERATOR,
T_INLINE_THEN,
];
/**
* Test that a normal object operator is still tokenized as such.
*
* @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
*
* @return void
*/
public function testObjectOperator()
{
$tokens = $this->phpcsFile->getTokens();
$operator = $this->getTargetToken('/* testObjectOperator */', $this->find);
$this->assertSame(T_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is object operator');
$this->assertSame('T_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is object operator');
}//end testObjectOperator()
/**
* Test that a nullsafe object operator is tokenized as such.
*
* @param string $testMarker The comment which prefaces the target token in the test file.
*
* @dataProvider dataNullsafeObjectOperator
* @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
*
* @return void
*/
public function testNullsafeObjectOperator($testMarker)
{
$tokens = $this->phpcsFile->getTokens();
$operator = $this->getTargetToken($testMarker, $this->find);
$this->assertSame(T_NULLSAFE_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is nullsafe object operator');
$this->assertSame('T_NULLSAFE_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is nullsafe object operator');
}//end testNullsafeObjectOperator()
/**
* Data provider.
*
* @see testNullsafeObjectOperator()
*
* @return array<string, array<string>>
*/
public static function dataNullsafeObjectOperator()
{
return [
'nullsafe operator' => ['/* testNullsafeObjectOperator */'],
'illegal nullsafe operator (write context)' => ['/* testNullsafeObjectOperatorWriteContext */'],
];
}//end dataNullsafeObjectOperator()
/**
* Test that a question mark not followed by an object operator is tokenized as T_TERNARY_THEN.
*
* @param string $testMarker The comment which prefaces the target token in the test file.
* @param bool $testObjectOperator Whether to test for the next non-empty token being tokenized
* as an object operator.
*
* @dataProvider dataTernaryThen
* @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
*
* @return void
*/
public function testTernaryThen($testMarker, $testObjectOperator=false)
{
$tokens = $this->phpcsFile->getTokens();
$operator = $this->getTargetToken($testMarker, $this->find);
$this->assertSame(T_INLINE_THEN, $tokens[$operator]['code'], 'Failed asserting code is inline then');
$this->assertSame('T_INLINE_THEN', $tokens[$operator]['type'], 'Failed asserting type is inline then');
if ($testObjectOperator === true) {
$next = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($operator + 1), null, true);
$this->assertSame(T_OBJECT_OPERATOR, $tokens[$next]['code'], 'Failed asserting code is object operator');
$this->assertSame('T_OBJECT_OPERATOR', $tokens[$next]['type'], 'Failed asserting type is object operator');
}
}//end testTernaryThen()
/**
* Data provider.
*
* @see testTernaryThen()
*
* @return array<string, array<string, string|bool>>
*/
public static function dataTernaryThen()
{
return [
'ternary then' => [
'testMarker' => '/* testTernaryThen */',
],
'whitespace between question mark and object operator' => [
'testMarker' => '/* testParseErrorWhitespaceNotAllowed */',
'testObjectOperator' => true,
],
'comment between question mark and object operator' => [
'testMarker' => '/* testParseErrorCommentNotAllowed */',
'testObjectOperator' => true,
],
'parse error/live coding' => [
'testMarker' => '/* testLiveCoding */',
],
];
}//end dataTernaryThen()
}//end class
|