QmakeProject: Show project hierarchy of .pri files

For a reason that seems lost in time, all .pri files that are
(directly or indirectly) included in a .pro file are listed
in a flat list.

Change that to properly show a tree.

For example a.pro including b.pri, which includes c.pri is
now shown like this:
a.pro
|-> b.pri
    |-> c.pri

Task-number: QTCREATORBUG-487
Change-Id: I1bc29a512fb27e6fe9b399738f2a37f2a95ce10f
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Daniel Teske <daniel.teske@theqtcompany.com>
This commit is contained in:
Daniel Teske
2015-08-12 12:59:38 +02:00
parent 9aa58ab26e
commit 51ba32bccc
4 changed files with 211 additions and 224 deletions

View File

@@ -215,6 +215,21 @@ public:
QMap<FileType, QSet<FileName> > foundFiles; QMap<FileType, QSet<FileName> > foundFiles;
}; };
class IncludedPriFile
{
public:
Utils::FileName name;
PriFileEvalResult result;
QMap<Utils::FileName, IncludedPriFile *> children;
QVector<ProFile *> proFilesExact;
QVector<ProFile *> proFilesCumulative;
~IncludedPriFile()
{
qDeleteAll(children);
}
};
class EvalResult class EvalResult
{ {
public: public:
@@ -223,18 +238,12 @@ public:
QmakeProjectType projectType; QmakeProjectType projectType;
QStringList subProjectsNotToDeploy; QStringList subProjectsNotToDeploy;
QHash<FileName, ProFile*> includeFilesExact;
FileNameList newProjectFilesExact;
QSet<FileName> exactSubdirs; QSet<FileName> exactSubdirs;
ProFile *fileForCurrentProjectExact; // probably only used in parser thread IncludedPriFile includedFiles;
QHash<FileName, ProFile*> includeFilesCumlative;
FileNameList newProjectFilesCumlative;
ProFile *fileForCurrentProjectCumlative; // probably only used in parser thread
TargetInformation targetInformation; TargetInformation targetInformation;
InstallsList installsList; InstallsList installsList;
QHash<QmakeVariable, QStringList> newVarValues; QHash<QmakeVariable, QStringList> newVarValues;
bool isDeployable; bool isDeployable;
QHash<FileName, PriFileEvalResult> priFileResults;
QStringList errors; QStringList errors;
}; };
} }
@@ -643,14 +652,16 @@ QSet<FileName> QmakePriFileNode::recursiveEnumerate(const QString &folder)
return result; return result;
} }
PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input, ProFile *includeFileExact, ProFile *includeFileCumlative, PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input,
QVector<ProFile *> includeFilesExact,
QVector<ProFile *> includeFilesCumlative,
const QList<QList<VariableAndVPathInformation>> &variableAndVPathInformation) const QList<QList<VariableAndVPathInformation>> &variableAndVPathInformation)
{ {
PriFileEvalResult result; PriFileEvalResult result;
// Figure out DEPLOYMENT and INSTALL folders // Figure out DEPLOYMENT and INSTALL folders
QStringList dynamicVariables = dynamicVarNames(input.readerExact, input.readerCumulative, input.isQt5); QStringList dynamicVariables = dynamicVarNames(input.readerExact, input.readerCumulative, input.isQt5);
if (includeFileExact) foreach (ProFile *includeFileExact, includeFilesExact)
foreach (const QString &dynamicVar, dynamicVariables) { foreach (const QString &dynamicVar, dynamicVariables) {
result.folders += input.readerExact->values(dynamicVar, includeFileExact); result.folders += input.readerExact->values(dynamicVar, includeFileExact);
// Ignore stuff from cumulative parse // Ignore stuff from cumulative parse
@@ -698,7 +709,7 @@ PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input, ProFil
const QList<VariableAndVPathInformation> &qmakeVariables = variableAndVPathInformation.at(i); const QList<VariableAndVPathInformation> &qmakeVariables = variableAndVPathInformation.at(i);
QSet<FileName> newFilePaths; QSet<FileName> newFilePaths;
foreach (const VariableAndVPathInformation &qmakeVariable, qmakeVariables) { foreach (const VariableAndVPathInformation &qmakeVariable, qmakeVariables) {
if (includeFileExact) { foreach (ProFile *includeFileExact, includeFilesExact) {
QStringList tmp = input.readerExact->absoluteFileValues(qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsExact, includeFileExact); QStringList tmp = input.readerExact->absoluteFileValues(qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsExact, includeFileExact);
foreach (const QString &t, tmp) { foreach (const QString &t, tmp) {
tmpFi.setFile(t); tmpFi.setFile(t);
@@ -706,7 +717,7 @@ PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input, ProFil
newFilePaths += FileName::fromString(t); newFilePaths += FileName::fromString(t);
} }
} }
if (includeFileCumlative) { foreach (ProFile *includeFileCumlative, includeFilesCumlative) {
QStringList tmp = input.readerCumulative->absoluteFileValues(qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsCumulative, includeFileCumlative); QStringList tmp = input.readerCumulative->absoluteFileValues(qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsCumulative, includeFileCumlative);
foreach (const QString &t, tmp) { foreach (const QString &t, tmp) {
tmpFi.setFile(t); tmpFi.setFile(t);
@@ -1767,40 +1778,6 @@ void QmakeProFileNode::setupReader()
m_readerCumulative->setCumulative(true); m_readerCumulative->setCumulative(true);
} }
static FileNameList mergeList(const FileNameList &listA, const FileNameList &listB)
{
FileNameList result;
result.reserve(qMax(listA.size(), listB.size()));
auto ait = listA.constBegin();
auto aend = listA.constEnd();
auto bit = listB.constBegin();
auto bend = listB.constEnd();
while (ait != aend && bit != bend) {
const FileName &a = *ait;
const FileName &b = *bit;
if (a < b) {
result.append(a);
++ait;
} else if (b < a) {
result.append(b);
++bit;
} else {
result.append(a);
++ait;
++bit;
}
}
while (ait != aend) {
result.append(*ait);
++ait;
}
while (bit != bend) {
result.append(*bit);
++bit;
}
return result;
}
EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
{ {
EvalResult *result = new EvalResult; EvalResult *result = new EvalResult;
@@ -1819,41 +1796,90 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
result->projectType = proFileTemplateTypeToProjectType( result->projectType = proFileTemplateTypeToProjectType(
(result->state == EvalResult::EvalOk ? input.readerExact (result->state == EvalResult::EvalOk ? input.readerExact
: input.readerCumulative)->templateType()); : input.readerCumulative)->templateType());
result->fileForCurrentProjectExact = 0;
result->fileForCurrentProjectCumlative = 0;
if (result->state == EvalResult::EvalOk) { if (result->state == EvalResult::EvalOk) {
if (result->projectType == SubDirsTemplate) { if (result->projectType == SubDirsTemplate) {
QStringList errors; QStringList errors;
result->newProjectFilesExact = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors);
result->errors.append(errors); result->errors.append(errors);
result->exactSubdirs = result->newProjectFilesExact.toSet(); FileNameList subDirs = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors);
foreach (const Utils::FileName &subDirName, subDirs) {
IncludedPriFile *subDir = new IncludedPriFile;
subDir->name = subDirName;
result->includedFiles.children.insert(subDirName, subDir);
} }
foreach (ProFile *includeFile, input.readerExact->includeFiles()) {
if (includeFile->fileName() == input.projectFilePath.toString()) { // this file result->exactSubdirs = subDirs.toSet();
result->fileForCurrentProjectExact = includeFile; }
} else {
const FileName includeFileName = FileName::fromString(includeFile->fileName()); QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerExact->includeFiles();
result->newProjectFilesExact << includeFileName; QVector<ProFile *> tmp = includeFiles.value(nullptr);
result->includeFilesExact.insert(includeFileName, includeFile);
if (!tmp.isEmpty()) {
result->includedFiles.name = Utils::FileName::fromString(tmp.first()->fileName());
result->includedFiles.proFilesExact.append(tmp.first());
}
// Convert ProFileReader::includeFiles to IncludedPriFile structure
QList<IncludedPriFile *> toBuild = { &result->includedFiles };
while (!toBuild.isEmpty()) {
IncludedPriFile *current = toBuild.takeFirst();
foreach (ProFile *proFile, current->proFilesExact) {
QVector<ProFile *> children = includeFiles.value(proFile);
foreach (ProFile *child, children) {
const Utils::FileName childName = Utils::FileName::fromString(child->fileName());
auto it = current->children.find(childName);
if (it == current->children.end()) {
IncludedPriFile *childTree = new IncludedPriFile;
childTree->name = childName;
it = current->children.insert(childName, childTree);
}
(*it)->proFilesExact.append(child);
}
}
toBuild.append(current->children.values());
}
}
if (result->projectType == SubDirsTemplate) {
FileNameList subDirs = subDirsPaths(input.readerCumulative, input.projectDir, 0, 0);
foreach (const Utils::FileName &subDirName, subDirs) {
auto it = result->includedFiles.children.find(subDirName);
if (it == result->includedFiles.children.end()) {
IncludedPriFile *subDir = new IncludedPriFile;
subDir->name = subDirName;
result->includedFiles.children.insert(subDirName, subDir);
} }
} }
} }
if (result->projectType == SubDirsTemplate)
result->newProjectFilesCumlative = subDirsPaths(input.readerCumulative, input.projectDir, 0, 0); QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerCumulative->includeFiles();
foreach (ProFile *includeFile, input.readerCumulative->includeFiles()) { QVector<ProFile *> tmp = includeFiles.value(nullptr);
if (includeFile->fileName() == input.projectFilePath.toString()) {
result->fileForCurrentProjectCumlative = includeFile; if (!tmp.isEmpty()) {
} else { result->includedFiles.name = Utils::FileName::fromString(tmp.first()->fileName());
const FileName includeFileName = FileName::fromString(includeFile->fileName()); result->includedFiles.proFilesCumulative.append(tmp.first());
result->newProjectFilesCumlative << includeFileName; }
result->includeFilesCumlative.insert(includeFileName, includeFile);
QList<IncludedPriFile *> toBuild = { &result->includedFiles };
// Add ProFileReader::includeFiles information from cumulative paerse to IncludedPriFile structure
while (!toBuild.isEmpty()) {
IncludedPriFile *current = toBuild.takeFirst();
foreach (ProFile *proFile, current->proFilesCumulative) {
QVector<ProFile *> children = includeFiles.value(proFile);
foreach (ProFile *child, children) {
const Utils::FileName childName = Utils::FileName::fromString(child->fileName());
auto it = current->children.find(childName);
if (it == current->children.end()) {
IncludedPriFile *childTree = new IncludedPriFile;
childTree->name = childName;
it = current->children.insert(childName, childTree);
}
(*it)->proFilesCumulative.append(child);
} }
} }
SortByPath sortByPath; toBuild.append(current->children.values());
Utils::sort(result->newProjectFilesExact, sortByPath); }
Utils::sort(result->newProjectFilesCumlative, sortByPath);
if (result->state == EvalResult::EvalOk) { if (result->state == EvalResult::EvalOk) {
// create build_pass reader // create build_pass reader
@@ -1983,20 +2009,14 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
} }
} }
// extract values // extract values for each .pri file and add it to IncludedPriFiles structure
FileNameList allFiles = mergeList(result->newProjectFilesExact, result->newProjectFilesCumlative); QList<IncludedPriFile *> toExtract = { &result->includedFiles };
foreach (const FileName &file, allFiles) { while (!toExtract.isEmpty()) {
ProFile *fileExact = result->includeFilesExact.value(file); IncludedPriFile *current = toExtract.takeFirst();
ProFile *fileCumlative = result->includeFilesCumlative.value(file); current->result = extractValues(input, current->proFilesExact, current->proFilesCumulative, variableAndVPathInformation);
if (fileExact || fileCumlative) { toExtract.append(current->children.values());
result->priFileResults[file] = extractValues(input, fileExact, fileCumlative, variableAndVPathInformation);
} }
} }
result->priFileResults[input.projectFilePath] = extractValues(input, result->fileForCurrentProjectExact,
result->fileForCurrentProjectCumlative,
variableAndVPathInformation);
}
return result; return result;
} }
@@ -2089,107 +2109,54 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
// Add/Remove pri files, sub projects // Add/Remove pri files, sub projects
// //
QList<ProjectNode*> existingProjectNodes = subProjectNodes();
QString buildDirectory = buildDir(); QString buildDirectory = buildDir();
SortByPath sortByPath; SortByPath sortByPath;
QList<QPair<QmakePriFileNode *, IncludedPriFile *>> toCompare;
toCompare.append(qMakePair(this, &result->includedFiles));
while (!toCompare.isEmpty()) {
QmakePriFileNode *pn = toCompare.first().first;
IncludedPriFile *tree = toCompare.first().second;
toCompare.pop_front();
QList<ProjectNode*> existingProjectNodes = pn->subProjectNodes();
Utils::sort(existingProjectNodes, sortByPath); Utils::sort(existingProjectNodes, sortByPath);
// result is already sorted // result is already sorted
QList<ProjectNode*> toAdd; QList<ProjectNode*> toAdd;
QList<ProjectNode*> toRemove; QList<ProjectNode*> toRemove;
QList<QmakePriFileNode *> toUpdate;
QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin(); QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin();
FileNameList::const_iterator newExactIt = result->newProjectFilesExact.constBegin(); auto newIt = tree->children.constBegin();
FileNameList::const_iterator newCumlativeIt = result->newProjectFilesCumlative.constBegin();
forever { forever {
bool existingAtEnd = (existingIt == existingProjectNodes.constEnd()); bool existingAtEnd = (existingIt == existingProjectNodes.constEnd());
bool newExactAtEnd = (newExactIt == result->newProjectFilesExact.constEnd()); bool newAtEnd = (newIt == tree->children.constEnd());
bool newCumlativeAtEnd = (newCumlativeIt == result->newProjectFilesCumlative.constEnd());
if (existingAtEnd && newExactAtEnd && newCumlativeAtEnd) if (existingAtEnd && newAtEnd)
break; // we are done, hurray! break; // we are done, hurray!
// So this is one giant loop comparing 3 lists at once and sorting the comparison
// into mainly 2 buckets: toAdd and toRemove
// We need to distinguish between nodes that came from exact and cumalative
// parsing, since the update call is diffrent for them
// I believe this code to be correct, be careful in changing it
FileName nodeToAdd;
if (! existingAtEnd if (! existingAtEnd
&& (newExactAtEnd || (*existingIt)->path() < *newExactIt) && (newAtEnd || (*existingIt)->path() < (*newIt)->name)) {
&& (newCumlativeAtEnd || (*existingIt)->path() < *newCumlativeIt)) {
// Remove case // Remove case
toRemove << *existingIt; toRemove << *existingIt;
++existingIt; ++existingIt;
} else if (! newExactAtEnd } else if (! newAtEnd
&& (existingAtEnd || *newExactIt < (*existingIt)->path()) && (existingAtEnd || (*newIt)->name < (*existingIt)->path())) {
&& (newCumlativeAtEnd || *newExactIt < *newCumlativeIt)) { // Adding a node
// Mark node from exact for adding IncludedPriFile *nodeToAdd = *newIt;
nodeToAdd = *newExactIt; ++newIt;
++newExactIt;
} else if (! newCumlativeAtEnd
&& (existingAtEnd || *newCumlativeIt < (*existingIt)->path())
&& (newExactAtEnd || *newCumlativeIt < *newExactIt)) {
// Mark node from cumalative for adding
nodeToAdd = *newCumlativeIt;
++newCumlativeIt;
} else if (!newExactAtEnd
&& !newCumlativeAtEnd
&& (existingAtEnd || *newExactIt < (*existingIt)->path())
&& (existingAtEnd || *newCumlativeIt < (*existingIt)->path())) {
// Mark node from both for adding
nodeToAdd = *newExactIt;
++newExactIt;
++newCumlativeIt;
} else {
Q_ASSERT(!newExactAtEnd || !newCumlativeAtEnd);
// update case, figure out which case exactly
if (newExactAtEnd) {
++newCumlativeIt;
} else if (newCumlativeAtEnd) {
++newExactIt;
} else if (*newExactIt < *newCumlativeIt) {
++newExactIt;
} else if (*newCumlativeIt < *newExactIt) {
++newCumlativeIt;
} else {
++newExactIt;
++newCumlativeIt;
}
// Update existingNodeIte
ProFile *fileExact = result->includeFilesExact.value((*existingIt)->path());
ProFile *fileCumlative = result->includeFilesCumlative.value((*existingIt)->path());
if (fileExact || fileCumlative) {
QmakePriFileNode *priFileNode = static_cast<QmakePriFileNode *>(*existingIt);
priFileNode->update(result->priFileResults[(*existingIt)->path()]);
priFileNode->setIncludedInExactParse(fileExact != 0 && includedInExactParse());
} else {
// We always parse exactly, because we later when async parsing don't know whether
// the .pro file is included in this .pro file
// So to compare that later parse with the sync one
QmakeProFileNode *proFileNode = static_cast<QmakeProFileNode *>(*existingIt);
proFileNode->setIncludedInExactParse(result->exactSubdirs.contains(proFileNode->path())
&& includedInExactParse());
proFileNode->asyncUpdate();
}
++existingIt;
// newCumalativeIt and newExactIt are already incremented
} QVector<ProFile *> filesExact = nodeToAdd->proFilesExact;
// If we found something to add, do it QVector<ProFile *> filesCumlative = nodeToAdd->proFilesCumulative;
if (!nodeToAdd.isEmpty()) {
ProFile *fileExact = result->includeFilesExact.value(nodeToAdd);
ProFile *fileCumlative = result->includeFilesCumlative.value(nodeToAdd);
// Loop preventation, make sure that exact same node is not in our parent chain // Loop preventation, make sure that exact same node is not in our parent chain
bool loop = false; bool loop = false;
Node *n = this; Node *n = pn;
while ((n = n->parentFolderNode())) { while ((n = n->parentFolderNode())) {
if (dynamic_cast<QmakePriFileNode *>(n) && n->path() == nodeToAdd) { if (dynamic_cast<QmakePriFileNode *>(n) && n->path() == nodeToAdd->name) {
loop = true; loop = true;
break; break;
} }
@@ -2198,22 +2165,45 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
if (loop) { if (loop) {
// Do nothing // Do nothing
} else { } else {
if (fileExact || fileCumlative) { if (!filesExact.isEmpty() || !filesCumlative.isEmpty()) {
QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, nodeToAdd); QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, nodeToAdd->name);
qmakePriFileNode->setParentFolderNode(this); // Needed for loop detection qmakePriFileNode->setParentFolderNode(pn); // Needed for loop detection
qmakePriFileNode->setIncludedInExactParse(fileExact != 0 && includedInExactParse()); qmakePriFileNode->setIncludedInExactParse(!filesExact.isEmpty() && pn->includedInExactParse());
toAdd << qmakePriFileNode; toAdd << qmakePriFileNode;
toUpdate << qmakePriFileNode; qmakePriFileNode->update(nodeToAdd->result);
toCompare.append(qMakePair(qmakePriFileNode, nodeToAdd));
} else { } else {
QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, nodeToAdd); QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, nodeToAdd->name);
qmakeProFileNode->setParentFolderNode(this); // Needed for loop detection qmakeProFileNode->setParentFolderNode(pn); // Needed for loop detection
qmakeProFileNode->setIncludedInExactParse( qmakeProFileNode->setIncludedInExactParse(
result->exactSubdirs.contains(qmakeProFileNode->path()) result->exactSubdirs.contains(qmakeProFileNode->path())
&& includedInExactParse()); && pn->includedInExactParse());
qmakeProFileNode->asyncUpdate(); qmakeProFileNode->asyncUpdate();
toAdd << qmakeProFileNode; toAdd << qmakeProFileNode;
} }
} }
} else {
// Update existingNodeIte
QVector<ProFile *> filesExact = (*newIt)->proFilesExact;
QVector<ProFile *> filesCumlative = (*newIt)->proFilesCumulative;
if (!filesExact.isEmpty() || !filesCumlative.isEmpty()) {
QmakePriFileNode *priFileNode = static_cast<QmakePriFileNode *>(*existingIt);
priFileNode->update((*newIt)->result);
priFileNode->setIncludedInExactParse(!filesExact.isEmpty() && pn->includedInExactParse());
toCompare.append(qMakePair(priFileNode, *newIt));
} else {
// We always parse exactly, because we later when async parsing don't know whether
// the .pro file is included in this .pro file
// So to compare that later parse with the sync one
QmakeProFileNode *proFileNode = static_cast<QmakeProFileNode *>(*existingIt);
proFileNode->setIncludedInExactParse(result->exactSubdirs.contains(proFileNode->path())
&& pn->includedInExactParse());
proFileNode->asyncUpdate();
}
++newIt;
++existingIt;
// newCumalativeIt and newExactIt are already incremented
} }
} // for } // for
@@ -2225,14 +2215,12 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
} }
if (!toRemove.isEmpty()) if (!toRemove.isEmpty())
removeProjectNodes(toRemove); pn->removeProjectNodes(toRemove);
if (!toAdd.isEmpty()) if (!toAdd.isEmpty())
addProjectNodes(toAdd); pn->addProjectNodes(toAdd);
}
foreach (QmakePriFileNode *qmakePriFileNode, toUpdate) QmakePriFileNode::update(result->includedFiles.result);
qmakePriFileNode->update(result->priFileResults[qmakePriFileNode->path()]);
QmakePriFileNode::update(result->priFileResults[m_projectFilePath]);
m_validParse = (result->state == EvalResult::EvalOk); m_validParse = (result->state == EvalResult::EvalOk);
if (m_validParse) { if (m_validParse) {

View File

@@ -204,7 +204,7 @@ private:
QStringList formResources(const QString &formFile) const; QStringList formResources(const QString &formFile) const;
static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir); 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 QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir);
static Internal::PriFileEvalResult extractValues(const Internal::EvalInput &input, ProFile *includeFileExact, ProFile *includeFileCumlative, static Internal::PriFileEvalResult extractValues(const Internal::EvalInput &input, QVector<ProFile *> includeFilesExact, QVector<ProFile *> includeFilesCumlative,
const QList<QList<Internal::VariableAndVPathInformation>> &variableAndVPathInformation); const QList<QList<Internal::VariableAndVPathInformation>> &variableAndVPathInformation);
void watchFolders(const QSet<QString> &folders); void watchFolders(const QSet<QString> &folders);

View File

@@ -86,16 +86,19 @@ void ProFileReader::setCumulative(bool on)
ProFileEvaluator::setCumulative(on); ProFileEvaluator::setCumulative(on);
} }
void ProFileReader::aboutToEval(ProFile *, ProFile *pro, EvalFileType type) void ProFileReader::aboutToEval(ProFile *parent, ProFile *pro, EvalFileType type)
{ {
if (m_ignoreLevel || (type != EvalProjectFile && type != EvalIncludeFile)) { if (m_ignoreLevel || (type != EvalProjectFile && type != EvalIncludeFile)) {
m_ignoreLevel++; m_ignoreLevel++;
} else if (!m_includeFiles.contains(pro->fileName())) { } else {
m_includeFiles.insert(pro->fileName(), pro); QVector<ProFile *> children = m_includeFiles[parent];
if (!children.contains(pro)) {
children.append(pro);
m_proFiles.append(pro); m_proFiles.append(pro);
pro->ref(); pro->ref();
} }
} }
}
void ProFileReader::doneWithEval(ProFile *) void ProFileReader::doneWithEval(ProFile *)
{ {
@@ -103,14 +106,9 @@ void ProFileReader::doneWithEval(ProFile *)
m_ignoreLevel--; m_ignoreLevel--;
} }
QList<ProFile*> ProFileReader::includeFiles() const QHash<ProFile *, QVector<ProFile *> > ProFileReader::includeFiles() const
{ {
return m_includeFiles.values(); return m_includeFiles;
}
ProFile *ProFileReader::proFileFor(const QString &name)
{
return m_includeFiles.value(name);
} }
ProFileCacheManager *ProFileCacheManager::s_instance = 0; ProFileCacheManager *ProFileCacheManager::s_instance = 0;

View File

@@ -38,6 +38,7 @@
#include <QObject> #include <QObject>
#include <QMap> #include <QMap>
#include <QVector>
#include <QTimer> #include <QTimer>
namespace QtSupport { namespace QtSupport {
@@ -75,15 +76,15 @@ public:
void setCumulative(bool on); void setCumulative(bool on);
QList<ProFile*> includeFiles() const; QHash<ProFile *, QVector<ProFile *> > includeFiles() const;
ProFile *proFileFor(const QString &name);
virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type); virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type);
virtual void doneWithEval(ProFile *parent); virtual void doneWithEval(ProFile *parent);
private: private:
QMap<QString, ProFile *> m_includeFiles; // Tree of ProFiles, mapping from parent to children
QHash<ProFile *, QVector<ProFile *> > m_includeFiles;
// One entry per ProFile::ref() call, might contain duplicates
QList<ProFile *> m_proFiles; QList<ProFile *> m_proFiles;
int m_ignoreLevel; int m_ignoreLevel;
}; };