forked from qt-creator/qt-creator
		
	
		
			
	
	
		
			2336 lines
		
	
	
		
			87 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			2336 lines
		
	
	
		
			87 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								/****************************************************************************
							 | 
						||
| 
								 | 
							
								**
							 | 
						||
| 
								 | 
							
								** Copyright (C) 2016 The Qt Company Ltd.
							 | 
						||
| 
								 | 
							
								** Contact: https://www.qt.io/licensing/
							 | 
						||
| 
								 | 
							
								**
							 | 
						||
| 
								 | 
							
								** This file is part of Qt Creator.
							 | 
						||
| 
								 | 
							
								**
							 | 
						||
| 
								 | 
							
								** Commercial License Usage
							 | 
						||
| 
								 | 
							
								** Licensees holding valid commercial Qt licenses may use this file in
							 | 
						||
| 
								 | 
							
								** accordance with the commercial license agreement provided with the
							 | 
						||
| 
								 | 
							
								** Software or, alternatively, in accordance with the terms contained in
							 | 
						||
| 
								 | 
							
								** a written agreement between you and The Qt Company. For licensing terms
							 | 
						||
| 
								 | 
							
								** and conditions see https://www.qt.io/terms-conditions. For further
							 | 
						||
| 
								 | 
							
								** information use the contact form at https://www.qt.io/contact-us.
							 | 
						||
| 
								 | 
							
								**
							 | 
						||
| 
								 | 
							
								** GNU General Public License Usage
							 | 
						||
| 
								 | 
							
								** Alternatively, this file may be used under the terms of the GNU
							 | 
						||
| 
								 | 
							
								** General Public License version 3 as published by the Free Software
							 | 
						||
| 
								 | 
							
								** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
							 | 
						||
| 
								 | 
							
								** included in the packaging of this file. Please review the following
							 | 
						||
| 
								 | 
							
								** information to ensure the GNU General Public License requirements will
							 | 
						||
| 
								 | 
							
								** be met: https://www.gnu.org/licenses/gpl-3.0.html.
							 | 
						||
| 
								 | 
							
								**
							 | 
						||
| 
								 | 
							
								****************************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "qmakeparsernodes.h"
							 | 
						||
| 
								 | 
							
								#include "qmakeproject.h"
							 | 
						||
| 
								 | 
							
								#include "qmakeprojectmanager.h"
							 | 
						||
| 
								 | 
							
								#include "qmakeprojectmanagerconstants.h"
							 | 
						||
| 
								 | 
							
								#include "qmakebuildconfiguration.h"
							 | 
						||
| 
								 | 
							
								#include "qmakerunconfigurationfactory.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <projectexplorer/nodesvisitor.h>
							 | 
						||
| 
								 | 
							
								#include <projectexplorer/projectexplorer.h>
							 | 
						||
| 
								 | 
							
								#include <projectexplorer/projectexplorerconstants.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/editormanager/editormanager.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/editormanager/ieditor.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/fileiconprovider.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/documentmanager.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/icore.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/iversioncontrol.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/vcsmanager.h>
							 | 
						||
| 
								 | 
							
								#include <coreplugin/dialogs/readonlyfilesdialog.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <extensionsystem/pluginmanager.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <projectexplorer/buildmanager.h>
							 | 
						||
| 
								 | 
							
								#include <projectexplorer/projectexplorer.h>
							 | 
						||
| 
								 | 
							
								#include <projectexplorer/target.h>
							 | 
						||
| 
								 | 
							
								#include <projectexplorer/projecttree.h>
							 | 
						||
| 
								 | 
							
								#include <qtsupport/profilereader.h>
							 | 
						||
| 
								 | 
							
								#include <qtsupport/qtkitinformation.h>
							 | 
						||
| 
								 | 
							
								#include <cpptools/generatedcodemodelsupport.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <resourceeditor/resourcenode.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <cpptools/cppmodelmanager.h>
							 | 
						||
| 
								 | 
							
								#include <cpptools/cpptoolsconstants.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <utils/algorithm.h>
							 | 
						||
| 
								 | 
							
								#include <utils/fileutils.h>
							 | 
						||
| 
								 | 
							
								#include <utils/hostosinfo.h>
							 | 
						||
| 
								 | 
							
								#include <utils/qtcprocess.h>
							 | 
						||
| 
								 | 
							
								#include <utils/mimetypes/mimedatabase.h>
							 | 
						||
| 
								 | 
							
								#include <utils/stringutils.h>
							 | 
						||
| 
								 | 
							
								#include <utils/theme/theme.h>
							 | 
						||
| 
								 | 
							
								#include <proparser/prowriter.h>
							 | 
						||
| 
								 | 
							
								#include <proparser/qmakevfs.h>
							 | 
						||
| 
								 | 
							
								#include <proparser/ioutils.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <QApplication>
							 | 
						||
| 
								 | 
							
								#include <QDebug>
							 | 
						||
| 
								 | 
							
								#include <QDir>
							 | 
						||
| 
								 | 
							
								#include <QFile>
							 | 
						||
| 
								 | 
							
								#include <QFileInfo>
							 | 
						||
| 
								 | 
							
								#include <QTextCodec>
							 | 
						||
| 
								 | 
							
								#include <QXmlStreamReader>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <QMessageBox>
							 | 
						||
| 
								 | 
							
								#include <utils/QtConcurrentTools>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using namespace Core;
							 | 
						||
| 
								 | 
							
								using namespace ProjectExplorer;
							 | 
						||
| 
								 | 
							
								using namespace Utils;
							 | 
						||
| 
								 | 
							
								using namespace QMakeInternal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Static cached data in struct QmakeParserNodeStaticData providing information and icons
							 | 
						||
| 
								 | 
							
								// for file types and the project. Do some magic via qAddPostRoutine()
							 | 
						||
| 
								 | 
							
								// to make sure the icons do not outlive QApplication, triggering warnings on X11.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct FileTypeDataStorage {
							 | 
						||
| 
								 | 
							
								    FileType type;
							 | 
						||
| 
								 | 
							
								    const char *typeName;
							 | 
						||
| 
								 | 
							
								    const char *icon;
							 | 
						||
| 
								 | 
							
								    const char *addFileFilter;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const FileTypeDataStorage fileTypeDataStorage[] = {
							 | 
						||
| 
								 | 
							
								    { FileType::Header, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakeParserPriFileNode", "Headers"),
							 | 
						||
| 
								 | 
							
								      ProjectExplorer::Constants::FILEOVERLAY_H, "*.h; *.hh; *.hpp; *.hxx;"},
							 | 
						||
| 
								 | 
							
								    { FileType::Source, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakeParserPriFileNode", "Sources"),
							 | 
						||
| 
								 | 
							
								      ProjectExplorer::Constants::FILEOVERLAY_CPP, "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++;" },
							 | 
						||
| 
								 | 
							
								    { FileType::Form, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakeParserPriFileNode", "Forms"),
							 | 
						||
| 
								 | 
							
								      Constants::FILEOVERLAY_UI, "*.ui;" },
							 | 
						||
| 
								 | 
							
								    { FileType::StateChart, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakeParserPriFileNode", "State charts"),
							 | 
						||
| 
								 | 
							
								      ProjectExplorer::Constants::FILEOVERLAY_SCXML, "*.scxml;" },
							 | 
						||
| 
								 | 
							
								    { FileType::Resource, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakeParserPriFileNode", "Resources"),
							 | 
						||
| 
								 | 
							
								      ProjectExplorer::Constants::FILEOVERLAY_QRC, "*.qrc;" },
							 | 
						||
| 
								 | 
							
								    { FileType::QML, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakeParserPriFileNode", "QML"),
							 | 
						||
| 
								 | 
							
								      ProjectExplorer::Constants::FILEOVERLAY_QML, "*.qml;" },
							 | 
						||
| 
								 | 
							
								    { FileType::Unknown, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakeParserPriFileNode", "Other files"),
							 | 
						||
| 
								 | 
							
								      ProjectExplorer::Constants::FILEOVERLAY_UNKNOWN, "*;" }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class QmakeParserNodeStaticData {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    class FileTypeData {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        FileTypeData(FileType t = FileType::Unknown,
							 | 
						||
| 
								 | 
							
								                     const QString &tN = QString(),
							 | 
						||
| 
								 | 
							
								                     const QString &aff = QString(),
							 | 
						||
| 
								 | 
							
								                     const QIcon &i = QIcon()) :
							 | 
						||
| 
								 | 
							
								        type(t), typeName(tN), addFileFilter(aff), icon(i) { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        FileType type;
							 | 
						||
| 
								 | 
							
								        QString typeName;
							 | 
						||
| 
								 | 
							
								        QString addFileFilter;
							 | 
						||
| 
								 | 
							
								        QIcon icon;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QmakeParserNodeStaticData();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QVector<FileTypeData> fileTypeData;
							 | 
						||
| 
								 | 
							
								    QIcon projectIcon;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void clearQmakeParserNodeStaticData();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeParserNodeStaticData::QmakeParserNodeStaticData()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // File type data
							 | 
						||
| 
								 | 
							
								    const unsigned count = sizeof(fileTypeDataStorage)/sizeof(FileTypeDataStorage);
							 | 
						||
| 
								 | 
							
								    fileTypeData.reserve(count);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Overlay the SP_DirIcon with the custom icons
							 | 
						||
| 
								 | 
							
								    const QSize desiredSize = QSize(16, 16);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const QPixmap dirPixmap = qApp->style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize);
							 | 
						||
| 
								 | 
							
								    for (unsigned i = 0 ; i < count; ++i) {
							 | 
						||
| 
								 | 
							
								        const QIcon overlayIcon(QLatin1String(fileTypeDataStorage[i].icon));
							 | 
						||
| 
								 | 
							
								        QIcon folderIcon;
							 | 
						||
| 
								 | 
							
								        folderIcon.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
							 | 
						||
| 
								 | 
							
								        const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakeParserPriFileNode", fileTypeDataStorage[i].typeName);
							 | 
						||
| 
								 | 
							
								        const QString filter = QString::fromUtf8(fileTypeDataStorage[i].addFileFilter);
							 | 
						||
| 
								 | 
							
								        fileTypeData.push_back(QmakeParserNodeStaticData::FileTypeData(fileTypeDataStorage[i].type,
							 | 
						||
| 
								 | 
							
								                                                                 desc, filter, folderIcon));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    // Project icon
							 | 
						||
| 
								 | 
							
								    const QIcon projectBaseIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
							 | 
						||
| 
								 | 
							
								    const QPixmap projectPixmap = FileIconProvider::overlayIcon(dirPixmap, projectBaseIcon);
							 | 
						||
| 
								 | 
							
								    projectIcon.addPixmap(projectPixmap);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    qAddPostRoutine(clearQmakeParserNodeStaticData);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Q_GLOBAL_STATIC(QmakeParserNodeStaticData, qmakeParserNodeStaticData)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void clearQmakeParserNodeStaticData()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    qmakeParserNodeStaticData()->fileTypeData.clear();
							 | 
						||
| 
								 | 
							
								    qmakeParserNodeStaticData()->projectIcon = QIcon();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum { debug = 0 };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using namespace QmakeProjectManager;
							 | 
						||
| 
								 | 
							
								using namespace QmakeProjectManager::Internal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace QmakeProjectManager {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint qHash(Variable key, uint seed) { return ::qHash(static_cast<int>(key), seed); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace Internal {
							 | 
						||
| 
								 | 
							
								class QmakeEvalInput
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    QString projectDir;
							 | 
						||
| 
								 | 
							
								    FileName projectFilePath;
							 | 
						||
| 
								 | 
							
								    QString buildDirectory;
							 | 
						||
| 
								 | 
							
								    QString sysroot;
							 | 
						||
| 
								 | 
							
								    QtSupport::ProFileReader *readerExact;
							 | 
						||
| 
								 | 
							
								    QtSupport::ProFileReader *readerCumulative;
							 | 
						||
| 
								 | 
							
								    QMakeGlobals *qmakeGlobals;
							 | 
						||
| 
								 | 
							
								    QMakeVfs *qmakeVfs;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class QmakePriFileEvalResult
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    QStringList folders;
							 | 
						||
| 
								 | 
							
								    QSet<FileName> recursiveEnumerateFiles;
							 | 
						||
| 
								 | 
							
								    QMap<FileType, QSet<FileName> > foundFiles;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class QmakeIncludedPriFile
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    ProFile *proFile;
							 | 
						||
| 
								 | 
							
								    Utils::FileName name;
							 | 
						||
| 
								 | 
							
								    QmakePriFileEvalResult result;
							 | 
						||
| 
								 | 
							
								    QMap<Utils::FileName, QmakeIncludedPriFile *> children;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ~QmakeIncludedPriFile()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        qDeleteAll(children);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class QmakeEvalResult
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    enum EvalResultState { EvalAbort, EvalFail, EvalPartial, EvalOk };
							 | 
						||
| 
								 | 
							
								    EvalResultState state;
							 | 
						||
| 
								 | 
							
								    ProjectType projectType;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList subProjectsNotToDeploy;
							 | 
						||
| 
								 | 
							
								    QSet<FileName> exactSubdirs;
							 | 
						||
| 
								 | 
							
								    QmakeIncludedPriFile includedFiles;
							 | 
						||
| 
								 | 
							
								    TargetParserInformation targetInformation;
							 | 
						||
| 
								 | 
							
								    InstallsParserList installsList;
							 | 
						||
| 
								 | 
							
								    QHash<Variable, QStringList> newVarValues;
							 | 
						||
| 
								 | 
							
								    QStringList errors;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class QmakeParserPriFile : public Core::IDocument
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    QmakeParserPriFile(QmakeParserPriFileNode *qmakePriFile)
							 | 
						||
| 
								 | 
							
								        : IDocument(nullptr), m_priFile(qmakePriFile)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        setId("Qmake.PriFile");
							 | 
						||
| 
								 | 
							
								        setMimeType(QLatin1String(QmakeProjectManager::Constants::PROFILE_MIMETYPE));
							 | 
						||
| 
								 | 
							
								        setFilePath(m_priFile->filePath());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        Q_UNUSED(state)
							 | 
						||
| 
								 | 
							
								        Q_UNUSED(type)
							 | 
						||
| 
								 | 
							
								        return BehaviorSilent;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        Q_UNUSED(errorString)
							 | 
						||
| 
								 | 
							
								        Q_UNUSED(flag)
							 | 
						||
| 
								 | 
							
								        if (type == TypePermissions)
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        m_priFile->scheduleUpdate();
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    QmakeParserPriFileNode *m_priFile;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ProParserVirtualFolderNode : public VirtualFolderNode
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    ProParserVirtualFolderNode(InternalParserNode *node);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QString displayName() const final { return m_typeName; }
							 | 
						||
| 
								 | 
							
								    QString addFileFilter() const final { return m_addFileFilter; }
							 | 
						||
| 
								 | 
							
								    QString tooltip() const final { return QString(); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    QString m_typeName;
							 | 
						||
| 
								 | 
							
								    QString m_addFileFilter;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct InternalParserNode
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QList<InternalParserNode *> virtualfolders;
							 | 
						||
| 
								 | 
							
								    QMap<QString, InternalParserNode *> subnodes;
							 | 
						||
| 
								 | 
							
								    FileNameList files;
							 | 
						||
| 
								 | 
							
								    FileType type = FileType::Unknown;
							 | 
						||
| 
								 | 
							
								    int priority = Node::DefaultVirtualFolderPriority;
							 | 
						||
| 
								 | 
							
								    QString displayName;
							 | 
						||
| 
								 | 
							
								    QString typeName;
							 | 
						||
| 
								 | 
							
								    QString addFileFilter;
							 | 
						||
| 
								 | 
							
								    QString fullPath;
							 | 
						||
| 
								 | 
							
								    QIcon icon;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ~InternalParserNode()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        qDeleteAll(virtualfolders);
							 | 
						||
| 
								 | 
							
								        qDeleteAll(subnodes);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Creates: a tree structure from a list of absolute file paths.
							 | 
						||
| 
								 | 
							
								    // Empty directories are compressed into a single entry with a longer path.
							 | 
						||
| 
								 | 
							
								    // * project
							 | 
						||
| 
								 | 
							
								    //    * /absolute/path
							 | 
						||
| 
								 | 
							
								    //       * file1
							 | 
						||
| 
								 | 
							
								    //    * relative
							 | 
						||
| 
								 | 
							
								    //       * path1
							 | 
						||
| 
								 | 
							
								    //          * file1
							 | 
						||
| 
								 | 
							
								    //          * file2
							 | 
						||
| 
								 | 
							
								    //       * path2
							 | 
						||
| 
								 | 
							
								    //          * file1
							 | 
						||
| 
								 | 
							
								    // The function first creates a tree that looks like the directory structure, i.e.
							 | 
						||
| 
								 | 
							
								    //    * /
							 | 
						||
| 
								 | 
							
								    //       * absolute
							 | 
						||
| 
								 | 
							
								    //          * path
							 | 
						||
| 
								 | 
							
								    // ...
							 | 
						||
| 
								 | 
							
								    // and afterwards calls compress() which merges directory nodes with single children, i.e. to
							 | 
						||
| 
								 | 
							
								    //    * /absolute/path
							 | 
						||
| 
								 | 
							
								    void create(const QString &projectDir, const QSet<FileName> &newFilePaths, FileType type)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        static const QChar separator = QLatin1Char('/');
							 | 
						||
| 
								 | 
							
								        const FileName projectDirFileName = FileName::fromString(projectDir);
							 | 
						||
| 
								 | 
							
								        foreach (const FileName &file, newFilePaths) {
							 | 
						||
| 
								 | 
							
								            FileName fileWithoutPrefix;
							 | 
						||
| 
								 | 
							
								            bool isRelative;
							 | 
						||
| 
								 | 
							
								            if (file.isChildOf(projectDirFileName)) {
							 | 
						||
| 
								 | 
							
								                isRelative = true;
							 | 
						||
| 
								 | 
							
								                fileWithoutPrefix = file.relativeChildPath(projectDirFileName);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                isRelative = false;
							 | 
						||
| 
								 | 
							
								                fileWithoutPrefix = file;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            QStringList parts = fileWithoutPrefix.toString().split(separator, QString::SkipEmptyParts);
							 | 
						||
| 
								 | 
							
								            if (!HostOsInfo::isWindowsHost() && !isRelative && parts.count() > 0)
							 | 
						||
| 
								 | 
							
								                parts[0].prepend(separator);
							 | 
						||
| 
								 | 
							
								            QStringListIterator it(parts);
							 | 
						||
| 
								 | 
							
								            InternalParserNode *currentNode = this;
							 | 
						||
| 
								 | 
							
								            QString path = (isRelative ? (projectDirFileName.toString() + QLatin1Char('/')) : QString());
							 | 
						||
| 
								 | 
							
								            while (it.hasNext()) {
							 | 
						||
| 
								 | 
							
								                const QString &key = it.next();
							 | 
						||
| 
								 | 
							
								                if (it.hasNext()) { // key is directory
							 | 
						||
| 
								 | 
							
								                    path += key;
							 | 
						||
| 
								 | 
							
								                    if (!currentNode->subnodes.contains(path)) {
							 | 
						||
| 
								 | 
							
								                        InternalParserNode *val = new InternalParserNode;
							 | 
						||
| 
								 | 
							
								                        val->type = type;
							 | 
						||
| 
								 | 
							
								                        val->fullPath = path;
							 | 
						||
| 
								 | 
							
								                        val->displayName = key;
							 | 
						||
| 
								 | 
							
								                        currentNode->subnodes.insert(path, val);
							 | 
						||
| 
								 | 
							
								                        currentNode = val;
							 | 
						||
| 
								 | 
							
								                    } else {
							 | 
						||
| 
								 | 
							
								                        currentNode = currentNode->subnodes.value(path);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    path += separator;
							 | 
						||
| 
								 | 
							
								                } else { // key is filename
							 | 
						||
| 
								 | 
							
								                    currentNode->files.append(file);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        this->compress();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Removes folder nodes with only a single sub folder in it
							 | 
						||
| 
								 | 
							
								    void compress()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        QMap<QString, InternalParserNode*> newSubnodes;
							 | 
						||
| 
								 | 
							
								        QMapIterator<QString, InternalParserNode*> i(subnodes);
							 | 
						||
| 
								 | 
							
								        while (i.hasNext()) {
							 | 
						||
| 
								 | 
							
								            i.next();
							 | 
						||
| 
								 | 
							
								            i.value()->compress();
							 | 
						||
| 
								 | 
							
								            if (i.value()->files.isEmpty() && i.value()->subnodes.size() == 1) {
							 | 
						||
| 
								 | 
							
								                // replace i.value() by i.value()->subnodes.begin()
							 | 
						||
| 
								 | 
							
								                QString key = i.value()->subnodes.begin().key();
							 | 
						||
| 
								 | 
							
								                InternalParserNode *keep = i.value()->subnodes.value(key);
							 | 
						||
| 
								 | 
							
								                keep->displayName = i.value()->displayName + QDir::separator() + keep->displayName;
							 | 
						||
| 
								 | 
							
								                newSubnodes.insert(key, keep);
							 | 
						||
| 
								 | 
							
								                i.value()->subnodes.clear();
							 | 
						||
| 
								 | 
							
								                delete i.value();
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                newSubnodes.insert(i.key(), i.value());
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        subnodes = newSubnodes;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    FolderNode *createFolderNode(InternalParserNode *node)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        FolderNode *newNode = 0;
							 | 
						||
| 
								 | 
							
								        if (node->typeName.isEmpty())
							 | 
						||
| 
								 | 
							
								            newNode = new FolderNode(FileName::fromString(node->fullPath));
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            newNode = new ProParserVirtualFolderNode(node);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        newNode->setDisplayName(node->displayName);
							 | 
						||
| 
								 | 
							
								        if (!node->icon.isNull())
							 | 
						||
| 
								 | 
							
								            newNode->setIcon(node->icon);
							 | 
						||
| 
								 | 
							
								        return newNode;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Makes the projectNode's subtree below the given folder match this internal node's subtree
							 | 
						||
| 
								 | 
							
								    void addSubFolderContents(FolderNode *folder)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (type == FileType::Resource) {
							 | 
						||
| 
								 | 
							
								            for (const FileName &file : files) {
							 | 
						||
| 
								 | 
							
								                auto vfs = static_cast<QmakeParserPriFileNode *>(folder->parentProjectNode())->m_project->qmakeVfs();
							 | 
						||
| 
								 | 
							
								                QString contents;
							 | 
						||
| 
								 | 
							
								                // Prefer the cumulative file if it's non-empty, based on the assumption
							 | 
						||
| 
								 | 
							
								                // that it contains more "stuff".
							 | 
						||
| 
								 | 
							
								                vfs->readVirtualFile(file.toString(), QMakeVfs::VfsCumulative, &contents);
							 | 
						||
| 
								 | 
							
								                // If the cumulative evaluation botched the file too much, try the exact one.
							 | 
						||
| 
								 | 
							
								                if (contents.isEmpty())
							 | 
						||
| 
								 | 
							
								                    vfs->readVirtualFile(file.toString(), QMakeVfs::VfsExact, &contents);
							 | 
						||
| 
								 | 
							
								                auto resourceNode = new ResourceEditor::ResourceTopLevelNode(file, contents, folder);
							 | 
						||
| 
								 | 
							
								                folder->addNode(resourceNode);
							 | 
						||
| 
								 | 
							
								                resourceNode->addInternalNodes();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            for (const FileName &file : files)
							 | 
						||
| 
								 | 
							
								                folder->addNode(new FileNode(file, type, false));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Virtual
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            for (InternalParserNode *node : virtualfolders) {
							 | 
						||
| 
								 | 
							
								                FolderNode *newNode = createFolderNode(node);
							 | 
						||
| 
								 | 
							
								                folder->addNode(newNode);
							 | 
						||
| 
								 | 
							
								                node->addSubFolderContents(newNode);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        // Subnodes
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            QMap<QString, InternalParserNode *>::const_iterator it = subnodes.constBegin();
							 | 
						||
| 
								 | 
							
								            QMap<QString, InternalParserNode *>::const_iterator end = subnodes.constEnd();
							 | 
						||
| 
								 | 
							
								            for ( ; it != end; ++it) {
							 | 
						||
| 
								 | 
							
								                FolderNode *newNode = createFolderNode(it.value());
							 | 
						||
| 
								 | 
							
								                folder->addNode(newNode);
							 | 
						||
| 
								 | 
							
								                it.value()->addSubFolderContents(newNode);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ProParserVirtualFolderNode::ProParserVirtualFolderNode(InternalParserNode *node)
							 | 
						||
| 
								 | 
							
								    : VirtualFolderNode(FileName::fromString(node->fullPath), node->priority),
							 | 
						||
| 
								 | 
							
								      m_typeName(node->typeName),
							 | 
						||
| 
								 | 
							
								      m_addFileFilter(node->addFileFilter)
							 | 
						||
| 
								 | 
							
								{}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // Internal
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								  \class QmakeParserPriFileNode
							 | 
						||
| 
								 | 
							
								  Implements abstract ProjectNode class
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeParserPriFileNode::QmakeParserPriFileNode(QmakeProject *project,
							 | 
						||
| 
								 | 
							
								                                               QmakeParserProFileNode *qmakeProFileNode,
							 | 
						||
| 
								 | 
							
								                                               const FileName &filePath)
							 | 
						||
| 
								 | 
							
								    : ProjectNode(filePath),
							 | 
						||
| 
								 | 
							
								      m_project(project),
							 | 
						||
| 
								 | 
							
								      m_qmakeProFileNode(qmakeProFileNode),
							 | 
						||
| 
								 | 
							
								      m_projectFilePath(filePath),
							 | 
						||
| 
								 | 
							
								      m_projectDir(filePath.toFileInfo().absolutePath())
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Q_ASSERT(project);
							 | 
						||
| 
								 | 
							
								    m_qmakePriFile = new QmakeParserPriFile(this);
							 | 
						||
| 
								 | 
							
								    Core::DocumentManager::addDocument(m_qmakePriFile);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    setDisplayName(filePath.toFileInfo().completeBaseName());
							 | 
						||
| 
								 | 
							
								    setIcon(qmakeParserNodeStaticData()->projectIcon);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeParserPriFileNode::~QmakeParserPriFileNode()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    watchFolders(QSet<QString>());
							 | 
						||
| 
								 | 
							
								    delete m_qmakePriFile;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::scheduleUpdate()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								    m_qmakeProFileNode->scheduleUpdate(QmakeParserProFileNode::ParseLater);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserPriFileNode::baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList result;
							 | 
						||
| 
								 | 
							
								    if (!reader)
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    result += reader->absolutePathValues(QLatin1String("VPATH"), projectDir);
							 | 
						||
| 
								 | 
							
								    result << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH
							 | 
						||
| 
								 | 
							
								    result << buildDir;
							 | 
						||
| 
								 | 
							
								    result.removeDuplicates();
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserPriFileNode::fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader,
							 | 
						||
| 
								 | 
							
								                                               const QString &qmakeVariable, const QString &projectDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList vPaths;
							 | 
						||
| 
								 | 
							
								    if (!reader)
							 | 
						||
| 
								 | 
							
								        return vPaths;
							 | 
						||
| 
								 | 
							
								    vPaths = reader->absolutePathValues(QLatin1String("VPATH_") + qmakeVariable, projectDir);
							 | 
						||
| 
								 | 
							
								    vPaths += baseVPaths;
							 | 
						||
| 
								 | 
							
								    vPaths.removeDuplicates();
							 | 
						||
| 
								 | 
							
								    return vPaths;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QSet<FileName> QmakeParserPriFileNode::recursiveEnumerate(const QString &folder)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QSet<FileName> result;
							 | 
						||
| 
								 | 
							
								    QDir dir(folder);
							 | 
						||
| 
								 | 
							
								    dir.setFilter(dir.filter() | QDir::NoDotAndDotDot);
							 | 
						||
| 
								 | 
							
								    foreach (const QFileInfo &file, dir.entryInfoList()) {
							 | 
						||
| 
								 | 
							
								        if (file.isDir() && !file.isSymLink())
							 | 
						||
| 
								 | 
							
								            result += recursiveEnumerate(file.absoluteFilePath());
							 | 
						||
| 
								 | 
							
								        else if (!Core::EditorManager::isAutoSaveFile(file.fileName()))
							 | 
						||
| 
								 | 
							
								            result += FileName(file);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static QStringList fileListForVar(
							 | 
						||
| 
								 | 
							
								        const QHash<QString, QVector<ProFileEvaluator::SourceFile> > &sourceFiles,
							 | 
						||
| 
								 | 
							
								        const QString &varName)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    const QVector<ProFileEvaluator::SourceFile> &sources = sourceFiles[varName];
							 | 
						||
| 
								 | 
							
								    QStringList result;
							 | 
						||
| 
								 | 
							
								    result.reserve(sources.size());
							 | 
						||
| 
								 | 
							
								    foreach (const ProFileEvaluator::SourceFile &sf, sources)
							 | 
						||
| 
								 | 
							
								        result << sf.fileName;
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::extractSources(
							 | 
						||
| 
								 | 
							
								        QHash<const ProFile *, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
							 | 
						||
| 
								 | 
							
								        QVector<ProFileEvaluator::SourceFile> sourceFiles, FileType type)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    foreach (const ProFileEvaluator::SourceFile &source, sourceFiles) {
							 | 
						||
| 
								 | 
							
								        QmakePriFileEvalResult *result = proToResult.value(source.proFile);
							 | 
						||
| 
								 | 
							
								        if (!result)
							 | 
						||
| 
								 | 
							
								            result = fallback;
							 | 
						||
| 
								 | 
							
								        result->foundFiles[type].insert(FileName::fromString(source.fileName));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::extractInstalls(
							 | 
						||
| 
								 | 
							
								        QHash<const ProFile *, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
							 | 
						||
| 
								 | 
							
								        const InstallsParserList &installList)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    for (const InstallsParserItem &item : installList.items) {
							 | 
						||
| 
								 | 
							
								        for (const ProFileEvaluator::SourceFile &source : item.files) {
							 | 
						||
| 
								 | 
							
								            auto *result = proToResult.value(source.proFile);
							 | 
						||
| 
								 | 
							
								            if (!result)
							 | 
						||
| 
								 | 
							
								                result = fallback;
							 | 
						||
| 
								 | 
							
								            result->folders << source.fileName;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::processValues(QmakePriFileEvalResult &result)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    result.folders.removeDuplicates();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Remove non existing items and non folders
							 | 
						||
| 
								 | 
							
								    QStringList::iterator it = result.folders.begin();
							 | 
						||
| 
								 | 
							
								    while (it != result.folders.end()) {
							 | 
						||
| 
								 | 
							
								        QFileInfo fi(*it);
							 | 
						||
| 
								 | 
							
								        if (fi.exists()) {
							 | 
						||
| 
								 | 
							
								            if (fi.isDir()) {
							 | 
						||
| 
								 | 
							
								                // keep directories
							 | 
						||
| 
								 | 
							
								                ++it;
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                // move files directly to recursiveEnumerateFiles
							 | 
						||
| 
								 | 
							
								                result.recursiveEnumerateFiles << FileName::fromString(*it);
							 | 
						||
| 
								 | 
							
								                it = result.folders.erase(it);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            // do remove non exsting stuff
							 | 
						||
| 
								 | 
							
								            it = result.folders.erase(it);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach (const QString &folder, result.folders)
							 | 
						||
| 
								 | 
							
								        result.recursiveEnumerateFiles += recursiveEnumerate(folder);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const QVector<QmakeParserNodeStaticData::FileTypeData> &fileTypes = qmakeParserNodeStaticData()->fileTypeData;
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < fileTypes.size(); ++i) {
							 | 
						||
| 
								 | 
							
								        FileType type = fileTypes.at(i).type;
							 | 
						||
| 
								 | 
							
								        QSet<FileName> &foundFiles = result.foundFiles[type];
							 | 
						||
| 
								 | 
							
								        result.recursiveEnumerateFiles.subtract(foundFiles);
							 | 
						||
| 
								 | 
							
								        QSet<FileName> newFilePaths = filterFilesProVariables(type, foundFiles);
							 | 
						||
| 
								 | 
							
								        newFilePaths += filterFilesRecursiveEnumerata(type, result.recursiveEnumerateFiles);
							 | 
						||
| 
								 | 
							
								        foundFiles = newFilePaths;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::update(const Internal::QmakePriFileEvalResult &result)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // add project file node
							 | 
						||
| 
								 | 
							
								    if (fileNodes().isEmpty())
							 | 
						||
| 
								 | 
							
								        addNode(new FileNode(m_projectFilePath, FileType::Project, false));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_recursiveEnumerateFiles = result.recursiveEnumerateFiles;
							 | 
						||
| 
								 | 
							
								    watchFolders(result.folders.toSet());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    InternalParserNode contents;
							 | 
						||
| 
								 | 
							
								    const QVector<QmakeParserNodeStaticData::FileTypeData> &fileTypes = qmakeParserNodeStaticData()->fileTypeData;
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < fileTypes.size(); ++i) {
							 | 
						||
| 
								 | 
							
								        FileType type = fileTypes.at(i).type;
							 | 
						||
| 
								 | 
							
								        const QSet<FileName> &newFilePaths = result.foundFiles.value(type);
							 | 
						||
| 
								 | 
							
								        // We only need to save this information if
							 | 
						||
| 
								 | 
							
								        // we are watching folders
							 | 
						||
| 
								 | 
							
								        if (!result.folders.isEmpty())
							 | 
						||
| 
								 | 
							
								            m_files[type] = newFilePaths;
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            m_files[type].clear();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!newFilePaths.isEmpty()) {
							 | 
						||
| 
								 | 
							
								            InternalParserNode *subfolder = new InternalParserNode;
							 | 
						||
| 
								 | 
							
								            subfolder->type = type;
							 | 
						||
| 
								 | 
							
								            subfolder->icon = fileTypes.at(i).icon;
							 | 
						||
| 
								 | 
							
								            subfolder->fullPath = m_projectDir;
							 | 
						||
| 
								 | 
							
								            subfolder->typeName = fileTypes.at(i).typeName;
							 | 
						||
| 
								 | 
							
								            subfolder->addFileFilter = fileTypes.at(i).addFileFilter;
							 | 
						||
| 
								 | 
							
								            subfolder->priority = Node::DefaultVirtualFolderPriority - i;
							 | 
						||
| 
								 | 
							
								            subfolder->displayName = fileTypes.at(i).typeName;
							 | 
						||
| 
								 | 
							
								            contents.virtualfolders.append(subfolder);
							 | 
						||
| 
								 | 
							
								            // create the hierarchy with subdirectories
							 | 
						||
| 
								 | 
							
								            subfolder->create(m_projectDir, newFilePaths, type);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    contents.addSubFolderContents(this);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::watchFolders(const QSet<QString> &folders)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QSet<QString> toUnwatch = m_watchedFolders;
							 | 
						||
| 
								 | 
							
								    toUnwatch.subtract(folders);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QSet<QString> toWatch = folders;
							 | 
						||
| 
								 | 
							
								    toWatch.subtract(m_watchedFolders);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if 0 // Enable again!
							 | 
						||
| 
								 | 
							
								    if (!toUnwatch.isEmpty())
							 | 
						||
| 
								 | 
							
								        m_project->unwatchFolders(toUnwatch.toList(), this);
							 | 
						||
| 
								 | 
							
								    if (!toWatch.isEmpty())
							 | 
						||
| 
								 | 
							
								        m_project->watchFolders(toWatch.toList(), this);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_watchedFolders = folders;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::folderChanged(const QString &changedFolder, const QSet<FileName> &newFiles)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    //qDebug()<<"########## QmakeParserPriFileNode::folderChanged";
							 | 
						||
| 
								 | 
							
								    // So, we need to figure out which files changed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QSet<FileName> addedFiles = newFiles;
							 | 
						||
| 
								 | 
							
								    addedFiles.subtract(m_recursiveEnumerateFiles);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QSet<FileName> removedFiles = m_recursiveEnumerateFiles;
							 | 
						||
| 
								 | 
							
								    removedFiles.subtract(newFiles);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach (const FileName &file, removedFiles) {
							 | 
						||
| 
								 | 
							
								        if (!file.isChildOf(FileName::fromString(changedFolder)))
							 | 
						||
| 
								 | 
							
								            removedFiles.remove(file);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (addedFiles.isEmpty() && removedFiles.isEmpty())
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_recursiveEnumerateFiles = newFiles;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Apply the differences
							 | 
						||
| 
								 | 
							
								    // per file type
							 | 
						||
| 
								 | 
							
								    const QVector<QmakeParserNodeStaticData::FileTypeData> &fileTypes = qmakeParserNodeStaticData()->fileTypeData;
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < fileTypes.size(); ++i) {
							 | 
						||
| 
								 | 
							
								        FileType type = fileTypes.at(i).type;
							 | 
						||
| 
								 | 
							
								        QSet<FileName> add = filterFilesRecursiveEnumerata(type, addedFiles);
							 | 
						||
| 
								 | 
							
								        QSet<FileName> remove = filterFilesRecursiveEnumerata(type, removedFiles);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!add.isEmpty() || !remove.isEmpty()) {
							 | 
						||
| 
								 | 
							
								            // Scream :)
							 | 
						||
| 
								 | 
							
								//            qDebug()<<"For type"<<fileTypes.at(i).typeName<<"\n"
							 | 
						||
| 
								 | 
							
								//                    <<"added files"<<add<<"\n"
							 | 
						||
| 
								 | 
							
								//                    <<"removed files"<<remove;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            m_files[type].unite(add);
							 | 
						||
| 
								 | 
							
								            m_files[type].subtract(remove);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Now apply stuff
							 | 
						||
| 
								 | 
							
								    InternalParserNode contents;
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < fileTypes.size(); ++i) {
							 | 
						||
| 
								 | 
							
								        FileType type = fileTypes.at(i).type;
							 | 
						||
| 
								 | 
							
								        if (!m_files[type].isEmpty()) {
							 | 
						||
| 
								 | 
							
								            InternalParserNode *subfolder = new InternalParserNode;
							 | 
						||
| 
								 | 
							
								            subfolder->type = type;
							 | 
						||
| 
								 | 
							
								            subfolder->icon = fileTypes.at(i).icon;
							 | 
						||
| 
								 | 
							
								            subfolder->fullPath = m_projectDir;
							 | 
						||
| 
								 | 
							
								            subfolder->typeName = fileTypes.at(i).typeName;
							 | 
						||
| 
								 | 
							
								            subfolder->priority = Node::DefaultVirtualFolderPriority - i;
							 | 
						||
| 
								 | 
							
								            subfolder->displayName = fileTypes.at(i).typeName;
							 | 
						||
| 
								 | 
							
								            contents.virtualfolders.append(subfolder);
							 | 
						||
| 
								 | 
							
								            // create the hierarchy with subdirectories
							 | 
						||
| 
								 | 
							
								            subfolder->create(m_projectDir, m_files[type], type);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    contents.addSubFolderContents(this);
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::deploysFolder(const QString &folder) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QString f = folder;
							 | 
						||
| 
								 | 
							
								    const QChar slash = QLatin1Char('/');
							 | 
						||
| 
								 | 
							
								    if (!f.endsWith(slash))
							 | 
						||
| 
								 | 
							
								        f.append(slash);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach (const QString &wf, m_watchedFolders) {
							 | 
						||
| 
								 | 
							
								        if (f.startsWith(wf)
							 | 
						||
| 
								 | 
							
								            && (wf.endsWith(slash)
							 | 
						||
| 
								 | 
							
								                || (wf.length() < f.length() && f.at(wf.length()) == slash)))
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QList<RunConfiguration *> QmakeParserPriFileNode::runConfigurations() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QmakeRunConfigurationFactory *factory = QmakeRunConfigurationFactory::find(m_project->activeTarget());
							 | 
						||
| 
								 | 
							
								    if (factory)
							 | 
						||
| 
								 | 
							
								        return factory->runConfigurationsForNode(m_project->activeTarget(), this);
							 | 
						||
| 
								 | 
							
								    return QList<RunConfiguration *>();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QList<QmakeParserPriFileNode *> QmakeParserPriFileNode::subProjectNodesExact() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QList<QmakeParserPriFileNode *> nodes;
							 | 
						||
| 
								 | 
							
								    foreach (ProjectNode *node, projectNodes()) {
							 | 
						||
| 
								 | 
							
								        QmakeParserPriFileNode *n = dynamic_cast<QmakeParserPriFileNode *>(node);
							 | 
						||
| 
								 | 
							
								        if (n && n->includedInExactParse())
							 | 
						||
| 
								 | 
							
								            nodes << n;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return nodes;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeParserProFileNode *QmakeParserPriFileNode::proFileNode() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_qmakeProFileNode;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::includedInExactParse() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_includedInExactParse;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::setIncludedInExactParse(bool b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_includedInExactParse = b;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QList<ProjectAction> QmakeParserPriFileNode::supportedActions(Node *node) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QList<ProjectAction> actions;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const FolderNode *folderNode = this;
							 | 
						||
| 
								 | 
							
								    const QmakeParserProFileNode *proFileNode;
							 | 
						||
| 
								 | 
							
								    while (!(proFileNode = dynamic_cast<const QmakeParserProFileNode*>(folderNode)))
							 | 
						||
| 
								 | 
							
								        folderNode = folderNode->parentFolderNode();
							 | 
						||
| 
								 | 
							
								    Q_ASSERT(proFileNode);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch (proFileNode->projectType()) {
							 | 
						||
| 
								 | 
							
								    case ProjectType::ApplicationTemplate:
							 | 
						||
| 
								 | 
							
								    case ProjectType::StaticLibraryTemplate:
							 | 
						||
| 
								 | 
							
								    case ProjectType::SharedLibraryTemplate:
							 | 
						||
| 
								 | 
							
								    case ProjectType::AuxTemplate: {
							 | 
						||
| 
								 | 
							
								        // TODO: Some of the file types don't make much sense for aux
							 | 
						||
| 
								 | 
							
								        // projects (e.g. cpp). It'd be nice if the "add" action could
							 | 
						||
| 
								 | 
							
								        // work on a subset of the file types according to project type.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        actions << AddNewFile;
							 | 
						||
| 
								 | 
							
								        if (m_recursiveEnumerateFiles.contains(node->filePath()))
							 | 
						||
| 
								 | 
							
								            actions << EraseFile;
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            actions << RemoveFile;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        bool addExistingFiles = true;
							 | 
						||
| 
								 | 
							
								        if (node->nodeType() == NodeType::VirtualFolder) {
							 | 
						||
| 
								 | 
							
								            // A virtual folder, we do what the projectexplorer does
							 | 
						||
| 
								 | 
							
								            FolderNode *folder = node->asFolderNode();
							 | 
						||
| 
								 | 
							
								            if (folder) {
							 | 
						||
| 
								 | 
							
								                QStringList list;
							 | 
						||
| 
								 | 
							
								                foreach (FolderNode *f, folder->folderNodes())
							 | 
						||
| 
								 | 
							
								                    list << f->filePath().toString() + QLatin1Char('/');
							 | 
						||
| 
								 | 
							
								                if (deploysFolder(Utils::commonPath(list)))
							 | 
						||
| 
								 | 
							
								                    addExistingFiles = false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        addExistingFiles = addExistingFiles && !deploysFolder(node->filePath().toString());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (addExistingFiles)
							 | 
						||
| 
								 | 
							
								            actions << AddExistingFile << AddExistingDirectory;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    case ProjectType::SubDirsTemplate:
							 | 
						||
| 
								 | 
							
								        actions << AddSubProject << RemoveSubProject;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    FileNode *fileNode = node->asFileNode();
							 | 
						||
| 
								 | 
							
								    if ((fileNode && fileNode->fileType() != FileType::Project)
							 | 
						||
| 
								 | 
							
								            || dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(node)) {
							 | 
						||
| 
								 | 
							
								        actions << Rename;
							 | 
						||
| 
								 | 
							
								        actions << DuplicateFile;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Target *target = m_project->activeTarget();
							 | 
						||
| 
								 | 
							
								    QmakeRunConfigurationFactory *factory = QmakeRunConfigurationFactory::find(target);
							 | 
						||
| 
								 | 
							
								    if (factory && !factory->runConfigurationsForNode(target, node).isEmpty())
							 | 
						||
| 
								 | 
							
								        actions << HasSubProjectRunConfigurations;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return actions;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::canAddSubProject(const QString &proFilePath) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QFileInfo fi(proFilePath);
							 | 
						||
| 
								 | 
							
								    if (fi.suffix() == QLatin1String("pro")
							 | 
						||
| 
								 | 
							
								        || fi.suffix() == QLatin1String("pri"))
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static QString simplifyProFilePath(const QString &proFilePath)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // if proFilePath is like: _path_/projectName/projectName.pro
							 | 
						||
| 
								 | 
							
								    // we simplify it to: _path_/projectName
							 | 
						||
| 
								 | 
							
								    QFileInfo fi(proFilePath);
							 | 
						||
| 
								 | 
							
								    const QString parentPath = fi.absolutePath();
							 | 
						||
| 
								 | 
							
								    QFileInfo parentFi(parentPath);
							 | 
						||
| 
								 | 
							
								    if (parentFi.fileName() == fi.completeBaseName())
							 | 
						||
| 
								 | 
							
								        return parentPath;
							 | 
						||
| 
								 | 
							
								    return proFilePath;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::addSubProjects(const QStringList &proFilePaths)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    FindAllFilesVisitor visitor;
							 | 
						||
| 
								 | 
							
								    accept(&visitor);
							 | 
						||
| 
								 | 
							
								    const FileNameList &allFiles = visitor.filePaths();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList uniqueProFilePaths;
							 | 
						||
| 
								 | 
							
								    foreach (const QString &proFile, proFilePaths)
							 | 
						||
| 
								 | 
							
								        if (!allFiles.contains(FileName::fromString(proFile)))
							 | 
						||
| 
								 | 
							
								            uniqueProFilePaths.append(simplifyProFilePath(proFile));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList failedFiles;
							 | 
						||
| 
								 | 
							
								    changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), uniqueProFilePaths, &failedFiles, AddToProFile);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return failedFiles.isEmpty();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::removeSubProjects(const QStringList &proFilePaths)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList failedOriginalFiles;
							 | 
						||
| 
								 | 
							
								    changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), proFilePaths, &failedOriginalFiles, RemoveFromProFile);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList simplifiedProFiles = Utils::transform(failedOriginalFiles, &simplifyProFilePath);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList failedSimplifiedFiles;
							 | 
						||
| 
								 | 
							
								    changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), simplifiedProFiles, &failedSimplifiedFiles, RemoveFromProFile);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return failedSimplifiedFiles.isEmpty();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // If a file is already referenced in the .pro file then we don't add them.
							 | 
						||
| 
								 | 
							
								    // That ignores scopes and which variable was used to reference the file
							 | 
						||
| 
								 | 
							
								    // So it's obviously a bit limited, but in those cases you need to edit the
							 | 
						||
| 
								 | 
							
								    // project files manually anyway.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    FindAllFilesVisitor visitor;
							 | 
						||
| 
								 | 
							
								    accept(&visitor);
							 | 
						||
| 
								 | 
							
								    const FileNameList &allFiles = visitor.filePaths();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    typedef QMap<QString, QStringList> TypeFileMap;
							 | 
						||
| 
								 | 
							
								    // Split into lists by file type and bulk-add them.
							 | 
						||
| 
								 | 
							
								    TypeFileMap typeFileMap;
							 | 
						||
| 
								 | 
							
								    Utils::MimeDatabase mdb;
							 | 
						||
| 
								 | 
							
								    foreach (const QString &file, filePaths) {
							 | 
						||
| 
								 | 
							
								        const Utils::MimeType mt = mdb.mimeTypeForFile(file);
							 | 
						||
| 
								 | 
							
								        typeFileMap[mt.name()] << file;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList failedFiles;
							 | 
						||
| 
								 | 
							
								    foreach (const QString &type, typeFileMap.keys()) {
							 | 
						||
| 
								 | 
							
								        const QStringList typeFiles = typeFileMap.value(type);
							 | 
						||
| 
								 | 
							
								        QStringList qrcFiles; // the list of qrc files referenced from ui files
							 | 
						||
| 
								 | 
							
								        if (type == QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE)) {
							 | 
						||
| 
								 | 
							
								            foreach (const QString &formFile, typeFiles) {
							 | 
						||
| 
								 | 
							
								                QStringList resourceFiles = formResources(formFile);
							 | 
						||
| 
								 | 
							
								                foreach (const QString &resourceFile, resourceFiles)
							 | 
						||
| 
								 | 
							
								                    if (!qrcFiles.contains(resourceFile))
							 | 
						||
| 
								 | 
							
								                        qrcFiles.append(resourceFile);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        QStringList uniqueQrcFiles;
							 | 
						||
| 
								 | 
							
								        foreach (const QString &file, qrcFiles) {
							 | 
						||
| 
								 | 
							
								            if (!allFiles.contains(FileName::fromString(file)))
							 | 
						||
| 
								 | 
							
								                uniqueQrcFiles.append(file);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        QStringList uniqueFilePaths;
							 | 
						||
| 
								 | 
							
								        foreach (const QString &file, typeFiles) {
							 | 
						||
| 
								 | 
							
								            if (!allFiles.contains(FileName::fromString(file)))
							 | 
						||
| 
								 | 
							
								                uniqueFilePaths.append(file);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        changeFiles(type, uniqueFilePaths, &failedFiles, AddToProFile);
							 | 
						||
| 
								 | 
							
								        if (notAdded)
							 | 
						||
| 
								 | 
							
								            *notAdded += failedFiles;
							 | 
						||
| 
								 | 
							
								        changeFiles(QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE), uniqueQrcFiles, &failedFiles, AddToProFile);
							 | 
						||
| 
								 | 
							
								        if (notAdded)
							 | 
						||
| 
								 | 
							
								            *notAdded += failedFiles;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return failedFiles.isEmpty();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::removeFiles(const QStringList &filePaths,
							 | 
						||
| 
								 | 
							
								                              QStringList *notRemoved)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList failedFiles;
							 | 
						||
| 
								 | 
							
								    typedef QMap<QString, QStringList> TypeFileMap;
							 | 
						||
| 
								 | 
							
								    // Split into lists by file type and bulk-add them.
							 | 
						||
| 
								 | 
							
								    TypeFileMap typeFileMap;
							 | 
						||
| 
								 | 
							
								    Utils::MimeDatabase mdb;
							 | 
						||
| 
								 | 
							
								    foreach (const QString &file, filePaths) {
							 | 
						||
| 
								 | 
							
								        const Utils::MimeType mt = mdb.mimeTypeForFile(file);
							 | 
						||
| 
								 | 
							
								        typeFileMap[mt.name()] << file;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    foreach (const QString &type, typeFileMap.keys()) {
							 | 
						||
| 
								 | 
							
								        const QStringList typeFiles = typeFileMap.value(type);
							 | 
						||
| 
								 | 
							
								        changeFiles(type, typeFiles, &failedFiles, RemoveFromProFile);
							 | 
						||
| 
								 | 
							
								        if (notRemoved)
							 | 
						||
| 
								 | 
							
								            *notRemoved = failedFiles;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return failedFiles.isEmpty();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::deleteFiles(const QStringList &filePaths)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    removeFiles(filePaths);
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::canRenameFile(const QString &filePath, const QString &newFilePath)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (newFilePath.isEmpty())
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath());
							 | 
						||
| 
								 | 
							
								    if (changeProFileOptional)
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								    Utils::MimeDatabase mdb;
							 | 
						||
| 
								 | 
							
								    const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return renameFile(filePath, newFilePath, mt.name(), Change::TestOnly);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::renameFile(const QString &filePath, const QString &newFilePath)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (newFilePath.isEmpty())
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath());
							 | 
						||
| 
								 | 
							
								    Utils::MimeDatabase mdb;
							 | 
						||
| 
								 | 
							
								    const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (renameFile(filePath, newFilePath, mt.name()))
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								    return changeProFileOptional;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								FolderNode::AddNewInformation QmakeParserPriFileNode::addNewInformation(const QStringList &files, Node *context) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Q_UNUSED(files)
							 | 
						||
| 
								 | 
							
								    return FolderNode::AddNewInformation(filePath().fileName(), context && context->parentProjectNode() == this ? 120 : 90);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::priFileWritable(const QString &path)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    ReadOnlyFilesDialog roDialog(path, ICore::mainWindow());
							 | 
						||
| 
								 | 
							
								    roDialog.setShowFailWarning(true);
							 | 
						||
| 
								 | 
							
								    return roDialog.exec() != ReadOnlyFilesDialog::RO_Cancel;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::saveModifiedEditors()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Core::IDocument *document
							 | 
						||
| 
								 | 
							
								            = Core::DocumentModel::documentForFilePath(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								    if (!document || !document->isModified())
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!Core::DocumentManager::saveDocument(document))
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // force instant reload of ourselves
							 | 
						||
| 
								 | 
							
								    QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								    m_project->projectManager()->notifyChanged(m_projectFilePath);
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserPriFileNode::formResources(const QString &formFile) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList resourceFiles;
							 | 
						||
| 
								 | 
							
								    QFile file(formFile);
							 | 
						||
| 
								 | 
							
								    if (!file.open(QIODevice::ReadOnly))
							 | 
						||
| 
								 | 
							
								        return resourceFiles;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QXmlStreamReader reader(&file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QFileInfo fi(formFile);
							 | 
						||
| 
								 | 
							
								    QDir formDir = fi.absoluteDir();
							 | 
						||
| 
								 | 
							
								    while (!reader.atEnd()) {
							 | 
						||
| 
								 | 
							
								        reader.readNext();
							 | 
						||
| 
								 | 
							
								        if (reader.isStartElement()) {
							 | 
						||
| 
								 | 
							
								            if (reader.name() == QLatin1String("iconset")) {
							 | 
						||
| 
								 | 
							
								                const QXmlStreamAttributes attributes = reader.attributes();
							 | 
						||
| 
								 | 
							
								                if (attributes.hasAttribute(QLatin1String("resource")))
							 | 
						||
| 
								 | 
							
								                    resourceFiles.append(QDir::cleanPath(formDir.absoluteFilePath(
							 | 
						||
| 
								 | 
							
								                                  attributes.value(QLatin1String("resource")).toString())));
							 | 
						||
| 
								 | 
							
								            } else if (reader.name() == QLatin1String("include")) {
							 | 
						||
| 
								 | 
							
								                const QXmlStreamAttributes attributes = reader.attributes();
							 | 
						||
| 
								 | 
							
								                if (attributes.hasAttribute(QLatin1String("location")))
							 | 
						||
| 
								 | 
							
								                    resourceFiles.append(QDir::cleanPath(formDir.absoluteFilePath(
							 | 
						||
| 
								 | 
							
								                                  attributes.value(QLatin1String("location")).toString())));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (reader.hasError())
							 | 
						||
| 
								 | 
							
								        qWarning() << "Could not read form file:" << formFile;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return resourceFiles;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::ensureWriteableProFile(const QString &file)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // Ensure that the file is not read only
							 | 
						||
| 
								 | 
							
								    QFileInfo fi(file);
							 | 
						||
| 
								 | 
							
								    if (!fi.isWritable()) {
							 | 
						||
| 
								 | 
							
								        // Try via vcs manager
							 | 
						||
| 
								 | 
							
								        Core::IVersionControl *versionControl = Core::VcsManager::findVersionControlForDirectory(fi.absolutePath());
							 | 
						||
| 
								 | 
							
								        if (!versionControl || !versionControl->vcsOpen(file)) {
							 | 
						||
| 
								 | 
							
								            bool makeWritable = QFile::setPermissions(file, fi.permissions() | QFile::WriteUser);
							 | 
						||
| 
								 | 
							
								            if (!makeWritable) {
							 | 
						||
| 
								 | 
							
								                QMessageBox::warning(Core::ICore::mainWindow(),
							 | 
						||
| 
								 | 
							
								                                     QCoreApplication::translate("QmakeParserPriFileNode", "Failed"),
							 | 
						||
| 
								 | 
							
								                                     QCoreApplication::translate("QmakeParserPriFileNode", "Could not write project file %1.").arg(file));
							 | 
						||
| 
								 | 
							
								                return false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QPair<ProFile *, QStringList> QmakeParserPriFileNode::readProFile(const QString &file)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList lines;
							 | 
						||
| 
								 | 
							
								    ProFile *includeFile = 0;
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        QString contents;
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            FileReader reader;
							 | 
						||
| 
								 | 
							
								            if (!reader.fetch(file, QIODevice::Text)) {
							 | 
						||
| 
								 | 
							
								                QmakeProject::proFileParseError(reader.errorString());
							 | 
						||
| 
								 | 
							
								                return qMakePair(includeFile, lines);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            const QTextCodec *codec = Core::EditorManager::defaultTextCodec();
							 | 
						||
| 
								 | 
							
								            contents = codec->toUnicode(reader.data());
							 | 
						||
| 
								 | 
							
								            lines = contents.split(QLatin1Char('\n'));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        QMakeVfs vfs;
							 | 
						||
| 
								 | 
							
								        QtSupport::ProMessageHandler handler;
							 | 
						||
| 
								 | 
							
								        QMakeParser parser(0, &vfs, &handler);
							 | 
						||
| 
								 | 
							
								        includeFile = parser.parsedProBlock(QStringRef(&contents), file, 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return qMakePair(includeFile, lines);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::prepareForChange()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return saveModifiedEditors() && ensureWriteableProFile(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::renameFile(const QString &oldName,
							 | 
						||
| 
								 | 
							
								                                  const QString &newName,
							 | 
						||
| 
								 | 
							
								                                  const QString &mimeType,
							 | 
						||
| 
								 | 
							
								                                  Change mode)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!prepareForChange())
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								    ProFile *includeFile = pair.first;
							 | 
						||
| 
								 | 
							
								    QStringList lines = pair.second;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!includeFile)
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QDir priFileDir = QDir(m_qmakeProFileNode->m_projectDir);
							 | 
						||
| 
								 | 
							
								    QStringList notChanged = ProWriter::removeFiles(includeFile, &lines, priFileDir,
							 | 
						||
| 
								 | 
							
								                                                    QStringList(oldName), varNamesForRemoving());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    includeFile->deref();
							 | 
						||
| 
								 | 
							
								    if (!notChanged.isEmpty())
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // We need to re-parse here: The file has changed.
							 | 
						||
| 
								 | 
							
								    QMakeParser parser(0, 0, 0);
							 | 
						||
| 
								 | 
							
								    QString contents = lines.join(QLatin1Char('\n'));
							 | 
						||
| 
								 | 
							
								    includeFile = parser.parsedProBlock(QStringRef(&contents),
							 | 
						||
| 
								 | 
							
								                                        m_projectFilePath.toString(), 1, QMakeParser::FullGrammar);
							 | 
						||
| 
								 | 
							
								    QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ProWriter::addFiles(includeFile, &lines,
							 | 
						||
| 
								 | 
							
								                        QStringList(newName),
							 | 
						||
| 
								 | 
							
								                        varNameForAdding(mimeType));
							 | 
						||
| 
								 | 
							
								    if (mode == Change::Save)
							 | 
						||
| 
								 | 
							
								        save(lines);
							 | 
						||
| 
								 | 
							
								    includeFile->deref();
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::changeFiles(const QString &mimeType,
							 | 
						||
| 
								 | 
							
								                                 const QStringList &filePaths,
							 | 
						||
| 
								 | 
							
								                                 QStringList *notChanged,
							 | 
						||
| 
								 | 
							
								                                 ChangeType change, Change mode)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (filePaths.isEmpty())
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    *notChanged = filePaths;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Check for modified editors
							 | 
						||
| 
								 | 
							
								    if (!prepareForChange())
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								    ProFile *includeFile = pair.first;
							 | 
						||
| 
								 | 
							
								    QStringList lines = pair.second;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!includeFile)
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (change == AddToProFile) {
							 | 
						||
| 
								 | 
							
								        // Use the first variable for adding.
							 | 
						||
| 
								 | 
							
								        ProWriter::addFiles(includeFile, &lines, filePaths, varNameForAdding(mimeType));
							 | 
						||
| 
								 | 
							
								        notChanged->clear();
							 | 
						||
| 
								 | 
							
								    } else { // RemoveFromProFile
							 | 
						||
| 
								 | 
							
								        QDir priFileDir = QDir(m_qmakeProFileNode->m_projectDir);
							 | 
						||
| 
								 | 
							
								        *notChanged = ProWriter::removeFiles(includeFile, &lines, priFileDir, filePaths, varNamesForRemoving());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // save file
							 | 
						||
| 
								 | 
							
								    if (mode == Change::Save)
							 | 
						||
| 
								 | 
							
								        save(lines);
							 | 
						||
| 
								 | 
							
								    includeFile->deref();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserPriFileNode::setProVariable(const QString &var, const QStringList &values, const QString &scope, int flags)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!prepareForChange())
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								    ProFile *includeFile = pair.first;
							 | 
						||
| 
								 | 
							
								    QStringList lines = pair.second;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!includeFile)
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ProWriter::putVarValues(includeFile, &lines, values, var,
							 | 
						||
| 
								 | 
							
								                            ProWriter::PutFlags(flags),
							 | 
						||
| 
								 | 
							
								                            scope);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    save(lines);
							 | 
						||
| 
								 | 
							
								    includeFile->deref();
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserPriFileNode::save(const QStringList &lines)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        FileChangeBlocker changeGuard(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								        FileSaver saver(m_projectFilePath.toString(), QIODevice::Text);
							 | 
						||
| 
								 | 
							
								        const QTextCodec *codec = Core::EditorManager::defaultTextCodec();
							 | 
						||
| 
								 | 
							
								        saver.write(codec->fromUnicode(lines.join(QLatin1Char('\n'))));
							 | 
						||
| 
								 | 
							
								        saver.finalize(Core::ICore::mainWindow());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // This is a hack.
							 | 
						||
| 
								 | 
							
								    // We are saving twice in a very short timeframe, once the editor and once the ProFile.
							 | 
						||
| 
								 | 
							
								    // So the modification time might not change between those two saves.
							 | 
						||
| 
								 | 
							
								    // We manually tell each editor to reload it's file.
							 | 
						||
| 
								 | 
							
								    // (The .pro files are notified by the file system watcher.)
							 | 
						||
| 
								 | 
							
								    QStringList errorStrings;
							 | 
						||
| 
								 | 
							
								    Core::IDocument *document = Core::DocumentModel::documentForFilePath(m_projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								    if (document) {
							 | 
						||
| 
								 | 
							
								        QString errorString;
							 | 
						||
| 
								 | 
							
								        if (!document->reload(&errorString, Core::IDocument::FlagReload, Core::IDocument::TypeContents))
							 | 
						||
| 
								 | 
							
								            errorStrings << errorString;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (!errorStrings.isEmpty())
							 | 
						||
| 
								 | 
							
								        QMessageBox::warning(Core::ICore::mainWindow(), QCoreApplication::translate("QmakeParserPriFileNode", "File Error"),
							 | 
						||
| 
								 | 
							
								                             errorStrings.join(QLatin1Char('\n')));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserPriFileNode::varNames(FileType type, QtSupport::ProFileReader *readerExact)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList vars;
							 | 
						||
| 
								 | 
							
								    switch (type) {
							 | 
						||
| 
								 | 
							
								    case FileType::Header:
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("HEADERS");
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("PRECOMPILED_HEADER");
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    case FileType::Source: {
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("SOURCES");
							 | 
						||
| 
								 | 
							
								        QStringList listOfExtraCompilers = readerExact->values(QLatin1String("QMAKE_EXTRA_COMPILERS"));
							 | 
						||
| 
								 | 
							
								        foreach (const QString &var, listOfExtraCompilers) {
							 | 
						||
| 
								 | 
							
								            QStringList inputs = readerExact->values(var + QLatin1String(".input"));
							 | 
						||
| 
								 | 
							
								            foreach (const QString &input, inputs)
							 | 
						||
| 
								 | 
							
								                // FORMS, RESOURCES, and STATECHARTS are handled below, HEADERS and SOURCES above
							 | 
						||
| 
								 | 
							
								                if (input != QLatin1String("FORMS")
							 | 
						||
| 
								 | 
							
								                        && input != QLatin1String("STATECHARTS")
							 | 
						||
| 
								 | 
							
								                        && input != QLatin1String("RESOURCES")
							 | 
						||
| 
								 | 
							
								                        && input != QLatin1String("SOURCES")
							 | 
						||
| 
								 | 
							
								                        && input != QLatin1String("HEADERS"))
							 | 
						||
| 
								 | 
							
								                    vars << input;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    case FileType::Resource:
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("RESOURCES");
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    case FileType::Form:
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("FORMS");
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    case FileType::StateChart:
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("STATECHARTS");
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    case FileType::Project:
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("SUBDIRS");
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    case FileType::QML:
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("OTHER_FILES");
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("DISTFILES");
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("OTHER_FILES");
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("DISTFILES");
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("ICON");
							 | 
						||
| 
								 | 
							
								        vars << QLatin1String("QMAKE_INFO_PLIST");
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return vars;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//!
							 | 
						||
| 
								 | 
							
								//! \brief QmakeParserPriFileNode::varNames
							 | 
						||
| 
								 | 
							
								//! \param mimeType
							 | 
						||
| 
								 | 
							
								//! \return the qmake variable name for the mime type
							 | 
						||
| 
								 | 
							
								//! Note: Only used for adding.
							 | 
						||
| 
								 | 
							
								//!
							 | 
						||
| 
								 | 
							
								QString QmakeParserPriFileNode::varNameForAdding(const QString &mimeType)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (mimeType == QLatin1String(ProjectExplorer::Constants::CPP_HEADER_MIMETYPE)
							 | 
						||
| 
								 | 
							
								            || mimeType == QLatin1String(ProjectExplorer::Constants::C_HEADER_MIMETYPE)) {
							 | 
						||
| 
								 | 
							
								        return QLatin1String("HEADERS");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mimeType == QLatin1String(ProjectExplorer::Constants::CPP_SOURCE_MIMETYPE)
							 | 
						||
| 
								 | 
							
								               || mimeType == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)
							 | 
						||
| 
								 | 
							
								               || mimeType == QLatin1String(ProjectExplorer::Constants::C_SOURCE_MIMETYPE)) {
							 | 
						||
| 
								 | 
							
								        return QLatin1String("SOURCES");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mimeType == QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE))
							 | 
						||
| 
								 | 
							
								        return QLatin1String("RESOURCES");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mimeType == QLatin1String(ProjectExplorer::Constants::FORM_MIMETYPE))
							 | 
						||
| 
								 | 
							
								        return QLatin1String("FORMS");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mimeType == QLatin1String(ProjectExplorer::Constants::QML_MIMETYPE))
							 | 
						||
| 
								 | 
							
								        return QLatin1String("DISTFILES");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mimeType == QLatin1String(ProjectExplorer::Constants::SCXML_MIMETYPE))
							 | 
						||
| 
								 | 
							
								        return QLatin1String("STATECHARTS");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mimeType == QLatin1String(Constants::PROFILE_MIMETYPE))
							 | 
						||
| 
								 | 
							
								        return QLatin1String("SUBDIRS");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return QLatin1String("DISTFILES");
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//!
							 | 
						||
| 
								 | 
							
								//! \brief QmakeParserPriFileNode::varNamesForRemoving
							 | 
						||
| 
								 | 
							
								//! \return all qmake variables which are displayed in the project tree
							 | 
						||
| 
								 | 
							
								//! Note: Only used for removing.
							 | 
						||
| 
								 | 
							
								//!
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserPriFileNode::varNamesForRemoving()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList vars;
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("HEADERS");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("OBJECTIVE_HEADERS");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("PRECOMPILED_HEADER");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("SOURCES");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("OBJECTIVE_SOURCES");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("RESOURCES");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("FORMS");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("OTHER_FILES");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("SUBDIRS");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("DISTFILES");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("ICON");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("QMAKE_INFO_PLIST");
							 | 
						||
| 
								 | 
							
								    vars << QLatin1String("STATECHARTS");
							 | 
						||
| 
								 | 
							
								    return vars;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QSet<FileName> QmakeParserPriFileNode::filterFilesProVariables(FileType fileType, const QSet<FileName> &files)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (fileType != FileType::QML && fileType != FileType::Unknown)
							 | 
						||
| 
								 | 
							
								        return files;
							 | 
						||
| 
								 | 
							
								    QSet<FileName> result;
							 | 
						||
| 
								 | 
							
								    if (fileType == FileType::QML) {
							 | 
						||
| 
								 | 
							
								        foreach (const FileName &file, files)
							 | 
						||
| 
								 | 
							
								            if (file.toString().endsWith(QLatin1String(".qml")))
							 | 
						||
| 
								 | 
							
								                result << file;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        foreach (const FileName &file, files)
							 | 
						||
| 
								 | 
							
								            if (!file.toString().endsWith(QLatin1String(".qml")))
							 | 
						||
| 
								 | 
							
								                result << file;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QSet<FileName> QmakeParserPriFileNode::filterFilesRecursiveEnumerata(FileType fileType, const QSet<FileName> &files)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QSet<FileName> result;
							 | 
						||
| 
								 | 
							
								    if (fileType != FileType::QML && fileType != FileType::Unknown)
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    if (fileType == FileType::QML) {
							 | 
						||
| 
								 | 
							
								        foreach (const FileName &file, files)
							 | 
						||
| 
								 | 
							
								            if (file.toString().endsWith(QLatin1String(".qml")))
							 | 
						||
| 
								 | 
							
								                result << file;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        foreach (const FileName &file, files)
							 | 
						||
| 
								 | 
							
								            if (!file.toString().endsWith(QLatin1String(".qml")))
							 | 
						||
| 
								 | 
							
								                result << file;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace QmakeProjectManager
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static QmakeProjectType proFileTemplateTypeToProjectType(ProFileEvaluator::TemplateType type)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    switch (type) {
							 | 
						||
| 
								 | 
							
								    case ProFileEvaluator::TT_Unknown:
							 | 
						||
| 
								 | 
							
								    case ProFileEvaluator::TT_Application:
							 | 
						||
| 
								 | 
							
								        return ApplicationTemplate;
							 | 
						||
| 
								 | 
							
								    case ProFileEvaluator::TT_StaticLibrary:
							 | 
						||
| 
								 | 
							
								        return StaticLibraryTemplate;
							 | 
						||
| 
								 | 
							
								    case ProFileEvaluator::TT_SharedLibrary:
							 | 
						||
| 
								 | 
							
								        return SharedLibraryTemplate;
							 | 
						||
| 
								 | 
							
								    case ProFileEvaluator::TT_Script:
							 | 
						||
| 
								 | 
							
								        return ScriptTemplate;
							 | 
						||
| 
								 | 
							
								    case ProFileEvaluator::TT_Aux:
							 | 
						||
| 
								 | 
							
								        return AuxTemplate;
							 | 
						||
| 
								 | 
							
								    case ProFileEvaluator::TT_Subdirs:
							 | 
						||
| 
								 | 
							
								        return SubDirsTemplate;
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								        return InvalidProject;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace {
							 | 
						||
| 
								 | 
							
								    // feed all files accepted by any of the factories to the callback.
							 | 
						||
| 
								 | 
							
								    class FindGeneratorSourcesVisitor : public NodesVisitor
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        FindGeneratorSourcesVisitor(
							 | 
						||
| 
								 | 
							
								                const QList<ProjectExplorer::ExtraCompilerFactory *> &factories,
							 | 
						||
| 
								 | 
							
								                std::function<void(FileNode *, ProjectExplorer::ExtraCompilerFactory *)> callback) :
							 | 
						||
| 
								 | 
							
								            factories(factories), callback(callback) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void visitFolderNode(FolderNode *folderNode) final
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            foreach (FileNode *fileNode, folderNode->fileNodes()) {
							 | 
						||
| 
								 | 
							
								                foreach (ProjectExplorer::ExtraCompilerFactory *factory, factories) {
							 | 
						||
| 
								 | 
							
								                    if (factory->sourceType() == fileNode->fileType())
							 | 
						||
| 
								 | 
							
								                        callback(fileNode, factory);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const QList<ProjectExplorer::ExtraCompilerFactory *> factories;
							 | 
						||
| 
								 | 
							
								        std::function<void(FileNode *, ProjectExplorer::ExtraCompilerFactory *)> callback;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeParserProFileNode *QmakeParserProFileNode::findProFileFor(const FileName &fileName) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (fileName == filePath())
							 | 
						||
| 
								 | 
							
								        return const_cast<QmakeParserProFileNode *>(this);
							 | 
						||
| 
								 | 
							
								    foreach (ProjectNode *pn, projectNodes())
							 | 
						||
| 
								 | 
							
								        if (QmakeParserProFileNode *qmakeProFileNode = dynamic_cast<QmakeParserProFileNode *>(pn))
							 | 
						||
| 
								 | 
							
								            if (QmakeParserProFileNode *result = qmakeProFileNode->findProFileFor(fileName))
							 | 
						||
| 
								 | 
							
								                return result;
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::makefile() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return singleVariableValue(Variable::Makefile);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::objectExtension() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (m_varValues[Variable::ObjectExt].isEmpty())
							 | 
						||
| 
								 | 
							
								        return HostOsInfo::isWindowsHost() ? QLatin1String(".obj") : QLatin1String(".o");
							 | 
						||
| 
								 | 
							
								    return m_varValues[Variable::ObjectExt].first();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::objectsDirectory() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return singleVariableValue(Variable::ObjectsDir);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QByteArray QmakeParserProFileNode::cxxDefines() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QByteArray result;
							 | 
						||
| 
								 | 
							
								    foreach (const QString &def, variableValue(Variable::Defines)) {
							 | 
						||
| 
								 | 
							
								        // 'def' is shell input, so interpret it.
							 | 
						||
| 
								 | 
							
								        QtcProcess::SplitError error = QtcProcess::SplitOk;
							 | 
						||
| 
								 | 
							
								        const QStringList args = QtcProcess::splitArgs(def, HostOsInfo::hostOs(), false, &error);
							 | 
						||
| 
								 | 
							
								        if (error != QtcProcess::SplitOk || args.size() == 0)
							 | 
						||
| 
								 | 
							
								            continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        result += "#define ";
							 | 
						||
| 
								 | 
							
								        const QString defInterpreted = args.first();
							 | 
						||
| 
								 | 
							
								        const int index = defInterpreted.indexOf(QLatin1Char('='));
							 | 
						||
| 
								 | 
							
								        if (index == -1) {
							 | 
						||
| 
								 | 
							
								            result += defInterpreted.toLatin1();
							 | 
						||
| 
								 | 
							
								            result += " 1\n";
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            const QString name = defInterpreted.left(index);
							 | 
						||
| 
								 | 
							
								            const QString value = defInterpreted.mid(index + 1);
							 | 
						||
| 
								 | 
							
								            result += name.toLatin1();
							 | 
						||
| 
								 | 
							
								            result += ' ';
							 | 
						||
| 
								 | 
							
								            result += value.toLocal8Bit();
							 | 
						||
| 
								 | 
							
								            result += '\n';
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								  \class QmakeParserProFileNode
							 | 
						||
| 
								 | 
							
								  Implements abstract ProjectNode class
							 | 
						||
| 
								 | 
							
								  */
							 | 
						||
| 
								 | 
							
								QmakeParserProFileNode::QmakeParserProFileNode(QmakeProject *project,
							 | 
						||
| 
								 | 
							
								                               const FileName &filePath)
							 | 
						||
| 
								 | 
							
								        : QmakeParserPriFileNode(project, this, filePath)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // The slot is a lambda, so that QmakeParserProFileNode does not need to be
							 | 
						||
| 
								 | 
							
								    // a qobject. The lifetime of the m_parserFutureWatcher is shorter
							 | 
						||
| 
								 | 
							
								    // than of this, so this is all safe
							 | 
						||
| 
								 | 
							
								    QObject::connect(&m_parseFutureWatcher, &QFutureWatcherBase::finished,
							 | 
						||
| 
								 | 
							
								                     [this](){
							 | 
						||
| 
								 | 
							
								                         applyAsyncEvaluate();
							 | 
						||
| 
								 | 
							
								                     });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeParserProFileNode::~QmakeParserProFileNode()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    qDeleteAll(m_extraCompilers);
							 | 
						||
| 
								 | 
							
								    m_parseFutureWatcher.waitForFinished();
							 | 
						||
| 
								 | 
							
								    if (m_readerExact)
							 | 
						||
| 
								 | 
							
								        applyAsyncEvaluate();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserProFileNode::isParent(QmakeParserProFileNode *node)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    while ((node = dynamic_cast<QmakeParserProFileNode *>(node->parentFolderNode()))) {
							 | 
						||
| 
								 | 
							
								        if (node == this)
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								FolderNode::AddNewInformation QmakeParserProFileNode::addNewInformation(const QStringList &files, Node *context) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Q_UNUSED(files)
							 | 
						||
| 
								 | 
							
								    return AddNewInformation(filePath().fileName(), context && context->parentProjectNode() == this ? 120 : 100);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserProFileNode::isDebugAndRelease() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    const QStringList configValues = m_varValues.value(Variable::Config);
							 | 
						||
| 
								 | 
							
								    return configValues.contains(QLatin1String("debug_and_release"));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserProFileNode::isQtcRunnable() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    const QStringList configValues = m_varValues.value(Variable::Config);
							 | 
						||
| 
								 | 
							
								    return configValues.contains(QLatin1String("qtc_runnable"));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ProjectType QmakeParserProFileNode::projectType() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_projectType;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserProFileNode::variableValue(const Variable var) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_varValues.value(var);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::singleVariableValue(const Variable var) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    const QStringList &values = variableValue(var);
							 | 
						||
| 
								 | 
							
								    return values.isEmpty() ? QString() : values.first();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::setParseInProgressRecursive(bool b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    setParseInProgress(b);
							 | 
						||
| 
								 | 
							
								    foreach (ProjectNode *subNode, projectNodes()) {
							 | 
						||
| 
								 | 
							
								        if (QmakeParserProFileNode *node = dynamic_cast<QmakeParserProFileNode *>(subNode))
							 | 
						||
| 
								 | 
							
								            node->setParseInProgressRecursive(b);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::setParseInProgress(bool b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (m_parseInProgress == b)
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								    m_parseInProgress = b;
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    emit m_project->proFileUpdated(this, m_validParse, m_parseInProgress);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Do note the absence of signal emission, always set validParse
							 | 
						||
| 
								 | 
							
								// before setParseInProgress, as that will emit the signals
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::setValidParseRecursive(bool b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_validParse = b;
							 | 
						||
| 
								 | 
							
								    foreach (ProjectNode *subNode, projectNodes()) {
							 | 
						||
| 
								 | 
							
								        if (QmakeParserProFileNode *node = dynamic_cast<QmakeParserProFileNode *>(subNode))
							 | 
						||
| 
								 | 
							
								            node->setValidParseRecursive(b);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserProFileNode::validParse() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_validParse;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool QmakeParserProFileNode::parseInProgress() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_parseInProgress;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::scheduleUpdate(QmakeParserProFileNode::AsyncUpdateDelay delay)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    setParseInProgressRecursive(true);
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    m_project->scheduleAsyncUpdate(this, delay);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::asyncUpdate()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_project->incrementPendingEvaluateFutures();
							 | 
						||
| 
								 | 
							
								    setupReader();
							 | 
						||
| 
								 | 
							
								    if (!includedInExactParse())
							 | 
						||
| 
								 | 
							
								        m_readerExact->setExact(false);
							 | 
						||
| 
								 | 
							
								    m_parseFutureWatcher.waitForFinished();
							 | 
						||
| 
								 | 
							
								    QmakeEvalInput input = evalInput();
							 | 
						||
| 
								 | 
							
								    QFuture<QmakeEvalResult *> future = Utils::runAsync(ProjectExplorerPlugin::sharedThreadPool(),
							 | 
						||
| 
								 | 
							
								                                                   QThread::LowestPriority,
							 | 
						||
| 
								 | 
							
								                                                   &QmakeParserProFileNode::asyncEvaluate,
							 | 
						||
| 
								 | 
							
								                                                   this, input);
							 | 
						||
| 
								 | 
							
								    m_parseFutureWatcher.setFuture(future);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeEvalInput QmakeParserProFileNode::evalInput() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QmakeEvalInput input;
							 | 
						||
| 
								 | 
							
								    input.projectDir = m_projectDir;
							 | 
						||
| 
								 | 
							
								    input.projectFilePath = m_projectFilePath;
							 | 
						||
| 
								 | 
							
								    input.buildDirectory = buildDir();
							 | 
						||
| 
								 | 
							
								    input.sysroot = m_project->qmakeSysroot();
							 | 
						||
| 
								 | 
							
								    input.readerExact = m_readerExact;
							 | 
						||
| 
								 | 
							
								    input.readerCumulative = m_readerCumulative;
							 | 
						||
| 
								 | 
							
								    input.qmakeGlobals = m_project->qmakeGlobals();
							 | 
						||
| 
								 | 
							
								    input.qmakeVfs = m_project->qmakeVfs();
							 | 
						||
| 
								 | 
							
								    return input;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::setupReader()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Q_ASSERT(!m_readerExact);
							 | 
						||
| 
								 | 
							
								    Q_ASSERT(!m_readerCumulative);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    m_readerExact = m_project->createProFileReader(this);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_readerCumulative = m_project->createProFileReader(this);
							 | 
						||
| 
								 | 
							
								    m_readerCumulative->setCumulative(true);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool evaluateOne(
							 | 
						||
| 
								 | 
							
								        const EvalInput &input, ProFile *pro, QtSupport::ProFileReader *reader,
							 | 
						||
| 
								 | 
							
								        bool cumulative, QtSupport::ProFileReader **buildPassReader)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    if (!reader->accept(pro, QMakeEvaluator::LoadAll))
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList builds = reader->values(QLatin1String("BUILDS"));
							 | 
						||
| 
								 | 
							
								    if (builds.isEmpty()) {
							 | 
						||
| 
								 | 
							
								        *buildPassReader = reader;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        QString build = builds.first();
							 | 
						||
| 
								 | 
							
								        QHash<QString, QStringList> basevars;
							 | 
						||
| 
								 | 
							
								        QStringList basecfgs = reader->values(build + QLatin1String(".CONFIG"));
							 | 
						||
| 
								 | 
							
								        basecfgs += build;
							 | 
						||
| 
								 | 
							
								        basecfgs += QLatin1String("build_pass");
							 | 
						||
| 
								 | 
							
								        basevars[QLatin1String("BUILD_PASS")] = QStringList(build);
							 | 
						||
| 
								 | 
							
								        QStringList buildname = reader->values(build + QLatin1String(".name"));
							 | 
						||
| 
								 | 
							
								        basevars[QLatin1String("BUILD_NAME")] = (buildname.isEmpty() ? QStringList(build) : buildname);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // We don't increase/decrease m_qmakeGlobalsRefCnt here, because the outer profilereaders keep m_qmakeGlobals alive anyway
							 | 
						||
| 
								 | 
							
								        auto bpReader = new QtSupport::ProFileReader(input.qmakeGlobals, input.qmakeVfs); // needs to access m_qmakeGlobals, m_qmakeVfs
							 | 
						||
| 
								 | 
							
								        bpReader->setOutputDir(input.buildDirectory);
							 | 
						||
| 
								 | 
							
								        bpReader->setCumulative(cumulative);
							 | 
						||
| 
								 | 
							
								        bpReader->setExtraVars(basevars);
							 | 
						||
| 
								 | 
							
								        bpReader->setExtraConfigs(basecfgs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (bpReader->accept(pro, QMakeEvaluator::LoadAll))
							 | 
						||
| 
								 | 
							
								            *buildPassReader = bpReader;
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            delete bpReader;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QmakeEvalResult *QmakeParserProFileNode::evaluate(const QmakeEvalInput &input)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QmakeEvalResult *result = new QmakeEvalResult;
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    QtSupport::ProFileReader *exactBuildPassReader = nullptr;
							 | 
						||
| 
								 | 
							
								    QtSupport::ProFileReader *cumulativeBuildPassReader = nullptr;
							 | 
						||
| 
								 | 
							
								    ProFile *pro;
							 | 
						||
| 
								 | 
							
								    if ((pro = input.readerExact->parsedProFile(input.projectFilePath.toString()))) {
							 | 
						||
| 
								 | 
							
								        bool exactOk = evaluateOne(input, pro, input.readerExact, false, &exactBuildPassReader);
							 | 
						||
| 
								 | 
							
								        bool cumulOk = evaluateOne(input, pro, input.readerCumulative, true, &cumulativeBuildPassReader);
							 | 
						||
| 
								 | 
							
								        pro->deref();
							 | 
						||
| 
								 | 
							
								        result->state = exactOk ? ParserEvalResult::EvalOk : cumulOk ? ParserEvalResult::EvalPartial : ParserEvalResult::EvalFail;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        result->state = ParserEvalResult::EvalFail;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (result->state == ParserEvalResult::EvalFail)
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    result->includedFiles.proFile = pro;
							 | 
						||
| 
								 | 
							
								    result->includedFiles.name = input.projectFilePath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QHash<const ProFile *, PriFileEvalResult *> proToResult;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    result->projectType = proFileTemplateTypeToProjectType(
							 | 
						||
| 
								 | 
							
								                (result->state == ParserEvalResult::EvalOk ? input.readerExact
							 | 
						||
| 
								 | 
							
								                                                     : input.readerCumulative)->templateType());
							 | 
						||
| 
								 | 
							
								    if (result->state == ParserEvalResult::EvalOk) {
							 | 
						||
| 
								 | 
							
								        if (result->projectType == SubDirsTemplate) {
							 | 
						||
| 
								 | 
							
								            QStringList errors;
							 | 
						||
| 
								 | 
							
								            FileNameList subDirs = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors);
							 | 
						||
| 
								 | 
							
								            result->errors.append(errors);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            foreach (const Utils::FileName &subDirName, subDirs) {
							 | 
						||
| 
								 | 
							
								                IncludedPriFile *subDir = new IncludedPriFile;
							 | 
						||
| 
								 | 
							
								                subDir->proFile = nullptr;
							 | 
						||
| 
								 | 
							
								                subDir->name = subDirName;
							 | 
						||
| 
								 | 
							
								                result->includedFiles.children.insert(subDirName, subDir);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            result->exactSubdirs = subDirs.toSet();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Convert ProFileReader::includeFiles to IncludedPriFile structure
							 | 
						||
| 
								 | 
							
								        QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerExact->includeFiles();
							 | 
						||
| 
								 | 
							
								        QList<IncludedPriFile *> toBuild = { &result->includedFiles };
							 | 
						||
| 
								 | 
							
								        while (!toBuild.isEmpty()) {
							 | 
						||
| 
								 | 
							
								            IncludedPriFile *current = toBuild.takeFirst();
							 | 
						||
| 
								 | 
							
								            if (!current->proFile)
							 | 
						||
| 
								 | 
							
								                continue;  // Don't attempt to map subdirs here
							 | 
						||
| 
								 | 
							
								            QVector<ProFile *> children = includeFiles.value(current->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->proFile = child;
							 | 
						||
| 
								 | 
							
								                    childTree->name = childName;
							 | 
						||
| 
								 | 
							
								                    current->children.insert(childName, childTree);
							 | 
						||
| 
								 | 
							
								                    proToResult[child] = &childTree->result;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            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->proFile = nullptr;
							 | 
						||
| 
								 | 
							
								                subDir->name = subDirName;
							 | 
						||
| 
								 | 
							
								                result->includedFiles.children.insert(subDirName, subDir);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Add ProFileReader::includeFiles information from cumulative parse to IncludedPriFile structure
							 | 
						||
| 
								 | 
							
								    QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerCumulative->includeFiles();
							 | 
						||
| 
								 | 
							
								    QList<IncludedPriFile *> toBuild = { &result->includedFiles };
							 | 
						||
| 
								 | 
							
								    while (!toBuild.isEmpty()) {
							 | 
						||
| 
								 | 
							
								        IncludedPriFile *current = toBuild.takeFirst();
							 | 
						||
| 
								 | 
							
								        if (!current->proFile)
							 | 
						||
| 
								 | 
							
								            continue;  // Don't attempt to map subdirs here
							 | 
						||
| 
								 | 
							
								        QVector<ProFile *> children = includeFiles.value(current->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->proFile = child;
							 | 
						||
| 
								 | 
							
								                childTree->name = childName;
							 | 
						||
| 
								 | 
							
								                current->children.insert(childName, childTree);
							 | 
						||
| 
								 | 
							
								                proToResult[child] = &childTree->result;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        toBuild.append(current->children.values());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    auto exactReader = exactBuildPassReader ? exactBuildPassReader : input.readerExact;
							 | 
						||
| 
								 | 
							
								    auto cumulativeReader = cumulativeBuildPassReader ? cumulativeBuildPassReader : input.readerCumulative;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QHash<QString, QVector<ProFileEvaluator::SourceFile> > exactSourceFiles;
							 | 
						||
| 
								 | 
							
								    QHash<QString, QVector<ProFileEvaluator::SourceFile> > cumulativeSourceFiles;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList baseVPathsExact = baseVPaths(exactReader, input.projectDir, input.buildDirectory);
							 | 
						||
| 
								 | 
							
								    QStringList baseVPathsCumulative = baseVPaths(cumulativeReader, input.projectDir, input.buildDirectory);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const QVector<QmakeParserNodeStaticData::FileTypeData> &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) {
							 | 
						||
| 
								 | 
							
								            QHash<ProString, bool> handled;
							 | 
						||
| 
								 | 
							
								            if (result->state == ParserEvalResult::EvalOk) {
							 | 
						||
| 
								 | 
							
								                QStringList vPathsExact = fullVPaths(
							 | 
						||
| 
								 | 
							
								                            baseVPathsExact, exactReader, qmakeVariable, input.projectDir);
							 | 
						||
| 
								 | 
							
								                auto sourceFiles = exactReader->absoluteFileValues(
							 | 
						||
| 
								 | 
							
								                            qmakeVariable, input.projectDir, vPathsExact, &handled);
							 | 
						||
| 
								 | 
							
								                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, &handled);
							 | 
						||
| 
								 | 
							
								            cumulativeSourceFiles[qmakeVariable] = sourceFiles;
							 | 
						||
| 
								 | 
							
								            extractSources(proToResult, &result->includedFiles.result, sourceFiles, type);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // This is used for two things:
							 | 
						||
| 
								 | 
							
								    // - Actual deployment, in which case we need exact values.
							 | 
						||
| 
								 | 
							
								    // - The project tree, in which case we also want exact values to avoid recursively
							 | 
						||
| 
								 | 
							
								    //   watching bogus paths. However, we accept the values even if the evaluation
							 | 
						||
| 
								 | 
							
								    //   failed, to at least have a best-effort result.
							 | 
						||
| 
								 | 
							
								    result->installsList = installsList(exactBuildPassReader, input.projectFilePath.toString(),
							 | 
						||
| 
								 | 
							
								                                        input.projectDir, input.buildDirectory);
							 | 
						||
| 
								 | 
							
								    extractInstalls(proToResult, &result->includedFiles.result, result->installsList);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (result->state == ParserEvalResult::EvalOk) {
							 | 
						||
| 
								 | 
							
								        result->targetInformation = targetInformation(input.readerExact, exactBuildPassReader,
							 | 
						||
| 
								 | 
							
								                                                      input.buildDirectory, input.projectFilePath.toString());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // update other variables
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::Defines] = exactReader->values(QLatin1String("DEFINES"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::IncludePath] = includePaths(exactReader, input.sysroot,
							 | 
						||
| 
								 | 
							
								                                                            input.buildDirectory, input.projectDir);
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::CppFlags] = exactReader->values(QLatin1String("QMAKE_CXXFLAGS"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::Source] =
							 | 
						||
| 
								 | 
							
								                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"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::UiDir] = QStringList() << uiDirPath(exactReader, input.buildDirectory);
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::HeaderExtension] = QStringList() << exactReader->value(QLatin1String("QMAKE_EXT_H"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::CppExtension] = QStringList() << exactReader->value(QLatin1String("QMAKE_EXT_CPP"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::MocDir] = QStringList() << mocDirPath(exactReader, input.buildDirectory);
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::ExactResource] = fileListForVar(exactSourceFiles, QLatin1String("RESOURCES"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::CumulativeResource] = fileListForVar(cumulativeSourceFiles, QLatin1String("RESOURCES"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::PkgConfig] = exactReader->values(QLatin1String("PKGCONFIG"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::PrecompiledHeader] = ProFileEvaluator::sourcesToFiles(exactReader->fixifiedValues(
							 | 
						||
| 
								 | 
							
								                    QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::LibDirectories] = libDirectories(exactReader);
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::Config] = exactReader->values(QLatin1String("CONFIG"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::QmlImportPath] = exactReader->absolutePathValues(
							 | 
						||
| 
								 | 
							
								                    QLatin1String("QML_IMPORT_PATH"), input.projectDir);
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::QmlDesignerImportPath] = exactReader->absolutePathValues(
							 | 
						||
| 
								 | 
							
								                    QLatin1String("QML_DESIGNER_IMPORT_PATH"), input.projectDir);
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::Makefile] = exactReader->values(QLatin1String("MAKEFILE"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::Qt] = exactReader->values(QLatin1String("QT"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::ObjectExt] = exactReader->values(QLatin1String("QMAKE_EXT_OBJ"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::ObjectsDir] = exactReader->values(QLatin1String("OBJECTS_DIR"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::Version] = exactReader->values(QLatin1String("VERSION"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::TargetExt] = exactReader->values(QLatin1String("TARGET_EXT"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::TargetVersionExt]
							 | 
						||
| 
								 | 
							
								                = exactReader->values(QLatin1String("TARGET_VERSION_EXT"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::StaticLibExtension] = exactReader->values(QLatin1String("QMAKE_EXTENSION_STATICLIB"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::ShLibExtension] = exactReader->values(QLatin1String("QMAKE_EXTENSION_SHLIB"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::AndroidArch] = exactReader->values(QLatin1String("ANDROID_TARGET_ARCH"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::AndroidDeploySettingsFile] = exactReader->values(QLatin1String("ANDROID_DEPLOYMENT_SETTINGS_FILE"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::AndroidPackageSourceDir] = exactReader->values(QLatin1String("ANDROID_PACKAGE_SOURCE_DIR"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::AndroidExtraLibs] = exactReader->values(QLatin1String("ANDROID_EXTRA_LIBS"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::IsoIcons] = exactReader->values(QLatin1String("ISO_ICONS"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::QmakeProjectName] = exactReader->values(QLatin1String("QMAKE_PROJECT_NAME"));
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::QmakeCc] = exactReader->values("QMAKE_CC");
							 | 
						||
| 
								 | 
							
								        result->newVarValues[Variable::QmakeCxx] = exactReader->values("QMAKE_CXX");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (result->state == ParserEvalResult::EvalOk || result->state == ParserEvalResult::EvalPartial) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        QList<IncludedPriFile *> toExtract = { &result->includedFiles };
							 | 
						||
| 
								 | 
							
								        while (!toExtract.isEmpty()) {
							 | 
						||
| 
								 | 
							
								            IncludedPriFile *current = toExtract.takeFirst();
							 | 
						||
| 
								 | 
							
								            processValues(current->result);
							 | 
						||
| 
								 | 
							
								            toExtract.append(current->children.values());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (exactBuildPassReader && exactBuildPassReader != input.readerExact)
							 | 
						||
| 
								 | 
							
								        delete exactBuildPassReader;
							 | 
						||
| 
								 | 
							
								    if (cumulativeBuildPassReader && cumulativeBuildPassReader != input.readerCumulative)
							 | 
						||
| 
								 | 
							
								        delete cumulativeBuildPassReader;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::asyncEvaluate(QFutureInterface<QmakeEvalResult *> &fi, QmakeEvalInput input)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QmakeEvalResult *evalResult = evaluate(input);
							 | 
						||
| 
								 | 
							
								    fi.reportResult(evalResult);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::applyAsyncEvaluate()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    applyEvaluate(m_parseFutureWatcher.result());
							 | 
						||
| 
								 | 
							
								    m_project->decrementPendingEvaluateFutures();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool sortByParserNodes(Node *a, Node *b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return a->filePath() < b->filePath();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::applyEvaluate(QmakeEvalResult *evalResult)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QScopedPointer<QmakeEvalResult> result(evalResult);
							 | 
						||
| 
								 | 
							
								    if (!m_readerExact)
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (m_project->asyncUpdateState() == QmakeProject::ShuttingDown) {
							 | 
						||
| 
								 | 
							
								        cleanupProFileReaders();
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach (const QString &error, evalResult->errors)
							 | 
						||
| 
								 | 
							
								        QmakeProject::proFileParseError(error);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // we are changing what is executed in that case
							 | 
						||
| 
								 | 
							
								    if (result->state == QmakeEvalResult::EvalFail || m_project->wasEvaluateCanceled()) {
							 | 
						||
| 
								 | 
							
								        m_validParse = false;
							 | 
						||
| 
								 | 
							
								        cleanupProFileReaders();
							 | 
						||
| 
								 | 
							
								        setValidParseRecursive(false);
							 | 
						||
| 
								 | 
							
								        setParseInProgressRecursive(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (result->state == QmakeEvalResult::EvalFail) {
							 | 
						||
| 
								 | 
							
								            QmakeProject::proFileParseError(QCoreApplication::translate("QmakeParserProFileNode", "Error while parsing file %1. Giving up.")
							 | 
						||
| 
								 | 
							
								                                            .arg(m_projectFilePath.toUserOutput()));
							 | 
						||
| 
								 | 
							
								            if (m_projectType == ProjectType::Invalid)
							 | 
						||
| 
								 | 
							
								                return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // delete files && folders && projects
							 | 
						||
| 
								 | 
							
								            makeEmpty();
							 | 
						||
| 
								 | 
							
								            m_projectType = ProjectType::Invalid;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (debug)
							 | 
						||
| 
								 | 
							
								        qDebug() << "QmakeParserProFileNode - updating files for file " << m_projectFilePath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (result->projectType != m_projectType) {
							 | 
						||
| 
								 | 
							
								        // probably all subfiles/projects have changed anyway
							 | 
						||
| 
								 | 
							
								        // delete files && folders && projects
							 | 
						||
| 
								 | 
							
								        foreach (ProjectNode *projectNode, projectNodes()) {
							 | 
						||
| 
								 | 
							
								            if (QmakeParserProFileNode *qmakeProFileNode = dynamic_cast<QmakeParserProFileNode *>(projectNode)) {
							 | 
						||
| 
								 | 
							
								                qmakeProFileNode->setValidParseRecursive(false);
							 | 
						||
| 
								 | 
							
								                qmakeProFileNode->setParseInProgressRecursive(false);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        makeEmpty();
							 | 
						||
| 
								 | 
							
								        m_projectType = result->projectType;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // Add/Remove pri files, sub projects
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QString buildDirectory = buildDir();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QList<QPair<QmakeParserPriFileNode *, QmakeIncludedPriFile *>> toCompare;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    toCompare.append(qMakePair(this, &result->includedFiles));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    makeEmpty();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (!toCompare.isEmpty()) {
							 | 
						||
| 
								 | 
							
								        QmakeParserPriFileNode *pn = toCompare.first().first;
							 | 
						||
| 
								 | 
							
								        QmakeIncludedPriFile *tree = toCompare.first().second;
							 | 
						||
| 
								 | 
							
								        toCompare.pop_front();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (QmakeIncludedPriFile *priFile : tree->children) {
							 | 
						||
| 
								 | 
							
								            // 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<QmakeParserPriFileNode *>(n) && n->filePath() == priFile->name) {
							 | 
						||
| 
								 | 
							
								                    loop = true;
							 | 
						||
| 
								 | 
							
								                    break;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (loop)
							 | 
						||
| 
								 | 
							
								                continue; // Do nothing
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (priFile->proFile) {
							 | 
						||
| 
								 | 
							
								                QmakeParserPriFileNode *qmakePriFileNode = new QmakeParserPriFileNode(m_project, this, priFile->name);
							 | 
						||
| 
								 | 
							
								                pn->addNode(qmakePriFileNode);
							 | 
						||
| 
								 | 
							
								                qmakePriFileNode->setIncludedInExactParse(
							 | 
						||
| 
								 | 
							
								                            (result->state == QmakeEvalResult::EvalOk) && pn->includedInExactParse());
							 | 
						||
| 
								 | 
							
								                qmakePriFileNode->update(priFile->result);
							 | 
						||
| 
								 | 
							
								                toCompare.append(qMakePair(qmakePriFileNode, priFile));
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                QmakeParserProFileNode *qmakeProFileNode = new QmakeParserProFileNode(m_project, priFile->name);
							 | 
						||
| 
								 | 
							
								                pn->addNode(qmakeProFileNode);
							 | 
						||
| 
								 | 
							
								                qmakeProFileNode->setIncludedInExactParse(
							 | 
						||
| 
								 | 
							
								                            result->exactSubdirs.contains(qmakeProFileNode->filePath())
							 | 
						||
| 
								 | 
							
								                            && pn->includedInExactParse());
							 | 
						||
| 
								 | 
							
								                qmakeProFileNode->setParseInProgress(true);
							 | 
						||
| 
								 | 
							
								                qmakeProFileNode->asyncUpdate();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QmakeParserPriFileNode::update(result->includedFiles.result);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_validParse = (result->state == QmakeEvalResult::EvalOk);
							 | 
						||
| 
								 | 
							
								    if (m_validParse) {
							 | 
						||
| 
								 | 
							
								        // update TargetInformation
							 | 
						||
| 
								 | 
							
								        m_qmakeTargetInformation = result->targetInformation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        m_subProjectsNotToDeploy = result->subProjectsNotToDeploy;
							 | 
						||
| 
								 | 
							
								        m_installsList = result->installsList;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (m_varValues != result->newVarValues)
							 | 
						||
| 
								 | 
							
								            m_varValues = result->newVarValues;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const QString projectName = singleVariableValue(Variable::QmakeProjectName);
							 | 
						||
| 
								 | 
							
								        if (projectName.isEmpty())
							 | 
						||
| 
								 | 
							
								            setDisplayName(m_projectFilePath.toFileInfo().completeBaseName());
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            setDisplayName(projectName);
							 | 
						||
| 
								 | 
							
								    } // result == EvalOk
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    setParseInProgress(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    updateGeneratedFiles(buildDirectory);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    cleanupProFileReaders();
							 | 
						||
| 
								 | 
							
								    ProjectNode::emitTreeChanged();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::cleanupProFileReaders()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_project->destroyProFileReader(m_readerExact);
							 | 
						||
| 
								 | 
							
								    m_project->destroyProFileReader(m_readerCumulative);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_readerExact = nullptr;
							 | 
						||
| 
								 | 
							
								    m_readerCumulative = nullptr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::uiDirPath(QtSupport::ProFileReader *reader, const QString &buildDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QString path = reader->value(QLatin1String("UI_DIR"));
							 | 
						||
| 
								 | 
							
								    if (QFileInfo(path).isRelative())
							 | 
						||
| 
								 | 
							
								        path = QDir::cleanPath(buildDir + QLatin1Char('/') + path);
							 | 
						||
| 
								 | 
							
								    return path;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::mocDirPath(QtSupport::ProFileReader *reader, const QString &buildDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QString path = reader->value(QLatin1String("MOC_DIR"));
							 | 
						||
| 
								 | 
							
								    if (QFileInfo(path).isRelative())
							 | 
						||
| 
								 | 
							
								        path = QDir::cleanPath(buildDir + QLatin1Char('/') + path);
							 | 
						||
| 
								 | 
							
								    return path;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::sysrootify(const QString &path, const QString &sysroot,
							 | 
						||
| 
								 | 
							
								                                     const QString &baseDir, const QString &outputDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#ifdef Q_OS_WIN
							 | 
						||
| 
								 | 
							
								    Qt::CaseSensitivity cs = Qt::CaseInsensitive;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    Qt::CaseSensitivity cs = Qt::CaseSensitive;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    if (sysroot.isEmpty() || path.startsWith(sysroot, cs)
							 | 
						||
| 
								 | 
							
								        || path.startsWith(baseDir, cs) || path.startsWith(outputDir, cs)) {
							 | 
						||
| 
								 | 
							
								        return path;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    QString sysrooted = QDir::cleanPath(sysroot + path);
							 | 
						||
| 
								 | 
							
								    return !IoUtils::exists(sysrooted) ? path : sysrooted;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserProFileNode::includePaths(QtSupport::ProFileReader *reader, const QString &sysroot,
							 | 
						||
| 
								 | 
							
								                                           const QString &buildDir, const QString &projectDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList paths;
							 | 
						||
| 
								 | 
							
								    foreach (const QString &cxxflags, reader->values(QLatin1String("QMAKE_CXXFLAGS"))) {
							 | 
						||
| 
								 | 
							
								        if (cxxflags.startsWith(QLatin1String("-I")))
							 | 
						||
| 
								 | 
							
								            paths.append(cxxflags.mid(2));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach (const ProFileEvaluator::SourceFile &el,
							 | 
						||
| 
								 | 
							
								             reader->fixifiedValues(QLatin1String("INCLUDEPATH"), projectDir, buildDir)) {
							 | 
						||
| 
								 | 
							
								        paths << sysrootify(el.fileName, sysroot, projectDir, buildDir);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    // paths already contains moc dir and ui dir, due to corrrectly parsing uic.prf and moc.prf
							 | 
						||
| 
								 | 
							
								    // except if those directories don't exist at the time of parsing
							 | 
						||
| 
								 | 
							
								    // thus we add those directories manually (without checking for existence)
							 | 
						||
| 
								 | 
							
								    paths << mocDirPath(reader, buildDir) << uiDirPath(reader, buildDir);
							 | 
						||
| 
								 | 
							
								    paths.removeDuplicates();
							 | 
						||
| 
								 | 
							
								    return paths;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserProFileNode::libDirectories(QtSupport::ProFileReader *reader)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    QStringList result;
							 | 
						||
| 
								 | 
							
								    foreach (const QString &str, reader->values(QLatin1String("LIBS"))) {
							 | 
						||
| 
								 | 
							
								        if (str.startsWith(QLatin1String("-L")))
							 | 
						||
| 
								 | 
							
								            result.append(str.mid(2));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								FileNameList QmakeParserProFileNode::subDirsPaths(QtSupport::ProFileReader *reader,
							 | 
						||
| 
								 | 
							
								                                            const QString &projectDir,
							 | 
						||
| 
								 | 
							
								                                            QStringList *subProjectsNotToDeploy,
							 | 
						||
| 
								 | 
							
								                                            QStringList *errors)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    FileNameList subProjectPaths;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const QStringList subDirVars = reader->values(QLatin1String("SUBDIRS"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach (const QString &subDirVar, subDirVars) {
							 | 
						||
| 
								 | 
							
								        // Special case were subdir is just an identifier:
							 | 
						||
| 
								 | 
							
								        //   "SUBDIR = subid
							 | 
						||
| 
								 | 
							
								        //    subid.subdir = realdir"
							 | 
						||
| 
								 | 
							
								        // or
							 | 
						||
| 
								 | 
							
								        //   "SUBDIR = subid
							 | 
						||
| 
								 | 
							
								        //    subid.file = realdir/realfile.pro"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        QString realDir;
							 | 
						||
| 
								 | 
							
								        const QString subDirKey = subDirVar + QLatin1String(".subdir");
							 | 
						||
| 
								 | 
							
								        const QString subDirFileKey = subDirVar + QLatin1String(".file");
							 | 
						||
| 
								 | 
							
								        if (reader->contains(subDirKey))
							 | 
						||
| 
								 | 
							
								            realDir = reader->value(subDirKey);
							 | 
						||
| 
								 | 
							
								        else if (reader->contains(subDirFileKey))
							 | 
						||
| 
								 | 
							
								            realDir = reader->value(subDirFileKey);
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            realDir = subDirVar;
							 | 
						||
| 
								 | 
							
								        QFileInfo info(realDir);
							 | 
						||
| 
								 | 
							
								        if (!info.isAbsolute())
							 | 
						||
| 
								 | 
							
								            info.setFile(projectDir + QLatin1Char('/') + realDir);
							 | 
						||
| 
								 | 
							
								        realDir = info.filePath();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        QString realFile;
							 | 
						||
| 
								 | 
							
								        if (info.isDir())
							 | 
						||
| 
								 | 
							
								            realFile = QString::fromLatin1("%1/%2.pro").arg(realDir, info.fileName());
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            realFile = realDir;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (QFile::exists(realFile)) {
							 | 
						||
| 
								 | 
							
								            realFile = QDir::cleanPath(realFile);
							 | 
						||
| 
								 | 
							
								            subProjectPaths << FileName::fromString(realFile);
							 | 
						||
| 
								 | 
							
								            if (subProjectsNotToDeploy && !subProjectsNotToDeploy->contains(realFile)
							 | 
						||
| 
								 | 
							
								                    && reader->values(subDirVar + QLatin1String(".CONFIG"))
							 | 
						||
| 
								 | 
							
								                        .contains(QLatin1String("no_default_target"))) {
							 | 
						||
| 
								 | 
							
								                subProjectsNotToDeploy->append(realFile);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            if (errors)
							 | 
						||
| 
								 | 
							
								                errors->append(QCoreApplication::translate("QmakeParserProFileNode", "Could not find .pro file for subdirectory \"%1\" in \"%2\".")
							 | 
						||
| 
								 | 
							
								                               .arg(subDirVar).arg(realDir));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return Utils::filteredUnique(subProjectPaths);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TargetParserInformation QmakeParserProFileNode::targetInformation(QtSupport::ProFileReader *reader,
							 | 
						||
| 
								 | 
							
								                                                                  QtSupport::ProFileReader *readerBuildPass, const QString &buildDir, const QString &projectFilePath)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    TargetParserInformation result;
							 | 
						||
| 
								 | 
							
								    if (!reader || !readerBuildPass)
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QStringList builds = reader->values(QLatin1String("BUILDS"));
							 | 
						||
| 
								 | 
							
								    if (!builds.isEmpty()) {
							 | 
						||
| 
								 | 
							
								        QString build = builds.first();
							 | 
						||
| 
								 | 
							
								        result.buildTarget = reader->value(build + QLatin1String(".target"));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // BUILD DIR
							 | 
						||
| 
								 | 
							
								    result.buildDir = buildDir;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (readerBuildPass->contains(QLatin1String("DESTDIR")))
							 | 
						||
| 
								 | 
							
								        result.destDir = readerBuildPass->value(QLatin1String("DESTDIR"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Target
							 | 
						||
| 
								 | 
							
								    result.target = readerBuildPass->value(QLatin1String("TARGET"));
							 | 
						||
| 
								 | 
							
								    if (result.target.isEmpty())
							 | 
						||
| 
								 | 
							
								        result.target = QFileInfo(projectFilePath).baseName();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    result.valid = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TargetParserInformation QmakeParserProFileNode::targetInformation() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_qmakeTargetInformation;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								InstallsParserList QmakeParserProFileNode::installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath,
							 | 
						||
| 
								 | 
							
								                                                        const QString &projectDir, const QString &buildDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    InstallsParserList result;
							 | 
						||
| 
								 | 
							
								    if (!reader)
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    const QStringList &itemList = reader->values(QLatin1String("INSTALLS"));
							 | 
						||
| 
								 | 
							
								    if (itemList.isEmpty())
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const QString installPrefix
							 | 
						||
| 
								 | 
							
								            = reader->propertyValue(QLatin1String("QT_INSTALL_PREFIX"));
							 | 
						||
| 
								 | 
							
								    const QString devInstallPrefix
							 | 
						||
| 
								 | 
							
								            = reader->propertyValue(QLatin1String("QT_INSTALL_PREFIX/dev"));
							 | 
						||
| 
								 | 
							
								    bool fixInstallPrefix = (installPrefix != devInstallPrefix);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach (const QString &item, itemList) {
							 | 
						||
| 
								 | 
							
								        bool active = !reader->values(item + QLatin1String(".CONFIG"))
							 | 
						||
| 
								 | 
							
								                        .contains(QLatin1String("no_default_install"));
							 | 
						||
| 
								 | 
							
								        const QString pathVar = item + QLatin1String(".path");
							 | 
						||
| 
								 | 
							
								        const QStringList &itemPaths = reader->values(pathVar);
							 | 
						||
| 
								 | 
							
								        if (itemPaths.count() != 1) {
							 | 
						||
| 
								 | 
							
								            qDebug("Invalid RHS: Variable '%s' has %d values.",
							 | 
						||
| 
								 | 
							
								                qPrintable(pathVar), itemPaths.count());
							 | 
						||
| 
								 | 
							
								            if (itemPaths.isEmpty()) {
							 | 
						||
| 
								 | 
							
								                qDebug("%s: Ignoring INSTALLS item '%s', because it has no path.",
							 | 
						||
| 
								 | 
							
								                    qPrintable(projectFilePath), qPrintable(item));
							 | 
						||
| 
								 | 
							
								                continue;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        QString itemPath = itemPaths.last();
							 | 
						||
| 
								 | 
							
								        if (fixInstallPrefix && itemPath.startsWith(installPrefix)) {
							 | 
						||
| 
								 | 
							
								            // This is a hack for projects which install into $$[QT_INSTALL_*],
							 | 
						||
| 
								 | 
							
								            // in particular Qt itself, examples being most relevant.
							 | 
						||
| 
								 | 
							
								            // Projects which implement their own install path policy must
							 | 
						||
| 
								 | 
							
								            // parametrize their INSTALLS themselves depending on the intended
							 | 
						||
| 
								 | 
							
								            // installation/deployment mode.
							 | 
						||
| 
								 | 
							
								            itemPath.replace(0, installPrefix.length(), devInstallPrefix);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (item == QLatin1String("target")) {
							 | 
						||
| 
								 | 
							
								            if (active)
							 | 
						||
| 
								 | 
							
								                result.targetPath = itemPath;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            const auto &itemFiles = reader->fixifiedValues(
							 | 
						||
| 
								 | 
							
								                        item + QLatin1String(".files"), projectDir, buildDir);
							 | 
						||
| 
								 | 
							
								            result.items << InstallsParserItem(itemPath, itemFiles, active);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								InstallsParserList QmakeParserProFileNode::installsList() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_installsList;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::sourceDir() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_projectDir;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QString QmakeParserProFileNode::buildDir(QmakeBuildConfiguration *bc) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    const QDir srcDirRoot = m_project->rootProjectNode()->sourceDir();
							 | 
						||
| 
								 | 
							
								    const QString relativeDir = srcDirRoot.relativeFilePath(m_projectDir);
							 | 
						||
| 
								 | 
							
								    if (!bc && m_project->activeTarget())
							 | 
						||
| 
								 | 
							
								        bc = static_cast<QmakeBuildConfiguration *>(m_project->activeTarget()->activeBuildConfiguration());
							 | 
						||
| 
								 | 
							
								    if (!bc)
							 | 
						||
| 
								 | 
							
								        return QString();
							 | 
						||
| 
								 | 
							
								    return QDir::cleanPath(QDir(bc->buildDirectory().toString()).absoluteFilePath(relativeDir));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QStringList QmakeParserProFileNode::generatedFiles(const QString &buildDir,
							 | 
						||
| 
								 | 
							
								                                             const ProjectExplorer::FileNode *sourceFile) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // The mechanism for finding the file names is rather crude, but as we
							 | 
						||
| 
								 | 
							
								    // cannot parse QMAKE_EXTRA_COMPILERS and qmake has facilities to put
							 | 
						||
| 
								 | 
							
								    // ui_*.h files into a special directory, or even change the .h suffix, we
							 | 
						||
| 
								 | 
							
								    // cannot help doing this here.
							 | 
						||
| 
								 | 
							
								    switch (sourceFile->fileType()) {
							 | 
						||
| 
								 | 
							
								    case FileType::Form: {
							 | 
						||
| 
								 | 
							
								        FileName location;
							 | 
						||
| 
								 | 
							
								        auto it = m_varValues.constFind(Variable::UiDir);
							 | 
						||
| 
								 | 
							
								        if (it != m_varValues.constEnd() && !it.value().isEmpty())
							 | 
						||
| 
								 | 
							
								            location = FileName::fromString(it.value().front());
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								            location = FileName::fromString(buildDir);
							 | 
						||
| 
								 | 
							
								        if (location.isEmpty())
							 | 
						||
| 
								 | 
							
								            return QStringList();
							 | 
						||
| 
								 | 
							
								        location.appendPath(QLatin1String("ui_")
							 | 
						||
| 
								 | 
							
								                            + sourceFile->filePath().toFileInfo().completeBaseName()
							 | 
						||
| 
								 | 
							
								                            + singleVariableValue(Variable::HeaderExtension));
							 | 
						||
| 
								 | 
							
								        return QStringList(QDir::cleanPath(location.toString()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    case FileType::StateChart: {
							 | 
						||
| 
								 | 
							
								        if (buildDir.isEmpty())
							 | 
						||
| 
								 | 
							
								            return QStringList();
							 | 
						||
| 
								 | 
							
								        QString location = QDir::cleanPath(FileName::fromString(buildDir).appendPath(
							 | 
						||
| 
								 | 
							
								                    sourceFile->filePath().toFileInfo().completeBaseName()).toString());
							 | 
						||
| 
								 | 
							
								        return QStringList({location + singleVariableValue(Variable::HeaderExtension),
							 | 
						||
| 
								 | 
							
								                            location + singleVariableValue(Variable::CppExtension)});
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								        // TODO: Other types will be added when adapters for their compilers become available.
							 | 
						||
| 
								 | 
							
								        return QStringList();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QList<ExtraCompiler *> QmakeParserProFileNode::extraCompilers() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_extraCompilers;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void QmakeParserProFileNode::updateGeneratedFiles(const QString &buildDir)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // We can do this because other plugins are not supposed to keep the compilers around.
							 | 
						||
| 
								 | 
							
								    qDeleteAll(m_extraCompilers);
							 | 
						||
| 
								 | 
							
								    m_extraCompilers.clear();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Only those project types can have generated files for us
							 | 
						||
| 
								 | 
							
								    if (m_projectType != ProjectType::ApplicationTemplate
							 | 
						||
| 
								 | 
							
								            && m_projectType != ProjectType::SharedLibraryTemplate
							 | 
						||
| 
								 | 
							
								            && m_projectType != ProjectType::StaticLibraryTemplate) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    QList<ExtraCompilerFactory *> factories =
							 | 
						||
| 
								 | 
							
								            ProjectExplorer::ExtraCompilerFactory::extraCompilerFactories();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    FindGeneratorSourcesVisitor filesVisitor(factories, [&](
							 | 
						||
| 
								 | 
							
								                                             FileNode *file, ExtraCompilerFactory *factory) {
							 | 
						||
| 
								 | 
							
								        QStringList generated = generatedFiles(buildDir, file);
							 | 
						||
| 
								 | 
							
								        if (!generated.isEmpty()) {
							 | 
						||
| 
								 | 
							
								            FileNameList fileNames = Utils::transform(generated, [](const QString &name) {
							 | 
						||
| 
								 | 
							
								                return FileName::fromString(name);
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            m_extraCompilers.append(factory->create(m_project, file->filePath(), fileNames));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Find all generated files
							 | 
						||
| 
								 | 
							
								    accept(&filesVisitor);
							 | 
						||
| 
								 | 
							
								}
							 |