CppEditor: Fix quickfix for adding include for static functions

Task-number: QTCREATORBUG-14499
Change-Id: Id3e962ed310f43c33b91c7834a1f9ca074519a38
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Przemyslaw Gorszkowski
2017-06-19 18:51:26 +02:00
parent a9eb1d39c8
commit c6771c39c1
2 changed files with 75 additions and 28 deletions

View File

@@ -236,7 +236,6 @@ QuickFixOperationTest::QuickFixOperationTest(const QList<QuickFixTestDocument::P
QuickFixOperations operations; QuickFixOperations operations;
factory->match(quickFixInterface, operations); factory->match(quickFixInterface, operations);
if (operations.isEmpty()) { if (operations.isEmpty()) {
QEXPECT_FAIL("onBaseOfQualifiedClassName", "QTCREATORBUG-14499", Continue);
QVERIFY(testDocuments.first()->m_expectedSource.isEmpty()); QVERIFY(testDocuments.first()->m_expectedSource.isEmpty());
return; return;
} }
@@ -3031,6 +3030,37 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_data()
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
// Header File
original = "template <typename T> class Foo { static void bar() {} };\n";
expected = original;
testDocuments << QuickFixTestDocument::create("afile.h", original, expected);
// Source File
original =
"#include \"header.h\"\n"
"\n"
"void f()\n"
"{\n"
" @Foo<int>::bar();\n"
"}\n"
;
expected =
"#include \"afile.h\"\n"
"#include \"header.h\"\n"
"\n"
"void f()\n"
"{\n"
" Foo<int>::bar();\n"
"}\n"
;
testDocuments << QuickFixTestDocument::create("afile.cpp", original, expected);
QTest::newRow("onBaseOfQualifiedTemplateClassName")
<< TestIncludePaths::globalIncludePath()
<< testDocuments << firstRefactoringOperation << "";
testDocuments.clear();
// -------------------------------------------------------------------------------------------
// Header File // Header File
original = "namespace N { template <typename T> class Foo {}; }\n"; original = "namespace N { template <typename T> class Foo {}; }\n";
expected = original; expected = original;

View File

@@ -1872,24 +1872,6 @@ QString templateNameAsString(const TemplateNameId *templateName)
return QString::fromUtf8(id->chars(), id->size()); 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()) {
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);
}
}
Snapshot forwardingHeaders(const CppQuickFixInterface &interface) Snapshot forwardingHeaders(const CppQuickFixInterface &interface)
{ {
Snapshot result; Snapshot result;
@@ -1909,6 +1891,44 @@ bool looksLikeAQtClass(const QString &identifier)
&& identifier.at(1).isUpper(); && identifier.at(1).isUpper();
} }
bool matchName(const Name *name, QList<Core::LocatorFilterEntry> *matches, QString *className) {
if (!name)
return false;
if (CppClassesFilter *classesFilter
= ExtensionSystem::PluginManager::getObject<CppClassesFilter>()) {
QFutureInterface<Core::LocatorFilterEntry> dummy;
const Overview oo;
if (const QualifiedNameId *qualifiedName = name->asQualifiedNameId()) {
const Name *name = qualifiedName->name();
if (const TemplateNameId *templateName = name->asTemplateNameId()) {
*className = templateNameAsString(templateName);
} else {
*className = oo.prettyName(name);
*matches = classesFilter->matchesFor(dummy, *className);
if (matches->empty()) {
if (const Name *name = qualifiedName->base()) {
if (const TemplateNameId *templateName = name->asTemplateNameId())
*className = templateNameAsString(templateName);
else
*className = oo.prettyName(name);
}
}
}
} else if (const TemplateNameId *templateName = name->asTemplateNameId()) {
*className = templateNameAsString(templateName);
} else {
*className = oo.prettyName(name);
}
if (matches->empty())
*matches = classesFilter->matchesFor(dummy, *className);
}
return !matches->empty();
}
} // anonymous namespace } // anonymous namespace
void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interface, void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interface,
@@ -1921,20 +1941,14 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
if (canLookupDefinition(interface, nameAst)) if (canLookupDefinition(interface, nameAst))
return; return;
const QString className = unqualifiedNameForLocator(nameAst->name); QString className;
if (className.isEmpty()) QList<Core::LocatorFilterEntry> matches;
return;
const QString currentDocumentFilePath = interface.semanticInfo().doc->fileName(); const QString currentDocumentFilePath = interface.semanticInfo().doc->fileName();
const ProjectPartHeaderPaths headerPaths = relevantHeaderPaths(currentDocumentFilePath); const ProjectPartHeaderPaths headerPaths = relevantHeaderPaths(currentDocumentFilePath);
bool qtHeaderFileIncludeOffered = false; bool qtHeaderFileIncludeOffered = false;
// Find an include file through the locator // Find an include file through the locator
if (CppClassesFilter *classesFilter if (matchName(nameAst->name, &matches, &className)) {
= ExtensionSystem::PluginManager::getObject<CppClassesFilter>()) {
QFutureInterface<Core::LocatorFilterEntry> dummy;
const QList<Core::LocatorFilterEntry> matches = classesFilter->matchesFor(dummy, className);
const Snapshot forwardHeaders = forwardingHeaders(interface); const Snapshot forwardHeaders = forwardingHeaders(interface);
foreach (const Core::LocatorFilterEntry &entry, matches) { foreach (const Core::LocatorFilterEntry &entry, matches) {
IndexItem::Ptr info = entry.internalData.value<IndexItem::Ptr>(); IndexItem::Ptr info = entry.internalData.value<IndexItem::Ptr>();
@@ -1971,6 +1985,9 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
} }
} }
if (className.isEmpty())
return;
// The header file we are looking for might not be (yet) included in any file we have parsed. // The header file we are looking for might not be (yet) included in any file we have parsed.
// As such, it will not be findable via locator. At least for Qt classes, check also for // As such, it will not be findable via locator. At least for Qt classes, check also for
// headers with the same name. // headers with the same name.