summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPrzemyslaw Gorszkowski <pgorszkowski@gmail.com>2013-11-24 21:02:26 +0100
committerErik Verbruggen <erik.verbruggen@digia.com>2014-03-12 14:07:58 +0100
commit376f77952e9c579043a26fcd6be33baed9fd1610 (patch)
treeab23a657dae14e854f0c07749d4bed7329144341 /src
parentb96bb6172e736379b780ad72c8c4055b93d82da2 (diff)
downloadqt-creator-376f77952e9c579043a26fcd6be33baed9fd1610.tar.gz
C++: fix support for nested anonymous classes
A member of nested anonymous class should be visible as a member of enclosing class(if there is no declaration of this nested anonymous class). Fix: * marking * find usage * follow symbol * completion Task-number: QTCREATORBUG-10876 Task-number: QTCREATORBUG-11170 Change-Id: If5b4d198e9075f2a8aa899ae59190f2c05f7b1ff Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Przemyslaw Gorszkowski <pgorszkowski@gmail.com> Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/libs/cplusplus/LookupContext.cpp15
-rw-r--r--src/libs/cplusplus/LookupContext.h4
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp63
-rw-r--r--src/plugins/cpptools/cppcompletionassist.cpp51
-rw-r--r--src/plugins/cpptools/cppcompletionassist.h1
5 files changed, 115 insertions, 19 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index ecf54a5f1a..0d600993c6 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -680,6 +680,15 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
foreach (ClassOrNamespace *u, binding->usings())
lookup_helper(name, u, result, processed, binding->_templateId);
+
+ Anonymouses::const_iterator cit = binding->_anonymouses.begin();
+ Anonymouses::const_iterator citEnd = binding->_anonymouses.end();
+ for (; cit != citEnd; ++cit) {
+ const AnonymousNameId *anonymousNameId = cit.key();
+ ClassOrNamespace *a = cit.value();
+ if (!binding->_declaredAnonymouses.contains(anonymousNameId))
+ lookup_helper(name, a, result, processed, binding->_templateId);
+ }
}
}
@@ -1578,8 +1587,12 @@ bool CreateBindings::visit(Declaration *decl)
}
}
}
+ } else if (Class *clazz = decl->type()->asClassType()) {
+ if (const Name *name = clazz->name()) {
+ if (const AnonymousNameId *anonymousNameId = name->asAnonymousNameId())
+ _currentClassOrNamespace->_declaredAnonymouses.insert(anonymousNameId);
+ }
}
-
return false;
}
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 84c9d47006..11c7bc6268 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -93,6 +93,7 @@ public:
private:
typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table;
typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable;
+ typedef QHash<const AnonymousNameId *, ClassOrNamespace *> Anonymouses;
/// \internal
void flush();
@@ -138,7 +139,8 @@ private:
QSharedPointer<Control> _control;
TemplateNameIdTable _specializations;
QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
- QHash<const AnonymousNameId *, ClassOrNamespace *> _anonymouses;
+ Anonymouses _anonymouses;
+ QSet<const AnonymousNameId *> _declaredAnonymouses;
QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index 7b78ac901a..eb657f783b 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -1425,7 +1425,9 @@ void CppToolsPlugin::test_completion_data()
" @\n"
"}\n"
) << _("s.") << (QStringList()
- << QLatin1String("S"));
+ << QLatin1String("S")
+ << QLatin1String("i")
+ << QLatin1String("c"));
QTest::newRow("instantiate_template_function") << _(
"template <typename T>\n"
@@ -1439,6 +1441,65 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("A")
<< QLatin1String("a"));
+ QTest::newRow("nested_anonymous_class_QTCREATORBUG10876_1") << _(
+ "struct EnclosingStruct\n"
+ "{\n"
+ " int memberOfEnclosingStruct;\n"
+ " struct\n"
+ " {\n"
+ " int memberNestedAnonymousClass;\n"
+ " };\n"
+ " void fun()\n"
+ " {\n"
+ " @\n"
+ " }\n"
+ "};\n"
+ ) << _("member") << (QStringList()
+ << QLatin1String("memberNestedAnonymousClass")
+ << QLatin1String("memberOfEnclosingStruct"));
+
+ QTest::newRow("nested_anonymous_class_QTCREATORBUG10876_2") << _(
+ "struct EnclosingStruct\n"
+ "{\n"
+ " int memberOfEnclosingStruct;\n"
+ " struct\n"
+ " {\n"
+ " int memberOfNestedAnonymousClass;\n"
+ " struct\n"
+ " {\n"
+ " int memberOfNestedOfNestedAnonymousClass;\n"
+ " };\n"
+ " };\n"
+ " void fun()\n"
+ " {\n"
+ " @\n"
+ " }\n"
+ "};\n"
+ ) << _("member") << (QStringList()
+ << QLatin1String("memberOfNestedAnonymousClass")
+ << QLatin1String("memberOfNestedOfNestedAnonymousClass")
+ << QLatin1String("memberOfEnclosingStruct"));
+
+ QTest::newRow("nested_anonymous_class_QTCREATORBUG10876_3") << _(
+ "struct EnclosingStruct\n"
+ "{\n"
+ " int memberOfEnclosingStruct;\n"
+ " struct\n"
+ " {\n"
+ " int memberOfNestedAnonymousClass;\n"
+ " struct\n"
+ " {\n"
+ " int memberOfNestedOfNestedAnonymousClass;\n"
+ " } nestedOfNestedAnonymousClass;\n"
+ " };\n"
+ " void fun()\n"
+ " {\n"
+ " @\n"
+ " }\n"
+ "};\n"
+ ) << _("nestedOfNestedAnonymousClass.") << (QStringList()
+ << QLatin1String("memberOfNestedOfNestedAnonymousClass"));
+
QTest::newRow("crash_cloning_template_class_QTCREATORBUG9329") << _(
"struct A {};\n"
"template <typename T>\n"
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index c65c0f22ef..d0eb4af103 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -1554,25 +1554,44 @@ void CppCompletionAssistProcessor::completeClass(CPlusPlus::ClassOrNamespace *b,
if (staticLookup)
addCompletionItem(scope, InjectedClassNameOrder); // add a completion item for the injected class name.
- for (Scope::iterator it = scope->firstMember(); it != scope->lastMember(); ++it) {
- Symbol *member = *it;
- if (member->isFriend()
- || member->isQtPropertyDeclaration()
- || member->isQtEnum()) {
- continue;
- } else if (!staticLookup && (member->isTypedef() ||
- member->isEnum() ||
- member->isClass())) {
- continue;
- }
+ addClassMembersToCompletion(scope, staticLookup);
+ }
+ }
+}
- if (member->isPublic())
- addCompletionItem(member, PublicClassMemberOrder);
- else
- addCompletionItem(member);
- }
+void CppCompletionAssistProcessor::addClassMembersToCompletion(Scope *scope, bool staticLookup)
+{
+ if (!scope)
+ return;
+
+ std::set<Class *> nestedAnonymouses;
+
+ for (Scope::iterator it = scope->firstMember(); it != scope->lastMember(); ++it) {
+ Symbol *member = *it;
+ if (member->isFriend()
+ || member->isQtPropertyDeclaration()
+ || member->isQtEnum()) {
+ continue;
+ } else if (!staticLookup && (member->isTypedef() ||
+ member->isEnum() ||
+ member->isClass())) {
+ continue;
+ } else if (member->isClass() && member->name()->isAnonymousNameId()) {
+ nestedAnonymouses.insert(member->asClass());
+ } else if (member->isDeclaration()) {
+ Class *declTypeAsClass = member->asDeclaration()->type()->asClassType();
+ if (declTypeAsClass && declTypeAsClass->name()->isAnonymousNameId())
+ nestedAnonymouses.erase(declTypeAsClass);
}
+
+ if (member->isPublic())
+ addCompletionItem(member, PublicClassMemberOrder);
+ else
+ addCompletionItem(member);
}
+ std::set<Class *>::const_iterator citEnd = nestedAnonymouses.end();
+ for (std::set<Class *>::const_iterator cit = nestedAnonymouses.begin(); cit != citEnd; ++cit)
+ addClassMembersToCompletion(*cit, staticLookup);
}
bool CppCompletionAssistProcessor::completeQtMethod(const QList<CPlusPlus::LookupItem> &results, bool wantSignals)
diff --git a/src/plugins/cpptools/cppcompletionassist.h b/src/plugins/cpptools/cppcompletionassist.h
index 0e0268b74b..ae2e45a23e 100644
--- a/src/plugins/cpptools/cppcompletionassist.h
+++ b/src/plugins/cpptools/cppcompletionassist.h
@@ -136,6 +136,7 @@ private:
bool completeScope(const QList<CPlusPlus::LookupItem> &results);
void completeNamespace(CPlusPlus::ClassOrNamespace *binding);
void completeClass(CPlusPlus::ClassOrNamespace *b, bool staticLookup = true);
+ void addClassMembersToCompletion(CPlusPlus::Scope *scope, bool staticLookup);
bool completeQtMethod(const QList<CPlusPlus::LookupItem> &results, bool wantSignals);
bool completeSignal(const QList<CPlusPlus::LookupItem> &results)
{ return completeQtMethod(results, true); }