AutoCompleterTest.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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\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 $line
  21. * @param $mustContain
  22. * @param $mustNotContain
  23. * @dataProvider classesInput
  24. */
  25. public function testClassesCompletion($line, $mustContain, $mustNotContain)
  26. {
  27. $context = new Context();
  28. $commands = array(
  29. new ShowCommand(),
  30. new ListCommand(),
  31. );
  32. $matchers = array(
  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(array('foo' => 12, 'bar' => new \DOMDocument()));
  53. $code = $tabCompletion->processCallback('', 0, array(
  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 array(
  84. // input, must had, must not had
  85. array('T_OPE', array('T_OPEN_TAG'), array()),
  86. array('st', array('stdClass'), array()),
  87. array('stdCla', array('stdClass'), array()),
  88. array('new s', array('stdClass'), array()),
  89. array(
  90. 'new ',
  91. array('stdClass', 'Psy\\Context', 'Psy\\Configuration'),
  92. array('require', 'array_search', 'T_OPEN_TAG', '$foo'),
  93. ),
  94. array('new Psy\\C', array('Context'), array('CASE_LOWER')),
  95. array('\s', array('stdClass'), array()),
  96. array('array_', array('array_search', 'array_map', 'array_merge'), array()),
  97. array('$bar->', array('load'), array()),
  98. array('$b', array('bar'), array()),
  99. array('6 + $b', array('bar'), array()),
  100. array('$f', array('foo'), array()),
  101. array('l', array('ls'), array()),
  102. array('ls ', array(), array('ls')),
  103. array('sho', array('show'), array()),
  104. array('12 + clone $', array('foo'), array()),
  105. // array(
  106. // '$foo ',
  107. // array('+', 'clone'),
  108. // array('$foo', 'DOMDocument', 'array_map')
  109. // ), requires a operator matcher?
  110. array('$', array('foo', 'bar'), array('require', 'array_search', 'T_OPEN_TAG', 'Psy')),
  111. array(
  112. 'Psy\\',
  113. array('Context', 'TabCompletion\\Matcher\\AbstractMatcher'),
  114. array('require', 'array_search'),
  115. ),
  116. array(
  117. 'Psy\Test\TabCompletion\StaticSample::CO',
  118. array('Psy\Test\TabCompletion\StaticSample::CONSTANT_VALUE'),
  119. array(),
  120. ),
  121. array(
  122. 'Psy\Test\TabCompletion\StaticSample::',
  123. array('Psy\Test\TabCompletion\StaticSample::$staticVariable'),
  124. array(),
  125. ),
  126. array(
  127. 'Psy\Test\TabCompletion\StaticSample::',
  128. array('Psy\Test\TabCompletion\StaticSample::staticFunction'),
  129. array(),
  130. ),
  131. );
  132. }
  133. }