C++: fix include/framework path handling.

Instead of having two lists of paths, now only one list is used where
both include paths and framework paths can be mixed. This reflects the
way the compiler is invoked, and retains the (correct) search order.

Task-number: QTCREATORBUG-11599
Change-Id: I373953e3e305df5b7a0d10920e12d146584adf9f
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
Erik Verbruggen
2014-06-25 17:23:19 +02:00
parent 76152088e9
commit 3d33886e53
32 changed files with 353 additions and 370 deletions

View File

@@ -213,7 +213,8 @@ IAssistInterface *ClangCompletionAssistProvider::createAssistInterface(
QList<ProjectPart::Ptr> parts = modelManager->projectPart(fileName);
if (parts.isEmpty())
parts += modelManager->fallbackProjectPart();
QStringList includePaths, frameworkPaths, options;
ProjectPart::HeaderPaths headerPaths;
QStringList options;
PchInfo::Ptr pchInfo;
foreach (ProjectPart::Ptr part, parts) {
if (part.isNull())
@@ -222,15 +223,14 @@ IAssistInterface *ClangCompletionAssistProvider::createAssistInterface(
pchInfo = PchManager::instance()->pchInfo(part);
if (!pchInfo.isNull())
options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName()));
includePaths = part->includePaths;
frameworkPaths = part->frameworkPaths;
headerPaths = part->headerPaths;
break;
}
return new ClangCodeModel::ClangCompletionAssistInterface(
m_clangCompletionWrapper,
document, position, fileName, reason,
options, includePaths, frameworkPaths, pchInfo);
options, headerPaths, pchInfo);
}
// ------------------------
@@ -550,14 +550,12 @@ ClangCompletionAssistInterface::ClangCompletionAssistInterface(ClangCompleter::P
const QString &fileName,
AssistReason reason,
const QStringList &options,
const QStringList &includePaths,
const QStringList &frameworkPaths,
const QList<CppTools::ProjectPart::HeaderPath> &headerPaths,
const PchInfo::Ptr &pchInfo)
: DefaultAssistInterface(document, position, fileName, reason)
, m_clangWrapper(clangWrapper)
, m_options(options)
, m_includePaths(includePaths)
, m_frameworkPaths(frameworkPaths)
, m_headerPaths(headerPaths)
, m_savedPchPointer(pchInfo)
{
Q_ASSERT(!clangWrapper.isNull());
@@ -1138,29 +1136,22 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
}
// Make completion for all relevant includes
QStringList includePaths = m_interface->includePaths();
const QString &currentFilePath = QFileInfo(m_interface->fileName()).path();
if (!includePaths.contains(currentFilePath))
includePaths.append(currentFilePath);
ProjectPart::HeaderPaths headerPaths = m_interface->headerPaths();
const ProjectPart::HeaderPath currentFilePath(QFileInfo(m_interface->fileName()).path(),
ProjectPart::HeaderPath::IncludePath);
if (!headerPaths.contains(currentFilePath))
headerPaths.append(currentFilePath);
const Core::MimeType mimeType = Core::MimeDatabase::findByType(QLatin1String("text/x-c++hdr"));
const QStringList suffixes = mimeType.suffixes();
foreach (const QString &includePath, includePaths) {
QString realPath = includePath;
foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) {
QString realPath = headerPath.path;
if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/');
realPath += directoryPrefix;
}
completeIncludePath(realPath, suffixes);
}
foreach (const QString &frameworkPath, m_interface->frameworkPaths()) {
QString realPath = frameworkPath;
if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/');
realPath += directoryPrefix;
realPath += QLatin1String(".framework/Headers");
if (headerPath.isFrameworkPath())
realPath += QLatin1String(".framework/Headers");
}
completeIncludePath(realPath, suffixes);
}

View File

@@ -35,6 +35,7 @@
#include <cplusplus/Icons.h>
#include <cpptools/cppcompletionassistprovider.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <texteditor/codeassist/basicproposalitem.h>
#include <texteditor/codeassist/completionassistprovider.h>
@@ -76,8 +77,7 @@ public:
const QString &fileName,
TextEditor::AssistReason reason,
const QStringList &options,
const QStringList &includePaths,
const QStringList &frameworkPaths,
const QList<CppTools::ProjectPart::HeaderPath> &headerPaths,
const Internal::PchInfo::Ptr &pchInfo);
ClangCodeModel::ClangCompleter::Ptr clangWrapper() const
@@ -91,16 +91,14 @@ public:
const QStringList &options() const
{ return m_options; }
const QStringList &includePaths() const
{ return m_includePaths; }
const QStringList &frameworkPaths() const
{ return m_frameworkPaths; }
const QList<CppTools::ProjectPart::HeaderPath> &headerPaths() const
{ return m_headerPaths; }
private:
ClangCodeModel::ClangCompleter::Ptr m_clangWrapper;
ClangCodeModel::Internal::UnsavedFiles m_unsavedFiles;
QStringList m_options, m_includePaths, m_frameworkPaths;
QStringList m_options;
QList<CppTools::ProjectPart::HeaderPath> m_headerPaths;
Internal::PchInfo::Ptr m_savedPchPointer;
};

View File

@@ -209,11 +209,20 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind
result << buildDefines(pPart->toolchainDefines, false);
result << buildDefines(pPart->projectDefines, false);
foreach (const QString &frameworkPath, pPart->frameworkPaths)
result.append(QLatin1String("-F") + frameworkPath);
foreach (const QString &inc, pPart->includePaths)
if (!inc.isEmpty() && !isBlacklisted(inc))
result << (QLatin1String("-I") + inc);
typedef ProjectPart::HeaderPath HeaderPath;
foreach (const HeaderPath &headerPath , pPart->headerPaths) {
if (headerPath.path.isEmpty() || isBlacklisted(headerPath.path))
continue;
QString prefix;
switch (headerPath.type) {
case HeaderPath::IncludePath: prefix = QLatin1String("-I"); break;
case HeaderPath::FrameworkPath: prefix = QLatin1String("-F"); break;
default: Q_UNREACHABLE(); break;
}
result.append(prefix + headerPath.path);
}
#if 0
qDebug() << "--- m_args:";

View File

@@ -249,7 +249,8 @@ void PchManager::doPchInfoUpdateNone(QFutureInterface<void> &future,
void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
const PchManager::UpdateParams params)
{
QHash<QString, QSet<QString> > includes, frameworks;
typedef ProjectPart::HeaderPath HeaderPath;
QHash<QString, QSet<HeaderPath>> headers;
QHash<QString, QSet<QByteArray> > definesPerPCH;
QHash<QString, bool> objc;
QHash<QString, bool> cplusplus;
@@ -266,8 +267,7 @@ void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
continue;
inputToParts[pch].append(projectPart);
includes[pch].unite(QSet<QString>::fromList(projectPart->includePaths));
frameworks[pch].unite(QSet<QString>::fromList(projectPart->frameworkPaths));
headers[pch].unite(QSet<HeaderPath>::fromList(projectPart->headerPaths));
cVersions[pch] = std::max(cVersions.value(pch, ProjectPart::C89), projectPart->cVersion);
cxxVersions[pch] = std::max(cxxVersions.value(pch, ProjectPart::CXX98), projectPart->cxxVersion);
cxxExtensionsMap[pch] = cxxExtensionsMap[pch] | projectPart->cxxExtensions;
@@ -306,8 +306,7 @@ void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
projectPart->cVersion = cVersions[pch];
projectPart->cxxVersion = cxxVersions[pch];
projectPart->cxxExtensions = cxxExtensionsMap[pch];
projectPart->includePaths = includes[pch].toList();
projectPart->frameworkPaths = frameworks[pch].toList();
projectPart->headerPaths = headers[pch].toList();
QList<QByteArray> defines = definesPerPCH[pch].toList();
if (!defines.isEmpty()) {
@@ -378,22 +377,20 @@ void PchManager::doPchInfoUpdateCustom(QFutureInterface<void> &future,
future.setProgressRange(0, 1);
future.setProgressValue(0);
QSet<QString> includes, frameworks;
ProjectPart::HeaderPaths headers;
bool objc = false;
bool cplusplus = false;
ProjectPart::Ptr united(new ProjectPart());
united->cxxVersion = ProjectPart::CXX98;
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
includes.unite(QSet<QString>::fromList(projectPart->includePaths));
frameworks.unite(QSet<QString>::fromList(projectPart->frameworkPaths));
headers += projectPart->headerPaths;
united->cVersion = std::max(united->cVersion, projectPart->cVersion);
united->cxxVersion = std::max(united->cxxVersion, projectPart->cxxVersion);
united->qtVersion = std::max(united->qtVersion, projectPart->qtVersion);
objc |= hasObjCFiles(projectPart);
cplusplus |= hasCppFiles(projectPart);
}
united->frameworkPaths = frameworks.toList();
united->includePaths = includes.toList();
united->headerPaths = headers;
QStringList opts = Utils::createClangOptions(
united, getPrefixFileKind(objc, cplusplus));
united.clear();