TokenTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <?php
  2. /*
  3. * This file is part of PHP CS Fixer.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. namespace PhpCsFixer\Tests\Tokenizer;
  12. use PhpCsFixer\Tokenizer\CT;
  13. use PhpCsFixer\Tokenizer\Token;
  14. use PHPUnit\Framework\TestCase;
  15. /**
  16. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  17. *
  18. * @internal
  19. *
  20. * @covers \PhpCsFixer\Tokenizer\Token
  21. */
  22. final class TokenTest extends TestCase
  23. {
  24. public function getBraceToken()
  25. {
  26. return new Token($this->getBraceTokenPrototype());
  27. }
  28. public function getBraceTokenPrototype()
  29. {
  30. return '(';
  31. }
  32. public function getForeachToken()
  33. {
  34. return new Token($this->getForeachTokenPrototype());
  35. }
  36. public function getForeachTokenPrototype()
  37. {
  38. static $prototype = [T_FOREACH, 'foreach'];
  39. return $prototype;
  40. }
  41. /**
  42. * @param mixed $input
  43. *
  44. * @dataProvider provideConstructorValidationCases
  45. */
  46. public function testConstructorValidation($input)
  47. {
  48. $this->expectException(\InvalidArgumentException::class);
  49. new Token($input);
  50. }
  51. public function provideConstructorValidationCases()
  52. {
  53. return [
  54. [null],
  55. [123],
  56. [new \stdClass()],
  57. [['asd', 'asd']],
  58. [[null, 'asd']],
  59. [[new \stdClass(), 'asd']],
  60. [[T_WHITESPACE, null]],
  61. [[T_WHITESPACE, 123]],
  62. [[T_WHITESPACE, '']],
  63. [[T_WHITESPACE, new \stdClass()]],
  64. ];
  65. }
  66. public function testGetPrototype()
  67. {
  68. $this->assertSame($this->getBraceTokenPrototype(), $this->getBraceToken()->getPrototype());
  69. $this->assertSame($this->getForeachTokenPrototype(), $this->getForeachToken()->getPrototype());
  70. }
  71. public function testIsArray()
  72. {
  73. $this->assertFalse($this->getBraceToken()->isArray());
  74. $this->assertTrue($this->getForeachToken()->isArray());
  75. }
  76. /**
  77. * @param Token $token
  78. * @param bool $isCast
  79. *
  80. * @dataProvider provideIsCastCases
  81. */
  82. public function testIsCast(Token $token, $isCast)
  83. {
  84. $this->assertSame($isCast, $token->isCast());
  85. }
  86. public function provideIsCastCases()
  87. {
  88. return [
  89. [$this->getBraceToken(), false],
  90. [$this->getForeachToken(), false],
  91. [new Token([T_ARRAY_CAST, '(array)', 1]), true],
  92. [new Token([T_BOOL_CAST, '(bool)', 1]), true],
  93. [new Token([T_DOUBLE_CAST, '(double)', 1]), true],
  94. [new Token([T_INT_CAST, '(int)', 1]), true],
  95. [new Token([T_OBJECT_CAST, '(object)', 1]), true],
  96. [new Token([T_STRING_CAST, '(string)', 1]), true],
  97. [new Token([T_UNSET_CAST, '(unset)', 1]), true],
  98. ];
  99. }
  100. /**
  101. * @param Token $token
  102. * @param bool $isClassy
  103. *
  104. * @dataProvider provideIsClassyCases
  105. */
  106. public function testIsClassy(Token $token, $isClassy)
  107. {
  108. $this->assertSame($isClassy, $token->isClassy());
  109. }
  110. public function provideIsClassyCases()
  111. {
  112. $cases = [
  113. [$this->getBraceToken(), false],
  114. [$this->getForeachToken(), false],
  115. [new Token([T_CLASS, 'class', 1]), true],
  116. [new Token([T_INTERFACE, 'interface', 1]), true],
  117. [new Token([T_TRAIT, 'trait', 1]), true],
  118. ];
  119. return $cases;
  120. }
  121. /**
  122. * @param Token $token
  123. * @param bool $isComment
  124. *
  125. * @dataProvider provideIsCommentCases
  126. */
  127. public function testIsComment(Token $token, $isComment)
  128. {
  129. $this->assertSame($isComment, $token->isComment());
  130. }
  131. public function provideIsCommentCases()
  132. {
  133. return [
  134. [$this->getBraceToken(), false],
  135. [$this->getForeachToken(), false],
  136. [new Token([T_COMMENT, '/* comment */', 1]), true],
  137. [new Token([T_DOC_COMMENT, '/** docs */', 1]), true],
  138. ];
  139. }
  140. public function testIsGivenKind()
  141. {
  142. $braceToken = $this->getBraceToken();
  143. $foreachToken = $this->getForeachToken();
  144. $this->assertFalse($braceToken->isGivenKind(T_FOR));
  145. $this->assertFalse($braceToken->isGivenKind(T_FOREACH));
  146. $this->assertFalse($braceToken->isGivenKind([T_FOR]));
  147. $this->assertFalse($braceToken->isGivenKind([T_FOREACH]));
  148. $this->assertFalse($braceToken->isGivenKind([T_FOR, T_FOREACH]));
  149. $this->assertFalse($foreachToken->isGivenKind(T_FOR));
  150. $this->assertTrue($foreachToken->isGivenKind(T_FOREACH));
  151. $this->assertFalse($foreachToken->isGivenKind([T_FOR]));
  152. $this->assertTrue($foreachToken->isGivenKind([T_FOREACH]));
  153. $this->assertTrue($foreachToken->isGivenKind([T_FOR, T_FOREACH]));
  154. }
  155. public function testIsKeywords()
  156. {
  157. $this->assertTrue($this->getForeachToken()->isKeyword());
  158. $this->assertFalse($this->getBraceToken()->isKeyword());
  159. }
  160. /**
  161. * @param ?int $tokenId
  162. * @param string $content
  163. * @param bool $isConstant
  164. *
  165. * @dataProvider provideMagicConstantCases
  166. */
  167. public function testIsMagicConstant($tokenId, $content, $isConstant = true)
  168. {
  169. $token = new Token(
  170. null === $tokenId ? $content : [$tokenId, $content]
  171. );
  172. $this->assertSame($isConstant, $token->isMagicConstant());
  173. }
  174. public function provideMagicConstantCases()
  175. {
  176. $cases = [
  177. [T_CLASS_C, '__CLASS__'],
  178. [T_DIR, '__DIR__'],
  179. [T_FILE, '__FILE__'],
  180. [T_FUNC_C, '__FUNCTION__'],
  181. [T_LINE, '__LINE__'],
  182. [T_METHOD_C, '__METHOD__'],
  183. [T_NS_C, '__NAMESPACE__'],
  184. [T_TRAIT_C, '__TRAIT__'],
  185. ];
  186. foreach ($cases as $case) {
  187. $cases[] = [$case[0], strtolower($case[1])];
  188. }
  189. foreach ([$this->getForeachToken(), $this->getBraceToken()] as $token) {
  190. $cases[] = [$token->getId(), $token->getContent(), false];
  191. $cases[] = [$token->getId(), strtolower($token->getContent()), false];
  192. }
  193. return $cases;
  194. }
  195. /**
  196. * @param Token $token
  197. * @param bool $isNativeConstant
  198. *
  199. * @dataProvider provideIsNativeConstantCases
  200. */
  201. public function testIsNativeConstant(Token $token, $isNativeConstant)
  202. {
  203. $this->assertSame($isNativeConstant, $token->isNativeConstant());
  204. }
  205. public function provideIsNativeConstantCases()
  206. {
  207. return [
  208. [$this->getBraceToken(), false],
  209. [$this->getForeachToken(), false],
  210. [new Token([T_STRING, 'null', 1]), true],
  211. [new Token([T_STRING, 'false', 1]), true],
  212. [new Token([T_STRING, 'true', 1]), true],
  213. [new Token([T_STRING, 'tRuE', 1]), true],
  214. [new Token([T_STRING, 'TRUE', 1]), true],
  215. ];
  216. }
  217. /**
  218. * @param Token $token
  219. * @param bool $isWhitespace
  220. * @param null|string $whitespaces
  221. *
  222. * @dataProvider provideIsWhitespaceCases
  223. */
  224. public function testIsWhitespace(Token $token, $isWhitespace, $whitespaces = null)
  225. {
  226. if (null !== $whitespaces) {
  227. $this->assertSame($isWhitespace, $token->isWhitespace($whitespaces));
  228. } else {
  229. $this->assertSame($isWhitespace, $token->isWhitespace());
  230. }
  231. }
  232. public function provideIsWhitespaceCases()
  233. {
  234. return [
  235. [$this->getBraceToken(), false],
  236. [$this->getForeachToken(), false],
  237. [new Token(' '), true],
  238. [new Token("\t "), true],
  239. [new Token("\t "), false, ' '],
  240. [new Token([T_WHITESPACE, "\r", 1]), true],
  241. [new Token([T_WHITESPACE, "\0", 1]), true],
  242. [new Token([T_WHITESPACE, "\x0B", 1]), true],
  243. [new Token([T_WHITESPACE, "\n", 1]), true],
  244. [new Token([T_WHITESPACE, "\n", 1]), false, " \t"],
  245. ];
  246. }
  247. /**
  248. * @param mixed $prototype
  249. * @param null|int $expectedId
  250. * @param null|string $expectedContent
  251. * @param null|bool $expectedIsArray
  252. * @param null|string $expectedExceptionClass
  253. *
  254. * @dataProvider provideCreatingTokenCases
  255. */
  256. public function testCreatingToken($prototype, $expectedId, $expectedContent, $expectedIsArray, $expectedExceptionClass = null)
  257. {
  258. if ($expectedExceptionClass) {
  259. $this->expectException($expectedExceptionClass);
  260. }
  261. $token = new Token($prototype);
  262. $this->assertSame($expectedId, $token->getId());
  263. $this->assertSame($expectedContent, $token->getContent());
  264. $this->assertSame($expectedIsArray, $token->isArray());
  265. }
  266. public function provideCreatingTokenCases()
  267. {
  268. return [
  269. [[T_FOREACH, 'foreach'], T_FOREACH, 'foreach', true],
  270. ['(', null, '(', false],
  271. [123, null, null, null, \InvalidArgumentException::class],
  272. [false, null, null, null, \InvalidArgumentException::class],
  273. [null, null, null, null, \InvalidArgumentException::class],
  274. ];
  275. }
  276. public function testEqualsDefaultIsCaseSensitive()
  277. {
  278. $token = new Token([T_FUNCTION, 'function', 1]);
  279. $this->assertTrue($token->equals([T_FUNCTION, 'function']));
  280. $this->assertFalse($token->equals([T_FUNCTION, 'Function']));
  281. }
  282. /**
  283. * @param Token $token
  284. * @param string $equals
  285. * @param array|string|Token $other
  286. * @param bool $caseSensitive
  287. *
  288. * @dataProvider provideEqualsCases
  289. */
  290. public function testEquals(Token $token, $equals, $other, $caseSensitive = true)
  291. {
  292. $this->assertSame($equals, $token->equals($other, $caseSensitive));
  293. }
  294. public function provideEqualsCases()
  295. {
  296. $brace = $this->getBraceToken();
  297. $function = new Token([T_FUNCTION, 'function', 1]);
  298. return [
  299. [$brace, false, '!'],
  300. [$brace, false, '!', false],
  301. [$brace, true, '('],
  302. [$brace, true, '(', false],
  303. [$function, false, '('],
  304. [$function, false, '(', false],
  305. [$function, false, [T_NAMESPACE]],
  306. [$function, false, [T_NAMESPACE], false],
  307. [$function, false, [T_VARIABLE, 'function']],
  308. [$function, false, [T_VARIABLE, 'function'], false],
  309. [$function, false, [T_VARIABLE, 'Function']],
  310. [$function, false, [T_VARIABLE, 'Function'], false],
  311. [$function, true, [T_FUNCTION]],
  312. [$function, true, [T_FUNCTION], false],
  313. [$function, true, [T_FUNCTION, 'function']],
  314. [$function, true, [T_FUNCTION, 'function'], false],
  315. [$function, false, [T_FUNCTION, 'Function']],
  316. [$function, true, [T_FUNCTION, 'Function'], false],
  317. [$function, false, [T_FUNCTION, 'junction'], false],
  318. [$function, true, new Token([T_FUNCTION, 'function'])],
  319. [$function, false, new Token([T_FUNCTION, 'Function'])],
  320. [$function, true, new Token([T_FUNCTION, 'Function']), false],
  321. // if it is an array any additional field is checked too
  322. [$function, false, [T_FUNCTION, 'function', 'unexpected']],
  323. ];
  324. }
  325. public function testEqualsAnyDefaultIsCaseSensitive()
  326. {
  327. $token = new Token([T_FUNCTION, 'function', 1]);
  328. $this->assertTrue($token->equalsAny([[T_FUNCTION, 'function']]));
  329. $this->assertFalse($token->equalsAny([[T_FUNCTION, 'Function']]));
  330. }
  331. /**
  332. * @param bool $equalsAny
  333. * @param array $other
  334. * @param bool $caseSensitive
  335. *
  336. * @dataProvider provideEqualsAnyCases
  337. */
  338. public function testEqualsAny($equalsAny, array $other, $caseSensitive = true)
  339. {
  340. $token = new Token([T_FUNCTION, 'function', 1]);
  341. $this->assertSame($equalsAny, $token->equalsAny($other, $caseSensitive));
  342. }
  343. public function provideEqualsAnyCases()
  344. {
  345. $brace = $this->getBraceToken();
  346. $foreach = $this->getForeachToken();
  347. return [
  348. [false, []],
  349. [false, [$brace]],
  350. [false, [$brace, $foreach]],
  351. [true, [$brace, $foreach, [T_FUNCTION]]],
  352. [true, [$brace, $foreach, [T_FUNCTION, 'function']]],
  353. [false, [$brace, $foreach, [T_FUNCTION, 'Function']]],
  354. [true, [$brace, $foreach, [T_FUNCTION, 'Function']], false],
  355. [false, [[T_VARIABLE, 'junction'], [T_FUNCTION, 'junction']], false],
  356. ];
  357. }
  358. /**
  359. * @param bool $isKeyCaseSensitive
  360. * @param array|bool $caseSensitive
  361. * @param int $key
  362. *
  363. * @dataProvider provideIsKeyCaseSensitiveCases
  364. */
  365. public function testIsKeyCaseSensitive($isKeyCaseSensitive, $caseSensitive, $key)
  366. {
  367. $this->assertSame($isKeyCaseSensitive, Token::isKeyCaseSensitive($caseSensitive, $key));
  368. }
  369. public function provideIsKeyCaseSensitiveCases()
  370. {
  371. return [
  372. [true, true, 0],
  373. [true, true, 1],
  374. [true, [], 0],
  375. [true, [true], 0],
  376. [true, [false, true], 1],
  377. [true, [false, true, false], 1],
  378. [true, [false], 10],
  379. [false, false, 10],
  380. [false, [false], 0],
  381. [false, [true, false], 1],
  382. [false, [true, false, true], 1],
  383. [false, [1 => false], 1],
  384. ];
  385. }
  386. /**
  387. * @param null|string $expected
  388. * @param int $id
  389. *
  390. * @dataProvider provideTokenGetNameCases
  391. */
  392. public function testTokenGetNameForId($expected, $id)
  393. {
  394. $this->assertSame($expected, Token::getNameForId($id));
  395. }
  396. public function provideTokenGetNameCases()
  397. {
  398. return [
  399. [
  400. null,
  401. -1,
  402. ],
  403. [
  404. 'T_CLASS',
  405. T_CLASS,
  406. ],
  407. [
  408. 'CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE',
  409. CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE,
  410. ],
  411. ];
  412. }
  413. }