Skip to content

Commit aa1bbc7

Browse files
committed
moved to php tokenizer
1 parent 48165e5 commit aa1bbc7

5 files changed

Lines changed: 135 additions & 88 deletions

File tree

src/Complete/Completer/Completer.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,16 @@
66
use Entity\Project;
77

88
class Completer{
9-
private $classNameCompleter;
10-
private $interfaceNameCompleter;
11-
private $namespaceCompleter;
12-
139
public function __construct(
1410
ClassNameCompleter $classNameCompleter,
1511
InterfaceNameCompleter $interfaceNameCompleter,
16-
NamespaceCompleter $namespaceCompleter
12+
NamespaceCompleter $namespaceCompleter,
13+
ObjectCompleter $objectCompleter
1714
){
1815
$this->classNameCompleter = $classNameCompleter;
1916
$this->interfaceNameCompleter = $interfaceNameCompleter;
2017
$this->namespaceCompleter = $namespaceCompleter;
18+
$this->objectCompleter = $objectCompleter;
2119
}
2220
public function getEntries(Project $project, Context $context){
2321
if($context->isNamespace()){
@@ -32,6 +30,9 @@ public function getEntries(Project $project, Context $context){
3230
printf("Interfaces completion");
3331
return $this->getAllInterfaces($project, $context);
3432
}
33+
elseif($context->isThis() || $context->isObject()){
34+
return $this->getObjectCompletion($project, $context);
35+
}
3536
return [];
3637
}
3738
protected function getAllNamespaces(Project $project, Context $context){
@@ -43,4 +44,12 @@ protected function getAllClasses(Project $project, Context $context){
4344
protected function getAllInterfaces(Project $project, Context $context){
4445
return $this->interfaceNameCompleter->getEntries($project, $context);
4546
}
47+
protected function getObjectCompletion(Project $project, Context $context){
48+
return $this->objectCompleter->getEntries($project, $context);
49+
}
50+
51+
private $classNameCompleter;
52+
private $interfaceNameCompleter;
53+
private $namespaceCompleter;
54+
private $objectCompleter;
4655
}

src/Complete/ContentManager.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ public function createCompletion(
3535
){
3636
$entries = [];
3737
if($line){
38-
list($lines, $badLine) = $this->prepareContent(
38+
list($lines, $badLine, $completionLine) = $this->prepareContent(
3939
$content,
40-
$line
40+
$line,
41+
$column
4142
);
42-
$this->updateFileIndex($project, $lines, $file);
43-
$entries = $this->findEntries($project, $badLine, $column, $lines);
43+
try {
44+
$this->updateFileIndex($project, $lines, $file);
45+
}
46+
catch(\Exception $e){}
47+
$entries = $this->findEntries($project, $completionLine, $column, $lines);
4448
}
4549
elseif(!empty($content)) {
4650
$this->updateFileIndex($project, $content, $file);
@@ -59,11 +63,17 @@ protected function findEntries(Project $project, $badLine, $column, $lines){
5963
* @TODO
6064
* Should check for bad lines
6165
*/
62-
protected function prepareContent($content, $line){
66+
protected function prepareContent($content, $line, $column){
6367
$lines = explode(PHP_EOL, $content);
64-
$badLine = trim($lines[$line-1]);
68+
if($line > count($lines)){
69+
$badLine = "";
70+
}
71+
else{
72+
$badLine = $lines[$line-1];
73+
}
74+
$completionLine = substr($badLine, 0, $column+1);
6575
$lines[$line-1] = "";
66-
return [$lines, $badLine];
76+
return [$lines, trim($badLine), trim($completionLine)];
6777
}
6878
protected function updateFileIndex(Project $project, $lines, $file){
6979
if(is_array($lines)){

src/Complete/ContextResolver.php

Lines changed: 88 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,66 +6,89 @@
66
use Entity\Completion\Context;
77

88
class ContextResolver{
9-
const S_VAR = '$';
10-
const S_CLASS = '->';
11-
const S_STATIC = '::';
12-
const S_USE = 'use';
13-
const S_NAMESPACE = 'namespace';
14-
const S_NEW_CLASS = 'new';
15-
const S_EXT_CLASS = 'extends';
16-
const S_IMPL_INTERFACE = 'implements';
17-
protected static $SOFT_TERMINATES = [
18-
' ', '(', ')', '[', ']', '\'', '"'
19-
];
20-
protected static $TERMINATES = [
21-
';', ',', '.', '='
22-
];
23-
public function getContext($badLine, $column){
9+
public function getContext($badLine){
2410
if(empty($badLine)){
25-
return null;
26-
}
27-
$token = new Token;
28-
$length = strlen($badLine);
29-
for($i=0; $i<$length ;++$i){
30-
$curChar = $badLine[$i];
31-
$token = $this->addChar($token, $curChar);
11+
throw new \Exception("Could not define empty line context");
3212
}
33-
$context = new Context($token->prefix, $token->postfix);
13+
printf("\n%s\n", $badLine);
14+
$token = $this->getCompletionToken($badLine);
15+
$context = new Context($token, $token->symbol);
3416
return $this->defineContextType($context, $token);
3517
}
36-
public function addChar($token, $curChar){
37-
$token->postfix .= $curChar;
38-
if(
39-
$this->isSimpleSymbol($token->postfix)
40-
|| $this->isTerminableSymbol($token->postfix)
18+
protected function getCompletionToken($badLine){
19+
$token = new Token;
20+
$token->type = -1;
21+
$token->parent = $token;
22+
if(strpos($badLine, '<?php') === false
23+
|| strpos($badLine, '<?') === false
4124
){
42-
$token->updateSymbol();
25+
$badLine = '<?php ' . $badLine;
4326
}
44-
elseif(
45-
!$this->isTerminableSymbol($token->symbol)
46-
&& $this->isSoftTerminateSymbol($curChar)
47-
){
48-
$token = new Token;
27+
$symbols = token_get_all($badLine);
28+
$symbols = array_slice($symbols, 1);
29+
foreach($symbols AS $symbol){
30+
$token = $this->addSymbol($token, $symbol);
4931
}
50-
elseif(
51-
$this->isTerminateSymbol($curChar)
52-
){
53-
$token = new Token;
32+
return $token;
33+
}
34+
protected function addSymbol(Token $parent, $symbol){
35+
print_r($symbol);
36+
if(is_array($symbol)){
37+
$code = $symbol[0];
38+
$symbol = $symbol[1];
39+
}
40+
else {
41+
$code = $symbol;
42+
}
43+
if($code == T_WHITESPACE){
44+
return $parent;
45+
}
46+
if($code === T_STRING || $code === T_NS_SEPARATOR){
47+
$parent->symbol .= $symbol;
48+
return $parent;
49+
}
50+
if(is_int($code)){
51+
printf("%s\n", token_name($code));
52+
}
53+
$token = new Token;
54+
if($code === ';' || $code === ','){
55+
return $parent;
56+
}
57+
switch($code){
58+
case T_VARIABLE:
59+
$token->symbol = $symbol;
60+
case T_NAMESPACE:
61+
case T_USE:
62+
case T_NEW:
63+
case T_EXTENDS:
64+
case T_IMPLEMENTS:
65+
case T_OBJECT_OPERATOR:
66+
$token->type = self::$MAP[$code];
67+
break;
68+
case ')':
69+
case ']':
70+
$token = $parent->parent;
71+
break;
72+
default:
73+
return $parent;
74+
}
75+
if($token){
76+
$parent->addChild($token);
5477
}
5578
return $token;
5679
}
5780
protected function defineContextType(Context $context, Token $token){
58-
printf("\n%s: %s - %s\n", $token->symbol, $token->postfix, $token->prefix);
59-
switch($token->symbol){
81+
print_r($token);
82+
switch($token->type){
6083
case self::S_VAR:
6184
$context->addType(Context::TYPE_VAR);
6285
break;
63-
case self::S_CLASS:
64-
if($token->prefix === '$this'){
86+
case self::S_OBJECT:
87+
if($token->symbol === '$this'){
6588
$context->addType(Context::TYPE_THIS);
6689
}
6790
else {
68-
$context->addType(Context::TYPE_CLASS);
91+
$context->addType(Context::TYPE_OBJECT);
6992
}
7093
break;
7194
case self::S_STATIC:
@@ -76,34 +99,33 @@ protected function defineContextType(Context $context, Token $token){
7699
break;
77100
case self::S_USE:
78101
$context->addType(Context::TYPE_USE);
79-
case self::S_NEW_CLASS:
80-
case self::S_EXT_CLASS:
102+
case self::S_NEW:
103+
case self::S_EXTENDS:
81104
$context->addType(Context::TYPE_CLASSNAME);
82105
break;
83-
case self::S_IMPL_INTERFACE:
106+
case self::S_IMPLEMENTS:
84107
$context->addType(Context::TYPE_INTERFACENAME);
85108
break;
86109
}
87110
return $context;
88111
}
89-
protected function isSimpleSymbol($symbol){
90-
return $this->isSymbol($symbol, self::S_VAR)
91-
|| $this->isSymbol($symbol, self::S_CLASS)
92-
|| $this->isSymbol($symbol, self::S_STATIC);
93-
}
94-
protected function isTerminableSymbol($symbol){
95-
return $this->isSymbol($symbol, self::S_USE)
96-
|| $this->isSymbol($symbol, self::S_NEW_CLASS)
97-
|| $this->isSymbol($symbol, self::S_NAMESPACE);
98-
}
99-
protected function isSoftTerminateSymbol($symbol){
100-
return in_array($symbol, self::$SOFT_TERMINATES);
101-
}
102-
protected function isTerminateSymbol($symbol){
103-
return in_array($symbol, self::$TERMINATES);
104-
}
105-
protected function isSymbol($symbol, $check){
106-
$symbol = strtolower($symbol);
107-
return strpos($symbol, $check) === strlen($symbol) - strlen($check);
108-
}
112+
const S_VAR = '$';
113+
const S_OBJECT = '->';
114+
const S_STATIC = '::';
115+
const S_USE = 'use';
116+
const S_NAMESPACE = 'namespace';
117+
const S_NEW = 'new';
118+
const S_EXTENDS = 'extends';
119+
const S_IMPLEMENTS = 'implements';
120+
121+
public static $MAP = [
122+
T_VARIABLE => self::S_VAR,
123+
T_OBJECT_OPERATOR => self::S_OBJECT,
124+
T_STATIC => self::S_STATIC,
125+
T_USE => self::S_USE,
126+
T_NAMESPACE => self::S_NAMESPACE,
127+
T_NEW => self::S_NEW,
128+
T_EXTENDS => self::S_EXTENDS,
129+
T_IMPLEMENTS => self::S_IMPLEMENTS
130+
];
109131
}

src/Entity/Completion/Context.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class Context {
66
const TYPE_VAR = 1;
77
const TYPE_USE = 2;
88
const TYPE_NAMESPACE = 4;
9-
const TYPE_CLASS = 8;
9+
const TYPE_OBJECT = 8;
1010
const TYPE_CLASSNAME = 16;
1111
const TYPE_INTERFACENAME = 32;
1212
const TYPE_THIS = 64;
@@ -15,16 +15,17 @@ class Context {
1515

1616
private $type = 0;
1717
private $postfix = "";
18-
private $prefix = "";
19-
public function __construct($prefix, $postfix){
20-
$this->prefix = $prefix;
18+
private $token;
19+
private $scope;
20+
public function __construct(Token $token, $postfix){
21+
$this->token = $token;
2122
$this->postfix = $postfix;
2223
}
2324
public function addType($type){
2425
$this->type = $this->type | $type;
2526
}
26-
public function getPrefix(){
27-
return $this->prefix;
27+
public function getToken(){
28+
return $this->token;
2829
}
2930
public function getPostfix(){
3031
return $this->postfix;
@@ -41,8 +42,8 @@ public function isUse(){
4142
public function isNamespace(){
4243
return (bool) ($this->type & self::TYPE_NAMESPACE);
4344
}
44-
public function isClass(){
45-
return (bool) ($this->type & self::TYPE_CLASS);
45+
public function isObject(){
46+
return (bool) ($this->type & self::TYPE_OBJECT);
4647
}
4748
public function isClassName(){
4849
return (bool) ($this->type & self::TYPE_CLASSNAME);

src/Entity/Completion/Token.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@
44

55
class Token {
66
public $symbol = "";
7-
public $prefix = "";
8-
public $postfix = "";
7+
public $type = 0;
8+
public $parent;
9+
public $children = [];
910
public function updateSymbol(){
1011
if(!empty($this->symbol)){
1112
$this->prefix = $this->symbol . $this->postfix;
1213
}
1314
$this->symbol = $this->postfix;
1415
$this->postfix = "";
1516
}
17+
public function addChild(Token $token){
18+
$this->children[] = $token;
19+
$token->parent = $this;
20+
}
1621
}

0 commit comments

Comments
 (0)