forked from qt-creator/qt-creator
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:
@@ -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) {
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user