Commit 2db588f8 authored by Nikolai Kosjar's avatar Nikolai Kosjar

CppEditor: Make AddIncludeForUndefinedIdentifier work on template name ids

Task-number: QTCREATORBUG-9704
Change-Id: Ib08c331364fbfcb6e3fb9971d45e8b27311143ae
Reviewed-by: default avatarChristian Stenger <christian.stenger@digia.com>
parent 57279c0d
......@@ -151,6 +151,8 @@ private slots:
void test_quickfix_AddIncludeForUndefinedIdentifier_onSimpleName();
void test_quickfix_AddIncludeForUndefinedIdentifier_onNameOfQualifiedName();
void test_quickfix_AddIncludeForUndefinedIdentifier_onBaseOfQualifiedName();
void test_quickfix_AddIncludeForUndefinedIdentifier_onTemplateName();
void test_quickfix_AddIncludeForUndefinedIdentifier_onTemplateNameInsideArguments();
void test_quickfix_AddIncludeForUndefinedIdentifier_inserting_ignoremoc();
void test_quickfix_AddIncludeForUndefinedIdentifier_inserting_sortingTop();
void test_quickfix_AddIncludeForUndefinedIdentifier_inserting_sortingMiddle();
......
......@@ -2325,6 +2325,84 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_onBaseOfQua
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_onTemplateName()
{
QList<QuickFixTestDocument::Ptr> testFiles;
QByteArray original;
QByteArray expected;
// Header File
original = "namespace N { template <typename T> class Foo {}; }\n";
expected = original;
testFiles << QuickFixTestDocument::create(TestIncludePaths::directoryOfTestFile().toUtf8()
+ "/afile.h", original, expected);
// Source File
original =
"#include \"header.h\"\n"
"\n"
"void f()\n"
"{\n"
" @N::Foo<Bar> foo;\n"
"}\n"
;
expected =
"#include \"afile.h\"\n"
"#include \"header.h\"\n"
"\n"
"void f()\n"
"{\n"
" N::Foo<Bar> foo;\n"
"}\n"
;
testFiles << QuickFixTestDocument::create(TestIncludePaths::directoryOfTestFile().toUtf8()
+ "/afile.cpp", original, expected);
// Do not use the test factory, at least once we want to go through the "full stack".
AddIncludeForUndefinedIdentifier factory;
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_onTemplateNameInsideArguments()
{
QList<QuickFixTestDocument::Ptr> testFiles;
QByteArray original;
QByteArray expected;
// Header File
original = "namespace N { template <typename T> class Foo {}; }\n";
expected = original;
testFiles << QuickFixTestDocument::create(TestIncludePaths::directoryOfTestFile().toUtf8()
+ "/afile.h", original, expected);
// Source File
original =
"#include \"header.h\"\n"
"\n"
"void f()\n"
"{\n"
" N::Bar<@Foo> foo;\n"
"}\n"
;
expected =
"#include \"afile.h\"\n"
"#include \"header.h\"\n"
"\n"
"void f()\n"
"{\n"
" N::Bar<Foo> foo;\n"
"}\n"
;
testFiles << QuickFixTestDocument::create(TestIncludePaths::directoryOfTestFile().toUtf8()
+ "/afile.cpp", original, expected);
// Do not use the test factory, at least once we want to go through the "full stack".
AddIncludeForUndefinedIdentifier factory;
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Ignore *.moc includes
void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_inserting_ignoremoc()
{
......
......@@ -1910,6 +1910,10 @@ NameAST *nameUnderCursor(const QList<AST *> &path)
AST * const ast = path.at(i);
if (SimpleNameAST *simpleName = ast->asSimpleName()) {
nameAst = simpleName;
} else if (TemplateIdAST *templateId = ast->asTemplateId()) {
nameAst = templateId;
} else if (nameAst && ast->asNamedTypeSpecifier()) {
break; // Stop at "Foo" for "N::Bar<@Foo>"
} else if (QualifiedNameAST *qualifiedName = ast->asQualifiedName()) {
nameAst = qualifiedName;
break;
......@@ -1937,15 +1941,28 @@ bool canLookup(const CppQuickFixInterface &interface, const NameAST *nameAst)
return !existingResults.isEmpty();
}
QString unqualifiedName(const Name *name)
QString templateNameAsString(const TemplateNameId *templateName)
{
const Identifier *id = templateName->identifier();
return QString::fromUtf8(id->chars(), id->size());
}
// For templates, simply the name is returned, without '<...>'.
QString unqualifiedNameForLocator(const Name *name)
{
QTC_ASSERT(name, return QString());
const Overview oo;
if (const QualifiedNameId *qualifiedName = name->asQualifiedNameId())
return oo.prettyName(qualifiedName->name());
else
if (const QualifiedNameId *qualifiedName = name->asQualifiedNameId()) {
const Name *name = qualifiedName->name();
if (const TemplateNameId *templateName = name->asTemplateNameId())
return templateNameAsString(templateName);
return oo.prettyName(name);
} else if (const TemplateNameId *templateName = name->asTemplateNameId()) {
return templateNameAsString(templateName);
} else {
return oo.prettyName(name);
}
}
} // anonymous namespace
......@@ -1964,7 +1981,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
if (canLookup(interface, nameAst))
return; // There are results, so include isn't needed
const QString className = unqualifiedName(nameAst->name);
const QString className = unqualifiedNameForLocator(nameAst->name);
if (className.isEmpty())
return;
......
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