Commit 3d33886e authored by Erik Verbruggen's avatar Erik Verbruggen

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: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent 76152088
......@@ -427,7 +427,10 @@ void AutotoolsProject::updateCppCodeModel()
foreach (const QString &file, m_files)
part->files << CppTools::ProjectFile(file, CppTools::ProjectFile::CXXSource);
part->includePaths += m_makefileParserThread->includePaths();
foreach (const QString &inc, m_makefileParserThread->includePaths()) {
part->headerPaths += CppTools::ProjectPart::HeaderPath(
inc, CppTools::ProjectPart::HeaderPath::IncludePath);
}
part->projectDefines += m_makefileParserThread->defines();
pinfo.appendProjectPart(part);
......
......@@ -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);
}
......
......@@ -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;
};
......
......@@ -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:";
......
......@@ -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();
......
......@@ -338,27 +338,32 @@ bool CMakeProject::parseCMakeLists()
CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
pinfo.clearProjectParts();
CppTools::ProjectPart::Ptr part(new CppTools::ProjectPart);
typedef CppTools::ProjectPart ProjectPart;
ProjectPart::Ptr part(new ProjectPart);
part->project = this;
part->displayName = displayName();
part->projectFile = projectFilePath().toString();
// This explicitly adds -I. to the include paths
part->includePaths += projectDirectory().toString();
part->headerPaths += ProjectPart::HeaderPath(projectDirectory().toString(),
ProjectPart::HeaderPath::IncludePath);
foreach (const QString &includeFile, cbpparser.includeFiles()) {
ProjectPart::HeaderPath hp(includeFile, ProjectPart::HeaderPath::IncludePath);
// CodeBlocks is utterly ignorant of frameworks on Mac, and won't report framework
// paths. The work-around is to check if the include path ends in ".framework", and
// if so, add the parent directory as framework path.
if (includeFile.endsWith(QLatin1String(".framework"))) {
const int slashIdx = includeFile.lastIndexOf(QLatin1Char('/'));
if (slashIdx != -1) {
part->frameworkPaths += includeFile.left(slashIdx);
hp = ProjectPart::HeaderPath(includeFile.left(slashIdx),
ProjectPart::HeaderPath::FrameworkPath);
continue;
}
}
part->includePaths += includeFile;
part->headerPaths += hp;
}
part->projectDefines += cbpparser.defines();
......
......@@ -1446,7 +1446,7 @@ void CppCodeModelInspectorDialog::refresh()
}
// Merged entities
dumper.dumpMergedEntities(cmmi->includePaths(), cmmi->frameworkPaths(), cmmi->definedMacros());
dumper.dumpMergedEntities(cmmi->headerPaths(), cmmi->definedMacros());
}
enum DocumentTabs {
......@@ -1559,8 +1559,7 @@ enum ProjectPartTabs {
ProjectPartGeneralTab,
ProjectPartFilesTab,
ProjectPartDefinesTab,
ProjectPartIncludePathsTab,
ProjectPartFrameworkPathsTab,
ProjectPartHeaderPathsTab,
ProjectPartPrecompiledHeadersTab
};
......@@ -1570,8 +1569,7 @@ static QString partTabName(int tabIndex, int numberOfEntries = -1)
"&General",
"Project &Files",
"&Defines",
"&Include Paths",
"F&ramework Paths",
"&Header Paths",
"Pre&compiled Headers"
};
QString result = QLatin1String(names[tabIndex]);
......@@ -1591,13 +1589,9 @@ void CppCodeModelInspectorDialog::clearProjectPartData()
m_ui->partProjectDefinesEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab, partTabName(ProjectPartDefinesTab));
m_ui->partIncludePathsEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartIncludePathsTab,
partTabName(ProjectPartIncludePathsTab));
m_ui->partFrameworkPathsEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartFrameworkPathsTab,
partTabName(ProjectPartFrameworkPathsTab));
m_ui->partHeaderPathsEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
partTabName(ProjectPartHeaderPathsTab));
m_ui->partPrecompiledHeadersEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartPrecompiledHeadersTab,
......@@ -1654,15 +1648,10 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab,
partTabName(ProjectPartDefinesTab, numberOfDefines));
// Include Paths
m_ui->partIncludePathsEdit->setPlainText(CMI::Utils::pathListToString(part->includePaths));
m_ui->projectPartTab->setTabText(ProjectPartIncludePathsTab,
partTabName(ProjectPartIncludePathsTab, part->includePaths.size()));
// Framework Paths
m_ui->partFrameworkPathsEdit->setPlainText(CMI::Utils::pathListToString(part->frameworkPaths));
m_ui->projectPartTab->setTabText(ProjectPartFrameworkPathsTab,
partTabName(ProjectPartFrameworkPathsTab, part->frameworkPaths.size()));
// Header Paths
m_ui->partHeaderPathsEdit->setPlainText(CMI::Utils::pathListToString(part->headerPaths));
m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
partTabName(ProjectPartHeaderPathsTab, part->headerPaths.size()));
// Precompiled Headers
m_ui->partPrecompiledHeadersEdit->setPlainText(
......
......@@ -261,25 +261,11 @@
</widget>
<widget class="QWidget" name="tab_15">
<attribute name="title">
<string notr="true">&amp;Include Paths</string>
<string notr="true">&amp;Header Paths</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_16">
<item>
<widget class="QPlainTextEdit" name="partIncludePathsEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="definesTab_2">
<attribute name="title">
<string notr="true">F&amp;ramework Paths</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
<widget class="QPlainTextEdit" name="partFrameworkPathsEdit">
<widget class="QPlainTextEdit" name="partHeaderPathsEdit">
<property name="readOnly">
<bool>true</bool>
</property>
......
This diff is collapsed.
......@@ -74,10 +74,13 @@ class QuickFixTestCase : public TestCase
public:
QuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &theTestFiles,
CppQuickFixFactory *factory,
const QStringList &includePaths = QStringList(),
const CppTools::ProjectPart::HeaderPaths &includePaths =
CppTools::ProjectPart::HeaderPaths(),
int resultIndex = 0);
~QuickFixTestCase();
static void run(const QList<QuickFixTestDocument::Ptr> &theTestFiles,
CppQuickFixFactory *factory, const QString &incPath);
private:
QSharedPointer<TextEditor::QuickFixOperation> getFix(CppQuickFixFactory *factory,
CPPEditorWidget *editorWidget,
......@@ -89,8 +92,8 @@ private:
CppTools::CppCodeStylePreferences *m_cppCodeStylePreferences;
QByteArray m_cppCodeStylePreferencesOriginalDelegateId;
QStringList m_includePathsToRestore;
bool m_restoreIncludePaths;
CppTools::ProjectPart::HeaderPaths m_headerPathsToRestore;
bool m_restoreHeaderPaths;
};
QList<QuickFixTestDocument::Ptr> singleDocument(const QByteArray &original,
......
......@@ -1896,7 +1896,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
return;
// find the include paths
QStringList includePaths;
ProjectPart::HeaderPaths headerPaths;
CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
QList<CppModelManagerInterface::ProjectInfo> projectInfos = modelManager->projectInfos();
bool inProject = false;
......@@ -1905,14 +1905,14 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
foreach (const ProjectFile &file, part->files) {
if (file.path == doc->fileName()) {
inProject = true;
includePaths += part->includePaths;
headerPaths += part->headerPaths;
}
}
}
}
if (!inProject) {
// better use all include paths than none
includePaths = modelManager->includePaths();
headerPaths = modelManager->headerPaths();
}
// find a include file through the locator
......@@ -1933,10 +1933,10 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
if (fileInfo.path() == QFileInfo(doc->fileName()).path()) {
shortestInclude = QLatin1Char('"') + fileInfo.fileName() + QLatin1Char('"');
} else {
foreach (const QString &includePath, includePaths) {
if (!fileName.startsWith(includePath))
foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) {
if (!fileName.startsWith(headerPath.path))
continue;
QString relativePath = fileName.mid(includePath.size());
QString relativePath = fileName.mid(headerPath.path.size());
if (!relativePath.isEmpty() && relativePath.at(0) == QLatin1Char('/'))
relativePath = relativePath.mid(1);
if (shortestInclude.isEmpty() || relativePath.size() + 2 < shortestInclude.size())
......@@ -1965,11 +1965,11 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
// otherwise, check for a header file with the same name in the Qt include paths
} else {
foreach (const QString &includePath, includePaths) {
if (!includePath.contains(QLatin1String("/Qt"))) // "QtCore", "QtGui" etc...
foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) {
if (!headerPath.path.contains(QLatin1String("/Qt"))) // "QtCore", "QtGui" etc...
continue;
const QString headerPathCandidate = includePath + QLatin1Char('/') + className;
const QString headerPathCandidate = headerPath.path + QLatin1Char('/') + className;
const QFileInfo fileInfo(headerPathCandidate);
if (fileInfo.exists() && fileInfo.isFile()) {
const QString include = QLatin1Char('<') + className + QLatin1Char('>');
......
......@@ -51,7 +51,7 @@ static void parse(QFutureInterface<void> &future,
bool processingHeaders = false;
CppModelManager *cmm = CppModelManager::instance();
const QStringList fallbackIncludePaths = cmm->includePaths();
const ProjectPart::HeaderPaths fallbackHeaderPaths = cmm->headerPaths();
for (int i = 0; i < files.size(); ++i) {
if (future.isPaused())
future.waitForResume();
......@@ -71,10 +71,10 @@ static void parse(QFutureInterface<void> &future,
}
QList<ProjectPart::Ptr> parts = cmm->projectPart(fileName);
QStringList includePaths = parts.isEmpty()
? fallbackIncludePaths
: parts.first()->includePaths;
sourceProcessor->setIncludePaths(includePaths);
ProjectPart::HeaderPaths headerPaths = parts.isEmpty()
? fallbackHeaderPaths
: parts.first()->headerPaths;
sourceProcessor->setHeaderPaths(headerPaths);
sourceProcessor->run(fileName);
future.setProgressValue(files.size() - sourceProcessor->todo().size());
......@@ -190,8 +190,7 @@ QFuture<void> BuiltinIndexingSupport::refreshSourceFiles(const QStringList &sour
CppSourceProcessor *preproc = CppModelManager::createSourceProcessor();
preproc->setDumpFileNameWhileParsing(m_dumpFileNameWhileParsing);
preproc->setRevision(++m_revision);
preproc->setIncludePaths(mgr->includePaths());
preproc->setFrameworkPaths(mgr->frameworkPaths());
preproc->setHeaderPaths(mgr->headerPaths());
preproc->setWorkingCopy(workingCopy);
QFuture<void> result = QtConcurrent::run(&parse, preproc, sourceFiles);
......
......@@ -413,6 +413,18 @@ QString Utils::pathListToString(const QStringList &pathList)
return result.join(QLatin1String("\n"));
}
QString Utils::pathListToString(const ProjectPart::HeaderPaths &pathList)
{
QStringList result;
foreach (const ProjectPart::HeaderPath &path, pathList) {
result << QString(QLatin1String("%1 (%2 path)")).arg(
QDir::toNativeSeparators(path.path),
path.isFrameworkPath() ? QLatin1String("framework") : QLatin1String("include")
);
}
return result.join(QLatin1String("\n"));
}
QList<CPlusPlus::Document::Ptr> Utils::snapshotToList(const CPlusPlus::Snapshot &snapshot)
{
QList<CPlusPlus::Document::Ptr> documents;
......@@ -511,16 +523,14 @@ void Dumper::dumpProjectInfos( const QList<CppModelManagerInterface::ProjectInfo
m_out << i4 << defineLine << "\n";
}
if (!part->includePaths.isEmpty()) {
m_out << i3 << "Include Paths:{{{4\n";
foreach (const QString &includePath, part->includePaths)
m_out << i4 << includePath << "\n";
}
if (!part->frameworkPaths.isEmpty()) {
m_out << i3 << "Framework Paths:{{{4\n";
foreach (const QString &frameworkPath, part->frameworkPaths)
m_out << i4 << frameworkPath << "\n";
if (!part->headerPaths.isEmpty()) {
m_out << i3 << "Header Paths:{{{4\n";
foreach (const ProjectPart::HeaderPath &headerPath, part->headerPaths)
m_out << i4 << headerPath.path
<< (headerPath.type == ProjectPart::HeaderPath::IncludePath
? "(include path)"
: "(framework path)")
<< "\n";
}
if (!part->precompiledHeaders.isEmpty()) {
......@@ -582,18 +592,18 @@ void Dumper::dumpWorkingCopy(const CppModelManagerInterface::WorkingCopy &workin
}
}
void Dumper::dumpMergedEntities(const QStringList &mergedIncludePaths,
const QStringList &mergedFrameworkPaths,
void Dumper::dumpMergedEntities(const ProjectPart::HeaderPaths &mergedHeaderPaths,
const QByteArray &mergedMacros)
{
m_out << "Merged Entities{{{1\n";
const QByteArray i2 = indent(2);
const QByteArray i3 = indent(3);
m_out << i2 << "Merged Include Paths{{{2\n";
dumpStringList(mergedIncludePaths, i3);
m_out << i2 << "Merged Framework Paths{{{2\n";
dumpStringList(mergedFrameworkPaths, i3);
m_out << i2 << "Merged Header Paths{{{2\n";
foreach (const ProjectPart::HeaderPath &hp, mergedHeaderPaths)
m_out << i3 << hp.path
<< (hp.isFrameworkPath() ? " (framework path)" : " (include path)")
<< "\n";
m_out << i2 << "Merged Defines{{{2\n";
m_out << mergedMacros;
}
......
......@@ -58,6 +58,7 @@ struct CPPTOOLS_EXPORT Utils
static QString partsForFile(const QString &fileName);
static QString unresolvedFileNameWithDelimiters(const CPlusPlus::Document::Include &include);
static QString pathListToString(const QStringList &pathList);
static QString pathListToString(const ProjectPart::HeaderPaths &pathList);
static QList<CPlusPlus::Document::Ptr> snapshotToList(const CPlusPlus::Snapshot &snapshot);
};
......@@ -73,8 +74,7 @@ public:
const QString &title,
bool isGlobalSnapshot = false);
void dumpWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy);
void dumpMergedEntities(const QStringList &mergedIncludePaths,
const QStringList &mergedFrameworkPaths,
void dumpMergedEntities(const ProjectPart::HeaderPaths &mergedHeaderPaths,
const QByteArray &mergedMacros);
private:
......
......@@ -105,7 +105,7 @@ public:
= new CppCompletionAssistInterface(m_editorWidget->document(), m_position,
m_editorWidget->baseTextDocument()->filePath(),
ExplicitlyInvoked, m_snapshot,
QStringList(), QStringList());
ProjectPart::HeaderPaths());
CppCompletionAssistProcessor processor;
IAssistProposal *proposal = processor.perform(ai);
if (!proposal)
......
......@@ -1139,30 +1139,23 @@ bool CppCompletionAssistProcessor::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;
}
completeInclude(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");
}
completeInclude(realPath, suffixes);
}
......@@ -1969,8 +1962,7 @@ void CppCompletionAssistInterface::getCppSpecifics() const
if (QSharedPointer<SnapshotUpdater> updater = supp->snapshotUpdater()) {
updater->update(m_workingCopy);
m_snapshot = updater->snapshot();
m_includePaths = updater->includePaths();
m_frameworkPaths = updater->frameworkPaths();
m_headerPaths = updater->headerPaths();
}
}
}
......@@ -191,22 +191,20 @@ public:
const QString &fileName,
TextEditor::AssistReason reason,
const CPlusPlus::Snapshot &snapshot,
const QStringList &includePaths,
const QStringList &frameworkPaths)
const ProjectPart::HeaderPaths &headerPaths)
: TextEditor::DefaultAssistInterface(textDocument, position, fileName, reason)
, m_editor(0)
, m_isObjCEnabled(false)
, m_gotCppSpecifics(true)
, m_snapshot(snapshot)
, m_includePaths(includePaths)
, m_frameworkPaths(frameworkPaths)
, m_headerPaths(headerPaths)
{}
bool isObjCEnabled() const { return m_isObjCEnabled; }
const CPlusPlus::Snapshot &snapshot() const { getCppSpecifics(); return m_snapshot; }
const QStringList &includePaths() const { getCppSpecifics(); return m_includePaths; }
const<