Commit 31daed5c authored by Sergey Kalinichev's avatar Sergey Kalinichev

Correctly build parent context for out-of-line methods

Use a helper context for that.

REVIEW: 124513
parent 38b11c1e
......@@ -510,13 +510,29 @@ Declaration* findDeclaration(const QualifiedIdentifier& qid, const DUContextPoin
}
/// If any parent of this context is a class, the closest class declaration is returned, nullptr otherwise
Declaration* classDeclarationForContext(const DUContextPointer& context)
Declaration* classDeclarationForContext(const DUContextPointer& context, const CursorInRevision& position, const QMultiHash<QualifiedIdentifier, Declaration*>& declarationsCache)
{
auto parent = context;
while (parent) {
if (parent->type() == DUContext::Class) {
break;
}
if (auto owner = parent->owner()) {
// Work-around for out-of-line methods. They have Helper context instead of Class context
if (owner->context() && owner->context()->type() == DUContext::Helper) {
auto qid = owner->qualifiedIdentifier();
qid.pop();
QSet<Declaration*> tmp;
auto decl = findDeclaration(qid, context, position, declarationsCache, tmp);
if (decl && decl->internalContext() && decl->internalContext()->type() == DUContext::Class) {
parent = decl->internalContext();
break;
}
}
}
parent = parent->parentContext();
}
......@@ -634,7 +650,9 @@ QList<CompletionTreeItemPointer> ClangCodeCompletionContext::completionItems(boo
continue;
}
if (availability == CXAvailability_NotAccessible && (!isDeclaration || !classDeclarationForContext(ctx))) {
// If ctx is/inside the Class context, this represents that context.
auto currentClassContext = classDeclarationForContext(ctx, m_position, declarationsCache);
if (availability == CXAvailability_NotAccessible && (!isDeclaration || !currentClassContext)) {
continue;
}
......@@ -743,8 +761,7 @@ QList<CompletionTreeItemPointer> ClangCodeCompletionContext::completionItems(boo
continue;
}
auto declarationClassContext = classDeclarationForContext(DUContextPointer(found->context()));
auto currentClassContext = classDeclarationForContext(ctx);
auto declarationClassContext = classDeclarationForContext(DUContextPointer(found->context()), m_position, declarationsCache);
uint steps = 10;
auto inheriters = DUChainUtils::getInheriters(declarationClassContext, steps);
......
......@@ -946,7 +946,7 @@ CXChildVisitResult Visitor::buildDeclaration(CXCursor cursor)
// Code path for class declarations that may be defined "out-of-line", e.g.
// "SomeNameSpace::SomeClass {};"
QScopedPointer<CurrentContext> helperContext;
if (CursorKindTraits::isClass(CK)) {
if (CursorKindTraits::isClass(CK) || CursorKindTraits::isFunction(CK)) {
const auto lexicalParent = clang_getCursorLexicalParent(cursor);
const auto semanticParent = clang_getCursorSemanticParent(cursor);
const bool isOutOfLine = !clang_equalCursors(lexicalParent, semanticParent);
......
......@@ -4,7 +4,7 @@ class foo
/// "isDefinition": false,
/// "definition": {
/// "range": "[(11, 9), (11, 12)]",
/// "qualifiedIdentifier": "foo::bar", "EXPECT_FAIL": {"qualifiedIdentifier": "the parent context is not set properly"}
/// "qualifiedIdentifier": "foo::bar"
/// }
int bar();
};
......
......@@ -177,7 +177,6 @@ void executeCompletionPriorityTest(const QString& code, const CompletionPriority
for(const auto& declaration : expectedCompletionItems.completions){
const auto declarationItem = tester.findItem(declaration.name);
QEXPECT_FAIL("protected-access2", declaration.failMessage.toUtf8().constData(), Abort);
QVERIFY(declarationItem);
QVERIFY(declarationItem->declaration());
......@@ -724,5 +723,5 @@ void TestCodeCompletion::testCompletionPriority_data()
<< "class Base { protected: int m_protected; };"
"class Derived: public Base {public: void f();};"
"void Derived::f(){\n }"
<< CompletionPriorityItems{{1,0}, {{"m_protected", 0, 37, QStringLiteral("Out of line methods have wrong parent context attached (Global instead of Class)")}}};
<< CompletionPriorityItems{{1,0}, {{"m_protected", 0, 37}}};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment