AutoCompleterTest.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. <?php
  2. /*
  3. * This file is part of Psy Shell.
  4. *
  5. * (c) 2012-2018 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\TabCompletion;
  11. use Psy\Command\ListCommand;
  12. use Psy\Command\ShowCommand;
  13. use Psy\Configuration;
  14. use Psy\Context;
  15. use Psy\ContextAware;
  16. use Psy\TabCompletion\Matcher;
  17. class AutoCompleterTest extends \PHPUnit\Framework\TestCase
  18. {
  19. /**
  20. * @param string $line
  21. * @param array $mustContain
  22. * @param array $mustNotContain
  23. * @dataProvider classesInput
  24. */
  25. public function testClassesCompletion($line, $mustContain, $mustNotContain)
  26. {
  27. $context = new Context();
  28. $commands = [
  29. new ShowCommand(),
  30. new ListCommand(),
  31. ];
  32. $matchers = [
  33. new Matcher\VariablesMatcher(),
  34. new Matcher\ClassNamesMatcher(),
  35. new Matcher\ConstantsMatcher(),
  36. new Matcher\FunctionsMatcher(),
  37. new Matcher\ObjectMethodsMatcher(),
  38. new Matcher\ObjectAttributesMatcher(),
  39. new Matcher\KeywordsMatcher(),
  40. new Matcher\ClassAttributesMatcher(),
  41. new Matcher\ClassMethodsMatcher(),
  42. new Matcher\CommandsMatcher($commands),
  43. ];
  44. $config = new Configuration();
  45. $tabCompletion = $config->getAutoCompleter();
  46. foreach ($matchers as $matcher) {
  47. if ($matcher instanceof ContextAware) {
  48. $matcher->setContext($context);
  49. }
  50. $tabCompletion->addMatcher($matcher);
  51. }
  52. $context->setAll(['foo' => 12, 'bar' => new \DOMDocument()]);
  53. $code = $tabCompletion->processCallback('', 0, [
  54. 'line_buffer' => $line,
  55. 'point' => 0,
  56. 'end' => \strlen($line),
  57. ]);
  58. foreach ($mustContain as $mc) {
  59. $this->assertContains($mc, $code);
  60. }
  61. foreach ($mustNotContain as $mnc) {
  62. $this->assertNotContains($mnc, $code);
  63. }
  64. }
  65. /**
  66. * TODO
  67. * ====
  68. * draft, open to modifications
  69. * - [ ] if the variable is an array, return the square bracket for completion
  70. * - [ ] if the variable is a constructor or method, reflect to complete as a function call
  71. * - [ ] if the preceding token is a variable, call operators or keywords compatible for completion
  72. * - [X] a command always should be the second token after php_open_tag
  73. * - [X] keywords are never consecutive
  74. * - [X] namespacing completion should work just fine
  75. * - [X] after a new keyword, should always be a class constructor, never a function call or keyword, constant,
  76. * or variable that does not contain a existing class name.
  77. * - [X] on a namespaced constructor the completion must show the classes related, not constants.
  78. *
  79. * @return array
  80. */
  81. public function classesInput()
  82. {
  83. return [
  84. // input, must had, must not had
  85. ['T_OPE', ['T_OPEN_TAG'], []],
  86. ['st', ['stdClass'], []],
  87. ['stdCla', ['stdClass'], []],
  88. ['new s', ['stdClass'], []],
  89. [
  90. 'new ',
  91. ['stdClass', 'Psy\\Context', 'Psy\\Configuration'],
  92. ['require', 'array_search', 'T_OPEN_TAG', '$foo'],
  93. ],
  94. ['new Psy\\C', ['Context'], ['CASE_LOWER']],
  95. ['\s', ['stdClass'], []],
  96. ['array_', ['array_search', 'array_map', 'array_merge'], []],
  97. ['$bar->', ['load'], []],
  98. ['$b', ['bar'], []],
  99. ['6 + $b', ['bar'], []],
  100. ['$f', ['foo'], []],
  101. ['l', ['ls'], []],
  102. ['ls ', [], ['ls']],
  103. ['sho', ['show'], []],
  104. ['12 + clone $', ['foo'], []],
  105. // array(
  106. // '$foo ',
  107. // array('+', 'clone'),
  108. // array('$foo', 'DOMDocument', 'array_map')
  109. // ), requires a operator matcher?
  110. ['$', ['foo', 'bar'], ['require', 'array_search', 'T_OPEN_TAG', 'Psy']],
  111. [
  112. 'Psy\\',
  113. ['Context', 'TabCompletion\\Matcher\\AbstractMatcher'],
  114. ['require', 'array_search'],
  115. ],
  116. [
  117. 'Psy\Test\TabCompletion\StaticSample::CO',
  118. ['StaticSample::CONSTANT_VALUE'],
  119. [],
  120. ],
  121. [
  122. 'Psy\Test\TabCompletion\StaticSample::',
  123. ['StaticSample::$staticVariable'],
  124. [],
  125. ],
  126. [
  127. 'Psy\Test\TabCompletion\StaticSample::',
  128. ['StaticSample::staticFunction'],
  129. [],
  130. ],
  131. ];
  132. }
  133. }