aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2016-08-05 11:59:28 +0300
committerUlf Hermann <ulf.hermann@qt.io>2016-08-05 11:40:07 +0200
commit1853f01a5b0955a28e9c321cd36f45d5f17651bf (patch)
tree5d357de37f3c2ef93e38bbc79ef96b6f8982cd6f /src
parent713bc04ad4560123d97bb469d109a0885cf36373 (diff)
parentd004203b13fa17d1258ee62d5eb4f681adf32398 (diff)
Merge remote-tracking branch 'origin/4.1'
Diffstat (limited to 'src')
-rw-r--r--src/libs/extensionsystem/pluginmanager.cpp4
-rw-r--r--src/libs/utils/smallstring.h1
-rw-r--r--src/libs/utils/theme/theme.h1
-rw-r--r--src/plugins/android/androidrunner.cpp53
-rw-r--r--src/plugins/android/androidrunner.h2
-rw-r--r--src/plugins/autotest/testcodeparser.cpp7
-rw-r--r--src/plugins/coreplugin/dialogs/externaltoolconfig.ui13
-rw-r--r--src/plugins/coreplugin/find/itemviewfind.cpp31
-rw-r--r--src/plugins/coreplugin/find/itemviewfind.h4
-rw-r--r--src/plugins/coreplugin/generalsettings.ui6
-rw-r--r--src/plugins/coreplugin/mimetypemagicdialog.ui9
-rw-r--r--src/plugins/coreplugin/mimetypesettingspage.ui10
-rw-r--r--src/plugins/coreplugin/systemsettings.ui15
-rw-r--r--src/plugins/cppeditor/cppautocompleter.cpp2
-rw-r--r--src/plugins/cppeditor/cppeditor.pro6
-rw-r--r--src/plugins/cppeditor/cppeditor.qbs3
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy.cpp414
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy.h79
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy_test.cpp8
-rw-r--r--src/plugins/cppeditor/cppincludehierarchyitem.cpp123
-rw-r--r--src/plugins/cppeditor/cppincludehierarchyitem.h68
-rw-r--r--src/plugins/cppeditor/cppincludehierarchymodel.cpp371
-rw-r--r--src/plugins/cppeditor/cppincludehierarchymodel.h90
-rw-r--r--src/plugins/cppeditor/cppincludehierarchytreeview.cpp52
-rw-r--r--src/plugins/cppeditor/cppincludehierarchytreeview.h42
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp5
-rw-r--r--src/plugins/debugger/debuggerkitconfigwidget.cpp10
-rw-r--r--src/plugins/debugger/debuggerkitconfigwidget.h1
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp3
-rw-r--r--src/plugins/debugger/debuggerruncontrol.cpp22
-rw-r--r--src/plugins/debugger/debuggersourcepathmappingwidget.cpp3
-rw-r--r--src/plugins/debugger/pdb/pdbengine.cpp4
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp4
-rw-r--r--src/plugins/debugger/watchhandler.cpp7
-rw-r--r--src/plugins/help/localhelpmanager.cpp2
-rw-r--r--src/plugins/nim/project/nimbuildconfiguration.cpp4
-rw-r--r--src/plugins/nim/project/nimrunconfiguration.cpp1
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp7
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.cpp5
-rw-r--r--src/plugins/qmldesigner/components/componentcore/theming.cpp10
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp12
-rw-r--r--src/plugins/resourceeditor/resourceeditorconstants.h2
-rw-r--r--src/shared/proparser/proitems.cpp15
-rw-r--r--src/shared/proparser/proitems.h21
-rw-r--r--src/shared/proparser/prowriter.cpp2
-rw-r--r--src/shared/proparser/qmakebuiltins.cpp340
-rw-r--r--src/shared/proparser/qmakeevaluator.cpp230
-rw-r--r--src/shared/proparser/qmakeevaluator.h27
-rw-r--r--src/shared/proparser/qmakeglobals.cpp29
-rw-r--r--src/shared/proparser/qmakeglobals.h3
-rw-r--r--src/shared/proparser/qmakeparser.cpp54
-rw-r--r--src/shared/proparser/qmakeparser.h6
-rw-r--r--src/shared/proparser/qmakevfs.cpp18
-rw-r--r--src/shared/proparser/qmakevfs.h2
m---------src/shared/qbs0
55 files changed, 1043 insertions, 1220 deletions
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index 63d9840853..cf8fd1b85e 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -51,6 +51,7 @@
#include <utils/qtcassert.h>
#ifdef WITH_TESTS
+#include <utils/hostosinfo.h>
#include <QTest>
#endif
@@ -1025,7 +1026,8 @@ static int executeTestPlan(const TestPlan &testPlan)
<< QLatin1String("-maxwarnings") << QLatin1String("0"); // unlimit output
qExecArguments << functions;
// avoid being stuck in QTBUG-24925
- qExecArguments << "-nocrashhandler";
+ if (!Utils::HostOsInfo::isWindowsHost())
+ qExecArguments << "-nocrashhandler";
failedTests += QTest::qExec(testObject, qExecArguments);
}
diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h
index 9e7ad9fb69..316fdb7741 100644
--- a/src/libs/utils/smallstring.h
+++ b/src/libs/utils/smallstring.h
@@ -38,6 +38,7 @@
#include <QString>
#include <algorithm>
+#include <cmath>
#include <cstdlib>
#include <climits>
#include <cstring>
diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h
index dd2eac9a0d..188ed0cc9e 100644
--- a/src/libs/utils/theme/theme.h
+++ b/src/libs/utils/theme/theme.h
@@ -282,6 +282,7 @@ public:
ClangCodeModel_Warning_TextMarkColor,
/* QmlDesigner */
+ QmlDesigner_BackgroundColor,
QmlDesigner_HighlightColor
};
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index 62361a443c..a56ec7ffd5 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -258,23 +258,6 @@ static int extractPid(const QString &exeName, const QByteArray &psOutput)
return extractPidFromChunk(psOutput, from);
}
-QByteArray AndroidRunner::runPs()
-{
- if (QThread::currentThread() != thread()) {
- QByteArray ret;
- QMetaObject::invokeMethod(this, "runPs", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QByteArray, ret));
- return ret;
- } else {
- QByteArray psLine("ps");
- if (m_isBusyBox)
- psLine += " -w";
- psLine += '\n';
- m_psProc.write(psLine);
- m_psProc.waitForBytesWritten(psLine.size());
- return m_psProc.readAllStandardOutput();
- }
-}
-
void AndroidRunner::launchAVDProcesses()
{
// Its assumed that the device or avd serial returned by selector() is online.
@@ -284,8 +267,13 @@ void AndroidRunner::launchAVDProcesses()
void AndroidRunner::checkPID()
{
- QByteArray psOut = runPs();
- m_processPID = extractPid(m_androidRunnable.packageName, psOut);
+ // Don't write to m_psProc from a different thread
+ QTC_ASSERT(QThread::currentThread() == thread(), return);
+
+ QByteArray psLine(m_isBusyBox ? "ps -w\n" : "ps\n");
+ m_psProc.write(psLine);
+ m_psProc.waitForBytesWritten(psLine.size());
+ m_processPID = extractPid(m_androidRunnable.packageName, m_psProc.readAllStandardOutput());
if (m_processPID == -1) {
if (m_wasStarted) {
@@ -320,11 +308,17 @@ void AndroidRunner::checkPID()
void AndroidRunner::forceStop()
{
+ // Don't run Utils::SynchronousProcess on the GUI thread
+ QTC_ASSERT(QThread::currentThread() != thread(), return);
+
runAdb(selector() << _("shell") << _("am") << _("force-stop") << m_androidRunnable.packageName,
nullptr, 30);
// try killing it via kill -9
- const QByteArray out = runPs();
+ const QByteArray out = Utils::SynchronousProcess()
+ .runBlocking(m_adb, selector() << _("shell") << _(m_isBusyBox ? "ps -w" : "ps"))
+ .allRawOutput();
+
int from = 0;
while (1) {
const int to = out.indexOf('\n', from);
@@ -346,7 +340,7 @@ void AndroidRunner::start()
launchAVD();
}
- Utils::runAsync(&AndroidRunner::asyncStart, this);
+ Utils::runAsync(&AndroidRunner::asyncStart, this).waitForFinished();
}
void AndroidRunner::asyncStart()
@@ -588,8 +582,6 @@ void AndroidRunner::handleRemoteDebuggerRunning()
void AndroidRunner::stop()
{
- QMutexLocker locker(&m_mutex);
-
if (m_avdFutureInterface.isRunning()) {
m_avdFutureInterface.cancel();
m_avdFutureInterface.waitForFinished();
@@ -597,16 +589,21 @@ void AndroidRunner::stop()
}
m_checkPIDTimer.stop();
+ m_adbLogcatProcess.kill();
+ m_psProc.kill();
+ Utils::runAsync(&AndroidRunner::asyncStop, this).waitForFinished();
+ m_adbLogcatProcess.waitForFinished();
+ m_psProc.waitForFinished();
+}
+
+void AndroidRunner::asyncStop()
+{
+ QMutexLocker locker(&m_mutex);
m_tries = 0;
if (m_processPID != -1) {
forceStop();
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" terminated.").arg(m_androidRunnable.packageName));
}
- //QObject::disconnect(&m_adbLogcatProcess, 0, this, 0);
- m_adbLogcatProcess.kill();
- m_adbLogcatProcess.waitForFinished();
- m_psProc.kill();
- m_psProc.waitForFinished();
foreach (const QStringList &entry, m_androidRunnable.afterFinishADBCommands)
runAdb(selector() << entry);
}
diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h
index 3ed99e0061..62e7ad9518 100644
--- a/src/plugins/android/androidrunner.h
+++ b/src/plugins/android/androidrunner.h
@@ -80,7 +80,7 @@ private:
void logcatReadStandardError();
void logcatReadStandardOutput();
void asyncStart();
- Q_INVOKABLE QByteArray runPs();
+ void asyncStop();
Q_INVOKABLE void launchAVDProcesses();
void adbKill(qint64 pid);
QStringList selector() const { return m_selector; }
diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp
index 45f7a07b1b..ff911de5d3 100644
--- a/src/plugins/autotest/testcodeparser.cpp
+++ b/src/plugins/autotest/testcodeparser.cpp
@@ -318,8 +318,13 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
QStringList list;
if (isFullParse) {
list = ProjectExplorer::SessionManager::startupProject()->files(ProjectExplorer::Project::SourceFiles);
- if (list.isEmpty())
+ if (list.isEmpty()) {
+ // at least project file should be there, but might happen if parsing current project
+ // takes too long, especially when opening sessions holding multiple projects
+ qCDebug(LOG) << "File list empty (FullParse) - trying again in a sec";
+ emitUpdateTestTree();
return;
+ }
qCDebug(LOG) << "setting state to FullParse (scanForTests)";
m_parserState = FullParse;
} else {
diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.ui b/src/plugins/coreplugin/dialogs/externaltoolconfig.ui
index 1c8a76c30e..36d3247d26 100644
--- a/src/plugins/coreplugin/dialogs/externaltoolconfig.ui
+++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.ui
@@ -288,6 +288,19 @@
</slots>
</customwidget>
</customwidgets>
+ <tabstops>
+ <tabstop>toolTree</tabstop>
+ <tabstop>addButton</tabstop>
+ <tabstop>removeButton</tabstop>
+ <tabstop>revertButton</tabstop>
+ <tabstop>description</tabstop>
+ <tabstop>arguments</tabstop>
+ <tabstop>outputBehavior</tabstop>
+ <tabstop>errorOutputBehavior</tabstop>
+ <tabstop>environmentButton</tabstop>
+ <tabstop>modifiesDocumentCheckbox</tabstop>
+ <tabstop>inputText</tabstop>
+ </tabstops>
<resources/>
<connections/>
</ui>
diff --git a/src/plugins/coreplugin/find/itemviewfind.cpp b/src/plugins/coreplugin/find/itemviewfind.cpp
index b9328f6550..3588f125ec 100644
--- a/src/plugins/coreplugin/find/itemviewfind.cpp
+++ b/src/plugins/coreplugin/find/itemviewfind.cpp
@@ -128,25 +128,42 @@ IFindSupport::Result ItemViewFind::findStep(const QString &txt, FindFlags findFl
return result;
}
-QFrame *ItemViewFind::createSearchableWrapper(QAbstractItemView *treeView, ColorOption lightColored, FetchOption option)
+static QFrame *createHelper(QAbstractItemView *treeView,
+ ItemViewFind::ColorOption colorOption,
+ ItemViewFind *finder)
{
- QFrame *widget = new QFrame;
+ auto widget = new QFrame;
widget->setFrameStyle(QFrame::NoFrame);
- QVBoxLayout *vbox = new QVBoxLayout(widget);
+
+ auto placeHolder = new FindToolBarPlaceHolder(widget);
+ placeHolder->setLightColored(colorOption);
+
+ auto vbox = new QVBoxLayout(widget);
vbox->setMargin(0);
vbox->setSpacing(0);
vbox->addWidget(treeView);
- auto placeHolder = new FindToolBarPlaceHolder(widget);
- placeHolder->setLightColored(lightColored);
vbox->addWidget(placeHolder);
- Aggregation::Aggregate *agg = new Aggregation::Aggregate;
+ auto agg = new Aggregation::Aggregate;
agg->add(treeView);
- agg->add(new ItemViewFind(treeView, Qt::DisplayRole, option));
+ agg->add(finder);
return widget;
}
+QFrame *ItemViewFind::createSearchableWrapper(QAbstractItemView *treeView,
+ ColorOption colorOption,
+ FetchOption option)
+{
+ return createHelper(treeView, colorOption, new ItemViewFind(treeView, Qt::DisplayRole, option));
+}
+
+QFrame *ItemViewFind::createSearchableWrapper(ItemViewFind *finder,
+ ItemViewFind::ColorOption colorOption)
+{
+ return createHelper(finder->d->m_view, colorOption, finder);
+}
+
IFindSupport::Result ItemViewFind::find(const QString &searchTxt,
FindFlags findFlags,
bool startFromCurrentIndex,
diff --git a/src/plugins/coreplugin/find/itemviewfind.h b/src/plugins/coreplugin/find/itemviewfind.h
index dad9089dc5..026ed4d557 100644
--- a/src/plugins/coreplugin/find/itemviewfind.h
+++ b/src/plugins/coreplugin/find/itemviewfind.h
@@ -65,8 +65,10 @@ public:
Result findIncremental(const QString &txt, FindFlags findFlags);
Result findStep(const QString &txt, FindFlags findFlags);
- static QFrame *createSearchableWrapper(QAbstractItemView *treeView, ColorOption lightColored = DarkColored,
+ static QFrame *createSearchableWrapper(QAbstractItemView *treeView, ColorOption colorOption = DarkColored,
FetchOption option = DoNotFetchMoreWhileSearching);
+ static QFrame *createSearchableWrapper(ItemViewFind *finder, ColorOption colorOption = DarkColored);
+
private:
Result find(const QString &txt, FindFlags findFlags,
bool startFromCurrentIndex, bool *wrapped);
diff --git a/src/plugins/coreplugin/generalsettings.ui b/src/plugins/coreplugin/generalsettings.ui
index be3adc7c55..333be51ac7 100644
--- a/src/plugins/coreplugin/generalsettings.ui
+++ b/src/plugins/coreplugin/generalsettings.ui
@@ -155,6 +155,12 @@
<container>1</container>
</customwidget>
</customwidgets>
+ <tabstops>
+ <tabstop>colorButton</tabstop>
+ <tabstop>resetColorButton</tabstop>
+ <tabstop>languageBox</tabstop>
+ <tabstop>resetWarningsButton</tabstop>
+ </tabstops>
<resources/>
<connections/>
</ui>
diff --git a/src/plugins/coreplugin/mimetypemagicdialog.ui b/src/plugins/coreplugin/mimetypemagicdialog.ui
index bca3dad241..f638354881 100644
--- a/src/plugins/coreplugin/mimetypemagicdialog.ui
+++ b/src/plugins/coreplugin/mimetypemagicdialog.ui
@@ -238,6 +238,15 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>valueLineEdit</tabstop>
+ <tabstop>typeSelector</tabstop>
+ <tabstop>maskLineEdit</tabstop>
+ <tabstop>useRecommendedGroupBox</tabstop>
+ <tabstop>startRangeSpinBox</tabstop>
+ <tabstop>endRangeSpinBox</tabstop>
+ <tabstop>prioritySpinBox</tabstop>
+ </tabstops>
<resources/>
<connections>
<connection>
diff --git a/src/plugins/coreplugin/mimetypesettingspage.ui b/src/plugins/coreplugin/mimetypesettingspage.ui
index 2b4e6fbadc..ca3a23f8a2 100644
--- a/src/plugins/coreplugin/mimetypesettingspage.ui
+++ b/src/plugins/coreplugin/mimetypesettingspage.ui
@@ -169,6 +169,16 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>filterLineEdit</tabstop>
+ <tabstop>mimeTypesTreeView</tabstop>
+ <tabstop>resetButton</tabstop>
+ <tabstop>patternsLineEdit</tabstop>
+ <tabstop>magicHeadersTreeWidget</tabstop>
+ <tabstop>addMagicButton</tabstop>
+ <tabstop>editMagicButton</tabstop>
+ <tabstop>removeMagicButton</tabstop>
+ </tabstops>
<resources/>
<connections/>
</ui>
diff --git a/src/plugins/coreplugin/systemsettings.ui b/src/plugins/coreplugin/systemsettings.ui
index f79d829a47..0afda779ea 100644
--- a/src/plugins/coreplugin/systemsettings.ui
+++ b/src/plugins/coreplugin/systemsettings.ui
@@ -374,6 +374,21 @@
</slots>
</customwidget>
</customwidgets>
+ <tabstops>
+ <tabstop>terminalComboBox</tabstop>
+ <tabstop>resetTerminalButton</tabstop>
+ <tabstop>externalFileBrowserEdit</tabstop>
+ <tabstop>resetFileBrowserButton</tabstop>
+ <tabstop>helpExternalFileBrowserButton</tabstop>
+ <tabstop>fileSystemCaseSensitivityChooser</tabstop>
+ <tabstop>reloadBehavior</tabstop>
+ <tabstop>autoSaveCheckBox</tabstop>
+ <tabstop>autoSaveInterval</tabstop>
+ <tabstop>autoSuspendCheckBox</tabstop>
+ <tabstop>autoSuspendMinDocumentCount</tabstop>
+ <tabstop>warnBeforeOpeningBigFiles</tabstop>
+ <tabstop>bigFilesLimitSpinBox</tabstop>
+ </tabstops>
<resources>
<include location="core.qrc"/>
</resources>
diff --git a/src/plugins/cppeditor/cppautocompleter.cpp b/src/plugins/cppeditor/cppautocompleter.cpp
index 2df19e8a02..da1e6b527b 100644
--- a/src/plugins/cppeditor/cppautocompleter.cpp
+++ b/src/plugins/cppeditor/cppautocompleter.cpp
@@ -371,7 +371,7 @@ void CppEditorPlugin::test_autoBackspace_data()
QTest::newRow((QLatin1String("Inside ") + charGroupTestName(c)).toLatin1().data())
<< fileContent(InBetween, c)
- << QString("([").contains(c);
+ << QString("(['\"").contains(c);
}
}
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index b616682dce..6394bba5bb 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -18,9 +18,6 @@ HEADERS += \
cpphighlighter.h \
cpphoverhandler.h \
cppincludehierarchy.h \
- cppincludehierarchyitem.h \
- cppincludehierarchymodel.h \
- cppincludehierarchytreeview.h \
cppinsertvirtualmethods.h \
cpplocalrenaming.h \
cppoutline.h \
@@ -48,9 +45,6 @@ SOURCES += \
cpphighlighter.cpp \
cpphoverhandler.cpp \
cppincludehierarchy.cpp \
- cppincludehierarchyitem.cpp \
- cppincludehierarchymodel.cpp \
- cppincludehierarchytreeview.cpp \
cppinsertvirtualmethods.cpp \
cpplocalrenaming.cpp \
cppoutline.cpp \
diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs
index 79105dc907..8267939e14 100644
--- a/src/plugins/cppeditor/cppeditor.qbs
+++ b/src/plugins/cppeditor/cppeditor.qbs
@@ -37,9 +37,6 @@ QtcPlugin {
"cpphighlighter.cpp", "cpphighlighter.h",
"cpphoverhandler.cpp", "cpphoverhandler.h",
"cppincludehierarchy.cpp", "cppincludehierarchy.h",
- "cppincludehierarchyitem.cpp", "cppincludehierarchyitem.h",
- "cppincludehierarchymodel.cpp", "cppincludehierarchymodel.h",
- "cppincludehierarchytreeview.cpp", "cppincludehierarchytreeview.h",
"cppinsertvirtualmethods.cpp",
"cppinsertvirtualmethods.h",
"cpplocalrenaming.cpp", "cpplocalrenaming.h",
diff --git a/src/plugins/cppeditor/cppincludehierarchy.cpp b/src/plugins/cppeditor/cppincludehierarchy.cpp
index b2eedf8021..b3b4f6c9f9 100644
--- a/src/plugins/cppeditor/cppincludehierarchy.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchy.cpp
@@ -29,50 +29,341 @@
#include "cppeditorconstants.h"
#include "cppeditorplugin.h"
#include "cppelementevaluator.h"
-#include "cppincludehierarchymodel.h"
-#include "cppincludehierarchytreeview.h"
-
-#include <texteditor/textdocument.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/fileiconprovider.h>
#include <coreplugin/find/itemviewfind.h>
+
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cppmodelmanager.h>
+#include <cpptools/cpptoolsbridge.h>
+#include <cpptools/editordocumenthandle.h>
+
#include <cplusplus/CppDocument.h>
#include <utils/annotateditemdelegate.h>
+#include <utils/dropsupport.h>
#include <utils/fileutils.h>
+#include <utils/navigationtreeview.h>
+#include <utils/qtcassert.h>
-#include <QDir>
+#include <QCoreApplication>
+#include <QKeyEvent>
#include <QLabel>
-#include <QLatin1String>
-#include <QModelIndex>
-#include <QStandardItem>
+#include <QStackedWidget>
#include <QVBoxLayout>
+using namespace Core;
+using namespace CPlusPlus;
+using namespace CppTools;
using namespace TextEditor;
using namespace Utils;
namespace CppEditor {
namespace Internal {
+enum {
+ AnnotationRole = Qt::UserRole + 1,
+ LinkRole
+};
+
+static Snapshot globalSnapshot()
+{
+ return CppModelManager::instance()->snapshot();
+}
+
+struct FileAndLine
+{
+ FileAndLine() {}
+ FileAndLine(const QString &f, int l) : file(f), line(l) {}
+
+ QString file;
+ int line = 0;
+};
+
+using FileAndLines = QList<FileAndLine>;
+
+static FileAndLines findIncluders(const QString &filePath)
+{
+ FileAndLines result;
+ const Snapshot snapshot = globalSnapshot();
+ for (auto cit = snapshot.begin(), citEnd = snapshot.end(); cit != citEnd; ++cit) {
+ const QString filePathFromSnapshot = cit.key().toString();
+ Document::Ptr doc = cit.value();
+ const QList<Document::Include> resolvedIncludes = doc->resolvedIncludes();
+ for (const auto &includeFile : resolvedIncludes) {
+ const QString includedFilePath = includeFile.resolvedFileName();
+ if (includedFilePath == filePath)
+ result.append(FileAndLine(filePathFromSnapshot, int(includeFile.line())));
+ }
+ }
+ return result;
+}
+
+static FileAndLines findIncludes(const QString &filePath, const Snapshot &snapshot)
+{
+ FileAndLines result;
+ if (Document::Ptr doc = snapshot.document(filePath)) {
+ const QList<Document::Include> resolvedIncludes = doc->resolvedIncludes();
+ for (const auto &includeFile : resolvedIncludes)
+ result.append(FileAndLine(includeFile.resolvedFileName(), 0));
+ }
+ return result;
+}
+
+class CppIncludeHierarchyItem
+ : public TypedTreeItem<CppIncludeHierarchyItem, CppIncludeHierarchyItem>
+{
+public:
+ enum SubTree { RootItem, InIncludes, InIncludedBy };
+ CppIncludeHierarchyItem() {}
+
+ void createChild(const QString &filePath, SubTree subTree,
+ int line = 0, bool definitelyNoChildren = false)
+ {
+ auto item = new CppIncludeHierarchyItem;
+ item->m_fileName = filePath.mid(filePath.lastIndexOf('/') + 1);
+ item->m_filePath = filePath;
+ item->m_line = line;
+ item->m_subTree = subTree;
+ appendChild(item);
+ for (auto ancestor = this; ancestor; ancestor = ancestor->parent()) {
+ if (ancestor->filePath() == filePath) {
+ item->m_isCyclic = true;
+ break;
+ }
+ }
+ if (filePath == model()->editorFilePath() || definitelyNoChildren)
+ item->setChildrenChecked();
+ }
+
+ QString filePath() const
+ {
+ return isPhony() ? model()->editorFilePath() : m_filePath;
+ }
+
+private:
+ bool isPhony() const { return !parent() || !parent()->parent(); }
+ void setChildrenChecked() { m_checkedForChildren = true; }
+
+ CppIncludeHierarchyModel *model() const
+ {
+ return static_cast<CppIncludeHierarchyModel *>(TreeItem::model());
+ }
+
+ QVariant data(int column, int role) const override;
+
+ Qt::ItemFlags flags(int) const override
+ {
+ TextEditorWidget::Link link(m_filePath, m_line);
+ if (link.hasValidTarget())
+ return Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ }
+
+ bool canFetchMore() const override;
+ void fetchMore() override;
+
+ QString m_fileName;
+ QString m_filePath;
+ int m_line = 0;
+ SubTree m_subTree = RootItem;
+ bool m_isCyclic = false;
+ bool m_checkedForChildren = false;
+};
+
+QVariant CppIncludeHierarchyItem::data(int column, int role) const
+{
+ Q_UNUSED(column);
+ if (role == Qt::DisplayRole) {
+ if (isPhony() && childCount() == 0)
+ return QString(m_fileName + ' ' + CppIncludeHierarchyModel::tr("(none)"));
+ if (m_isCyclic)
+ return QString(m_fileName + ' ' + CppIncludeHierarchyModel::tr("(cyclic)"));
+ return m_fileName;
+ }
+
+ if (isPhony())
+ return QVariant();
+
+ switch (role) {
+ case Qt::ToolTipRole:
+ return m_filePath;
+ case Qt::DecorationRole:
+ return FileIconProvider::icon(QFileInfo(m_filePath));
+ case LinkRole:
+ return QVariant::fromValue(TextEditorWidget::Link(m_filePath, m_line));
+ }
+
+ return QVariant();
+}
+
+bool CppIncludeHierarchyItem::canFetchMore() const
+{
+ if (m_isCyclic || m_checkedForChildren || !children().isEmpty())
+ return false;
+
+ return !model()->m_searching || !model()->m_seen.contains(m_filePath);
+}
+
+void CppIncludeHierarchyItem::fetchMore()
+{
+ QTC_ASSERT(canFetchMore(), setChildrenChecked(); return);
+ QTC_ASSERT(model(), return);
+ QTC_ASSERT(m_subTree != RootItem, return); // Root should always be populated.
+
+ model()->m_seen.insert(m_filePath);
+
+ const QString editorFilePath = model()->editorFilePath();
+
+ setChildrenChecked();
+ if (m_subTree == InIncludes) {
+ auto processor = CppToolsBridge::baseEditorDocumentProcessor(editorFilePath);
+ QTC_ASSERT(processor, return);
+ const Snapshot snapshot = processor->snapshot();
+ const FileAndLines includes = findIncludes(filePath(), snapshot);
+ for (const FileAndLine &include : includes) {
+ const FileAndLines subIncludes = findIncludes(include.file, snapshot);
+ bool definitelyNoChildren = subIncludes.isEmpty();
+ createChild(include.file, InIncludes, include.line, definitelyNoChildren);
+ }
+ } else if (m_subTree == InIncludedBy) {
+ const FileAndLines includers = findIncluders(filePath());
+ for (const FileAndLine &includer : includers) {
+ const FileAndLines subIncluders = findIncluders(includer.file);
+ bool definitelyNoChildren = subIncluders.isEmpty();
+ createChild(includer.file, InIncludedBy, includer.line, definitelyNoChildren);
+ }
+ }
+}
+
+void CppIncludeHierarchyModel::buildHierarchy(const QString &document)
+{
+ m_editorFilePath = document;
+ rootItem()->removeChildren();
+ rootItem()->createChild(tr("Includes"), CppIncludeHierarchyItem::InIncludes);
+ rootItem()->createChild(tr("Included by"), CppIncludeHierarchyItem::InIncludedBy);
+}
+
+void CppIncludeHierarchyModel::setSearching(bool on)
+{
+ m_searching = on;
+ m_seen.clear();
+}
+
+
+// CppIncludeHierarchyModel
+
+CppIncludeHierarchyModel::CppIncludeHierarchyModel()
+{
+ setRootItem(new CppIncludeHierarchyItem); // FIXME: Remove in 4.2
+}
+
+Qt::DropActions CppIncludeHierarchyModel::supportedDragActions() const
+{
+ return Qt::MoveAction;
+}
+
+QStringList CppIncludeHierarchyModel::mimeTypes() const
+{
+ return DropSupport::mimeTypesForFilePaths();
+}
+
+QMimeData *CppIncludeHierarchyModel::mimeData(const QModelIndexList &indexes) const
+{
+ auto data = new DropMimeData;
+ foreach (const QModelIndex &index, indexes) {
+ auto link = index.data(LinkRole).value<TextEditorWidget::Link>();
+ if (link.hasValidTarget())
+ data->addFile(link.targetFileName, link.targetLine, link.targetColumn);
+ }
+ return data;
+}
+
+
+// CppIncludeHierarchyTreeView
+
+class CppIncludeHierarchyTreeView : public NavigationTreeView
+{
+public:
+ CppIncludeHierarchyTreeView()
+ {
+ setDragEnabled(true);
+ setDragDropMode(QAbstractItemView::DragOnly);
+ }
+
+protected:
+ void keyPressEvent(QKeyEvent *event) override
+ {
+ if (event->key())
+ QAbstractItemView::keyPressEvent(event);
+ else
+ NavigationTreeView::keyPressEvent(event);
+ }
+};
+
+
+// IncludeFinder
+
+class IncludeFinder : public ItemViewFind
+{
+public:
+ IncludeFinder(QAbstractItemView *view, CppIncludeHierarchyModel *model)
+ : ItemViewFind(view, Qt::DisplayRole, FetchMoreWhileSearching)
+ , m_model(model)
+ {}
+
+private:
+ Result findIncremental(const QString &txt, FindFlags findFlags)
+ {
+ m_model->setSearching(true);
+ Result result = ItemViewFind::findIncremental(txt, findFlags);
+ m_model->setSearching(false);
+ return result;
+ }
+
+ CppIncludeHierarchyModel *m_model; // Not owned.
+};
+
+
// CppIncludeHierarchyWidget
-CppIncludeHierarchyWidget::CppIncludeHierarchyWidget() :
- QWidget(0),
- m_treeView(0),
- m_model(0),
- m_delegate(0),
- m_includeHierarchyInfoLabel(0),
- m_editor(0)
+
+class CppIncludeHierarchyWidget : public QWidget
+{
+ Q_DECLARE_TR_FUNCTIONS(CppEditor::CppIncludeHierarchy)
+
+public:
+ CppIncludeHierarchyWidget();
+ ~CppIncludeHierarchyWidget() { delete m_treeView; }
+
+ void perform();
+
+private:
+ void onItemActivated(const QModelIndex &index);
+ void editorsClosed(QList<IEditor *> editors);
+ void showNoIncludeHierarchyLabel();
+ void showIncludeHierarchy();
+
+ CppIncludeHierarchyTreeView *m_treeView = nullptr;
+ CppIncludeHierarchyModel m_model;
+ AnnotatedItemDelegate m_delegate;
+ TextEditorLinkLabel *m_inspectedFile = nullptr;
+ QLabel *m_includeHierarchyInfoLabel = nullptr;
+ BaseTextEditor *m_editor = nullptr;
+};
+
+CppIncludeHierarchyWidget::CppIncludeHierarchyWidget()
{
+ m_delegate.setDelimiter(" ");
+ m_delegate.setAnnotationRole(AnnotationRole);
+
m_inspectedFile = new TextEditorLinkLabel(this);
m_inspectedFile->setMargin(5);
- m_model = new CppIncludeHierarchyModel(this);
- m_treeView = new CppIncludeHierarchyTreeView(this);
- m_delegate = new AnnotatedItemDelegate(this);
- m_delegate->setDelimiter(QLatin1String(" "));
- m_delegate->setAnnotationRole(AnnotationRole);
- m_treeView->setModel(m_model);
+
+ m_treeView = new CppIncludeHierarchyTreeView;
+ m_treeView->setModel(&m_model);
m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
- m_treeView->setItemDelegate(m_delegate);
+ m_treeView->setItemDelegate(&m_delegate);
connect(m_treeView, &QAbstractItemView::activated, this, &CppIncludeHierarchyWidget::onItemActivated);
m_includeHierarchyInfoLabel = new QLabel(tr("No include hierarchy available"), this);
@@ -81,69 +372,53 @@ CppIncludeHierarchyWidget::CppIncludeHierarchyWidget() :
m_includeHierarchyInfoLabel->setBackgroundRole(QPalette::Base);
m_includeHierarchyInfoLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
- QVBoxLayout *layout = new QVBoxLayout;
+ auto layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(m_inspectedFile);
- layout->addWidget(Core::ItemViewFind::createSearchableWrapper(
- m_treeView,
- Core::ItemViewFind::DarkColored,
- Core::ItemViewFind::FetchMoreWhileSearching));
+ layout->addWidget(ItemViewFind::createSearchableWrapper(new IncludeFinder(m_treeView, &m_model)));
layout->addWidget(m_includeHierarchyInfoLabel);
- setLayout(layout);
connect(CppEditorPlugin::instance(), &CppEditorPlugin::includeHierarchyRequested,
this, &CppIncludeHierarchyWidget::perform);
- connect(Core::EditorManager::instance(), &Core::EditorManager::editorsClosed,
+ connect(EditorManager::instance(), &EditorManager::editorsClosed,
this, &CppIncludeHierarchyWidget::editorsClosed);
-
-}
-
-CppIncludeHierarchyWidget::~CppIncludeHierarchyWidget()
-{
}
void CppIncludeHierarchyWidget::perform()
{
showNoIncludeHierarchyLabel();
- m_editor = qobject_cast<CppEditor *>(Core::EditorManager::currentEditor());
+ m_editor = qobject_cast<CppEditor *>(EditorManager::currentEditor());
if (!m_editor)
return;
- CppEditorWidget *widget = qobject_cast<CppEditorWidget *>(m_editor->widget());
- if (!widget)
- return;
+ QString document = m_editor->textDocument()->filePath().toString();
+ m_model.buildHierarchy(document);
- m_model->clear();
- m_model->buildHierarchy(m_editor, widget->textDocument()->filePath().toString());
- if (m_model->isEmpty())
- return;
-
- m_inspectedFile->setText(widget->textDocument()->displayName());
- m_inspectedFile->setLink(TextEditorWidget::Link(widget->textDocument()->filePath().toString()));
+ m_inspectedFile->setText(m_editor->textDocument()->displayName());
+ m_inspectedFile->setLink(TextEditorWidget::Link(document));
- //expand "Includes"
- m_treeView->expand(m_model->index(0, 0));
- //expand "Included by"
- m_treeView->expand(m_model->index(1, 0));
+ // expand "Includes" adn "Included by"
+ m_treeView->expand(m_model.index(0, 0));
+ m_treeView->expand(m_model.index(1, 0));
showIncludeHierarchy();
}
void CppIncludeHierarchyWidget::onItemActivated(const QModelIndex &index)
{
- const TextEditorWidget::Link link = index.data(LinkRole).value<TextEditorWidget::Link>();
+ const auto link = index.data(LinkRole).value<TextEditorWidget::Link>();
if (link.hasValidTarget())
- Core::EditorManager::openEditorAt(link.targetFileName,
- link.targetLine,
- link.targetColumn,
- Constants::CPPEDITOR_ID);
+ EditorManager::openEditorAt(link.targetFileName,
+ link.targetLine,
+ link.targetColumn,
+ Constants::CPPEDITOR_ID);
}
-void CppIncludeHierarchyWidget::editorsClosed(QList<Core::IEditor *> editors)
+void CppIncludeHierarchyWidget::editorsClosed(QList<IEditor *> editors)
{
- foreach (Core::IEditor *editor, editors) {
+ foreach (IEditor *editor, editors) {
if (m_editor == editor)
perform();
}
@@ -163,20 +438,9 @@ void CppIncludeHierarchyWidget::showIncludeHierarchy()
m_includeHierarchyInfoLabel->hide();
}
-// CppIncludeHierarchyStackedWidget
-CppIncludeHierarchyStackedWidget::CppIncludeHierarchyStackedWidget(QWidget *parent) :
- QStackedWidget(parent),
- m_typeHiearchyWidgetInstance(new CppIncludeHierarchyWidget)
-{
- addWidget(m_typeHiearchyWidgetInstance);
-}
-
-CppIncludeHierarchyStackedWidget::~CppIncludeHierarchyStackedWidget()
-{
- delete m_typeHiearchyWidgetInstance;
-}
// CppIncludeHierarchyFactory
+
CppIncludeHierarchyFactory::CppIncludeHierarchyFactory()
{
setDisplayName(tr("Include Hierarchy"));
@@ -184,12 +448,16 @@ CppIncludeHierarchyFactory::CppIncludeHierarchyFactory()
setId(Constants::INCLUDE_HIERARCHY_ID);
}
-Core::NavigationView CppIncludeHierarchyFactory::createWidget()
+NavigationView CppIncludeHierarchyFactory::createWidget()
{
- CppIncludeHierarchyStackedWidget *w = new CppIncludeHierarchyStackedWidget;
- static_cast<CppIncludeHierarchyWidget *>(w->currentWidget())->perform();
- Core::NavigationView navigationView;
- navigationView.widget = w;
+ auto hierarchyWidget = new CppIncludeHierarchyWidget;
+ hierarchyWidget->perform();
+
+ auto stack = new QStackedWidget;
+ stack->addWidget(hierarchyWidget);
+
+ NavigationView navigationView;
+ navigationView.widget = stack;
return navigationView;
}
diff --git a/src/plugins/cppeditor/cppincludehierarchy.h b/src/plugins/cppeditor/cppincludehierarchy.h
index b1cb25a1f7..45645a74c0 100644
--- a/src/plugins/cppeditor/cppincludehierarchy.h
+++ b/src/plugins/cppeditor/cppincludehierarchy.h
@@ -26,83 +26,52 @@
#pragma once
#include <coreplugin/inavigationwidgetfactory.h>
+#include <utils/treemodel.h>
-#include <QString>
-#include <QStackedWidget>
-#include <QWidget>
-
-QT_BEGIN_NAMESPACE
-class QStandardItemModel;
-class QStandardItem;
-class QModelIndex;
-class QLabel;
-QT_END_NAMESPACE
-
-namespace Core { class IEditor; }
-
-namespace TextEditor {
-class BaseTextEditor;
-class TextEditorLinkLabel;
-}
-
-namespace Utils {
-class AnnotatedItemDelegate;
-class FileName;
-}
+#include <QSet>
namespace CppEditor {
namespace Internal {
-class CppEditor;
-class CppEditorWidget;
-class CppInclude;
-class CppIncludeHierarchyModel;
-class CppIncludeHierarchyTreeView;
+class CppIncludeHierarchyItem;
-class CppIncludeHierarchyWidget : public QWidget
+class CppIncludeHierarchyModel : public Utils::TreeModel<CppIncludeHierarchyItem>
{
Q_OBJECT
-public:
- CppIncludeHierarchyWidget();
- virtual ~CppIncludeHierarchyWidget();
+ typedef Utils::TreeModel<CppIncludeHierarchyItem> base_type;
- void perform();
+public:
+ CppIncludeHierarchyModel();
-private:
- void onItemActivated(const QModelIndex &index);
- void editorsClosed(QList<Core::IEditor *> editors);
- void showNoIncludeHierarchyLabel();
- void showIncludeHierarchy();
+ Qt::DropActions supportedDragActions() const override;
+ QStringList mimeTypes() const override;
+ QMimeData *mimeData(const QModelIndexList &indexes) const override;
- CppEditorWidget *m_cppEditor;
- CppIncludeHierarchyTreeView *m_treeView;
- CppIncludeHierarchyModel *m_model;
- Utils::AnnotatedItemDelegate *m_delegate;
- TextEditor::TextEditorLinkLabel *m_inspectedFile;
- QLabel *m_includeHierarchyInfoLabel;
- TextEditor::BaseTextEditor *m_editor;
-};
+ void buildHierarchy(const QString &filePath);
+ QString editorFilePath() const { return m_editorFilePath; }
+ void setSearching(bool on);
+ QString toString() const;
-// @todo: Pretty much the same design as the OutlineWidgetStack. Maybe we can generalize the
-// outline factory so that it works for different widgets that support the same editor.
-class CppIncludeHierarchyStackedWidget : public QStackedWidget
-{
- Q_OBJECT
-public:
- CppIncludeHierarchyStackedWidget(QWidget *parent = 0);
- virtual ~CppIncludeHierarchyStackedWidget();
+#if WITH_TESTS
+ using base_type::canFetchMore;
+ using base_type::fetchMore;
+#endif
private:
- CppIncludeHierarchyWidget *m_typeHiearchyWidgetInstance;
+ friend class CppIncludeHierarchyItem;
+ QString m_editorFilePath;
+ QSet<QString> m_seen;
+ bool m_searching = false;
};
class CppIncludeHierarchyFactory : public Core::INavigationWidgetFactory
{
Q_OBJECT
+
public:
CppIncludeHierarchyFactory();
- Core::NavigationView createWidget();
+ Core::NavigationView createWidget() override;
};
} // namespace Internal
diff --git a/src/plugins/cppeditor/cppincludehierarchy_test.cpp b/src/plugins/cppeditor/cppincludehierarchy_test.cpp
index 8bb29f4123..95995e732a 100644
--- a/src/plugins/cppeditor/cppincludehierarchy_test.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchy_test.cpp
@@ -25,7 +25,7 @@
#include "cppeditorplugin.h"
#include "cppeditortestcase.h"
-#include "cppincludehierarchymodel.h"
+#include "cppincludehierarchy.h"
#include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppmodelmanager.h>
@@ -61,6 +61,8 @@ QString toString(CppIncludeHierarchyModel &model, const QModelIndex &index, int
QString toString(CppIncludeHierarchyModel &model)
{
+ model.fetchMore(model.index(0, 0));
+ model.fetchMore(model.index(1, 0));
return toString(model, model.index(0, 0))
+ toString(model, model.index(1, 0));
}
@@ -98,8 +100,8 @@ public:
closeEditorAtEndOfTestCase(editor);
// Test model
- CppIncludeHierarchyModel model(0);
- model.buildHierarchy(editor, fileName);
+ CppIncludeHierarchyModel model;
+ model.buildHierarchy(editor->document()->filePath().toString());
const QString actualHierarchy = toString(model);
QCOMPARE(actualHierarchy, expectedHierarchy);
}
diff --git a/src/plugins/cppeditor/cppincludehierarchyitem.cpp b/src/plugins/cppeditor/cppincludehierarchyitem.cpp
deleted file mode 100644
index 10f5fd01d6..0000000000
--- a/src/plugins/cppeditor/cppincludehierarchyitem.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
-** 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 "cppincludehierarchyitem.h"
-
-namespace CppEditor {
-namespace Internal {
-
-CppIncludeHierarchyItem::CppIncludeHierarchyItem(const QString &filePath,
- CppIncludeHierarchyItem *parent,
- bool isCyclic)
- : m_fileName(filePath.mid(filePath.lastIndexOf(QLatin1Char('/')) + 1))
- , m_filePath(filePath)
- , m_parentItem(parent)
- , m_isCyclic(isCyclic)
- , m_hasChildren(false)
- , m_line(0)
-{
-}
-
-CppIncludeHierarchyItem::~CppIncludeHierarchyItem()
-{
- removeChildren();
-}
-
-const QString &CppIncludeHierarchyItem::fileName() const
-{
- return m_fileName;
-}
-
-const QString &CppIncludeHierarchyItem::filePath() const
-{
- return m_filePath;
-}
-
-CppIncludeHierarchyItem *CppIncludeHierarchyItem::parent() const
-{
- return m_parentItem;
-}
-
-bool CppIncludeHierarchyItem::isCyclic() const
-{
- return m_isCyclic;
-}
-
-void CppIncludeHierarchyItem::appendChild(CppIncludeHierarchyItem *childItem)
-{
- m_childItems.append(childItem);
-}
-
-CppIncludeHierarchyItem *CppIncludeHierarchyItem::child(int row)
-{
- return m_childItems.at(row);
-}
-
-int CppIncludeHierarchyItem::row() const
-{
- if (m_parentItem)
- return m_parentItem->m_childItems.indexOf(const_cast<CppIncludeHierarchyItem*>(this));
-
- return 0;
-}
-
-int CppIncludeHierarchyItem::childCount() const
-{
- return m_childItems.size();
-}
-
-void CppIncludeHierarchyItem::removeChildren()
-{
- qDeleteAll(m_childItems);
- m_childItems.clear();
-}
-
-bool CppIncludeHierarchyItem::needChildrenPopulate() const
-{
- return m_hasChildren && m_childItems.isEmpty();
-}
-
-bool CppIncludeHierarchyItem::hasChildren() const
-{
- return m_hasChildren;
-}
-
-void CppIncludeHierarchyItem::setHasChildren(bool hasChildren)
-{
- m_hasChildren = hasChildren;
-}
-
-int CppIncludeHierarchyItem::line() const
-{
- return m_line;
-}
-
-void CppIncludeHierarchyItem::setLine(int line)
-{
- m_line = line;
-}
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppincludehierarchyitem.h b/src/plugins/cppeditor/cppincludehierarchyitem.h
deleted file mode 100644
index f7cd897dab..0000000000
--- a/src/plugins/cppeditor/cppincludehierarchyitem.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
-** 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.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QList>
-#include <QString>
-
-namespace CppEditor {
-namespace Internal {
-
-class CppIncludeHierarchyItem
-{
-public:
- CppIncludeHierarchyItem(const QString &filePath, CppIncludeHierarchyItem *parent = 0,
- bool isCyclic = false);
- virtual ~CppIncludeHierarchyItem();
-
- CppIncludeHierarchyItem *parent() const;
- CppIncludeHierarchyItem *child(int row);
- int childCount() const;
- void appendChild(CppIncludeHierarchyItem *childItem);
- void removeChildren();
- bool needChildrenPopulate() const;
- int row() const;
- bool isCyclic() const;
-
- const QString &fileName() const;
- const QString &filePath() const;
- bool hasChildren() const;
- void setHasChildren(bool hasChildren);
- int line() const;
- void setLine(int line);
-
-private:
- QString m_fileName;
- QString m_filePath;
- QList<CppIncludeHierarchyItem *> m_childItems;
- CppIncludeHierarchyItem *m_parentItem;
- bool m_isCyclic;
- bool m_hasChildren;
- int m_line;
-};
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.cpp b/src/plugins/cppeditor/cppincludehierarchymodel.cpp
deleted file mode 100644
index 5ad964affb..0000000000
--- a/src/plugins/cppeditor/cppincludehierarchymodel.cpp
+++ /dev/null
@@ -1,371 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
-** 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 "cppincludehierarchymodel.h"
-
-#include "cppincludehierarchyitem.h"
-
-#include <coreplugin/fileiconprovider.h>
-#include <cpptools/baseeditordocumentprocessor.h>
-#include <cpptools/cppmodelmanager.h>
-#include <cpptools/cpptoolsbridge.h>
-#include <cpptools/editordocumenthandle.h>
-#include <texteditor/texteditor.h>
-
-#include <cplusplus/CppDocument.h>
-#include <utils/dropsupport.h>
-#include <utils/qtcassert.h>
-
-#include <QSet>
-
-using namespace CPlusPlus;
-using namespace CppTools;
-
-namespace {
-
-Snapshot globalSnapshot()
-{
- return CppModelManager::instance()->snapshot();
-}
-
-} // anonymous namespace
-
-namespace CppEditor {
-namespace Internal {
-
-CppIncludeHierarchyModel::CppIncludeHierarchyModel(QObject *parent)
- : QAbstractItemModel(parent)
- , m_rootItem(new CppIncludeHierarchyItem(QString()))
- , m_includesItem(new CppIncludeHierarchyItem(tr("Includes"), m_rootItem))
- , m_includedByItem(new CppIncludeHierarchyItem(tr("Included by"), m_rootItem))
- , m_editor(0)
-{
- m_rootItem->appendChild(m_includesItem);
- m_rootItem->appendChild(m_includedByItem);
-}
-
-CppIncludeHierarchyModel::~CppIncludeHierarchyModel()
-{
- delete m_rootItem;
-}
-
-QModelIndex CppIncludeHierarchyModel::index(int row, int column, const QModelIndex &parent) const
-{
- if (!hasIndex(row, column, parent))
- return QModelIndex();
-
- CppIncludeHierarchyItem *parentItem = parent.isValid()
- ? static_cast<CppIncludeHierarchyItem*>(parent.internalPointer())
- : m_rootItem;
-
- CppIncludeHierarchyItem *childItem = parentItem->child(row);
- return childItem ? createIndex(row, column, childItem) : QModelIndex();
-}
-
-QModelIndex CppIncludeHierarchyModel::parent(const QModelIndex &index) const
-{
- if (!index.isValid())
- return QModelIndex();
-
- CppIncludeHierarchyItem *childItem
- = static_cast<CppIncludeHierarchyItem*>(index.internalPointer());
- CppIncludeHierarchyItem *parentItem = childItem->parent();
-
- if (parentItem == m_rootItem)
- return QModelIndex();
-
- return createIndex(parentItem->row(), 0, parentItem);
-}
-
-int CppIncludeHierarchyModel::rowCount(const QModelIndex &parent) const
-{
- CppIncludeHierarchyItem *parentItem;
-
- if (!parent.isValid())
- parentItem = m_rootItem;
- else
- parentItem = static_cast<CppIncludeHierarchyItem*>(parent.internalPointer());
-
- return parentItem->childCount();
-}
-
-int CppIncludeHierarchyModel::columnCount(const QModelIndex &) const
-{
- return 1;
-}
-
-QVariant CppIncludeHierarchyModel::data(const QModelIndex &index, int role) const
-{
- if (!index.isValid())
- return QVariant();
-
- CppIncludeHierarchyItem *item = static_cast<CppIncludeHierarchyItem*>(index.internalPointer());
-
- if (!item)
- return QVariant();
-
- if (role == Qt::DisplayRole) {
- if ((item == m_includesItem && m_includesItem->childCount() == 0)
- || (item == m_includedByItem && m_includedByItem->childCount() == 0)) {
- return QString(item->fileName() + QLatin1Char(' ') + tr("(none)"));
- }
-
- if (item->isCyclic())
- return QString(item->fileName() + QLatin1Char(' ') + tr("(cyclic)"));
-
- return item->fileName();
- }
-
- if (item == m_rootItem || item == m_includesItem || item == m_includedByItem)
- return QVariant();
-
- switch (role) {
- case Qt::ToolTipRole:
- return item->filePath();
- case Qt::DecorationRole:
- return Core::FileIconProvider::icon(QFileInfo(item->filePath()));
- case LinkRole: {
- QVariant itemLink;
- TextEditor::TextEditorWidget::Link link(item->filePath(), item->line());
- itemLink.setValue(link);
- return itemLink;
- }
- }
-
- return QVariant();
-}
-
-void CppIncludeHierarchyModel::fetchMore(const QModelIndex &parent)
-{
- if (!parent.isValid())
- return;
-
- CppIncludeHierarchyItem *parentItem
- = static_cast<CppIncludeHierarchyItem*>(parent.internalPointer());
- Q_ASSERT(parentItem);
-
- if (parentItem == m_rootItem || parentItem == m_includesItem || parentItem == m_includedByItem)
- return;
-
- if (parentItem->needChildrenPopulate()) {
- const QString editorFilePath = m_editor->document()->filePath().toString();
- QSet<QString> cyclic;
- cyclic << editorFilePath;
- CppIncludeHierarchyItem *item = parentItem->parent();
- while (!(item == m_includesItem || item == m_includedByItem)) {
- cyclic << item->filePath();
- item = item->parent();
- }
-
- if (item == m_includesItem) {
- auto *processor = CppToolsBridge::baseEditorDocumentProcessor(editorFilePath);
- QTC_ASSERT(processor, return);
- const Snapshot editorDocumentSnapshot = processor->snapshot();
- buildHierarchyIncludes_helper(parentItem->filePath(), parentItem,
- editorDocumentSnapshot, &cyclic);
- } else {
- buildHierarchyIncludedBy_helper(parentItem->filePath(), parentItem,
- globalSnapshot(), &cyclic);
- }
- }
-
-}
-
-bool CppIncludeHierarchyModel::canFetchMore(const QModelIndex &parent) const
-{
- if (!parent.isValid())
- return false;
-
- CppIncludeHierarchyItem *parentItem
- = static_cast<CppIncludeHierarchyItem*>(parent.internalPointer());
- Q_ASSERT(parentItem);
-
- if (parentItem == m_includesItem || parentItem == m_includedByItem)
- return false;
-
- if (parentItem->needChildrenPopulate())
- return true;
-
- return false;
-}
-
-void CppIncludeHierarchyModel::clear()
-{
- beginResetModel();
- m_includesItem->removeChildren();
- m_includedByItem->removeChildren();
- endResetModel();
-}
-
-void CppIncludeHierarchyModel::buildHierarchy(TextEditor::BaseTextEditor *editor,
- const QString &filePath)
-{
- m_editor = editor;
- beginResetModel();
- buildHierarchyIncludes(filePath);
- buildHierarchyIncludedBy(filePath);
- endResetModel();
-}
-
-bool CppIncludeHierarchyModel::hasChildren(const QModelIndex &parent) const
-{
- if (!parent.isValid())
- return true;
- CppIncludeHierarchyItem *parentItem
- = static_cast<CppIncludeHierarchyItem*>(parent.internalPointer());
-
- Q_ASSERT(parentItem);
- return parentItem->hasChildren();
-}
-
-Qt::ItemFlags CppIncludeHierarchyModel::flags(const QModelIndex &index) const
-{
- const TextEditor::TextEditorWidget::Link link
- = index.data(LinkRole).value<TextEditor::TextEditorWidget::Link>();
- if (link.hasValidTarget())
- return Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
- return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
-}
-
-Qt::DropActions CppIncludeHierarchyModel::supportedDragActions() const
-{
- return Qt::MoveAction;
-}
-
-QStringList CppIncludeHierarchyModel::mimeTypes() const
-{
- return Utils::DropSupport::mimeTypesForFilePaths();
-}
-
-QMimeData *CppIncludeHierarchyModel::mimeData(const QModelIndexList &indexes) const
-{
- auto data = new Utils::DropMimeData;
- foreach (const QModelIndex &index, indexes) {
- const TextEditor::TextEditorWidget::Link link
- = index.data(LinkRole).value<TextEditor::TextEditorWidget::Link>();
- if (link.hasValidTarget())
- data->addFile(link.targetFileName, link.targetLine, link.targetColumn);
- }
- return data;
-}
-
-bool CppIncludeHierarchyModel::isEmpty() const
-{
- return !m_includesItem->hasChildren() && !m_includedByItem->hasChildren();
-}
-
-void CppIncludeHierarchyModel::buildHierarchyIncludes(const QString &currentFilePath)
-{
- if (!m_editor)
- return;
-
- const QString editorFilePath = m_editor->document()->filePath().toString();
- auto *documentProcessor = CppToolsBridge::baseEditorDocumentProcessor(editorFilePath);
- QTC_ASSERT(documentProcessor, return);
- const Snapshot editorDocumentSnapshot = documentProcessor->snapshot();
- QSet<QString> cyclic;
- buildHierarchyIncludes_helper(currentFilePath, m_includesItem, editorDocumentSnapshot, &cyclic);
-}
-
-void CppIncludeHierarchyModel::buildHierarchyIncludes_helper(const QString &filePath,
- CppIncludeHierarchyItem *parent,
- Snapshot snapshot,
- QSet<QString> *cyclic,
- bool recursive)
-{
- Document::Ptr doc = snapshot.document(filePath);
- if (!doc)
- return;
-
- parent->setHasChildren(doc->resolvedIncludes().size() > 0);
- if (!recursive)
- return;
-
- cyclic->insert(filePath);
-
- foreach (const Document::Include &includeFile, doc->resolvedIncludes()) {
- const QString includedFilePath = includeFile.resolvedFileName();
- CppIncludeHierarchyItem *item = 0;
-
- if (cyclic->contains(includedFilePath)) {
- item = new CppIncludeHierarchyItem(includedFilePath, parent, true);
- parent->appendChild(item);
- continue;
- }
- item = new CppIncludeHierarchyItem(includedFilePath, parent);
- parent->appendChild(item);
- buildHierarchyIncludes_helper(includedFilePath, item, snapshot, cyclic, false);
-
- }
- cyclic->remove(filePath);
-}
-
-void CppIncludeHierarchyModel::buildHierarchyIncludedBy(const QString &currentFilePath)
-{
- QSet<QString> cyclic;
- buildHierarchyIncludedBy_helper(currentFilePath, m_includedByItem, globalSnapshot(), &cyclic);
-}
-
-void CppIncludeHierarchyModel::buildHierarchyIncludedBy_helper(const QString &filePath,
- CppIncludeHierarchyItem *parent,
- Snapshot snapshot,
- QSet<QString> *cyclic,
- bool recursive)
-{
- cyclic->insert(filePath);
- Snapshot::const_iterator citEnd = snapshot.end();
- for (Snapshot::const_iterator cit = snapshot.begin(); cit != citEnd; ++cit) {
- const QString filePathFromSnapshot = cit.key().toString();
- Document::Ptr doc = cit.value();
- foreach (const Document::Include &includeFile, doc->resolvedIncludes()) {
- const QString includedFilePath = includeFile.resolvedFileName();
-
- if (includedFilePath == filePath) {
- parent->setHasChildren(true);
- if (!recursive) {
- cyclic->remove(filePath);
- return;
- }
-
- const bool isCyclic = cyclic->contains(filePathFromSnapshot);
- CppIncludeHierarchyItem *item = new CppIncludeHierarchyItem(filePathFromSnapshot,
- parent,
- isCyclic);
- item->setLine(includeFile.line());
- parent->appendChild(item);
-
- if (isCyclic)
- continue;
-
- buildHierarchyIncludedBy_helper(filePathFromSnapshot, item, snapshot, cyclic,
- false);
- }
- }
- }
- cyclic->remove(filePath);
-}
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.h b/src/plugins/cppeditor/cppincludehierarchymodel.h
deleted file mode 100644
index 2bc80bcb12..0000000000
--- a/src/plugins/cppeditor/cppincludehierarchymodel.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
-** 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.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QAbstractItemModel>
-
-namespace {
-
-enum ItemRole {
- AnnotationRole = Qt::UserRole + 1,
- LinkRole
-};
-
-} // Anonymous
-
-namespace CPlusPlus { class Snapshot; }
-namespace TextEditor { class BaseTextEditor; }
-
-namespace CppEditor {
-namespace Internal {
-
-class CppEditor;
-class CppIncludeHierarchyItem;
-
-class CppIncludeHierarchyModel : public QAbstractItemModel
-{
- Q_OBJECT
-public:
- explicit CppIncludeHierarchyModel(QObject *parent);
- ~CppIncludeHierarchyModel();
-
- QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
- QModelIndex parent(const QModelIndex &index) const;
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- int columnCount(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- void fetchMore(const QModelIndex &parent);
- bool canFetchMore(const QModelIndex &parent) const;
- bool hasChildren(const QModelIndex &parent) const;
- Qt::ItemFlags flags(const QModelIndex &index) const;
-
- Qt::DropActions supportedDragActions() const;
- QStringList mimeTypes() const;
- QMimeData *mimeData(const QModelIndexList &indexes) const;
-
- void clear();
- void buildHierarchy(TextEditor::BaseTextEditor *editor, const QString &filePath);
- bool isEmpty() const;
-
-private:
- void buildHierarchyIncludes(const QString &currentFilePath);
- void buildHierarchyIncludes_helper(const QString &filePath, CppIncludeHierarchyItem *parent,
- CPlusPlus::Snapshot snapshot,
- QSet<QString> *cyclic, bool recursive = true);
- void buildHierarchyIncludedBy(const QString &currentFilePath);
- void buildHierarchyIncludedBy_helper(const QString &filePath, CppIncludeHierarchyItem *parent,
- CPlusPlus::Snapshot snapshot, QSet<QString> *cyclic,
- bool recursive = true);
-
- CppIncludeHierarchyItem *m_rootItem;
- CppIncludeHierarchyItem *m_includesItem;
- CppIncludeHierarchyItem *m_includedByItem;
- TextEditor::BaseTextEditor *m_editor;
-};
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppincludehierarchytreeview.cpp b/src/plugins/cppeditor/cppincludehierarchytreeview.cpp
deleted file mode 100644
index c363eb229c..0000000000
--- a/src/plugins/cppeditor/cppincludehierarchytreeview.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
-** 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 "cppincludehierarchytreeview.h"
-
-#include <QKeyEvent>
-
-namespace CppEditor {
-namespace Internal {
-
-CppIncludeHierarchyTreeView::CppIncludeHierarchyTreeView(QWidget *parent/* = 0*/)
- : NavigationTreeView(parent)
-{
- setDragEnabled(true);
- setDragDropMode(QAbstractItemView::DragOnly);
-}
-
-void CppIncludeHierarchyTreeView::keyPressEvent(QKeyEvent *event)
-{
- switch (event->key()) {
- case Qt::Key_Asterisk:
- QAbstractItemView::keyPressEvent(event);
- return;
- }
-
- NavigationTreeView::keyPressEvent(event);
-}
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppincludehierarchytreeview.h b/src/plugins/cppeditor/cppincludehierarchytreeview.h
deleted file mode 100644
index 083b6f1614..0000000000
--- a/src/plugins/cppeditor/cppincludehierarchytreeview.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
-** 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.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/navigationtreeview.h>
-
-namespace CppEditor {
-namespace Internal {
-
-class CppIncludeHierarchyTreeView : public Utils::NavigationTreeView
-{
-public:
- CppIncludeHierarchyTreeView(QWidget *parent = 0);
-protected:
- void keyPressEvent(QKeyEvent *event);
-};
-
-} // namespace Internal
-} // namespace CppEditor
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index e3c7e7a5a2..bd79057f11 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -1516,12 +1516,15 @@ void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie)
str << cookie.address << ' ' << cookie.length;
cmd.args = args;
cmd.callback = [this, cookie](const DebuggerResponse &response) {
- if (response.resultClass == ResultDone && cookie.agent) {
+ if (!cookie.agent)
+ return;
+ if (response.resultClass == ResultDone) {
const QByteArray data = QByteArray::fromHex(response.data.data().toUtf8());
if (unsigned(data.size()) == cookie.length)
cookie.agent->addData(cookie.address, data);
} else {
showMessage(response.data["msg"].data(), LogWarning);
+ cookie.agent->addData(cookie.address, QByteArray(int(cookie.length), char()));
}
};
runCommand(cmd);
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp
index 0a0aa8ce2c..34f68fe6f1 100644
--- a/src/plugins/debugger/debuggerkitconfigwidget.cpp
+++ b/src/plugins/debugger/debuggerkitconfigwidget.cpp
@@ -142,16 +142,6 @@ void DebuggerKitConfigWidget::currentDebuggerChanged(int)
m_kit->setValue(DebuggerKitInformation::id(), id);
}
-int DebuggerKitConfigWidget::indexOf(const QVariant &id)
-{
- QTC_ASSERT(id.isValid(), return -1);
- for (int i = 0; i < m_comboBox->count(); ++i) {
- if (id == m_comboBox->itemData(i))
- return i;
- }
- return -1;
-}
-
QVariant DebuggerKitConfigWidget::currentId() const
{
return m_comboBox->itemData(m_comboBox->currentIndex());
diff --git a/src/plugins/debugger/debuggerkitconfigwidget.h b/src/plugins/debugger/debuggerkitconfigwidget.h
index ff89d4e70d..9fbe1f124d 100644
--- a/src/plugins/debugger/debuggerkitconfigwidget.h
+++ b/src/plugins/debugger/debuggerkitconfigwidget.h
@@ -68,7 +68,6 @@ private:
void manageDebuggers();
void currentDebuggerChanged(int idx);
- int indexOf(const QVariant &id);
QVariant currentId() const;
void updateComboBox(const QVariant &id);
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 5f118ed6cd..abf5498be0 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -1650,8 +1650,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
cmd->setAttribute(Command::CA_UpdateText);
debugMenu->addAction(cmd);
- cmd = ActionManager::registerAction(m_stepOutAction,
- Constants::STEPOUT, cppDebuggercontext);
+ cmd = ActionManager::registerAction(m_stepOutAction, Constants::STEPOUT);
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Shift+T") : tr("Shift+F11")));
cmd->setAttribute(Command::CA_Hide);
debugMenu->addAction(cmd);
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index a0ead85150..8c18d420fa 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -441,17 +441,19 @@ static DebuggerRunControl *doCreate(DebuggerRunParameters rp, RunConfiguration *
if (rp.languages & QmlLanguage) {
if (rp.device && rp.device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
- QTcpServer server;
- const bool canListen = server.listen(QHostAddress::LocalHost)
- || server.listen(QHostAddress::LocalHostIPv6);
- if (!canListen) {
- errors->append(DebuggerPlugin::tr("Not enough free ports for QML debugging.") + ' ');
- return 0;
+ if (rp.qmlServer.host.isEmpty() || !rp.qmlServer.port.isValid()) {
+ QTcpServer server;
+ const bool canListen = server.listen(QHostAddress::LocalHost)
+ || server.listen(QHostAddress::LocalHostIPv6);
+ if (!canListen) {
+ errors->append(DebuggerPlugin::tr("Not enough free ports for QML debugging.") + ' ');
+ return 0;
+ }
+ TcpServerConnection conn;
+ conn.host = server.serverAddress().toString();
+ conn.port = Utils::Port(server.serverPort());
+ rp.qmlServer = conn;
}
- TcpServerConnection conn;
- conn.host = server.serverAddress().toString();
- conn.port = Utils::Port(server.serverPort());
- rp.qmlServer = conn;
// Makes sure that all bindings go through the JavaScript engine, so that
// breakpoints are actually hit!
diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
index 11319c47c9..313cecefd7 100644
--- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
+++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
@@ -49,7 +49,8 @@ using namespace Utils;
static const char* qtBuildPaths[] = {
"Q:/qt5_workdir/w/s",
"C:/work/build/qt5_workdir/w/s",
- "c:/users/qt/work/qt"
+ "c:/users/qt/work/qt",
+ "c:/Users/qt/work/install"
};
#elif defined(Q_OS_MAC)
static const char* qtBuildPaths[] = {};
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index e0969d0221..eab055ba4f 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -91,6 +91,10 @@ void PdbEngine::postDirectCommand(const QString &command)
void PdbEngine::runCommand(const DebuggerCommand &cmd)
{
+ if (state() == EngineSetupRequested) { // cmd has been triggered too early
+ showMessage("IGNORED COMMAND: " + cmd.function);
+ return;
+ }
QTC_ASSERT(m_proc.state() == QProcess::Running, notifyEngineIll());
QString command = "qdebug('" + cmd.function + "'," + cmd.argsToPython() + ")";
showMessage(command, LogInput);
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 0d4ec99880..107d3708ba 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -1084,7 +1084,7 @@ void QmlEngine::quitDebugger()
d->noDebugOutputTimer.stop();
d->automaticConnect = false;
d->retryOnConnectFail = false;
- DebuggerEngine::quitDebugger();
+ shutdownInferior();
}
void QmlEngine::disconnected()
@@ -2150,7 +2150,7 @@ void QmlEnginePrivate::handleFrame(const QVariantMap &response)
StackHandler *stackHandler = engine->stackHandler();
WatchHandler * watchHandler = engine->watchHandler();
- watchHandler->notifyUpdateStarted();
+ watchHandler->notifyUpdateStarted({"local"});
const int frameIndex = stackHandler->currentIndex();
if (frameIndex < 0)
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 8143dc8767..3878cb337b 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -2042,6 +2042,13 @@ void WatchHandler::notifyUpdateFinished()
foreach (auto item, toRemove)
m_model->destroyItem(item);
+ m_model->forAllItems([this](WatchItem *item) {
+ if (item->wantsChildren && isExpandedIName(item->iname)) {
+ m_model->m_engine->showMessage(QString("ADJUSTING CHILD EXPECTATION FOR " + item->iname));
+ item->wantsChildren = false;
+ }
+ });
+
m_model->m_contentsValid = true;
updateWatchersWindow();
m_model->reexpandItems();
diff --git a/src/plugins/help/localhelpmanager.cpp b/src/plugins/help/localhelpmanager.cpp
index 929286687d..dee3ef7332 100644
--- a/src/plugins/help/localhelpmanager.cpp
+++ b/src/plugins/help/localhelpmanager.cpp
@@ -81,7 +81,7 @@ static QString defaultFallbackFontFamily()
if (Utils::HostOsInfo::isMacHost())
return QString("Helvetica");
if (Utils::HostOsInfo::isAnyUnixHost())
- return QString("sans-serif");
+ return QString("Sans Serif");
return QString("Arial");
}
diff --git a/src/plugins/nim/project/nimbuildconfiguration.cpp b/src/plugins/nim/project/nimbuildconfiguration.cpp
index 6837063fbf..d382ec5adb 100644
--- a/src/plugins/nim/project/nimbuildconfiguration.cpp
+++ b/src/plugins/nim/project/nimbuildconfiguration.cpp
@@ -106,14 +106,12 @@ bool NimBuildConfiguration::canRestore(const QVariantMap &map)
bool NimBuildConfiguration::hasNimCompilerBuildStep() const
{
BuildStepList *steps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
- QTC_ASSERT(steps, return false);
- return steps->contains(Constants::C_NIMCOMPILERBUILDSTEP_ID);
+ return steps ? steps->contains(Constants::C_NIMCOMPILERBUILDSTEP_ID) : false;
}
bool NimBuildConfiguration::hasNimCompilerCleanStep() const
{
BuildStepList *steps = stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN);
- QTC_ASSERT(steps, return false);
return steps ? steps->contains(Constants::C_NIMCOMPILERCLEANSTEP_ID) : false;
}
diff --git a/src/plugins/nim/project/nimrunconfiguration.cpp b/src/plugins/nim/project/nimrunconfiguration.cpp
index 3ac4724e0b..7b9e43ab47 100644
--- a/src/plugins/nim/project/nimrunconfiguration.cpp
+++ b/src/plugins/nim/project/nimrunconfiguration.cpp
@@ -80,6 +80,7 @@ Runnable NimRunConfiguration::runnable() const
result.executable = m_executable;
result.commandLineArguments = m_argumentAspect->arguments();
result.workingDirectory = m_workingDirectoryAspect->workingDirectory().toString();
+ result.environment = m_localEnvironmentAspect->environment();
return result;
}
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index 58869edf60..1f22cf65ed 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -110,7 +110,6 @@ private:
void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
- mutable QImage selectionGradient;
ListWidget *m_listWidget;
};
@@ -128,9 +127,6 @@ void TargetSelectorDelegate::paint(QPainter *painter,
painter->save();
painter->setClipping(false);
- if (selectionGradient.isNull())
- selectionGradient.load(QLatin1String(":/projectexplorer/images/targetpanel_gradient.png"));
-
if (option.state & QStyle::State_Selected) {
const QColor color = (option.state & QStyle::State_HasFocus) ?
option.palette.highlight().color() :
@@ -139,6 +135,7 @@ void TargetSelectorDelegate::paint(QPainter *painter,
painter->fillRect(option.rect, color);
} else {
painter->fillRect(option.rect, color.darker(140));
+ static const QImage selectionGradient(":/projectexplorer/images/targetpanel_gradient.png");
StyleHelper::drawCornerImage(selectionGradient, painter, option.rect.adjusted(0, 0, 0, -1), 5, 5, 5, 5);
const QRectF borderRect = QRectF(option.rect).adjusted(0.5, 0.5, -0.5, -0.5);
painter->setPen(QColor(255, 255, 255, 60));
@@ -1596,7 +1593,7 @@ void MiniProjectTargetSelector::paintEvent(QPaintEvent *)
if (creatorTheme()->flag(Theme::DrawTargetSelectorBottom)) {
// draw thicker border on the bottom
QRect bottomRect(0, rect().height() - 8, rect().width(), 8);
- static QImage image(QLatin1String(":/projectexplorer/images/targetpanel_bottom.png"));
+ static const QImage image(":/projectexplorer/images/targetpanel_bottom.png");
StyleHelper::drawCornerImage(image, &painter, bottomRect, 1, 1, 1, 1);
}
}
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
index eba1144f98..c2266a5086 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
@@ -1229,7 +1229,7 @@ QPair<ProFile *, QStringList> QmakePriFileNode::readProFile(const QString &file)
QMakeVfs vfs;
QtSupport::ProMessageHandler handler;
QMakeParser parser(0, &vfs, &handler);
- includeFile = parser.parsedProBlock(contents, file, 1);
+ includeFile = parser.parsedProBlock(QStringRef(&contents), file, 1);
}
return qMakePair(includeFile, lines);
}
@@ -1264,7 +1264,8 @@ bool QmakePriFileNode::renameFile(const QString &oldName,
// We need to re-parse here: The file has changed.
QMakeParser parser(0, 0, 0);
- includeFile = parser.parsedProBlock(lines.join(QLatin1Char('\n')),
+ 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.
diff --git a/src/plugins/qmldesigner/components/componentcore/theming.cpp b/src/plugins/qmldesigner/components/componentcore/theming.cpp
index c2ba9b37d9..d1429ff45b 100644
--- a/src/plugins/qmldesigner/components/componentcore/theming.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/theming.cpp
@@ -33,13 +33,6 @@
namespace QmlDesigner {
-QColor midtone(const QColor &a, const QColor &b)
-{
- QColor alphaB = b;
- alphaB.setAlpha(128);
- return Utils::StyleHelper::alphaBlendedColors(a ,alphaB);
-}
-
void Theming::insertTheme(QQmlPropertyMap *map)
{
const QVariantHash creatorTheme = Utils::creatorTheme()->values();
@@ -47,6 +40,7 @@ void Theming::insertTheme(QQmlPropertyMap *map)
map->insert(it.key(), it.value());
/* Define QmlDesigner colors and remove alpha channels */
+ const QColor backgroundColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_BackgroundColor);
const QColor panelStatusBarBackgroundColor = Utils::creatorTheme()->color(Utils::Theme::PanelStatusBarBackgroundColor);
const QColor fancyToolButtonSelectedColor = Utils::creatorTheme()->color(Utils::Theme::FancyToolButtonSelectedColor);
const QColor darkerBackground = Utils::StyleHelper::alphaBlendedColors(panelStatusBarBackgroundColor, fancyToolButtonSelectedColor);
@@ -65,7 +59,7 @@ void Theming::insertTheme(QQmlPropertyMap *map)
}
map->insert("QmlDesignerBackgroundColorDarker", darkerBackground);
- map->insert("QmlDesignerBackgroundColorDarkAlternate", midtone(panelStatusBarBackgroundColor, buttonColor));
+ map->insert("QmlDesignerBackgroundColorDarkAlternate", backgroundColor);
map->insert("QmlDesignerTabLight", tabLight);
map->insert("QmlDesignerTabDark", tabDark);
map->insert("QmlDesignerButtonColor", buttonColor);
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index 4229d69776..696813a8a6 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -320,13 +320,13 @@ void DesignModeWidget::setup()
connect(m_warningWidget.data(), &DocumentWarningWidget::gotoCodeClicked, [=]
(const QString &filePath, int codeLine, int codeColumn) {
Q_UNUSED(filePath);
+
+ QTC_ASSERT(textEditor(), return;);
QTC_ASSERT(textEditor()->textDocument()->filePath().toString() == filePath,
- qDebug() << Q_FUNC_INFO << textEditor()->textDocument()->filePath().toString() <<
- filePath; );
- textEditor()->gotoLine(codeLine, codeColumn);
- Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
- }
- );
+ qDebug() << Q_FUNC_INFO << textEditor()->textDocument()->filePath().toString() << filePath; );
+ textEditor()->gotoLine(codeLine, codeColumn);
+ Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
+ });
QList<Core::SideBarItem*> sideBarItems;
QList<Core::SideBarItem*> leftSideBarItems;
diff --git a/src/plugins/resourceeditor/resourceeditorconstants.h b/src/plugins/resourceeditor/resourceeditorconstants.h
index b0f9b3ebf5..ae3fb962e1 100644
--- a/src/plugins/resourceeditor/resourceeditorconstants.h
+++ b/src/plugins/resourceeditor/resourceeditorconstants.h
@@ -39,7 +39,7 @@ const char C_RESOURCE_MIMETYPE[] = "application/vnd.qt.xml.resource";
const char C_ADD_PREFIX[] = "ResourceEditor.AddPrefix";
const char C_REMOVE_PREFIX[] = "ResourceEditor.RemovePrefix";
const char C_RENAME_PREFIX[] = "ResourceEditor.RenamePrefix";
-const char C_REMOVE_NON_EXISTING[] = "RessourceEditor.RemoveNonExistign";
+const char C_REMOVE_NON_EXISTING[] = "ResourceEditor.RemoveNonExisting";
const char C_REMOVE_FILE[] = "ResourceEditor.RemoveFile";
const char C_RENAME_FILE[] = "ResourceEditor.RenameFile";
diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp
index 1a22a3c50b..795b8b4564 100644
--- a/src/shared/proparser/proitems.cpp
+++ b/src/shared/proparser/proitems.cpp
@@ -362,6 +362,11 @@ static QString ProStringList_join(const ProStringList &this_, const QChar *sep,
return res;
}
+QString ProStringList::join(const ProString &sep) const
+{
+ return ProStringList_join(*this, sep.constData(), sep.size());
+}
+
QString ProStringList::join(const QString &sep) const
{
return ProStringList_join(*this, sep.constData(), sep.size());
@@ -388,7 +393,7 @@ void ProStringList::removeAll(const char *str)
void ProStringList::removeEach(const ProStringList &value)
{
- foreach (const ProString &str, value)
+ for (const ProString &str : value)
if (!str.isEmpty())
removeAll(str);
}
@@ -421,7 +426,7 @@ void ProStringList::removeDuplicates()
void ProStringList::insertUnique(const ProStringList &value)
{
- foreach (const ProString &str, value)
+ for (const ProString &str : value)
if (!str.isEmpty() && !contains(str))
append(str);
}
@@ -429,7 +434,7 @@ void ProStringList::insertUnique(const ProStringList &value)
ProStringList::ProStringList(const QStringList &list)
{
reserve(list.size());
- foreach (const QString &str, list)
+ for (const QString &str : list)
*this << ProString(str);
}
@@ -437,8 +442,8 @@ QStringList ProStringList::toQStringList() const
{
QStringList ret;
ret.reserve(size());
- for (int i = 0; i < size(); i++) // foreach causes MSVC2010 ICE
- ret << at(i).toQString();
+ for (const auto &e : *this)
+ ret.append(e.toQString());
return ret;
}
diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h
index d6bc4fe1cb..31e662bcf0 100644
--- a/src/shared/proparser/proitems.h
+++ b/src/shared/proparser/proitems.h
@@ -96,6 +96,7 @@ public:
bool operator!=(const QString &other) const { return !(*this == other); }
bool operator!=(QLatin1String other) const { return !(*this == other); }
bool operator!=(const char *other) const { return !(*this == other); }
+ bool operator<(const ProString &other) const { return toQStringRef() < other.toQStringRef(); }
bool isNull() const { return m_string.isNull(); }
bool isEmpty() const { return !m_length; }
int length() const { return m_length; }
@@ -126,8 +127,9 @@ public:
bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s, 0, cs) >= 0; }
bool contains(const char *s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(QLatin1String(s), 0, cs) >= 0; }
bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(c, 0, cs) >= 0; }
- int toInt(bool *ok = 0, int base = 10) const { return toQString().toInt(ok, base); } // XXX optimize
- short toShort(bool *ok = 0, int base = 10) const { return toQString().toShort(ok, base); } // XXX optimize
+ int toLongLong(bool *ok = 0, int base = 10) const { return toQStringRef().toLongLong(ok, base); }
+ int toInt(bool *ok = 0, int base = 10) const { return toQStringRef().toInt(ok, base); }
+ short toShort(bool *ok = 0, int base = 10) const { return toQStringRef().toShort(ok, base); }
uint hash() const { return m_hash; }
static uint hash(const QChar *p, int n);
@@ -228,6 +230,7 @@ public:
int length() const { return size(); }
+ QString join(const ProString &sep) const;
QString join(const QString &sep) const;
QString join(QChar sep) const;
@@ -360,6 +363,8 @@ class ProFunctionDef {
public:
ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); }
ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); }
+ ProFunctionDef(ProFunctionDef &&other) Q_DECL_NOTHROW
+ : m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; }
~ProFunctionDef() { m_pro->deref(); }
ProFunctionDef &operator=(const ProFunctionDef &o)
{
@@ -371,6 +376,18 @@ public:
}
return *this;
}
+ ProFunctionDef &operator=(ProFunctionDef &&other) Q_DECL_NOTHROW
+ {
+ ProFunctionDef moved(std::move(other));
+ swap(moved);
+ return *this;
+ }
+ void swap(ProFunctionDef &other) Q_DECL_NOTHROW
+ {
+ qSwap(m_pro, other.m_pro);
+ qSwap(m_offset, other.m_offset);
+ }
+
ProFile *pro() const { return m_pro; }
const ushort *tokPtr() const { return m_pro->tokPtr() + m_offset; }
private:
diff --git a/src/shared/proparser/prowriter.cpp b/src/shared/proparser/prowriter.cpp
index 700e134c1b..d49c3aa864 100644
--- a/src/shared/proparser/prowriter.cpp
+++ b/src/shared/proparser/prowriter.cpp
@@ -175,7 +175,7 @@ QString ProWriter::compileScope(const QString &scope)
if (scope.isEmpty())
return QString();
QMakeParser parser(0, 0, 0);
- ProFile *includeFile = parser.parsedProBlock(scope, QLatin1String("no-file"), 1);
+ ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), QLatin1String("no-file"), 1);
if (!includeFile)
return QString();
QString result = includeFile->items();
diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp
index f5868c5de0..8ceebd9cf0 100644
--- a/src/shared/proparser/qmakebuiltins.cpp
+++ b/src/shared/proparser/qmakebuiltins.cpp
@@ -52,6 +52,8 @@
#include <utime.h>
#include <errno.h>
#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#else
@@ -62,9 +64,11 @@
#ifdef Q_OS_WIN32
#define QT_POPEN _popen
+#define QT_POPEN_READ "rb"
#define QT_PCLOSE _pclose
#else
#define QT_POPEN popen
+#define QT_POPEN_READ "r"
#define QT_PCLOSE pclose
#endif
@@ -75,9 +79,10 @@ QT_BEGIN_NAMESPACE
#define fL1S(s) QString::fromLatin1(s)
enum ExpandFunc {
- E_INVALID = 0, E_MEMBER, E_FIRST, E_LAST, E_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST,
- E_SPRINTF, E_FORMAT_NUMBER, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION,
- E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND,
+ E_INVALID = 0, E_MEMBER, E_STR_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST,
+ E_SIZE, E_STR_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER,
+ E_NUM_ADD, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION,
+ E_FIND, E_SYSTEM, E_UNIQUE, E_SORTED, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND,
E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE,
E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS,
E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH,
@@ -99,15 +104,20 @@ void QMakeEvaluator::initFunctionStatics()
const ExpandFunc func;
} expandInits[] = {
{ "member", E_MEMBER },
+ { "str_member", E_STR_MEMBER },
{ "first", E_FIRST },
+ { "take_first", E_TAKE_FIRST },
{ "last", E_LAST },
+ { "take_last", E_TAKE_LAST },
{ "size", E_SIZE },
+ { "str_size", E_STR_SIZE },
{ "cat", E_CAT },
{ "fromfile", E_FROMFILE },
{ "eval", E_EVAL },
{ "list", E_LIST },
{ "sprintf", E_SPRINTF },
{ "format_number", E_FORMAT_NUMBER },
+ { "num_add", E_NUM_ADD },
{ "join", E_JOIN },
{ "split", E_SPLIT },
{ "basename", E_BASENAME },
@@ -116,6 +126,7 @@ void QMakeEvaluator::initFunctionStatics()
{ "find", E_FIND },
{ "system", E_SYSTEM },
{ "unique", E_UNIQUE },
+ { "sorted", E_SORTED },
{ "reverse", E_REVERSE },
{ "quote", E_QUOTE },
{ "escape_expand", E_ESCAPE_EXPAND },
@@ -140,6 +151,7 @@ void QMakeEvaluator::initFunctionStatics()
{ "shell_quote", E_SHELL_QUOTE },
{ "getenv", E_GETENV },
};
+ statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0])));
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
statics.expands.insert(ProKey(expandInits[i].name), expandInits[i].func);
@@ -179,16 +191,59 @@ void QMakeEvaluator::initFunctionStatics()
{ "touch", T_TOUCH },
{ "cache", T_CACHE },
};
+ statics.functions.reserve((int)(sizeof(testInits)/sizeof(testInits[0])));
for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i)
statics.functions.insert(ProKey(testInits[i].name), testInits[i].func);
}
-static bool isTrue(const ProString &_str, QString &tmp)
+static bool isTrue(const ProString &str)
{
- const QString &str = _str.toQString(tmp);
return !str.compare(statics.strtrue, Qt::CaseInsensitive) || str.toInt();
}
+bool
+QMakeEvaluator::getMemberArgs(const ProKey &func, int srclen, const ProStringList &args,
+ int *start, int *end)
+{
+ *start = 0, *end = 0;
+ if (args.count() >= 2) {
+ bool ok = true;
+ const ProString &start_str = args.at(1);
+ *start = start_str.toInt(&ok);
+ if (!ok) {
+ if (args.count() == 2) {
+ int dotdot = start_str.indexOf(statics.strDotDot);
+ if (dotdot != -1) {
+ *start = start_str.left(dotdot).toInt(&ok);
+ if (ok)
+ *end = start_str.mid(dotdot+2).toInt(&ok);
+ }
+ }
+ if (!ok) {
+ evalError(fL1S("%1() argument 2 (start) '%2' invalid.")
+ .arg(func.toQString(m_tmp1), start_str.toQString(m_tmp2)));
+ return false;
+ }
+ } else {
+ *end = *start;
+ if (args.count() == 3)
+ *end = args.at(2).toInt(&ok);
+ if (!ok) {
+ evalError(fL1S("%1() argument 3 (end) '%2' invalid.")
+ .arg(func.toQString(m_tmp1), args.at(2).toQString(m_tmp2)));
+ return false;
+ }
+ }
+ }
+ if (*start < 0)
+ *start += srclen;
+ if (*end < 0)
+ *end += srclen;
+ if (*start < 0 || *start >= srclen || *end < 0 || *end >= srclen)
+ return false;
+ return true;
+}
+
#if defined(Q_OS_WIN) && defined(PROEVALUATOR_FULL)
static QString windowsErrorCode()
{
@@ -285,19 +340,26 @@ static void insertJsonKeyValue(const QString &key, const QStringList &values, Pr
static void addJsonArray(const QJsonArray &array, const QString &keyPrefix, ProValueMap *map)
{
QStringList keys;
- for (int i = 0; i < array.count(); ++i) {
- keys.append(QString::number(i));
- addJsonValue(array.at(i), keyPrefix + QString::number(i), map);
+ const int size = array.count();
+ keys.reserve(size);
+ for (int i = 0; i < size; ++i) {
+ const QString number = QString::number(i);
+ keys.append(number);
+ addJsonValue(array.at(i), keyPrefix + number, map);
}
insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), keys, map);
}
static void addJsonObject(const QJsonObject &object, const QString &keyPrefix, ProValueMap *map)
{
- foreach (const QString &key, object.keys())
- addJsonValue(object.value(key), keyPrefix + key, map);
-
- insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), object.keys(), map);
+ QStringList keys;
+ keys.reserve(object.size());
+ for (auto it = object.begin(), end = object.end(); it != end; ++it) {
+ const QString key = it.key();
+ keys.append(key);
+ addJsonValue(it.value(), keyPrefix + key, map);
+ }
+ insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), keys, map);
}
static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProValueMap *map)
@@ -323,11 +385,16 @@ static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProV
}
}
-static QMakeEvaluator::VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value)
+QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value)
{
- QJsonDocument document = QJsonDocument::fromJson(json);
- if (document.isNull())
+ QJsonParseError error;
+ QJsonDocument document = QJsonDocument::fromJson(json, &error);
+ if (document.isNull()) {
+ if (error.error != QJsonParseError::NoError)
+ evalError(fL1S("Error parsing json at offset %1: %2")
+ .arg(error.offset).arg(error.errorString()));
return QMakeEvaluator::ReturnFalse;
+ }
QString currentKey = into + QLatin1Char('.');
@@ -344,10 +411,10 @@ static QMakeEvaluator::VisitReturn parseJsonInto(const QByteArray &json, const Q
QMakeEvaluator::VisitReturn
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
- const QString &contents)
+ bool exe, const QString &contents)
{
QString errStr;
- if (!m_vfs->writeFile(fn, mode, contents, &errStr)) {
+ if (!m_vfs->writeFile(fn, mode, exe, contents, &errStr)) {
evalError(fL1S("Cannot write %1file %2: %3")
.arg(ctx, QDir::toNativeSeparators(fn), errStr));
return ReturnFalse;
@@ -401,7 +468,7 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const
#else
if (FILE *proc = QT_POPEN(QString(QLatin1String("cd ")
+ IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory()))
- + QLatin1String(" && ") + args).toLocal8Bit().constData(), "r")) {
+ + QLatin1String(" && ") + args).toLocal8Bit().constData(), QT_POPEN_READ)) {
while (!feof(proc)) {
char buff[10 * 1024];
int read_in = int(fread(buff, 1, sizeof(buff), proc));
@@ -411,6 +478,9 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const
}
QT_PCLOSE(proc);
}
+# ifdef Q_OS_WIN
+ out.replace("\r\n", "\n");
+# endif
#endif
return out;
}
@@ -421,11 +491,11 @@ void QMakeEvaluator::populateDeps(
QHash<ProKey, QSet<ProKey> > &dependencies, ProValueMap &dependees,
QMultiMap<int, ProString> &rootSet) const
{
- foreach (const ProString &item, deps)
+ for (const ProString &item : deps)
if (!dependencies.contains(item.toKey())) {
QSet<ProKey> &dset = dependencies[item.toKey()]; // Always create entry
ProStringList depends;
- foreach (const ProString &suffix, suffixes)
+ for (const ProString &suffix : suffixes)
depends += values(ProKey(prefix + item + suffix));
if (depends.isEmpty()) {
rootSet.insert(first(ProKey(prefix + item + priosfx)).toInt(), item);
@@ -462,9 +532,9 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
} else {
var = args[0];
sep = args.at(1).toQString();
- beg = args.at(2).toQString(m_tmp2).toInt();
+ beg = args.at(2).toInt();
if (args.count() == 4)
- end = args.at(3).toQString(m_tmp2).toInt();
+ end = args.at(3).toInt();
}
} else {
if (args.count() != 1) {
@@ -480,14 +550,15 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
}
}
if (!var.isEmpty()) {
+ const auto strings = values(map(var));
if (regexp) {
QRegExp sepRx(sep);
- foreach (const ProString &str, values(map(var))) {
+ for (const ProString &str : strings) {
const QString &rstr = str.toQString(m_tmp1).section(sepRx, beg, end);
ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr).setSource(str));
}
} else {
- foreach (const ProString &str, values(map(var))) {
+ for (const ProString &str : strings) {
const QString &rstr = str.toQString(m_tmp1).section(sep, beg, end);
ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr).setSource(str));
}
@@ -516,7 +587,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
bool leftalign = false;
enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign;
if (args.count() >= 2) {
- foreach (const ProString &opt, split_value_list(args.at(1).toQString(m_tmp2))) {
+ const auto opts = split_value_list(args.at(1).toQStringRef());
+ for (const ProString &opt : opts) {
opt.toQString(m_tmp3);
if (m_tmp3.startsWith(QLatin1String("ibase="))) {
ibase = m_tmp3.mid(6).toInt();
@@ -544,7 +616,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
break;
}
bool ok;
- qlonglong num = m_tmp3.toLongLong(&ok, ibase);
+ qlonglong num = args.at(0).toLongLong(&ok, ibase);
if (!ok) {
evalError(fL1S("format_number(): malformed number %2 for base %1.")
.arg(ibase).arg(m_tmp3));
@@ -575,14 +647,36 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
}
formfail:
break;
+ case E_NUM_ADD:
+ if (args.count() < 1 || args.at(0).isEmpty()) {
+ evalError(fL1S("num_add(num, ...) requires at least one argument."));
+ } else {
+ qlonglong sum = 0;
+ foreach (const ProString &arg, args) {
+ if (arg.contains(QLatin1Char('.'))) {
+ evalError(fL1S("num_add(): floats are currently not supported."));
+ goto nafail;
+ }
+ bool ok;
+ qlonglong num = arg.toLongLong(&ok);
+ if (!ok) {
+ evalError(fL1S("num_add(): malformed number %1.")
+ .arg(arg.toQString(m_tmp3)));
+ goto nafail;
+ }
+ sum += num;
+ }
+ ret += ProString(QString::number(sum));
+ }
+ nafail:
+ break;
case E_JOIN: {
if (args.count() < 1 || args.count() > 4) {
evalError(fL1S("join(var, glue, before, after) requires one to four arguments."));
} else {
- QString glue;
- ProString before, after;
+ ProString glue, before, after;
if (args.count() >= 2)
- glue = args.at(1).toQString(m_tmp1);
+ glue = args.at(1);
if (args.count() >= 3)
before = args[2];
if (args.count() == 4)
@@ -590,7 +684,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
const ProStringList &var = values(map(args.at(0)));
if (!var.isEmpty()) {
const ProFile *src = currentProFile();
- foreach (const ProString &v, var)
+ for (const ProString &v : var)
if (const ProFile *s = v.sourceFile()) {
src = s;
break;
@@ -605,56 +699,49 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
evalError(fL1S("split(var, sep) requires one or two arguments."));
} else {
const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep;
- foreach (const ProString &var, values(map(args.at(0))))
- foreach (const QString &splt, var.toQString(m_tmp2).split(sep))
+ const auto vars = values(map(args.at(0)));
+ for (const ProString &var : vars) {
+ const auto splits = var.toQString(m_tmp2).split(sep);
+ for (const QString &splt : splits)
ret << (splt.isSharedWith(m_tmp2) ? var : ProString(splt).setSource(var));
+ }
}
break;
case E_MEMBER:
if (args.count() < 1 || args.count() > 3) {
evalError(fL1S("member(var, start, end) requires one to three arguments."));
} else {
- bool ok = true;
- const ProStringList &var = values(map(args.at(0)));
- int start = 0, end = 0;
- if (args.count() >= 2) {
- const QString &start_str = args.at(1).toQString(m_tmp1);
- start = start_str.toInt(&ok);
- if (!ok) {
- if (args.count() == 2) {
- int dotdot = start_str.indexOf(statics.strDotDot);
- if (dotdot != -1) {
- start = start_str.left(dotdot).toInt(&ok);
- if (ok)
- end = start_str.mid(dotdot+2).toInt(&ok);
- }
- }
- if (!ok)
- evalError(fL1S("member() argument 2 (start) '%2' invalid.")
- .arg(start_str));
+ const ProStringList &src = values(map(args.at(0)));
+ int start, end;
+ if (getMemberArgs(func, src.size(), args, &start, &end)) {
+ ret.reserve(qAbs(end - start) + 1);
+ if (start < end) {
+ for (int i = start; i <= end && src.size() >= i; i++)
+ ret += src.at(i);
} else {
- end = start;
- if (args.count() == 3)
- end = args.at(2).toQString(m_tmp1).toInt(&ok);
- if (!ok)
- evalError(fL1S("member() argument 3 (end) '%2' invalid.")
- .arg(args.at(2).toQString(m_tmp1)));
+ for (int i = start; i >= end && src.size() >= i && i >= 0; i--)
+ ret += src.at(i);
}
}
- if (ok) {
- if (start < 0)
- start += var.count();
- if (end < 0)
- end += var.count();
- if (start < 0 || start >= var.count() || end < 0 || end >= var.count()) {
- //nothing
- } else if (start < end) {
- for (int i = start; i <= end && var.count() >= i; i++)
- ret.append(var[i]);
+ }
+ break;
+ case E_STR_MEMBER:
+ if (args.count() < 1 || args.count() > 3) {
+ evalError(fL1S("str_member(str, start, end) requires one to three arguments."));
+ } else {
+ const ProString &src = args.at(0);
+ int start, end;
+ if (getMemberArgs(func, src.size(), args, &start, &end)) {
+ QString res;
+ res.reserve(qAbs(end - start) + 1);
+ if (start < end) {
+ for (int i = start; i <= end && src.size() >= i; i++)
+ res += src.at(i);
} else {
- for (int i = start; i >= end && var.count() >= i && i >= 0; i--)
- ret += var[i];
+ for (int i = start; i >= end && src.size() >= i && i >= 0; i--)
+ res += src.at(i);
}
+ ret += ProString(res);
}
}
break;
@@ -672,12 +759,32 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
}
}
break;
+ case E_TAKE_FIRST:
+ case E_TAKE_LAST:
+ if (args.count() != 1) {
+ evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1)));
+ } else {
+ ProStringList &var = valuesRef(map(args.at(0)));
+ if (!var.isEmpty()) {
+ if (func_t == E_TAKE_FIRST)
+ ret.append(var.takeFirst());
+ else
+ ret.append(var.takeLast());
+ }
+ }
+ break;
case E_SIZE:
if (args.count() != 1)
evalError(fL1S("size(var) requires one argument."));
else
ret.append(ProString(QString::number(values(map(args.at(0))).size())));
break;
+ case E_STR_SIZE:
+ if (args.count() != 1)
+ evalError(fL1S("str_size(str) requires one argument."));
+ else
+ ret.append(ProString(QString::number(args.at(0).size())));
+ break;
case E_CAT:
if (args.count() < 1 || args.count() > 2) {
evalError(fL1S("cat(file, singleline=true) requires one or two arguments."));
@@ -707,7 +814,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
if (lines) {
ret += ProString(stream.readLine());
} else {
- ret += split_value_list(stream.readLine().trimmed());
+ const QString &line = stream.readLine();
+ ret += split_value_list(QStringRef(&line).trimmed());
if (!singleLine)
ret += ProString("\n");
}
@@ -738,8 +846,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
tmp.sprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++);
ret = ProStringList(ProString(tmp));
ProStringList lst;
- foreach (const ProString &arg, args)
- lst += split_value_list(arg.toQString(m_tmp1), arg.sourceFile()); // Relies on deep copy
+ for (const ProString &arg : args)
+ lst += split_value_list(arg.toQStringRef(), arg.sourceFile()); // Relies on deep copy
m_valuemapStack.top()[ret.at(0).toKey()] = lst;
break; }
case E_FIND:
@@ -748,7 +856,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
} else {
QRegExp regx(args.at(1).toQString());
int t = 0;
- foreach (const ProString &val, values(map(args.at(0)))) {
+ const auto vals = values(map(args.at(0)));
+ for (const ProString &val : vals) {
if (regx.indexIn(val.toQString(m_tmp[t])) != -1)
ret += val;
t ^= 1;
@@ -785,7 +894,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
output.replace(QLatin1Char('\t'), QLatin1Char(' '));
if (singleLine)
output.replace(QLatin1Char('\n'), QLatin1Char(' '));
- ret += split_value_list(output);
+ ret += split_value_list(QStringRef(&output));
}
}
}
@@ -799,6 +908,14 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
ret.removeDuplicates();
}
break;
+ case E_SORTED:
+ if (args.count() != 1) {
+ evalError(fL1S("sorted(var) requires one argument."));
+ } else {
+ ret = values(map(args.at(0)));
+ std::sort(ret.begin(), ret.end());
+ }
+ break;
case E_REVERSE:
if (args.count() != 1) {
evalError(fL1S("reverse(var) requires one argument."));
@@ -857,7 +974,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
} else {
const ProStringList &vals = values(args.at(0).toKey());
ret.reserve(vals.size());
- foreach (const ProString &str, vals)
+ for (const ProString &str : vals)
ret += ProString(quoteValue(str));
}
break;
@@ -882,7 +999,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
} else {
bool recursive = false;
if (args.count() == 2)
- recursive = isTrue(args.at(1), m_tmp2);
+ recursive = isTrue(args.at(1));
QStringList dirs;
QString r = m_option->expandEnvVars(args.at(0).toQString(m_tmp1))
.replace(QLatin1Char('\\'), QLatin1Char('/'));
@@ -934,7 +1051,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
QFile qfile;
if (qfile.open(stdin, QIODevice::ReadOnly)) {
QTextStream t(&qfile);
- ret = split_value_list(t.readLine());
+ const QString &line = t.readLine();
+ ret = split_value_list(QStringRef(&line));
}
}
break; }
@@ -945,7 +1063,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
} else {
const QRegExp before(args.at(1).toQString());
const QString &after(args.at(2).toQString(m_tmp2));
- foreach (const ProString &val, values(map(args.at(0)))) {
+ const auto vals = values(map(args.at(0)));
+ for (const ProString &val : vals) {
QString rstr = val.toQString(m_tmp1);
QString copy = rstr; // Force a detach on modify
rstr.replace(before, after);
@@ -967,7 +1086,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
ProString priosfx = args.count() < 4 ? ProString(".priority") : args.at(3);
populateDeps(orgList, prefix,
args.count() < 3 ? ProStringList(ProString(".depends"))
- : split_value_list(args.at(2).toQString(m_tmp2)),
+ : split_value_list(args.at(2).toQStringRef()),
priosfx, dependencies, dependees, rootSet);
while (!rootSet.isEmpty()) {
QMultiMap<int, ProString>::iterator it = rootSet.begin();
@@ -1010,7 +1129,11 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
QString rstr = QDir::cleanPath(
QDir(args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory())
.absoluteFilePath(args.at(0).toQString(m_tmp1)));
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
+ ret << (rstr.isSharedWith(m_tmp1)
+ ? args.at(0)
+ : args.count() > 1 && rstr.isSharedWith(m_tmp2)
+ ? args.at(1)
+ : ProString(rstr).setSource(args.at(0)));
}
break;
case E_RELATIVE_PATH:
@@ -1174,7 +1297,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
regx.setPattern(copy);
}
int t = 0;
- foreach (const ProString &s, vars.value(map(args.at(1)))) {
+ const auto strings = vars.value(map(args.at(1)));
+ for (const ProString &s : strings) {
if ((!regx.isEmpty() && regx.exactMatch(s.toQString(m_tmp[t]))) || s == qry)
return ReturnTrue;
t ^= 1;
@@ -1183,12 +1307,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
case T_REQUIRES:
#ifdef PROEVALUATOR_FULL
- checkRequirements(args);
+ if (checkRequirements(args) == ReturnError)
+ return ReturnError;
#endif
return ReturnFalse; // Another qmake breakage
case T_EVAL: {
VisitReturn ret = ReturnFalse;
- ProFile *pro = m_parser->parsedProBlock(args.join(statics.field_sep),
+ QString contents = args.join(statics.field_sep);
+ ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
m_current.pro->fileName(), m_current.line);
if (m_cumulative || pro->isOk()) {
m_locationStack.push(m_current);
@@ -1204,8 +1330,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
evalError(fL1S("if(condition) requires one argument."));
return ReturnFalse;
}
- return returnBool(evaluateConditional(args.at(0).toQString(),
- m_current.pro->fileName(), m_current.line));
+ return evaluateConditional(args.at(0).toQStringRef(),
+ m_current.pro->fileName(), m_current.line);
}
case T_CONFIG: {
if (args.count() < 1 || args.count() > 2) {
@@ -1268,7 +1394,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
int cnt = values(map(args.at(0))).count();
- int val = args.at(1).toQString(m_tmp1).toInt();
+ int val = args.at(1).toInt();
if (args.count() == 3) {
const ProString &comp = args.at(2);
if (comp == QLatin1String(">") || comp == QLatin1String("greaterThan")) {
@@ -1377,7 +1503,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
flags = LoadSilent;
if (args.count() >= 2) {
parseInto = args.at(1).toQString(m_tmp2);
- if (args.count() >= 3 && isTrue(args.at(2), m_tmp3))
+ if (args.count() >= 3 && isTrue(args.at(2)))
flags = LoadSilent;
}
QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
@@ -1415,7 +1541,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
case T_LOAD: {
bool ignore_error = false;
if (args.count() == 2) {
- ignore_error = isTrue(args.at(1), m_tmp2);
+ ignore_error = isTrue(args.at(1));
} else if (args.count() != 1) {
evalError(fL1S("load(feature) requires one or two arguments."));
return ReturnFalse;
@@ -1480,9 +1606,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
runProcess(&proc, args.at(0).toQString(m_tmp2));
return returnBool(proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0);
#else
- return returnBool(system((QLatin1String("cd ")
- + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory()))
- + QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData()) == 0);
+ int ec = system((QLatin1String("cd ")
+ + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory()))
+ + QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData());
+# ifdef Q_OS_UNIX
+ if (ec != -1 && WIFSIGNALED(ec) && (WTERMSIG(ec) == SIGQUIT || WTERMSIG(ec) == SIGINT))
+ raise(WTERMSIG(ec));
+# endif
+ return returnBool(ec == 0);
#endif
#else
return ReturnTrue;
@@ -1533,22 +1664,34 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
case T_WRITE_FILE: {
if (args.count() > 3) {
- evalError(fL1S("write_file(name, [content var, [append]]) requires one to three arguments."));
+ evalError(fL1S("write_file(name, [content var, [append] [exe]]) requires one to three arguments."));
return ReturnFalse;
}
QIODevice::OpenMode mode = QIODevice::Truncate;
+ bool exe = false;
QString contents;
if (args.count() >= 2) {
const ProStringList &vals = values(args.at(1).toKey());
if (!vals.isEmpty())
contents = vals.join(QLatin1Char('\n')) + QLatin1Char('\n');
- if (args.count() >= 3)
- if (!args.at(2).toQString(m_tmp1).compare(fL1S("append"), Qt::CaseInsensitive))
- mode = QIODevice::Append;
+ if (args.count() >= 3) {
+ const auto opts = split_value_list(args.at(2).toQStringRef());
+ for (const ProString &opt : opts) {
+ opt.toQString(m_tmp3);
+ if (m_tmp3 == QLatin1String("append")) {
+ mode = QIODevice::Append;
+ } else if (m_tmp3 == QLatin1String("exe")) {
+ exe = true;
+ } else {
+ evalError(fL1S("write_file(): invalid flag %1.").arg(m_tmp3));
+ return ReturnFalse;
+ }
+ }
+ }
}
QString path = resolvePath(args.at(0).toQString(m_tmp1));
path.detach(); // make sure to not leak m_tmp1 into the map of written files.
- return writeFile(QString(), path, mode, contents);
+ return writeFile(QString(), path, mode, exe, contents);
}
case T_TOUCH: {
if (args.count() != 2) {
@@ -1605,7 +1748,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet;
ProKey srcvar;
if (args.count() >= 2) {
- foreach (const ProString &opt, split_value_list(args.at(1).toQString(m_tmp2))) {
+ const auto opts = split_value_list(args.at(1).toQStringRef());
+ for (const ProString &opt : opts) {
opt.toQString(m_tmp3);
if (m_tmp3 == QLatin1String("transient")) {
persist = false;
@@ -1723,7 +1867,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
varstr += QLatin1Char(' ');
varstr += quoteValue(diffval.at(0));
} else if (!diffval.isEmpty()) {
- foreach (const ProString &vval, diffval) {
+ for (const ProString &vval : diffval) {
varstr += QLatin1String(" \\\n ");
varstr += quoteValue(vval);
}
@@ -1759,7 +1903,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
}
}
- return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr);
+ return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr);
}
default:
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp
index dafb56244a..7d43610a31 100644
--- a/src/shared/proparser/qmakeevaluator.cpp
+++ b/src/shared/proparser/qmakeevaluator.cpp
@@ -183,6 +183,7 @@ void QMakeEvaluator::initStatics()
{ "IN_PWD", "PWD" },
{ "DEPLOYMENT", "INSTALLS" }
};
+ statics.varMap.reserve((int)(sizeof(mapInits)/sizeof(mapInits[0])));
for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i)
statics.varMap.insert(ProKey(mapInits[i].oldname), ProKey(mapInits[i].newname));
}
@@ -266,7 +267,7 @@ void QMakeEvaluator::skipHashStr(const ushort *&tokPtr)
// FIXME: this should not build new strings for direct sections.
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
-ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFile *source)
+ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, const ProFile *source)
{
QString build;
ProStringList ret;
@@ -401,7 +402,7 @@ static ALWAYS_INLINE void addStrList(
}
}
-void QMakeEvaluator::evaluateExpression(
+QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpression(
const ushort *&tokPtr, ProStringList *ret, bool joined)
{
debugMsg(2, joined ? "evaluating joined expression" : "evaluating expression");
@@ -451,12 +452,15 @@ void QMakeEvaluator::evaluateExpression(
case TokFuncName: {
const ProKey &func = pro->getHashStr(tokPtr);
debugMsg(2, "function %s", dbgKey(func));
- addStrList(evaluateExpandFunction(func, tokPtr), tok, ret, pending, joined);
+ ProStringList val;
+ if (evaluateExpandFunction(func, tokPtr, &val) == ReturnError)
+ return ReturnError;
+ addStrList(val, tok, ret, pending, joined);
break; }
default:
debugMsg(2, "evaluated expression => %s", dbgStrList(*ret));
tokPtr--;
- return;
+ return ReturnTrue;
}
}
}
@@ -528,7 +532,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
case TokAppendUnique:
case TokRemove:
case TokReplace:
- visitProVariable(tok, curr, tokPtr);
+ ret = visitProVariable(tok, curr, tokPtr);
+ if (ret == ReturnError)
+ break;
curr.clear();
continue;
case TokBranch:
@@ -688,9 +694,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
continue;
default: {
const ushort *oTokPtr = --tokPtr;
- evaluateExpression(tokPtr, &curr, false);
- if (tokPtr != oTokPtr)
- continue;
+ ret = evaluateExpression(tokPtr, &curr, false);
+ if (ret == ReturnError || tokPtr != oTokPtr)
+ break;
}
Q_ASSERT_X(false, "visitProBlock", "unexpected item type");
continue;
@@ -723,7 +729,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
int index = 0;
ProKey variable;
ProStringList oldVarVal;
- ProString it_list = expandVariableReferences(exprPtr, 0, true).at(0);
+ ProStringList it_list_out;
+ if (expandVariableReferences(exprPtr, 0, &it_list_out, true) == ReturnError)
+ return ReturnError;
+ ProString it_list = it_list_out.at(0);
if (_variable.isEmpty()) {
if (it_list != statics.strever) {
evalError(fL1S("Invalid loop expression."));
@@ -752,12 +761,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
if (ok) {
int end = itl.mid(dotdot+2).toInt(&ok);
if (ok) {
- if (m_cumulative && qAbs(end - start) > 100) {
+ const int absDiff = qAbs(end - start);
+ if (m_cumulative && absDiff > 100) {
// Such a loop is unlikely to contribute something useful to the
// file collection, and may cause considerable delay.
traceMsg("skipping excessive loop in cumulative mode");
return ReturnFalse;
}
+ list.reserve(absDiff + 1);
if (start < end) {
for (int i = start; i <= end; i++)
list << ProString(QString::number(i));
@@ -820,7 +831,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
return ret;
}
-void QMakeEvaluator::visitProVariable(
+QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable(
ushort tok, const ProStringList &curr, const ushort *&tokPtr)
{
int sizeHint = *tokPtr++;
@@ -829,24 +840,26 @@ void QMakeEvaluator::visitProVariable(
skipExpression(tokPtr);
if (!m_cumulative || !curr.isEmpty())
evalError(fL1S("Left hand side of assignment must expand to exactly one word."));
- return;
+ return ReturnTrue;
}
const ProKey &varName = map(curr.first());
if (tok == TokReplace) { // ~=
// DEFINES ~= s/a/b/?[gqi]
- const ProStringList &varVal = expandVariableReferences(tokPtr, sizeHint, true);
+ ProStringList varVal;
+ if (expandVariableReferences(tokPtr, sizeHint, &varVal, true) == ReturnError)
+ return ReturnError;
const QString &val = varVal.at(0).toQString(m_tmp1);
if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
evalError(fL1S("The ~= operator can handle only the s/// function."));
- return;
+ return ReturnTrue;
}
QChar sep = val.at(1);
QStringList func = val.split(sep);
if (func.count() < 3 || func.count() > 4) {
evalError(fL1S("The s/// function expects 3 or 4 arguments."));
- return;
+ return ReturnTrue;
}
bool global = false, quote = false, case_sense = false;
@@ -867,7 +880,9 @@ void QMakeEvaluator::visitProVariable(
replaceInList(&valuesRef(varName), regexp, replace, global, m_tmp2);
debugMsg(2, "replaced %s with %s", dbgQStr(pattern), dbgQStr(replace));
} else {
- ProStringList varVal = expandVariableReferences(tokPtr, sizeHint);
+ ProStringList varVal;
+ if (expandVariableReferences(tokPtr, sizeHint, &varVal, false) == ReturnError)
+ return ReturnError;
switch (tok) {
default: // whatever - cannot happen
case TokAssign: // =
@@ -913,8 +928,10 @@ void QMakeEvaluator::visitProVariable(
}
#ifdef PROEVALUATOR_FULL
else if (varName == statics.strREQUIRES)
- checkRequirements(values(varName));
+ return checkRequirements(values(varName));
#endif
+
+ return ReturnTrue;
}
void QMakeEvaluator::setTemplate()
@@ -949,7 +966,7 @@ static ProString msvcBinDirToQMakeArch(QString subdir)
if (idx >= 0)
subdir.remove(0, idx + 1);
subdir = subdir.toLower();
- if (subdir == QStringLiteral("amd64"))
+ if (subdir == QLatin1String("amd64"))
return ProString("x86_64");
return ProString(subdir);
}
@@ -970,7 +987,8 @@ static ProString msvcArchitecture(const QString &vcInstallDir, const QString &pa
QString vcBinDir = vcInstallDir;
if (vcBinDir.endsWith(QLatin1Char('\\')))
vcBinDir.chop(1);
- foreach (const QString &dir, pathVar.split(QLatin1Char(';'))) {
+ const auto dirs = pathVar.split(QLatin1Char(';'));
+ for (const QString &dir : dirs) {
if (!dir.startsWith(vcBinDir, Qt::CaseInsensitive))
continue;
const ProString arch = msvcBinDirToQMakeArch(dir.mid(vcBinDir.length() + 1));
@@ -992,6 +1010,8 @@ void QMakeEvaluator::loadDefaults()
vars[ProKey("QMAKE_QMAKE")] << ProString(m_option->qmake_abslocation);
if (!m_option->qmake_args.isEmpty())
vars[ProKey("QMAKE_ARGS")] = ProStringList(m_option->qmake_args);
+ if (!m_option->qtconf.isEmpty())
+ vars[ProKey("QMAKE_QTCONF")] = ProString(m_option->qtconf);
vars[ProKey("QMAKE_HOST.cpu_count")] = ProString(QString::number(idealThreadCount()));
#if defined(Q_OS_WIN32)
vars[ProKey("QMAKE_HOST.os")] << ProString("Windows");
@@ -1268,7 +1288,7 @@ void QMakeEvaluator::setupProject()
void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where)
{
if (!cmds.isEmpty()) {
- ProFile *pro = m_parser->parsedProBlock(cmds, where, -1);
+ ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1);
if (pro->isOk()) {
m_locationStack.push(m_current);
visitProBlock(pro, pro->tokPtr());
@@ -1442,7 +1462,8 @@ void QMakeEvaluator::updateMkspecPaths()
QStringList ret;
const QString concat = QLatin1String("/mkspecs");
- foreach (const QString &it, m_option->getPathListEnv(QLatin1String("QMAKEPATH")))
+ const auto paths = m_option->getPathListEnv(QLatin1String("QMAKEPATH"));
+ for (const QString &it : paths)
ret << it + concat;
foreach (const QString &it, m_qmakepath)
@@ -1467,11 +1488,8 @@ void QMakeEvaluator::updateFeaturePaths()
QStringList feature_roots;
- foreach (const QString &f, m_option->getPathListEnv(QLatin1String("QMAKEFEATURES")))
- feature_roots += f;
-
+ feature_roots += m_option->getPathListEnv(QLatin1String("QMAKEFEATURES"));
feature_roots += m_qmakefeatures;
-
feature_roots += m_option->splitPathList(
m_option->propertyValue(ProKey("QMAKEFEATURES")).toQString(m_mtmp));
@@ -1485,7 +1503,8 @@ void QMakeEvaluator::updateFeaturePaths()
feature_bases << m_sourceRoot;
}
- foreach (const QString &item, m_option->getPathListEnv(QLatin1String("QMAKEPATH")))
+ const auto items = m_option->getPathListEnv(QLatin1String("QMAKEPATH"));
+ for (const QString &item : items)
feature_bases << (item + mkspecs_concat);
foreach (const QString &item, m_qmakepath)
@@ -1511,7 +1530,8 @@ void QMakeEvaluator::updateFeaturePaths()
feature_bases << (m_option->propertyValue(ProKey("QT_HOST_DATA/src")) + mkspecs_concat);
foreach (const QString &fb, feature_bases) {
- foreach (const ProString &sfx, values(ProKey("QMAKE_PLATFORM")))
+ const auto sfxs = values(ProKey("QMAKE_PLATFORM"));
+ for (const ProString &sfx : sfxs)
feature_roots << (fb + features_concat + sfx + QLatin1Char('/'));
feature_roots << (fb + features_concat);
}
@@ -1584,7 +1604,8 @@ bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex)
// CONFIG variable
int t = 0;
- foreach (const ProString &configValue, values(statics.strCONFIG)) {
+ const auto configValues = values(statics.strCONFIG);
+ for (const ProString &configValue : configValues) {
if (re.exactMatch(configValue.toQString(m_tmp[t])))
return true;
t ^= 1;
@@ -1602,18 +1623,18 @@ bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex)
return false;
}
-ProStringList QMakeEvaluator::expandVariableReferences(
- const ushort *&tokPtr, int sizeHint, bool joined)
+QMakeEvaluator::VisitReturn QMakeEvaluator::expandVariableReferences(
+ const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined)
{
- ProStringList ret;
- ret.reserve(sizeHint);
+ ret->reserve(sizeHint);
forever {
- evaluateExpression(tokPtr, &ret, joined);
+ if (evaluateExpression(tokPtr, ret, joined) == ReturnError)
+ return ReturnError;
switch (*tokPtr) {
case TokValueTerminator:
case TokFuncTerminator:
tokPtr++;
- return ret;
+ return ReturnTrue;
case TokArgSeparator:
if (joined) {
tokPtr++;
@@ -1627,28 +1648,28 @@ ProStringList QMakeEvaluator::expandVariableReferences(
}
}
-QList<ProStringList> QMakeEvaluator::prepareFunctionArgs(const ushort *&tokPtr)
+QMakeEvaluator::VisitReturn QMakeEvaluator::prepareFunctionArgs(
+ const ushort *&tokPtr, QList<ProStringList> *ret)
{
- QList<ProStringList> args_list;
if (*tokPtr != TokFuncTerminator) {
for (;; tokPtr++) {
ProStringList arg;
- evaluateExpression(tokPtr, &arg, false);
- args_list << arg;
+ if (evaluateExpression(tokPtr, &arg, false) == ReturnError)
+ return ReturnError;
+ *ret << arg;
if (*tokPtr == TokFuncTerminator)
break;
Q_ASSERT(*tokPtr == TokArgSeparator);
}
}
tokPtr++;
- return args_list;
+ return ReturnTrue;
}
-ProStringList QMakeEvaluator::evaluateFunction(
- const ProFunctionDef &func, const QList<ProStringList> &argumentsList, VisitReturn *ok)
+QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFunction(
+ const ProFunctionDef &func, const QList<ProStringList> &argumentsList, ProStringList *ret)
{
VisitReturn vr;
- ProStringList ret;
if (m_valuemapStack.count() >= 100) {
evalError(fL1S("Ran into infinite recursion (depth > 100)."));
@@ -1667,25 +1688,22 @@ ProStringList QMakeEvaluator::evaluateFunction(
vr = visitProBlock(func.pro(), func.tokPtr());
if (vr == ReturnReturn)
vr = ReturnTrue;
- ret = m_returnValue;
+ if (vr == ReturnTrue)
+ *ret = m_returnValue;
m_returnValue.clear();
m_current = m_locationStack.pop();
m_valuemapStack.pop();
}
- if (ok)
- *ok = vr;
- if (vr == ReturnTrue)
- return ret;
- return ProStringList();
+ return vr;
}
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction(
const ProFunctionDef &func, const QList<ProStringList> &argumentsList,
const ProString &function)
{
- VisitReturn vr;
- ProStringList ret = evaluateFunction(func, argumentsList, &vr);
+ ProStringList ret;
+ VisitReturn vr = evaluateFunction(func, argumentsList, &ret);
if (vr == ReturnTrue) {
if (ret.isEmpty())
return ReturnTrue;
@@ -1713,13 +1731,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
{
if (int func_t = statics.functions.value(func)) {
//why don't the builtin functions just use args_list? --Sam
- return evaluateBuiltinConditional(func_t, func, expandVariableReferences(tokPtr, 5, true));
+ ProStringList args;
+ if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError)
+ return ReturnError;
+ return evaluateBuiltinConditional(func_t, func, args);
}
QHash<ProKey, ProFunctionDef>::ConstIterator it =
m_functionDefs.testFunctions.constFind(func);
if (it != m_functionDefs.testFunctions.constEnd()) {
- const QList<ProStringList> args = prepareFunctionArgs(tokPtr);
+ QList<ProStringList> args;
+ if (prepareFunctionArgs(tokPtr, &args) == ReturnError)
+ return ReturnError;
traceMsg("calling %s(%s)", dbgKey(func), dbgStrListList(args));
return evaluateBoolFunction(*it, args, func);
}
@@ -1729,34 +1752,41 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
return ReturnFalse;
}
-ProStringList QMakeEvaluator::evaluateExpandFunction(
- const ProKey &func, const ushort *&tokPtr)
+QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction(
+ const ProKey &func, const ushort *&tokPtr, ProStringList *ret)
{
if (int func_t = statics.expands.value(func)) {
//why don't the builtin functions just use args_list? --Sam
- return evaluateBuiltinExpand(func_t, func, expandVariableReferences(tokPtr, 5, true));
+ ProStringList args;
+ if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError)
+ return ReturnError;
+ *ret = evaluateBuiltinExpand(func_t, func, args);
+ return ReturnTrue;
}
QHash<ProKey, ProFunctionDef>::ConstIterator it =
m_functionDefs.replaceFunctions.constFind(func);
if (it != m_functionDefs.replaceFunctions.constEnd()) {
- const QList<ProStringList> args = prepareFunctionArgs(tokPtr);
+ QList<ProStringList> args;
+ if (prepareFunctionArgs(tokPtr, &args) == ReturnError)
+ return ReturnError;
traceMsg("calling $$%s(%s)", dbgKey(func), dbgStrListList(args));
- return evaluateFunction(*it, args, 0);
+ return evaluateFunction(*it, args, ret);
}
skipExpression(tokPtr);
evalError(fL1S("'%1' is not a recognized replace function.").arg(func.toQString(m_tmp1)));
- return ProStringList();
+ return ReturnFalse;
}
-bool QMakeEvaluator::evaluateConditional(const QString &cond, const QString &where, int line)
+QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional(
+ const QStringRef &cond, const QString &where, int line)
{
- bool ret = false;
+ VisitReturn ret = ReturnFalse;
ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar);
if (pro->isOk()) {
m_locationStack.push(m_current);
- ret = visitProBlock(pro, pro->tokPtr()) == ReturnTrue;
+ ret = visitProBlock(pro, pro->tokPtr());
m_current = m_locationStack.pop();
}
pro->deref();
@@ -1764,28 +1794,49 @@ bool QMakeEvaluator::evaluateConditional(const QString &cond, const QString &whe
}
#ifdef PROEVALUATOR_FULL
-void QMakeEvaluator::checkRequirements(const ProStringList &deps)
+QMakeEvaluator::VisitReturn QMakeEvaluator::checkRequirements(const ProStringList &deps)
{
ProStringList &failed = valuesRef(ProKey("QMAKE_FAILED_REQUIREMENTS"));
- foreach (const ProString &dep, deps)
- if (!evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line))
+ for (const ProString &dep : deps) {
+ VisitReturn vr = evaluateConditional(dep.toQStringRef(), m_current.pro->fileName(), m_current.line);
+ if (vr == ReturnError)
+ return ReturnError;
+ if (vr != ReturnTrue)
failed << dep;
+ }
+ return ReturnTrue;
}
#endif
+static bool isFunctParam(const ProKey &variableName)
+{
+ const int len = variableName.size();
+ const QChar *data = variableName.constData();
+ for (int i = 0; i < len; i++) {
+ ushort c = data[i].unicode();
+ if (c < '0' || c > '9')
+ return false;
+ }
+ return true;
+}
+
ProValueMap *QMakeEvaluator::findValues(const ProKey &variableName, ProValueMap::Iterator *rit)
{
ProValueMapStack::Iterator vmi = m_valuemapStack.end();
- do {
+ for (bool first = true; ; first = false) {
--vmi;
ProValueMap::Iterator it = (*vmi).find(variableName);
if (it != (*vmi).end()) {
if (it->constBegin() == statics.fakeValue.constBegin())
- return 0;
+ break;
*rit = it;
return &(*vmi);
}
- } while (vmi != m_valuemapStack.begin());
+ if (vmi == m_valuemapStack.begin())
+ break;
+ if (first && isFunctParam(variableName))
+ break;
+ }
return 0;
}
@@ -1797,18 +1848,20 @@ ProStringList &QMakeEvaluator::valuesRef(const ProKey &variableName)
it->clear();
return *it;
}
- ProValueMapStack::Iterator vmi = m_valuemapStack.end();
- if (--vmi != m_valuemapStack.begin()) {
- do {
- --vmi;
- ProValueMap::ConstIterator it = (*vmi).constFind(variableName);
- if (it != (*vmi).constEnd()) {
- ProStringList &ret = m_valuemapStack.top()[variableName];
- if (it->constBegin() != statics.fakeValue.constBegin())
- ret = *it;
- return ret;
- }
- } while (vmi != m_valuemapStack.begin());
+ if (!isFunctParam(variableName)) {
+ ProValueMapStack::Iterator vmi = m_valuemapStack.end();
+ if (--vmi != m_valuemapStack.begin()) {
+ do {
+ --vmi;
+ ProValueMap::ConstIterator it = (*vmi).constFind(variableName);
+ if (it != (*vmi).constEnd()) {
+ ProStringList &ret = m_valuemapStack.top()[variableName];
+ if (it->constBegin() != statics.fakeValue.constBegin())
+ ret = *it;
+ return ret;
+ }
+ } while (vmi != m_valuemapStack.begin());
+ }
}
return m_valuemapStack.top()[variableName];
}
@@ -1816,7 +1869,7 @@ ProStringList &QMakeEvaluator::valuesRef(const ProKey &variableName)
ProStringList QMakeEvaluator::values(const ProKey &variableName) const
{
ProValueMapStack::ConstIterator vmi = m_valuemapStack.constEnd();
- do {
+ for (bool first = true; ; first = false) {
--vmi;
ProValueMap::ConstIterator it = (*vmi).constFind(variableName);
if (it != (*vmi).constEnd()) {
@@ -1824,7 +1877,11 @@ ProStringList QMakeEvaluator::values(const ProKey &variableName) const
break;
return *it;
}
- } while (vmi != m_valuemapStack.constBegin());
+ if (vmi == m_valuemapStack.constBegin())
+ break;
+ if (first && isFunctParam(variableName))
+ break;
+ }
return ProStringList();
}
@@ -1864,9 +1921,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFileChecked(
{
if (fileName.isEmpty())
return ReturnFalse;
- QMakeEvaluator *ref = this;
+ const QMakeEvaluator *ref = this;
do {
- foreach (const ProFile *pf, ref->m_profileStack)
+ for (const ProFile *pf : ref->m_profileStack)
if (pf->fileName() == fileName) {
evalError(fL1S("Circular inclusion of %1.").arg(fileName));
return ReturnFalse;
@@ -1967,7 +2024,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFileInto(
*values = visitor.m_valuemapStack.top();
ProKey qiif("QMAKE_INTERNAL_INCLUDED_FILES");
ProStringList &iif = m_valuemapStack.first()[qiif];
- foreach (const ProString &ifn, values->value(qiif))
+ const auto ifns = values->value(qiif);
+ for (const ProString &ifn : ifns)
if (!iif.contains(ifn))
iif << ifn;
return ReturnTrue;
@@ -2066,7 +2124,7 @@ QString QMakeEvaluator::formatValueList(const ProStringList &vals, bool commas)
{
QString ret;
- foreach (const ProString &str, vals) {
+ for (const ProString &str : vals) {
if (!ret.isEmpty()) {
if (commas)
ret += QLatin1Char(',');
@@ -2081,7 +2139,7 @@ QString QMakeEvaluator::formatValueListList(const QList<ProStringList> &lists)
{
QString ret;
- foreach (const ProStringList &list, lists) {
+ for (const ProStringList &list : lists) {
if (!ret.isEmpty())
ret += QLatin1String(", ");
ret += formatValueList(list);
diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h
index 7bb673cb89..e9cff77c67 100644
--- a/src/shared/proparser/qmakeevaluator.h
+++ b/src/shared/proparser/qmakeevaluator.h
@@ -144,7 +144,7 @@ public:
{ return b ? ReturnTrue : ReturnFalse; }
static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
- void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
+ VisitReturn evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
void skipExpression(const ushort *&tokPtr);
@@ -164,7 +164,7 @@ public:
VisitReturn visitProLoop(const ProKey &variable, const ushort *exprPtr,
const ushort *tokPtr);
void visitProFunctionDef(ushort tok, const ProKey &name, const ushort *tokPtr);
- void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);
+ VisitReturn visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);
ALWAYS_INLINE const ProKey &map(const ProString &var) { return map(var.toKey()); }
const ProKey &map(const ProKey &var);
@@ -172,9 +172,8 @@ public:
void setTemplate();
- ProStringList split_value_list(const QString &vals, const ProFile *source = 0);
- ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
- ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false);
+ ProStringList split_value_list(const QStringRef &vals, const ProFile *source = 0);
+ VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined);
QString currentFileName() const;
QString currentDirectory() const;
@@ -199,22 +198,22 @@ public:
void deprecationWarning(const QString &msg) const
{ message(QMakeHandler::EvalWarnDeprecated, msg); }
- QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
- ProStringList evaluateFunction(const ProFunctionDef &func,
- const QList<ProStringList> &argumentsList, VisitReturn *ok);
+ VisitReturn prepareFunctionArgs(const ushort *&tokPtr, QList<ProStringList> *ret);
+ VisitReturn evaluateFunction(const ProFunctionDef &func,
+ const QList<ProStringList> &argumentsList, ProStringList *ret);
VisitReturn evaluateBoolFunction(const ProFunctionDef &func,
const QList<ProStringList> &argumentsList,
const ProString &function);
- ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr);
+ VisitReturn evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr, ProStringList *ret);
VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args);
VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
- bool evaluateConditional(const QString &cond, const QString &where, int line = -1);
+ VisitReturn evaluateConditional(const QStringRef &cond, const QString &where, int line = -1);
#ifdef PROEVALUATOR_FULL
- void checkRequirements(const ProStringList &deps);
+ VisitReturn checkRequirements(const ProStringList &deps);
#endif
void updateMkspecPaths();
@@ -228,8 +227,12 @@ public:
QHash<ProKey, QSet<ProKey> > &dependencies, ProValueMap &dependees,
QMultiMap<int, ProString> &rootSet) const;
+ bool getMemberArgs(const ProKey &name, int srclen, const ProStringList &args,
+ int *start, int *end);
+ VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value);
+
VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
- const QString &contents);
+ bool exe, const QString &contents);
#ifndef QT_BOOTSTRAPPED
void runProcess(QProcess *proc, const QString &command) const;
#endif
diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp
index 2231391f9a..f3600b33e0 100644
--- a/src/shared/proparser/qmakeglobals.cpp
+++ b/src/shared/proparser/qmakeglobals.cpp
@@ -56,9 +56,11 @@
#ifdef Q_OS_WIN32
#define QT_POPEN _popen
+#define QT_POPEN_READ "rb"
#define QT_PCLOSE _pclose
#else
#define QT_POPEN popen
+#define QT_POPEN_READ "r"
#define QT_PCLOSE pclose
#endif
@@ -101,7 +103,7 @@ QString QMakeGlobals::cleanSpec(QMakeCmdLineParserState &state, const QString &s
QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments(
QMakeCmdLineParserState &state, QStringList &args, int *pos)
{
- enum { ArgNone, ArgConfig, ArgSpec, ArgXSpec, ArgTmpl, ArgTmplPfx, ArgCache } argState = ArgNone;
+ enum { ArgNone, ArgConfig, ArgSpec, ArgXSpec, ArgTmpl, ArgTmplPfx, ArgCache, ArgQtConf } argState = ArgNone;
for (; *pos < args.count(); (*pos)++) {
QString arg = args.at(*pos);
switch (argState) {
@@ -126,8 +128,16 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments(
case ArgCache:
cachefile = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg));
break;
+ case ArgQtConf:
+ qtconf = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg));
+ break;
default:
if (arg.startsWith(QLatin1Char('-'))) {
+ if (arg == QLatin1String("--")) {
+ state.extraargs = args.mid(*pos + 1);
+ *pos = args.size();
+ return ArgumentsOk;
+ }
if (arg == QLatin1String("-after"))
state.after = true;
else if (arg == QLatin1String("-config"))
@@ -136,6 +146,8 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments(
do_cache = false;
else if (arg == QLatin1String("-cache"))
argState = ArgCache;
+ else if (arg == QLatin1String("-qtconf"))
+ argState = ArgQtConf;
else if (arg == QLatin1String("-platform") || arg == QLatin1String("-spec"))
argState = ArgSpec;
else if (arg == QLatin1String("-xplatform") || arg == QLatin1String("-xspec"))
@@ -171,6 +183,12 @@ void QMakeGlobals::commitCommandLineArguments(QMakeCmdLineParserState &state)
{
if (!state.preconfigs.isEmpty())
state.precmds << (fL1S("CONFIG += ") + state.preconfigs.join(QLatin1Char(' ')));
+ if (!state.extraargs.isEmpty()) {
+ QString extra = fL1S("QMAKE_EXTRA_ARGS =");
+ foreach (const QString &ea, state.extraargs)
+ extra += QLatin1Char(' ') + QMakeEvaluator::quoteValue(ProString(ea));
+ state.precmds << extra;
+ }
precmds = state.precmds.join(QLatin1Char('\n'));
if (!state.postconfigs.isEmpty())
state.postcmds << (fL1S("CONFIG += ") + state.postconfigs.join(QLatin1Char(' ')));
@@ -240,9 +258,9 @@ QStringList QMakeGlobals::splitPathList(const QString &val) const
QStringList ret;
if (!val.isEmpty()) {
QDir bdir;
- QStringList vals = val.split(dirlist_sep);
+ const QStringList vals = val.split(dirlist_sep);
ret.reserve(vals.length());
- foreach (const QString &it, vals)
+ for (const QString &it : vals)
ret << QDir::cleanPath(bdir.absoluteFilePath(it));
}
return ret;
@@ -299,14 +317,15 @@ bool QMakeGlobals::initProperties()
data = proc.readAll();
#else
if (FILE *proc = QT_POPEN(QString(QMakeInternal::IoUtils::shellQuote(qmake_abslocation)
- + QLatin1String(" -query")).toLocal8Bit(), "r")) {
+ + QLatin1String(" -query")).toLocal8Bit(), QT_POPEN_READ)) {
char buff[1024];
while (!feof(proc))
data.append(buff, int(fread(buff, 1, 1023, proc)));
QT_PCLOSE(proc);
}
#endif
- foreach (QByteArray line, data.split('\n')) {
+ const auto lines = data.split('\n');
+ for (QByteArray line : lines) {
int off = line.indexOf(':');
if (off < 0) // huh?
continue;
diff --git a/src/shared/proparser/qmakeglobals.h b/src/shared/proparser/qmakeglobals.h
index 33a5bdb831..9942113681 100644
--- a/src/shared/proparser/qmakeglobals.h
+++ b/src/shared/proparser/qmakeglobals.h
@@ -81,7 +81,7 @@ class QMAKE_EXPORT QMakeCmdLineParserState
public:
QMakeCmdLineParserState(const QString &_pwd) : pwd(_pwd), after(false) {}
QString pwd;
- QStringList precmds, preconfigs, postcmds, postconfigs;
+ QStringList precmds, preconfigs, postcmds, postconfigs, extraargs;
bool after;
void flush() { after = false; }
@@ -103,6 +103,7 @@ public:
QString qmake_abslocation;
QStringList qmake_args;
+ QString qtconf;
QString qmakespec, xqmakespec;
QString user_template, user_template_prefix;
QString precmds, postcmds;
diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp
index 59dc289548..7751265e91 100644
--- a/src/shared/proparser/qmakeparser.cpp
+++ b/src/shared/proparser/qmakeparser.cpp
@@ -221,7 +221,7 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
}
ProFile *QMakeParser::parsedProBlock(
- const QString &contents, const QString &name, int line, SubGrammar grammar)
+ const QStringRef &contents, const QString &name, int line, SubGrammar grammar)
{
ProFile *pro = new ProFile(name);
read(pro, contents, line, grammar);
@@ -244,7 +244,7 @@ bool QMakeParser::read(ProFile *pro, ParseFlags flags)
fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr));
return false;
}
- read(pro, content, 1, FullGrammar);
+ read(pro, QStringRef(&content), 1, FullGrammar);
return true;
}
@@ -272,7 +272,8 @@ void QMakeParser::putHashStr(ushort *&pTokPtr, const ushort *buf, uint len)
*tokPtr++ = (ushort)hash;
*tokPtr++ = (ushort)(hash >> 16);
*tokPtr++ = (ushort)len;
- memcpy(tokPtr, buf, len * 2);
+ if (len) // buf may be nullptr; don't pass that to memcpy (-> undefined behavior)
+ memcpy(tokPtr, buf, len * 2);
pTokPtr = tokPtr + len;
}
@@ -285,7 +286,7 @@ void QMakeParser::finalizeHashStr(ushort *buf, uint len)
buf[-2] = (ushort)(hash >> 16);
}
-void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar grammar)
+void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar grammar)
{
m_proFile = pro;
m_lineNo = line;
@@ -295,27 +296,30 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
// Worst-case size calculations:
// - line marker adds 1 (2-nl) to 1st token of each line
// - empty assignment "A=":2 =>
- // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 0(1) +
+ // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + size_hint(1) +
// TokValueTerminator(1) == 8 (9)
// - non-empty assignment "A=B C":5 =>
- // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 2(1) +
+ // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + size_hint(1) +
// TokLiteral(1) + len(1) + "B"(1) +
// TokLiteral(1) + len(1) + "C"(1) + TokValueTerminator(1) == 14 (15)
// - variable expansion: "$$f":3 =>
// TokVariable(1) + hash(2) + len(1) + "f"(1) = 5
// - function expansion: "$$f()":5 =>
// TokFuncName(1) + hash(2) + len(1) + "f"(1) + TokFuncTerminator(1) = 6
+ // - test literal: "X":1 =>
+ // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokCondition(1) = 6 (7)
// - scope: "X:":2 =>
// TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokCondition(1) +
- // TokBranch(1) + len(2) + ... + len(2) + ... == 10
- // - test: "X():":4 =>
+ // TokBranch(1) + len(2) + ... + len(2) + ... == 11 (12)
+ // - test call: "X():":4 =>
// TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokTestCall(1) + TokFuncTerminator(1) +
- // TokBranch(1) + len(2) + ... + len(2) + ... == 11
+ // TokBranch(1) + len(2) + ... + len(2) + ... == 12 (13)
// - "for(A,B):":9 =>
// TokForLoop(1) + hash(2) + len(1) + "A"(1) +
// len(2) + TokLiteral(1) + len(1) + "B"(1) + TokValueTerminator(1) +
// len(2) + ... + TokTerminator(1) == 14 (15)
- tokBuff.reserve((in.size() + 1) * 5);
+ // One extra for possibly missing trailing newline.
+ tokBuff.reserve((in.size() + 1) * 7);
ushort *tokPtr = (ushort *)tokBuff.constData(); // Current writing position
// Expression precompiler buffer.
@@ -330,8 +334,8 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
QStack<ParseCtx> xprStack;
xprStack.reserve(10);
- // We rely on QStrings being null-terminated, so don't maintain a global end pointer.
const ushort *cur = (const ushort *)in.unicode();
+ const ushort *inend = cur + in.length();
m_canElse = false;
freshLine:
m_state = StNew;
@@ -414,7 +418,7 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
int indent;
if (context == CtxPureValue) {
- end = (const ushort *)in.unicode() + in.length();
+ end = inend;
cptr = 0;
lineCont = false;
indent = 0; // just gcc being stupid
@@ -426,24 +430,30 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
// First, skip leading whitespace
for (indent = 0; ; ++cur, ++indent) {
+ if (cur == inend) {
+ cur = 0;
+ goto flushLine;
+ }
c = *cur;
if (c == '\n') {
++cur;
goto flushLine;
- } else if (!c) {
- cur = 0;
- goto flushLine;
- } else if (c != ' ' && c != '\t' && c != '\r') {
- break;
}
+ if (c != ' ' && c != '\t' && c != '\r')
+ break;
}
// Then strip comments. Yep - no escaping is possible.
for (cptr = cur;; ++cptr) {
+ if (cptr == inend) {
+ end = cptr;
+ break;
+ }
c = *cptr;
if (c == '#') {
- for (end = cptr; (c = *++cptr);) {
- if (c == '\n') {
+ end = cptr;
+ while (++cptr < inend) {
+ if (*cptr == '\n') {
++cptr;
break;
}
@@ -456,10 +466,6 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra
}
break;
}
- if (!c) {
- end = cptr;
- break;
- }
if (c == '\n') {
end = cptr++;
break;
@@ -1211,7 +1217,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
bool QMakeParser::resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr,
ushort **buf, QString *xprBuff,
ushort **tokPtr, QString *tokBuff,
- const ushort *cur, const QString &in)
+ const ushort *cur, const QStringRef &in)
{
QString out;
m_tmp.setRawData((const QChar *)xprPtr, tlen);
diff --git a/src/shared/proparser/qmakeparser.h b/src/shared/proparser/qmakeparser.h
index d44523d024..d370d17cbb 100644
--- a/src/shared/proparser/qmakeparser.h
+++ b/src/shared/proparser/qmakeparser.h
@@ -83,7 +83,7 @@ public:
enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar };
// fileName is expected to be absolute and cleanPath()ed.
ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault);
- ProFile *parsedProBlock(const QString &contents, const QString &name, int line = 0,
+ ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0,
SubGrammar grammar = FullGrammar);
void discardFileFromCache(const QString &fileName);
@@ -126,7 +126,7 @@ private:
};
bool read(ProFile *pro, ParseFlags flags);
- void read(ProFile *pro, const QString &content, int line, SubGrammar grammar);
+ void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len);
@@ -137,7 +137,7 @@ private:
ALWAYS_INLINE bool resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr,
ushort **buf, QString *xprBuff,
ushort **tokPtr, QString *tokBuff,
- const ushort *cur, const QString &in);
+ const ushort *cur, const QStringRef &in);
void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount);
void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc);
void warnOperator(const char *msg);
diff --git a/src/shared/proparser/qmakevfs.cpp b/src/shared/proparser/qmakevfs.cpp
index 7eb35bebca..0231fa9a46 100644
--- a/src/shared/proparser/qmakevfs.cpp
+++ b/src/shared/proparser/qmakevfs.cpp
@@ -44,8 +44,8 @@ QMakeVfs::QMakeVfs()
{
}
-bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QString &contents,
- QString *errStr)
+bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
+ const QString &contents, QString *errStr)
{
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
@@ -57,6 +57,7 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QStr
else
*cont = contents;
Q_UNUSED(errStr)
+ Q_UNUSED(exe)
return true;
#else
QFileInfo qfi(fn);
@@ -67,8 +68,16 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QStr
QByteArray bytes = contents.toLocal8Bit();
QFile cfile(fn);
if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- if (cfile.readAll() == bytes)
+ if (cfile.readAll() == bytes) {
+ if (exe) {
+ cfile.setPermissions(cfile.permissions()
+ | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
+ } else {
+ cfile.setPermissions(cfile.permissions()
+ & ~(QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther));
+ }
return true;
+ }
cfile.close();
}
if (!cfile.open(mode | QIODevice::WriteOnly | QIODevice::Text)) {
@@ -81,6 +90,9 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QStr
*errStr = cfile.errorString();
return false;
}
+ if (exe)
+ cfile.setPermissions(cfile.permissions()
+ | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
return true;
#endif
}
diff --git a/src/shared/proparser/qmakevfs.h b/src/shared/proparser/qmakevfs.h
index 8c387fe29d..3ffe67c1ba 100644
--- a/src/shared/proparser/qmakevfs.h
+++ b/src/shared/proparser/qmakevfs.h
@@ -43,7 +43,7 @@ class QMAKE_EXPORT QMakeVfs
public:
QMakeVfs();
- bool writeFile(const QString &fn, QIODevice::OpenMode mode, const QString &contents, QString *errStr);
+ bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr);
bool readFile(const QString &fn, QString *contents, QString *errStr);
bool exists(const QString &fn);
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject 65cb4cba999b47a643e820a102b3185f861b97c
+Subproject a3466fc55fb7756fcc9ddd6aeabbdef80c0108e