summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthijs Tijink <matthijstijink@gmail.com>2017-07-26 17:07:37 (GMT)
committerAlexander Zhigalin <alexander@zhigalin.tk>2017-07-26 17:16:31 (GMT)
commit2c863b8a3071f057126d49dc55438020a821e2e4 (patch)
tree425981b9cb490079dabc7d939ea459a05567c6cd
parent8862dde3b4ee101395c900e4041cc2a2534f153e (diff)
Fix uses of class in closure parameters and default values for functions
Summary: Uses of classes in closures and default values for functions were not captured previously, this diff adds that. Reviewers: #kdevelop, zhigalin Subscribers: zhigalin, kdevelop-devel, #kdevelop Tags: #kdevelop Differential Revision: https://phabricator.kde.org/D6690
-rw-r--r--duchain/builders/usebuilder.cpp3
-rw-r--r--duchain/expressionvisitor.cpp20
-rw-r--r--duchain/tests/uses.cpp27
-rw-r--r--duchain/tests/uses.h2
4 files changed, 52 insertions, 0 deletions
diff --git a/duchain/builders/usebuilder.cpp b/duchain/builders/usebuilder.cpp
index 044da88..15c1feb 100644
--- a/duchain/builders/usebuilder.cpp
+++ b/duchain/builders/usebuilder.cpp
@@ -67,6 +67,9 @@ void UseBuilder::visitParameter(ParameterAst *node)
if (node->parameterType && node->parameterType->objectType) {
buildNamespaceUses(node->parameterType->objectType);
}
+ if (node->defaultValue) {
+ visitNodeWithExprVisitor(node->defaultValue);
+ }
}
void UseBuilder::visitClassImplements(ClassImplementsAst *node)
diff --git a/duchain/expressionvisitor.cpp b/duchain/expressionvisitor.cpp
index 1853cc1..58d51f3 100644
--- a/duchain/expressionvisitor.cpp
+++ b/duchain/expressionvisitor.cpp
@@ -219,6 +219,14 @@ void ExpressionVisitor::visitClosure(ClosureAst* node)
if (node->functionBody) {
visitInnerStatementList(node->functionBody);
}
+ if (node->returnType && node->returnType->objectType) {
+ NamespacedIdentifierAst* objectType = node->returnType->objectType;
+ QualifiedIdentifier id = identifierForNamespace(objectType, m_editor);
+ DeclarationPointer dec = findDeclarationImport(ClassDeclarationType, id);
+
+ usingDeclaration(objectType->namespaceNameSequence->back()->element, dec);
+ buildNamespaceUses(objectType, id);
+ }
//First try return typehint or phpdoc return typehint
AbstractType::Ptr type = returnType(node->returnType, {}, m_editor, m_currentContext);
@@ -233,6 +241,18 @@ void ExpressionVisitor::visitClosure(ClosureAst* node)
forever {
AbstractType::Ptr type = parameterType(it->element, {}, m_editor, m_currentContext);
closureType->addArgument(type);
+
+ if (it->element->parameterType && it->element->parameterType->objectType) {
+ NamespacedIdentifierAst* objectType = it->element->parameterType->objectType;
+ QualifiedIdentifier id = identifierForNamespace(objectType, m_editor);
+ DeclarationPointer dec = findDeclarationImport(ClassDeclarationType, id);
+
+ usingDeclaration(objectType->namespaceNameSequence->back()->element, dec);
+ buildNamespaceUses(objectType, id);
+ }
+ if (it->element->defaultValue) {
+ visitExpr(it->element->defaultValue);
+ }
if ( it->hasNext() ) {
it = it->next;
} else {
diff --git a/duchain/tests/uses.cpp b/duchain/tests/uses.cpp
index 0615882..c3e1538 100644
--- a/duchain/tests/uses.cpp
+++ b/duchain/tests/uses.cpp
@@ -1067,6 +1067,18 @@ void TestUses::closures()
QVERIFY(b->uses().isEmpty());
}
+void TestUses::closureTypehints() {
+ TopDUContext* top = parse("<?php class A {} $b = function (A $a): A {};", DumpNone);
+ QVERIFY(top);
+ DUChainReleaser releaseTop(top);
+ DUChainWriteLocker lock;
+
+ QCOMPARE(top->localDeclarations().count(), 3);
+ Declaration* a = top->localDeclarations().at(0);
+ QCOMPARE(a->qualifiedIdentifier(), QualifiedIdentifier("a"));
+ compareUses(a, QList<RangeInRevision>() << RangeInRevision(0, 32, 0, 33) << RangeInRevision(0, 39, 0, 40));
+}
+
void TestUses::instanceof()
{
// 0 1 2 3 4 5
@@ -1243,5 +1255,20 @@ void TestUses::returnTypeFunction() {
compareUses(a, QList<RangeInRevision>() << RangeInRevision(0, 30, 0, 31));
}
+void TestUses::defaultValue() {
+ QByteArray method("<? class A {const C = 1;} function foo($a = A::C) {}");
+ TopDUContext *top = parse(method, DumpNone);
+ DUChainReleaser releaseTop(top);
+ DUChainWriteLocker lock(DUChain::lock());
+
+ Declaration *a = top->localDeclarations().at(0);
+ QCOMPARE(a->identifier().toString(), QString("a"));
+ compareUses(a, QList<RangeInRevision>() << RangeInRevision(0, 44, 0, 45));
+
+ Declaration *c = top->childContexts().at(0)->localDeclarations().at(0);
+ QCOMPARE(c->identifier().toString(), QString("C"));
+ compareUses(c, QList<RangeInRevision>() << RangeInRevision(0, 47, 0, 48));
+}
+
}
diff --git a/duchain/tests/uses.h b/duchain/tests/uses.h
index ae52d4c..fa4580f 100644
--- a/duchain/tests/uses.h
+++ b/duchain/tests/uses.h
@@ -81,12 +81,14 @@ private slots:
void useNamespace();
void lateStatic();
void closures();
+ void closureTypehints();
void instanceof();
void classNameString();
void useTrait();
void exceptionFinally();
void returnTypeClassFunction();
void returnTypeFunction();
+ void defaultValue();
};
}