LoopContextPassTest.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /*
  3. * This file is part of Psy Shell.
  4. *
  5. * (c) 2012-2017 Justin Hileman
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Psy\Test\CodeCleaner;
  11. use PhpParser\NodeTraverser;
  12. use Psy\CodeCleaner\LoopContextPass;
  13. class LoopContextPassTest extends CodeCleanerTestCase
  14. {
  15. public function setUp()
  16. {
  17. $this->pass = new LoopContextPass();
  18. $this->traverser = new NodeTraverser();
  19. $this->traverser->addVisitor($this->pass);
  20. }
  21. /**
  22. * @dataProvider invalidStatements
  23. * @expectedException \Psy\Exception\FatalErrorException
  24. */
  25. public function testProcessStatementFails($code)
  26. {
  27. $stmts = $this->parse($code);
  28. $this->traverser->traverse($stmts);
  29. }
  30. public function invalidStatements()
  31. {
  32. return array(
  33. array('continue'),
  34. array('break'),
  35. array('if (true) { continue; }'),
  36. array('if (true) { break; }'),
  37. array('if (false) { continue; }'),
  38. array('if (false) { break; }'),
  39. array('function foo() { break; }'),
  40. array('function foo() { continue; }'),
  41. // actually enforce break/continue depth argument
  42. array('do { break 2; } while (true)'),
  43. array('do { continue 2; } while (true)'),
  44. array('for ($a; $b; $c) { break 2; }'),
  45. array('for ($a; $b; $c) { continue 2; }'),
  46. array('foreach ($a as $b) { break 2; }'),
  47. array('foreach ($a as $b) { continue 2; }'),
  48. array('switch (true) { default: break 2; }'),
  49. array('switch (true) { default: continue 2; }'),
  50. array('while (true) { break 2; }'),
  51. array('while (true) { continue 2; }'),
  52. // invalid in 5.4+ because they're floats
  53. // ... in 5.3 because the number is too big
  54. array('while (true) { break 2.0; }'),
  55. array('while (true) { continue 2.0; }'),
  56. // and once with nested loops, just for good measure
  57. array('while (true) { while (true) { break 3; } }'),
  58. array('while (true) { while (true) { continue 3; } }'),
  59. );
  60. }
  61. /**
  62. * @dataProvider invalidPHP54Statements
  63. * @expectedException \Psy\Exception\FatalErrorException
  64. */
  65. public function testPHP54ProcessStatementFails($code)
  66. {
  67. if (version_compare(PHP_VERSION, '5.4.0', '<')) {
  68. $this->markTestSkipped();
  69. }
  70. $stmts = $this->parse($code);
  71. $this->traverser->traverse($stmts);
  72. }
  73. public function invalidPHP54Statements()
  74. {
  75. return array(
  76. // In PHP 5.4+, only positive literal integers are allowed
  77. array('while (true) { break $n; }'),
  78. array('while (true) { continue $n; }'),
  79. array('while (true) { break N; }'),
  80. array('while (true) { continue N; }'),
  81. array('while (true) { break 0; }'),
  82. array('while (true) { continue 0; }'),
  83. array('while (true) { break -1; }'),
  84. array('while (true) { continue -1; }'),
  85. array('while (true) { break 1.0; }'),
  86. array('while (true) { continue 1.0; }'),
  87. );
  88. }
  89. /**
  90. * @dataProvider validStatements
  91. */
  92. public function testProcessStatementPasses($code)
  93. {
  94. $stmts = $this->parse($code);
  95. $this->traverser->traverse($stmts);
  96. }
  97. public function validStatements()
  98. {
  99. return array(
  100. array('do { break; } while (true)'),
  101. array('do { continue; } while (true)'),
  102. array('for ($a; $b; $c) { break; }'),
  103. array('for ($a; $b; $c) { continue; }'),
  104. array('foreach ($a as $b) { break; }'),
  105. array('foreach ($a as $b) { continue; }'),
  106. array('switch (true) { default: break; }'),
  107. array('switch (true) { default: continue; }'),
  108. array('while (true) { break; }'),
  109. array('while (true) { continue; }'),
  110. // `break 1` is redundant, but not invalid
  111. array('while (true) { break 1; }'),
  112. array('while (true) { continue 1; }'),
  113. // and once with nested loops just for good measure
  114. array('while (true) { while (true) { break 2; } }'),
  115. array('while (true) { while (true) { continue 2; } }'),
  116. );
  117. }
  118. }