diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2020-06-04 16:16:57 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2020-06-05 14:56:21 +0000 |
commit | e100939ba7876c04190646f92a1070502a991ece (patch) | |
tree | 3f06583f0207b7278a0e580098f5cb0642b2ee18 /src/plugins/cppeditor/cppquickfixes.cpp | |
parent | d811e7773f7d7431fe58fd997da1a3a15ba53f85 (diff) |
CppEditor: Extend "Add Include" quickfix
... so it works for all kinds of symbols, not just Qt classes.
Fixes: QTCREATORBUG-21
Change-Id: I2d329c09b64cd8f7eef8cce7d9f022aca8586c0d
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/cppeditor/cppquickfixes.cpp')
-rw-r--r-- | src/plugins/cppeditor/cppquickfixes.cpp | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 1753f9ff07..149d102396 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -58,6 +58,7 @@ #include <projectexplorer/projectnodes.h> #include <projectexplorer/projecttree.h> +#include <utils/algorithm.h> #include <utils/fancylineedit.h> #include <utils/fileutils.h> #include <utils/qtcassert.h> @@ -1916,25 +1917,20 @@ QString findShortestInclude(const QString currentDocumentFilePath, return result; } -QString findQtIncludeWithSameName(const QString &className, - const ProjectExplorer::HeaderPaths &headerPaths) +QString findMatchingInclude(const QString &className, + const ProjectExplorer::HeaderPaths &headerPaths) { - QString result; - - // Check for a header file with the same name in the Qt include paths - foreach (const ProjectExplorer::HeaderPath &headerPath, headerPaths) { - if (!headerPath.path.contains(QLatin1String("/Qt"))) // "QtCore", "QtGui" etc... - continue; - - const QString headerPathCandidate = headerPath.path + QLatin1Char('/') + className; - const QFileInfo fileInfo(headerPathCandidate); - if (fileInfo.exists() && fileInfo.isFile()) { - result = QLatin1Char('<') + className + QLatin1Char('>'); - break; + const QStringList candidateFileNames{className, className + ".h", className + ".hpp", + className.toLower(), className.toLower() + ".h", className.toLower() + ".hpp"}; + for (const QString &fileName : candidateFileNames) { + for (const ProjectExplorer::HeaderPath &headerPath : headerPaths) { + const QString headerPathCandidate = headerPath.path + QLatin1Char('/') + fileName; + const QFileInfo fileInfo(headerPathCandidate); + if (fileInfo.exists() && fileInfo.isFile()) + return '<' + fileName + '>'; } } - - return result; + return {}; } ProjectExplorer::HeaderPaths relevantHeaderPaths(const QString &filePath) @@ -2030,17 +2026,11 @@ Snapshot forwardingHeaders(const CppQuickFixInterface &interface) return result; } -bool looksLikeAQtClass(const QString &identifier) -{ - return identifier.size() > 2 - && identifier.at(0) == QLatin1Char('Q') - && identifier.at(1).isUpper(); -} - bool matchName(const Name *name, QList<Core::LocatorFilterEntry> *matches, QString *className) { if (!name) return false; + QString simpleName; if (Core::ILocatorFilter *classesFilter = CppTools::CppModelManager::instance()->classesFilter()) { QFutureInterface<Core::LocatorFilterEntry> dummy; @@ -2051,7 +2041,8 @@ bool matchName(const Name *name, QList<Core::LocatorFilterEntry> *matches, QStri if (const TemplateNameId *templateName = name->asTemplateNameId()) { *className = templateNameAsString(templateName); } else { - *className = oo.prettyName(name); + simpleName = oo.prettyName(name); + *className = simpleName; *matches = classesFilter->matchesFor(dummy, *className); if (matches->empty()) { if (const Name *name = qualifiedName->base()) { @@ -2070,6 +2061,8 @@ bool matchName(const Name *name, QList<Core::LocatorFilterEntry> *matches, QStri if (matches->empty()) *matches = classesFilter->matchesFor(dummy, *className); + if (matches->empty() && !simpleName.isEmpty()) + *className = simpleName; } return !matches->empty(); @@ -2092,7 +2085,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa QList<Core::LocatorFilterEntry> matches; const QString currentDocumentFilePath = interface.semanticInfo().doc->fileName(); const ProjectExplorer::HeaderPaths headerPaths = relevantHeaderPaths(currentDocumentFilePath); - bool qtHeaderFileIncludeOffered = false; + QList<Utils::FilePath> headers; // Find an include file through the locator if (matchName(nameAst->name, &matches, &className)) { @@ -2124,11 +2117,9 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa else if (headerFileName.at(1).isUpper()) priority = 1; - if (looksLikeAQtClass(include.mid(1, include.size() - 2))) - qtHeaderFileIncludeOffered = true; - result << new AddIncludeForUndefinedIdentifierOp(interface, priority, include); + headers << header; } } } @@ -2158,12 +2149,16 @@ 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. - // As such, it will not be findable via locator. At least for Qt classes, check also for - // headers with the same name. - if (!qtHeaderFileIncludeOffered && looksLikeAQtClass(className)) { - const QString include = findQtIncludeWithSameName(className, headerPaths); - if (!include.isEmpty()) + // Fallback: Check the include paths for files that look like candidates + // for the given name. + if (!Utils::contains(headers, + [&className](const Utils::FilePath &fp) { return fp.fileName() == className; })) { + const QString include = findMatchingInclude(className, headerPaths); + const auto matcher = [&include](const QuickFixOperation::Ptr &o) { + const auto includeOp = o.dynamicCast<AddIncludeForUndefinedIdentifierOp>(); + return includeOp && includeOp->include() == include; + }; + if (!include.isEmpty() && !Utils::contains(result, matcher)) result << new AddIncludeForUndefinedIdentifierOp(interface, 1, include); } } |