FixerFactoryTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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\AutoReview;
  12. use PhpCsFixer\Fixer\FixerInterface;
  13. use PhpCsFixer\FixerFactory;
  14. use PhpCsFixer\Tests\TestCase;
  15. /**
  16. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  17. *
  18. * @internal
  19. *
  20. * @coversNothing
  21. * @group auto-review
  22. */
  23. final class FixerFactoryTest extends TestCase
  24. {
  25. public function testFixersPriorityEdgeFixers()
  26. {
  27. $factory = new FixerFactory();
  28. $factory->registerBuiltInFixers();
  29. $fixers = $factory->getFixers();
  30. $this->assertSame('encoding', $fixers[0]->getName());
  31. $this->assertSame('full_opening_tag', $fixers[1]->getName());
  32. $this->assertSame('single_blank_line_at_eof', $fixers[count($fixers) - 1]->getName());
  33. }
  34. /**
  35. * @dataProvider provideFixersPriorityCases
  36. * @dataProvider provideFixersPrioritySpecialPhpdocCases
  37. */
  38. public function testFixersPriority(FixerInterface $first, FixerInterface $second)
  39. {
  40. $this->assertLessThan($first->getPriority(), $second->getPriority(), sprintf('"%s" should have less priority than "%s"', get_class($second), get_class($first)));
  41. }
  42. public function provideFixersPriorityCases()
  43. {
  44. $factory = new FixerFactory();
  45. $factory->registerBuiltInFixers();
  46. $fixers = array();
  47. foreach ($factory->getFixers() as $fixer) {
  48. $fixers[$fixer->getName()] = $fixer;
  49. }
  50. return array(
  51. array($fixers['array_syntax'], $fixers['binary_operator_spaces']),
  52. array($fixers['array_syntax'], $fixers['ternary_operator_spaces']),
  53. array($fixers['blank_line_after_opening_tag'], $fixers['no_blank_lines_before_namespace']),
  54. array($fixers['class_keyword_remove'], $fixers['no_unused_imports']),
  55. array($fixers['combine_consecutive_unsets'], $fixers['no_extra_consecutive_blank_lines']),
  56. array($fixers['combine_consecutive_unsets'], $fixers['no_trailing_whitespace']),
  57. array($fixers['combine_consecutive_unsets'], $fixers['no_whitespace_in_blank_line']),
  58. array($fixers['combine_consecutive_unsets'], $fixers['space_after_semicolon']),
  59. array($fixers['declare_strict_types'], $fixers['blank_line_after_opening_tag']),
  60. array($fixers['declare_strict_types'], $fixers['declare_equal_normalize']),
  61. array($fixers['declare_strict_types'], $fixers['single_blank_line_before_namespace']),
  62. array($fixers['elseif'], $fixers['braces']),
  63. array($fixers['function_to_constant'], $fixers['native_function_casing']),
  64. array($fixers['function_to_constant'], $fixers['no_extra_consecutive_blank_lines']),
  65. array($fixers['function_to_constant'], $fixers['no_singleline_whitespace_before_semicolons']),
  66. array($fixers['function_to_constant'], $fixers['no_trailing_whitespace']),
  67. array($fixers['function_to_constant'], $fixers['no_whitespace_in_blank_line']),
  68. array($fixers['indentation_type'], $fixers['phpdoc_indent']),
  69. array($fixers['line_ending'], $fixers['single_blank_line_at_eof']),
  70. array($fixers['method_separation'], $fixers['braces']),
  71. array($fixers['method_separation'], $fixers['indentation_type']),
  72. array($fixers['no_alias_functions'], $fixers['php_unit_dedicate_assert']),
  73. array($fixers['no_blank_lines_after_phpdoc'], $fixers['single_blank_line_before_namespace']),
  74. array($fixers['no_empty_comment'], $fixers['no_extra_consecutive_blank_lines']),
  75. array($fixers['no_empty_comment'], $fixers['no_trailing_whitespace']),
  76. array($fixers['no_empty_comment'], $fixers['no_whitespace_in_blank_line']),
  77. array($fixers['no_empty_phpdoc'], $fixers['no_extra_consecutive_blank_lines']),
  78. array($fixers['no_empty_phpdoc'], $fixers['no_trailing_whitespace']),
  79. array($fixers['no_empty_phpdoc'], $fixers['no_whitespace_in_blank_line']),
  80. array($fixers['no_empty_statement'], $fixers['braces']),
  81. array($fixers['no_empty_statement'], $fixers['combine_consecutive_unsets']),
  82. array($fixers['no_empty_statement'], $fixers['no_extra_consecutive_blank_lines']),
  83. array($fixers['no_empty_statement'], $fixers['no_multiline_whitespace_before_semicolons']),
  84. array($fixers['no_empty_statement'], $fixers['no_singleline_whitespace_before_semicolons']),
  85. array($fixers['no_empty_statement'], $fixers['no_trailing_whitespace']),
  86. array($fixers['no_empty_statement'], $fixers['no_useless_else']),
  87. array($fixers['no_empty_statement'], $fixers['no_useless_return']),
  88. array($fixers['no_empty_statement'], $fixers['no_whitespace_in_blank_line']),
  89. array($fixers['no_empty_statement'], $fixers['space_after_semicolon']),
  90. array($fixers['no_empty_statement'], $fixers['switch_case_semicolon_to_colon']),
  91. array($fixers['no_leading_import_slash'], $fixers['ordered_imports']),
  92. array($fixers['no_multiline_whitespace_around_double_arrow'], $fixers['binary_operator_spaces']),
  93. array($fixers['no_multiline_whitespace_around_double_arrow'], $fixers['trailing_comma_in_multiline_array']),
  94. array($fixers['no_multiline_whitespace_before_semicolons'], $fixers['space_after_semicolon']),
  95. array($fixers['no_php4_constructor'], $fixers['ordered_class_elements']),
  96. array($fixers['no_short_bool_cast'], $fixers['cast_spaces']),
  97. array($fixers['no_short_echo_tag'], $fixers['no_mixed_echo_print']),
  98. array($fixers['no_spaces_after_function_name'], $fixers['function_to_constant']),
  99. array($fixers['no_spaces_inside_parenthesis'], $fixers['function_to_constant']),
  100. array($fixers['no_unneeded_control_parentheses'], $fixers['no_trailing_whitespace']),
  101. array($fixers['no_unused_imports'], $fixers['blank_line_after_namespace']),
  102. array($fixers['no_unused_imports'], $fixers['no_extra_consecutive_blank_lines']),
  103. array($fixers['no_unused_imports'], $fixers['no_leading_import_slash']),
  104. array($fixers['no_useless_else'], $fixers['braces']),
  105. array($fixers['no_useless_else'], $fixers['combine_consecutive_unsets']),
  106. array($fixers['no_useless_else'], $fixers['no_extra_consecutive_blank_lines']),
  107. array($fixers['no_useless_else'], $fixers['no_trailing_whitespace']),
  108. array($fixers['no_useless_else'], $fixers['no_useless_return']),
  109. array($fixers['no_useless_else'], $fixers['no_whitespace_in_blank_line']),
  110. array($fixers['no_useless_return'], $fixers['blank_line_before_return']),
  111. array($fixers['no_useless_return'], $fixers['no_extra_consecutive_blank_lines']),
  112. array($fixers['no_useless_return'], $fixers['no_whitespace_in_blank_line']),
  113. array($fixers['ordered_class_elements'], $fixers['method_separation']),
  114. array($fixers['ordered_class_elements'], $fixers['no_blank_lines_after_class_opening']),
  115. array($fixers['ordered_class_elements'], $fixers['space_after_semicolon']),
  116. array($fixers['php_unit_fqcn_annotation'], $fixers['no_unused_imports']),
  117. array($fixers['php_unit_strict'], $fixers['php_unit_construct']),
  118. array($fixers['phpdoc_add_missing_param_annotation'], $fixers['phpdoc_align']),
  119. array($fixers['phpdoc_add_missing_param_annotation'], $fixers['phpdoc_order']),
  120. array($fixers['phpdoc_no_access'], $fixers['no_empty_phpdoc']),
  121. array($fixers['phpdoc_no_access'], $fixers['phpdoc_order']),
  122. array($fixers['phpdoc_no_access'], $fixers['phpdoc_separation']),
  123. array($fixers['phpdoc_no_access'], $fixers['phpdoc_trim']),
  124. array($fixers['phpdoc_no_alias_tag'], $fixers['phpdoc_add_missing_param_annotation']),
  125. array($fixers['phpdoc_no_alias_tag'], $fixers['phpdoc_single_line_var_spacing']),
  126. array($fixers['phpdoc_no_empty_return'], $fixers['no_empty_phpdoc']),
  127. array($fixers['phpdoc_no_empty_return'], $fixers['phpdoc_order']),
  128. array($fixers['phpdoc_no_empty_return'], $fixers['phpdoc_separation']),
  129. array($fixers['phpdoc_no_empty_return'], $fixers['phpdoc_trim']),
  130. array($fixers['phpdoc_no_package'], $fixers['no_empty_phpdoc']),
  131. array($fixers['phpdoc_no_package'], $fixers['phpdoc_order']),
  132. array($fixers['phpdoc_no_package'], $fixers['phpdoc_separation']),
  133. array($fixers['phpdoc_no_package'], $fixers['phpdoc_trim']),
  134. array($fixers['phpdoc_no_useless_inheritdoc'], $fixers['no_empty_phpdoc']),
  135. array($fixers['phpdoc_no_useless_inheritdoc'], $fixers['no_trailing_whitespace_in_comment']),
  136. array($fixers['phpdoc_order'], $fixers['phpdoc_separation']),
  137. array($fixers['phpdoc_order'], $fixers['phpdoc_trim']),
  138. array($fixers['phpdoc_separation'], $fixers['phpdoc_trim']),
  139. array($fixers['phpdoc_summary'], $fixers['phpdoc_trim']),
  140. array($fixers['phpdoc_to_comment'], $fixers['no_empty_comment']),
  141. array($fixers['phpdoc_to_comment'], $fixers['phpdoc_no_useless_inheritdoc']),
  142. array($fixers['phpdoc_var_without_name'], $fixers['phpdoc_trim']),
  143. array($fixers['pow_to_exponentiation'], $fixers['binary_operator_spaces']),
  144. array($fixers['pow_to_exponentiation'], $fixers['method_argument_space']),
  145. array($fixers['pow_to_exponentiation'], $fixers['native_function_casing']),
  146. array($fixers['pow_to_exponentiation'], $fixers['no_spaces_after_function_name']),
  147. array($fixers['pow_to_exponentiation'], $fixers['no_spaces_inside_parenthesis']),
  148. array($fixers['protected_to_private'], $fixers['ordered_class_elements']),
  149. array($fixers['simplified_null_return'], $fixers['no_useless_return']),
  150. array($fixers['single_import_per_statement'], $fixers['no_leading_import_slash']),
  151. array($fixers['single_import_per_statement'], $fixers['no_multiline_whitespace_before_semicolons']),
  152. array($fixers['single_import_per_statement'], $fixers['no_singleline_whitespace_before_semicolons']),
  153. array($fixers['single_import_per_statement'], $fixers['no_unused_imports']),
  154. array($fixers['single_import_per_statement'], $fixers['space_after_semicolon']),
  155. array($fixers['unary_operator_spaces'], $fixers['not_operator_with_space']),
  156. array($fixers['unary_operator_spaces'], $fixers['not_operator_with_successor_space']),
  157. );
  158. }
  159. public function provideFixersPrioritySpecialPhpdocCases()
  160. {
  161. $factory = new FixerFactory();
  162. $factory->registerBuiltInFixers();
  163. $fixers = array();
  164. foreach ($factory->getFixers() as $fixer) {
  165. $fixers[$fixer->getName()] = $fixer;
  166. }
  167. $cases = array();
  168. // prepare bulk tests for phpdoc fixers to test that:
  169. // * `phpdoc_to_comment` is first
  170. // * `phpdoc_indent` is second
  171. // * `phpdoc_types` is third
  172. // * `phpdoc_scalar` is fourth
  173. // * `phpdoc_align` is last
  174. $cases[] = array($fixers['phpdoc_indent'], $fixers['phpdoc_types']);
  175. $cases[] = array($fixers['phpdoc_to_comment'], $fixers['phpdoc_indent']);
  176. $cases[] = array($fixers['phpdoc_types'], $fixers['phpdoc_scalar']);
  177. $docFixerNames = array_filter(
  178. array_keys($fixers),
  179. function ($name) {
  180. return false !== strpos($name, 'phpdoc');
  181. }
  182. );
  183. foreach ($docFixerNames as $docFixerName) {
  184. if (!in_array($docFixerName, array('phpdoc_to_comment', 'phpdoc_indent', 'phpdoc_types', 'phpdoc_scalar'), true)) {
  185. $cases[] = array($fixers['phpdoc_indent'], $fixers[$docFixerName]);
  186. $cases[] = array($fixers['phpdoc_scalar'], $fixers[$docFixerName]);
  187. $cases[] = array($fixers['phpdoc_to_comment'], $fixers[$docFixerName]);
  188. $cases[] = array($fixers['phpdoc_types'], $fixers[$docFixerName]);
  189. }
  190. if ('phpdoc_align' !== $docFixerName) {
  191. $cases[] = array($fixers[$docFixerName], $fixers['phpdoc_align']);
  192. }
  193. }
  194. return $cases;
  195. }
  196. /**
  197. * @dataProvider provideFixersPriorityPairsHaveIntegrationTestCases
  198. *
  199. * @requires PHP 5.4
  200. */
  201. public function testFixersPriorityPairsHaveIntegrationTest(FixerInterface $first, FixerInterface $second)
  202. {
  203. // This structure contains older cases that are not yet covered by tests.
  204. // It may only shrink, never add anything to it.
  205. $casesWithoutTests = array(
  206. 'indentation_type,phpdoc_indent.test',
  207. 'line_ending,single_blank_line_at_eof.test',
  208. 'method_separation,braces.test',
  209. 'method_separation,indentation_type.test',
  210. 'no_empty_statement,no_multiline_whitespace_before_semicolons.test',
  211. 'no_empty_statement,no_singleline_whitespace_before_semicolons.test',
  212. 'php_unit_strict,php_unit_construct.test',
  213. 'phpdoc_no_access,phpdoc_order.test',
  214. 'phpdoc_no_access,phpdoc_separation.test',
  215. 'phpdoc_no_empty_return,phpdoc_trim.test',
  216. 'phpdoc_no_package,phpdoc_order.test',
  217. 'phpdoc_no_package,phpdoc_trim.test',
  218. 'phpdoc_order,phpdoc_separation.test',
  219. 'phpdoc_order,phpdoc_trim.test',
  220. 'phpdoc_separation,phpdoc_trim.test',
  221. 'phpdoc_summary,phpdoc_trim.test',
  222. 'phpdoc_var_without_name,phpdoc_trim.test',
  223. 'unary_operator_spaces,not_operator_with_space.test',
  224. 'unary_operator_spaces,not_operator_with_successor_space.test',
  225. );
  226. $integrationTestExists = $this->doesIntegrationTestExist($first, $second);
  227. if (in_array($this->generateIntegrationTestName($first, $second), $casesWithoutTests, true)) {
  228. $this->assertFalse($integrationTestExists, sprintf('Case "%s" already has an integration test, so it should be removed from "$casesWithoutTests".', $this->generateIntegrationTestName($first, $second)));
  229. $this->markTestIncomplete(sprintf('Case "%s" has no integration test yet, please help and add it.', $this->generateIntegrationTestName($first, $second)));
  230. }
  231. $this->assertTrue($integrationTestExists, sprintf('There shall be an integration test "%s". How do you know that priority set up is good, if there is no integration test to check it?', $this->generateIntegrationTestName($first, $second)));
  232. }
  233. public function provideFixersPriorityPairsHaveIntegrationTestCases()
  234. {
  235. $self = $this;
  236. return array_filter(
  237. $this->provideFixersPriorityCases(),
  238. // ignore speed-up only priorities set up
  239. function (array $case) use ($self) {
  240. return !in_array(
  241. $self->generateIntegrationTestName($case[0], $case[1]),
  242. array(
  243. 'function_to_constant,native_function_casing.test',
  244. 'no_unused_imports,no_leading_import_slash.test',
  245. 'pow_to_exponentiation,method_argument_space.test',
  246. 'pow_to_exponentiation,native_function_casing.test',
  247. 'pow_to_exponentiation,no_spaces_after_function_name.test',
  248. 'pow_to_exponentiation,no_spaces_inside_parenthesis.test',
  249. ),
  250. true
  251. );
  252. }
  253. );
  254. }
  255. /**
  256. * @private
  257. */
  258. public function generateIntegrationTestName(FixerInterface $first, FixerInterface $second)
  259. {
  260. return "{$first->getName()},{$second->getName()}.test";
  261. }
  262. private function doesIntegrationTestExist(FixerInterface $first, FixerInterface $second)
  263. {
  264. return is_file(__DIR__.'/../Fixtures/Integration/priority/'.$this->generateIntegrationTestName($first, $second)) || is_file(__DIR__.'/../Fixtures/Integration/priority/'.$this->generateIntegrationTestName($second, $first));
  265. }
  266. }