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);
}
result->exactSubdirs = subDirs.toSet();
} }
foreach (ProFile *includeFile, input.readerExact->includeFiles()) {
if (includeFile->fileName() == input.projectFilePath.toString()) { // this file QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerExact->includeFiles();
result->fileForCurrentProjectExact = includeFile; QVector<ProFile *> tmp = includeFiles.value(nullptr);
} else {
const FileName includeFileName = FileName::fromString(includeFile->fileName()); if (!tmp.isEmpty()) {
result->newProjectFilesExact << includeFileName; result->includedFiles.name = Utils::FileName::fromString(tmp.first()->fileName());
result->includeFilesExact.insert(includeFileName, includeFile); 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);
}
}
toBuild.append(current->children.values());
} }
SortByPath sortByPath;
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,19 +2009,13 @@ 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,150 +2109,118 @@ 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;
Utils::sort(existingProjectNodes, sortByPath);
// result is already sorted
QList<ProjectNode*> toAdd; QList<QPair<QmakePriFileNode *, IncludedPriFile *>> toCompare;
QList<ProjectNode*> toRemove;
QList<QmakePriFileNode *> toUpdate;
QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin(); toCompare.append(qMakePair(this, &result->includedFiles));
FileNameList::const_iterator newExactIt = result->newProjectFilesExact.constBegin();
FileNameList::const_iterator newCumlativeIt = result->newProjectFilesCumlative.constBegin();
forever { while (!toCompare.isEmpty()) {
bool existingAtEnd = (existingIt == existingProjectNodes.constEnd()); QmakePriFileNode *pn = toCompare.first().first;
bool newExactAtEnd = (newExactIt == result->newProjectFilesExact.constEnd()); IncludedPriFile *tree = toCompare.first().second;
bool newCumlativeAtEnd = (newCumlativeIt == result->newProjectFilesCumlative.constEnd()); toCompare.pop_front();
if (existingAtEnd && newExactAtEnd && newCumlativeAtEnd) QList<ProjectNode*> existingProjectNodes = pn->subProjectNodes();
break; // we are done, hurray! Utils::sort(existingProjectNodes, sortByPath);
// result is already sorted
// So this is one giant loop comparing 3 lists at once and sorting the comparison QList<ProjectNode*> toAdd;
// into mainly 2 buckets: toAdd and toRemove QList<ProjectNode*> 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; QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin();
if (! existingAtEnd auto newIt = tree->children.constBegin();
&& (newExactAtEnd || (*existingIt)->path() < *newExactIt)
&& (newCumlativeAtEnd || (*existingIt)->path() < *newCumlativeIt)) {
// Remove case
toRemove << *existingIt;
++existingIt;
} else if (! newExactAtEnd
&& (existingAtEnd || *newExactIt < (*existingIt)->path())
&& (newCumlativeAtEnd || *newExactIt < *newCumlativeIt)) {
// Mark node from exact for adding
nodeToAdd = *newExactIt;
++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
} forever {
// If we found something to add, do it bool existingAtEnd = (existingIt == existingProjectNodes.constEnd());
if (!nodeToAdd.isEmpty()) { bool newAtEnd = (newIt == tree->children.constEnd());
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 if (existingAtEnd && newAtEnd)
bool loop = false; break; // we are done, hurray!
Node *n = this;
while ((n = n->parentFolderNode())) { if (! existingAtEnd
if (dynamic_cast<QmakePriFileNode *>(n) && n->path() == nodeToAdd) { && (newAtEnd || (*existingIt)->path() < (*newIt)->name)) {
loop = true; // Remove case
break; toRemove << *existingIt;
++existingIt;
} else if (! newAtEnd
&& (existingAtEnd || (*newIt)->name < (*existingIt)->path())) {
// Adding a node
IncludedPriFile *nodeToAdd = *newIt;
++newIt;
QVector<ProFile *> filesExact = nodeToAdd->proFilesExact;
QVector<ProFile *> filesCumlative = nodeToAdd->proFilesCumulative;
// Loop preventation, make sure that exact same node is not in our parent chain
bool loop = false;
Node *n = pn;
while ((n = n->parentFolderNode())) {
if (dynamic_cast<QmakePriFileNode *>(n) && n->path() == nodeToAdd->name) {
loop = true;
break;
}
} }
}
if (loop) { if (loop) {
// Do nothing // Do nothing
} else {
if (fileExact || fileCumlative) {
QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, nodeToAdd);
qmakePriFileNode->setParentFolderNode(this); // Needed for loop detection
qmakePriFileNode->setIncludedInExactParse(fileExact != 0 && includedInExactParse());
toAdd << qmakePriFileNode;
toUpdate << qmakePriFileNode;
} else { } else {
QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, nodeToAdd); if (!filesExact.isEmpty() || !filesCumlative.isEmpty()) {
qmakeProFileNode->setParentFolderNode(this); // Needed for loop detection QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, nodeToAdd->name);
qmakeProFileNode->setIncludedInExactParse( qmakePriFileNode->setParentFolderNode(pn); // Needed for loop detection
result->exactSubdirs.contains(qmakeProFileNode->path()) qmakePriFileNode->setIncludedInExactParse(!filesExact.isEmpty() && pn->includedInExactParse());
&& includedInExactParse()); toAdd << qmakePriFileNode;
qmakeProFileNode->asyncUpdate(); qmakePriFileNode->update(nodeToAdd->result);
toAdd << qmakeProFileNode; toCompare.append(qMakePair(qmakePriFileNode, nodeToAdd));
} else {
QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, nodeToAdd->name);
qmakeProFileNode->setParentFolderNode(pn); // Needed for loop detection
qmakeProFileNode->setIncludedInExactParse(
result->exactSubdirs.contains(qmakeProFileNode->path())
&& pn->includedInExactParse());
qmakeProFileNode->asyncUpdate();
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
foreach (ProjectNode *node, toRemove) {
if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(node)) {
qmakeProFileNode->setValidParseRecursive(false);
qmakeProFileNode->setParseInProgressRecursive(false);
} }
} }
} // for
foreach (ProjectNode *node, toRemove) { if (!toRemove.isEmpty())
if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(node)) { pn->removeProjectNodes(toRemove);
qmakeProFileNode->setValidParseRecursive(false); if (!toAdd.isEmpty())
qmakeProFileNode->setParseInProgressRecursive(false); pn->addProjectNodes(toAdd);
}
} }
if (!toRemove.isEmpty()) QmakePriFileNode::update(result->includedFiles.result);
removeProjectNodes(toRemove);
if (!toAdd.isEmpty())
addProjectNodes(toAdd);
foreach (QmakePriFileNode *qmakePriFileNode, toUpdate)
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,14 +86,17 @@ 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];
m_proFiles.append(pro); if (!children.contains(pro)) {
pro->ref(); children.append(pro);
m_proFiles.append(pro);
pro->ref();
}
} }
} }
@@ -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;
}; };