Commit 798d84b3 authored by Przemyslaw Gorszkowski's avatar Przemyslaw Gorszkowski Committed by Erik Verbruggen

C++: fix 'using' for templates in typedefs

Fix resolving typedef of templates which is from different namespace
and there was 'using' used for it.
Examples are in tests.
Another step to bring code completion for stl containters.

Task-number: QTCREATORBUG-7978

Change-Id: I2e9e71b45d60536c1e25cf2d371c4719b15edf79
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent ea321915
......@@ -752,6 +752,12 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
const TemplateNameId *templId = name->asTemplateNameId();
if (templId) {
// for "using" we should use the real one ClassOrNamespace(it should be the first
// one item from usings list)
// we indicate that it is a 'using' by checking number of symbols(it should be 0)
if (reference->symbols().count() == 0 && reference->usings().count() != 0)
reference = reference->_usings[0];
// if it is a TemplateNameId it could be a specialization(full or partial) or
// instantiation of one of the specialization(reference->_specialization) or
// base class(reference)
......
......@@ -835,8 +835,9 @@ public:
void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding)
{
QSet<Symbol *> visited;
_binding = binding;
while (NamedType *namedTy = getNamedType(*type)) {
QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, binding);
QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
#ifdef DEBUG_LOOKUP
qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
......@@ -908,7 +909,7 @@ private:
}
bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
Scope **scope, QSet<Symbol *>& visited) const
Scope **scope, QSet<Symbol *>& visited)
{
bool foundTypedef = false;
foreach (const LookupItem &it, namedTypeItems) {
......@@ -921,6 +922,7 @@ private:
// continue working with the typedefed type and scope
*type = declaration->type();
*scope = it.scope();
_binding = it.binding();
foundTypedef = true;
break;
}
......@@ -930,6 +932,8 @@ private:
}
const LookupContext &_context;
// binding has to be remembered in case of resolving typedefs for templates
ClassOrNamespace *_binding;
};
ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
......
......@@ -1646,3 +1646,108 @@ void CppToolsPlugin::test_completion_template_specialization_with_pointer()
QVERIFY(completions.contains(QLatin1String("Template")));
QVERIFY(completions.contains(QLatin1String("pointer")));
}
void CppToolsPlugin::test_completion_typedef_using_templates1()
{
TestData data;
data.srcText = "\n"
"namespace NS1\n"
"{\n"
"template<typename T>\n"
"struct NS1Struct\n"
"{\n"
" typedef T *pointer;\n"
" pointer bar;\n"
"};\n"
"}\n"
"namespace NS2\n"
"{\n"
"using NS1::NS1Struct;\n"
"\n"
"template <typename T>\n"
"struct NS2Struct\n"
"{\n"
" typedef NS1Struct<T> NS1StructTypedef;\n"
" typedef typename NS1StructTypedef::pointer pointer;\n"
" pointer p;\n"
"};\n"
"}\n"
"struct Foo\n"
"{\n"
" int bar;\n"
"};\n"
"void fun()\n"
"{\n"
" NS2::NS2Struct<Foo> s;\n"
" @\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("s.p->");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 2);
QVERIFY(completions.contains(QLatin1String("Foo")));
QVERIFY(completions.contains(QLatin1String("bar")));
}
void CppToolsPlugin::test_completion_typedef_using_templates2()
{
TestData data;
data.srcText = "\n"
"namespace NS1\n"
"{\n"
"template<typename T>\n"
"struct NS1Struct\n"
"{\n"
" typedef T *pointer;\n"
" pointer bar;\n"
"};\n"
"}\n"
"namespace NS2\n"
"{\n"
"using NS1::NS1Struct;\n"
"\n"
"template <typename T>\n"
"struct NS2Struct\n"
"{\n"
" typedef NS1Struct<T> NS1StructTypedef;\n"
" typedef typename NS1StructTypedef::pointer pointer;\n"
" pointer p;\n"
"};\n"
"}\n"
"struct Foo\n"
"{\n"
" int bar;\n"
"};\n"
"void fun()\n"
"{\n"
" NS2::NS2Struct<Foo>::pointer p;\n"
" @\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("p->");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 2);
QVERIFY(completions.contains(QLatin1String("Foo")));
QVERIFY(completions.contains(QLatin1String("bar")));
}
......@@ -124,6 +124,8 @@ private slots:
void test_completion_typedef_is_inside_function_before_declaration_block();
void test_completion_resolve_complex_typedef_with_template();
void test_completion_template_specialization_with_pointer();
void test_completion_typedef_using_templates1();
void test_completion_typedef_using_templates2();
void test_format_pointerdeclaration_in_simpledeclarations();
void test_format_pointerdeclaration_in_simpledeclarations_data();
......
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