1
0
Fork 0

Merge remote-tracking branch 'felixfbecker/master' into return-self

pull/576/head
Philip Nelson 2018-01-09 20:10:00 +11:00
commit fcbc729f3f
No known key found for this signature in database
GPG Key ID: 8C8235644C5E2279
6 changed files with 78 additions and 25 deletions

View File

@ -56,5 +56,5 @@ stages:
if: branch = master AND type = push AND fork = false if: branch = master AND type = push AND fork = false
branches: branches:
except: only:
- /^v\d+\.\d+\.\d+$/ - master

View File

@ -14,7 +14,7 @@ use RecursiveIteratorIterator;
$totalSize = 0; $totalSize = 0;
$frameworks = ["drupal", "wordpress", "php-language-server", "tolerant-php-parser", "math-php", "symfony", "CodeIgniter", "cakephp"]; $frameworks = ["drupal", "wordpress", "php-language-server", "tolerant-php-parser", "math-php", "symfony", "codeigniter", "cakephp"];
foreach($frameworks as $framework) { foreach($frameworks as $framework) {
$iterator = new RecursiveDirectoryIterator(__DIR__ . "/validation/frameworks/$framework"); $iterator = new RecursiveDirectoryIterator(__DIR__ . "/validation/frameworks/$framework");

View File

@ -186,6 +186,7 @@ Example:
- [Eclipse Che](https://eclipse.org/che/) - [Eclipse Che](https://eclipse.org/che/)
- [Eclipse IDE (LSP4E-PHP)](https://github.com/eclipselabs/lsp4e-php) - [Eclipse IDE (LSP4E-PHP)](https://github.com/eclipselabs/lsp4e-php)
- NeoVim: [LanguageServer-php-neovim](https://github.com/roxma/LanguageServer-php-neovim) with [LanguageClient neovim](https://github.com/autozimu/LanguageClient-neovim) - NeoVim: [LanguageServer-php-neovim](https://github.com/roxma/LanguageServer-php-neovim) with [LanguageClient neovim](https://github.com/autozimu/LanguageClient-neovim)
- Atom: [ide-php](https://github.com/atom/ide-php)
## Contributing ## Contributing

View File

@ -35,3 +35,12 @@ foreach ($array3 as $key => $value) {
foreach ($bar->test() as $value) { foreach ($bar->test() as $value) {
$ $
} }
foreach ($unknownArray as $member->access => $unknown) {
$unkno
foreach ($loop as $loop) {
}
foreach ($loop->getArray() as $loop) {
}

View File

@ -545,6 +545,15 @@ class DefinitionResolver
} else { } else {
throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var)); throw new \InvalidArgumentException('$var must be Variable, Param or ClosureUse, not ' . get_class($var));
} }
if (empty($name)) {
return null;
}
$shouldDescend = function ($nodeToDescand) {
// Make sure not to decend into functions or classes (they represent a scope boundary)
return !($nodeToDescand instanceof PhpParser\FunctionLike || $nodeToDescand instanceof PhpParser\ClassLike);
};
// Traverse the AST up // Traverse the AST up
do { do {
// If a function is met, check the parameters and use statements // If a function is met, check the parameters and use statements
@ -569,37 +578,55 @@ class DefinitionResolver
break; break;
} }
// If we get to a ForeachStatement, check the keys and values // Check each previous sibling node and their descendents for a variable assignment to that variable
if ($n instanceof Node\Statement\ForeachStatement) { // Each previous sibling could contain a declaration of the variable
if ($n->foreachKey && $n->foreachKey->expression->getName() === $name) {
return $n->foreachKey;
}
if ($n->foreachValue
&& $n->foreachValue->expression instanceof Node\Expression\Variable
&& $n->foreachValue->expression->getName() === $name
) {
return $n->foreachValue;
}
}
// Check each previous sibling node for a variable assignment to that variable
while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) { while (($prevSibling = $n->getPreviousSibling()) !== null && $n = $prevSibling) {
if ($n instanceof Node\Statement\ExpressionStatement) {
$n = $n->expression; // Check the sibling itself
} if (self::isVariableDeclaration($n, $name)) {
if (
// TODO - clean this up
($n instanceof Node\Expression\AssignmentExpression && $n->operator->kind === PhpParser\TokenKind::EqualsToken)
&& $n->leftOperand instanceof Node\Expression\Variable && $n->leftOperand->getName() === $name
) {
return $n; return $n;
} }
// Check descendant of this sibling (e.g. the children of a previous if block)
foreach ($n->getDescendantNodes($shouldDescend) as $descendant) {
if (self::isVariableDeclaration($descendant, $name)) {
return $descendant;
}
}
} }
} while (isset($n) && $n = $n->parent); } while (isset($n) && $n = $n->parent);
// Return null if nothing was found // Return null if nothing was found
return null; return null;
} }
/**
* Checks whether the given Node declares the given variable name
*
* @param Node $n The Node to check
* @param string $name The name of the wanted variable
* @return bool
*/
private static function isVariableDeclaration(Node $n, string $name)
{
if (
// TODO - clean this up
($n instanceof Node\Expression\AssignmentExpression && $n->operator->kind === PhpParser\TokenKind::EqualsToken)
&& $n->leftOperand instanceof Node\Expression\Variable && $n->leftOperand->getName() === $name
) {
return true;
}
if (
($n instanceof Node\ForeachValue || $n instanceof Node\ForeachKey)
&& $n->expression instanceof Node\Expression\Variable
&& $n->expression->getName() === $name
) {
return true;
}
return false;
}
/** /**
* Given an expression node, resolves that expression recursively to a type. * Given an expression node, resolves that expression recursively to a type.
* If the type could not be resolved, returns Types\Mixed_. * If the type could not be resolved, returns Types\Mixed_.
@ -1122,6 +1149,7 @@ class DefinitionResolver
if ($collectionType instanceof Types\Array_) { if ($collectionType instanceof Types\Array_) {
return $collectionType->getValueType(); return $collectionType->getValueType();
} }
return new Types\Mixed_();
} }
// PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS // PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS

View File

@ -691,6 +691,21 @@ class CompletionTest extends TestCase
), ),
] ]
], ],
'foreach unknown type' => [
new Position(39, 10),
[
new CompletionItem(
'$unknown',
CompletionItemKind::VARIABLE,
'mixed',
null,
null,
null,
null,
new TextEdit(new Range(new Position(39, 10), new Position(39, 10)), 'wn')
),
]
],
]; ];
} }