From e19fa27601e93b19a7f1ac6eed08bb31f7997373 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 25 Oct 2016 20:04:29 +0200 Subject: [PATCH] de-duplicate resolution of exact sources rather than resolving them once in bulk (for the code model) and once per pri file (for the project view), resolve them only in bulk, but "tag" them. then do a cheap filtering pass for the project view. as a side effect, this fixes the problem that sources that are listed by a file that is not shown in the project tree (as is the case for qrc files synthesized by resources.prf) would not be shown at all. instead, these sources now appear belonging directly to the pro file. Task-number: QTCREATORBUG-3670 Change-Id: I1a1756d95bd90db4da1274eebcc4dad2a854f43d Reviewed-by: Tobias Hunger --- .../qmakeprojectmanager/qmakenodes.cpp | 168 ++++++++---------- src/plugins/qmakeprojectmanager/qmakenodes.h | 28 ++- src/shared/proparser/profileevaluator.cpp | 16 +- src/shared/proparser/profileevaluator.h | 12 +- 4 files changed, 100 insertions(+), 124 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index 4895e66331a..994431c24f6 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -636,12 +636,33 @@ QSet QmakePriFileNode::recursiveEnumerate(const QString &folder) return result; } -PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input, - ProFile *proFile, bool haveExact, - const QList> &variableAndVPathInformation) +QStringList QmakeProFileNode::fileListForVar( + const QHash > &sourceFiles, + const QString &varName) { - PriFileEvalResult result; + const QVector &sources = sourceFiles[varName]; + QStringList result; + result.reserve(sources.size()); + foreach (const ProFileEvaluator::SourceFile &sf, sources) + result << sf.fileName; + return result; +} +void QmakePriFileNode::extractSources( + QHash proToResult, PriFileEvalResult *fallback, + QVector sourceFiles, FileType type) +{ + foreach (const ProFileEvaluator::SourceFile &source, sourceFiles) { + PriFileEvalResult *result = proToResult.value(source.proFile); + if (!result) + result = fallback; + result->foundFiles[type].insert(FileName::fromString(source.fileName)); + } +} + +void QmakePriFileNode::extractValues( + const EvalInput &input, ProFile *proFile, PriFileEvalResult &result) +{ // Figure out DEPLOYMENT and INSTALL folders. // Ignore stuff from cumulative parse, as we are recursively enumerating // all the files from those folders and add watchers for them. That's too @@ -682,40 +703,14 @@ PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input, result.recursiveEnumerateFiles += recursiveEnumerate(folder); const QVector &fileTypes = qmakeNodeStaticData()->fileTypeData; - // update files for (int i = 0; i < fileTypes.size(); ++i) { FileType type = fileTypes.at(i).type; - const QList &qmakeVariables = variableAndVPathInformation.at(i); - QSet newFilePaths; - foreach (const VariableAndVPathInformation &qmakeVariable, qmakeVariables) { - if (haveExact) { - QStringList tmp = input.readerExact->absoluteFileValues( - qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsExact, proFile); - foreach (const QString &t, tmp) - newFilePaths += FileName::fromString(t); - } - { - QStringList tmp = input.readerCumulative->absoluteFileValues( - qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsCumulative, proFile); - foreach (const QString &t, tmp) - newFilePaths += FileName::fromString(t); - } - } - - result.foundFiles[type] = newFilePaths; - result.recursiveEnumerateFiles.subtract(newFilePaths); - } - - - for (int i = 0; i < fileTypes.size(); ++i) { - FileType type = fileTypes.at(i).type; - QSet newFilePaths = filterFilesProVariables(type, result.foundFiles[type]); + QSet &foundFiles = result.foundFiles[type]; + result.recursiveEnumerateFiles.subtract(foundFiles); + QSet newFilePaths = filterFilesProVariables(type, foundFiles); newFilePaths += filterFilesRecursiveEnumerata(type, result.recursiveEnumerateFiles); - result.foundFiles[type] = newFilePaths; + foundFiles = newFilePaths; } - - - return result; } void QmakePriFileNode::update(const Internal::PriFileEvalResult &result) @@ -1850,6 +1845,8 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) result->includedFiles.proFile = pro; result->includedFiles.name = input.projectFilePath; + QHash proToResult; + result->projectType = proFileTemplateTypeToProjectType( (result->state == EvalResult::EvalOk ? input.readerExact : input.readerCumulative)->templateType()); @@ -1883,6 +1880,7 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) childTree->proFile = child; childTree->name = childName; current->children.insert(childName, childTree); + proToResult[child] = &childTree->result; } } toBuild.append(current->children.values()); @@ -1916,6 +1914,7 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) childTree->proFile = child; childTree->name = childName; current->children.insert(childName, childTree); + proToResult[child] = &childTree->result; } } toBuild.append(current->children.values()); @@ -1924,6 +1923,34 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) auto exactReader = exactBuildPassReader ? exactBuildPassReader : input.readerExact; auto cumulativeReader = cumulativeBuildPassReader ? cumulativeBuildPassReader : input.readerCumulative; + QHash > exactSourceFiles; + QHash > cumulativeSourceFiles; + + QStringList baseVPathsExact = baseVPaths(exactReader, input.projectDir, input.buildDirectory); + QStringList baseVPathsCumulative = baseVPaths(cumulativeReader, input.projectDir, input.buildDirectory); + + const QVector &fileTypes = qmakeNodeStaticData()->fileTypeData; + for (int i = 0; i < fileTypes.size(); ++i) { + FileType type = fileTypes.at(i).type; + QStringList qmakeVariables = varNames(type, exactReader); + foreach (const QString &qmakeVariable, qmakeVariables) { + if (result->state == EvalResult::EvalOk) { + QStringList vPathsExact = fullVPaths( + baseVPathsExact, exactReader, qmakeVariable, input.projectDir); + auto sourceFiles = exactReader->absoluteFileValues( + qmakeVariable, input.projectDir, vPathsExact); + exactSourceFiles[qmakeVariable] = sourceFiles; + extractSources(proToResult, &result->includedFiles.result, sourceFiles, type); + } + QStringList vPathsCumulative = fullVPaths( + baseVPathsCumulative, cumulativeReader, qmakeVariable, input.projectDir); + auto sourceFiles = cumulativeReader->absoluteFileValues( + qmakeVariable, input.projectDir, vPathsCumulative); + cumulativeSourceFiles[qmakeVariable] = sourceFiles; + extractSources(proToResult, &result->includedFiles.result, sourceFiles, type); + } + } + if (result->state == EvalResult::EvalOk) { result->targetInformation = targetInformation(input.readerExact, exactBuildPassReader, input.buildDirectory, input.projectFilePath.toString()); @@ -1935,21 +1962,21 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) result->newVarValues[IncludePathVar] = includePaths(exactReader, input.sysroot, input.buildDirectory, input.projectDir); result->newVarValues[CppFlagsVar] = exactReader->values(QLatin1String("QMAKE_CXXFLAGS")); - result->newVarValues[SourceVar] = - fileListForVar(exactReader, cumulativeReader, - QLatin1String("SOURCES"), input.projectDir, input.buildDirectory) + - fileListForVar(exactReader, cumulativeReader, - QLatin1String("HEADERS"), input.projectDir, input.buildDirectory) + - fileListForVar(exactReader, cumulativeReader, - QLatin1String("OBJECTIVE_HEADERS"), input.projectDir, input.buildDirectory); + QStringList allSources = + fileListForVar(exactSourceFiles, QLatin1String("SOURCES")) + + fileListForVar(cumulativeSourceFiles, QLatin1String("SOURCES")) + + fileListForVar(exactSourceFiles, QLatin1String("HEADERS")) + + fileListForVar(cumulativeSourceFiles, QLatin1String("HEADERS")) + + fileListForVar(exactSourceFiles, QLatin1String("OBJECTIVE_HEADERS")) + + fileListForVar(cumulativeSourceFiles, QLatin1String("OBJECTIVE_HEADERS")); + allSources.removeDuplicates(); + result->newVarValues[SourceVar] = allSources; result->newVarValues[UiDirVar] = QStringList() << uiDirPath(exactReader, input.buildDirectory); result->newVarValues[HeaderExtensionVar] = QStringList() << exactReader->value(QLatin1String("QMAKE_EXT_H")); result->newVarValues[CppExtensionVar] = QStringList() << exactReader->value(QLatin1String("QMAKE_EXT_CPP")); result->newVarValues[MocDirVar] = QStringList() << mocDirPath(exactReader, input.buildDirectory); - result->newVarValues[ExactResourceVar] = fileListForVar(exactReader, 0, - QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory); - result->newVarValues[CumulativeResourceVar] = fileListForVar(cumulativeReader, 0, - QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory); + result->newVarValues[ExactResourceVar] = fileListForVar(exactSourceFiles, QLatin1String("RESOURCES")); + result->newVarValues[CumulativeResourceVar] = fileListForVar(cumulativeSourceFiles, QLatin1String("RESOURCES")); result->newVarValues[PkgConfigVar] = exactReader->values(QLatin1String("PKGCONFIG")); result->newVarValues[PrecompiledHeaderVar] = exactReader->fixifiedValues( QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory); @@ -1981,37 +2008,11 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) if (result->state == EvalResult::EvalOk || result->state == EvalResult::EvalPartial) { - QList> variableAndVPathInformation; - { // Collect information on VPATHS and qmake variables - QStringList baseVPathsExact = baseVPaths(exactReader, input.projectDir, input.buildDirectory); - QStringList baseVPathsCumulative = baseVPaths(cumulativeReader, input.projectDir, input.buildDirectory); - - const QVector &fileTypes = qmakeNodeStaticData()->fileTypeData; - - variableAndVPathInformation.reserve(fileTypes.size()); - for (int i = 0; i < fileTypes.size(); ++i) { - FileType type = fileTypes.at(i).type; - - QList list; - QStringList qmakeVariables = varNames(type, exactReader); - list.reserve(qmakeVariables.size()); - foreach (const QString &qmakeVariable, qmakeVariables) { - VariableAndVPathInformation info; - info.variable = qmakeVariable; - info.vPathsExact = fullVPaths(baseVPathsExact, exactReader, qmakeVariable, input.projectDir); - info.vPathsCumulative = fullVPaths(baseVPathsCumulative, cumulativeReader, qmakeVariable, input.projectDir); - list.append(info); - } - variableAndVPathInformation.append(list); - } - } - // extract values for each .pri file and add it to IncludedPriFiles structure QList toExtract = { &result->includedFiles }; while (!toExtract.isEmpty()) { IncludedPriFile *current = toExtract.takeFirst(); - current->result = extractValues(input, current->proFile, (result->state == EvalResult::EvalOk), - variableAndVPathInformation); + extractValues(input, current->proFile, current->result); toExtract.append(current->children.values()); } } @@ -2254,29 +2255,6 @@ void QmakeProFileNode::cleanupProFileReaders() m_readerCumulative = nullptr; } -QStringList QmakeProFileNode::fileListForVar(QtSupport::ProFileReader *readerExact, QtSupport::ProFileReader *readerCumulative, - const QString &varName, const QString &projectDir, const QString &buildDir) -{ - QStringList baseVPathsExact = baseVPaths(readerExact, projectDir, buildDir); - QStringList vPathsExact = fullVPaths(baseVPathsExact, readerExact, varName, projectDir); - - QStringList result; - result = readerExact->absoluteFileValues(varName, - projectDir, - vPathsExact, - 0); - if (readerCumulative) { - QStringList baseVPathsCumulative = baseVPaths(readerCumulative, projectDir, buildDir); - QStringList vPathsCumulative = fullVPaths(baseVPathsCumulative, readerCumulative, varName, projectDir); - result += readerCumulative->absoluteFileValues(varName, - projectDir, - vPathsCumulative, - 0); - } - result.removeDuplicates(); - return result; -} - QString QmakeProFileNode::uiDirPath(QtSupport::ProFileReader *reader, const QString &buildDir) { QString path = reader->value(QLatin1String("UI_DIR")); diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.h b/src/plugins/qmakeprojectmanager/qmakenodes.h index 3f981395486..66e2d167d36 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.h +++ b/src/plugins/qmakeprojectmanager/qmakenodes.h @@ -27,6 +27,7 @@ #include "qmakeprojectmanager_global.h" #include "proparser/prowriter.h" +#include "proparser/profileevaluator.h" #include #include @@ -38,11 +39,6 @@ #include #include -// defined in proitems.h -QT_BEGIN_NAMESPACE -class ProFile; -QT_END_NAMESPACE - namespace Utils { class FileName; } namespace Core { class ICore; } @@ -117,15 +113,6 @@ struct InternalNode; class EvalInput; class EvalResult; class PriFileEvalResult; -// TOOD can probably move into the .cpp file -class VariableAndVPathInformation -{ -public: - QString variable; - QStringList vPathsExact; - QStringList vPathsCumulative; -}; - } // Implements ProjectNode for qmake .pri files @@ -210,8 +197,12 @@ private: QStringList formResources(const QString &formFile) const; static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir); static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir); - static Internal::PriFileEvalResult extractValues(const Internal::EvalInput &input, ProFile *proFile, bool haveExact, - const QList> &variableAndVPathInformation); + static void extractSources( + QHash proToResult, + Internal::PriFileEvalResult *fallback, + QVector sourceFiles, ProjectExplorer::FileType type); + static void extractValues( + const Internal::EvalInput &input, ProFile *proFile, Internal::PriFileEvalResult &result); void watchFolders(const QSet &folders); QmakeProject *m_project; @@ -387,8 +378,9 @@ private: void updateGeneratedFiles(const QString &buildDir); - static QStringList fileListForVar(QtSupport::ProFileReader *readerExact, QtSupport::ProFileReader *readerCumulative, - const QString &varName, const QString &projectDir, const QString &buildDir); + static QStringList fileListForVar( + const QHash > &sourceFiles, + const QString &varName); static QString uiDirPath(QtSupport::ProFileReader *reader, const QString &buildDir); static QString mocDirPath(QtSupport::ProFileReader *reader, const QString &buildDir); static QString sysrootify(const QString &path, const QString &sysroot, const QString &baseDir, const QString &outputDir); diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 995658cdd2d..2c179a2584a 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -119,17 +119,17 @@ QStringList ProFileEvaluator::absolutePathValues( return result; } -QStringList ProFileEvaluator::absoluteFileValues( - const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, - const ProFile *pro) const +QVector ProFileEvaluator::absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs) const { QMakeVfs::VfsFlags flags = (d->m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); - QStringList result; - foreach (const QString &el, pro ? values(variable, pro) : values(variable)) { + QVector result; + foreach (const ProString &str, d->values(ProKey(variable))) { + const QString &el = d->m_option->expandEnvVars(str.toQString()); QString absEl; if (IoUtils::isAbsolutePath(el)) { if (m_vfs->exists(el, flags)) { - result << el; + result << SourceFile{ el, str.sourceFile() }; goto next; } absEl = el; @@ -137,7 +137,7 @@ QStringList ProFileEvaluator::absoluteFileValues( foreach (const QString &dir, searchDirs) { QString fn = QDir::cleanPath(dir + QLatin1Char('/') + el); if (m_vfs->exists(fn, flags)) { - result << fn; + result << SourceFile{ QDir::cleanPath(fn), str.sourceFile() }; goto next; } } @@ -157,7 +157,7 @@ QStringList ProFileEvaluator::absoluteFileValues( theDir.setFilter(theDir.filter() & ~QDir::AllDirs); foreach (const QString &fn, theDir.entryList(QStringList(wildcard))) if (fn != QLatin1String(".") && fn != QLatin1String("..")) - result << absDir + QLatin1Char('/') + fn; + result << SourceFile{ absDir + QLatin1Char('/') + fn, str.sourceFile() }; } // else if (acceptMissing) } } diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h index 898198e66be..c6d4a79cfae 100644 --- a/src/shared/proparser/profileevaluator.h +++ b/src/shared/proparser/profileevaluator.h @@ -53,6 +53,11 @@ public: TT_Subdirs }; + struct SourceFile { + QString fileName; + const ProFile *proFile; + }; + // Call this from a concurrency-free context static void initialize(); @@ -79,9 +84,8 @@ public: QStringList fixifiedValues( const QString &variable, const QString &baseDirectory, const QString &buildDirectory) const; QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const; - QStringList absoluteFileValues( - const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, - const ProFile *pro) const; + QVector absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs) const; QString propertyValue(const QString &val) const; private: @@ -89,4 +93,6 @@ private: QMakeVfs *m_vfs; }; +Q_DECLARE_TYPEINFO(ProFileEvaluator::SourceFile, Q_MOVABLE_TYPE); + QT_END_NAMESPACE