From 80415bd14ed472733929a38e3fce054bd4a5eab9 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Tue, 19 Sep 2017 11:10:32 +0200 Subject: [PATCH 01/63] Revert "SearchResultWidget: Disable replace button if replace text is unchanged" The Refactor -> Convert to Camel Case quickfix calls setReplacementText() with the replacement text already, in contrast to the other search and refactoring functions, which pass the search text. Therefore, the replace button is disabled wrongly in that case. This reverts commit e75f5958737f3a302508d3e72aed4e4672a43557. Task-number: QTCREATORBUG-18947 Change-Id: I906a58f65a88cce42d2da6431e59b88fae4ec45a Reviewed-by: Eike Ziller --- .../coreplugin/find/searchresultwidget.cpp | 15 ++------------- src/plugins/coreplugin/find/searchresultwidget.h | 2 -- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/plugins/coreplugin/find/searchresultwidget.cpp b/src/plugins/coreplugin/find/searchresultwidget.cpp index 3db6a08f26a..9eee8dee632 100644 --- a/src/plugins/coreplugin/find/searchresultwidget.cpp +++ b/src/plugins/coreplugin/find/searchresultwidget.cpp @@ -210,8 +210,6 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) : this, &SearchResultWidget::handleReplaceButton); connect(m_replaceButton, &QAbstractButton::clicked, this, &SearchResultWidget::handleReplaceButton); - connect(m_replaceTextEdit, &QLineEdit::textChanged, - this, &SearchResultWidget::handleReplaceEditTextChanged); } SearchResultWidget::~SearchResultWidget() @@ -306,7 +304,6 @@ void SearchResultWidget::setSupportsReplace(bool replaceSupported, const QString void SearchResultWidget::setTextToReplace(const QString &textToReplace) { - m_replaceText = textToReplace; m_replaceTextEdit->setText(textToReplace); } @@ -409,6 +406,7 @@ void SearchResultWidget::goToPrevious() void SearchResultWidget::restart() { m_replaceTextEdit->setEnabled(false); + m_replaceButton->setEnabled(false); m_searchResultTreeView->clear(); m_count = 0; Id sizeWarningId(SIZE_WARNING_ID); @@ -418,7 +416,6 @@ void SearchResultWidget::restart() m_searchAgainButton->setVisible(false); m_messageWidget->setVisible(false); updateMatchesFoundLabel(); - handleReplaceEditTextChanged(); emit restarted(); } @@ -439,6 +436,7 @@ void SearchResultWidget::finishSearch(bool canceled) m_infoBar.removeInfo(sizeWarningId); m_infoBar.enableInfo(sizeWarningId); m_replaceTextEdit->setEnabled(m_count > 0); + m_replaceButton->setEnabled(m_count > 0); m_preserveCaseCheck->setEnabled(m_count > 0); m_cancelButton->setVisible(false); m_messageWidget->setVisible(canceled); @@ -463,15 +461,6 @@ void SearchResultWidget::cancelAfterSizeWarning() emit paused(false); } -void SearchResultWidget::handleReplaceEditTextChanged() -{ - const bool enabled = m_replaceTextEdit->text() != m_replaceText; - m_replaceButton->setEnabled(enabled); - m_replaceButton->setToolTip(enabled - ? QString() - : tr("Cannot replace because replacement text is unchanged.")); -} - void SearchResultWidget::handleJumpToSearchResult(const SearchResultItem &item) { emit activated(item); diff --git a/src/plugins/coreplugin/find/searchresultwidget.h b/src/plugins/coreplugin/find/searchresultwidget.h index bf4b9055440..5309ed69e1e 100644 --- a/src/plugins/coreplugin/find/searchresultwidget.h +++ b/src/plugins/coreplugin/find/searchresultwidget.h @@ -115,7 +115,6 @@ private: void setShowReplaceUI(bool visible); void continueAfterSizeWarning(); void cancelAfterSizeWarning(); - void handleReplaceEditTextChanged(); QList checkedItems() const; void updateMatchesFoundLabel(); @@ -142,7 +141,6 @@ private: bool m_isShowingReplaceUI = false; bool m_searchAgainSupported = false; bool m_replaceSupported = false; - QString m_replaceText; }; } // Internal From 9afe6fa1c462b53d32787517dd82464121829286 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Thu, 7 Sep 2017 16:41:56 +0200 Subject: [PATCH 02/63] Squish: Update texts of message boxes Change-Id: I3ca17bb62201d6271c0e98d07a99f7344faba439 Reviewed-by: Christian Stenger --- tests/system/objects.map | 2 +- tests/system/suite_editors/tst_delete_externally/test.py | 8 ++++---- tests/system/suite_editors/tst_edit_externally/test.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/system/objects.map b/tests/system/objects.map index e8aa510c03c..02020a785f4 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -178,7 +178,7 @@ :QtVersionLabel_KitPage {container=':qt_tabwidget_stackedwidget_QWidget' text='Qt version:' type='QLabel' unnamed='1' visible='1'} :Remove_QPushButton {container=':qt_tabwidget_stackedwidget_QScrollArea' text='Remove' type='QPushButton' unnamed='1' visible='1'} :Restart required.OK_QPushButton {text='OK' type='QPushButton' unnamed='1' visible='1' window=':Restart required_QMessageBox'} -:Restart required_QMessageBox {text='The language change will take effect after a restart of Qt Creator.' type='QMessageBox' unnamed='1' visible='1'} +:Restart required_QMessageBox {text='The language change will take effect after restart.' type='QMessageBox' unnamed='1' visible='1'} :Revert to Saved.Proceed_QPushButton {text='Proceed' type='QPushButton' unnamed='1' visible='1' window=':Revert to Saved_QMessageBox'} :Revert to Saved_QMessageBox {text?='You will lose your current changes if you proceed reverting*' type='QMessageBox' unnamed='1' visible='1'} :RunSettingsEnvironmentDetails_Utils::DetailsButton {leftWidget=':RunSettingsUseBuildEnvironment_QLabel' text='Details' type='Utils::DetailsButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} diff --git a/tests/system/suite_editors/tst_delete_externally/test.py b/tests/system/suite_editors/tst_delete_externally/test.py index fa85df88ae5..89d72c6a88b 100644 --- a/tests/system/suite_editors/tst_delete_externally/test.py +++ b/tests/system/suite_editors/tst_delete_externally/test.py @@ -45,7 +45,8 @@ def main(): contentBefore = readFile(currentFile) os.remove(currentFile) if not currentFile.endswith(".bin"): - popupText = "The file %s was removed. Do you want to save it under a different name, or close the editor?" + popupText = ("The file %s has been removed from disk. Do you want to " + "save it under a different name, or close the editor?") test.compare(waitForObject(":File has been removed_QMessageBox").text, popupText % currentFile) clickButton(waitForObject(":File has been removed.Save_QPushButton")) @@ -56,11 +57,10 @@ def main(): test.compare(readFile(currentFile), contentBefore, "Verifying that file '%s' was restored correctly" % currentFile) - # Different warning because of QTCREATORBUG-8130 - popupText2 = "The file %s has been removed outside Qt Creator. Do you want to save it under a different name, or close the editor?" + # Test for QTCREATORBUG-8130 os.remove(currentFile) test.compare(waitForObject(":File has been removed_QMessageBox").text, - popupText2 % currentFile) + popupText % currentFile) clickButton(waitForObject(":File has been removed.Close_QPushButton")) test.verify(checkIfObjectExists(objectMap.realName(editor), False), "Was the editor closed after deleting the file?") diff --git a/tests/system/suite_editors/tst_edit_externally/test.py b/tests/system/suite_editors/tst_edit_externally/test.py index e48232e9a4d..c545b64dea3 100644 --- a/tests/system/suite_editors/tst_edit_externally/test.py +++ b/tests/system/suite_editors/tst_edit_externally/test.py @@ -45,9 +45,9 @@ def main(): if not startedWithoutPluginError(): return - mBox = ("{text?='The file * has changed outside Qt Creator. Do you want to reload it?' " + mBox = ("{text?='The file * has been changed on disk. Do you want to reload it?' " "type='QMessageBox' unnamed='1' visible='1'}") - popupText = "The file %s has changed outside Qt Creator. Do you want to reload it?" + popupText = "The file %s has been changed on disk. Do you want to reload it?" formerContent = None for i, currentFile in enumerate(files): From be376ae7060e547c6dc9092e7e77dde6e9e6570f Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 14 Sep 2017 15:36:18 +0200 Subject: [PATCH 03/63] CMake: Enable type forcing for CMake configuation values Allow to force the type for CMake configuration values, now that this type changes how you can edit the values. Change-Id: Id89e0ec8547b778fc0aff9a2e00c0d7406cbcac1 Reviewed-by: hjk --- .../cmakebuildsettingswidget.cpp | 40 +++++++++++++++++-- .../cmakebuildsettingswidget.h | 1 + .../cmakeprojectmanager/configmodel.cpp | 12 +++--- src/plugins/cmakeprojectmanager/configmodel.h | 4 +- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp index c0531ebf379..620facdcd4d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp @@ -378,6 +378,33 @@ void CMakeBuildSettingsWidget::updateSelection(const QModelIndex ¤t, const m_editButton->setEnabled(currentModelIndex.flags().testFlag(Qt::ItemIsEditable)); } +QAction *CMakeBuildSettingsWidget::createForceAction(int type, const QModelIndex &idx) +{ + ConfigModel::DataItem::Type t = static_cast(type); + QString typeString; + switch (type) { + case ConfigModel::DataItem::BOOLEAN: + typeString = tr("bool", "display string for cmake type BOOLEAN"); + break; + case ConfigModel::DataItem::FILE: + typeString = tr("file", "display string for cmake type FILE"); + break; + case ConfigModel::DataItem::DIRECTORY: + typeString = tr("directory", "display string for cmake type DIRECTORY"); + break; + case ConfigModel::DataItem::STRING: + typeString = tr("string", "display string for cmake type STRING"); + break; + case ConfigModel::DataItem::UNKNOWN: + return nullptr; + } + QAction *forceAction = new QAction(tr("Force to %1").arg(typeString)); + forceAction->setEnabled(m_configModel->canForceTo(idx, t)); + connect(forceAction, &QAction::triggered, + this, [this, idx, t]() { m_configModel->forceTo(idx, t); }); + return forceAction; +} + bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event) { // handle context menu events: @@ -392,10 +419,15 @@ bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event) QMenu *menu = new QMenu(this); connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater); - QAction *forceToStringAction = new QAction(tr("Force to String"), nullptr); - forceToStringAction->setEnabled(m_configModel->canForceToString(idx)); - menu->addAction(forceToStringAction); - connect(forceToStringAction, &QAction::triggered, this, [this, idx]() { m_configModel->forceToString(idx); }); + QAction *action = nullptr; + if ((action = createForceAction(ConfigModel::DataItem::BOOLEAN, idx))) + menu->addAction(action); + if ((action = createForceAction(ConfigModel::DataItem::FILE, idx))) + menu->addAction(action); + if ((action = createForceAction(ConfigModel::DataItem::DIRECTORY, idx))) + menu->addAction(action); + if ((action = createForceAction(ConfigModel::DataItem::STRING, idx))) + menu->addAction(action); menu->move(e->globalPos()); menu->show(); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h index a15cfe6e0aa..e6e4b1e21c2 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h @@ -65,6 +65,7 @@ private: void updateFromKit(); void updateSelection(const QModelIndex ¤t, const QModelIndex &previous); + QAction *createForceAction(int type, const QModelIndex &idx); bool eventFilter(QObject *target, QEvent *event); diff --git a/src/plugins/cmakeprojectmanager/configmodel.cpp b/src/plugins/cmakeprojectmanager/configmodel.cpp index f87ffb967da..ff43d0cc63e 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.cpp +++ b/src/plugins/cmakeprojectmanager/configmodel.cpp @@ -135,23 +135,23 @@ bool ConfigModel::hasCMakeChanges() const return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isCMakeChanged; }); } -bool ConfigModel::canForceToString(const QModelIndex &idx) const +bool ConfigModel::canForceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type) const { if (idx.model() != const_cast(this) || idx.column() != 1) return false; Utils::TreeItem *item = itemForIndex(idx); auto cmti = dynamic_cast(item); - return cmti && (cmti->dataItem->type != DataItem::STRING); + return cmti && (cmti->dataItem->type != type); } -void ConfigModel::forceToString(const QModelIndex &idx) +void ConfigModel::forceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type) { - QTC_ASSERT(canForceToString(idx), return); + QTC_ASSERT(canForceTo(idx, type), return); Utils::TreeItem *item = itemForIndex(idx); auto cmti = dynamic_cast(item); - cmti->dataItem->type = DataItem::STRING; - const QModelIndex valueIdx = idx.sibling(1, idx.column()); + cmti->dataItem->type = type; + const QModelIndex valueIdx = idx.sibling(idx.row(), 1); emit dataChanged(valueIdx, valueIdx); } diff --git a/src/plugins/cmakeprojectmanager/configmodel.h b/src/plugins/cmakeprojectmanager/configmodel.h index adf6edc87e3..626d487ac63 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.h +++ b/src/plugins/cmakeprojectmanager/configmodel.h @@ -73,8 +73,8 @@ public: bool hasChanges() const; bool hasCMakeChanges() const; - bool canForceToString(const QModelIndex &idx) const; - void forceToString(const QModelIndex &idx); + bool canForceTo(const QModelIndex &idx, const DataItem::Type type) const; + void forceTo(const QModelIndex &idx, const DataItem::Type type); static DataItem dataItemFromIndex(const QModelIndex &idx); From a627f4eef73fa80abc91863fbebd8ce28e73bfb4 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 17 Sep 2017 17:16:12 +0300 Subject: [PATCH 04/63] Dumpers: Print readable output in tests Change-Id: I32864c9c1b8fe60b5b01423f68e63a3c00b936f8 Reviewed-by: hjk --- tests/auto/debugger/tst_dumpers.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 91af07f8f13..a7a9d7b9317 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1035,7 +1035,7 @@ void tst_Dumpers::initTestCase() ok = debugger.waitForFinished(); QVERIFY(ok); QByteArray output = debugger.readAllStandardOutput(); - //qDebug() << "stdout: " << output; + //qDebug().noquote() << "stdout: " << output; bool usePython = !output.contains("Python scripting is not supported in this copy of GDB"); qDebug() << "Python : " << (usePython ? "ok" : "*** not ok ***"); qDebug() << "Dumper dir : " << DUMPERDIR; @@ -1404,11 +1404,11 @@ void tst_Dumpers::dumper() error = make.readAllStandardError(); //qDebug() << "stdout: " << output; if (make.exitCode()) { - qDebug() << error; + qDebug().noquote() << error; qDebug() << "\n------------------ CODE --------------------"; - qDebug() << fullCode; + qDebug().noquote() << fullCode; qDebug() << "\n------------------ CODE --------------------"; - qDebug() << "Project file: " << proFile.fileName(); + qDebug().noquote() << "Project file: " << proFile.fileName(); } if (data.neededDwarfVersion.isRestricted) { @@ -1574,7 +1574,7 @@ void tst_Dumpers::dumper() if (m_debuggerEngine == GdbEngine) { int posDataStart = output.indexOf("data="); if (posDataStart == -1) { - qDebug() << "NO \"data=\" IN OUTPUT: " << output; + qDebug().noquote() << "NO \"data=\" IN OUTPUT: " << output; QVERIFY(posDataStart != -1); } contents = output.mid(posDataStart); @@ -1586,7 +1586,7 @@ void tst_Dumpers::dumper() //qDebug() << "FOUND NS: " << context.nameSpace; } else if (m_debuggerEngine == LldbEngine) { - //qDebug() << "GOT OUTPUT: " << output; + //qDebug().noquote() << "GOT OUTPUT: " << output; int pos = output.indexOf("data=[{"); QVERIFY(pos != -1); output = output.mid(pos); @@ -1594,7 +1594,7 @@ void tst_Dumpers::dumper() int posNameSpaceStart = output.indexOf("@NS@"); if (posNameSpaceStart == -1) - qDebug() << "OUTPUT: " << output; + qDebug().noquote() << "OUTPUT: " << output; QVERIFY(posNameSpaceStart != -1); posNameSpaceStart += sizeof("@NS@") - 1; int posNameSpaceEnd = output.indexOf("@", posNameSpaceStart); @@ -1610,7 +1610,7 @@ void tst_Dumpers::dumper() QByteArray locals("|script|"); int localsBeginPos = output.indexOf(locals, output.indexOf(localsAnswerStart)); if (localsBeginPos == -1) - qDebug() << "OUTPUT: " << output; + qDebug().noquote() << "OUTPUT: " << output; QVERIFY(localsBeginPos != -1); do { const int msgStart = localsBeginPos + locals.length(); @@ -1741,8 +1741,8 @@ void tst_Dumpers::dumper() break; qDebug() << "MSG: " << fullOutput.mid(pos1, pos2 - pos1 - 1); } - qDebug() << "CONTENTS : " << contents; - qDebug() << "FULL OUTPUT : " << fullOutput.data(); + qDebug().noquote() << "CONTENTS : " << contents; + qDebug().noquote() << "FULL OUTPUT : " << fullOutput.data(); qDebug() << "Qt VERSION : " << QString::number(context.qtVersion, 16); if (m_debuggerEngine != CdbEngine) qDebug() << "GCC VERSION : " << context.gccVersion; From 0bf27af0a718887248229b9693de16f150a38bf3 Mon Sep 17 00:00:00 2001 From: Serhii Moroz Date: Fri, 18 Aug 2017 18:58:51 +0300 Subject: [PATCH 05/63] TextEditor: Fix blockSelection painting in "Text Wrapping" mode Change-Id: I1ba4587ce4f8e88a1c81c5ac3c9d6dac582bd71f Reviewed-by: Christian Stenger Reviewed-by: Eike Ziller --- src/plugins/texteditor/texteditor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 06f02615eba..f237c0f7ed8 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -4298,7 +4298,6 @@ void TextEditorWidget::paintEvent(QPaintEvent *e) for (int i = line.lineNumber() + 1; i < eline.lineNumber(); ++i) { rr = layout->lineAt(i).naturalTextRect(); rr.moveTop(rr.top() + r.top()); - rr.setLeft(r.left() + x); painter.fillRect(rr, palette().highlight()); } From 5e89fae10f95a83d5fd098e39523dee71c9c6b84 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 12 Sep 2017 18:55:14 +0200 Subject: [PATCH 06/63] Unify the dimensions for all mode/action bar icons Having icons of all different kinds of sizes makes it difficult to get the painting right in all cases. It definitely fails when the szsytem is running in multi-monitor mode with different scaling factors. Unifying the dimensions makes it possible. This change should not cause any visual difference in a purely scaled or unscaled screen. Task-number: QTCREATORBUG-18869 Change-Id: I3a864c9a86036b4f4f3b350a489077b247ca85b7 Reviewed-by: Thomas Hartmann --- src/libs/utils/stylehelper.cpp | 11 +- src/plugins/android/images/androiddevice.png | Bin 211 -> 216 bytes .../android/images/androiddevice@2x.png | Bin 255 -> 259 bytes .../baremetal/images/baremetaldevice.png | Bin 184 -> 185 bytes .../baremetal/images/baremetaldevice@2x.png | Bin 277 -> 280 bytes src/plugins/coreplugin/coreconstants.h | 2 +- src/plugins/coreplugin/fancyactionbar.cpp | 8 +- src/plugins/coreplugin/fancytabwidget.cpp | 6 +- src/plugins/coreplugin/images/mode_Design.png | Bin 1779 -> 1565 bytes .../coreplugin/images/mode_Design@2x.png | Bin 6227 -> 5116 bytes src/plugins/coreplugin/images/mode_Edit.png | Bin 426 -> 389 bytes .../coreplugin/images/mode_Edit@2x.png | Bin 3157 -> 1081 bytes .../coreplugin/images/mode_design_mask.png | Bin 223 -> 218 bytes .../coreplugin/images/mode_design_mask@2x.png | Bin 369 -> 362 bytes .../coreplugin/images/mode_edit_mask.png | Bin 109 -> 110 bytes .../coreplugin/images/mode_edit_mask@2x.png | Bin 118 -> 117 bytes .../debugger/images/debugger_continue.png | Bin 2812 -> 2601 bytes .../debugger/images/debugger_continue@2x.png | Bin 2271 -> 2222 bytes .../images/debugger_continue_1_mask.png | Bin 97 -> 97 bytes .../images/debugger_continue_1_mask@2x.png | Bin 99 -> 101 bytes .../images/debugger_continue_2_mask.png | Bin 147 -> 157 bytes .../images/debugger_continue_2_mask@2x.png | Bin 192 -> 202 bytes .../debugger/images/debugger_interrupt.png | Bin 1231 -> 1193 bytes .../debugger/images/debugger_interrupt@2x.png | Bin 1442 -> 1402 bytes .../images/debugger_interrupt_mask.png | Bin 98 -> 100 bytes .../images/debugger_interrupt_mask@2x.png | Bin 101 -> 105 bytes src/plugins/debugger/images/mode_debug.png | Bin 2061 -> 1756 bytes src/plugins/debugger/images/mode_debug@2x.png | Bin 6535 -> 5524 bytes .../debugger/images/mode_debug_mask.png | Bin 285 -> 282 bytes .../debugger/images/mode_debug_mask@2x.png | Bin 547 -> 531 bytes src/plugins/help/images/mode_help.png | Bin 1445 -> 1328 bytes src/plugins/help/images/mode_help@2x.png | Bin 5215 -> 4348 bytes src/plugins/help/images/mode_help_mask.png | Bin 316 -> 312 bytes src/plugins/help/images/mode_help_mask@2x.png | Bin 629 -> 614 bytes src/plugins/ios/images/iosdevice.png | Bin 196 -> 196 bytes src/plugins/ios/images/iosdevice@2x.png | Bin 349 -> 351 bytes src/plugins/projectexplorer/images/build.png | Bin 1239 -> 925 bytes .../projectexplorer/images/build@2x.png | Bin 2803 -> 2305 bytes .../images/build_hammerhandle_mask.png | Bin 165 -> 173 bytes .../images/build_hammerhandle_mask@2x.png | Bin 240 -> 258 bytes .../images/build_hammerhead_mask.png | Bin 183 -> 183 bytes .../images/build_hammerhead_mask@2x.png | Bin 228 -> 246 bytes .../images/debugger_beetle_mask.png | Bin 198 -> 207 bytes .../images/debugger_beetle_mask@2x.png | Bin 357 -> 375 bytes .../projectexplorer/images/debugger_start.png | Bin 2094 -> 1677 bytes .../images/debugger_start@2x.png | Bin 5121 -> 5095 bytes .../projectexplorer/images/desktopdevice.png | Bin 181 -> 187 bytes .../images/desktopdevice@2x.png | Bin 227 -> 233 bytes .../images/devicestatusindicator.png | Bin 158 -> 157 bytes .../images/devicestatusindicator@2x.png | Bin 265 -> 269 bytes .../projectexplorer/images/mode_project.png | Bin 1658 -> 870 bytes .../images/mode_project@2x.png | Bin 4227 -> 3256 bytes .../images/mode_project_mask.png | Bin 239 -> 235 bytes .../images/mode_project_mask@2x.png | Bin 410 -> 399 bytes src/plugins/projectexplorer/images/run.png | Bin 1719 -> 1152 bytes src/plugins/projectexplorer/images/run@2x.png | Bin 3058 -> 2832 bytes .../projectexplorer/images/run_mask.png | Bin 177 -> 179 bytes .../projectexplorer/images/run_mask@2x.png | Bin 273 -> 291 bytes .../miniprojecttargetselector.cpp | 16 +- src/plugins/welcome/images/mode_welcome.png | Bin 1243 -> 1100 bytes .../welcome/images/mode_welcome@2x.png | Bin 2282 -> 2271 bytes .../welcome/images/mode_welcome_mask.png | Bin 100 -> 101 bytes .../welcome/images/mode_welcome_mask@2x.png | Bin 106 -> 107 bytes src/plugins/winrt/images/winrtdevice.png | Bin 163 -> 164 bytes src/plugins/winrt/images/winrtdevice@2x.png | Bin 235 -> 239 bytes src/tools/icons/qtcreatoricons.svg | 852 ++++++++++-------- 66 files changed, 496 insertions(+), 399 deletions(-) diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp index fd270a5a860..b70ea7b07c4 100644 --- a/src/libs/utils/stylehelper.cpp +++ b/src/libs/utils/stylehelper.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include // Clamps float color values within (0, 255) @@ -397,7 +398,9 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter *p, QIcon::Mode iconMode, int dipRadius, const QColor &color, const QPoint &dipOffset) { QPixmap cache; - QString pixmapName = QString::fromLatin1("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height()); + const int devicePixelRatio = p->device()->devicePixelRatio(); + QString pixmapName = QString::fromLatin1("icon %0 %1 %2 %3") + .arg(icon.cacheKey()).arg(iconMode).arg(rect.height()).arg(devicePixelRatio); if (!QPixmapCache::find(pixmapName, cache)) { // High-dpi support: The in parameters (rect, radius, offset) are in @@ -405,9 +408,8 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect, // return a high-dpi pixmap, which will in that case have a devicePixelRatio // different than 1. The shadow drawing caluculations are done in device // pixels. - QWindow *window = QApplication::allWidgets().first()->windowHandle(); + QWindow *window = dynamic_cast(p->device())->window()->windowHandle(); QPixmap px = icon.pixmap(window, rect.size(), iconMode); - int devicePixelRatio = qCeil(px.devicePixelRatio()); int radius = dipRadius * devicePixelRatio; QPoint offset = dipOffset * devicePixelRatio; cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)); @@ -415,7 +417,8 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect, QPainter cachePainter(&cache); if (iconMode == QIcon::Disabled) { - const bool hasDisabledState = icon.availableSizes(QIcon::Disabled).contains(px.size()); + const bool hasDisabledState = + icon.availableSizes().count() == icon.availableSizes(QIcon::Disabled).count(); if (!hasDisabledState) px = disabledSideBarIcon(icon.pixmap(window, rect.size())); } else if (creatorTheme()->flag(Theme::ToolBarIconShadow)) { diff --git a/src/plugins/android/images/androiddevice.png b/src/plugins/android/images/androiddevice.png index f72af6020b17224f2499aafd51aca0de37b79a4e..fd68e6aa3aa2b1940a13644b5f6f6642c30a8b51 100644 GIT binary patch delta 165 zcmcc2c!N=~Gr-TCmrII^fq{Y7)59f*fq_8@gjtvw7#L1uihZ1@Xj7f$>EaloaXz`C zoloL~c;)H?3`{=XA1L)pC^+!zeQJ2l!y)rvambP0l+XkK98x-g delta 160 zcmcb?c$rbLGr-TCmrII^fq{Y7)59f*fq_8*gjtvw7#JEu(vMG6v?)vUba4#PIGro%g&x%tGjT+JfZhH9E|32tKQ3ONWII(#S_>hxyWQe zAdiZm>&3JgH&!SvZc9)xQ*l1wzcIv+rzSiz`#mSIKJ3dSc(UAlN1tZP1Vm?dmUlDx_GfLZx$!&wPcZd)FK1NjXK zj?9ZbNKf#%(BOXQM^nHr(}#NJU%N2QncKR;eevI8j+qP$MVvF={9Lqx7vwWfS3j3^ HP6$jIR*xX22U5q5R22vKl}v@c*0b9 zJUYs}z7-oNF!ueO;l;;!#9X0KrE#x>mxYj2fCCeIn@}5@$$^GdEGgC=B76&Ee1Zd} z2BZo4aE5h%nA!A7tVV3%ET?&{UmYF4vebwiIUwM2K&eDEV$nuBjU96NCURmfo;;mR k)h9iJzIfkrR=Um1Q2wQ1DYM9~?;tmMy85}Sb4q9e02EL;`v3p{ literal 184 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=dQTU}5R22vKl~XCE`&2O z3oUAG`YXfZ(U5GvtI3(^Bd>>oXM+ALroI+7kqHMHmo+S8V)Kp*A7UwKgEYHZGpU(17LPR;E}+x0I{wtk)lRt~uPKadEE3 jj_Freocmp@8!Ckv_Obnys(jn;26B?8tDnm{r-UW|Cm=cW diff --git a/src/plugins/baremetal/images/baremetaldevice@2x.png b/src/plugins/baremetal/images/baremetaldevice@2x.png index d1341f90ee688a8ff1c3e8b942e56b1d360d2782..f99932ab5e4a2dba3fb9600c8fa92b1abdb31bce 100644 GIT binary patch literal 280 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=8;_dQ)4Ln02pz3$7`tRTSp zpuFMI)Q#aUnEV3rQX?l7+>+Yqvb!kpX}Z9QC5d8rCh;k8XL>5cHA9A7Jri;Pxu*6pXlZ`VxuDV|n zxbFUa>)v4gn{w(c6RLw)GL7fvKMAnn^su(&bo~>3At$`!`N`7@E=()tJb||7GU3C?8L^wW{iy^3K-w i{}o^IpSf&_=M&~#DNHY=_dBludD+v|&t;ucLK6U2Ty(Gi literal 277 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4h9AWhJGeJCI$wEJDx6%ArXh)PBY|dHsEpn z&p6AkBW|Iyg=4YyEW;qbXcxVUempG+>^_>VKbgHBE&oxkD4oABfI*#&;blJK8x{`U zw9@*I4ROsA-dQ?i1la!Vd6WB#O=pF_kWzzNuB~FU^JIpGHQ(j*JIFA242KvX7WE(|n?|&ZCQBQX#swG1hf^wsXJQ9&a#1bh&o*BYVbA dp$y9zY8ckUeL3^dGO`WiUr$#*mvv4FO#m@4XQu!F diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index e5a612d5949..aa9b9fbbc25 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -207,7 +207,7 @@ const char TR_CLEAR_MENU[] = QT_TRANSLATE_NOOP("Core", "Clear Menu"); const char DEFAULT_BUILD_DIRECTORY[] = "../%{JS: Util.asciify(\"build-%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}\")}"; -const int TARGET_ICON_SIZE = 32; +const int MODEBAR_ICON_SIZE = 34; const int DEFAULT_MAX_LINE_COUNT = 100000; } // namespace Constants diff --git a/src/plugins/coreplugin/fancyactionbar.cpp b/src/plugins/coreplugin/fancyactionbar.cpp index 6cbaeea716b..206e5e4d6ed 100644 --- a/src/plugins/coreplugin/fancyactionbar.cpp +++ b/src/plugins/coreplugin/fancyactionbar.cpp @@ -178,7 +178,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event) const QIcon::Mode iconMode = isEnabled() ? ((isDown() || isChecked()) ? QIcon::Active : QIcon::Normal) : QIcon::Disabled; - QRect iconRect(0, 0, Constants::TARGET_ICON_SIZE, Constants::TARGET_ICON_SIZE); + QRect iconRect(0, 0, Constants::MODEBAR_ICON_SIZE, Constants::MODEBAR_ICON_SIZE); // draw popup texts if (isTitledAction) { @@ -203,7 +203,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event) painter.setFont(normalFont); QPoint textOffset = centerRect.center() - QPoint(iconRect.width()/2, iconRect.height()/2); - textOffset = textOffset - QPoint(0, lineHeight + 4); + textOffset = textOffset - QPoint(0, lineHeight + 3); QRectF r(0, textOffset.y(), rect().width(), lineHeight); painter.setPen(creatorTheme()->color(isEnabled() ? Theme::PanelTextColorLight @@ -218,8 +218,8 @@ void FancyToolButton::paintEvent(QPaintEvent *event) // draw build configuration name textOffset = iconRect.center() + QPoint(iconRect.width()/2, iconRect.height()/2); QRectF buildConfigRect[2]; - buildConfigRect[0] = QRectF(0, textOffset.y() + 5, rect().width(), lineHeight); - buildConfigRect[1] = QRectF(0, textOffset.y() + 5 + lineHeight, rect().width(), lineHeight); + buildConfigRect[0] = QRectF(0, textOffset.y() + 4, rect().width(), lineHeight); + buildConfigRect[1] = QRectF(0, textOffset.y() + 4 + lineHeight, rect().width(), lineHeight); painter.setFont(boldFont); QVector splitBuildConfiguration(2); const QString buildConfiguration = defaultAction()->property("subtitle").toString(); diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp index a87041ef579..cc0da7b7533 100644 --- a/src/plugins/coreplugin/fancytabwidget.cpp +++ b/src/plugins/coreplugin/fancytabwidget.cpp @@ -25,6 +25,7 @@ #include "fancytabwidget.h" #include "fancyactionbar.h" +#include "coreconstants.h" #include #include @@ -324,7 +325,10 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const tabIconRect.adjust(0, 4, 0, -textHeight); const QIcon::Mode iconMode = enabled ? (selected ? QIcon::Active : QIcon::Normal) : QIcon::Disabled; - StyleHelper::drawIconWithShadow(tab->icon, tabIconRect, painter, iconMode); + QRect iconRect(0, 0, Core::Constants::MODEBAR_ICON_SIZE, Core::Constants::MODEBAR_ICON_SIZE); + iconRect.moveCenter(tabIconRect.center()); + iconRect = iconRect.intersected(tabIconRect); + StyleHelper::drawIconWithShadow(tab->icon, iconRect, painter, iconMode); } painter->setOpacity(1.0); //FIXME: was 0.7 before? diff --git a/src/plugins/coreplugin/images/mode_Design.png b/src/plugins/coreplugin/images/mode_Design.png index 268376e5fe745a6e69f7f9c835f3785ba0a8cf71..9f155db22ad2819183074ca2ff7f7212e812b206 100644 GIT binary patch literal 1565 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4mJh`1}k^&LktY8Pdr^5Ln02pyY4bg-P7@VKwg zD5bcgLFvRMpNBTz?gj6weYdrKOMOJ-vj0E4_f>vUo4(tB-pA^9v74SG*RH9&mbQ0s zjf%BL-=sIHKT8bveeY@8z;SZnPK9qrmWv+m>0x$F{Tlh?X2n7YrW++*$&r)0w{HBN zBUoi~0dMb*U?$xO@+bYc12;qC9ispp1b&L*)iSs&NYXe4T8Iq+1%0$Ost$0 zZ(04GI3cKE*0F25b|#(B(NX32znlGuK;b#Db@noREE~Sm3gqsu?p!nPpyn4||Hb(k zQnI$nEFUG-&aIs>XP%?*_UdcK&I0r2hl!`%-yX#HyU*G$T9PL>XkwJv?9`3E>ES-A z>C+dku4l4kp8P^B^R?WuBUjGc_SxrHs=NJPtwhrehqNZ?)a8v{%jD}e-{-gFob@=z z{N=osElE{rb*ge{w(iyMC9HlQyXblBUL$9ZFw6G6>}Q_Tgk0TM_uNRZSiM*zi9ax{GSiz zzCL*4hltcH>xvnF{~r-J!aD!1_QZ#YEPi1ckIqXR4(ViTGMJzJe}O^aN&gp_J5xP; zs=KbgZO(Wp!?ZnF;OyGH60)MjzU%2K&`W3l4gsfUiJYKIGdRYOzA;i1P-q#b<+OtoRXAb!qYPC++f! zr!l;mwQEITK?YBWzk1UIr_39yA;vWatd{j91bfPa3%4z5Il$7Wp?7WWXR*U)QjaVb zRkCXAef7(XN5JJtW%ZAD(aoP;WLF55iu&v>?btSj(bDio5${%&>0-Z`{`9nWcAQT8 zFzrQXv9{9rn-7v%D>(M_ z%8t+fIRB-c(pdg`(SvE)N_?jj|I9Ysu`!y*-JHYGFNVQKt+=7)UdG0}xAj-Q`-QVk ze#f2`cW-gWB#-=*_;QCCJ9*y8NATMJ4YkQz^SzVoFG`whwk33UA}qq=a#i=b(L&N1Etq>D#@Gvc-0+zJmfpKRLGO?eVjXl zyQ~v+QpBeyKlfCX)SeI@(rW+6NW%z91C-SHMgp+lSX)Av=&mm|LPk}rM?MJb+Ed?9>||kSc`+v^XVKZSXBVzt-~aaZc4uE-UM?=K z2~(yV=@QjWx_>d9qwORIPkqPigC9N4>NQTcZ@nC>kRii_XhQ}eT^ iQ&s+T^564c#k1btcyY~B&zXUNfx*+&&t;ucLK6Uy^4T^3 literal 1779 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 im*2nrc>TqX^lFGOM literal 6227 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 literal 426 zcmeAS@N?(olHy`uVBq!ia0y~yU@%}{U{K&-VPIhRch`720|R5Br;B5V$ML7r_Ie$0 z5IA1n=&)g%C1=<#nI<6}zYAVEx>wvS-iVwFIuiBgfE&yFgYANW_Z{+zcb<-Va(K?o zH+hrZ&PlUxoBRLFpY*n`s=h*r`s;h8?*E$^GEazUt@gf?<~J)&eQR>~9mlQ^t#b1B zd`%~&-&=1hZ}a}!a^=AS!3VAnD+`5G+=^;uf7xRklo9;wKr?qk=)COhoWiW`bCoU5 zmhYCC@^a#hj#L)^`cL{ZqRl!4AI#V-v?5};&s5htoDa6?9EtzDacQA8L#Dy~$tfov z9y-hCteWHAAW{)yAU=7EQGTfFB>rdGyL_m*KT{d&4*Q!d7a7O z#o`XvcE+nR@Z4N;@vdaTg!Qj;E`)Aj5d7=Pyy00dB4|zDI)+VUif10y^S@h2GR}2gc44$rjF6*2UngC!`y9fXP diff --git a/src/plugins/coreplugin/images/mode_Edit@2x.png b/src/plugins/coreplugin/images/mode_Edit@2x.png index d223679dc36605d6f16ef8899cf7f87b2d3a41f1..032d37a222368b091f2f08570b1d61749e52835f 100644 GIT binary patch literal 1081 zcmeAS@N?(olHy`uVBq!ia0y~yU~pkzU~uAKU|?W4t*Bqjz`(#%666=mz)&{%tOWxD z^CwRi$B+p3w^wc!Es7Fhdrc1~9mFw+!s>|~vj`1hf=YHOG^8f2Sd-klEV`Fcx zKmGLb<;#yI8O}d1FTeZ^=M$b}v!#Cpp5-K)EnILS@>oewo8oiH%Z5CK44K&>YqsrT zG8UZiW>R_2$%TfEitE=uPWiM-XxG{ht$3%>X@8wsoP4GoSRJ^_^*yh|qdm^vYWC_A zpKL$%cKf5}0^V0RrgS{gXueQ#U9s#K=abOc{LgDoS7mNKr(^u^<_y15SzVrEvuYFO zIFwD5d->(UhJ`1tRfM?mHEca-Y@@IL?zqt11yZm4H=oVr(b!b&-m04CVm2$)$;G7m za<_utVhd5vC#N!&ZZXs0cyumEgz?};4~^~z3*~Pem{-3vKuh8zi?>F2l(fK+*UTN- z3Fkx(KTzMaZO8WKLC!&;2}Nyz`fGayMQ)a!nk6$M&+2Wi|C*FA2d7_GX3eth)uhveYw}5oS*k* zLqGH32Bp&oj0i&&q@ z5-+6+QckY751r$-=u-I=$5Ss@4tj~2NbEQi)VM5rg)_&d7_C-L`*%0DrSV=3JTB7O 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 diff --git a/src/plugins/coreplugin/images/mode_design_mask@2x.png b/src/plugins/coreplugin/images/mode_design_mask@2x.png index f4eced6284dc536aa9a63a2e334b808d6058aeac..2aef9018a8ac9d6a189a12f2fc2e982f8763ffe1 100644 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=AUhMq2tArXh)UR&$O>?p$e zKzWwI`i3OOhYBYag@-6qFsgWp@&_KCJz;^T+Uto^XRP9#rN@~jeQ8N^LgJ0P)^G1@ zo}p&U|KaJG^K)f()JJ%DI0v&68&D{u}0! ztp2IwL-D-Iw=p|Y*e?7sZ`<>1AJcqhhIblI^7$UroK)C&%uMChjiw{gi7tsOg1v%H zA#My8C5;xDxVU6{blegU*n82PV{yBIn|NjB*?+FCq1}=b7q|CFE^gk_FR{4UCcuq- z=fWPdO_ob~%#89oa-uAyW->~|-aBvZto6cTckLgETgl=pZ>y^){%)^fT>sR$_4kaO Q+@L`8boFyt=akR{0G*bW-v9sr literal 369 zcmeAS@N?(olHy`uVBq!ia0y~yU`SwKU~u4IU|?W45U+cQfq~J&)5S3);_%xWx_pNW zL=JpZ_qZV%z$3!f#M0}au!CU|%TYyxJ1s1}mmW-n;x#jVw=zy#KR;$g;xAXmk5Tje z887N{tU2{QeKzNB;qPhcPkvA3zH@u)oO-imZw`F_!x*KWcVJCFJJ0Wo16%r8dwzQy z*wfFbP0l+XkKn3$co diff --git a/src/plugins/coreplugin/images/mode_edit_mask.png b/src/plugins/coreplugin/images/mode_edit_mask.png index 8e2a971f15ff7559d95b1d3e4e661e2aa0d15ca4..51197249c0a5b6aaf71a14b3093a39b7ae5ab7a4 100644 GIT binary patch delta 96 zcmd1JQ|t`zbLZuf;$mQ6;Pv!y31VPiPy%5_W(EcZhR&Id6BR`*ls#P>LpY+7fAF)g wOLQpyH#E5MSn=uq2MP5GI(^MYN|@t>7}&oSSugbK*#^?)>FVdQ&MBb@09d{oRR910 delta 95 zcmd1HRqPD#bLZuf;$mQ6;Pv!y31VPiFkoO{P+(+cU|`6T%8Z|=C~B_c>Eal|5uN;l zpN;28K)r;-E6%`g_8&gT323*sA9`hUM}*-+&(w*V7V(uaFfcH9y85}Sb4q9e05jPe ATmS$7 diff --git a/src/plugins/coreplugin/images/mode_edit_mask@2x.png b/src/plugins/coreplugin/images/mode_edit_mask@2x.png index d683f154e0e4a477d7b69df010beabe8245d892c..389ac6dc4e31181cfece228f820ba155e633ac8e 100644 GIT binary patch delta 103 zcmXRbRqPD#bLZuf;$mQ6;Pv!y31VPiZ~w)h?MNtQBPZ!4!jo{=T z{VWn}^3R!>1#a+bwEzGApZSL6m202b+0!4qT`0`X*T%!naK$YCbBWhNaRvqk22WQ% Jmvv4FO#s;AAU6O2 diff --git a/src/plugins/debugger/images/debugger_continue.png b/src/plugins/debugger/images/debugger_continue.png index 6ec4eddc1a1a9f725e2ae30a8a059fa5388fdfb0..e15d7e72624b9904a77949c5aa68a1f8d9a26f96 100644 GIT binary patch literal 2601 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 literal 2812 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 delta 77 zcmYdHRO}4!bLZuf;$mQ6;Pv!y31VPikN{yuW(Ed^TRYe9o~S6TDx3V{|9^XC4*Lzu f`Pyc(FJ*N6V8MObP0l+XkKHFFkM diff --git a/src/plugins/debugger/images/debugger_continue_2_mask.png b/src/plugins/debugger/images/debugger_continue_2_mask.png index 756ba959f032de3914cdafaa499a481eca8d96b7..8b83259ed131f59f09913ee6673e36d2454f605f 100644 GIT binary patch delta 136 zcmbQtIG0heGr-TCmrII^fq{Y7)59f*fq_8@gjtvw7#L1uihZ1@C>Q7H>EaloG4bsA zgS-q19L|9p+6GO^228)tKXK&0W#91aN03w2+KuXy1ll8Xo71~8vrs#Ofq{X+)78&qol`;+07F14+W-In delta 126 zcmbQsIGItgGr-TCmrII^fq{Y7)59f*fq_8+gjtvw7#M^i6;4l7lnb%855PFmUM_|dhuwmGiM!ah%$H( dy}|qkqoK6ZnObJ9-wX^444$rjF6*2Ung9U)C4B$@ diff --git a/src/plugins/debugger/images/debugger_continue_2_mask@2x.png b/src/plugins/debugger/images/debugger_continue_2_mask@2x.png index a4801fa6baca4853a25997928f88fd97c01b8805..860f76ca187e9337659041775764658c5b8f00c6 100644 GIT binary patch delta 182 zcmX@Wc#2W6Gr-TCmrII^fq{Y7)59f*fq}sVgjtvw7#L33_BBpal&dfEba4#vIR5s` zM&1Sk5$1~#agBl!5BnedO<%;^B(!dk?pP2~* Q0|SGntDnm{C#HlZ0HxqFOaK4? diff --git a/src/plugins/debugger/images/debugger_interrupt.png b/src/plugins/debugger/images/debugger_interrupt.png index f61bf0881b9b16b41f620054ea4240a4e34c4656..fccdf1149efcf00a2850041536c5b823bced3f1a 100644 GIT binary patch literal 1193 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4mJh`1}k^&LktWo1)eUBArXh)PR-8Ph|n-=6R z65pKgMJr5lg`n_FlibTGujbU7-M;((_wzf|=PIiT*I#bszV0UYhP$2l{6m}P#dY`J zfBt=N&a*G}6Yt~{e*I;>M!Gj??c6^HqW1VaJG||g?QOZ3?^RpN=EyzXG1*+?L$T$b zntjXGR-SK-W;HaA?m2q8V!_AAKQ(nio2GkRzP3rep~lSn>ZYf6b{2^?u?o5{1kQP# zv3&R67hANF^7iF?{A;uCy||hFzbpZ^$p_Z(avo+_!^$Y=n8}^AJhyk|CF7+5QNF8o z1~HX2iB1vV`f*LDW!giZzSWN#%GZq(NSdk@aabo}^2b`fI6on) zWgn&=ObUG)TV=pP4KX2}aXH5+v3u1$9jE)Ml zRZcp&urT}W>AC4u@2q!!&enRauVT2q=ix-bUuGG!8fB&5wiGQtDiC@35t9p8JV_*Dkk920asNK^{wXX}D zcD+B>k|U_)LhJ5i0r$tp7Jd2l?SAR`u3a+mf~^i=f8C%f=p zlT-FOym}RW@y@5@$7hTtoe#ctk@5Pn+`@ZDl=$*Gv)S0%4`=KNQgG?|d-(J(ojtXJ zbJhEm|8X2E%u#zi{XB?bj+<4jRk#JpnzU{xi5AT~*zk8&zAE+g>euqWE3P@Nd-+!P{ok5Z>09m{S>@&J^?ahFzfsv&k;lo+ zWhE6JIuWX7HSb=wrR>?0bamU>_c6cNm#1Y#W{WzUU37|j?fo}CCTrq0m=}L^X!k9R z?>Tzf<6Hcs5UaB%Ud*_nx6*c7%}d#>?RCG__1~Pf^;$_;8J9zF@MMNJx3}k8J6!*{ z@om4&uP3eIW;t0mw^qNG`^Wt@KU1{fy4l{H6D`kX`u%VE$MVW!M||q}9lZ<;3=E#G KelF{r5}E)iI6)2o literal 1231 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 GLK6Tc$eT_8 diff --git a/src/plugins/debugger/images/debugger_interrupt_mask.png b/src/plugins/debugger/images/debugger_interrupt_mask.png index 87f195f5c08cceab8dc5fed8e78f8ad039638806..52f4f275b9fdf3a6a4f4269351791062f4ed8387 100644 GIT binary patch delta 86 zcmYdFQS1!xbLZuf;$mQ6;Pv!y31VPiPy%5_W(EcZhR&Id6BR}EBt2amLpY+7fAF)g mOLQnn@?W{!dt}R815SqDMvd!N?c5^^QtavK=d#Wzp$PyekruB2 delta 84 zcmYdEQtS-ybLZuf;$mQ6;Pv!y31VPikN{yuW(Ed^TRYe9o~S6QBkt+q7{Vc&{OA0E m1009=mDUBb9zN52i6KixTk*oD={*b#3=E#GelF{r5}E*RM;MC$ diff --git a/src/plugins/debugger/images/debugger_interrupt_mask@2x.png b/src/plugins/debugger/images/debugger_interrupt_mask@2x.png index 6c477085d7be89d34dd14090d244697502c0f1e4..c7794000177e07d87c4e697d378f0fd0c6da517a 100644 GIT binary patch delta 91 zcmYezRO}4!bLZuf;$mQ6;Pv!y31VPiZ~%XzvuhG+yQ|KMkp tmtbS=Zv4sI{8yv{J%8O8tr delta 87 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%0D0WziQyD zWRduMX@b|0`x~uo+TK)r4XmttmZa*iDPmv53!U_R9urJM=W4gM?&*}hEN$R>cSZB* zXN+kXTMch4)=W;xDp3dsS{n64C)G0i?0l!KGMlsZ|0+~eh&R4!d?k2wj-lB3iO)|2 zNpNRAsdSn0BXG;Vsu=mr9%29V71ye0JXbnwx!B~R)1SQyjCBiNi=BDO+xEo9U~S>y zmFBZAzb#G+>RjR)_v!QZn)iP^>V2Ok{jPSDPuJxqh>rSTcQ&d7wFMfzI=(C!cd2`kXX#JxfhQucvMEsx@2LN*%ZSee7^R zUYU3K>Qm=_+dnEd6e!qs^V*(&uRG5y-9N7`ak_W?t{+VL|J4sLY%Q`+O?-ZY88kKG M>FVdQ&MBb@0E5l8t^fc4 diff --git a/src/plugins/debugger/images/mode_debug_mask.png b/src/plugins/debugger/images/mode_debug_mask.png index ed72f606c4402abe80a766196bf66a4e96925529..fe7b6819a5b3bf93d21eecfa5f24d7b46339f88c 100644 GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4h9AW26>$jIR*xXhn_BuAr_~TfA|X+@RX}c z>+IAue;68cnt|zS#gv#-7VX46U7;uU-~a#L{_m#y94iiG{GY!3|NsC0+SjGbJ~+F0 zQc!W-dGne7tNW%r*=f#p+dya4l_#vT7VLifpD$M7?CQwQqq=el3qE zMYwy?^d1c_iTTM|kp~+VwIs6cnxx9Zli?*HF>TT8O)S1AgM7N}HZ0UgtZhH)zD~pI z&W6fe@~)otVyfRoSSC#2(71Cr;8Sqot!{-KlNN|y7O6{|QN-FYy}My*hfe#ajjAiR lpT7KWxo*Anp-oaVy%+IAupSWP*G)9(Jo!1Jc3a)AVs3j=%@9)3=|6fl3>*ny)?e~70zyJS#xBnxx zO>&Q=x~A##?=_Qu?tkv#Ij=f-LvO=mEz`=zWv}1;*zYXv@i{9@=u0#EjlVqq6{oN# z`e!f5xS+D)p{jBh+p*^@CTkKLE*{vxw7*T2hbKcyLSovZ?TMVT+LpG=`O?Vi%KX~8 zY2lNuMF)EeHhf#0@j`vY!+A{%lh_zrt65C`gv|J+#Ia8C#Zi;ic$Sa{ng1_O+b^p-{l#)dhTpkbUrbWIoC5jV)78&qol`;+05K|n9{>OV diff --git a/src/plugins/debugger/images/mode_debug_mask@2x.png b/src/plugins/debugger/images/mode_debug_mask@2x.png index 510c817c82103990e2452425f2cfc6cae1522008..5340947ec75c4569acb12d152a2e0065e4f25378 100644 GIT binary patch literal 531 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=AUw>(`OLn02py>?!kB~gO? z!}`0KQ>Pwwd$MJxrS7TLr~D45_9p}fZF19ey_OrRslIfLO3<3qUVJ-t?$TcB+L^Jo zd24+8$KgumQdh9=8YZU{7 z)HPY<^~yiiT-@WV!WHam;mmi2O^Z)fu~<|rp{ z{I>S|6FzIC7^;kYehF+o@6w*X^sjB_v8OVg&!$P+FN*x=IGx2hHEzl?mC6fA^CYLQ z?Mt29xP@o&A=P_lU4^SZneC*O+G|X@ZtW=tDPn} zsl3+j53%*^@9F#GvHZ)OnSoo4HJz6&ES>JW%k+%Lgv^ZS7~UyPOq_YsLbxUtXGE)9 z{(ID;e%6y^ZQRjMO!wvQQDF*GnPBiN`18+vnHSfY)0RBH^srRhRP0kji@M3QUnk#w oESr62U#b3Ky+=xVpTbW_&rsZdfSIj$A}F>!UHx3vIVCg!0K7QvW&i*H literal 547 zcmeAS@N?(olHy`uVBq!ia0y~yU`SwKU~u4IU|?W45U+cQfr0Urr;B4q#NoHs_j(@= z5McPQSyyn4g^26RkUMi$HFdlFXPDabzsXgj>4uvC%h6p|Ll1figt$y;>h*S&xpH>v zZiNncg)X7j32%NT{qa~+8}k0>%exo)rx)!nDCd38SS6#t$m!w0l+^f})l}k5Y|RI* zi2Szg88<($R7kd-m(Z?cP&p_l{HU=uy>5l20NaVuwb3TtZU4?Q>L!_eyV-CZ}!O;zWOamu8h66o@hS* zu;pb=-0ivAn!iML{!4gsecgIb#^haxnTwbjMEEbTFv!|0n9O(QXJy0tX*@fkKgh0F z#Q9;h*c3)7$rlfp=c+7_KJ~~tq4ig~!&<%?k?`g^)63c;C^IZMqBtIPb&l7#(iE6@eFAz7*6l+ zUA=IA!v(3lP{j|8!P@q>(~q8Nl(^j)c}SA8;^do~^4Fa58t(p!e)8P=iRPxqStmHZ z%&#tJIo0o8EB2tf@A+P<)O#s{o6SGX(E-Q6fBrp8?h>oC_86?%35tDBS3j3^P6zt~7W98pGnFx4_|$}s5S8@PimTo?Z^~r3dszELiO%9{ z7ENBE{6fYlH>w}#^iIyL6!>{SBFT2KM?2qdBP-40#<6{(=M379EfrspdB#~OX|CH<>=`aK5>zT+13=kJ+3M z%+6WR_?b!CO(xkkyGc)96ZijDzq2TP^is?55Ci3UK+J^F}Tgt~FM? z_C?9I=X$Ndw;vboY(5b4IyS*Q;q7B_aglT3$y2CF4^_`;+40_hxnEqej4ZE=E!UJN2#&( zt?dM+vsk?rfge1>&^ei=>xgqm|?)~P=dmH+{t1n!aIw>%4?PLvs z$PABg1I5*s+BmOlJzM0nIbi0q8CAyazCWE^v)K3f3OTIEP%eI==i()tB;*}<+2)|e zU#-`IctcB(0apZ-Fiev)g?;(VUx%6rW^iFA4F^Q>$3hR+Rkh$3wdSRbK-!Y zaj?MT14dIPw_3R6C*9e7Lhs?BRdG|U_Zx_2^##0b2{^p-gz=^8Gn+X*JAK6##XNS~ zd9AmLVXm~(qpZ2YHA|Uyd!ATO+$Jk3RkZb*BhTc&hXq(xw0WACHYumOI>zrSIs0)( zh$)}rUlo=tKgomZOPj)Nj~tn!slH$QqmI(A5YDdbHyR%oFJxT0wIrK=O>`OC@7Jq( zemnBj-L?3!igSw4QByyWkef4{cJj6hou1d`GFOMu-|omtz75UGH!PmR08$^$8P1XqMdC+yG&E}=TrxY2fix;ii;&!(mWl>^Y7$V5&ee&w%zuB|nG%oIc zr{DiXdG#LgohpwuRXkW3bCQ93W6ACdwiYLy)?GO9-05>Cw`$rRaUpkq&mX7Pc?Nx# zKj-SyCubk_O}SmDaM5GdH}FLO<4Kk=IV&O;q_bWB`2z{e^fF}>}2??iIErE*L2mXJT;sAyrje8Ab*T( v(xbE2ORWu`?Vo!fd-q&W0kmJPo;hrV#J^Q97A#?4U|{fc^>bP0l+XkK9pifL literal 1445 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}k|nMYCBgY=CFO}lsSJ)O z`AMk?p1FzXsX?iUDV2pMQ*9U+SlvBc978H@y$R3u32_(sr`O*atHJSf;|2xp9Szz~ zw{mQ8jh1$}toD{ayVuYxs(#DLWrk*3O}B1aqVFu6d^y}CN?Q8w#Yxj(1)*_lYkX{mQkiZxi@ zc_+j%>*SL|pVHHVzpI=Snv@~L-RW`3$;hQ>#*=KJ+iS0x%iR6BJ-^A`(c{3%E1~CR ziSE==uhug%e&(?Js?x~`44v2Fca=z9&%fi49?ri;cCLi<|62aD^?%p9{1atlig&$x z&Ru+Zrnue?d8YWM8yl@Yyy(07uV>cct=Bzcor7#;8x`aqM1L-RzgkCcQ$kshkc#Is zjwYK{4USWcPc)gh<#gKY?9}$`Tlw{L-{o|(3(LQ!%P_O-v$EG;zG+d8;Gx5Z6@_*v z>}dG)D|f~Ee3$*X0*4QWbL#MYR5|)t*Td`5;mrLfIbR<-bmNb#?A-L6dDA|4HXJy6 z=1uFgnvBv!y@IFPo!zqxtc+Sx{ii6NPH_oJlBv?aQSj~&gWc`_vOa3UV$-HwsFA!F zxH(|LbY`Uu{nO?tz5INg$$FZO-t`w>Ia%~}{yn1;aQ{L}^8FenF>4=}Ko_qdn@PNd zC+4Of`sEwy;d4P*_v(r3Dw9>kY-3ifwXJ&;E4A*+O!gZularE8adUC~IH?-=Ol8J@ z*GrEdC0(q}W4LX9tN(a-j?2+YUn^eCJp1Eoi1wkcOqwzK<3$YCuGiCk{``64(>Xm4#>9y2?<)7~`k5M{v+lt0-K#VEIEvl0 z^uB%F&Ec*0Nhi%%jV!OWRzUvlnL7d>5TOarSKQNzeN@cOPc#b!$%W6`12E zcwJp>0Vm(H2k(}a1gEL1KYo(`^{L6NXWb2!Mq0Dx&k7cQAj+&IIQ8a@7ZOp?Yb)05 znWFQ+#kp8LsK+gz>57t)Qp9x2wcID%8=Dkd*xB0;X!_2KfAVZPheKier@dRZvQ~e4 z=NcAeBNv%*@WKa;eHK5IH$9*EvnKFvb5p3W&>@AS<)w_NS`$4qo`w6poB4v}s}+|; z;Ud1ri^Dg3UAoo7T&iH%}my?(|V@3}jC+AnDFAtn% zTVF`bJ23WmQGqtUb`ta%l$Nk&$vwys8{k%6W{KDJvqO-Y9S z@?=eJ{e9mQW%#UpBqQf6Sg^;V$>3{@QRp;Pt{ZB{z7)?FTi}rL^H;;xwI^jy>a4u+ zwoI>P&632ehM{7yk(Z|$s_JJ)+`fHdOYD~IXYWtS@h*OR^5nsTjPv~7mYkZ+qNn*F z=kdJFcPli@8ZJ}Z+~vPZ@Mt4b@}PTM4}GP^9ARdh(rQ)qS2B_jdh z)$_ehx8(brKOp_S_SDIxlh#cN`de2yVcv`4yGz(}0kO%a>n~>Z(>+{3BL=w;2!p8x+NvM&r;4Us|2$>B)c?zy{=AFd{NJ?Eo>hWD*y&;CJtHo5 Q1_lNOPgg&ebxsLQ00`x+r~m)} diff --git a/src/plugins/help/images/mode_help@2x.png b/src/plugins/help/images/mode_help@2x.png index ae8db24fd7521aa80701ce25ebc7d603bf74be9c..51e4ed8ff87f5ce8e757a3dd372225f177d1a55c 100644 GIT binary patch literal 4348 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 QPy-4QPgg&ebxsLQ0EuLV6#xJL literal 316 zcmeAS@N?(olHy`uVBq!ia0y~yU@%}{U{K&-U|?V<+`r@i0|O(or;B5V#p&c9{z?fF zR~Z=X!(CPt7q50-_s4Tio2eI1z=A!~IC$&3BqunWjBk=!@JjVd#eot{Mc(WKr_P*b zUOVe3Z_>Ks>mRD$_*<0!fB)W3|NrL*L_bxJIUheal8`~OwDGV z(1m z45xzB4_$WH@VSR=O6&d0+KEyTI}_Jj{h{n9xyb9mJ^pYG@2BGbmTVMT$r;aC#~LIM&1pn`xMVkSn9+R z(eQywi09|jLk-L+f7Gr`SU-=)qVaq9Bc7kF$9WcL?(Z~WIjVoA&Ct@bFUCV@<`Ica zES}8OUyD1~mv<|%gbSHH5e?eo5!=FTf4#N4YmaJ%htwgSzSAC$`YRtky4k{0*)rvr zlp|Apx&Pg-{6|)}R(#@QbUrna>51ut|7ST*6#ZjOiFG*<^2q!Ne^6bai-eV^$mgB{ z$(#EtcrDvROxMlsyIZrIA#GXHlO2LV>K~;pb=kHyIz1N_+Aq6a(J|tzKn>fJsAd&` zrt1Q^IcXo{SdUJUo7ABf=e%JmL(FeSBhwR3N)^0`hm(#uPB>B`Vpt}`n|O;!X#NS0 zCdC=|JQ+F57jt$^kl3KmE|cygd_~o;%b(Fz`vU7n_d@A5#pex+R=#MGt>CrnOZ0fY zDs=Un4VL`d73)(aI~a<77%MFMF4?lh@X_8bhssY9vF?B8|L6A&Y_*stq$Ot@Xll`L zByVxoQz4z?`y7iiH2(F6O))U&*sC0qs^e~WgiobJ&Nai-aB4VP*R)IT|F6${{FNun zxvqL~nwg}?y7&1?+9mmSJdb>r-sszXf98%eC;s|6DW@;xFjGDfHu>6}s@Z4z@>ty8 zSx=I#^VbUeG%@CD@TOS{>ixI1zu?-qk@ID1$sDEioL0BC$(yEJnXoXCgW)Ih2Ay?Z RZJj|0$kWx&Wt~$(699|8{;>c6 literal 629 zcmeAS@N?(olHy`uVBq!ia0y~yU`SwKU~u4IU|?W45U+cQfq}`!)5S3);&Ad0|KtM( zSqE3JE*9&Fa`5H;CzH*4Nhl>%^a@{=^}p$_#B8*tr#UbgiT1C|I=I@zjLqc0w4ZHN zVmhKp2bfyI15P%@Yw}n)9Lvv&_;7VHqxy$`UOQR$f0)6)<)Qgeu>~#sn-hKfCMkKP-&1&yXYiT=R8@=u{l zgoWsoD#?dNo9a()dms@cRCKrG%`cJ@%G7W3LL9{ zHl1$>%AUaDbYh!>^z5H|+#OeX@_V{W&*9!M^-|1lMHDzJc~po6qwIiz#*zE`K0l&Pe#+O5T9ks8y1PaXnLZ4*^Gz#9HVRS zMONz*+a6f7vCdr`wzlZdGu=-*KeSIfuuM?izu_=X9-Crr&z5Lc$J!4Pcenhq|1Upl z5m%wj(j}+PxR{<{R4J1V)tSD?>SwP(SK`tC7gsT{v284$Vj4YdaYO>UkX66ZmRXnD z!r8hCm)`#$e_2hjp<}~??dDkr)tV1|UApJxkN>O9-|0N~-79tW`~8_a&YWNB^;wo9 ztSiAdF2~fcs`Ite-m_`$=JS-l%Z6Gv`fCNAQr-D#dC2=?|7>r{Ez&-6Ol^tyrNXXX ncW+!=*b>O?rYo_vVHyL&I_X){)E63j0;MNUS3j3^P6$jIR*xXZci7-5R22vKl}v@F2tXd zt7KDA*w5ZABqHiy8ZpJdAjge~hsW8)(@{WCReI{O$KjKfq@?RV-XPUK$*N$5mdKI;Vst05PCKBme*a literal 196 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=Zci7-5R22vKl~XC0{jok zRkEol>}Pjo?6L`9ZDV38g~!EtDP!s1IMHC&UXym^x<6ZSYHfSpgd`KyH} zOS9;chuf6I)*O)C-el)t6Y{uhiKItdg=ik@={t)r&r#?5cjC}u2GIur3YOW^RN`10 xXPdJ>2vFcRO;kI=!g{7>v4g_n3wocK7@p<7dKU5W#XOMnJYD@<);T3K0RU~SL<|4` diff --git a/src/plugins/ios/images/iosdevice@2x.png b/src/plugins/ios/images/iosdevice@2x.png index 1e078270c64bd7ef75116a4d444ddcfb521bed28..89bbaf03477915158976ac17a1f7f412c518897f 100644 GIT binary patch literal 351 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=AUYMw5RArXg@fB3T=FvvRL zVe%xD$DWz*fc*b13+K3#1`imG)^`}G%wyE=P&_42_owZHa4Lt#(=-_d74xhUD-@gW zOwhY3)Ww^blsLz2qv9nVJ(22k!Rhak7THiNcF znI7UrrO8ftU8asjp7uN2&OB(7e&k!nwkAC}A;j=Wa>9jpe@DG}p;qOepM5>cEA7tx zD$u!Yzv7Pr43dW?Z74{z;cjhfIDM^xi#M_(j(KA438qWDf(PEqIxgbrbmF{G@uk66 z<$?u;1iHQze zL57Pq_3$ts5%?9EHsN8bs|Vi&MRkF61<3@rK1S~eJOX#O%-m#<(4l^uL0^Sg!uh1Z z0`8qw28!ycvlMnNm@mVeR&bd2gPOka)y;+mt0X=d8oXGqZft%|YwqsK&%d6v^)6oe zX$7P6WrmuDb8H(_bYdjVJ2f&s*kmw|iCJvXb%7Mg4GkvDEFY>JCoEtL)M%9Gm+RHO8kMoouF{@boFyt=akR{0GA1X A00000 diff --git a/src/plugins/projectexplorer/images/build.png b/src/plugins/projectexplorer/images/build.png index e4590537ed8cdcf3880768493d5d458fd75543f1..76bdf9a460c6d3de192038d5963a61d186418100 100644 GIT binary patch literal 925 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4rY+Z%-d_r6q7#LVtSqpVJ%MH0# zuU@@={rVj{b}%q7{Qv)-fq{XEiK#F*TZe(c%gZZ8g)KpWB~^iefq@}c9z?=%PfyQ8 zTW$!q+=#o(kgLj=wOEs(+=#1Ki=otztIUwA%mBoOaGRT(K_Z4+#oCO;+DxT}T&0Fw zB|6Myh9C!*=(3aY#IB;N+yYMtm!N$hMo}Qi=Gp6h6 z>c+>%*VfkFnV%^ktKi|`5gZ&G5fRbS($d;9xwp5sueWE?q)AiVMW=g-&-50b7bv|j zSaxZI!pa!sbxG=*QZ+YK1Z>aN+tm=hyTI^Zso9Y#%d<`P92^|N!ouR>;!;vlQVMF) z($exu$_gs#N=iyvnwr|;oZ8yjy1Kfi(rl*kyjE6L_V)I!uC5^=Az@)*l`&3@X}-

TCPNF?dB0Wx`eJ-N?uA-CN#U^`*PxTU?I%C!}Z}DlD$iwAzQ?LU?^VVA ztMlDfuU@?-&v8w@%i0*3wRsL}*RNlfZLu!La$T;?x?I~0ak85eWjE)VZ{50eTXpdE zWZ7M5a(gr6_qIeI?1(#@r*yO@@mQhqv17+hOh`F1Iqm%P%!{+KuFlQ5HZS+a!n}jA zMuiLv42&f~e!&b5&u*kKFfe@cba4!^IGvmzam(TE;p2?^yFMNJw)S`UjEAAgp&{~{ zk|xcauW#oX7kaQU_w4UIA6FLY=5}@FeLRvKnOf-bhDEwYYg@~;HrFF-=U&R{_ddES zxw1Ozl+t3RKd(1v2SnDJls}JQYwl|MkX5`!E5uyp$wf;eM{yuD6BKzrA=6_;8Poa$?kWJ-hQe^gHI? qS=n!Y(yFvnLeT3+pBj%cI|GAdg7;!!w*@ajY17ly&t;ucLK6VapjfK_ literal 1239 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANMU^E_P~Ln03EotEnpohowN zKQVT}8J)hwNbiN(98T9Aw=b05rN9#w*Tj5UAlCSXOv>hL>#!Y9T}9mP9xJPyI6bJN zCwG_Yy{M&+IGkE6XRDrDd2yjy-KWd@ew@rtvpN1ePGj|Dezq#hlP8Odf8Y82e{S)- z;wr{#3AVPj56X5YW@T}?xw{{HSn%Qd?p?ba0yamj)xIv`;KJx4;_zhmaf6;gD%uKI{VT^aM?dElGY!yNPzIs;b_&cFpZx@@~)KRK_xy8-Er!adOHy1UGe6!g ze)&XuGgt6a=|IWp4NI3UJ(9Ow_}0AsS+i&V_wx33{SDcFV~^!iLt?(#1tZ9d3&qZ`qoMiSLa6A9dByuHm!ZW$zye zA56|&xA9-5z4+s*xHc2-^y%B>CU`CNXcd22WGTKg{p`f>_Z;6Cx9s%!{jt4q`-g7h zsG`@ttbAgwO0p(b>r%bAIXMr0_)y?ilQ(su{kqDnY0dl#itqd}s=Hp!l`mN?bl#A) zE?`Hmo8HRb{ox|rE{m$O`}U+Qzrp@M!Z`iG-gjPeR(Pn)mkE7vKzm}u;;AMqIcMxD zZ_S({An)*hhAQ{_vUv{IKe8C*bsYM~WcT*{zxgY7?rL;CI-Rl2?M&nk(`ue}-i;|g zzG{>_@t){8(Zsm%&-BmzbFN)sFQ~mzB=B5c?x^%qucFN^eS0f|^xi&awz?X%X^Qss zt-BA`Fv#~u6ct>nV_E-F^ojFcncc-pVs1q<|C)OE=F>$fb+y&+#pDm%@Cdc@GvDjB zPUPgtt4fk(FXufx5-D(L8l#=;wkMCD^H#k%KYh|cXQMYK`W{@mck<074&^z2B@)Vx zRB@lT+#r;^%X``;;NqaFHvfsd(naKexU-68jLR)f)f% z9>e>a7CYj<%j`I{sFGoJy;@6#d;H$qEiCc3zHYdX-f(+b#E&-5hQQ{eOe?NhiSUFV zr^ID1Ln8{N9o(ZT_b%#j;tvlI{($}ImoLp@IPiy8!}RO1$-$up3=9kmp00i_>zopr E0PZ+L8~^|S diff --git a/src/plugins/projectexplorer/images/build@2x.png b/src/plugins/projectexplorer/images/build@2x.png index bb2b17ebc4240c17d1dacbbd001e9e9f95290363..b3e3c581a34bd27e563ba24fbe6ef02bbfb92146 100644 GIT binary patch literal 2305 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4mJh`1`FZIn-~~4PI$UFhE&{odn+>_BwUQW zz_5$yZqBAH7kGQlUea1|@yrV4J`IHnExvDhV+Dc@RcA?vhX@!*DRxX;u%J&!B*P)F z`B*~(%ax8!!&ygll0T^i8;1s)n#wQB(lXWhZ~488y^$fwxLxwCy_h)#v!p}&EtV~-*w{l$S!TU)EwldSzb~S^W@E&IeJsQg5SJ( z^W;l<-jr|Wnb>xF9DQ`O`@X-I*RSOV6L!p=II+;)+FCj?GSb7xrzL3R9_`5|_o*%j zfBC*DxKCWWtwrmB>aH90M~)mxxVx)##mbcj4>q$0hKIM`x)t@W*434ji;HW*gb4=< z{yls5Zl2@&sk5|SKiqIjHSPVgXJJbMG~WIG`SalY`|?t~Y^|-WE7q)WDJ?Z+U%7t0 zdvda}|F^I2?(P(Lpjj~YL& z+`cRMXYu=d-+6zTYvmJqHNHJQ)*HNQ*RFS;zI@s9@bTl%@{Grgmix?PdS$4gt$lc= zaeBeKJC<9vZvDu0>GjugTN@jxxOuPd)zFGUndb~Bp$h@R!%8Jq{+X|6Z8& ztY55I-aXRt_E+yVooQ<$z0Q_%o8GRTrm^Pdr89@5*FOCexxdaf>AA+m6~+s%968yx z=#T8`m(MLaGUEyt-A&>BI(7Fn4Ms*r4?n+Ww?DRWi(7bAS6koTrJTmPP%Er$X&0wk z)&AWQ=S@#})GxPAY+PKfur=yzV9UHi(}FTHHJzNNe3y}t;dz#O^PbI?UeUvr?&|{m zc4S`py?C`t`%dGKiVF6wo}MEQ54X2#x9ZNHG)ZVh$g24n9jiZo`cyTyY~@pvm**CH zahrV?v0i;NW1(B+Vy)TvYyUpI8DU^tab=H?oLt}D>hFAu=h)RsS(m?i645QD`>0t? zcjLmJpPz5OxwJp`^RUobjjD67srsUETv9^fz}wr~e`>!rTr=rK3Gb{4zt3!!TeH$AOvr6t=8GuNQ`>_T zZ=Mm9)RGU?%wbPTU$kO{#+tajv%ZUmDdu$C-kvYt)!i*9FV7!kC7UC@dDE#A+gI=i zyUhN%HB9&LvgfJ+CvE@#T~Rz?0=Kx{lfNyYY}UdTJ0(k8UM#u){OcCInd}m5VUm$z zw#tPesT*tr^bbF~DU>lqIR8?0`X=T_j~yb8wzRf>Ow?0SI@Dz#chxv7GR*A&2hZF~ zjfp4D8oQnNzgkFfE!X2#i(iJbX#|*e?H;6h!e^^lYqUw}klZ;*dHO&tnqhIdWXfAI4?P*d%HPg8#{?E&I zxamxuA1~SeD>mpe%daa*8eb0b#Y;%KxmuZC6#en#ZA^@oTF=ylEs49HsxSC+W?tgf z@5Um#5{~Ofrp9QSKd1`jTlfB~WBtYM7Qs>{@m7xiSs zsK>U8xdp+|#%zB<5zSg2160 zGR@yawKf>WG9+d;er&ZcT;{dUa^D^Hze_cD?D6hDoiBA^Z>Hw0;?Rt1C*>0)ME0cT z{N2m_<)B~Eu@A2IzoqcJx$sD+u_V9e*hx_}9==7!jT{o02Zg>FE_P~>xb(hn>8}Ob zEja(CN`2YC(Dizo#+(zJlE(xl<*wy9>|i~i!f@Kj3!8NrYgJeNC}?M!`+E8UU2O^9 zsQV97ByyPUeq#?`((2*T`OsgYK2xEGJNj{9VKtZDv}KR}WOrYjCEDWFd!AWf?t5mQ zsZX|97%uaCzh}0RbNE6jTi25>bR*k7uXkHuIyv!2kpSaUhdJ9DK5or0eDzXuF2C9F zpi-4ZyDcQsum9ydcE&*_-fpHk`^8@g`){>OTsNui@U$5chWpn0e>(KD*YJf-jbQ9; zp^JeV1df%c_ANi8!!hjF+kGW2wR`-ta%1Ta{4b^vXUN!BeQbtYg0%H9vBUiDZ{O5_HXgQZ eIJ&;$Kci^2+m)!ckX{A`1_n=8KbLh*2~7YdEMn9E literal 2803 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 diff --git a/src/plugins/projectexplorer/images/build_hammerhandle_mask.png b/src/plugins/projectexplorer/images/build_hammerhandle_mask.png index 8759e4204fc9d26f1b37c6ede75787b35a310bbf..15e318ac4abdcb48e1c7bf2fcc8713b1aacd3548 100644 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4h9AW26>$jIR*xX5>FS$5R22vKl}v@dbAXy zPTDtlU(-$CtBYuo>TXtPx8LY+S}Nn=3>$B6NYq!F5cL zCwV2;Xib>%AgD2bDXfqqUglvKV{nr@YY3;EXn<<p`RuDaGsdga^Fl2JTB;wI%K59aejf|GDoGDW~Uo$jURfA zlnlB$j%X+BMo1Pdzf9OyvY!pBxio?BQ*a&}5S2Y?91oF$v?y(h+dW+zLp+YZy=cwHWXRL< zaAJ|zHx`A1xi`A1^+j1bn#`<466c?^dd#O7Q@=m;{qWDc1l1 delta 133 zcmdnaxSdh4Gr-TCmrII^fq{Y7)59f*fq_8+gjtvw7#M^i6;4l7w2qbtPqtuYS+)9_Cj$cmgQu&X%Q~loCIGbbC@ug1 diff --git a/src/plugins/projectexplorer/images/build_hammerhead_mask@2x.png b/src/plugins/projectexplorer/images/build_hammerhead_mask@2x.png index 4bc0b4b7fc8c074a5bd0c9336df2c9267d102c91..ec7ecd42b0f2673222140675cc869a864daca782 100644 GIT binary patch delta 205 zcmaFD_>EDqGr-TCmrII^fq{Y7)59f*fq}sVgjtvw7#L33_BBpaG_LRUba4#vIR5tH zM!^OJp4P;3#SGgMSmqwoopCr&=3vw;o#hQ;D*YECDn0++tyi>o)o1)kuyeAvv7DD` z%A>H>hMpU)X)F^Ze=1F!=#p|Ewt`Jyp5ygYNtXz=e}Quwmz;Yrf1S~cIjWmAmZY@# zDpyMTOL@*zzob%rY_gxmo{474oyK1|-qt#~^+*_gk}hJDK4g3O^TpyC1_lNOPgg&e IbxsLQ097SUQvd(} delta 187 zcmeyy_=HihGr-TCmrII^fq{Y7)59f*fq}sQgjtvw7#No7JlQf)(YU_a)5S5w;`H0I zyLlT7cw7UulNh$0;4om0PU-78#BpWG$D$|7LjN;XezJP~;#9-?OI)d^ull`cSjZ&9 zRpHd2E)wC?sLGRZs6kD}<4~gtlbce4icpo(LUpcp)824JJzCWE>*(UPNjowe{cNHd q6xr35@a7))%w2G(W&cCQjnm!<+KXQ}*3H1cz~JfX=d#Wzp$P!`!bcwf diff --git a/src/plugins/projectexplorer/images/debugger_beetle_mask.png b/src/plugins/projectexplorer/images/debugger_beetle_mask.png index b041005b3ae1af80fc43b2a1b63dc6e7992d0047..816aacc33989628571bb6ff034f1c5c2d8cdcfa0 100644 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4h9AW26>$jIR*xXX`U{QAr_~TfA|X+^k_+j zHu<02ul}DyPqP32KR-Dw;T~UFVrY@?TOa=?dGGH|+?#%7U1IpB<@4q? zIzHUb#LQg%S3V}sFf}3J2mg^}7I#0ja;|Fm$<3$AlfbZe!|YFUg;%w_wmw(zv0dxq z@t4!;{7N?nm7c4U@!BWx?!T$=i~0{|?*Hc9|G?m>zFKz2QY(f9?8dGwUz6=YF7~Mg|6d*pq@ytoIo>s?ONIz{8+{vB&A!$GO5<2fxammH!vOS#M(f%kt_$ zp;vSMY6!*ieE&a7@{4`Nv-f}7;sZ+lxF#|(w8(ypQUA^T8stDvS3j3^P6zt~fZ7X4#YO-xTq&79HI%%if#@0RO7CgsU|872o^c(va;c}RH0 zw@+Gd{LytO;mNYr98#<1yc{@M9TbsHroY&U)Xm&0OCh3RyjS+4OdCJn2eFPR|U zwl~h=jPlcp&;^Q4Vxt{;?~KP}r~S|w}qpe5N0 z5~8J#Y~nW9Wt5V$z~0yQF zf_1E$r6w>kZ1yzsWjMjGb!Nb?V_m z{2#PmWt%rVd9GC?3x*Rmua!@@X(=IVDh5!Hn diff --git a/src/plugins/projectexplorer/images/debugger_start.png b/src/plugins/projectexplorer/images/debugger_start.png index 973d1fad52be6086344c76e4a6fbb46ae5f52462..0e7cd1a67238c1795f450e696e9fe62671ef963d 100644 GIT binary patch literal 1677 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 WQh%-xyve}8z~JfX=d#Wzp$Pz1i2V)# diff --git a/src/plugins/projectexplorer/images/debugger_start@2x.png b/src/plugins/projectexplorer/images/debugger_start@2x.png index e29d9b603d4557afb8891e5466f4396d6a28d3fa..ab7cc15f7aef519e58c4fe008cb68d4edc21dd61 100644 GIT binary patch literal 5095 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 Xe9uHbCfAyQfq}u()z4*}Q$iB}(G~ok literal 5121 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 diff --git a/src/plugins/projectexplorer/images/desktopdevice.png b/src/plugins/projectexplorer/images/desktopdevice.png index 2323f95b6f18c45cff4f54dac7d05360f325f433..10909fdd1d5aef157183fc13c7d72019e1cd58a5 100644 GIT binary patch delta 151 zcmdnWxSLV2Gr-TCmrII^fq{Y7)59f*fq_8@gjtvw7#L1uihZ1@sGA$%>EaloF)?{Y zC!fR$b)(P*Mm7oKgG$1Z0uI7DMvX^V*<>u-XK7h z!-uUaVo`?)gR4b=3r~a6nG;IJ2h2)?tnXc9V9-7L;pKLQy%`J)3=E#GelF{r5}E*6 C3@hFM delta 145 zcmdnZxRp_{Gr-TCmrII^fq{Y7)59f*fq_8*gjtvw7#JEu(vMG6)J+faba4#Pn3z1H zlTG4;5JyS_v*CsY2B!v2odXY;*m(}eGaUZy$-!7!A>fymu)&4%G8-Ekp9mu}8(UgR wqoe|})kGGxW)_`^EK&|kG9oUjS_}*+r%zg&Oc5?;U|?YIboFyt=akR{00F)vR{#J2 diff --git a/src/plugins/projectexplorer/images/desktopdevice@2x.png b/src/plugins/projectexplorer/images/desktopdevice@2x.png index 8abf5f330af42f1fa60e6236a1894ce2a1c6d2eb..4fd9ca8a169eb061713eca932e856184ba5bdc4d 100644 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=8;8$4YcLn02py?&bWuz>)} zg-i!N3tnGdw;dNn3`$k(Zq-`2|NpiimZxz;@%84ZEK-Sk6+KiY#w!%-X81_jnHhaA zSQ78EQtF@Vy{Q}@n*Xp6S9=vFJJw{r|fRjv1gsT zthS2T=dKpX>%Sx5Cis>;K;WTVBG1J_eNm?h7YWA_yD(OPd4j(LWAkU+;aJbHw`0v| jJ#{DU#D9#!Ke?Z9t4l7Pf3fFjB*+h*u6{1-oD!M<|F2a@ literal 227 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4h9AWhJGeJCI$wERh}-6ArXh)UO&y-Y#_m$ zpwBS%h0{DnSDjmoHtwedzh(5>)M*_paNhs^=alIp?DxAJnZ7eEyR^W__kZVsD+fKy z*%ur*CD3q;S&osRAv~2qp^-(%L!pu79p9F4`Rn(Xy%_HKuTJRM_~?xDSFKw{*QV&` zDwnKUTF6+zcA@H$6=MPK1@&2KVnXNYz9y?8Qb0sjSNk^Fw02Ehf)FJ3U6W~g8> e`0vB{=PZA@>(q(2l9^tBT<_`X=d#Wzp$PyKWK+lh diff --git a/src/plugins/projectexplorer/images/devicestatusindicator.png b/src/plugins/projectexplorer/images/devicestatusindicator.png index 2b13d25aa266abd425244434948e1b1569eb7a41..44e045cfb4d3c09b6f7314618c5c383b92a78071 100644 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4h9AW26>$jIR*xX6i*k&5R21qFK!fVP!M3g zV3MTl)38JKP}?H|n;9mdK II;Vst08t<{&Hw-a literal 158 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=R8JSj5R22vKl~XCdbA`$ z4KzgVcu!88>bbu?_#mGgo4|v+oz4esJ8S}uGQZ)vB$1%NyqigK2b1L+t{V@yZfw+^ z(5gK_{YjgT%)SS$r#{;r5#+O0)cR5Okmn@3WKmAhO#aSJZiZVw=gHlSYFq=d*wfX| JWt~$(69DNyH0A&R diff --git a/src/plugins/projectexplorer/images/devicestatusindicator@2x.png b/src/plugins/projectexplorer/images/devicestatusindicator@2x.png index 4cb3a5d42da5eea8a75400588b7cc47d08a6bb29..7f03474cd01030cf617b27d98cde56ed19f35244 100644 GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=8;S3F%DLn02py=utU-)XA5Io6ukt8u3Eb_(Ub!w|Qt+jT?-(}knb$MNQFEcv)|E=>C;=fv~;L$({aY+SSL|L#fpT<)RAV|ajpna2P^ zG_1*Am@Sbv#e8$ayQE9zVV52{lrC{B^B1XDn<29NNW(ja$vGDQ6voUD zerX9qLjd~`h7A`P^%yv06{az%G31msuro~LvtV>s$1Hb3F*56Z-o#+P5QXM{PVfDH zGk%+y^0MdmYc9Dd2{-N^ZdOX2|1a*+xqF-4wrVQ*bLj8e{(n}fsr=mjic(>r)Ds{- Ndb;|#taD0e0ssiTVl)5% diff --git a/src/plugins/projectexplorer/images/mode_project.png b/src/plugins/projectexplorer/images/mode_project.png index 67fc37204635ea1a8df516d6a2305e07d1e1a3bc..cb4856b325afecc06bf655f95e266779a5c6f4ee 100644 GIT binary patch literal 870 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4mJh`1}k^&LktYex}GkMArXh)Ua!wMQz&!% z#bs7*C(fS`FwVLmzun_>zsN>=jgwFKzs=Y9=`2}%>dbk8=!v;8>NAt> zq}<3UTV^fvHplqg^7qdl_ve=9mEW1Z&-v3j|NHg(?pM{s&Hw)U_IK|8ul03f*GMm0 zo_~uehh3||Xu+X0L+gJmE=)6~oqJvzY+TCAH_L8|Sr%_F>q+|!&E2YDan`aavoA^5 zq)3#Ov0pv^=E}{vJ4_l@Hr?49*D$5v^Ec*iayAEFB<`JITx`>3=r-vK+pOqYEAlIR zOV`d7FH>LltlysZ^-4GGr7Q}y|9F=983kqSJbpDud$Zk6&Ankhlk6l9&)B#oc4Nm6 zyV}gGEYEfIFMaBwZtwV37uvgucXdli%tRh9pM*5Yxo?*|Nj!Axf^49uTiSr9X#U8ujB@^48nytQ2|t zqT{)V{}SyZ&-oQvIAp`wUsPXSX1Jub#%7*5bK-)X==83rx^~CTzY&`f+$ttTefOw{clmaFZI{+L(KmgUo<#Zk zvZ(CwjE=f3VWqP1_i{Bcm21zN(**Y0JM{0^(c#(2dT~o+uGr>x84sr}ziL`0;_8+e zmMau!YTDXf=4Vy+Nho~XU8k2#KQ68_ZD+{2J7MMan{t-teDEQ1>84d|imq3-r$I`tK&5`?l`q}>WMy= zqT*srJv}xBWo75~b?({s`o3DtKDuV{Ztc>W({|-ne@cDsFX7ZN2+V g_euTV;;*8cUd)mG`95_g0|Nttr>mdKI;Vst0Lv7V`~Uy| literal 1658 zcmeAS@N?(olHy`uVBq!ia0y~yU@%}{U{K&-V_;wix$;|vfq~7@)5S3);_%T3&XAB$ ziGOJa8C_jmgSDr69W)gcVEVd)Ny$q?U3Bi27^jjWLH=^SE6i3s9s4#e7l&` z+2s)%5_q2-U3YA6kn9vK@r>=u7X&{)$D#7s!|6bZK|-;U(!?766eGzeMXayyZ%gF- zcPaG2!RGsdi}?;dyDD{l#!SIi4*U1Ld@JqPF=?iaors#yscA=43S`vhwx)2grmbFX zbUx_)C9?(RwIepy=q>Z_Jg}>!_Qo<_x2unnSoq(ze*I{8<453{=P_SdN*nU$fBBYs zS4L>jbiKiW}|(nu3N8U_vG~a#TzyV zoV;!JaQPkKg8ZY-vZh?G?R$=J`${kWCV$0x?i~-#n?(vqIUT7soE$4cw4MdN z3Vn6cxOIOdM})(_TRV3rMuiw8rTZUz_~v!MmRC*t_U>J{zM`jAQqy9Kz3frf@C&<- zf1Y8gd&aEn%aZGXzdk5#>=$eb@$}j2Y3sGO>fI;aXnWq6EgJ-MC4?@>vtPQl(D%3a zgdN(_KgIPFH8ePq-TGakw@F|N;y^4@`7y-j4B$} zD<*L7Y2&GV|K?3kd79sm6@t!z5h;hxP6}GGbg80|(WJZT9H!ZSJ6EtCg3B)hA|o@WE)e51=3(Qz$|lTR^yr6Rg?%2|H<`1mji)JelwL6voBj?v^jPh@=;>>#i#?ioCuXh8iYw9qvA$~#bEjR|eEw>-YsJdwbZgUGt{FaS zOuYRXv=00^&uzxK;<@%}p3>%LN2QEdZZ1Ec{O!vJw$%b#Cn)S}J;9=OZVf|d)3!}T zdk-(!`e^r>%TGEUc0G8wuZ(qJp3vtt{z0rSxFU-iwrgCN@Lsd1hzwfwtY|E>!w6( ztPm6lvc2;8Nu_D#^X)I>t)?bAM3}I#Rc%(dY1x+W_;}%;*^>{4R`bo(IeW_P_^*uU zT_u`E#>O|Ri>5j*yKr~!$IU&@1m1GjTk{D&(>b>8Z@Z$$ugzUPY^_dw>Pwltb~5>K zu|C?aVkpYe-M(1K?bFQrIbSSFpB?(D9J%w&zB%!yQuOrnj3${M)hTzm_jj$O)VD~N zD+LzYb2!7p!_Dkkm#|Dx$>4HxTB#DQdM(f2GFjy62Lh`%PL5vuy;1Ss i-wE|bKW9GwBV8u(y5!aLv}y(h1_n=8KbLh*2~7ZW8V^_i diff --git a/src/plugins/projectexplorer/images/mode_project@2x.png b/src/plugins/projectexplorer/images/mode_project@2x.png index f0b7fdae0efaf3abcd4fdd1f04e1eb02c951b418..264cece448f378c7888232a5f924a1a7d27c66dc 100644 GIT binary patch literal 3256 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 diff --git a/src/plugins/projectexplorer/images/mode_project_mask.png b/src/plugins/projectexplorer/images/mode_project_mask.png index beffa6722b858b2d6d6d5a4167cda8fdc3c9d573..6e6092b7ad4aa14dd3cb22e4f7d69bdf700be7ea 100644 GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4h9AW26>$jIR*xXO`a}}Ar_~TfA|X+^suPP zPcJ=N*X@6Dznvai+mii1rd%;vu<}4aQCnxD;v@aI?N69^Eg92t4=+6;wqgm-k%-g3 zc-n=u7YMcSP2g&qZZSoqX^H{MvCRe^|BkME;xE9=b0w+#^m~pST!-IBOjQUmaH~J^ zDzk&@=xOO+&utIM>D4DWXgzuVuAjxycUlGS|6e;KBqse6TEB1_@wkBDiCIktlMGI*Qb-bPE?l6~8G6)i3rAB^VuWi8E30UC?KIxqGgutM%s$Lk z5azARdtUC}_y2d!ZgKrTJIdeRyLbzB%skOpC3^j*a2KpV?BC z=MN_CnAoqn{Gr>nyKTZNRqnJ2NB%K87N0!jhvl6U_tv`#S#tU>Nmz5Y-^?P#*hP#d zSwfWWWE;mfUgqmEn?5y{$Zp}iQ*c5o>Qv(Cgv*w$(UJ8PmVS&5`3DrQ%H1$@pSEM3 z*aW5aE9orBt2`AKT?}8gZf}OlxfSN|Hmk+=OgBLq^{Y+$8&zicuVNKl zGRuDv>+>0&rt@96|0q6NU9&LIsFv-kgL#*NsBQ#PZ{tjlB=IHt0?#)EtzeDwc-Cz& zXYoANjRD*ezb2eXzu{%eEtDW;;O8>q{D!$zVp9wcF(Rsgu_I#jZMKcK>~*Qm@196Ig3R zcF%8M4FicZU7a%9Uty--)5L@avprA8J-hx`eP3_c5qDjQtqE6}7UnZDIIk5oyTy}X P0t$3bS3j3^P641&}-%Hb+=s2AMIZd zP_D~y%Qd*^*pVL|Gkbc~W*+l2Qkz_wfSTX)x9(Qn`m*tkf&p{DPpLzG>-C@PzW?XXLc94tLdxf?E&OYE zj``nLbEe$4>QVMtZ!WyCkufUU!hXAVgWcSd=PHZ3>JG%3PcXMi{`lgY?-Op;rqUOC z^RNGy{k^6CWJ7V5QtZ5iC)SoScfQ$lVco*oIERXLmma1$@A(uKoAGN7RqM z@qD&p`?Y_OLQg!>b>i;6I=)SIi`$PIEic(N=0>}e{SLW3F=LBe*u~85p!BjUvRi^} z{`mLESW0%gNBy zd1HMv@n&${kt1HcKc>wJ;ab9?>iGI6;{wr!Mn#`zbDC!8rI)-aymWDi^xDc>3k=r_&DzI6M(hs(yT*S2y=bbA-*EPkRI#HF=&UUpw2q@KEeOjXPp9 zFNtWhd`s9Bk>J)Bynlbt`+L{7ncv8$HGBP3+N=MCW`AJK%1bgfg5BX}zc-%N({P?~ zD{0pp!SBV}J)gbnim~jU#37>5IYDRw$IF8ycIjt+T-x>Ws?_4Q4#B%cL*rK@Xj)h= zTEA|WNfh&?_Jw~$?#diKdjI50(PtnuK=x?|7W#H*NF*!&wW9k|bM<Hpm|`u7iYS0CAarSjCYO*hIUA2#mZ@N-eCx|vAEfx?4Eti2P(wx(KTE!m|uXW{FU z+&AOSF<#cMuVLlLT@WLDy>$MRguuUxIQ^Rp7AW3vS+OT{$@)~+{P_Dv&#eE&W3cJY z##p%{Gxpotu-lX`EWCPo_mQs`qLg1P{<`VZI&<~ioA2zddw^z;enuC*q?GD_)s@-PST1tKus_)& z7+WT=bz)Xz`qmjgT{`!@ZvMO2Jk4I+`+6~380SVMNNHEx+>N@V+;amWP(6PhTgRWT~vi zwC!os5s&h$SBd{07ne10H%QmXPJA7E^YgxMSAwqosas&ZW&Zo=m6OdjP5dAJkLj|U X_a~wK>pwFvFfe$!`njxgN@xNAANo7b literal 1719 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANN9b)GJcArXi7Uat(8QYyjz z;r*f$T^$aZL0wXt7Tj4QbBu{=SI0gbZMp85k)uS~sY=;zy8e??{g^7s2rzbo-kR{L`1&$F4+AOE#`|GVznQ}z$vKNYWi zvMA0&=Dz#?Nt=JGJH?+X`d+s7=5E=D%71|oY2O^wC%?{q_iz7|Ex&9+OvRHgKjide5F5H<@*^nTujok@yJLchZClpt?A9b^s&xRekyV7Z~?=Kbv>;%AL(-2xox9Q;_T9 zM@NM-_um}6?!_`Unk{1WN$Kk{M&IWc2TZn1w>S{Fd&(TWfb;U_Cv~z{uYSnO2GT!i zD|;7*sGycoj+&F=p|nTZ&wn;WpFe-y^uXiLSvq?jO^94>V)}cD@3Xl&0sit^PuyU( z4Sgo(aV*c)$4GM4Mqx-Wfb7>&5>XO)^t<=Rsi@yl*Vr}IJz?k-PCeJj^!3ig9Le4G zF8o{G{K-zZ6{gX4>Va;+%J&YSh@A0yK}SHxhM63#KU#jQ*)F$Wb#}u_(Xz^?J-)}x zTUKq6-Loi{r-(hTaml{l%MVm}TyoR+%*K}A(6#E>_t&+vIzegSVY$f%rH`e1zB2r? za(VsZspq8Mj^Up7E)})vHlD2Kl6k_jrqwHkzcZR$^zefUx!c=jABj5|ZLj(yTuJBa zo$Fzt=CX@Qe=PbpY2)eWATvi*OXk;6>n1RA^7yQ1?214AU~2&LHHW0tJXuGs?K`_z z`>fH59oO?4({zgWG35VW@34UHVpeR1(CM(nD%)Zf8XK%rHQ2@_6nyf*)d`KF0XJt? zckfkm44U^!`|f34>B=^{d6&2Tdi;Ey!r!*Y_Ng;fN+$;VvEmjjI)y@3p*JQdplzf-t_xZ+7zoL%EF>m8 zHYK`vwtmmV4`2R=&5c>Tz(z(`U*fC7Z$X9s9oi=E1s2pEI{IOvJmcXV(%U{&eEOLn zBJX!(L-=onk|q3BUs{*nFB1)O-+4_^`4gY<7S#d~^XQ#CXa7zJKmTCPU!MGg{0~mQ zFVdQ&MBb@0G}&5 AqW}N^ diff --git a/src/plugins/projectexplorer/images/run@2x.png b/src/plugins/projectexplorer/images/run@2x.png index 9e6e984d7ca4dc78017a3e618fed61d47f4703f7..f55a9bd37c4d40e8a0cea1695d36fad2a198627d 100644 GIT binary patch literal 2832 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4mJh`1`FZIn;00lu6w#ThE&{oJ3Bf@=Bn(m z`sZif{1Q5T-6F2KRxx+J*4B`<6)Tv6v@0?~FJ2FG)#4CX5fb7WvZ9G;QK+jh*OCAw zjfF>fTf$rgT(RE}-jYrWaJ_?N-sy%u~A735-kWh&`aGP-NQ} z$u;5qNAFuwtK$xcfRSm@sIj)SHVf&96{=O_Cp%LKJD3o!?Suykpr~Kpe zWk0@uvnn&YBH0t@%wB&qfnf(jgtoWhxgUaBt=vo-0xLqqSU1h_nRxuc3(b4C#1?Ga znL17I-qN|#19})PpJqKHI^$Iu+gmmft(EN^70!VTn+|Tvox(cnghKrHi4RXMdw)Xn zUY)r|c=&x0=a9>1r4PI);wTTllIj%3%rx;zux##)ZB942Zg1PDyI~6R(M`E~j3(cC z<75-p`|jK3Kkx6RIk~s_3qLabRl#oYu+6&kuBJ+g=@N;KpoH68w}T?q8RjD&e``RDyTnc-4FRmgd zdH2)g-Ci@>r_P<}8&}78N@&&6M5jI5jaTUL#J+gWalUYle

)9o_n1*^amIDIY#N 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 amW6@UX6M{K|G5)DuJLsBb6Mw<&;$T}i8#3c literal 177 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4h9AWhNCh`Dhvz^6`n4RAsXkCfBgTy|NP(o zGa49MEMM0rOixG%xZCO6)Ohf@As;8(KhF9M-UbE|a>o@99uWD>wwr~y`NNs|8>$i# zZ`M7SkdScpcTa3nqhpn#UT3I^Wb5IgkFEbbJ}!93xyDhcL0P~#KB0d_tcvT}`^++( djM@h@85veImml_?DXj`}i>Irf%Q~loCIE$mLN@>a diff --git a/src/plugins/projectexplorer/images/run_mask@2x.png b/src/plugins/projectexplorer/images/run_mask@2x.png index 38f6445c2528350fa07487e4f47d274bc9fc4f1d..72af48223ed97ab72a821b31f2d45aa9c16530f3 100644 GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=8;uRL8GLn02py}pt6kbyw! zLvV7wgKXh~wx+EDihm(Wtb-OI%vT7zKk#MG_htD$I8~!*rT!_9_#v+j`ZOwGXkA>y$ z)w_KRlP5JWJQQH@uwda7;&E(aahjlXPvA(0J`3w3KF4MY=L?E`0$V(?IkJ}Mw&YKU z6|dWxC@-oMTo-tJ!vCtR1^hcDPIA1S sR(_&YJ45uSkLA~Hy85}Sb4q9e03vm57ytkO literal 273 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4h9AWhN8@6(F_a>H#}V&Lp+Wr|KMk{`~F{; zQ(}Qg`d|J_CI$v8-l+sKGdG`47BV&X;QzyU78@Je;m0aj2?<@bV9vvt|2-}rIFL}@ z>cY#jrgFaLap^e-T?uC+l`LnNHUEY->7M_p|AAwl=VxIpP$+T$QA_ zhEaE;z+y(#jRMOVH8%>ZWSkh$aeYJAGC!q@mmhKezi9M`$A7{U6BZAjnuYovryX`@ z%yRYAVM*X@bYqq5bXE0oT2NQmKTm)oLqK8UsY8devicePixelRatio(); - int deviceSpaceIconSize = Core::Constants::TARGET_ICON_SIZE * appDevicePixelRatio; - targetPixmap = QPixmap(deviceSpaceIconSize, deviceSpaceIconSize); + targetPixmap = QPixmap(Core::Constants::MODEBAR_ICON_SIZE * appDevicePixelRatio, + Core::Constants::MODEBAR_ICON_SIZE * appDevicePixelRatio); targetPixmap.setDevicePixelRatio(appDevicePixelRatio); targetPixmap.fill(Qt::transparent); QPainter painter(&targetPixmap); // painter in user space - QPixmap pixmap = icon.pixmap(Core::Constants::TARGET_ICON_SIZE); // already takes app devicePixelRatio into account + QPixmap pixmap = icon.pixmap(Core::Constants::MODEBAR_ICON_SIZE); // already takes app devicePixelRatio into account qreal pixmapDevicePixelRatio = pixmap.devicePixelRatio(); - painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2, - (Core::Constants::TARGET_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap); + painter.drawPixmap((Core::Constants::MODEBAR_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2, + (Core::Constants::MODEBAR_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap); if (!overlay.isNull()) { - pixmap = overlay.pixmap(Core::Constants::TARGET_ICON_SIZE); // already takes app devicePixelRatio into account + pixmap = overlay.pixmap(Core::Constants::MODEBAR_ICON_SIZE); // already takes app devicePixelRatio into account pixmapDevicePixelRatio = pixmap.devicePixelRatio(); - painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2, - (Core::Constants::TARGET_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap); + painter.drawPixmap((Core::Constants::MODEBAR_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2, + (Core::Constants::MODEBAR_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap); } return QIcon(targetPixmap); diff --git a/src/plugins/welcome/images/mode_welcome.png b/src/plugins/welcome/images/mode_welcome.png index 24cfcd8cc8ebf33e7a5fe63f4486f0b7a23a09d9..186b85f19185d1af420d7a92f0229a6b1e586c38 100644 GIT binary patch delta 501 zcmcc3d4@x?Gr-TCmrII^fq{Y7)59f*fq_8@ggKZ&A~Sz~U|?WM3GfMV-Kd|!R3FKF z>Hz}-17k^$UoeBivm0p)42;t}T^vI!PVc?^+&a2Yg#E+s8} zSa!=dwJ?)cZ4nETmb9>mZ*=FpUw`Urh2o^@&zHVmt^8Oy?|$XE_cCpjuWq;>`L*+w zNMDJ(=aph>K_UNVCwabaQA?3^RQmgC@g1}Jm3HhOws)-9;@t9N{)1iByq{gZ3Md*a zXzkJq2;0c8(m;}BpYYoSJLlK0_nP3twAH0pVyX8Oajr?e3#MeST(%K>`BdPC!k^h33tgkx0eSF$@;|9{z9&3pO(^dDQdEa?=!xr;&n zZI|EqO;TG=#ddfss+q~sTb8=ae{IrcT|0+QuUZe+&b9gMe%onT(p0Yei_M<1E`9kE zru8KAk-6xSFdoe(u`A8aoomgVUjDT0md)7{FAVsfy)5QV-TQ3U5rq}2lXy)eb8yXoEo0eZ# z+1T9D+S=OD+0{RF=F%0bR;^vPe#_SV2M?Y&arVN6i`TE;ymkBb-FpunJbd{0$;(&o z-oO9wpxV~eGlaEp219q#luN5}YPh)i=Gj)4K4 z9cyj|+zF5o-~KAc)QNF>ujM4s-t_ZfM~=R=jb;iz@O+oItf%9{o16C*YN|Kt*_Ldx z(AVn=)J{3i#`$Eyy^3!k&(Ce%{OD2ExjCyoU;1XVCwacU@}{OOZx0AW)z9Ecs$3m; zOzy_U%yz}7lI!zqS-GAtuwH&4Tm9|Ky^U^izK(|`Zf3vy_|B6i^W2-;vQJGb4czmB zb6L*!k3Ak2H<(JB<n!Yi&@6S zZWjETnmE#hMKcw}6mHiay!6!9INir*W=4ZZq>)pH%tQ11z~fsqg?BgKD10Kg+EVzp zdf9eXu1BX_q>N|nzMYg~S&-&z=q_#@%gDBhk-@y-&D{$pL$w$f7#KWV{an^LB{Ts5 DDO@AE diff --git a/src/plugins/welcome/images/mode_welcome@2x.png b/src/plugins/welcome/images/mode_welcome@2x.png index f1e9189523161d4e58c105aa7416e0b8e35ff3c9..f911a462542669a434f66143fdc76804e4eb0e69 100644 GIT binary patch literal 2271 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4mJh`1`FZIn-~~4mU+53hE&{oJG;_na=FCu z*PC=^N2YDk-926B^rn=X^|v?KiwWmi_ZAmVFaBERmYota= zy|GH}aof1wNzQqKSrOOGBEP+F6t_1WG<+xasbi1ifeq$u922^1v<|r|{_hLkyJL#Y ztGMet!mWQ+|K~jXE#PDo<7^wPmVf*DY+kkcTI%Z+Whs1NmM@bKnC*P);o2!_6Wre} zsQ(}AxA%+Xx}2*{&p!w(-IDsQv7>Lb$t=zb_WQh6-nU^YGY zq8CNnZI~r_%sS$=hv?}HzI5xY@9)GotXQ9LtN8c~-JM?bx7@QMQ;uFQdww%)OIQ2z z)l+usO<3Ei9eH>`+gTUAIH}b7skM2<>wG?`op`G4cAa(7busO%KToc>UbDTH@b%B0 z!iKk6KOIW+_BvXweLl&-;;NBZmPv#p?_smm;UBE3PuV^F+_}?)e|q;h^E8>FTm|;8 z^-%|B?67g$`5=^g?}}6TH>R!*7PCxs|0u;h_wG{p$TN>8Ioxu~TGOB~zvJa0?K7-b z+0Qd~-%q;rF4-qNAY#w|)ql93t*<LYxz&Oj?wb?!99Ya*w=cwxyXBrNT!#kp}#Uia)!KF4&eDPN8yv@>^hbw$mYIrFBZ zq@-rKhQN{kIjeY1Ee{C#GRL`*g`M4gZGgs?%F0TsSw)S`jWX+QTdlTZS-T_PLbe5$ zM?k=Z$xkGo?%lgrM^{((;6u-^?{CGYU0vxGT9>_4+HHaiW6L2IuegQwr8^d2ZLL;Z~qL)%+5}3ZEbaaV%dL2QeaKcZ@zQ{dx9UEna^5Ve$V~KT!W2^c|PB*uDJ5R#eBd0?!7NeU-(?oZ8Z4*<7@Zi$&>p{ zO-y3my?&j{%*<@l@b6!p+sTq&pKoqXmwb8j{OO%%7VbK0Y}LlF!{x4g+4*uMt$j<95$yK$vJRw zaYY0N3;*YNKhZrz>uTjGdH*xNZ{{7EdH=>z?a5*W4}KY2_U<;*yHwh)pjZ0!@s;2= zDgtaFJb$iT%t)N!tf{M;8nt#>J)7(k!6*HT-TT8V&L*0lD{Ey6F#d5*WnIC~+Jy@j zdT-jiSvoo@>c=O}^9>8tG}IJ&dwY9?wEy$GU&#G_!Jk7y!orj1vUz0vEz?%`ASBcB zUhijsiOrtSOZ^)etV>=5?1)=G-{odYp+r)^2TN1a(p}FRI#ew~>*Nz6Ko3mIvgf%$Xyz>|(|m2L^#k@l(0;g5zc! z{3Mq>O)%?p;gOs58+~`g2lZyp5ApkcP(q^AR>5P@@qYR3OpQj|5~il65qH^kKI2u| zCFy&wusksEBCABJN+$oQttpyZkIu|Au6ehh?5@Yd?|ZzN99?g2PCs8IQDUng!Okc1 zfY+SeadotuOKGX;VpCr0iVq1hSKl*yedLeG`}U3h8XCVXSg>e;>2}sdixxEno^N{f zX|gthbE>Gyn+xr~O63w`DG-8W!wj7ek)jEg(>Tx{0r ziB2EF(wU5WoZl{< zzhfls;Fa+|asPIwZ^p|ft^W|DQ~$;7oPXZB1NreUR3$VuHUC&0mE%~Y6>%q)lan)2 zyO3RR@nuFAj#h_-kLR#Cp03jt$l5yV;!f_{yUX8ilrDQ`bl=H0M8RvNrNGjlliQzt zb8uikU3be#XCd=SYn69Ojg5_~AF`_HAAG)K$&yR~4oO9h3RW%tx06GD{`_gHQK-Jq zr9xcNDsPq2vbw`!9B+Cq?n>`Eq;hku&EXioxmH&>6t=J*lI9W6SnMQlrCVZUss634 z+1IOu%Ehd#J6k`N{ITFY#L{@`Q>xbKAjM1n&i7W&a^kjYPRnJ uQ$K^sCh?~o=_;Uxg3Tkr{vA{PaI^5oYdx;kImE!gz~JfX=d#Wzp$P!}f;O)J literal 2282 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hEI8+fQuj`0A(ji`{~p;lZP(BG$#6oon{(lPd*$xRtn7cUqNj^8eqrU`)x)q`>Giju zlbcQ^m0kM(UvYWlSC;Ufe|)`@8MPvRKN42Zn(lF{W5WL05TpC9DhZJd+Xc-T^O&Y7 zG8%5Zzj4pEjB6Ha5|6FSyJi@7ded#C8+vzVhnq7_xjysVm&COEm__xm!n``GetEZ_ z|GD=|Wj~6 zzKbs@J!p6+F8$%MxZ26-@f$96ulv~*yT>G3RJd%~-n^xocPBMpEmm=KcwVuWm$8FA zY1fR>(~WN$UNfeyH;lcXxXfH@?YsYxUpYTt-j`#ppl8YW?^d`=t^NMw^(*$RvOej> z|B>;!^GR2kUgxv_PET&=SasfIe?iUPw7|b9d#Cs6U5fKK`g@PJM_)rr+uB9(7OQ?~ z2mU?rNS=;Wx`-5k6nHAh(?ta&CeV=QdtYgVILvmx|3jJmJX|Fbx&UP_wP-#-A ziOpeobx-Ij{}L{LiwUkO-VNLIou@F^zx7`9Yloi9@hIn|-VSdQ=4mkQ&zdKA^?2z+ zjaOa~CQKH6yKk;!nesJN?*vnT%*|zIX1FRUn3;WR?da(6ST0ns$hgkYkYVclf|RW+ zJLfdKc=2L+aZyp#qD6~D{8SnK?Vh01P@*QYlI`4578X`k+f^Z2ysfRRRloj9Ef*@- z@NqlqRYr~6R_2}eLRnbY*zA0a<4p|=4j3653(u8f`JZ)T(*iGpUC*+m?-nQ>6=j)l z^K`~F-sS%D(`033d(Qk-DrPIlbUw6IEn^>Q%3tV4n#aLKaC_iQD z)UV&Zf8TuXUR>FuBb|Du7|eI3m|7HUyW7^V>mbv|T??=8%FB?vdh;!7!h*Bg1eiFU zeEsay7 zeakQA&#DbRHL+n~)A$w~KYqOO!QH!e_xwD5~UZ-HbPKoc0RJVl18td63X8gHvLxO+L z#*GvI?_ImL_n=nHJrUP?=4btG=JwnwYdikauRkLD?xx*5-I6okJ^tNYKV=`sT*+Im zeBZrq{3!AAI`#0`vuE7R&CNL#6*JgvOiYew{5V@{SNcjsd2fsBO>vLxJBI7GS#)?^ z`v0b&UUAc};#&znr~RB}lfKW+S7?{=%ge_#PrO~dW{r$<3%kb*TNV`&QBgyIrq>;; zzP`Rar|#=^Z!?~f^da$Yy8lhq`vxIL%BJq!IN|PmO)L8izpr26?N?DzahWoGdcVRB zMw>2a;|PI(n3ywB(a}G%cl28<2wQ!A!hicMFRGh6)wgf_ES|pRz~L#+H{ULfJa_S1 zxx)01ubQV^E*C6NR@!o>>@_wqDM^isi}S9oww`~^;4?#-+Cd)&Z*T6!4kzLd*S<*lrfIif$&w{gRFxGL zzvP!@N?^TVaX0qgycIjESEjyCJ~(OGG_gbjiL?pF7}%8DnC#M1QqDZBd7=2ec}rUx zo0y#3zsr*Z8yM7lYM*Uf{w#Xoze+#N==bm6?|*b-W3uRn)CL9#W6mU&37wyfb2(+| zyI;fy1SF{Z-(T%{p8d`0|BhSk>Z&xP{VV>p$^6N)XWN(#I|Am z`t`?O=?6%uyS#X!dG=rK(xpq&8JQf<3UW?wo~`j=vbz7Leg03^ciwsF=_%0AAulGj zO^{)o3q#8Pe}8QPydP}&^|``9i#&_5|?H^Z!>R@YR~ZQi)Mee(5^f z2Uo9N?a5+u`7b|Rnenj7(G^cMU)1`xD}?812i)mkf9&hEDr^<$YbgHvEq!|M;#Gj>W=`1pF!6bFSV0y=Tg&vvZ<0o(tajtu9?IPHl5&Qdw&lgQu_W)7Lfb2Q*(L z8^h;$K+xey)ydtE%oOgn>>hE&_4h{!a&q&=Y`k=U|=#xyrjs^jXG})PrzgV{J z+qdt#$FHTDTrt}PHfR=4F@IiNecbP0l+XkKQu-He delta 86 zcmYdIQS1!xbLZuf;$mQ6;Pv!y31VPiFkoO{P+(+cU|`6T%8Z|=D5@vv>Eal|5uN;l qpN;28K)njjE6#u~*BmA=F>FYg`)Zm?p%McF1B0ilpUXO@geCwUz!nz( diff --git a/src/plugins/welcome/images/mode_welcome_mask@2x.png b/src/plugins/welcome/images/mode_welcome_mask@2x.png index daee953529c700f9362647d1fdfcd9717cca2280..060ada0cf54520c5b24459b6c2e989e760f3a63b 100644 GIT binary patch delta 93 zcmd1GR_qM$bLZuf;$mQ6;Pv!y31VPiZ~w)h?MNt!ZPZ!4!jfu%W x`dK8{^k)9k~Di diff --git a/src/plugins/winrt/images/winrtdevice.png b/src/plugins/winrt/images/winrtdevice.png index d8f5bb7121166c57354c1b326a3ae65cbd1d799a..2b45adb69a1846d0f6a77f83385a36a312752bfe 100644 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0y~yU{C^K4h9AW26>$jIR*xXY)==*5R22vKl}v@cs5Lm z=jYRZed_b^MNiI8{{R0sSCj6N84?E=JWqbU{91jQOT_6-3_E!|7(6*QJy;<$X-a_l zGI!_cIjZ;Hy^Fgs@mca2Zx@-pzy8+;MQ-V3l75)+=lh!{w>XbJY*xCh%*0JuwGJ$9_;f>t z*HcNfX7}#uME6u}~w^N9=$8!JprT`dmj PfNb}4^>bP0l+XkK)oweV diff --git a/src/plugins/winrt/images/winrtdevice@2x.png b/src/plugins/winrt/images/winrtdevice@2x.png index 305c2e9376d483dcee05d4e7ebab339243019e0a..a57f2b49783413724111d520fc215d26064c4ad7 100644 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0y~yU~mCp4h9AW2HA=;c?=8;+dN$yLn00*|L|u$V32iU zg<{0PZewZniPqYyYWhzrd*k@F#AMCtj#Px zD0gB4hu7=*kF*}&72S~OwdTr-@_#m#Y>RvxduvW<>jz9vbgEpjRY=%0>wvt6tiY+& m7uR1e*Oyq^?ar&n%fR4v^l_c+?+uSZKJj$*b6Mw<&;$U6)LvWw literal 235 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4h9AWhJGeJCI$wEO`a}}ArXg@fA}jVNSG!x z@KhA0Jyt2=`B7H>{md^Daa}n!1%-nQ3--0jX4)OA;W^Q;fiZsFTb4k9-v*3+%yo9Q zn^!68Ux}C`xTvGC(Sun|ChpeE*XcTa>pC)+3pAxn6RtD_GQ06E*w47Q^l^rj1Vn&s zGNXoWW>?qO^6&#{nj3?n^#4>A@wm)vk~%vjRA<4n?=7DKvQ^c*vX{ww@K&B$wQc?N ga(#)l((IEN8H&5F7U)-Rv<3OX)78&qol`;+00N0qi2wiq diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index 800361a9df1..c44a460e92f 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -18,6 +18,18 @@ sodipodi:docname="qtcreatoricons.svg"> + + + + - - - - + x1="510.75" + y1="73.5" + x2="510.75" + y2="75.5" /> + + transform="translate(388,513)" /> - + - + - + - + + d="m 212,52 c -1.275,0 -3.30877,1.17695 -3.88477,2.75195 L 212,56.9375 215.88477,54.75195 C 215.30877,53.17595 213.275,52 212,52 Z m -4.67578,3.68359 -1.98633,1.76563 -1.39648,-1.39453 c -0.194,-0.194 -0.51304,-0.194 -0.70703,0 -0.194,0.194 -0.194,0.51303 0,0.70703 l 1.6875,1.6875 L 204.03516,62 H 202.5 c -0.275,0 -0.5,0.225 -0.5,0.5 0,0.275 0.225,0.5 0.5,0.5 h 1.48828 l 1.19141,3.8125 -1.62696,1.62695 c -0.194,0.194 -0.194,0.51303 0,0.70703 0.194,0.194 0.51304,0.194 0.70704,0 l 1.375,-1.375 3.55273,2.36719 2.3125,0.58594 V 58 Z m 9.35156,0 L 212.5,58 v 12.72461 l 2.3125,-0.58594 3.55078,-2.36719 1.375,1.375 c 0.194,0.194 0.51303,0.194 0.70703,0 0.194,-0.194 0.194,-0.51303 0,-0.70703 l -1.625,-1.625 L 220.01172,63 H 221.5 c 0.275,0 0.5,-0.225 0.5,-0.5 0,-0.275 -0.225,-0.5 -0.5,-0.5 h -1.53516 l -0.88672,-3.55078 1.6875,-1.6875 c 0.19401,-0.194 0.194,-0.51303 0,-0.70703 -0.19399,-0.194 -0.51303,-0.194 -0.70703,0 l -1.39648,1.39453 z" + id="path5403-3" + inkscape:connector-curvature="0" /> - + - + - + + points="603,50 621,61 603,72 " + id="polygon5749-6" + transform="translate(0,-4)" /> - + + transform="translate(-5,-1.000238)"> - + + y="48" /> + y="48" /> - + + x="752" + y="48" /> - + - + + id="build-5" + transform="translate(-1,-3)"> - + + id="build-5-2" + transform="translate(-1,-3)"> + points="873.684,57.071 870.148,60.606 859.542,50 866.613,50 " + id="polygon5757-3-4" + transform="translate(0,-1)" /> - - - - + + + + + + - + transform="translate(-190,-45)"> + + + - + id="src/plugins/ios/images/iosdevice" + transform="translate(-266,-42)"> + + id="phone_body_big" + transform="translate(1,-3)"> - + transform="translate(-282,-26)"> + @@ -7791,20 +7853,22 @@ style="fill:#b3b3b3" /> - + + x="569" + y="370" /> + style="fill:#000000;fill-opacity:1"> - + transform="translate(-246,-26)"> + - + @@ -8084,34 +8151,36 @@ style="fill:#0dbf0d;fill-opacity:1" /> - + + transform="translate(0.5,-4)"> @@ -8120,7 +8189,7 @@ y="0" xlink:href="#g5189" id="use5200" - transform="matrix(1,0,0,-1,0,726)" + transform="matrix(1,0,0,-1,0,720)" width="100%" height="100%" /> - + transform="translate(-210,-26)"> + - + + x="501.75" + y="50.5" /> + bottoqtscreen="" + transform="translate(1,-3)"> - + transform="translate(-318,27)"> + + height="100%" + style="stroke-width:0.89442718" /> @@ -8330,11 +8405,11 @@ sodipodi:nodetypes="ccccccc" inkscape:connector-curvature="0" id="path5089-53" - d="m 581,371.5 -1.5,1.5 -6.5,0 0,-4.5 1.5,-1.5 6.5,0 z" + d="m 581,371.5 -1.5,1.5 H 573 v -4.5 l 1.5,-1.5 h 6.5 z" style="fill:#000000;fill-opacity:1" /> @@ -8350,7 +8425,7 @@ y="0" xlink:href="#rect5349" id="use5495" - transform="translate(12.5,0)" + transform="translate(12.5)" width="100%" height="100%" /> - + + x="501.75" + y="53.5" /> + transform="translate(2,-3)"> @@ -8422,19 +8499,20 @@ inkscape:connector-curvature="0" id="rect7899-2-7-1-7" style="fill:#333333" - d="m 524.75,71.5 4,0 0,1 -4,0 z m -5,0 4,0 0,1 -4,0 z m 5,-2 4,0 0,1 -4,0 z m -3,0 2,0 0,1 -2,0 z m 3,-5 4,0 0,1 -4,0 z m -3,0 2,0 0,1 -2,0 z m 3,-2 4,0 0,1 -4,0 z m -5,0 4,0 0,1 -4,0 z m 5,-4 4,0 0,1 -4,0 z m -4,0 3,0 0,1 -3,0 z" + d="m 525.75,68.5 h 4 v 1 h -4 z m -5,0 h 4 v 1 h -4 z m 5,-2 h 4 v 1 h -4 z m -3,0 h 2 v 1 h -2 z m 3,-5 h 4 v 1 h -4 z m -3,0 h 2 v 1 h -2 z m 3,-2 h 4 v 1 h -4 z m -5,0 h 4 v 1 h -4 z m 5,-4 h 4 v 1 h -4 z m -4,0 h 3 v 1 h -3 z" sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccc" /> - + transform="translate(-282,27)"> + - + + x="508.25" + y="55" + rx="2" + ry="2" /> + x="508.25" + y="55" + rx="2" + ry="2" /> - + - + transform="translate(-210,27)"> + - + id="src/plugins/winrt/images/winrtdevice" + transform="translate(-206,-74)"> + - + id="src/plugins/winrt/images/winrtdevicesmall" + transform="translate(-238,-58)"> + Date: Fri, 15 Sep 2017 14:48:07 +0200 Subject: [PATCH 07/63] ProjectExplorer: make the build_small icon themable and HighDPI-able Change-Id: Id53e52962e68ac27bc121bca04d572c0dff5b253 Reviewed-by: Alessandro Portale --- .../projectexplorer/images/build_small.png | Bin 475 -> 0 bytes .../images/buildhammerhandle.png | Bin 0 -> 153 bytes .../images/buildhammerhandle@2x.png | Bin 0 -> 184 bytes .../images/buildhammerhead.png | Bin 0 -> 143 bytes .../images/buildhammerhead@2x.png | Bin 0 -> 186 bytes .../images/rebuildhammerhandles.png | Bin 189 -> 168 bytes .../images/rebuildhammerhandles@2x.png | Bin 267 -> 240 bytes .../images/rebuildhammerheads.png | Bin 180 -> 143 bytes .../images/rebuildhammerheads@2x.png | Bin 169 -> 178 bytes .../projectexplorer/projectexplorer.qrc | 5 +- .../projectexplorer/projectexplorericons.cpp | 8 +- src/tools/icons/qtcreatoricons.svg | 133 ++++++++++-------- 12 files changed, 81 insertions(+), 65 deletions(-) delete mode 100644 src/plugins/projectexplorer/images/build_small.png create mode 100644 src/plugins/projectexplorer/images/buildhammerhandle.png create mode 100644 src/plugins/projectexplorer/images/buildhammerhandle@2x.png create mode 100644 src/plugins/projectexplorer/images/buildhammerhead.png create mode 100644 src/plugins/projectexplorer/images/buildhammerhead@2x.png diff --git a/src/plugins/projectexplorer/images/build_small.png b/src/plugins/projectexplorer/images/build_small.png deleted file mode 100644 index 991f2c0c3068e41e9cd63fdd1c7ec52b7975c922..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 475 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77kRokhFAzD|M~ylo>{el zb9x#hBjdpZ3l`j*ZJuAZDgFGs+P{DQ-nwzc=ur`)va+&yK=bx(+rIT&x)j8?z*;gs z|K*$KKfb-oes@iLtHI#{DTeR^Cr;=nsQg)BU>`nd{`B_1PuG~*w8Q0Qo5=nv5L?2w zTs(n|A@;}iV{QK*EaT0V-2ea2(GLd|oVP@!+z7znZ1es z-dOT{e|P`6@RO%^>R((~$erNrkl4WO&lPa1Br)#a|K?D&|GVe3nlqcKNJvWlojz^a zKeiO_hQs{JpE+#JO;3CJ=YDX`hyAx*Q?w%tnVW443g$DJav%7TxV5&ZfEQc4Tzwev&t}dH7ytVxx)1=vA z>4t%Rt~a0jy!x2ueB569K))qv6XJGoTfJfZX0&Nj$F%pAi`geBh&AvsxbYerwEP!Z k%^4|shxJ6$k`0Ve|NkA$ti8C7fq{X+)78&qol`;+03{FMcmMzZ diff --git a/src/plugins/projectexplorer/images/buildhammerhandle.png b/src/plugins/projectexplorer/images/buildhammerhandle.png new file mode 100644 index 0000000000000000000000000000000000000000..6c7c8a00e05e96e0f2358af026cd0c404b33950e GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdr%jd_r6q7#QT_lq|_4N%6 z4ILdF|NsAg?_Io}fq@~>)5S4FW8&G<8+jWHcw8FVdQ&MBb@01_rcS^xk5 literal 0 HcmV?d00001 diff --git a/src/plugins/projectexplorer/images/buildhammerhead.png b/src/plugins/projectexplorer/images/buildhammerhead.png new file mode 100644 index 0000000000000000000000000000000000000000..2f7fd76a1afc76ac9264fe69200adb8fbe09c280 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdu3Nd_r6q7#LVtS>@#9EG;eT z>+3r@I%dwCdFargyLa#Y|Nno1>pv3)1_m8Z7sn8e=;RrktUMY$3~am{$y&_8>MmRw sEQvme32j<@0_{f2QWj;Y&u3&1`|FncZ29He3=9kmp00i_>zopr0Eaj#4*&oF literal 0 HcmV?d00001 diff --git a/src/plugins/projectexplorer/images/buildhammerhead@2x.png b/src/plugins/projectexplorer/images/buildhammerhead@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..374166321cf91dc75f83a4f4ab555c1abc91b8a5 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;|vT8>H$6>t_%zetgNgO5)zh{ zmg(u~<>lq|_4OSc9W!UnJap*LlP6Dp{P^+z|Npcn`<62>F!*`8IEH8hCtEbLNoWXY zBqSsxxQbcui6nG5USkSv5@^tJG!j|F;>oaxeM?JAdwcucyLa#3zyI*z!~g&P z2WD6QU|?Xd_jGX#;fPMY!OO~1A!)p@C)V$7KwC3gNLFWrdCSJt5zMQyJ0n4?0OqW7 sLd)_vn3o79eM$+_NKRKdq{mQT8}j(4R`*{91_lOCS3g#lbxsLQ0BI*RBLDyZ delta 161 zcmZ3%xR-H)O1)NqPlzi60|P57tCWYc_@Gj&@Y3NR+hB+ufQ)}+lg$-!(wpg`^ScVT4;$-nRIE|C*M<*Z=?jKXuzJV+IC>YEKu(5RLQ6Kl<4u*d`wcuQzFA5DRHs&%^UigUMb} zA|ha`k3$fX7=zYCx2Z5zuyxm|&A){L SFETJNFnGH9xvXf5_ui ziHXyfD-*BV!f2V3V057RMfOMk1=CF@E}3=BC8%8}*h6ZTV zYrQ9?z~J23R*r8xiVm%}bP0l+XkK%+_XG diff --git a/src/plugins/projectexplorer/images/rebuildhammerheads.png b/src/plugins/projectexplorer/images/rebuildhammerheads.png index 24de5314c9df36add66093ebf0232e59f031ce0f..b683bd8bd47d8ee3766d65000a7552fed73bb25e 100644 GIT binary patch delta 114 zcmdnO*v~jYC0j1QC&ZP3fq|W!T}esF($ccNzP_QMVdl)4$B!R>`0(NX|NrC6jc+nA zFz9%?IEHXUC(qzy<>7D>X4alz=-j9%bf$spOo~CmhZX~_$c0_YE0Z#ocQ7)1W^i-; U5vV+sfq{X+)78&qol`;+0Qz1iBme*a delta 152 zcmeBY+`>3PrCv9{C&ZP3fq|8km7SekPEJlqNy*aEvcA5)p`oFpqhsdGnTHM?I)424 z-Me=mK79E9|9{UpYmFHg7@Ry^978ywlPlO+c{q-VvVCJ?n_bS6FDvmX&cI-PG6UD1 zYIcz%j)W7{-``0xYadoCn{bIuvu%2%!m-Vj9=9};7#OzPPZm7qGbbsOfq{X+)78&q Iol`;+0IG^OvH$=8 diff --git a/src/plugins/projectexplorer/images/rebuildhammerheads@2x.png b/src/plugins/projectexplorer/images/rebuildhammerheads@2x.png index 50f8757d19452dea15ffdb9ce4d41572828bf258..ac71ffc9cc862f4f8554d328cc37b6c4332ac6d6 100644 GIT binary patch delta 162 zcmZ3Q{rdm^|HI#EAa$OeE{-7@!B0;a@-_r89J%24!huWZ#>57$Eeje2f{NGt z&r4aF{CUHp+YybK653-mKcKiYeBMV(#TtF2*YvL<@z RGB7YOc)I$ztaD0e0sy9%KVJX< delta 153 zcmdnQxRP;#L_G%s0|P^tpsEG~14DtQi(`nz>Es{&3kRw*LNbK}XxP=h6jligQ%r2k0m_LW<9=o9h5B$wk9TqnU{qE|9xdjv;#T9)78&q Iol`;+026aN`Tzg` diff --git a/src/plugins/projectexplorer/projectexplorer.qrc b/src/plugins/projectexplorer/projectexplorer.qrc index 85e1a5a4add..649c3e658f5 100644 --- a/src/plugins/projectexplorer/projectexplorer.qrc +++ b/src/plugins/projectexplorer/projectexplorer.qrc @@ -1,6 +1,5 @@ - images/build_small.png images/category_buildrun.png images/closetab.png images/debugger_start.png @@ -12,6 +11,10 @@ images/mode_project_mask.png images/mode_project_mask@2x.png images/projectexplorer.png + images/buildhammerhandle.png + images/buildhammerhandle@2x.png + images/buildhammerhead.png + images/buildhammerhead@2x.png images/rebuildhammerhandles.png images/rebuildhammerhandles@2x.png images/rebuildhammerheads.png diff --git a/src/plugins/projectexplorer/projectexplorericons.cpp b/src/plugins/projectexplorer/projectexplorericons.cpp index e86fe915bc3..cd1913838da 100644 --- a/src/plugins/projectexplorer/projectexplorericons.cpp +++ b/src/plugins/projectexplorer/projectexplorericons.cpp @@ -34,10 +34,14 @@ const Icon BUILD(":/projectexplorer/images/build.png"); const Icon BUILD_FLAT({ {":/projectexplorer/images/build_hammerhandle_mask.png", Theme::IconsBuildHammerHandleColor}, {":/projectexplorer/images/build_hammerhead_mask.png", Theme::IconsBuildHammerHeadColor}}); -const Icon BUILD_SMALL(":/projectexplorer/images/build_small.png"); +const Icon BUILD_SMALL({ + {":/projectexplorer/images/buildhammerhandle.png", Theme::IconsBuildHammerHandleColor}, + {":/projectexplorer/images/buildhammerhead.png", Theme::IconsBuildHammerHeadColor}}, Icon::Tint); const Icon REBUILD({ {":/projectexplorer/images/rebuildhammerhandles.png", Theme::IconsBuildHammerHandleColor}, - {":/projectexplorer/images/rebuildhammerheads.png", Theme::IconsBuildHammerHeadColor}}, Icon::Tint); + {":/projectexplorer/images/buildhammerhandle.png", Theme::IconsBuildHammerHandleColor}, + {":/projectexplorer/images/rebuildhammerheads.png", Theme::IconsBuildHammerHeadColor}, + {":/projectexplorer/images/buildhammerhead.png", Theme::IconsBuildHammerHeadColor}}, Icon::Tint); const Icon RUN(":/projectexplorer/images/run.png"); const Icon RUN_FLAT({ {":/projectexplorer/images/run_mask.png", Theme::IconsRunToolBarColor}}); diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index c44a460e92f..d82f71ae752 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -5435,68 +5435,6 @@ d="m 52,564 c 8,-8 8,-8 8,-8" style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1.0;stroke-dasharray:none" /> - - - - - - - - - - - - @@ -6294,6 +6232,77 @@ cy="564" r="3.5" /> + + + + + + + + + + + + + + + Date: Sat, 9 Sep 2017 22:15:00 +0200 Subject: [PATCH 08/63] CamelHumpMatcher: Support uppercase snake matching Often used for macro names, e.g. TEST_ASSERT_EQUAL_FLOAT(), which can now be matched by "TAEF". Change-Id: I0626a60e2be68c1514c28769c679212075227281 Reviewed-by: Orgad Shaneh --- src/libs/utils/camelhumpmatcher.cpp | 5 ++++- tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libs/utils/camelhumpmatcher.cpp b/src/libs/utils/camelhumpmatcher.cpp index 4ede263d0d4..0661499c7a3 100644 --- a/src/libs/utils/camelhumpmatcher.cpp +++ b/src/libs/utils/camelhumpmatcher.cpp @@ -72,6 +72,7 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp( const QLatin1String lowercaseWordFirst("(?<=\\b|[A-Z0-9_])"); const QLatin1String uppercaseWordContinuation("[a-z0-9_]*"); const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?"); + const QLatin1String upperSnakeWordContinuation("[A-Z0-9]*_"); for (const QChar &c : pattern) { if (!c.isLetter()) { if (c == question) @@ -90,7 +91,9 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp( keyRegExp += '|' + lowercaseWordFirst + QRegularExpression::escape(c.toLower()) + ')'; } else { keyRegExp += ")|" + lowercaseWordContinuation; - keyRegExp += '(' + QRegularExpression::escape(c.toLower()) + ')'; + keyRegExp += '(' + QRegularExpression::escape(c.toLower()) + ")|"; + keyRegExp += upperSnakeWordContinuation; + keyRegExp += '(' + QRegularExpression::escape(c.toUpper()) + ')'; } keyRegExp += ')'; } else { diff --git a/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp b/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp index dea71dbf235..3777c7b755f 100644 --- a/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp +++ b/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp @@ -57,6 +57,7 @@ void tst_CamelHumpMatcher::camelHumpMatcher_data() QTest::addColumn("expectedIndex"); QTest::newRow("underscore") << "vl" << "very_long_camel_hump" << 0; + QTest::newRow("underscore-uppercase") << "vl" << "VERY_LONG_CAMEL_HUMP" << 0; QTest::newRow("exact") << "VeryLongCamelHump" << "VeryLongCamelHump" << 0; QTest::newRow("prefix-segments") << "velo" << "very_long_Camel_hump" << 0; QTest::newRow("humps") << "vlc" << "VeryLongCamelHump" << 0; @@ -74,6 +75,7 @@ void tst_CamelHumpMatcher::camelHumpMatcher_data() QTest::newRow("no-partial") << "NCH" << "LongCamelHump" << -1; QTest::newRow("middle-after-number") << "CH" << "Long1CamelHump" << 5; QTest::newRow("middle-after-underscore") << "CH" << "long_camel_hump" << 5; + QTest::newRow("middle-after-underscore-uppercase") << "CH" << "LONG_CAMEL_HUMP" << 5; QTest::newRow("middle-continued") << "cahu" << "LongCamelHump" << 4; } From bf5bc72b5a1d942afa8ff2f712c1f51303250daf Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 20 Sep 2017 06:52:37 +0200 Subject: [PATCH 09/63] CMakePM: Fix compile with Qt5.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broke with be376ae7. Change-Id: I9c99a7be78c7ec0359cefee84e2e1877d20f25bf Reviewed-by: André Hartmann --- src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp index 620facdcd4d..8985a0799e3 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp @@ -398,7 +398,7 @@ QAction *CMakeBuildSettingsWidget::createForceAction(int type, const QModelIndex case ConfigModel::DataItem::UNKNOWN: return nullptr; } - QAction *forceAction = new QAction(tr("Force to %1").arg(typeString)); + QAction *forceAction = new QAction(tr("Force to %1").arg(typeString), nullptr); forceAction->setEnabled(m_configModel->canForceTo(idx, t)); connect(forceAction, &QAction::triggered, this, [this, idx, t]() { m_configModel->forceTo(idx, t); }); From 76006a1353f1282a940bf80a523b93ead7beae93 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 19 Sep 2017 14:36:21 +0200 Subject: [PATCH 10/63] C++: Fix crash with invalid raw string literal While parsing a document Bind::asStringLiteral() Token::spell() was called for a raw string literal token with a Token::literal nullptr. This is due scanRawStringLiteral() not properly aborting for invalid/incomplete code and that the code paths handling multi-line-raw-strings were not limited to the highlighting case. Address both cases. Task-number: QTCREATORBUG-18941 Change-Id: I489d288ccbd7b59be396dada846613ff555436cf Reviewed-by: Eike Ziller Reviewed-by: Orgad Shaneh --- src/libs/3rdparty/cplusplus/Lexer.cpp | 16 ++++++++++------ tests/auto/cplusplus/lexer/tst_lexer.cpp | 8 ++++++++ tests/auto/cplusplus/misc/tst_misc.cpp | 13 +++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Lexer.cpp b/src/libs/3rdparty/cplusplus/Lexer.cpp index e62c9412a4e..079ae0ca6e6 100644 --- a/src/libs/3rdparty/cplusplus/Lexer.cpp +++ b/src/libs/3rdparty/cplusplus/Lexer.cpp @@ -211,7 +211,7 @@ void Lexer::scan_helper(Token *tok) _state = 0; scanCppComment(originalKind); return; - } else if (isRawStringLiteral(s._tokenKind)) { + } else if (!control() && isRawStringLiteral(s._tokenKind)) { tok->f.kind = s._tokenKind; if (scanUntilRawStringLiteralEndSimple()) _state = 0; @@ -755,13 +755,17 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) yyinp(); } else if (_yychar == ')') { yyinp(); - if (delimLength == -1) - break; + if (delimLength == -1) { + tok->f.kind = T_ERROR; + return; + } closingDelimCandidate = _currentChar; } else { if (delimLength == -1) { - if (_yychar == '\\' || std::isspace(_yychar)) - break; + if (_yychar == '\\' || std::isspace(_yychar)) { + tok->f.kind = T_ERROR; + return; + } yyinp(); } else { if (!closingDelimCandidate) { @@ -804,7 +808,7 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) else tok->f.kind = T_RAW_STRING_LITERAL; - if (!closed) + if (!control() && !closed) s._tokenKind = tok->f.kind; } diff --git a/tests/auto/cplusplus/lexer/tst_lexer.cpp b/tests/auto/cplusplus/lexer/tst_lexer.cpp index a2c415d33c2..1721efaedd6 100644 --- a/tests/auto/cplusplus/lexer/tst_lexer.cpp +++ b/tests/auto/cplusplus/lexer/tst_lexer.cpp @@ -366,6 +366,14 @@ void tst_SimpleLexer::literals_data() << T_RAW_STRING_LITERAL ; QTest::newRow("raw-string-literals") << source << expectedTokenKindList; + + source = "R\"\\" ; + expectedTokenKindList = TokenKindList() << T_ERROR; + QTest::newRow("invalid-raw-string-literals1") << source << expectedTokenKindList; + + source = "R\")" ; + expectedTokenKindList = TokenKindList() << T_ERROR; + QTest::newRow("invalid-raw-string-literals2") << source << expectedTokenKindList; } void tst_SimpleLexer::preprocessor() diff --git a/tests/auto/cplusplus/misc/tst_misc.cpp b/tests/auto/cplusplus/misc/tst_misc.cpp index aff5a12ce0b..808408df407 100644 --- a/tests/auto/cplusplus/misc/tst_misc.cpp +++ b/tests/auto/cplusplus/misc/tst_misc.cpp @@ -48,6 +48,8 @@ private slots: void astPathOnGeneratedTokens(); void typeMatcher(); + + void doNotCrashForInvalidRawString(); }; void tst_Misc::diagnosticClient_error() @@ -266,5 +268,16 @@ void tst_Misc::typeMatcher() } } +void tst_Misc::doNotCrashForInvalidRawString() +{ + const QByteArray src("\n" + "void f() { enum { Size = sizeof(R\"[^\\s]+([^]+)*\") }; }" + "}\n" + ); + Document::Ptr doc = Document::create("crash"); + doc->setUtf8Source(src); + doc->check(); +} + QTEST_MAIN(tst_Misc) #include "tst_misc.moc" From 846d89811a72f96909ad137fb973983f568c3643 Mon Sep 17 00:00:00 2001 From: Filipe Azevedo Date: Tue, 19 Sep 2017 12:37:56 +0200 Subject: [PATCH 11/63] Fix unstoppable debugger For some reason sometimes a user stop request with lldb can trigger a spontaneous stop, avoiding the debugger to stop correctly. This change fix the issue by emitting the correct states from lldbbridge.py. Change-Id: Ib8a2f4875824f4fff426b2d5e0fc4a79ce48c68e Reviewed-by: hjk --- share/qtcreator/debugger/lldbbridge.py | 6 ++---- src/plugins/debugger/lldb/lldbengine.cpp | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 9c85907f9a9..968572bb4d3 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -1240,9 +1240,7 @@ class Dumper(DumperBase): if not skipEventReporting: self.eventState = state if state == lldb.eStateExited: - if self.isShuttingDown_: - self.reportState("inferiorshutdownok") - else: + if not self.isShuttingDown_: self.reportState("inferiorexited") self.report('exited={status="%s",desc="%s"}' % (self.process.GetExitStatus(), self.process.GetExitDescription())) @@ -1272,7 +1270,7 @@ class Dumper(DumperBase): return if self.isInterrupting_: self.isInterrupting_ = False - self.reportState("stopped") + self.reportState("inferiorstopok") elif self.ignoreStops > 0: self.ignoreStops -= 1 self.process.Continue() diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index a844d982481..256f3ce4eeb 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -910,6 +910,8 @@ void LldbEngine::handleStateNotification(const GdbMi &reportedState) } } else if (newState == "inferiorstopok") { notifyInferiorStopOk(); + if (!isDying()) + updateAll(); } else if (newState == "inferiorstopfailed") notifyInferiorStopFailed(); else if (newState == "inferiorill") From a83d038208cb1e8f4430e5eb3ef5ae8e93636131 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Mon, 18 Sep 2017 11:23:09 +0200 Subject: [PATCH 12/63] Sqlite: Improve exception handling Introducing different exceptions for different error cases. Change-Id: I4371d1e64d9dca2a9f68dcbaa4a891c55879c1f5 Reviewed-by: Tim Jenssen Reviewed-by: Marco Bubke --- src/libs/sqlite/sqlitedatabasebackend.cpp | 30 ++- src/libs/sqlite/sqlitedatabasebackend.h | 5 +- src/libs/sqlite/sqliteexception.h | 207 ++++++++++++++++++ src/libs/sqlite/sqlitereadstatement.cpp | 2 +- src/libs/sqlite/sqlitestatement.cpp | 139 ++++++++---- src/libs/sqlite/sqlitestatement.h | 13 +- src/libs/sqlite/sqlitewritestatement.cpp | 2 +- .../unittest/sqlitedatabasebackend-test.cpp | 11 +- tests/unit/unittest/sqlitestatement-test.cpp | 89 ++++++-- 9 files changed, 419 insertions(+), 79 deletions(-) diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp index bef03ea9865..14919ec9fa7 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.cpp +++ b/src/libs/sqlite/sqlitedatabasebackend.cpp @@ -31,6 +31,7 @@ #include "sqlitestatement.h" #include "sqlitewritestatement.h" +#include #include #include @@ -230,24 +231,29 @@ void DatabaseBackend::cacheTextEncoding() void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed() { if (m_databaseHandle == nullptr) - throwException("SqliteDatabaseBackend::close: database is not open so it can not be closed."); + throw DatabaseIsAlreadyClosed("SqliteDatabaseBackend::close: database is not open so it can not be closed."); } void DatabaseBackend::checkDatabaseClosing(int resultCode) { switch (resultCode) { case SQLITE_OK: return; - default: throwException("SqliteDatabaseBackend::close: unknown error happens at closing!"); + case SQLITE_BUSY: throw DatabaseIsBusy("SqliteDatabaseBackend::close: database is busy because of e.g. unfinalized statements and will stay open!"); + default: throwUnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!"); } } void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath) { if (databaseFilePath.isEmpty()) - throw Exception("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database file path is empty!"); + throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because the file path is empty!"); + + if (!QFileInfo::exists(QFileInfo(QString(databaseFilePath)).path())) + throw WrongFilePath("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because of wrong file path!", + Utils::SmallString(databaseFilePath)); if (databaseIsOpen()) - throw Exception("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database is already open!"); + throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because it is already open!"); } void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode) @@ -262,16 +268,16 @@ void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode) } void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue, - Utils::SmallStringView expectedValue) + Utils::SmallStringView expectedValue) { if (databaseValue != expectedValue) - throwException("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!"); + throw PragmaValueNotSet("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!"); } void DatabaseBackend::checkDatabaseHandleIsNotNull() { if (m_databaseHandle == nullptr) - throwException("SqliteDatabaseBackend: database is not open!"); + throwDatabaseIsNotOpen("SqliteDatabaseBackend: database is not open!"); } void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode) @@ -392,6 +398,16 @@ void DatabaseBackend::throwException(const char *whatHasHappens) const throw Exception(whatHasHappens); } +void DatabaseBackend::throwUnknowError(const char *whatHasHappens) const +{ + throw UnknowError(whatHasHappens); +} + +void DatabaseBackend::throwDatabaseIsNotOpen(const char *whatHasHappens) const +{ + throw DatabaseIsNotOpen(whatHasHappens); +} + template Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement) { diff --git a/src/libs/sqlite/sqlitedatabasebackend.h b/src/libs/sqlite/sqlitedatabasebackend.h index 7e5b9aad02a..2cadd808469 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.h +++ b/src/libs/sqlite/sqlitedatabasebackend.h @@ -110,8 +110,9 @@ protected: Q_NORETURN static void throwExceptionStatic(const char *whatHasHappens); - Q_NORETURN void throwException(const char *whatHasHappens) const; - + [[noreturn]] void throwException(const char *whatHasHappens) const; + [[noreturn]] void throwUnknowError(const char *whatHasHappens) const; + [[noreturn]] void throwDatabaseIsNotOpen(const char *whatHasHappens) const; private: Database &m_database; diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h index 3ce2c20e9b9..319141d2573 100644 --- a/src/libs/sqlite/sqliteexception.h +++ b/src/libs/sqlite/sqliteexception.h @@ -48,4 +48,211 @@ private: Utils::SmallString m_sqliteErrorMessage; }; +class StatementIsBusy : public Exception +{ +public: + StatementIsBusy(const char *whatErrorHasHappen, + Utils::SmallString &&sqliteErrorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage)) + { + } +}; + +class DatabaseIsBusy : public Exception +{ +public: + DatabaseIsBusy(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class StatementHasError : public Exception +{ +public: + StatementHasError(const char *whatErrorHasHappen, + Utils::SmallString &&sqliteErrorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage)) + { + } +}; + +class StatementIsMisused : public Exception +{ +public: + StatementIsMisused(const char *whatErrorHasHappen, + Utils::SmallString &&sqliteErrorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage)) + { + } +}; + +class ContraintPreventsModification : public Exception +{ +public: + ContraintPreventsModification(const char *whatErrorHasHappen, + Utils::SmallString &&sqliteErrorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage)) + { + } +}; + +class NoValuesToFetch : public Exception +{ +public: + NoValuesToFetch(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class InvalidColumnFetched : public Exception +{ +public: + InvalidColumnFetched(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class BindingIndexIsOutOfRange : public Exception +{ +public: + BindingIndexIsOutOfRange(const char *whatErrorHasHappen, + Utils::SmallString &&sqliteErrorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage)) + { + } +}; + +class WrongBingingName : public Exception +{ +public: + WrongBingingName(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class DatabaseIsNotOpen : public Exception +{ +public: + DatabaseIsNotOpen(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class DatabaseCannotBeOpened : public Exception +{ +public: + DatabaseCannotBeOpened(const char *whatErrorHasHappen, + Utils::SmallString &&errorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(errorMessage)) + { + } +}; + +class DatabaseFilePathIsEmpty : public DatabaseCannotBeOpened +{ +public: + DatabaseFilePathIsEmpty(const char *whatErrorHasHappen) + : DatabaseCannotBeOpened(whatErrorHasHappen) + { + } +}; + +class DatabaseIsAlreadyOpen : public DatabaseCannotBeOpened +{ +public: + DatabaseIsAlreadyOpen(const char *whatErrorHasHappen) + : DatabaseCannotBeOpened(whatErrorHasHappen) + { + } +}; + +class DatabaseCannotBeClosed : public Exception +{ +public: + DatabaseCannotBeClosed(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class DatabaseIsAlreadyClosed : public DatabaseCannotBeClosed +{ +public: + DatabaseIsAlreadyClosed(const char *whatErrorHasHappen) + : DatabaseCannotBeClosed(whatErrorHasHappen) + { + } +}; + +class WrongFilePath : public DatabaseCannotBeOpened +{ +public: + WrongFilePath(const char *whatErrorHasHappen, + Utils::SmallString &&errorMessage = Utils::SmallString()) + : DatabaseCannotBeOpened(whatErrorHasHappen, std::move(errorMessage)) + { + } +}; + +class PragmaValueNotSet : public Exception +{ +public: + PragmaValueNotSet(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class NotReadOnlySqlStatement : public Exception +{ +public: + NotReadOnlySqlStatement(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class NotWriteSqlStatement : public Exception +{ +public: + NotWriteSqlStatement(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class DeadLock : public Exception +{ +public: + DeadLock(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + { + } +}; + +class UnknowError : public Exception +{ +public: + UnknowError(const char *whatErrorHasHappen, + Utils::SmallString &&errorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(errorMessage)) + { + } +}; + +class BindingTooBig : public Exception +{ +public: + BindingTooBig(const char *whatErrorHasHappen, + Utils::SmallString &&errorMessage = Utils::SmallString()) + : Exception(whatErrorHasHappen, std::move(errorMessage)) + { + } +}; + } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitereadstatement.cpp b/src/libs/sqlite/sqlitereadstatement.cpp index ec9e59c4a37..9af95f1cffa 100644 --- a/src/libs/sqlite/sqlitereadstatement.cpp +++ b/src/libs/sqlite/sqlitereadstatement.cpp @@ -39,7 +39,7 @@ ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement, void ReadStatement::checkIsReadOnlyStatement() { if (!isReadOnlyStatement()) - throwException("SqliteStatement::SqliteReadStatement: is not read only statement!"); + throw NotReadOnlySqlStatement("SqliteStatement::SqliteReadStatement: is not read only statement!"); } } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitestatement.cpp b/src/libs/sqlite/sqlitestatement.cpp index 709822ef95e..1e7a0829c89 100644 --- a/src/libs/sqlite/sqlitestatement.cpp +++ b/src/libs/sqlite/sqlitestatement.cpp @@ -95,19 +95,26 @@ private: void Statement::waitForUnlockNotify() const { UnlockNotification unlockNotification; - int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), UnlockNotification::unlockNotifyCallBack, &unlockNotification); + int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), + UnlockNotification::unlockNotifyCallBack, + &unlockNotification); - if (resultCode == SQLITE_OK) - unlockNotification.wait(); - else - throwException("SqliteStatement::waitForUnlockNotify: database is in a dead lock!"); + if (resultCode == SQLITE_LOCKED) + throw DeadLock("SqliteStatement::waitForUnlockNotify: database is in a dead lock!"); + + unlockNotification.wait(); } void Statement::reset() const { int resultCode = sqlite3_reset(m_compiledStatement.get()); - if (resultCode != SQLITE_OK) - throwException("SqliteStatement::reset: can't reset statement!"); + switch (resultCode) { + case SQLITE_OK: return; + case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!"); + case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!"); + case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!"); + case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!"); + } m_isReadyToFetchValues = false; } @@ -159,30 +166,30 @@ Utils::SmallStringVector Statement::columnNames() const void Statement::bind(int index, int value) { - int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value); - if (resultCode != SQLITE_OK) - throwException("SqliteStatement::bind: cant' bind 32 bit integer!"); + int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value); + checkForBindingError(resultCode); } void Statement::bind(int index, long long value) { - int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value); - if (resultCode != SQLITE_OK) - throwException("SqliteStatement::bind: cant' bind 64 bit integer!"); + int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value); + checkForBindingError(resultCode); } void Statement::bind(int index, double value) { int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value); - if (resultCode != SQLITE_OK) - throwException("SqliteStatement::bind: cant' bind double!"); + checkForBindingError(resultCode); } void Statement::bind(int index, Utils::SmallStringView text) { - int resultCode = sqlite3_bind_text(m_compiledStatement.get(), index, text.data(), int(text.size()), SQLITE_TRANSIENT); - if (resultCode != SQLITE_OK) - throwException("SqliteStatement::bind: cant' bind double!"); + int resultCode = sqlite3_bind_text(m_compiledStatement.get(), + index, + text.data(), + int(text.size()), + SQLITE_TRANSIENT); + checkForBindingError(resultCode); } template @@ -250,13 +257,13 @@ bool Statement::checkForStepError(int resultCode) const switch (resultCode) { case SQLITE_ROW: return true; case SQLITE_DONE: return false; - case SQLITE_BUSY: throwException("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!"); - case SQLITE_ERROR : throwException("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!"); - case SQLITE_MISUSE: throwException("SqliteStatement::stepStatement: was called inappropriately!"); - case SQLITE_CONSTRAINT: throwException("SqliteStatement::stepStatement: contraint prevent insert or update!"); + case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!"); + case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!"); + case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!"); + case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!"); } - throwException("SqliteStatement::stepStatement: unknown error has happened"); + throwUnknowError("SqliteStatement::stepStatement: unknown error has happened"); Q_UNREACHABLE(); } @@ -265,12 +272,24 @@ void Statement::checkForPrepareError(int resultCode) const { switch (resultCode) { case SQLITE_OK: return; - case SQLITE_BUSY: throwException("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!"); - case SQLITE_ERROR : throwException("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!"); - case SQLITE_MISUSE: throwException("SqliteStatement::prepareStatement: was called inappropriately!"); + case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!"); + case SQLITE_ERROR : throwStatementHasError("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!"); + case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::prepareStatement: was called inappropriately!"); } - throwException("SqliteStatement::prepareStatement: unknown error has happened"); + throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened"); +} + +void Statement::checkForBindingError(int resultCode) const +{ + switch (resultCode) { + case SQLITE_OK: return; + case SQLITE_TOOBIG: throwBingingTooBig("SqliteStatement::bind: string or blob are over size limits(SQLITE_LIMIT_LENGTH)!"); + case SQLITE_RANGE : throwBindingIndexIsOutOfRange("SqliteStatement::bind: binding index is out of range!"); + case SQLITE_NOMEM: throw std::bad_alloc(); + } + + throwUnknowError("SqliteStatement::bind: unknown error has happened"); } void Statement::setIfIsReadyToFetchValues(int resultCode) const @@ -285,33 +304,27 @@ void Statement::setIfIsReadyToFetchValues(int resultCode) const void Statement::checkIfIsReadyToFetchValues() const { if (!m_isReadyToFetchValues) - throwException("SqliteStatement::value: there are no values to fetch!"); + throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!"); } void Statement::checkColumnsAreValid(const std::vector &columns) const { for (int column : columns) { if (column < 0 || column >= m_columnCount) - throwException("SqliteStatement::values: column index out of bound!"); + throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!"); } } void Statement::checkColumnIsValid(int column) const { if (column < 0 || column >= m_columnCount) - throwException("SqliteStatement::values: column index out of bound!"); -} - -void Statement::checkBindingIndex(int index) const -{ - if (index <= 0 || index > m_bindingParameterCount) - throwException("SqliteStatement::bind: binding index is out of bound!"); + throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!"); } void Statement::checkBindingName(int index) const { if (index <= 0 || index > m_bindingParameterCount) - throwException("SqliteStatement::bind: binding name are not exists in this statement!"); + throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!"); } void Statement::setBindingParameterCount() @@ -345,9 +358,57 @@ bool Statement::isReadOnlyStatement() const return sqlite3_stmt_readonly(m_compiledStatement.get()); } -void Statement::throwException(const char *whatHasHappened) const +void Statement::throwStatementIsBusy(const char *whatHasHappened) const { - throw Exception(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); + throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); +} + +void Statement::throwStatementHasError(const char *whatHasHappened) const +{ + throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); +} + +void Statement::throwStatementIsMisused(const char *whatHasHappened) const +{ + throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); +} + +void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const +{ + throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); +} + +void Statement::throwNoValuesToFetch(const char *whatHasHappened) const +{ + throw NoValuesToFetch(whatHasHappened); +} + +void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const +{ + throw InvalidColumnFetched(whatHasHappened); +} + +void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const +{ + throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); +} + +void Statement::throwWrongBingingName(const char *whatHasHappened) const +{ + throw WrongBingingName(whatHasHappened); +} + +void Statement::throwUnknowError(const char *whatHasHappened) const +{ + if (sqliteDatabaseHandle()) + throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); + else + throw UnknowError(whatHasHappened); +} + +void Statement::throwBingingTooBig(const char *whatHasHappened) const +{ + throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } QString Statement::columnName(int column) const diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitestatement.h index 0e73de836f8..d1f7bb1906f 100644 --- a/src/libs/sqlite/sqlitestatement.h +++ b/src/libs/sqlite/sqlitestatement.h @@ -355,17 +355,26 @@ protected: bool checkForStepError(int resultCode) const; void checkForPrepareError(int resultCode) const; + void checkForBindingError(int resultCode) const; void setIfIsReadyToFetchValues(int resultCode) const; void checkIfIsReadyToFetchValues() const; void checkColumnsAreValid(const std::vector &columns) const; void checkColumnIsValid(int column) const; - void checkBindingIndex(int index) const; void checkBindingName(int index) const; void setBindingParameterCount(); void setBindingColumnNamesFromStatement(); void setColumnCount(); bool isReadOnlyStatement() const; - Q_NORETURN void throwException(const char *whatHasHappened) const; + [[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const; + [[noreturn]] void throwStatementHasError(const char *whatHasHappened) const; + [[noreturn]] void throwStatementIsMisused(const char *whatHasHappened) const; + [[noreturn]] void throwConstraintPreventsModification(const char *whatHasHappened) const; + [[noreturn]] void throwNoValuesToFetch(const char *whatHasHappened) const; + [[noreturn]] void throwInvalidColumnFetched(const char *whatHasHappened) const; + [[noreturn]] void throwBindingIndexIsOutOfRange(const char *whatHasHappened) const; + [[noreturn]] void throwWrongBingingName(const char *whatHasHappened) const; + [[noreturn]] void throwUnknowError(const char *whatHasHappened) const; + [[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const; template ContainerType columnValues(const std::vector &columnIndices) const; diff --git a/src/libs/sqlite/sqlitewritestatement.cpp b/src/libs/sqlite/sqlitewritestatement.cpp index 7878a284d37..26c8522b8a5 100644 --- a/src/libs/sqlite/sqlitewritestatement.cpp +++ b/src/libs/sqlite/sqlitewritestatement.cpp @@ -37,7 +37,7 @@ WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement, void WriteStatement::checkIsWritableStatement() { if (isReadOnlyStatement()) - throwException("SqliteStatement::SqliteWriteStatement: is not a writable statement!"); + throw NotWriteSqlStatement("SqliteStatement::SqliteWriteStatement: is not a writable statement!"); } } // namespace Sqlite diff --git a/tests/unit/unittest/sqlitedatabasebackend-test.cpp b/tests/unit/unittest/sqlitedatabasebackend-test.cpp index fb7fb032d9f..7663139f013 100644 --- a/tests/unit/unittest/sqlitedatabasebackend-test.cpp +++ b/tests/unit/unittest/sqlitedatabasebackend-test.cpp @@ -61,19 +61,21 @@ using SqliteDatabaseBackendSlowTest = SqliteDatabaseBackend; TEST_F(SqliteDatabaseBackend, OpenAlreadyOpenDatabase) { - ASSERT_THROW(databaseBackend.open(databaseFilePath, OpenMode::ReadWrite), Exception); + ASSERT_THROW(databaseBackend.open(databaseFilePath, OpenMode::ReadWrite), + Sqlite::DatabaseIsAlreadyOpen); } TEST_F(SqliteDatabaseBackend, CloseAlreadyClosedDatabase) { databaseBackend.close(); - ASSERT_THROW(databaseBackend.close(), Exception); + ASSERT_THROW(databaseBackend.close(), Sqlite::DatabaseIsAlreadyClosed); } TEST_F(SqliteDatabaseBackend, OpenWithWrongPath) { - ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db", OpenMode::ReadWrite), Exception); + ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db", OpenMode::ReadWrite), + Sqlite::WrongFilePath); } TEST_F(SqliteDatabaseBackend, DefaultJournalMode) @@ -148,7 +150,8 @@ TEST_F(SqliteDatabaseBackend, TextEncodingCannotBeChangedAfterTouchingDatabase) databaseBackend.execute("CREATE TABLE text(name, number)"); - ASSERT_THROW(databaseBackend.setTextEncoding(TextEncoding::Utf16), Exception); + ASSERT_THROW(databaseBackend.setTextEncoding(TextEncoding::Utf16), + Sqlite::PragmaValueNotSet); } TEST_F(SqliteDatabaseBackend, OpenModeReadOnly) diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index 21eabdfadd2..33703cf085a 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -87,12 +87,21 @@ struct Output } }; -TEST_F(SqliteStatement, PrepareFailure) +TEST_F(SqliteStatement, ThrowsStatementHasErrorForWrongSqlStatement) { - ASSERT_THROW(ReadStatement("blah blah blah", database), Exception); - ASSERT_THROW(WriteStatement("blah blah blah", database), Exception); - ASSERT_THROW(ReadStatement("INSERT INTO test(name, number) VALUES (?, ?)", database), Exception); - ASSERT_THROW(WriteStatement("SELECT name, number FROM test '", database), Exception); + ASSERT_THROW(ReadStatement("blah blah blah", database), Sqlite::StatementHasError); +} + +TEST_F(SqliteStatement, ThrowsNotReadOnlySqlStatementForWritableSqlStatementInReadStatement) +{ + ASSERT_THROW(ReadStatement("INSERT INTO test(name, number) VALUES (?, ?)", database), + Sqlite::NotReadOnlySqlStatement); +} + +TEST_F(SqliteStatement, ThrowsNotReadonlySqlStatementForWritableSqlStatementInReadStatement) +{ + ASSERT_THROW(WriteStatement("SELECT name, number FROM test", database), + Sqlite::NotWriteSqlStatement); } TEST_F(SqliteStatement, CountRows) @@ -124,21 +133,35 @@ TEST_F(SqliteStatement, Value) ASSERT_THAT(statement.text(1), "23.3"); } -TEST_F(SqliteStatement, ValueFailure) +TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement) { ReadStatement statement("SELECT name, number FROM test", database); - ASSERT_THROW(statement.value(0), Exception); - statement.reset(); + ASSERT_THROW(statement.value(0), Sqlite::NoValuesToFetch); +} +TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement) +{ + ReadStatement statement("SELECT name, number FROM test", database); while (statement.next()) {} - ASSERT_THROW(statement.value(0), Exception); - statement.reset(); + ASSERT_THROW(statement.value(0), Sqlite::NoValuesToFetch); +} +TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn) +{ + ReadStatement statement("SELECT name, number FROM test", database); statement.next(); - ASSERT_THROW(statement.value(-1), Exception); - ASSERT_THROW(statement.value(2), Exception); + + ASSERT_THROW(statement.value(-1), Sqlite::InvalidColumnFetched); +} + +TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn) +{ + ReadStatement statement("SELECT name, number FROM test", database); + statement.next(); + + ASSERT_THROW(statement.value(2), Sqlite::InvalidColumnFetched); } TEST_F(SqliteStatement, ToIntergerValue) @@ -245,13 +268,25 @@ TEST_F(SqliteStatement, BindDoubleByIndex) ASSERT_THAT(statement.text(0), "foo"); } -TEST_F(SqliteStatement, BindFailure) +TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBound) { - ReadStatement statement("SELECT name, number FROM test WHERE number=@number", database); + ReadStatement statement("SELECT name, number FROM test WHERE number=$1", database); - ASSERT_THROW(statement.bind(0, 40), Exception); - ASSERT_THROW(statement.bind(2, 40), Exception); - ASSERT_THROW(statement.bind("@name", 40), Exception); + ASSERT_THROW(statement.bind(0, 40), Sqlite::BindingIndexIsOutOfRange); +} + +TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBound) +{ + ReadStatement statement("SELECT name, number FROM test WHERE number=$1", database); + + ASSERT_THROW(statement.bind(2, 40), Sqlite::BindingIndexIsOutOfRange); +} + +TEST_F(SqliteStatement, WrongBindingNameThrowingBindingIndexIsOutOfBound) +{ + ReadStatement statement("SELECT name, number FROM test WHERE number=@name", database); + + ASSERT_THROW(statement.bind("@name2", 40), Sqlite::WrongBingingName); } TEST_F(SqliteStatement, RequestBindingNamesFromStatement) @@ -299,13 +334,20 @@ TEST_F(SqliteStatement, WriteNamedValues) ASSERT_THAT(statement, HasValues("see", "7.23", 1)); } -TEST_F(SqliteStatement, ClosedDatabase) +TEST_F(SqliteStatement, CannotWriteToClosedDatabase) { database.close(); - ASSERT_THROW(WriteStatement("INSERT INTO test(name, number) VALUES (?, ?)", database), Exception); - ASSERT_THROW(ReadStatement("SELECT * FROM test", database), Exception); - ASSERT_THROW(ReadWriteStatement("INSERT INTO test(name, number) VALUES (?, ?)", database), Exception); - database.open(QDir::tempPath() + QStringLiteral("/SqliteStatementTest.db")); + + ASSERT_THROW(WriteStatement("INSERT INTO test(name, number) VALUES (?, ?)", database), + Sqlite::DatabaseIsNotOpen); +} + +TEST_F(SqliteStatement, CannotReadFromClosedDatabase) +{ + database.close(); + + ASSERT_THROW(ReadStatement("SELECT * FROM test", database), + Sqlite::DatabaseIsNotOpen); } TEST_F(SqliteStatement, GetTupleValuesWithoutArguments) @@ -461,7 +503,8 @@ void SqliteStatement::SetUp() void SqliteStatement::TearDown() { - database.close(); + if (database.isOpen()) + database.close(); } } From c870199823885da6cb90beea3b1224fe6930eb1a Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Mon, 18 Sep 2017 15:59:08 +0200 Subject: [PATCH 13/63] Sqlite: Don't use the lower level interface of the statements We now have the very powerful write and read methods, so using the low level interface leads only to stupid errors and prevents optimizations. Change-Id: If2340833977935cb2d319735dee96b0bac33142b Reviewed-by: Tim Jenssen Reviewed-by: Marco Bubke --- src/libs/sqlite/sqlitereadstatement.h | 12 ----- src/libs/sqlite/sqlitereadwritestatement.h | 12 ----- src/libs/sqlite/sqlitewritestatement.h | 7 --- tests/unit/unittest/sqlitestatement-test.cpp | 43 ++++++++-------- tests/unit/unittest/sqliteteststatement.h | 54 ++++++++++++++++++++ tests/unit/unittest/unittest.pro | 3 +- 6 files changed, 78 insertions(+), 53 deletions(-) create mode 100644 tests/unit/unittest/sqliteteststatement.h diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h index c20221c34f9..1fddb3afce2 100644 --- a/src/libs/sqlite/sqlitereadstatement.h +++ b/src/libs/sqlite/sqlitereadstatement.h @@ -34,21 +34,9 @@ class SQLITE_EXPORT ReadStatement final : private Statement public: explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database); - using Statement::next; - using Statement::reset; - using Statement::value; using Statement::structValues; using Statement::tupleValues; - using Statement::text; using Statement::values; - using Statement::columnCount; - using Statement::columnNames; - using Statement::bind; - using Statement::bindValues; - using Statement::bindNameValues; - using Statement::bindingIndexForName; - using Statement::setBindingColumnNames; - using Statement::bindingColumnNames; using Statement::toValue; using Statement::database; diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h index 4b982525e7f..8c8d2541984 100644 --- a/src/libs/sqlite/sqlitereadwritestatement.h +++ b/src/libs/sqlite/sqlitereadwritestatement.h @@ -36,22 +36,10 @@ class SQLITE_EXPORT ReadWriteStatement final : private Statement public: ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database); - using Statement::next; using Statement::execute; - using Statement::reset; - using Statement::bind; - using Statement::bindValues; - using Statement::bindNameValues; - using Statement::bindingIndexForName; - using Statement::setBindingColumnNames; - using Statement::bindingColumnNames; - using Statement::value; - using Statement::text; using Statement::values; using Statement::structValues; using Statement::tupleValues; - using Statement::columnCount; - using Statement::columnNames; using Statement::toValue; using Statement::database; using Statement::write; diff --git a/src/libs/sqlite/sqlitewritestatement.h b/src/libs/sqlite/sqlitewritestatement.h index c673bbae201..ec00ae4e8f1 100644 --- a/src/libs/sqlite/sqlitewritestatement.h +++ b/src/libs/sqlite/sqlitewritestatement.h @@ -35,13 +35,6 @@ public: explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database); using Statement::execute; - using Statement::reset; - using Statement::bind; - using Statement::bindValues; - using Statement::bindNameValues; - using Statement::bindingIndexForName; - using Statement::setBindingColumnNames; - using Statement::bindingColumnNames; using Statement::database; using Statement::write; using Statement::writeNamed; diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index 33703cf085a..54be7bd0be9 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "googletest.h" +#include "sqliteteststatement.h" #include #include @@ -54,7 +55,7 @@ MATCHER_P3(HasValues, value1, value2, rowid, { Database &database = arg.database(); - ReadStatement statement("SELECT name, number FROM test WHERE rowid=?", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE rowid=?", database); statement.bind(1, rowid); statement.next(); @@ -106,7 +107,7 @@ TEST_F(SqliteStatement, ThrowsNotReadonlySqlStatementForWritableSqlStatementInRe TEST_F(SqliteStatement, CountRows) { - ReadStatement statement("SELECT * FROM test", database); + SqliteTestStatement statement("SELECT * FROM test", database); int nextCount = 0; while (statement.next()) ++nextCount; @@ -118,7 +119,7 @@ TEST_F(SqliteStatement, CountRows) TEST_F(SqliteStatement, Value) { - ReadStatement statement("SELECT name, number FROM test ORDER BY name", database); + SqliteTestStatement statement("SELECT name, number FROM test ORDER BY name", database); statement.next(); statement.next(); @@ -135,14 +136,14 @@ TEST_F(SqliteStatement, Value) TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement) { - ReadStatement statement("SELECT name, number FROM test", database); + SqliteTestStatement statement("SELECT name, number FROM test", database); ASSERT_THROW(statement.value(0), Sqlite::NoValuesToFetch); } TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement) { - ReadStatement statement("SELECT name, number FROM test", database); + SqliteTestStatement statement("SELECT name, number FROM test", database); while (statement.next()) {} ASSERT_THROW(statement.value(0), Sqlite::NoValuesToFetch); @@ -150,7 +151,7 @@ TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement) TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn) { - ReadStatement statement("SELECT name, number FROM test", database); + SqliteTestStatement statement("SELECT name, number FROM test", database); statement.next(); ASSERT_THROW(statement.value(-1), Sqlite::InvalidColumnFetched); @@ -158,7 +159,7 @@ TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn) TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn) { - ReadStatement statement("SELECT name, number FROM test", database); + SqliteTestStatement statement("SELECT name, number FROM test", database); statement.next(); ASSERT_THROW(statement.value(2), Sqlite::InvalidColumnFetched); @@ -188,7 +189,7 @@ TEST_F(SqliteStatement, ToStringValue) TEST_F(SqliteStatement, ColumnNames) { - ReadStatement statement("SELECT name, number FROM test", database); + SqliteTestStatement statement("SELECT name, number FROM test", database); auto columnNames = statement.columnNames(); @@ -198,7 +199,7 @@ TEST_F(SqliteStatement, ColumnNames) TEST_F(SqliteStatement, BindString) { - ReadStatement statement("SELECT name, number FROM test WHERE name=?", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE name=?", database); statement.bind(1, "foo"); @@ -210,7 +211,7 @@ TEST_F(SqliteStatement, BindString) TEST_F(SqliteStatement, BindInteger) { - ReadStatement statement("SELECT name, number FROM test WHERE number=?", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database); statement.bind(1, 40); statement.next(); @@ -220,7 +221,7 @@ TEST_F(SqliteStatement, BindInteger) TEST_F(SqliteStatement, BindLongInteger) { - ReadStatement statement("SELECT name, number FROM test WHERE number=?", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database); statement.bind(1, int64_t(40)); statement.next(); @@ -230,7 +231,7 @@ TEST_F(SqliteStatement, BindLongInteger) TEST_F(SqliteStatement, BindDouble) { - ReadStatement statement("SELECT name, number FROM test WHERE number=?", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database); statement.bind(1, 23.3); statement.next(); @@ -240,7 +241,7 @@ TEST_F(SqliteStatement, BindDouble) TEST_F(SqliteStatement, BindIntegerByParameter) { - ReadStatement statement("SELECT name, number FROM test WHERE number=@number", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@number", database); statement.bind("@number", 40); statement.next(); @@ -250,7 +251,7 @@ TEST_F(SqliteStatement, BindIntegerByParameter) TEST_F(SqliteStatement, BindLongIntegerByParameter) { - ReadStatement statement("SELECT name, number FROM test WHERE number=@number", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@number", database); statement.bind("@number", int64_t(40)); statement.next(); @@ -260,7 +261,7 @@ TEST_F(SqliteStatement, BindLongIntegerByParameter) TEST_F(SqliteStatement, BindDoubleByIndex) { - ReadStatement statement("SELECT name, number FROM test WHERE number=@number", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@number", database); statement.bind(statement.bindingIndexForName("@number"), 23.3); statement.next(); @@ -270,35 +271,35 @@ TEST_F(SqliteStatement, BindDoubleByIndex) TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBound) { - ReadStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(0, 40), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBound) { - ReadStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, 40), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, WrongBindingNameThrowingBindingIndexIsOutOfBound) { - ReadStatement statement("SELECT name, number FROM test WHERE number=@name", database); + SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@name", database); ASSERT_THROW(statement.bind("@name2", 40), Sqlite::WrongBingingName); } TEST_F(SqliteStatement, RequestBindingNamesFromStatement) { - WriteStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database); + SqliteTestStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database); ASSERT_THAT(statement.bindingColumnNames(), ElementsAre("name", "number", "id")); } TEST_F(SqliteStatement, BindValues) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + SqliteTestStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.bindValues("see", 7.23, 1); statement.execute(); @@ -317,7 +318,7 @@ TEST_F(SqliteStatement, WriteValues) TEST_F(SqliteStatement, BindNamedValues) { - WriteStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database); + SqliteTestStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database); statement.bindNameValues("@name", "see", "@number", 7.23, "@id", 1); statement.execute(); diff --git a/tests/unit/unittest/sqliteteststatement.h b/tests/unit/unittest/sqliteteststatement.h new file mode 100644 index 00000000000..43b6ab884c1 --- /dev/null +++ b/tests/unit/unittest/sqliteteststatement.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#pragma once + +#include + +class SQLITE_EXPORT SqliteTestStatement : public Sqlite::Statement +{ +public: + explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database) + : Sqlite::Statement(sqlStatement, database) + {} + + using Statement::bind; + using Statement::bindingColumnNames; + using Statement::bindingIndexForName; + using Statement::bindNameValues; + using Statement::bindValues; + using Statement::columnNames; + using Statement::database; + using Statement::execute; + using Statement::next; + using Statement::text; + using Statement::value; + +protected: + void checkIsWritableStatement(); +}; + diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 4b579ac7792..0a3a50f1584 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -200,7 +200,8 @@ HEADERS += \ mocksqlitedatabase.h \ mocksqlitereadstatement.h \ google-using-declarations.h \ - mocksymbolindexing.h + mocksymbolindexing.h \ + sqliteteststatement.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \ From ee5efe06e66c250cb822c1f20e76d965b1f65053 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Mon, 18 Sep 2017 15:53:51 +0200 Subject: [PATCH 14/63] Sqlite: Don't copy values for binding In Sqlite as you bind value you can bind or simply use a reference to the bound values. Because we hold the values anyway we do not copy them. Change-Id: I11c6fa5036ea958c8e48e3a117ad4a002d749c22 Reviewed-by: Tim Jenssen Reviewed-by: Marco Bubke --- src/libs/sqlite/sqlitestatement.cpp | 2 +- src/libs/sqlite/sqlitestatement.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libs/sqlite/sqlitestatement.cpp b/src/libs/sqlite/sqlitestatement.cpp index 1e7a0829c89..ba64f44a398 100644 --- a/src/libs/sqlite/sqlitestatement.cpp +++ b/src/libs/sqlite/sqlitestatement.cpp @@ -188,7 +188,7 @@ void Statement::bind(int index, Utils::SmallStringView text) index, text.data(), int(text.size()), - SQLITE_TRANSIENT); + SQLITE_STATIC); checkForBindingError(resultCode); } diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitestatement.h index d1f7bb1906f..6c3848e6798 100644 --- a/src/libs/sqlite/sqlitestatement.h +++ b/src/libs/sqlite/sqlitestatement.h @@ -84,26 +84,26 @@ protected: } template - void bindValues(ValueType... values) + void bindValues(const ValueType&... values) { bindValuesByIndex(1, values...); } template - void write(ValueType... values) + void write(const ValueType&... values) { bindValuesByIndex(1, values...); execute(); } template - void bindNameValues(ValueType... values) + void bindNameValues(const ValueType&... values) { bindValuesByName(values...); } template - void writeNamed(ValueType... values) + void writeNamed(const ValueType&... values) { bindValuesByName(values...); execute(); @@ -420,26 +420,26 @@ private: } template - void bindValuesByIndex(int index, ValueType value) + void bindValuesByIndex(int index, const ValueType &value) { bind(index, value); } template - void bindValuesByIndex(int index, ValueType value, ValueTypes... values) + void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values) { bind(index, value); bindValuesByIndex(index + 1, values...); } template - void bindValuesByName(Utils::SmallStringView name, ValueType value) + void bindValuesByName(Utils::SmallStringView name, const ValueType &value) { bind(bindingIndexForName(name), value); } template - void bindValuesByName(Utils::SmallStringView name, ValueType value, ValueTypes... values) + void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values) { bind(bindingIndexForName(name), value); bindValuesByName(values...); From 623135592c069a1d760b28e96aab6a5012fccc12 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 19 Sep 2017 11:48:47 +0200 Subject: [PATCH 15/63] Sqlite: Add locking for sqlite transactions If you use the database in a multi-threaded environment, you must always your statements in transactions. For read-only statements, you use DeferredTransaction and write statements you use ImmediateTransaction. If you mix read and write statements you have to use ImmediateTransaction. Don't use DeferredTransaction because it leads to undefined behavior. Change-Id: Ida298a20f33423c8da09e768a7b658dd8e918f46 Reviewed-by: Tim Jenssen Reviewed-by: Marco Bubke --- src/libs/sqlite/sqlitedatabase.h | 14 ++- src/libs/sqlite/sqlitetransaction.h | 6 +- tests/unit/unittest/mockmutex.h | 37 ++++++ tests/unit/unittest/mocksqlitedatabase.h | 13 ++ .../unit/unittest/sqlitetransaction-test.cpp | 115 ++++++++++++++++++ .../storagesqlitestatementfactory-test.cpp | 15 ++- tests/unit/unittest/symbolstorage-test.cpp | 6 +- tests/unit/unittest/unittest.pro | 6 +- 8 files changed, 201 insertions(+), 11 deletions(-) create mode 100644 tests/unit/unittest/mockmutex.h create mode 100644 tests/unit/unittest/sqlitetransaction-test.cpp diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h index 8bbdbb7de2e..7ba79513461 100644 --- a/src/libs/sqlite/sqlitedatabase.h +++ b/src/libs/sqlite/sqlitedatabase.h @@ -31,6 +31,7 @@ #include +#include #include namespace Sqlite { @@ -38,11 +39,13 @@ namespace Sqlite { class SQLITE_EXPORT Database { template - friend class SqliteAbstractTransaction; - friend class SqliteStatement; - friend class SqliteBackend; + friend class AbstractTransaction; + friend class Statement; + friend class Backend; public: + using MutexType = std::mutex; + Database(); Database(Utils::PathString &&databaseFilePath); @@ -79,12 +82,13 @@ public: private: void initializeTables(); - + std::mutex &databaseMutex() { return m_databaseMutex; } private: + Utils::PathString m_databaseFilePath; DatabaseBackend m_databaseBackend; std::vector m_sqliteTables; - Utils::PathString m_databaseFilePath; + std::mutex m_databaseMutex; JournalMode m_journalMode = JournalMode::Wal; OpenMode m_openMode = OpenMode::ReadWrite; bool m_isOpen = false; diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h index 183923cfa60..d271728baea 100644 --- a/src/libs/sqlite/sqlitetransaction.h +++ b/src/libs/sqlite/sqlitetransaction.h @@ -27,6 +27,8 @@ #include "sqliteglobal.h" +#include + namespace Sqlite { class DatabaseBackend; @@ -50,11 +52,13 @@ public: protected: AbstractTransaction(Database &database) - : m_database(database) + : m_databaseLock(database.databaseMutex()), + m_database(database) { } private: + std::lock_guard m_databaseLock; Database &m_database; bool m_isAlreadyCommited = false; }; diff --git a/tests/unit/unittest/mockmutex.h b/tests/unit/unittest/mockmutex.h new file mode 100644 index 00000000000..cccb34e2ff2 --- /dev/null +++ b/tests/unit/unittest/mockmutex.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +class MockMutex +{ +public: + using MutexType = MockMutex; + + MOCK_METHOD0(lock, void ()); + MOCK_METHOD0(unlock, void ()); +}; diff --git a/tests/unit/unittest/mocksqlitedatabase.h b/tests/unit/unittest/mocksqlitedatabase.h index 55c06cb81e4..bad4eefda2e 100644 --- a/tests/unit/unittest/mocksqlitedatabase.h +++ b/tests/unit/unittest/mocksqlitedatabase.h @@ -27,6 +27,8 @@ #include "googletest.h" +#include "mockmutex.h" + #include #include @@ -34,8 +36,19 @@ class MockSqliteDatabase { public: + using MutexType = MockMutex; + + MockSqliteDatabase() = default; + MockSqliteDatabase(const MockMutex &mockMutex) + { + ON_CALL(*this, databaseMutex()) + .WillByDefault(ReturnRef(const_cast(mockMutex))); + } + MOCK_METHOD1(execute, void (Utils::SmallStringView sqlStatement)); + MOCK_METHOD0(databaseMutex, + MockMutex &()); }; diff --git a/tests/unit/unittest/sqlitetransaction-test.cpp b/tests/unit/unittest/sqlitetransaction-test.cpp new file mode 100644 index 00000000000..69f90a71221 --- /dev/null +++ b/tests/unit/unittest/sqlitetransaction-test.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include +#include + +namespace { + +using DeferredTransaction = Sqlite::DeferredTransaction; +using ImmediateTransaction = Sqlite::ImmediateTransaction; +using ExclusiveTransaction = Sqlite::ExclusiveTransaction; + +class SqliteTransaction : public testing::Test +{ +protected: + MockMutex mockMutex; + MockSqliteDatabase mockDatabase{mockMutex}; +}; + +TEST_F(SqliteTransaction, DeferredTransactionCommit) +{ + EXPECT_CALL(mockDatabase, databaseMutex()); + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); + + DeferredTransaction transaction{mockDatabase}; + transaction.commit(); +} + +TEST_F(SqliteTransaction, DeferredTransactionRollBack) +{ + EXPECT_CALL(mockDatabase, databaseMutex()); + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN"))); + EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK"))); + EXPECT_CALL(mockMutex, unlock()); + + DeferredTransaction transaction{mockDatabase}; +} + +TEST_F(SqliteTransaction, ImmediateTransactionCommit) +{ + EXPECT_CALL(mockDatabase, databaseMutex()); + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); + + ImmediateTransaction transaction{mockDatabase}; + transaction.commit(); +} + +TEST_F(SqliteTransaction, ImmediateTransactionRollBack) +{ + EXPECT_CALL(mockDatabase, databaseMutex()); + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); + EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK"))); + EXPECT_CALL(mockMutex, unlock()); + + ImmediateTransaction transaction{mockDatabase}; +} + +TEST_F(SqliteTransaction, ExclusiveTransactionCommit) +{ + EXPECT_CALL(mockDatabase, databaseMutex()); + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN EXCLUSIVE"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); + + ExclusiveTransaction transaction{mockDatabase}; + transaction.commit(); +} + +TEST_F(SqliteTransaction, ExclusiveTransactionRollBack) +{ + EXPECT_CALL(mockDatabase, databaseMutex()); + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN EXCLUSIVE"))); + EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK"))); + EXPECT_CALL(mockMutex, unlock()); + + ExclusiveTransaction transaction{mockDatabase}; +} + +} + + diff --git a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp index cdf48b5817c..f9c2576702b 100644 --- a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp @@ -42,7 +42,8 @@ using Sqlite::Table; class StorageSqliteStatementFactory : public testing::Test { protected: - NiceMock mockDatabase; + NiceMock mockMutex; + NiceMock mockDatabase{mockMutex}; StatementFactory factory{mockDatabase}; }; @@ -50,10 +51,12 @@ TEST_F(StorageSqliteStatementFactory, AddSymbolsTable) { InSequence s; + EXPECT_CALL(mockMutex, lock()); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); factory.createSymbolsTable(); } @@ -62,10 +65,12 @@ TEST_F(StorageSqliteStatementFactory, AddLocationsTable) { InSequence s; + EXPECT_CALL(mockMutex, lock()); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); factory.createLocationsTable(); } @@ -74,9 +79,11 @@ TEST_F(StorageSqliteStatementFactory, AddSourcesTable) { InSequence s; + EXPECT_CALL(mockMutex, lock()); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); factory.createSourcesTable(); } @@ -85,11 +92,13 @@ TEST_F(StorageSqliteStatementFactory, AddNewSymbolsTable) { InSequence s; + EXPECT_CALL(mockMutex, lock()); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); factory.createNewSymbolsTable(); } @@ -99,10 +108,12 @@ TEST_F(StorageSqliteStatementFactory, AddNewLocationsTable) { InSequence s; + EXPECT_CALL(mockMutex, lock()); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newLocations_sourceId ON newLocations(sourceId)"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); factory.createNewLocationsTable(); } @@ -111,6 +122,8 @@ TEST_F(StorageSqliteStatementFactory, AddTablesInConstructor) { EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))).Times(5); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(5); + EXPECT_CALL(mockMutex, lock()).Times(5); + EXPECT_CALL(mockMutex, unlock()).Times(5); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp index fd8715b71b6..2628157a330 100644 --- a/tests/unit/unittest/symbolstorage-test.cpp +++ b/tests/unit/unittest/symbolstorage-test.cpp @@ -59,9 +59,9 @@ protected: protected: FilePathCache filePathCache; - NiceMock mockDatabase; + NiceMock mockMutex; + NiceMock mockDatabase{mockMutex}; StatementFactory statementFactory{mockDatabase}; - MockSqliteWriteStatement &insertSymbolsToNewSymbolsStatement = statementFactory.insertSymbolsToNewSymbolsStatement; MockSqliteWriteStatement &insertLocationsToNewLocationsStatement = statementFactory.insertLocationsToNewLocationsStatement; MockSqliteWriteStatement &insertSourcesStatement = statementFactory.insertSourcesStatement; @@ -172,6 +172,7 @@ TEST_F(SymbolStorage, AddSymbolsAndSourceLocationsCallsWrite) { InSequence sequence; + EXPECT_CALL(mockMutex, lock()); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(insertSymbolsToNewSymbolsStatement, write(_, _, _)).Times(2); EXPECT_CALL(insertLocationsToNewLocationsStatement, write(1, 42, 23, 3)); @@ -188,6 +189,7 @@ TEST_F(SymbolStorage, AddSymbolsAndSourceLocationsCallsWrite) EXPECT_CALL(deleteNewSymbolsTableStatement, execute()); EXPECT_CALL(deleteNewLocationsTableStatement, execute()); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); storage.addSymbolsAndSourceLocations(symbolEntries, sourceLocations); } diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 0a3a50f1584..f2f4c52d16b 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -74,7 +74,8 @@ SOURCES += \ symbolquery-test.cpp \ storagesqlitestatementfactory-test.cpp \ querysqlitestatementfactory-test.cpp \ - sqliteindex-test.cpp + sqliteindex-test.cpp \ + sqlitetransaction-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -201,7 +202,8 @@ HEADERS += \ mocksqlitereadstatement.h \ google-using-declarations.h \ mocksymbolindexing.h \ - sqliteteststatement.h + sqliteteststatement.h \ + mockmutex.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \ From 2df9a99cac658c363b8bdf096aac4309d534a01e Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 19 Sep 2017 17:56:54 +0200 Subject: [PATCH 16/63] Clang: Add RefactoringDatabaseInitializer We moved the creation of the tables and indices to an extra class which can be called from other places. So you can be sure that a database is initialized. Change-Id: Ief5b30ced7b9011ca94367aa2578098423dcecd9 Reviewed-by: Tim Jenssen --- src/libs/clangsupport/clangsupport-lib.pri | 3 +- .../refactoringdatabaseinitializer.h | 93 +++++++++++++++++++ .../source/storagesqlitestatementfactory.h | 53 ----------- .../source/symbolindexing.h | 7 +- .../refactoringdatabaseinitializer-test.cpp | 92 ++++++++++++++++++ .../storagesqlitestatementfactory-test.cpp | 54 +---------- tests/unit/unittest/unittest.pro | 3 +- 7 files changed, 198 insertions(+), 107 deletions(-) create mode 100644 src/libs/clangsupport/refactoringdatabaseinitializer.h create mode 100644 tests/unit/unittest/refactoringdatabaseinitializer-test.cpp diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index f7bd2674aec..6c7d00b7d87 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -175,6 +175,7 @@ HEADERS += \ $$PWD/requestsourcerangesforquerymessage.h \ $$PWD/stringcachefwd.h \ $$PWD/stringcachealgorithms.h \ - $$PWD/projectmanagementserverinterface.h + $$PWD/projectmanagementserverinterface.h \ + $$PWD/refactoringdatabaseinitializer.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h new file mode 100644 index 00000000000..29f41d621e9 --- /dev/null +++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#include +#include + +namespace ClangBackEnd { + +template +class RefactoringDatabaseInitializer +{ +public: + RefactoringDatabaseInitializer(DatabaseType &database) + : database(database) + { + Sqlite::ImmediateTransaction transaction{database}; + + createSymbolsTable(); + createLocationsTable(); + createSourcesTable(); + + transaction.commit(); + } + + void createSymbolsTable() + { + Sqlite::Table table; + table.setUseIfNotExists(true); + table.setName("symbols"); + table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); + const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text); + table.addColumn("symbolName", Sqlite::ColumnType::Text); + table.addIndex({usrColumn}); + + table.initialize(database); + } + + void createLocationsTable() + { + Sqlite::Table table; + table.setUseIfNotExists(true); + table.setName("locations"); + table.addColumn("symbolId", Sqlite::ColumnType::Integer); + table.addColumn("line", Sqlite::ColumnType::Integer); + table.addColumn("column", Sqlite::ColumnType::Integer); + const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); + table.addIndex({sourceIdColumn}); + + table.initialize(database); + } + + void createSourcesTable() + { + Sqlite::Table table; + table.setUseIfNotExists(true); + table.setName("sources"); + table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); + table.addColumn("sourcePath", Sqlite::ColumnType::Text); + + table.initialize(database); + } + +public: + DatabaseType &database; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h index 118fb8182a5..c144c7a9c51 100644 --- a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h +++ b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h @@ -47,56 +47,6 @@ public: { } - Sqlite::Table createSymbolsTable() - { - Sqlite::Table table; - table.setUseIfNotExists(true); - table.setName("symbols"); - table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); - const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text); - table.addColumn("symbolName", Sqlite::ColumnType::Text); - table.addIndex({usrColumn}); - - Sqlite::ImmediateTransaction transaction(database); - table.initialize(database); - transaction.commit(); - - return table; - } - - Sqlite::Table createLocationsTable() - { - Sqlite::Table table; - table.setUseIfNotExists(true); - table.setName("locations"); - table.addColumn("symbolId", Sqlite::ColumnType::Integer); - table.addColumn("line", Sqlite::ColumnType::Integer); - table.addColumn("column", Sqlite::ColumnType::Integer); - const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); - table.addIndex({sourceIdColumn}); - - Sqlite::ImmediateTransaction transaction(database); - table.initialize(database); - transaction.commit(); - - return table; - } - - Sqlite::Table createSourcesTable() - { - Sqlite::Table table; - table.setUseIfNotExists(true); - table.setName("sources"); - table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); - table.addColumn("sourcePath", Sqlite::ColumnType::Text); - - Sqlite::ImmediateTransaction transaction(database); - table.initialize(database); - transaction.commit(); - - return table; - } - Sqlite::Table createNewSymbolsTable() const { Sqlite::Table table; @@ -137,9 +87,6 @@ public: public: Database &database; - Sqlite::Table symbolsTable{createSymbolsTable()}; - Sqlite::Table locationsTable{createLocationsTable()}; - Sqlite::Table sourcesTable{createSourcesTable()}; Sqlite::Table newSymbolsTablet{createNewSymbolsTable()}; Sqlite::Table newLocationsTable{createNewLocationsTable()}; WriteStatement insertSymbolsToNewSymbolsStatement{ diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h index 7a8da5aafb7..4dd173e1bfb 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexing.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h @@ -32,6 +32,7 @@ #include "symbolscollector.h" #include "symbolstorage.h" +#include #include #include @@ -47,12 +48,13 @@ public: Sqlite::ReadStatement, Sqlite::WriteStatement>; using Storage = ClangBackEnd::SymbolStorage; + using DatabaseInitializer = RefactoringDatabaseInitializer; SymbolIndexing(FilePathCache &filePathCache, Utils::PathString &&databaseFilePath) : m_filePathCache(filePathCache), - m_database(std::move(databaseFilePath)) - + m_database(std::move(databaseFilePath)), + m_databaseInitializer(m_database) { } @@ -75,6 +77,7 @@ public: private: FilePathCache &m_filePathCache; Sqlite::Database m_database; + DatabaseInitializer m_databaseInitializer; SymbolsCollector m_collector{m_filePathCache}; StatementFactory m_statementFactory{m_database}; Storage m_symbolStorage{m_statementFactory, m_filePathCache}; diff --git a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp new file mode 100644 index 00000000000..3f1c52a0212 --- /dev/null +++ b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include + +#include + +namespace { + +using Initializer = ClangBackEnd::RefactoringDatabaseInitializer>; + +using Sqlite::Table; + +class RefactoringDatabaseInitializer : public testing::Test +{ +protected: + NiceMock mockMutex; + NiceMock mockDatabase{mockMutex}; + Initializer initializer{mockDatabase}; +}; + +TEST_F(RefactoringDatabaseInitializer, AddSymbolsTable) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); + + initializer.createSymbolsTable(); +} + +TEST_F(RefactoringDatabaseInitializer, AddLocationsTable) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); + + initializer.createLocationsTable(); +} + +TEST_F(RefactoringDatabaseInitializer, AddSourcesTable) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); + + initializer.createSourcesTable(); +} + + +TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor) +{ + InSequence s; + + EXPECT_CALL(mockMutex, lock()); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); + EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); + EXPECT_CALL(mockMutex, unlock()); + + Initializer initializer{mockDatabase}; +} +} diff --git a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp index f9c2576702b..0995663ad44 100644 --- a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp @@ -47,47 +47,6 @@ protected: StatementFactory factory{mockDatabase}; }; -TEST_F(StorageSqliteStatementFactory, AddSymbolsTable) -{ - InSequence s; - - EXPECT_CALL(mockMutex, lock()); - EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); - EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); - EXPECT_CALL(mockMutex, unlock()); - - factory.createSymbolsTable(); -} - -TEST_F(StorageSqliteStatementFactory, AddLocationsTable) -{ - InSequence s; - - EXPECT_CALL(mockMutex, lock()); - EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); - EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); - EXPECT_CALL(mockMutex, unlock()); - - factory.createLocationsTable(); -} - -TEST_F(StorageSqliteStatementFactory, AddSourcesTable) -{ - InSequence s; - - EXPECT_CALL(mockMutex, lock()); - EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); - EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); - EXPECT_CALL(mockMutex, unlock()); - - factory.createSourcesTable(); -} - TEST_F(StorageSqliteStatementFactory, AddNewSymbolsTable) { InSequence s; @@ -120,16 +79,11 @@ TEST_F(StorageSqliteStatementFactory, AddNewLocationsTable) TEST_F(StorageSqliteStatementFactory, AddTablesInConstructor) { - EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))).Times(5); - EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(5); - EXPECT_CALL(mockMutex, lock()).Times(5); - EXPECT_CALL(mockMutex, unlock()).Times(5); + EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))).Times(2); + EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(2); + EXPECT_CALL(mockMutex, lock()).Times(2); + EXPECT_CALL(mockMutex, unlock()).Times(2); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)"))); - EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)"))); diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index f2f4c52d16b..25ba21f42f8 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -75,7 +75,8 @@ SOURCES += \ storagesqlitestatementfactory-test.cpp \ querysqlitestatementfactory-test.cpp \ sqliteindex-test.cpp \ - sqlitetransaction-test.cpp + sqlitetransaction-test.cpp \ + refactoringdatabaseinitializer-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ From 899c518c6daffb3c6440642550593e2cc76ab6c4 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Wed, 20 Sep 2017 12:52:03 +0200 Subject: [PATCH 17/63] Android: Fix ma-make detection Broken by 71b56d2b9c3264bd481915c763aac685c1ad24d0 Change-Id: I8d92cb1f0ecfcb401f063ba49c357acac8cc832c Reviewed-by: Orgad Shaneh --- src/plugins/android/androidtoolchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index bb3b10ee92b..3d89d3018d3 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -213,7 +213,7 @@ QString AndroidToolChain::makeCommand(const Environment &env) const if (HostOsInfo::isWindowsHost()) { FileName tmp = env.searchInPath(QLatin1String("ma-make.exe"), extraDirectories); if (!tmp.isEmpty()) - return QString(); + return tmp.toString(); tmp = env.searchInPath(QLatin1String("mingw32-make"), extraDirectories); return tmp.isEmpty() ? QLatin1String("mingw32-make") : tmp.toString(); } From 434e895b7389e1499e971aa53aeae01f268a2604 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 18 Sep 2017 14:47:39 +0200 Subject: [PATCH 18/63] Debugger: Remove parts of the engine parameter fixup phase The idea is that the fixup should not be needed at all anymore, instead, static data coming e.g. from the RunConfiguration should be setup in the constructor, and everything else should be ready at entry into start(). This also proceeds on path to the planned-but-never-implemented idea that the RunConfiguration should (at most) be accessed at RunControl creation time, not later. Change-Id: I04d622785f5de628a7bb479bc0c39aff7d6cce01 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerengine.h | 3 +- src/plugins/debugger/debuggerruncontrol.cpp | 242 ++++++++------------ src/plugins/debugger/debuggerruncontrol.h | 5 +- 3 files changed, 105 insertions(+), 145 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 74fafa81434..e2a3b404a49 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -88,7 +88,6 @@ public: Utils::ProcessHandle attachPID; QStringList solibSearchPath; bool useTerminal = false; - bool needFixup = true; // FIXME: Make false the default... // Used by Qml debugging. QUrl qmlServer; @@ -160,6 +159,8 @@ public: // For Debugger testing. int testCase = 0; + + QStringList validationErrors; }; class UpdateParameters diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 0cf35d9d7c1..6946d8395d3 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -82,8 +82,6 @@ DebuggerEngine *createQmlEngine(bool useTerminal); DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal); DebuggerEngine *createLldbEngine(); -static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, QStringList &m_errors); - class LocalProcessRunner : public RunWorker { public: @@ -330,11 +328,6 @@ void DebuggerRunTool::setDeviceSymbolsRoot(const QString &deviceSymbolsRoot) m_runParameters.deviceSymbolsRoot = deviceSymbolsRoot; } -void DebuggerRunTool::setNeedFixup(bool on) -{ - m_runParameters.needFixup = on; -} - void DebuggerRunTool::setTestCase(int testCase) { m_runParameters.testCase = testCase; @@ -471,10 +464,8 @@ void DebuggerRunTool::start() // return; // } - if (!Internal::fixupParameters(m_runParameters, runControl(), m_errors)) { - reportFailure(m_errors.join('\n')); + if (!fixupParameters()) return; - } Utils::globalMacroExpander()->registerFileVariables( "DebuggedExecutable", tr("Debugged executable"), @@ -484,12 +475,19 @@ void DebuggerRunTool::start() runControl()->setDisplayName(m_runParameters.displayName); DebuggerEngine *cppEngine = nullptr; + switch (m_runParameters.cppEngineType) { case GdbEngineType: cppEngine = createGdbEngine(m_runParameters.useTerminal, m_runParameters.startMode); break; - case CdbEngineType: - cppEngine = createCdbEngine(&m_errors, m_runParameters.startMode); + case CdbEngineType: { + QStringList errors; + cppEngine = createCdbEngine(&errors, m_runParameters.startMode); + if (!errors.isEmpty()) { + reportFailure(errors.join('\n')); + return; + } + } break; case LldbEngineType: cppEngine = createLldbEngine(); @@ -516,9 +514,8 @@ void DebuggerRunTool::start() } if (!m_engine) { - m_errors.append(DebuggerPlugin::tr("Unable to create a debugging engine of the type \"%1\""). + reportFailure(DebuggerPlugin::tr("Unable to create a debugging engine of the type \"%1\""). arg(engineTypeName(m_runParameters.masterEngineType))); - reportFailure(m_errors.join('\n')); return; } @@ -615,145 +612,38 @@ void DebuggerRunTool::abortDebugger() m_engine->abortDebugger(); } -/////////////////////////////////////////////////////////////////////// -// -// DebuggerRunControlCreator -// -/////////////////////////////////////////////////////////////////////// - -namespace Internal { - -static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, QStringList &m_errors) +bool DebuggerRunTool::fixupParameters() { - RunConfiguration *runConfig = runControl->runConfiguration(); - if (!runConfig) - return false; - - const Kit *kit = runConfig->target()->kit(); - QTC_ASSERT(kit, return false); - - // Extract as much as possible from available RunConfiguration. - const Runnable runnable = runConfig->runnable(); - if (rp.needFixup && runnable.is()) { - // FIXME: Needed for core dump which stores the executable in inferior, but not in runConfig - // executable. - const QString prevExecutable = rp.inferior.executable; - rp.inferior = runnable.as(); - if (rp.inferior.executable.isEmpty()) - rp.inferior.executable = prevExecutable; - rp.useTerminal = rp.inferior.runMode == ApplicationLauncher::Console; - // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...) - rp.inferior.workingDirectory = FileUtils::normalizePathName(rp.inferior.workingDirectory); - } - - // We might get an executable from a local PID. - if (rp.needFixup && rp.inferior.executable.isEmpty() && rp.attachPID.isValid()) { - foreach (const DeviceProcessItem &p, DeviceProcessList::localProcesses()) { - if (p.pid == rp.attachPID.pid()) { - rp.inferior.executable = p.exe; - break; - } - } - } - - rp.macroExpander = kit->macroExpander(); + DebuggerRunParameters &rp = m_runParameters; if (rp.symbolFile.isEmpty()) rp.symbolFile = rp.inferior.executable; - rp.debugger = DebuggerKitInformation::runnable(kit); - const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH"); - if (!envBinary.isEmpty()) - rp.debugger.executable = QString::fromLocal8Bit(envBinary); + rp.stubEnvironment = rp.inferior.environment; // FIXME: Wrong, but contains DYLD_IMAGE_SUFFIX - if (rp.needFixup) { - if (auto envAspect = runConfig->extraAspect()) { - rp.inferior.environment = envAspect->environment(); // Correct. - rp.stubEnvironment = rp.inferior.environment; // FIXME: Wrong, but contains DYLD_IMAGE_SUFFIX - - // Copy over DYLD_IMAGE_SUFFIX etc - for (auto var : QStringList({"DYLD_IMAGE_SUFFIX", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH"})) - if (rp.inferior.environment.hasKey(var)) - rp.debugger.environment.set(var, rp.inferior.environment.value(var)); - } - } - if (Project *project = runConfig->target()->project()) { - rp.projectSourceDirectory = project->projectDirectory().toString(); - rp.projectSourceFiles = project->files(Project::SourceFiles); - } - - rp.toolChainAbi = ToolChainKitInformation::targetAbi(kit); - - bool ok = false; - int nativeMixedOverride = qgetenv("QTC_DEBUGGER_NATIVE_MIXED").toInt(&ok); - if (ok) - rp.nativeMixedEnabled = bool(nativeMixedOverride); - - rp.cppEngineType = DebuggerKitInformation::engineType(kit); - if (rp.sysRoot.isEmpty()) - rp.sysRoot = SysRootKitInformation::sysRoot(kit).toString(); - - if (rp.displayName.isEmpty()) - rp.displayName = runConfig->displayName(); - - if (runConfig->property("supportsDebugger").toBool()) { - QString mainScript = runConfig->property("mainScript").toString(); - QString interpreter = runConfig->property("interpreter").toString(); - if (!interpreter.isEmpty() && mainScript.endsWith(".py")) { - rp.mainScript = mainScript; - rp.interpreter = interpreter; - QString args = runConfig->property("arguments").toString(); - if (!args.isEmpty()) { - if (!rp.inferior.commandLineArguments.isEmpty()) - rp.inferior.commandLineArguments.append(QLatin1Char(' ')); - rp.inferior.commandLineArguments.append(args); - } - rp.masterEngineType = PdbEngineType; - } - } - - if (auto debuggerAspect = runConfig->extraAspect()) { - rp.multiProcess = debuggerAspect->useMultiProcess(); - if (rp.languages == NoLanguage) { - if (debuggerAspect->useCppDebugger()) - rp.languages |= CppLanguage; - if (debuggerAspect->useQmlDebugger()) - rp.languages |= QmlLanguage; - } - } + // Copy over DYLD_IMAGE_SUFFIX etc + for (auto var : QStringList({"DYLD_IMAGE_SUFFIX", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH"})) + if (rp.inferior.environment.hasKey(var)) + rp.debugger.environment.set(var, rp.inferior.environment.value(var)); // This can happen e.g. when started from the command line. if (rp.languages == NoLanguage) rp.languages = CppLanguage; // validate debugger if C++ debugging is enabled - if (rp.languages & CppLanguage) { - const QList tasks = DebuggerKitInformation::validateDebugger(kit); - if (!tasks.isEmpty()) { - foreach (const Task &t, tasks) { - if (t.type == Task::Warning) - continue; - m_errors.append(t.description); - } - if (!m_errors.isEmpty()) - return false; - } + if (rp.languages & CppLanguage && !rp.validationErrors.isEmpty()) { + reportFailure(rp.validationErrors.join('\n')); + return false; } - IDevice::ConstPtr device = runControl->device(); if (rp.languages & QmlLanguage) { - if (device && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { - if (rp.qmlServer.host().isEmpty() || rp.qmlServer.port() <= 0) { - QTcpServer server; - const bool canListen = server.listen(QHostAddress::LocalHost) - || server.listen(QHostAddress::LocalHostIPv6); - if (!canListen) { - m_errors.append(DebuggerPlugin::tr("Not enough free ports for QML debugging.") + ' '); + if (device() && device()->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { + if (rp.qmlServer.port() <= 0) { + rp.qmlServer = ProjectExplorer::urlFromLocalHostAndFreePort(); + if (rp.qmlServer.port() <= 0) { + reportFailure(DebuggerPlugin::tr("Not enough free ports for QML debugging.")); return false; } - rp.qmlServer.setHost(server.serverAddress().toString()); - rp.qmlServer.setPort(server.serverPort()); } - // Makes sure that all bindings go through the JavaScript engine, so that // breakpoints are actually hit! const QString optimizerKey = "QML_DISABLE_OPTIMIZER"; @@ -817,8 +707,8 @@ static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, Q if (perr != QtcProcess::SplitOk) { // perr == BadQuoting is never returned on Windows // FIXME? QTCREATORBUG-2809 - m_errors.append(DebuggerPlugin::tr("Debugging complex command lines " - "is currently not supported on Windows.")); + reportFailure(DebuggerPlugin::tr("Debugging complex command lines " + "is currently not supported on Windows.")); return false; } } @@ -826,15 +716,14 @@ static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, Q // FIXME: We can't handle terminals yet. if (rp.useTerminal && rp.cppEngineType == LldbEngineType) { qWarning("Run in Terminal is not supported yet with the LLDB backend"); - m_errors.append(DebuggerPlugin::tr("Run in Terminal is not supported with the LLDB backend.")); + appendMessage(DebuggerPlugin::tr("Run in Terminal is not supported with the LLDB backend."), + ErrorMessageFormat); rp.useTerminal = false; } return true; } -} // Internal - static DebuggerRunConfigurationAspect *debuggerAspect(const RunControl *runControl) { return runControl->runConfiguration()->extraAspect(); @@ -871,9 +760,78 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl) QString(), QString(), optionalPrompt); }); - Runnable r = runnable(); + Runnable r = runnable(); { if (r.is()) m_runParameters.inferior = r.as(); + m_runParameters.useTerminal = m_runParameters.inferior.runMode == ApplicationLauncher::Console; + // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...) + m_runParameters.inferior.workingDirectory = + FileUtils::normalizePathName(m_runParameters.inferior.workingDirectory); + } + + RunConfiguration *runConfig = runControl->runConfiguration(); + QTC_ASSERT(runConfig, return); + + m_runParameters.displayName = runConfig->displayName(); + + const Kit *kit = runConfig->target()->kit(); + QTC_ASSERT(kit, return); + + m_runParameters.macroExpander = kit->macroExpander(); + + m_runParameters.debugger = DebuggerKitInformation::runnable(kit); + const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH"); + if (!envBinary.isEmpty()) + m_runParameters.debugger.executable = QString::fromLocal8Bit(envBinary); + + if (Project *project = runConfig->target()->project()) { + m_runParameters.projectSourceDirectory = project->projectDirectory().toString(); + m_runParameters.projectSourceFiles = project->files(Project::SourceFiles); + } + + m_runParameters.toolChainAbi = ToolChainKitInformation::targetAbi(kit); + + bool ok = false; + int nativeMixedOverride = qgetenv("QTC_DEBUGGER_NATIVE_MIXED").toInt(&ok); + if (ok) + m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride); + + m_runParameters.cppEngineType = DebuggerKitInformation::engineType(kit); + m_runParameters.sysRoot = SysRootKitInformation::sysRoot(kit).toString(); + + // This will only be shown in some cases, but we don't want to access + // the kit at that time anymore. + const QList tasks = DebuggerKitInformation::validateDebugger(kit); + for (const Task &t : tasks) { + if (t.type != Task::Warning) + m_runParameters.validationErrors.append(t.description); + } + + if (runConfig->property("supportsDebugger").toBool()) { + const QString mainScript = runConfig->property("mainScript").toString(); + const QString interpreter = runConfig->property("interpreter").toString(); + if (!interpreter.isEmpty() && mainScript.endsWith(".py")) { + m_runParameters.mainScript = mainScript; + m_runParameters.interpreter = interpreter; + const QString args = runConfig->property("arguments").toString(); + if (!args.isEmpty()) { + if (!m_runParameters.inferior.commandLineArguments.isEmpty()) + m_runParameters.inferior.commandLineArguments.append(' '); + m_runParameters.inferior.commandLineArguments.append(args); + } + m_runParameters.masterEngineType = PdbEngineType; + } + } + + if (auto debuggerAspect = runConfig->extraAspect()) { + m_runParameters.multiProcess = debuggerAspect->useMultiProcess(); + if (m_runParameters.languages == NoLanguage) { + if (debuggerAspect->useCppDebugger()) + m_runParameters.languages |= CppLanguage; + if (debuggerAspect->useQmlDebugger()) + m_runParameters.languages |= QmlLanguage; + } + } } DebuggerEngine *DebuggerRunTool::activeEngine() const diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h index 6bec12913da..24a9db3dba6 100644 --- a/src/plugins/debugger/debuggerruncontrol.h +++ b/src/plugins/debugger/debuggerruncontrol.h @@ -126,7 +126,7 @@ public: void setIosPlatform(const QString &platform); void setDeviceSymbolsRoot(const QString &deviceSymbolsRoot); - void setNeedFixup(bool on); + void setNeedFixup(bool) {} // FIXME: Remove after use in QtAppMan is gone. void setTestCase(int testCase); void setOverrideStartScript(const QString &script); void setToolChainAbi(const ProjectExplorer::Abi &abi); @@ -135,9 +135,10 @@ signals: void aboutToNotifyInferiorSetupOk(); private: + bool fixupParameters(); + QPointer m_engine; // Master engine Internal::DebuggerRunParameters m_runParameters; - QStringList m_errors; bool m_isDying = false; const bool m_isCppDebugging; const bool m_isQmlDebugging; From 3118bdcbd86960cc991f00e1fead898b3c47db46 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 19 Sep 2017 14:00:03 +0200 Subject: [PATCH 19/63] ProjectExplorer: Convert empty macro to "KEY=" -DKEY is the same as #define KEY 1 -DKEY= is the same as #define KEY Change-Id: I958a89d7b024999f1a623d4d309513ce342f6f8a Reviewed-by: Nikolai Kosjar Reviewed-by: Tobias Hunger --- src/plugins/projectexplorer/projectmacro.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/projectexplorer/projectmacro.cpp b/src/plugins/projectexplorer/projectmacro.cpp index cdbd48772e7..63f69b6986f 100644 --- a/src/plugins/projectexplorer/projectmacro.cpp +++ b/src/plugins/projectexplorer/projectmacro.cpp @@ -109,6 +109,8 @@ QByteArray Macro::toKeyValue(const QByteArray &prefix) const keyValue = prefix; if (value.isEmpty()) + keyValue += key + '='; + else if (value == "1") keyValue += key; else keyValue += key + '=' + value; From 50bd20de210d62c650fec387ff5708941b5a7c2e Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Sat, 16 Sep 2017 22:32:32 +0200 Subject: [PATCH 20/63] Welcome: Remove unused image mode_edit_mask.png must have been added there by mistake Change-Id: I94c0380f267f473c1ae1347f567ea959f0752496 Reviewed-by: Thomas Hartmann --- src/plugins/welcome/images/mode_edit_mask.png | Bin 189 -> 0 bytes src/plugins/welcome/welcome.qrc | 1 - 2 files changed, 1 deletion(-) delete mode 100644 src/plugins/welcome/images/mode_edit_mask.png diff --git a/src/plugins/welcome/images/mode_edit_mask.png b/src/plugins/welcome/images/mode_edit_mask.png deleted file mode 100644 index 221f49151933146e4b2c14b3632e08e750ea46a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 189 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7Sc;uILpV4%IBGajIv5xj zI14-?iy0VruY)k7lg8`{1_lPn64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xh zq!<_&tUO&DLo9leQxXz>oOfVMSmg5gfk6Z7%+LSr3lAPVaiSx^I6$I9WhcYUXN`r7 mX483^4J3X{vG~Boz@WTUP`*uP4Ko7+1B0ilpUXO@geCwV!#Q*S diff --git a/src/plugins/welcome/welcome.qrc b/src/plugins/welcome/welcome.qrc index 5321c6ebd46..28e8d22d1c8 100644 --- a/src/plugins/welcome/welcome.qrc +++ b/src/plugins/welcome/welcome.qrc @@ -8,7 +8,6 @@ images/blogs@2x.png images/community.png images/community@2x.png - images/mode_edit_mask.png images/open.png images/open@2x.png images/project.png From 6745536f1ec000aba8fe5e1e126cc282bc8197ba Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 20 Sep 2017 13:28:22 +0200 Subject: [PATCH 21/63] QmlDesigner: Fix @NodeInstance With @NodeInstance we can override the value of any property. Change-Id: Ib64d8b6823b82f0a809092b2468c008d73a5525c Reviewed-by: Tim Jenssen --- .../qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp index 875c80d3781..aef747fb9bb 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -979,7 +979,7 @@ void NodeInstanceServer::setInstanceAuxiliaryData(const PropertyValueContainer & } } if (auxiliaryContainer.name().endsWith("@NodeInstance")) { - PropertyName propertyName = auxiliaryContainer.name().left(auxiliaryContainer.name().count() - 12); + PropertyName propertyName = auxiliaryContainer.name().left(auxiliaryContainer.name().count() - 13); if (!auxiliaryContainer.value().isNull()) { setInstancePropertyVariant(PropertyValueContainer(auxiliaryContainer.instanceId(), propertyName, From ab1d1daee339c369ce00c6d806ae0e705d9cda64 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 20 Sep 2017 13:34:34 +0200 Subject: [PATCH 22/63] QmlDesigner: Remove exception An invalid model node has as valid internal node that can be used. Change-Id: I4b4f11546645455cbcc058e057402e869b0ae5a1 Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/designercore/model/modelnode.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index ce532708143..d73f96df940 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -749,10 +749,6 @@ bool operator <(const ModelNode &firstNode, const ModelNode &secondNode) Internal::InternalNodePointer ModelNode::internalNode() const { - if (!isValid()) { - Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid"); - throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__); - } return m_internalNode; } From 8fb3105e2598213ed14ecf282bb8685f7c38d1f4 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 7 Sep 2017 14:00:29 +0200 Subject: [PATCH 23/63] CMake: Add option to auto-create build directories Add an option to CMakeTools to force auto-creation of build directories. This does lead to cmake cluttering up the file system with directories, but does not force users to go through the oftentimes long configuration process twice (once in a temporary directory and once in the real location). Task-number: QTCREATORBUG-16794 Change-Id: I68d92fc58638ad0a0a7622b7ef1621e055c9f2a7 Reviewed-by: Leena Miettinen Reviewed-by: Tim Jenssen --- .../cmakeprojectmanager/builddirmanager.cpp | 17 +++++++-- .../cmakeprojectmanager/cmakesettingspage.cpp | 36 ++++++++++++++----- src/plugins/cmakeprojectmanager/cmaketool.cpp | 17 +++++++++ src/plugins/cmakeprojectmanager/cmaketool.h | 3 ++ 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index 86d9e0945f6..67ae9387af0 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -72,12 +73,22 @@ BuildDirManager::~BuildDirManager() = default; const Utils::FileName BuildDirManager::workDirectory() const { const Utils::FileName bdir = m_buildConfiguration->buildDirectory(); - if (bdir.exists()) + const CMakeTool *cmake = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit()); + if (bdir.exists()) { return bdir; + } else { + if (cmake && cmake->autoCreateBuildDirectory()) { + if (!QDir().mkpath(bdir.toString())) + emitErrorOccured(tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput())); + return bdir; + } + } if (!m_tempDir) { m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX")); - if (!m_tempDir->isValid()) - emitErrorOccured(tr("Failed to create temporary directory \"%1\".").arg(m_tempDir->path())); + if (!m_tempDir->isValid()) { + emitErrorOccured(tr("Failed to create temporary directory \"%1\".") + .arg(QDir::toNativeSeparators(m_tempDir->path()))); + } } return Utils::FileName::fromString(m_tempDir->path()); } diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp index 8381323759d..9f1b7538924 100644 --- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp +++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp @@ -66,13 +66,13 @@ public: CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const; CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const; - QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool isAutoDetected); + QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected); void addCMakeTool(const CMakeTool *item, bool changed); TreeItem *autoGroupItem() const; TreeItem *manualGroupItem() const; void reevaluateChangedFlag(CMakeToolTreeItem *item) const; void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable, - bool autoRun); + bool autoRun, bool autoCreate); void removeCMakeTool(const Core::Id &id); void apply(); @@ -95,16 +95,18 @@ public: m_name(item->displayName()), m_executable(item->cmakeExecutable()), m_isAutoRun(item->isAutoRun()), + m_autoCreateBuildDirectory(item->autoCreateBuildDirectory()), m_autodetected(item->isAutoDetected()), m_changed(changed) {} CMakeToolTreeItem(const QString &name, const Utils::FileName &executable, - bool autoRun, bool autodetected) : + bool autoRun, bool autoCreate, bool autodetected) : m_id(Core::Id::fromString(QUuid::createUuid().toString())), m_name(name), m_executable(executable), m_isAutoRun(autoRun), + m_autoCreateBuildDirectory(autoCreate), m_autodetected(autodetected), m_changed(true) {} @@ -143,6 +145,7 @@ public: QString m_name; FileName m_executable; bool m_isAutoRun = true; + bool m_autoCreateBuildDirectory = false; bool m_autodetected = false; bool m_changed = true; }; @@ -166,9 +169,10 @@ CMakeToolItemModel::CMakeToolItemModel() } QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable, - const bool autoRun, const bool isAutoDetected) + const bool autoRun, const bool autoCreate, + const bool isAutoDetected) { - CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, isAutoDetected); + CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, autoCreate, isAutoDetected); if (isAutoDetected) autoGroupItem()->appendChild(item); else @@ -219,7 +223,8 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const } void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName, - const FileName &executable, bool autoRun) + const FileName &executable, bool autoRun, + bool autoCreate) { CMakeToolTreeItem *treeItem = cmakeToolItem(id); QTC_ASSERT(treeItem, return); @@ -227,6 +232,7 @@ void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &disp treeItem->m_name = displayName; treeItem->m_executable = executable; treeItem->m_isAutoRun = autoRun; + treeItem->m_autoCreateBuildDirectory = autoCreate; reevaluateChangedFlag(treeItem); } @@ -262,6 +268,7 @@ void CMakeToolItemModel::apply() cmake->setDisplayName(item->m_name); cmake->setCMakeExecutable(item->m_executable); cmake->setAutorun(item->m_isAutoRun); + cmake->setAutoCreateBuildDirectory(item->m_autoCreateBuildDirectory); } else { toRegister.append(item); } @@ -329,6 +336,7 @@ private: CMakeToolItemModel *m_model; QLineEdit *m_displayNameLineEdit; QCheckBox *m_autoRunCheckBox; + QCheckBox *m_autoCreateBuildDirectoryCheckBox; PathChooser *m_binaryChooser; Core::Id m_id; bool m_loadingItem; @@ -349,11 +357,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) m_autoRunCheckBox->setText(tr("Autorun CMake")); m_autoRunCheckBox->setToolTip(tr("Automatically run CMake after changes to CMake project files.")); + m_autoCreateBuildDirectoryCheckBox = new QCheckBox; + m_autoCreateBuildDirectoryCheckBox->setText(tr("Auto-create build directories")); + m_autoCreateBuildDirectoryCheckBox->setToolTip(tr("Automatically create build directories for CMake projects.")); + QFormLayout *formLayout = new QFormLayout(this); formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit); formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser); formLayout->addRow(m_autoRunCheckBox); + formLayout->addRow(m_autoCreateBuildDirectoryCheckBox); connect(m_binaryChooser, &PathChooser::rawPathChanged, this, &CMakeToolItemConfigWidget::store); @@ -361,13 +374,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) this, &CMakeToolItemConfigWidget::store); connect(m_autoRunCheckBox, &QCheckBox::toggled, this, &CMakeToolItemConfigWidget::store); + connect(m_autoCreateBuildDirectoryCheckBox, &QCheckBox::toggled, + this, &CMakeToolItemConfigWidget::store); } void CMakeToolItemConfigWidget::store() const { if (!m_loadingItem && m_id.isValid()) m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(), - m_autoRunCheckBox->checkState() == Qt::Checked); + m_autoRunCheckBox->checkState() == Qt::Checked, + m_autoCreateBuildDirectoryCheckBox->checkState() == Qt::Checked); } void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) @@ -387,6 +403,7 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) m_binaryChooser->setFileName(item->m_executable); m_autoRunCheckBox->setChecked(item->m_isAutoRun); + m_autoCreateBuildDirectoryCheckBox->setChecked(item->m_autoCreateBuildDirectory); m_id = item->m_id; m_loadingItem = false; @@ -492,7 +509,8 @@ void CMakeToolConfigWidget::cloneCMakeTool() QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name), m_currentItem->m_executable, - m_currentItem->m_isAutoRun, false); + m_currentItem->m_isAutoRun, + m_currentItem->m_autoCreateBuildDirectory, false); m_cmakeToolsView->setCurrentIndex(newItem); } @@ -500,7 +518,7 @@ void CMakeToolConfigWidget::cloneCMakeTool() void CMakeToolConfigWidget::addCMakeTool() { QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")), - FileName(), true, false); + FileName(), true, false, false); m_cmakeToolsView->setCurrentIndex(newItem); } diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index 1a107ccd554..9c071dacb85 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -46,6 +46,7 @@ const char CMAKE_INFORMATION_ID[] = "Id"; const char CMAKE_INFORMATION_COMMAND[] = "Binary"; const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName"; const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun"; +const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory"; const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected"; @@ -68,6 +69,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected(fr m_id = Core::Id::fromSetting(map.value(CMAKE_INFORMATION_ID)); m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString(); m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool(); + m_autoCreateBuildDirectory = map.value(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, false).toBool(); //loading a CMakeTool from SDK is always autodetection if (!fromSdk) @@ -102,6 +104,15 @@ void CMakeTool::setAutorun(bool autoRun) CMakeToolManager::notifyAboutUpdate(this); } +void CMakeTool::setAutoCreateBuildDirectory(bool autoBuildDir) +{ + if (m_autoCreateBuildDirectory == autoBuildDir) + return; + + m_autoCreateBuildDirectory = autoBuildDir; + CMakeToolManager::notifyAboutUpdate(this); +} + bool CMakeTool::isValid() const { if (!m_id.isValid()) @@ -142,6 +153,7 @@ QVariantMap CMakeTool::toMap() const data.insert(CMAKE_INFORMATION_ID, m_id.toSetting()); data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString()); data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun); + data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory); data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected); return data; } @@ -162,6 +174,11 @@ bool CMakeTool::isAutoRun() const return m_isAutoRun; } +bool CMakeTool::autoCreateBuildDirectory() const +{ + return m_autoCreateBuildDirectory; +} + QList CMakeTool::supportedGenerators() const { readInformation(QueryType::GENERATORS); diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index 5851c75bfc7..95556cefd70 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -90,9 +90,11 @@ public: void setCMakeExecutable(const Utils::FileName &executable); void setAutorun(bool autoRun); + void setAutoCreateBuildDirectory(bool autoBuildDir); Utils::FileName cmakeExecutable() const; bool isAutoRun() const; + bool autoCreateBuildDirectory() const; QList supportedGenerators() const; TextEditor::Keywords keywords(); bool hasServerMode() const; @@ -127,6 +129,7 @@ private: bool m_isAutoRun = true; bool m_isAutoDetected = false; + bool m_autoCreateBuildDirectory = false; mutable bool m_didAttemptToRun = false; mutable bool m_didRun = false; From 2ec0b5a00e59f4110b44a6299c665d5416adb5b8 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 19 Sep 2017 11:51:45 +0200 Subject: [PATCH 24/63] CppTools: Fix warning about inconsistent use of override Use final consistently instead of override. Change-Id: I38df29fff98273d486bfd97c316492f27737a7c4 Reviewed-by: Nikolai Kosjar --- src/plugins/cpptools/cppmodelmanagersupportinternal.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.h b/src/plugins/cpptools/cppmodelmanagersupportinternal.h index fba0cb23e3c..b205ab47ecd 100644 --- a/src/plugins/cpptools/cppmodelmanagersupportinternal.h +++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.h @@ -40,10 +40,10 @@ public: ModelManagerSupportInternal(); virtual ~ModelManagerSupportInternal(); - virtual CppCompletionAssistProvider *completionAssistProvider(); - virtual BaseEditorDocumentProcessor *editorDocumentProcessor( - TextEditor::TextDocument *baseTextDocument); - FollowSymbolInterface *followSymbolInterface() override; + CppCompletionAssistProvider *completionAssistProvider() final; + BaseEditorDocumentProcessor *editorDocumentProcessor( + TextEditor::TextDocument *baseTextDocument) final; + FollowSymbolInterface *followSymbolInterface() final; private: QScopedPointer m_completionAssistProvider; From d36694451907d0fb8e937cd3ae2347d854ed40bb Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 19 Sep 2017 14:12:06 +0200 Subject: [PATCH 25/63] QmlPuppet: Modernize (nullptr and member initialization) Change-Id: Ifac20a48df8702f9d31042eb8765cbaadb60b25b Reviewed-by: Tim Jenssen --- .../qml2puppet/instances/nodeinstanceserver.cpp | 16 ++++------------ .../qml2puppet/instances/nodeinstanceserver.h | 9 ++++----- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp index aef747fb9bb..fb1bad0603d 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -157,7 +157,7 @@ void sortFilterImports(const QStringList &imports, QStringList *workingImports, namespace QmlDesigner { -static NodeInstanceServer *nodeInstanceServerInstance = 0; +static NodeInstanceServer *nodeInstanceServerInstance = nullptr; static void notifyPropertyChangeCallBackFunction(QObject *object, const PropertyName &propertyName) { @@ -170,11 +170,7 @@ static void (*notifyPropertyChangeCallBackPointer)(QObject *, const PropertyName NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) : NodeInstanceServerInterface(), m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)), - m_nodeInstanceClient(nodeInstanceClient), - m_timer(0), - m_renderTimerInterval(16), - m_slowRenderTimer(false), - m_slowRenderTimerInterval(200) + m_nodeInstanceClient(nodeInstanceClient) { qmlRegisterType("QmlDesigner", 1, 0, "DummyContextObject"); @@ -184,10 +180,6 @@ NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstance Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack(); } -NodeInstanceServer::~NodeInstanceServer() -{ -} - QList NodeInstanceServer::createInstances(const QVector &containerVector) { Q_ASSERT(declarativeView() || quickView()); @@ -247,7 +239,7 @@ ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const bool NodeInstanceServer::hasInstanceForObject(QObject *object) const { - if (object == 0) + if (object == nullptr) return false; return m_objectInstanceHash.contains(object) && m_objectInstanceHash.value(object).isValid(); @@ -671,7 +663,7 @@ QQmlContext *NodeInstanceServer::context() const if (engine()) return rootContext(); - return 0; + return nullptr; } QQmlContext *NodeInstanceServer::rootContext() const diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h index c7a0e58b32f..c777c0a7a19 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h @@ -71,7 +71,6 @@ public: typedef QPair > DummyPair; explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient); - ~NodeInstanceServer(); void createInstances(const CreateInstancesCommand &command); void changeFileUrl(const ChangeFileUrlCommand &command); @@ -214,10 +213,10 @@ private: QPointer m_childrenChangeEventFilter; QUrl m_fileUrl; NodeInstanceClientInterface *m_nodeInstanceClient; - int m_timer; - int m_renderTimerInterval; - bool m_slowRenderTimer; - int m_slowRenderTimerInterval; + int m_timer = 0; + int m_renderTimerInterval = 16; + bool m_slowRenderTimer = false; + int m_slowRenderTimerInterval = 200; QVector m_changedPropertyList; QByteArray m_importCode; QPointer m_dummyContextObject; From 32ce2119d6929a28c7280d8e0780e6b77ce09c41 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 19 Sep 2017 14:12:25 +0200 Subject: [PATCH 26/63] QmlDesigner: Modernize (nullptr and member initialization) Change-Id: I4d791427959c32a8fe8f831ecb7bd76ffbee2a97 Reviewed-by: Tim Jenssen --- .../instances/nodeinstanceserverproxy.cpp | 10 +--------- .../instances/nodeinstanceserverproxy.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp index e8fbe3a71cf..eebf3c0f8d1 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp @@ -107,15 +107,7 @@ NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceV : NodeInstanceServerInterface(nodeInstanceView), m_localServer(new QLocalServer(this)), m_nodeInstanceView(nodeInstanceView), - m_firstBlockSize(0), - m_secondBlockSize(0), - m_thirdBlockSize(0), - m_writeCommandCounter(0), - m_firstLastReadCommandCounter(0), - m_secondLastReadCommandCounter(0), - m_thirdLastReadCommandCounter(0), - m_runModus(runModus), - m_synchronizeId(-1) + m_runModus(runModus) { if (instanceViewBenchmark().isInfoEnabled()) m_benchmarkTimer.start(); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h index 9ab15b15c7c..4cf8f1241e3 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h @@ -118,15 +118,15 @@ private: QPointer m_qmlPuppetEditorProcess; QPointer m_qmlPuppetPreviewProcess; QPointer m_qmlPuppetRenderProcess; - quint32 m_firstBlockSize; - quint32 m_secondBlockSize; - quint32 m_thirdBlockSize; - quint32 m_writeCommandCounter; - quint32 m_firstLastReadCommandCounter; - quint32 m_secondLastReadCommandCounter; - quint32 m_thirdLastReadCommandCounter; + quint32 m_firstBlockSize = 0; + quint32 m_secondBlockSize = 0; + quint32 m_thirdBlockSize = 0; + quint32 m_writeCommandCounter = 0; + quint32 m_firstLastReadCommandCounter = 0; + quint32 m_secondLastReadCommandCounter = 0; + quint32 m_thirdLastReadCommandCounter = 0; RunModus m_runModus; - int m_synchronizeId; + int m_synchronizeId = -1; QTime m_benchmarkTimer; }; From 39bf2257c50a3aecf7fc71d9481e3ada14648145 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Wed, 20 Sep 2017 11:53:01 +0200 Subject: [PATCH 27/63] ProjectMacro: Prettify output of toByteArray Remove a stray space in the output if the value of a #define is empty. Change-Id: I542c092416e00276dc72e31b43215349ecf1ca64 Reviewed-by: Nikolai Kosjar --- src/plugins/projectexplorer/projectmacro.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/projectmacro.cpp b/src/plugins/projectexplorer/projectmacro.cpp index 63f69b6986f..5d2824f01db 100644 --- a/src/plugins/projectexplorer/projectmacro.cpp +++ b/src/plugins/projectexplorer/projectmacro.cpp @@ -38,7 +38,11 @@ bool Macro::isValid() const QByteArray Macro::toByteArray() const { switch (type) { - case MacroType::Define: return QByteArray("#define ") + key + ' ' + value; + case MacroType::Define: { + if (value.isEmpty()) + return QByteArray("#define ") + key; + return QByteArray("#define ") + key + ' ' + value; + } case MacroType::Undefine: return QByteArray("#undef ") + key; case MacroType::Invalid: break; } From 189dbc585ea8edba0e87c06dc58240dfbcaba97c Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 20 Sep 2017 16:07:08 +0200 Subject: [PATCH 28/63] Debugger: Fix misplaced { Harm was limited, as these were the fallback values for terminal and working directory that are overridden in all cases with real RunConfiguations. Change-Id: I7d3cef1ac814a0ffcf60a8977e0ae13136ea50b5 Reviewed-by: Nikolai Kosjar --- src/plugins/debugger/debuggerruncontrol.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 6946d8395d3..160840da3b2 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -760,8 +760,8 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl) QString(), QString(), optionalPrompt); }); - Runnable r = runnable(); { - if (r.is()) + Runnable r = runnable(); + if (r.is()) { m_runParameters.inferior = r.as(); m_runParameters.useTerminal = m_runParameters.inferior.runMode == ApplicationLauncher::Console; // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...) From edab564cf0c051ad0774dc5a59751d3c5781b263 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 4 Sep 2017 15:18:42 +0200 Subject: [PATCH 29/63] Beautifier: ClangFormat: Add action "Disable Formatting for Selected Text" Change-Id: I0786dfdc0679bbdf1cf1157067bd7f572ac7d108 Reviewed-by: Ivan Donchevskii Reviewed-by: Leena Miettinen Reviewed-by: Tim Jenssen Reviewed-by: Lorenz Haas --- dist/clangformat/README.md | 1 + doc/src/editors/creator-beautifier.qdoc | 4 ++ src/plugins/beautifier/beautifierplugin.cpp | 6 +++ src/plugins/beautifier/beautifierplugin.h | 1 + .../beautifier/clangformat/clangformat.cpp | 45 +++++++++++++++++++ .../beautifier/clangformat/clangformat.h | 2 + .../clangformat/clangformatconstants.h | 1 + 7 files changed, 60 insertions(+) diff --git a/dist/clangformat/README.md b/dist/clangformat/README.md index ae714aad9ee..aa3584e4621 100644 --- a/dist/clangformat/README.md +++ b/dist/clangformat/README.md @@ -58,6 +58,7 @@ For Windows: In Menu: Tools > Options > Environment > Keyboard * ClangFormat / FormatFile - e.g. Alt+C, F * ClangFormat / FormatSelectedText - e.g. Alt+C, S + * ClangFormat / DisableFormattingSelectedText - e.g. Alt+C, D Due to several issues outlined below the FormatFile action might be of limited use. diff --git a/doc/src/editors/creator-beautifier.qdoc b/doc/src/editors/creator-beautifier.qdoc index c47f9fb5121..e93d222594a 100644 --- a/doc/src/editors/creator-beautifier.qdoc +++ b/doc/src/editors/creator-beautifier.qdoc @@ -178,4 +178,8 @@ select it when no text is selected, the whole file is formatted by default. To disable this behavior, deselect the \uicontrol {Format entire file if no text was selected} check box. + + ClangFormat provides additionally the \uicontrol {Disable Formatting for + Selected Text} command. If you select it, the selected lines will be + wrapped within \c {// clang-format off} and \c {// clang-format on}. */ diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index 0dcfbf7c0ef..947233606c1 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -496,6 +496,12 @@ QString BeautifierPlugin::msgFormatSelectedText() return tr("Format &Selected Text"); } +QString BeautifierPlugin::msgDisableFormattingSelectedText() +{ + //: Menu entry + return tr("&Disable Formatting for Selected Text"); +} + QString BeautifierPlugin::msgCommandPromptDialogTitle(const QString &command) { //: File dialog title for path chooser when choosing binary diff --git a/src/plugins/beautifier/beautifierplugin.h b/src/plugins/beautifier/beautifierplugin.h index 14d6674ab8a..32189bcb19d 100644 --- a/src/plugins/beautifier/beautifierplugin.h +++ b/src/plugins/beautifier/beautifierplugin.h @@ -80,6 +80,7 @@ public: static QString msgCannotGetConfigurationFile(const QString &command); static QString msgFormatCurrentFile(); static QString msgFormatSelectedText(); + static QString msgDisableFormattingSelectedText(); static QString msgCommandPromptDialogTitle(const QString &command); static void showError(const QString &error); diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp index 13f7caab24f..b677a59fbcc 100644 --- a/src/plugins/beautifier/clangformat/clangformat.cpp +++ b/src/plugins/beautifier/clangformat/clangformat.cpp @@ -48,6 +48,7 @@ #include #include +#include namespace Beautifier { namespace Internal { @@ -88,6 +89,14 @@ bool ClangFormat::initialize() menu->addAction(cmd); connect(m_formatRange, &QAction::triggered, this, &ClangFormat::formatSelectedText); + m_disableFormattingSelectedText + = new QAction(BeautifierPlugin::msgDisableFormattingSelectedText(), this); + cmd = Core::ActionManager::registerAction( + m_disableFormattingSelectedText, Constants::ClangFormat::ACTION_DISABLEFORMATTINGSELECTED); + menu->addAction(cmd); + connect(m_disableFormattingSelectedText, &QAction::triggered, + this, &ClangFormat::disableFormattingSelectedText); + Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu); connect(m_settings, &ClangFormatSettings::supportedMimeTypesChanged, @@ -130,6 +139,42 @@ void ClangFormat::formatSelectedText() } } +void ClangFormat::disableFormattingSelectedText() +{ + TextEditor::TextEditorWidget *widget = TextEditor::TextEditorWidget::currentTextEditorWidget(); + if (!widget) + return; + + const QTextCursor tc = widget->textCursor(); + if (!tc.hasSelection()) + return; + + // Insert start marker + const QTextBlock selectionStartBlock = tc.document()->findBlock(tc.selectionStart()); + QTextCursor insertCursor(tc.document()); + insertCursor.beginEditBlock(); + insertCursor.setPosition(selectionStartBlock.position()); + insertCursor.insertText("// clang-format off\n"); + const int positionToRestore = tc.position(); + + // Insert end marker + QTextBlock selectionEndBlock = tc.document()->findBlock(tc.selectionEnd()); + insertCursor.setPosition(selectionEndBlock.position() + selectionEndBlock.length() - 1); + insertCursor.insertText("\n// clang-format on"); + insertCursor.endEditBlock(); + + // Reset the cursor position in order to clear the selection. + QTextCursor restoreCursor(tc.document()); + restoreCursor.setPosition(positionToRestore); + widget->setTextCursor(restoreCursor); + + // The indentation of these markers might be undesired, so reformat. + // This is not optimal because two undo steps will be needed to remove the markers. + const int reformatTextLength = insertCursor.position() - selectionStartBlock.position(); + m_beautifierPlugin->formatCurrentFile(command(selectionStartBlock.position(), + reformatTextLength)); +} + Command ClangFormat::command() const { Command command; diff --git a/src/plugins/beautifier/clangformat/clangformat.h b/src/plugins/beautifier/clangformat/clangformat.h index 86037fac0cc..bb5e5bf7881 100644 --- a/src/plugins/beautifier/clangformat/clangformat.h +++ b/src/plugins/beautifier/clangformat/clangformat.h @@ -55,9 +55,11 @@ public: private: void formatFile(); void formatSelectedText(); + void disableFormattingSelectedText(); BeautifierPlugin *m_beautifierPlugin; QAction *m_formatFile = nullptr; QAction *m_formatRange = nullptr; + QAction *m_disableFormattingSelectedText = nullptr; ClangFormatSettings *m_settings; Command command(int offset, int length) const; }; diff --git a/src/plugins/beautifier/clangformat/clangformatconstants.h b/src/plugins/beautifier/clangformat/clangformatconstants.h index 837d3323069..51f3981fc5d 100644 --- a/src/plugins/beautifier/clangformat/clangformatconstants.h +++ b/src/plugins/beautifier/clangformat/clangformatconstants.h @@ -34,6 +34,7 @@ namespace ClangFormat { const char DISPLAY_NAME[] = QT_TRANSLATE_NOOP("Beautifier::Internal::ClangFormat::ClangFormat", "ClangFormat"); const char ACTION_FORMATFILE[] = "ClangFormat.FormatFile"; const char ACTION_FORMATSELECTED[] = "ClangFormat.FormatSelectedText"; +const char ACTION_DISABLEFORMATTINGSELECTED[] = "ClangFormat.DisableFormattingSelectedText"; const char MENU_ID[] = "ClangFormat.Menu"; const char OPTION_ID[] = "ClangFormat"; const char SETTINGS_NAME[] = "clangformat"; From 89fa23a916b55bd06b0b0756d6d874b4b03e5ba1 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 5 Sep 2017 09:59:25 +0200 Subject: [PATCH 30/63] Beautifier: ClangFormat: Format current syntactic entity for no selection In case there was no selection, the action "Format Selected Text" could format the whole file (option) as a fallback. However, there is also the use case of formatting the syntactic entity under the cursor. Introducing another separate action for this feels wrong, so remove the fallback instead since there is already an action handling this. Change-Id: Ia73f6074433e706bb4c2d375ad5b84dd59bc93a3 Reviewed-by: Leena Miettinen Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen Reviewed-by: Lorenz Haas --- dist/clangformat/README.md | 2 +- doc/src/editors/creator-beautifier.qdoc | 12 ++++--- src/plugins/beautifier/beautifierplugin.cpp | 6 ++++ src/plugins/beautifier/beautifierplugin.h | 1 + .../beautifier/clangformat/clangformat.cpp | 18 ++++++---- .../beautifier/clangformat/clangformat.h | 2 +- .../clangformat/clangformatconstants.h | 2 +- .../clangformat/clangformatoptionspage.cpp | 2 -- .../clangformat/clangformatoptionspage.ui | 36 +++++++------------ .../clangformat/clangformatsettings.cpp | 12 ------- .../clangformat/clangformatsettings.h | 3 -- 11 files changed, 42 insertions(+), 54 deletions(-) diff --git a/dist/clangformat/README.md b/dist/clangformat/README.md index aa3584e4621..05fd065c019 100644 --- a/dist/clangformat/README.md +++ b/dist/clangformat/README.md @@ -57,7 +57,7 @@ For Windows: 3. Set shortcuts for convenience: In Menu: Tools > Options > Environment > Keyboard * ClangFormat / FormatFile - e.g. Alt+C, F - * ClangFormat / FormatSelectedText - e.g. Alt+C, S + * ClangFormat / FormatAtCursor - e.g. Alt+C, C * ClangFormat / DisableFormattingSelectedText - e.g. Alt+C, D Due to several issues outlined below the FormatFile action might be of limited diff --git a/doc/src/editors/creator-beautifier.qdoc b/doc/src/editors/creator-beautifier.qdoc index e93d222594a..52662b53c9c 100644 --- a/doc/src/editors/creator-beautifier.qdoc +++ b/doc/src/editors/creator-beautifier.qdoc @@ -174,12 +174,14 @@ \endlist In addition to the \uicontrol {Format Current File} command, ClangFormat - and Uncrustify provide the \uicontrol {Format Selected Text} command. If you + and Uncrustify provide additional commands. + ClangFormat provides the \uicontrol {Format at Cursor} command. If you + select it when no text is selected, the syntactic entity under the cursor + is formatted. The \uicontrol {Disable Formatting for Selected Text} command + wraps selected lines within \c {// clang-format off} and + \c {// clang-format on}. + Uncrustify provides the \uicontrol {Format Selected Text} command. If you select it when no text is selected, the whole file is formatted by default. To disable this behavior, deselect the \uicontrol {Format entire file if no text was selected} check box. - - ClangFormat provides additionally the \uicontrol {Disable Formatting for - Selected Text} command. If you select it, the selected lines will be - wrapped within \c {// clang-format off} and \c {// clang-format on}. */ diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index 947233606c1..e2715af1464 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -496,6 +496,12 @@ QString BeautifierPlugin::msgFormatSelectedText() return tr("Format &Selected Text"); } +QString BeautifierPlugin::msgFormatAtCursor() +{ + //: Menu entry + return tr("&Format at Cursor"); +} + QString BeautifierPlugin::msgDisableFormattingSelectedText() { //: Menu entry diff --git a/src/plugins/beautifier/beautifierplugin.h b/src/plugins/beautifier/beautifierplugin.h index 32189bcb19d..f298063f0ae 100644 --- a/src/plugins/beautifier/beautifierplugin.h +++ b/src/plugins/beautifier/beautifierplugin.h @@ -80,6 +80,7 @@ public: static QString msgCannotGetConfigurationFile(const QString &command); static QString msgFormatCurrentFile(); static QString msgFormatSelectedText(); + static QString msgFormatAtCursor(); static QString msgDisableFormattingSelectedText(); static QString msgCommandPromptDialogTitle(const QString &command); static void showError(const QString &error); diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp index b677a59fbcc..97298ffc39e 100644 --- a/src/plugins/beautifier/clangformat/clangformat.cpp +++ b/src/plugins/beautifier/clangformat/clangformat.cpp @@ -83,11 +83,11 @@ bool ClangFormat::initialize() menu->addAction(cmd); connect(m_formatFile, &QAction::triggered, this, &ClangFormat::formatFile); - m_formatRange = new QAction(BeautifierPlugin::msgFormatSelectedText(), this); + m_formatRange = new QAction(BeautifierPlugin::msgFormatAtCursor(), this); cmd = Core::ActionManager::registerAction(m_formatRange, - Constants::ClangFormat::ACTION_FORMATSELECTED); + Constants::ClangFormat::ACTION_FORMATATCURSOR); menu->addAction(cmd); - connect(m_formatRange, &QAction::triggered, this, &ClangFormat::formatSelectedText); + connect(m_formatRange, &QAction::triggered, this, &ClangFormat::formatAtCursor); m_disableFormattingSelectedText = new QAction(BeautifierPlugin::msgDisableFormattingSelectedText(), this); @@ -122,7 +122,7 @@ void ClangFormat::formatFile() m_beautifierPlugin->formatCurrentFile(command()); } -void ClangFormat::formatSelectedText() +void ClangFormat::formatAtCursor() { const TextEditor::TextEditorWidget *widget = TextEditor::TextEditorWidget::currentTextEditorWidget(); @@ -134,8 +134,14 @@ void ClangFormat::formatSelectedText() const int offset = tc.selectionStart(); const int length = tc.selectionEnd() - offset; m_beautifierPlugin->formatCurrentFile(command(offset, length)); - } else if (m_settings->formatEntireFileFallback()) { - formatFile(); + } else { + // Pretend that the current line was selected. + // Note that clang-format will extend the range to the next bigger + // syntactic construct if needed. + const QTextBlock block = tc.block(); + const int offset = block.position(); + const int length = block.length(); + m_beautifierPlugin->formatCurrentFile(command(offset, length)); } } diff --git a/src/plugins/beautifier/clangformat/clangformat.h b/src/plugins/beautifier/clangformat/clangformat.h index bb5e5bf7881..34cccb5fbcc 100644 --- a/src/plugins/beautifier/clangformat/clangformat.h +++ b/src/plugins/beautifier/clangformat/clangformat.h @@ -54,7 +54,7 @@ public: private: void formatFile(); - void formatSelectedText(); + void formatAtCursor(); void disableFormattingSelectedText(); BeautifierPlugin *m_beautifierPlugin; QAction *m_formatFile = nullptr; diff --git a/src/plugins/beautifier/clangformat/clangformatconstants.h b/src/plugins/beautifier/clangformat/clangformatconstants.h index 51f3981fc5d..2c94b347a51 100644 --- a/src/plugins/beautifier/clangformat/clangformatconstants.h +++ b/src/plugins/beautifier/clangformat/clangformatconstants.h @@ -33,7 +33,7 @@ namespace ClangFormat { const char DISPLAY_NAME[] = QT_TRANSLATE_NOOP("Beautifier::Internal::ClangFormat::ClangFormat", "ClangFormat"); const char ACTION_FORMATFILE[] = "ClangFormat.FormatFile"; -const char ACTION_FORMATSELECTED[] = "ClangFormat.FormatSelectedText"; +const char ACTION_FORMATATCURSOR[] = "ClangFormat.FormatAtCursor"; const char ACTION_DISABLEFORMATTINGSELECTED[] = "ClangFormat.DisableFormattingSelectedText"; const char MENU_ID[] = "ClangFormat.Menu"; const char OPTION_ID[] = "ClangFormat"; diff --git a/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp b/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp index ddac14461f1..d9f881dc415 100644 --- a/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp +++ b/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp @@ -78,7 +78,6 @@ void ClangFormatOptionsPageWidget::restore() const int fallbackStyleIndex = ui->fallbackStyle->findText(m_settings->fallbackStyle()); if (fallbackStyleIndex != -1) ui->fallbackStyle->setCurrentIndex(fallbackStyleIndex); - ui->formatEntireFileFallback->setChecked(m_settings->formatEntireFileFallback()); ui->configurations->setSettings(m_settings); ui->configurations->setCurrentConfiguration(m_settings->customStyle()); @@ -96,7 +95,6 @@ void ClangFormatOptionsPageWidget::apply() m_settings->setPredefinedStyle(ui->predefinedStyle->currentText()); m_settings->setFallbackStyle(ui->fallbackStyle->currentText()); m_settings->setCustomStyle(ui->configurations->currentConfiguration()); - m_settings->setFormatEntireFileFallback(ui->formatEntireFileFallback->isChecked()); m_settings->save(); // update since not all MIME types are accepted (invalids or duplicates) diff --git a/src/plugins/beautifier/clangformat/clangformatoptionspage.ui b/src/plugins/beautifier/clangformat/clangformatoptionspage.ui index c40b28c0417..7d060611b4b 100644 --- a/src/plugins/beautifier/clangformat/clangformatoptionspage.ui +++ b/src/plugins/beautifier/clangformat/clangformatoptionspage.ui @@ -20,6 +20,19 @@ Options + + + + Use customized style: + + + true + + + + + + @@ -62,29 +75,6 @@ - - - - Use customized style: - - - true - - - - - - - - - - For action Format Selected Text. - - - Format entire file if no text was selected - - - diff --git a/src/plugins/beautifier/clangformat/clangformatsettings.cpp b/src/plugins/beautifier/clangformat/clangformatsettings.cpp index f4c2189181b..6369c60510f 100644 --- a/src/plugins/beautifier/clangformat/clangformatsettings.cpp +++ b/src/plugins/beautifier/clangformat/clangformatsettings.cpp @@ -43,7 +43,6 @@ const char USE_PREDEFINED_STYLE[] = "usePredefinedStyle"; const char PREDEFINED_STYLE[] = "predefinedStyle"; const char FALLBACK_STYLE[] = "fallbackStyle"; const char CUSTOM_STYLE[] = "customStyle"; -const char FORMAT_ENTIRE_FILE_FALLBACK[] = "formatEntireFileFallback"; } ClangFormatSettings::ClangFormatSettings() : @@ -54,7 +53,6 @@ ClangFormatSettings::ClangFormatSettings() : m_settings.insert(PREDEFINED_STYLE, "LLVM"); m_settings.insert(FALLBACK_STYLE, "Default"); m_settings.insert(CUSTOM_STYLE, QVariant()); - m_settings.insert(FORMAT_ENTIRE_FILE_FALLBACK, QVariant(true)); read(); } @@ -215,16 +213,6 @@ void ClangFormatSettings::setCustomStyle(const QString &customStyle) m_settings.insert(CUSTOM_STYLE, QVariant(customStyle)); } -bool ClangFormatSettings::formatEntireFileFallback() const -{ - return m_settings.value(FORMAT_ENTIRE_FILE_FALLBACK).toBool(); -} - -void ClangFormatSettings::setFormatEntireFileFallback(bool formatEntireFileFallback) -{ - m_settings.insert(FORMAT_ENTIRE_FILE_FALLBACK, QVariant(formatEntireFileFallback)); -} - QStringList ClangFormatSettings::predefinedStyles() const { return {"LLVM", "Google", "Chromium", "Mozilla", "WebKit", "File"}; diff --git a/src/plugins/beautifier/clangformat/clangformatsettings.h b/src/plugins/beautifier/clangformat/clangformatsettings.h index b8a62be6bdc..4fca7ddc248 100644 --- a/src/plugins/beautifier/clangformat/clangformatsettings.h +++ b/src/plugins/beautifier/clangformat/clangformatsettings.h @@ -54,9 +54,6 @@ public: QString customStyle() const; void setCustomStyle(const QString &customStyle); - bool formatEntireFileFallback() const; - void setFormatEntireFileFallback(bool formatEntireFileFallback); - QStringList predefinedStyles() const; QStringList fallbackStyles() const; From c3c9fbfc444c38450c3a81de5d0638b8a8eb86cb Mon Sep 17 00:00:00 2001 From: Nikita Baryshnikov Date: Wed, 20 Sep 2017 19:13:50 +0300 Subject: [PATCH 31/63] ResourceEditor: fix remove file Change-Id: I02a1a5376b0ec0d8013f75dcdec6e4b8992f5f15 Reviewed-by: Tobias Hunger --- src/plugins/resourceeditor/resourceeditorplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/resourceeditor/resourceeditorplugin.cpp b/src/plugins/resourceeditor/resourceeditorplugin.cpp index 07c532f4eff..bc28f947475 100644 --- a/src/plugins/resourceeditor/resourceeditorplugin.cpp +++ b/src/plugins/resourceeditor/resourceeditorplugin.cpp @@ -283,7 +283,7 @@ void ResourceEditorPlugin::renameFileContextMenu() void ResourceEditorPlugin::removeFileContextMenu() { - auto rfn = dynamic_cast(ProjectTree::findCurrentNode()); + auto rfn = dynamic_cast(ProjectTree::findCurrentNode()); QTC_ASSERT(rfn, return); QString path = rfn->filePath().toString(); FolderNode *parent = rfn->parentFolderNode(); From 32b1244b2a0b3ea9ace2ec9e9a9e25f5f8188f8b Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 4 Aug 2017 10:18:41 +0200 Subject: [PATCH 32/63] CppEditor: add startGlobalRenaming Existing built-in functionality is moved there. Clang part is to be implemented later Change-Id: I7595898495213c087243cd534b4ba1617b4c27e9 Reviewed-by: Nikolai Kosjar --- src/plugins/clangrefactoring/refactoringengine.cpp | 5 +++++ src/plugins/clangrefactoring/refactoringengine.h | 1 + src/plugins/cppeditor/cppeditorwidget.cpp | 6 ++++-- src/plugins/cppeditor/cpprefactoringengine.cpp | 8 ++++++++ src/plugins/cppeditor/cpprefactoringengine.h | 1 + src/plugins/cpptools/refactoringengineinterface.h | 1 + 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/plugins/clangrefactoring/refactoringengine.cpp b/src/plugins/clangrefactoring/refactoringengine.cpp index aba069d93e3..1d964fe8938 100644 --- a/src/plugins/clangrefactoring/refactoringengine.cpp +++ b/src/plugins/clangrefactoring/refactoringengine.cpp @@ -84,6 +84,11 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data, server.requestSourceLocationsForRenamingMessage(std::move(message)); } +void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &) +{ + // TODO: implement +} + bool RefactoringEngine::isUsable() const { return server.isUsable(); diff --git a/src/plugins/clangrefactoring/refactoringengine.h b/src/plugins/clangrefactoring/refactoringengine.h index a5fe5fc6417..83e67bfe27a 100644 --- a/src/plugins/clangrefactoring/refactoringengine.h +++ b/src/plugins/clangrefactoring/refactoringengine.h @@ -42,6 +42,7 @@ public: void startLocalRenaming(const CppTools::CursorInEditor &data, CppTools::ProjectPart *projectPart, RenameCallback &&renameSymbolsCallback) override; + void startGlobalRenaming(const CppTools::CursorInEditor &data) override; bool isUsable() const override; void setUsable(bool isUsable); diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index e11b2c8143d..28f49380244 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -546,8 +546,10 @@ void CppEditorWidget::renameSymbolUnderCursor() setExtraSelections(TextEditor::TextEditorWidget::CodeSemanticsSelection, selections); d->m_localRenaming.updateSelectionsForVariableUnderCursor(selections); } - if (!d->m_localRenaming.start()) // Rename local symbol - renameUsages(); // Rename non-local symbol or macro + if (!d->m_localRenaming.start()) { + refactoringEngine()->startGlobalRenaming( + CppTools::CursorInEditor{textCursor(), textDocument()->filePath(), this}); + } } }; diff --git a/src/plugins/cppeditor/cpprefactoringengine.cpp b/src/plugins/cppeditor/cpprefactoringengine.cpp index 06ad6bd2c15..c9bfceb49c2 100644 --- a/src/plugins/cppeditor/cpprefactoringengine.cpp +++ b/src/plugins/cppeditor/cpprefactoringengine.cpp @@ -46,5 +46,13 @@ void CppRefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &da editorWidget->document()->revision()); } +void CppRefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &data) +{ + CppEditorWidget *editorWidget = static_cast(data.editorWidget()); + if (!editorWidget) + return; + editorWidget->renameUsages(); +} + } // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cppeditor/cpprefactoringengine.h b/src/plugins/cppeditor/cpprefactoringengine.h index 380c537b3d8..02deeffc27a 100644 --- a/src/plugins/cppeditor/cpprefactoringengine.h +++ b/src/plugins/cppeditor/cpprefactoringengine.h @@ -38,6 +38,7 @@ public: void startLocalRenaming(const CppTools::CursorInEditor &data, CppTools::ProjectPart *projectPart, RenameCallback &&renameSymbolsCallback) override; + void startGlobalRenaming(const CppTools::CursorInEditor &data) override; bool isUsable() const override { return true; } }; diff --git a/src/plugins/cpptools/refactoringengineinterface.h b/src/plugins/cpptools/refactoringengineinterface.h index 1452c8e5768..85fee7ac3a7 100644 --- a/src/plugins/cpptools/refactoringengineinterface.h +++ b/src/plugins/cpptools/refactoringengineinterface.h @@ -54,6 +54,7 @@ public: virtual void startLocalRenaming(const CursorInEditor &data, CppTools::ProjectPart *projectPart, RenameCallback &&renameSymbolsCallback) = 0; + virtual void startGlobalRenaming(const CursorInEditor &data) = 0; virtual bool isUsable() const = 0; }; From 0a226c77b081a31174b3f529d9d846f763e4d384 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 20 Sep 2017 16:34:54 +0200 Subject: [PATCH 33/63] Debugger: Replace RunParameter::languagues by individual bools There was almost 1:1 overlap with DebuggerRunTool::is{Cpp,Qml}Debugging, use one version only. Change-Id: I4a8f2b7005d3f2e440cdab3eaf6ac476af894308 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerengine.cpp | 4 +- src/plugins/debugger/debuggerengine.h | 3 +- src/plugins/debugger/debuggerplugin.cpp | 31 ++++---- src/plugins/debugger/debuggerruncontrol.cpp | 78 ++++++++------------- src/plugins/debugger/debuggerruncontrol.h | 6 +- 5 files changed, 49 insertions(+), 73 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 7d46ca6cc08..47a62484173 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -1750,7 +1750,7 @@ void DebuggerEngine::validateExecutable() DebuggerRunParameters *sp = &runParameters(); if (sp->skipExecutableValidation) return; - if (sp->languages == QmlLanguage) + if (!sp->isCppDebugging) return; QString symbolFile = sp->symbolFile; @@ -2004,7 +2004,7 @@ bool DebuggerEngine::isNativeMixedEnabled() const { if (DebuggerRunTool *rt = runTool()) { const DebuggerRunParameters &runParams = rt->runParameters(); - return runParams.nativeMixedEnabled && (runParams.languages & QmlLanguage); + return runParams.nativeMixedEnabled && runParams.isQmlDebugging; } return false; } diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index e2a3b404a49..f29b0318cfe 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -131,7 +131,8 @@ public: DebuggerEngineType masterEngineType = NoEngineType; DebuggerEngineType cppEngineType = NoEngineType; - DebuggerLanguages languages = NoLanguage; + bool isCppDebugging = true; + bool isQmlDebugging = false; bool breakOnMain = false; bool multiProcess = false; // Whether to set detach-on-fork off. diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 45e70007f98..dcc07a6d87d 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -970,8 +970,6 @@ public: ActionContainer *m_menu = 0; - QHash m_contextsForLanguage; - Project *m_previousProject = 0; QPointer m_previousTarget; QPointer m_previousRunConfiguration; @@ -1073,11 +1071,6 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) dd = this; m_plugin = plugin; - -// m_toolBars.insert(CppLanguage, 0); -// m_toolBars.insert(QmlLanguage, 0); - m_contextsForLanguage.insert(CppLanguage, Context(C_CPPDEBUGGER)); - m_contextsForLanguage.insert(QmlLanguage, Context(C_QMLDEBUGGER)); } DebuggerPluginPrivate::~DebuggerPluginPrivate() @@ -2892,11 +2885,9 @@ static QString formatStartParameters(const DebuggerRunParameters &sp) str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode << "\nABI: " << sp.toolChainAbi.toString() << '\n'; str << "Languages: "; - if (sp.languages == AnyLanguage) - str << "any "; - if (sp.languages & CppLanguage) + if (sp.isCppDebugging) str << "c++ "; - if (sp.languages & QmlLanguage) + if (sp.isQmlDebugging) str << "qml"; str << '\n'; if (!sp.inferior.executable.isEmpty()) { @@ -3368,17 +3359,19 @@ void DebuggerPluginPrivate::updateActiveLanguages() { if (!dd->m_currentRunTool) return; - const DebuggerLanguages languages = dd->m_currentRunTool->runParameters().languages; + const DebuggerRunParameters &rp = dd->m_currentRunTool->runParameters(); // Id perspective = (languages & QmlLanguage) && !(languages & CppLanguage) // ? QmlPerspectiveId : CppPerspectiveId; // m_mainWindow->restorePerspective(perspective); - for (DebuggerLanguage language: {QmlLanguage, CppLanguage}) { - const Context context = m_contextsForLanguage.value(language); - if (languages & language) - ICore::addAdditionalContext(context); - else - ICore::removeAdditionalContext(context); - } + if (rp.isCppDebugging) + ICore::addAdditionalContext(Context(C_CPPDEBUGGER)); + else + ICore::removeAdditionalContext(Context(C_CPPDEBUGGER)); + + if (rp.isQmlDebugging) + ICore::addAdditionalContext(Context(C_QMLDEBUGGER)); + else + ICore::removeAdditionalContext(Context(C_QMLDEBUGGER)); } void DebuggerPluginPrivate::onModeChanged(Id mode) diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 160840da3b2..fb31b611001 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -187,7 +187,8 @@ void DebuggerRunTool::setStartMode(DebuggerStartMode startMode) { if (startMode == AttachToQmlServer) { m_runParameters.startMode = AttachToRemoteProcess; - m_runParameters.languages = QmlLanguage; + m_runParameters.isCppDebugging = false; + m_runParameters.isQmlDebugging = true; m_runParameters.masterEngineType = QmlEngineType; m_runParameters.closeMode = KillAtClose; @@ -455,7 +456,7 @@ void DebuggerRunTool::start() } // QML and/or mixed are not prepared for it. - setSupportsReRunning(!(m_runParameters.languages & QmlLanguage)); + setSupportsReRunning(!m_runParameters.isQmlDebugging); // FIXME: Disabled due to Android. Make Android device report available ports instead. // int portsUsed = portsUsedByDebugger(); @@ -581,6 +582,16 @@ const DebuggerRunParameters &DebuggerRunTool::runParameters() const return m_runParameters; } +bool DebuggerRunTool::isCppDebugging() const +{ + return m_runParameters.isCppDebugging; +} + +bool DebuggerRunTool::isQmlDebugging() const +{ + return m_runParameters.isQmlDebugging; +} + int DebuggerRunTool::portsUsedByDebugger() const { return isCppDebugging() + isQmlDebugging(); @@ -625,17 +636,13 @@ bool DebuggerRunTool::fixupParameters() if (rp.inferior.environment.hasKey(var)) rp.debugger.environment.set(var, rp.inferior.environment.value(var)); - // This can happen e.g. when started from the command line. - if (rp.languages == NoLanguage) - rp.languages = CppLanguage; - // validate debugger if C++ debugging is enabled - if (rp.languages & CppLanguage && !rp.validationErrors.isEmpty()) { + if (rp.isCppDebugging && !rp.validationErrors.isEmpty()) { reportFailure(rp.validationErrors.join('\n')); return false; } - if (rp.languages & QmlLanguage) { + if (rp.isQmlDebugging) { if (device() && device()->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { if (rp.qmlServer.port() <= 0) { rp.qmlServer = ProjectExplorer::urlFromLocalHostAndFreePort(); @@ -665,9 +672,9 @@ bool DebuggerRunTool::fixupParameters() } if (rp.masterEngineType == NoEngineType) { - if (rp.languages & QmlLanguage) { + if (rp.isQmlDebugging) { QmlDebug::QmlDebugServicesPreset service; - if (rp.languages & CppLanguage) { + if (rp.isCppDebugging) { if (rp.nativeMixedEnabled) { service = QmlDebug::QmlNativeDebuggerServices; } else { @@ -679,7 +686,7 @@ bool DebuggerRunTool::fixupParameters() service = QmlDebug::QmlDebuggerServices; } if (rp.startMode != AttachExternal && rp.startMode != AttachCrashedExternal) { - QString qmlarg = (rp.languages & CppLanguage) && rp.nativeMixedEnabled + QString qmlarg = rp.isCppDebugging && rp.nativeMixedEnabled ? QmlDebug::qmlDebugNativeArguments(service, false) : QmlDebug::qmlDebugTcpArguments(service, Port(rp.qmlServer.port())); QtcProcess::addArg(&rp.inferior.commandLineArguments, qmlarg); @@ -724,31 +731,13 @@ bool DebuggerRunTool::fixupParameters() return true; } -static DebuggerRunConfigurationAspect *debuggerAspect(const RunControl *runControl) -{ - return runControl->runConfiguration()->extraAspect(); -} - -static bool cppDebugging(const RunControl *runControl) -{ - auto aspect = debuggerAspect(runControl); - return aspect ? aspect->useCppDebugger() : true; // For cases like valgrind-with-gdb. -} - -static bool qmlDebugging(const RunControl *runControl) -{ - auto aspect = debuggerAspect(runControl); - return aspect ? aspect->useQmlDebugger() : false; // For cases like valgrind-with-gdb. -} - -/// DebuggerRunTool - DebuggerRunTool::DebuggerRunTool(RunControl *runControl) - : RunWorker(runControl), - m_isCppDebugging(cppDebugging(runControl)), - m_isQmlDebugging(qmlDebugging(runControl)) + : RunWorker(runControl) { setDisplayName("DebuggerRunTool"); + + RunConfiguration *runConfig = runControl->runConfiguration(); + runControl->setIcon(ProjectExplorer::Icons::DEBUG_START_SMALL_TOOLBAR); runControl->setPromptToStop([](bool *optionalPrompt) { return RunControl::showPromptToStopDialog( @@ -769,10 +758,14 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl) FileUtils::normalizePathName(m_runParameters.inferior.workingDirectory); } - RunConfiguration *runConfig = runControl->runConfiguration(); - QTC_ASSERT(runConfig, return); + if (auto aspect = runConfig ? runConfig->extraAspect() : nullptr) { + m_runParameters.isCppDebugging = aspect->useCppDebugger(); + m_runParameters.isQmlDebugging = aspect->useQmlDebugger(); + m_runParameters.multiProcess = aspect->useMultiProcess(); + } - m_runParameters.displayName = runConfig->displayName(); + if (runConfig) + m_runParameters.displayName = runConfig->displayName(); const Kit *kit = runConfig->target()->kit(); QTC_ASSERT(kit, return); @@ -784,7 +777,8 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl) if (!envBinary.isEmpty()) m_runParameters.debugger.executable = QString::fromLocal8Bit(envBinary); - if (Project *project = runConfig->target()->project()) { + Project *project = runConfig ? runConfig->target()->project() : nullptr; + if (project) { m_runParameters.projectSourceDirectory = project->projectDirectory().toString(); m_runParameters.projectSourceFiles = project->files(Project::SourceFiles); } @@ -822,16 +816,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl) m_runParameters.masterEngineType = PdbEngineType; } } - - if (auto debuggerAspect = runConfig->extraAspect()) { - m_runParameters.multiProcess = debuggerAspect->useMultiProcess(); - if (m_runParameters.languages == NoLanguage) { - if (debuggerAspect->useCppDebugger()) - m_runParameters.languages |= CppLanguage; - if (debuggerAspect->useQmlDebugger()) - m_runParameters.languages |= QmlLanguage; - } - } } DebuggerEngine *DebuggerRunTool::activeEngine() const diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h index 24a9db3dba6..ff46db5059f 100644 --- a/src/plugins/debugger/debuggerruncontrol.h +++ b/src/plugins/debugger/debuggerruncontrol.h @@ -70,8 +70,8 @@ public: void startDying() { m_isDying = true; } bool isDying() const { return m_isDying; } - bool isCppDebugging() const { return m_isCppDebugging; } - bool isQmlDebugging() const { return m_isQmlDebugging; } + bool isCppDebugging() const; + bool isQmlDebugging() const; int portsUsedByDebugger() const; void setSolibSearchPath(const QStringList &list); @@ -140,8 +140,6 @@ private: QPointer m_engine; // Master engine Internal::DebuggerRunParameters m_runParameters; bool m_isDying = false; - const bool m_isCppDebugging; - const bool m_isQmlDebugging; }; class DEBUGGER_EXPORT GdbServerPortsGatherer : public ProjectExplorer::RunWorker From fc231309e8bd0dcdcecced7a0efee8a7a0224dec Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 19 Sep 2017 19:01:05 +0200 Subject: [PATCH 34/63] Utils: Fix reverse iterators in SmallString Change-Id: I859c801fdb1ad68d5943b580f07a9e8260ae192a Reviewed-by: Tim Jenssen --- src/libs/utils/smallstring.h | 8 +- src/libs/utils/smallstringliteral.h | 4 +- src/libs/utils/smallstringview.h | 4 +- tests/unit/unittest/smallstring-test.cpp | 285 ++++++++++++++++++++++- 4 files changed, 284 insertions(+), 17 deletions(-) diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h index 3a86d2435ce..5b30662592c 100644 --- a/src/libs/utils/smallstring.h +++ b/src/libs/utils/smallstring.h @@ -322,22 +322,22 @@ public: reverse_iterator rbegin() noexcept { - return reverse_iterator(end() - static_cast(1)); + return reverse_iterator(end()); } reverse_iterator rend() noexcept { - return reverse_iterator(begin() - static_cast(1)); + return reverse_iterator(begin()); } const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(end() - static_cast(1)); + return const_reverse_iterator(end()); } const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(begin() - static_cast(1)); + return const_reverse_iterator(begin()); } const_iterator begin() const noexcept diff --git a/src/libs/utils/smallstringliteral.h b/src/libs/utils/smallstringliteral.h index 9ed2ce91145..eedcf45d139 100644 --- a/src/libs/utils/smallstringliteral.h +++ b/src/libs/utils/smallstringliteral.h @@ -80,12 +80,12 @@ public: const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(end() - static_cast(1)); + return const_reverse_iterator(end()); } const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(begin() - static_cast(1)); + return const_reverse_iterator(begin()); } constexpr static diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index e2c3f7ea92d..2320ef99b6b 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -111,12 +111,12 @@ public: const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(end() - static_cast(1)); + return const_reverse_iterator(end()); } const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(begin() - static_cast(1)); + return const_reverse_iterator(begin()); } operator std::string() const diff --git a/tests/unit/unittest/smallstring-test.cpp b/tests/unit/unittest/smallstring-test.cpp index ea18fcacc2d..64273c45b2e 100644 --- a/tests/unit/unittest/smallstring-test.cpp +++ b/tests/unit/unittest/smallstring-test.cpp @@ -286,21 +286,21 @@ TEST(SmallString, LongSmallStringHasShortSmallStringSizeZero) ASSERT_THAT(longText.shortStringSize(), 0); } -TEST(SmallString, BeginIsEqualEndForEmptySmallString) +TEST(SmallString, SmallStringBeginIsEqualEndForEmptySmallString) { SmallString text; ASSERT_THAT(text.begin(), Eq(text.end())); } -TEST(SmallString, BeginIsNotEqualEndForNonEmptySmallString) +TEST(SmallString, SmallStringBeginIsNotEqualEndForNonEmptySmallString) { SmallString text("x"); ASSERT_THAT(text.begin(), Ne(text.end())); } -TEST(SmallString, BeginPlusOneIsEqualEndForSmallStringWidthSizeOne) +TEST(SmallString, SmallStringBeginPlusOneIsEqualEndForSmallStringWidthSizeOne) { SmallString text("x"); @@ -309,21 +309,21 @@ TEST(SmallString, BeginPlusOneIsEqualEndForSmallStringWidthSizeOne) ASSERT_THAT(beginPlusOne, Eq(text.end())); } -TEST(SmallString, RBeginIsEqualREndForEmptySmallString) +TEST(SmallString, SmallStringRBeginIsEqualREndForEmptySmallString) { SmallString text; ASSERT_THAT(text.rbegin(), Eq(text.rend())); } -TEST(SmallString, RBeginIsNotEqualREndForNonEmptySmallString) +TEST(SmallString, SmallStringRBeginIsNotEqualREndForNonEmptySmallString) { SmallString text("x"); ASSERT_THAT(text.rbegin(), Ne(text.rend())); } -TEST(SmallString, RBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) +TEST(SmallString, SmallStringRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) { SmallString text("x"); @@ -332,21 +332,21 @@ TEST(SmallString, RBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) ASSERT_THAT(beginPlusOne, Eq(text.rend())); } -TEST(SmallString, ConstRBeginIsEqualREndForEmptySmallString) +TEST(SmallString, SmallStringConstRBeginIsEqualREndForEmptySmallString) { const SmallString text; ASSERT_THAT(text.rbegin(), Eq(text.rend())); } -TEST(SmallString, ConstRBeginIsNotEqualREndForNonEmptySmallString) +TEST(SmallString, SmallStringConstRBeginIsNotEqualREndForNonEmptySmallString) { const SmallString text("x"); ASSERT_THAT(text.rbegin(), Ne(text.rend())); } -TEST(SmallString, ConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) +TEST(SmallString, SmallStringSmallStringConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) { const SmallString text("x"); @@ -355,6 +355,273 @@ TEST(SmallString, ConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) ASSERT_THAT(beginPlusOne, Eq(text.rend())); } +TEST(SmallString, SmallStringDistanceBetweenBeginAndEndIsZeroForEmptyText) +{ + SmallString text(""); + + auto distance = std::distance(text.begin(), text.end()); + + ASSERT_THAT(distance, 0); +} + +TEST(SmallString, SmallStringDistanceBetweenBeginAndEndIsOneForOneSign) +{ + SmallString text("x"); + + auto distance = std::distance(text.begin(), text.end()); + + ASSERT_THAT(distance, 1); +} + +TEST(SmallString, SmallStringDistanceBetweenRBeginAndREndIsZeroForEmptyText) +{ + SmallString text(""); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 0); +} + +TEST(SmallString, SmallStringDistanceBetweenRBeginAndREndIsOneForOneSign) +{ + SmallString text("x"); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 1); +} + +TEST(SmallString, SmallStringBeginPointsToX) +{ + SmallString text("x"); + + auto sign = *text.begin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, SmallStringRBeginPointsToX) +{ + SmallString text("x"); + + auto sign = *text.rbegin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, ConstSmallStringBeginPointsToX) +{ + const SmallString text("x"); + + auto sign = *text.begin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, ConstSmallStringRBeginPointsToX) +{ + const SmallString text("x"); + + auto sign = *text.rbegin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, SmallStringViewBeginIsEqualEndForEmptySmallString) +{ + SmallStringView text{""}; + + ASSERT_THAT(text.begin(), Eq(text.end())); +} + +TEST(SmallString, SmallStringViewBeginIsNotEqualEndForNonEmptySmallString) +{ + SmallStringView text("x"); + + ASSERT_THAT(text.begin(), Ne(text.end())); +} + +TEST(SmallString, SmallStringViewBeginPlusOneIsEqualEndForSmallStringWidthSizeOne) +{ + SmallStringView text("x"); + + auto beginPlusOne = text.begin() + std::size_t(1); + + ASSERT_THAT(beginPlusOne, Eq(text.end())); +} + +TEST(SmallString, SmallStringViewRBeginIsEqualREndForEmptySmallString) +{ + SmallStringView text{""}; + + ASSERT_THAT(text.rbegin(), Eq(text.rend())); +} + +TEST(SmallString, SmallStringViewRBeginIsNotEqualREndForNonEmptySmallString) +{ + SmallStringView text("x"); + + ASSERT_THAT(text.rbegin(), Ne(text.rend())); +} + +TEST(SmallString, SmallStringViewRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) +{ + SmallStringView text("x"); + + auto beginPlusOne = text.rbegin() + 1l; + + ASSERT_THAT(beginPlusOne, Eq(text.rend())); +} + +TEST(SmallString, SmallStringViewConstRBeginIsEqualREndForEmptySmallString) +{ + const SmallStringView text{""}; + + ASSERT_THAT(text.rbegin(), Eq(text.rend())); +} + +TEST(SmallString, SmallStringViewConstRBeginIsNotEqualREndForNonEmptySmallString) +{ + const SmallStringView text("x"); + + ASSERT_THAT(text.rbegin(), Ne(text.rend())); +} + +TEST(SmallString, SmallStringViewConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) +{ + const SmallStringView text("x"); + + auto beginPlusOne = text.rbegin() + 1l; + + ASSERT_THAT(beginPlusOne, Eq(text.rend())); +} + +TEST(SmallString, SmallStringViewDistanceBetweenBeginAndEndIsZeroForEmptyText) +{ + SmallStringView text(""); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 0); +} + +TEST(SmallString, SmallStringViewDistanceBetweenBeginAndEndIsOneForOneSign) +{ + SmallStringView text("x"); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 1); +} + +TEST(SmallString, SmallStringViewDistanceBetweenRBeginAndREndIsZeroForEmptyText) +{ + SmallStringView text(""); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 0); +} + +TEST(SmallString, SmallStringViewDistanceBetweenRBeginAndREndIsOneForOneSign) +{ + SmallStringView text("x"); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 1); +} + +TEST(SmallString, ConstSmallStringViewDistanceBetweenBeginAndEndIsZeroForEmptyText) +{ + const SmallStringView text(""); + + auto distance = std::distance(text.begin(), text.end()); + + ASSERT_THAT(distance, 0); +} + +TEST(SmallString, ConstSmallStringViewDistanceBetweenBeginAndEndIsOneForOneSign) +{ + const SmallStringView text("x"); + + auto distance = std::distance(text.begin(), text.end()); + + ASSERT_THAT(distance, 1); +} + +TEST(SmallString, ConstSmallStringViewDistanceBetweenRBeginAndREndIsZeroForEmptyText) +{ + const SmallStringView text(""); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 0); +} + +TEST(SmallString, ConstSmallStringViewDistanceBetweenRBeginAndREndIsOneForOneSign) +{ + const SmallStringView text("x"); + + auto distance = std::distance(text.rbegin(), text.rend()); + + ASSERT_THAT(distance, 1); +} + +TEST(SmallString, SmallStringViewBeginPointsToX) +{ + SmallStringView text("x"); + + auto sign = *text.begin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, SmallStringViewRBeginPointsToX) +{ + SmallStringView text("x"); + + auto sign = *text.rbegin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, ConstSmallStringViewBeginPointsToX) +{ + const SmallStringView text("x"); + + auto sign = *text.begin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, ConstSmallStringViewRBeginPointsToX) +{ + const SmallStringView text("x"); + + auto sign = *text.rbegin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, SmallStringLiteralViewRBeginPointsToX) +{ + SmallStringLiteral text("x"); + + auto sign = *text.rbegin(); + + ASSERT_THAT(sign, 'x'); +} + +TEST(SmallString, ConstSmallStringLiteralViewRBeginPointsToX) +{ + const SmallStringLiteral text("x"); + + auto sign = *text.rbegin(); + + ASSERT_THAT(sign, 'x'); +} + TEST(SmallString, ConstructorStandardString) { std::string stdStringText = "short string"; From 816a9175bee47d038f2902cf281a3b2d3c2f4fb5 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 21 Sep 2017 11:33:26 +0200 Subject: [PATCH 35/63] Sqlite: Extend database lastInsertedRowId() function was added and more test are now under test. Change-Id: I02bf11dbab29654dbff9f2cad8c13c0c4d15e3be Reviewed-by: Tim Jenssen --- src/libs/sqlite/sqlitedatabase.cpp | 10 ------- src/libs/sqlite/sqlitedatabase.h | 18 ++++++++++--- src/libs/sqlite/sqlitedatabasebackend.cpp | 13 ++++++--- src/libs/sqlite/sqlitedatabasebackend.h | 10 ++++--- tests/unit/unittest/sqlitedatabase-test.cpp | 29 +++++++++++++++++++++ 5 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/libs/sqlite/sqlitedatabase.cpp b/src/libs/sqlite/sqlitedatabase.cpp index ecdff0fbaee..aa265593c5a 100644 --- a/src/libs/sqlite/sqlitedatabase.cpp +++ b/src/libs/sqlite/sqlitedatabase.cpp @@ -108,16 +108,6 @@ OpenMode Database::openMode() const return m_openMode; } -int Database::changesCount() -{ - return m_databaseBackend.changesCount(); -} - -int Database::totalChangesCount() -{ - return m_databaseBackend.totalChangesCount(); -} - void Database::execute(Utils::SmallStringView sqlStatement) { m_databaseBackend.execute(sqlStatement); diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h index 7ba79513461..125bccaf24a 100644 --- a/src/libs/sqlite/sqlitedatabase.h +++ b/src/libs/sqlite/sqlitedatabase.h @@ -73,13 +73,25 @@ public: void setOpenMode(OpenMode openMode); OpenMode openMode() const; - int changesCount(); - int totalChangesCount(); - void execute(Utils::SmallStringView sqlStatement); DatabaseBackend &backend(); + int64_t lastInsertedRowId() const + { + return m_databaseBackend.lastInsertedRowId(); + } + + int changesCount() + { + return m_databaseBackend.changesCount(); + } + + int totalChangesCount() + { + return m_databaseBackend.totalChangesCount(); + } + private: void initializeTables(); std::mutex &databaseMutex() { return m_databaseMutex; } diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp index 14919ec9fa7..e50b07aac25 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.cpp +++ b/src/libs/sqlite/sqlitedatabasebackend.cpp @@ -110,7 +110,7 @@ void DatabaseBackend::open(Utils::SmallStringView databaseFilePath, OpenMode mod cacheTextEncoding(); } -sqlite3 *DatabaseBackend::sqliteDatabaseHandle() +sqlite3 *DatabaseBackend::sqliteDatabaseHandle() const { checkDatabaseHandleIsNotNull(); return m_databaseHandle; @@ -157,16 +157,21 @@ Utils::SmallStringVector DatabaseBackend::columnNames(Utils::SmallStringView tab return statement.columnNames(); } -int DatabaseBackend::changesCount() +int DatabaseBackend::changesCount() const { return sqlite3_changes(sqliteDatabaseHandle()); } -int DatabaseBackend::totalChangesCount() +int DatabaseBackend::totalChangesCount() const { return sqlite3_total_changes(sqliteDatabaseHandle()); } +int64_t DatabaseBackend::lastInsertedRowId() const +{ + return sqlite3_last_insert_rowid(sqliteDatabaseHandle()); +} + void DatabaseBackend::execute(Utils::SmallStringView sqlStatement) { ReadWriteStatement statement(sqlStatement, m_database); @@ -274,7 +279,7 @@ void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue, throw PragmaValueNotSet("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!"); } -void DatabaseBackend::checkDatabaseHandleIsNotNull() +void DatabaseBackend::checkDatabaseHandleIsNotNull() const { if (m_databaseHandle == nullptr) throwDatabaseIsNotOpen("SqliteDatabaseBackend: database is not open!"); diff --git a/src/libs/sqlite/sqlitedatabasebackend.h b/src/libs/sqlite/sqlitedatabasebackend.h index 2cadd808469..6ff56b11b22 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.h +++ b/src/libs/sqlite/sqlitedatabasebackend.h @@ -58,7 +58,7 @@ public: void close(); void closeWithoutException(); - sqlite3* sqliteDatabaseHandle(); + sqlite3* sqliteDatabaseHandle() const; void setJournalMode(JournalMode journalMode); JournalMode journalMode(); @@ -68,8 +68,10 @@ public: Utils::SmallStringVector columnNames(Utils::SmallStringView tableName); - int changesCount(); - int totalChangesCount(); + int changesCount() const; + int totalChangesCount() const; + + int64_t lastInsertedRowId() const; void execute(Utils::SmallStringView sqlStatement); @@ -95,7 +97,7 @@ protected: void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath); void checkDatabaseCouldBeOpened(int resultCode); void checkPragmaValue(Utils::SmallStringView databaseValue, Utils::SmallStringView expectedValue); - void checkDatabaseHandleIsNotNull(); + void checkDatabaseHandleIsNotNull() const; void checkIfMultithreadingIsActivated(int resultCode); void checkIfLoogingIsActivated(int resultCode); void checkMmapSizeIsSet(int resultCode); diff --git a/tests/unit/unittest/sqlitedatabase-test.cpp b/tests/unit/unittest/sqlitedatabase-test.cpp index 83dd405122c..98b14359458 100644 --- a/tests/unit/unittest/sqlitedatabase-test.cpp +++ b/tests/unit/unittest/sqlitedatabase-test.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -96,6 +97,30 @@ TEST_F(SqliteDatabase, AddTable) ASSERT_THAT(database.tables(), Contains(sqliteTable)); } +TEST_F(SqliteDatabase, GetChangesCount) +{ + Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database); + statement.write(42); + + ASSERT_THAT(database.changesCount(), 1); +} + +TEST_F(SqliteDatabase, GetTotalChangesCount) +{ + Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database); + statement.write(42); + + ASSERT_THAT(database.lastInsertedRowId(), 1); +} + +TEST_F(SqliteDatabase, GetLastInsertedRowId) +{ + Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database); + statement.write(42); + + ASSERT_THAT(database.lastInsertedRowId(), 1); +} + TEST_F(SqliteDatabase, TableIsReadyAfterOpenDatabase) { database.close(); @@ -112,6 +137,10 @@ void SqliteDatabase::SetUp() { database.setJournalMode(JournalMode::Memory); database.setDatabaseFilePath(databaseFilePath); + auto &table = database.addTable(); + table.setName("test"); + table.addColumn("name"); + database.open(); } From 2fc4e17e3188085a3c0c91dd8366d07919d9d1ea Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 21 Sep 2017 11:34:41 +0200 Subject: [PATCH 36/63] Utils: Add Utils::SmallStringView::empty It is required by many template function because it is used in the STL. Change-Id: I5a2b9266d0c9d79bdc37cbbc4e7b62fac7a82b8b Reviewed-by: Tim Jenssen --- src/libs/utils/smallstringview.h | 6 ++++++ tests/unit/unittest/smallstring-test.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index 2320ef99b6b..3d479195f17 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -97,6 +97,12 @@ public: return m_size == 0; } + constexpr + size_type empty() const noexcept + { + return m_size == 0; + } + constexpr const_iterator begin() const noexcept { diff --git a/tests/unit/unittest/smallstring-test.cpp b/tests/unit/unittest/smallstring-test.cpp index 64273c45b2e..345480182bc 100644 --- a/tests/unit/unittest/smallstring-test.cpp +++ b/tests/unit/unittest/smallstring-test.cpp @@ -1004,6 +1004,12 @@ TEST(SmallString, StringViewIsEmpty) ASSERT_TRUE(SmallStringView("").isEmpty()); } +TEST(SmallString, StringViewEmpty) +{ + ASSERT_FALSE(SmallStringView("text").empty()); + ASSERT_TRUE(SmallStringView("").empty()); +} + TEST(SmallString, HasContent) { ASSERT_TRUE(SmallString("text").hasContent()); From e88a08121360fe59a7f7bda81dbded3567041598 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 21 Sep 2017 11:37:35 +0200 Subject: [PATCH 37/63] Utils: Import std::experimental::in_place to Utils namespace It is needed to construct an optional in place. Change-Id: I92e6bec6a33b469d806d3144ea9eb8c64d25580f Reviewed-by: Tobias Hunger Reviewed-by: Tim Jenssen --- src/libs/utils/optional.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/utils/optional.h b/src/libs/utils/optional.h index 1960297de43..be07015d3d5 100644 --- a/src/libs/utils/optional.h +++ b/src/libs/utils/optional.h @@ -41,6 +41,8 @@ namespace Utils { using std::experimental::optional; // --> Utils::nullopt using std::experimental::nullopt; +// --> Utils::inplace +using std::experimental::in_place; // TODO: make_optional is a copy, since there is no sensible way to import functions in C++ template From ed2ae5fa81adb554e0c74d513edbcd99ee377a2c Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 21 Sep 2017 11:43:24 +0200 Subject: [PATCH 38/63] Sqlite: Improve SqliteStatement There are now only value and values methods. value returns an optional and values are returning a vector. The result value count has now be specified instead of the result value list. Change-Id: I17a0741d5e838b4bf4b9486825c870ada1722584 Reviewed-by: Tim Jenssen --- src/libs/sqlite/sqlitedatabasebackend.cpp | 2 +- src/libs/sqlite/sqlitereadstatement.h | 3 +- src/libs/sqlite/sqlitereadwritestatement.h | 3 +- src/libs/sqlite/sqlitestatement.cpp | 54 +++- src/libs/sqlite/sqlitestatement.h | 285 ++++++------------ .../clangrefactoring/sourcelocations.h | 21 +- src/plugins/clangrefactoring/symbolquery.h | 4 +- .../unit/unittest/mocksqlitereadstatement.cpp | 49 +-- tests/unit/unittest/mocksqlitereadstatement.h | 31 +- tests/unit/unittest/sqlitestatement-test.cpp | 81 +++-- tests/unit/unittest/sqliteteststatement.h | 2 +- tests/unit/unittest/symbolquery-test.cpp | 4 +- 12 files changed, 250 insertions(+), 289 deletions(-) diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp index e50b07aac25..5c4fc95e732 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.cpp +++ b/src/libs/sqlite/sqlitedatabasebackend.cpp @@ -420,7 +420,7 @@ Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement) statement.next(); - return statement.value(0); + return statement.fetchValue(0); } } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h index 1fddb3afce2..828d1f7c377 100644 --- a/src/libs/sqlite/sqlitereadstatement.h +++ b/src/libs/sqlite/sqlitereadstatement.h @@ -34,8 +34,7 @@ class SQLITE_EXPORT ReadStatement final : private Statement public: explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database); - using Statement::structValues; - using Statement::tupleValues; + using Statement::value; using Statement::values; using Statement::toValue; using Statement::database; diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h index 8c8d2541984..8645a6eae8a 100644 --- a/src/libs/sqlite/sqlitereadwritestatement.h +++ b/src/libs/sqlite/sqlitereadwritestatement.h @@ -37,9 +37,8 @@ public: ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database); using Statement::execute; + using Statement::value; using Statement::values; - using Statement::structValues; - using Statement::tupleValues; using Statement::toValue; using Statement::database; using Statement::write; diff --git a/src/libs/sqlite/sqlitestatement.cpp b/src/libs/sqlite/sqlitestatement.cpp index ba64f44a398..0e70b5aaca6 100644 --- a/src/libs/sqlite/sqlitestatement.cpp +++ b/src/libs/sqlite/sqlitestatement.cpp @@ -445,8 +445,7 @@ static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column) Q_UNREACHABLE(); } -template<> -int Statement::value(int column) const +int Statement::fetchIntValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); @@ -454,13 +453,23 @@ int Statement::value(int column) const } template<> -long Statement::value(int column) const +int Statement::fetchValue(int column) const { - return long(value(column)); + return fetchIntValue(column); +} + +long Statement::fetchLongValue(int column) const +{ + return long(fetchValue(column)); } template<> -long long Statement::value(int column) const +long Statement::fetchValue(int column) const +{ + return fetchLongValue(column); +} + +long long Statement::fetchLongLongValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); @@ -468,27 +477,48 @@ long long Statement::value(int column) const } template<> -double Statement::value(int column) const +long long Statement::fetchValue(int column) const +{ + return fetchLongLongValue(column); +} + +double Statement::fetchDoubleValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); return sqlite3_column_double(m_compiledStatement.get(), column); } +template<> +double Statement::fetchValue(int column) const +{ + return fetchDoubleValue(column); +} + template -StringType Statement::value(int column) const +StringType Statement::fetchValue(int column) const { checkIfIsReadyToFetchValues(); checkColumnIsValid(column); return convertToTextForColumn(m_compiledStatement.get(), column); } -template SQLITE_EXPORT Utils::SmallString Statement::value(int column) const; -template SQLITE_EXPORT Utils::PathString Statement::value(int column) const; +Utils::SmallString Statement::fetchSmallStringValue(int column) const +{ + return fetchValue(column); +} + +Utils::PathString Statement::fetchPathStringValue(int column) const +{ + return fetchValue(column); +} + +template SQLITE_EXPORT Utils::SmallString Statement::fetchValue(int column) const; +template SQLITE_EXPORT Utils::PathString Statement::fetchValue(int column) const; Utils::SmallString Statement::text(int column) const { - return value(column); + return fetchValue(column); } template @@ -498,7 +528,7 @@ ContainerType Statement::columnValues(const std::vector &columnIndices) con ContainerType valueContainer; valueContainer.reserve(columnIndices.size()); for (int columnIndex : columnIndices) - valueContainer.push_back(value(columnIndex)); + valueContainer.push_back(fetchValue(columnIndex)); return valueContainer; } @@ -510,7 +540,7 @@ Type Statement::toValue(Utils::SmallStringView sqlStatement, Database &database) statement.next(); - return statement.value(0); + return statement.fetchValue(0); } template SQLITE_EXPORT int Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitestatement.h index 6c3848e6798..3e93b7ba8d6 100644 --- a/src/libs/sqlite/sqlitestatement.h +++ b/src/libs/sqlite/sqlitestatement.h @@ -31,6 +31,8 @@ #include +#include + #include #include #include @@ -58,16 +60,22 @@ protected: void execute() const; void reset() const; + int fetchIntValue(int column) const; + long fetchLongValue(int column) const; + long long fetchLongLongValue(int column) const; + double fetchDoubleValue(int column) const; + Utils::SmallString fetchSmallStringValue(int column) const; + Utils::PathString fetchPathStringValue(int column) const; template - Type value(int column) const; + Type fetchValue(int column) const; Utils::SmallString text(int column) const; int columnCount() const; Utils::SmallStringVector columnNames() const; - void bind(int index, int value); - void bind(int index, long long value); - void bind(int index, double value); - void bind(int index, Utils::SmallStringView value); + void bind(int index, int fetchValue); + void bind(int index, long long fetchValue); + void bind(int index, double fetchValue); + void bind(int index, Utils::SmallStringView fetchValue); void bind(int index, uint value) { @@ -110,138 +118,60 @@ protected: } template - void bind(Utils::SmallStringView name, Type value); + void bind(Utils::SmallStringView name, Type fetchValue); int bindingIndexForName(Utils::SmallStringView name) const; void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames); const Utils::SmallStringVector &bindingColumnNames() const; - template - std::vector> tupleValues(std::size_t reserveSize) + template + std::vector values(std::size_t reserveSize) { - using Container = std::vector>; - Container resultValues; + std::vector resultValues; resultValues.reserve(reserveSize); while (next()) - emplaceTupleValues(resultValues); + emplaceBackValues(resultValues); reset(); return resultValues; } - template - std::vector> tupleValues(std::size_t reserveSize, const QueryTypes&... queryValues) + std::vector values(std::size_t reserveSize, const QueryTypes&... queryValues) { - using Container = std::vector>; - Container resultValues; + std::vector resultValues; resultValues.reserve(reserveSize); bindValues(queryValues...); while (next()) - emplaceTupleValues(resultValues); + emplaceBackValues(resultValues); reset(); return resultValues; } - template - std::vector> tupleValues(std::size_t reserveSize, - const std::vector> &queryTuples) - { - using Container = std::vector>; - Container resultValues; - resultValues.reserve(reserveSize); - - for (const auto &queryTuple : queryTuples) { - bindTupleValues(queryTuple); - - while (next()) - emplaceTupleValues(resultValues); - - reset(); - } - - return resultValues; - } - - template - std::vector> tupleValues(std::size_t reserveSize, - const std::vector &queryValues) - { - using Container = std::vector>; - Container resultValues; - resultValues.reserve(reserveSize); - - for (const QueryElementType &queryValue : queryValues) { - bindValues(queryValue); - - while (next()) - emplaceTupleValues(resultValues); - - reset(); - } - - return resultValues; - } - - template - std::vector structValues(std::size_t reserveSize) - { - using Container = std::vector; - Container resultValues; - resultValues.reserve(reserveSize); - - while (next()) - pushBackStructValues(resultValues); - - reset(); - - return resultValues; - } - - template - std::vector structValues(std::size_t reserveSize, const QueryTypes&... queryValues) - { - using Container = std::vector; - Container resultValues; - resultValues.reserve(reserveSize); - - bindValues(queryValues...); - - while (next()) - pushBackStructValues(resultValues); - - reset(); - - return resultValues; - } - - template - std::vector structValues(std::size_t reserveSize, + std::vector values(std::size_t reserveSize, const std::vector &queryValues) { - using Container = std::vector; - Container resultValues; + std::vector resultValues; resultValues.reserve(reserveSize); for (const QueryElementType &queryValue : queryValues) { bindValues(queryValue); while (next()) - pushBackStructValues(resultValues); + emplaceBackValues(resultValues); reset(); } @@ -250,9 +180,9 @@ protected: } template - std::vector structValues(std::size_t reserveSize, + std::vector values(std::size_t reserveSize, const std::vector> &queryTuples) { using Container = std::vector; @@ -263,62 +193,7 @@ protected: bindTupleValues(queryTuple); while (next()) - pushBackStructValues(resultValues); - - reset(); - } - - return resultValues; - } - - template - std::vector values(std::size_t reserveSize) - { - std::vector resultValues; - resultValues.reserve(reserveSize); - - while (next()) - resultValues.push_back(value(0)); - - reset(); - - return resultValues; - } - - template - std::vector values(std::size_t reserveSize, - const std::vector> &queryTuples) - { - std::vector resultValues; - resultValues.reserve(reserveSize); - - for (const auto &queryTuple : queryTuples) { - bindTupleValues(queryTuple); - - while (next()) - resultValues.push_back(value(0)); - - reset(); - } - - return resultValues; - } - - template - std::vector values(std::size_t reserveSize, - const std::vector &queryValues) - { - std::vector resultValues; - resultValues.reserve(reserveSize); - - for (const ElementType &queryValue : queryValues) { - bindValues(queryValue); - - while (next()) - resultValues.push_back(value(0)); + emplaceBackValues(resultValues); reset(); } @@ -327,20 +202,20 @@ protected: } template - std::vector values(std::size_t reserveSize, const QueryTypes&... queryValues) + Utils::optional value( const QueryTypes&... queryValues) { - std::vector resultValues; - resultValues.reserve(reserveSize); + Utils::optional resultValue; bindValues(queryValues...); - while (next()) - resultValues.push_back(value(0)); + if (next()) + resultValue = assignValue, ResultTypeCount>(); reset(); - return resultValues; + return resultValue; } template @@ -352,7 +227,6 @@ protected: sqlite3 *sqliteDatabaseHandle() const; TextEncoding databaseTextEncoding(); - bool checkForStepError(int resultCode) const; void checkForPrepareError(int resultCode) const; void checkForBindingError(int resultCode) const; @@ -388,35 +262,74 @@ protected: DatabaseBackend &databaseBackend); private: + class ValueGetter + { + public: + ValueGetter(Statement &statement, int column) + : statement(statement), + column(column) + {} + + operator int() + { + return statement.fetchIntValue(column); + } + + operator long() + { + return statement.fetchLongValue(column); + } + + operator long long() + { + return statement.fetchLongLongValue(column); + } + + operator double() + { + return statement.fetchDoubleValue(column); + } + + operator Utils::SmallString() + { + return statement.fetchSmallStringValue(column); + } + + operator Utils::PathString() + { + return statement.fetchPathStringValue(column); + } + + Statement &statement; + int column; + }; + template - void emplaceTupleValues(ContainerType &container, std::integer_sequence) + void emplaceBackValues(ContainerType &container, std::integer_sequence) { - container.emplace_back(value(ColumnIndices)...); + container.emplace_back(ValueGetter(*this, ColumnIndices)...); } - template - void emplaceTupleValues(ContainerType &container) + template + void emplaceBackValues(ContainerType &container) { - emplaceTupleValues(container, std::make_integer_sequence{}); + emplaceBackValues(container, std::make_integer_sequence{}); } - template - void pushBackStructValues(ContainerType &container, std::integer_sequence) + ResultOptionalType assignValue(std::integer_sequence) { - using ResultType = typename ContainerType::value_type; - container.push_back(ResultType{value(ColumnIndices)...}); + return ResultOptionalType(Utils::in_place, ValueGetter(*this, ColumnIndices)...); } - template - void pushBackStructValues(ContainerType &container) + template + ResultOptionalType assignValue() { - pushBackStructValues(container, std::make_integer_sequence{}); + return assignValue(std::make_integer_sequence{}); } template @@ -478,10 +391,10 @@ extern template SQLITE_EXPORT long long Statement::toValue(Utils::Sma extern template SQLITE_EXPORT double Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); extern template SQLITE_EXPORT Utils::SmallString Statement::toValue(Utils::SmallStringView sqlStatement, Database &database); -template <> SQLITE_EXPORT int Statement::value(int column) const; -template <> SQLITE_EXPORT long Statement::value(int column) const; -template <> SQLITE_EXPORT long long Statement::value(int column) const; -template <> SQLITE_EXPORT double Statement::value(int column) const; -extern template SQLITE_EXPORT Utils::SmallString Statement::value(int column) const; -extern template SQLITE_EXPORT Utils::PathString Statement::value(int column) const; +template <> SQLITE_EXPORT int Statement::fetchValue(int column) const; +template <> SQLITE_EXPORT long Statement::fetchValue(int column) const; +template <> SQLITE_EXPORT long long Statement::fetchValue(int column) const; +template <> SQLITE_EXPORT double Statement::fetchValue(int column) const; +extern template SQLITE_EXPORT Utils::SmallString Statement::fetchValue(int column) const; +extern template SQLITE_EXPORT Utils::PathString Statement::fetchValue(int column) const; } // namespace Sqlite diff --git a/src/plugins/clangrefactoring/sourcelocations.h b/src/plugins/clangrefactoring/sourcelocations.h index fe2d3dace94..9ae4241c01a 100644 --- a/src/plugins/clangrefactoring/sourcelocations.h +++ b/src/plugins/clangrefactoring/sourcelocations.h @@ -39,24 +39,25 @@ class SourceLocations public: struct Location { - qint64 sourceId; - qint64 line; - qint64 column; + Location(qint64 sourceId, qint64 line, qint64 column) + : sourceId(sourceId), line(line), column(column) + {} + + qint64 sourceId; + qint64 line; + qint64 column; }; struct Source { + Source(qint64 sourceId, Utils::PathString &&sourcePath) + : sourceId(sourceId), sourcePath(std::move(sourcePath)) + {} + qint64 sourceId; Utils::PathString sourcePath; }; - enum LocationGetter - { - SourceId = 0, - Line, - Column - }; - std::vector locations; std::unordered_map sources; }; diff --git a/src/plugins/clangrefactoring/symbolquery.h b/src/plugins/clangrefactoring/symbolquery.h index 778156410a4..19faf972294 100644 --- a/src/plugins/clangrefactoring/symbolquery.h +++ b/src/plugins/clangrefactoring/symbolquery.h @@ -52,7 +52,7 @@ public: const std::size_t reserveSize = 128; - auto locations = locationsStatement.template structValues( + auto locations = locationsStatement.template values( reserveSize, filePath, line, @@ -62,7 +62,7 @@ public: ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId; - auto sources = sourcesStatement.template structValues( + auto sources = sourcesStatement.template values( reserveSize, sourceIds); diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index 862742aedd9..386424386f9 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -25,31 +25,6 @@ #include "mocksqlitereadstatement.h" -template -std::vector values(std::size_t, QueryType...) -{ - FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload."; -} - -template -std::vector> values(std::size_t, - Utils::SmallStringView, - uint, - uint) -{ - FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload."; -} - -template class ContainerType, - typename ElementType> -std::vector> tupleValues(std::size_t, - const ContainerType &) -{ - FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload."; -} - template <> std::vector MockSqliteReadStatement::values(std::size_t reserveSize) { @@ -58,20 +33,24 @@ std::vector MockSqliteReadStatement::values(std::s template <> std::vector -MockSqliteReadStatement::structValues( - std::size_t reserveSize, - const Utils::PathString &sourcePath, - const uint &line, - const uint &column) +MockSqliteReadStatement::values(std::size_t reserveSize, + const Utils::PathString &sourcePath, + const uint &line, + const uint &column) { - return structValuesReturnStdVectorLocation(reserveSize, sourcePath, line, column); + return valuesReturnStdVectorLocation(reserveSize, sourcePath, line, column); } template <> std::vector -MockSqliteReadStatement::structValues( - std::size_t reserveSize, - const std::vector &sourceIds) +MockSqliteReadStatement::values(std::size_t reserveSize, const std::vector &sourceIds) { - return structValuesReturnStdVectorSource(reserveSize, sourceIds); + return valuesReturnStdVectorSource(reserveSize, sourceIds); +} + +template <> +Utils::optional +MockSqliteReadStatement::value(const Utils::SmallStringView &text) +{ + return valueReturnUInt32(text); } diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index f5b88c84673..b97ab1dc7d2 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -31,6 +31,7 @@ #include "mocksqlitedatabase.h" +#include #include #include @@ -53,28 +54,31 @@ public: MOCK_CONST_METHOD1(valuesReturnStdVectorInt, std::vector(std::size_t)); - MOCK_CONST_METHOD4(structValuesReturnStdVectorLocation, + MOCK_CONST_METHOD4(valuesReturnStdVectorLocation, std::vector(std::size_t, Utils::SmallStringView, qint64, qint64)); - MOCK_CONST_METHOD2(structValuesReturnStdVectorSource, + MOCK_CONST_METHOD2(valuesReturnStdVectorSource, std::vector(std::size_t, const std::vector &)); - template - std::vector values(std::size_t, QueryType...); + MOCK_CONST_METHOD1(valueReturnUInt32, + Utils::optional(Utils::SmallStringView)); + template - std::vector structValues(std::size_t reserveSize, const QueryType&... queryValues); + std::vector values(std::size_t reserveSize, const QueryType&... queryValues); template class QueryContainerType, typename QueryElementType> - std::vector structValues(std::size_t reserveSize, - const QueryContainerType &queryValues); + std::vector values(std::size_t reserveSize, + const QueryContainerType &queryValues); + template + Utils::optional value(const QueryTypes&... queryValues); public: Utils::SmallString sqlStatement; @@ -85,7 +89,7 @@ std::vector MockSqliteReadStatement::values(std::size_t reserveSize); template <> std::vector -MockSqliteReadStatement::structValues( +MockSqliteReadStatement::values( std::size_t reserveSize, const Utils::PathString &sourcePath, const uint &line, @@ -93,8 +97,11 @@ MockSqliteReadStatement::structValues( template <> std::vector -MockSqliteReadStatement::structValues( +MockSqliteReadStatement::values( std::size_t reserveSize, const std::vector &); +template <> +Utils::optional +MockSqliteReadStatement::value(const Utils::SmallStringView&); diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index 54be7bd0be9..30ea9cbca84 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -75,6 +75,10 @@ protected: struct Output { + Output(Utils::SmallString name, Utils::SmallString number, long long value) + : name(name), number(number), value(value) + {} + Utils::SmallString name; Utils::SmallString number; long long value; @@ -124,13 +128,13 @@ TEST_F(SqliteStatement, Value) statement.next(); - ASSERT_THAT(statement.value(0), 0); - ASSERT_THAT(statement.value(0), 0); - ASSERT_THAT(statement.value(0), 0.0); + ASSERT_THAT(statement.fetchValue(0), 0); + ASSERT_THAT(statement.fetchValue(0), 0); + ASSERT_THAT(statement.fetchValue(0), 0.0); ASSERT_THAT(statement.text(0), "foo"); - ASSERT_THAT(statement.value(1), 23); - ASSERT_THAT(statement.value(1), 23); - ASSERT_THAT(statement.value(1), 23.3); + ASSERT_THAT(statement.fetchValue(1), 23); + ASSERT_THAT(statement.fetchValue(1), 23); + ASSERT_THAT(statement.fetchValue(1), 23.3); ASSERT_THAT(statement.text(1), "23.3"); } @@ -138,7 +142,7 @@ TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement) { SqliteTestStatement statement("SELECT name, number FROM test", database); - ASSERT_THROW(statement.value(0), Sqlite::NoValuesToFetch); + ASSERT_THROW(statement.fetchValue(0), Sqlite::NoValuesToFetch); } TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement) @@ -146,7 +150,7 @@ TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement) SqliteTestStatement statement("SELECT name, number FROM test", database); while (statement.next()) {} - ASSERT_THROW(statement.value(0), Sqlite::NoValuesToFetch); + ASSERT_THROW(statement.fetchValue(0), Sqlite::NoValuesToFetch); } TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn) @@ -154,7 +158,7 @@ TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn) SqliteTestStatement statement("SELECT name, number FROM test", database); statement.next(); - ASSERT_THROW(statement.value(-1), Sqlite::InvalidColumnFetched); + ASSERT_THROW(statement.fetchValue(-1), Sqlite::InvalidColumnFetched); } TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn) @@ -162,7 +166,7 @@ TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn) SqliteTestStatement statement("SELECT name, number FROM test", database); statement.next(); - ASSERT_THROW(statement.value(2), Sqlite::InvalidColumnFetched); + ASSERT_THROW(statement.fetchValue(2), Sqlite::InvalidColumnFetched); } TEST_F(SqliteStatement, ToIntergerValue) @@ -206,7 +210,7 @@ TEST_F(SqliteStatement, BindString) statement.next(); ASSERT_THAT(statement.text(0), "foo"); - ASSERT_THAT(statement.value(1), 23.3); + ASSERT_THAT(statement.fetchValue(1), 23.3); } TEST_F(SqliteStatement, BindInteger) @@ -356,7 +360,7 @@ TEST_F(SqliteStatement, GetTupleValuesWithoutArguments) using Tuple = std::tuple; ReadStatement statement("SELECT name, number, value FROM test", database); - auto values = statement.tupleValues(3); + auto values = statement.values(3); ASSERT_THAT(values, ElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, @@ -376,7 +380,7 @@ TEST_F(SqliteStatement, GetStructValuesWithoutArguments) { ReadStatement statement("SELECT name, number, value FROM test", database); - auto values = statement.structValues(3); + auto values = statement.values(3); ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1}, Output{"foo", "23.3", 2}, @@ -399,7 +403,7 @@ TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndContainerQueryValues) std::vector queryValues = {40, 23.3}; ReadStatement statement("SELECT name, number, value FROM test WHERE number=?", database); - auto values = statement.tupleValues(3, queryValues); + auto values = statement.values(3, queryValues); ASSERT_THAT(values, ElementsAre(Tuple{"poo", 40, 3.}, Tuple{"foo", 23.3, 2.})); @@ -418,14 +422,14 @@ TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryValues) TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndContainerQueryTupleValues) { using Tuple = std::tuple; - using Tuple2 = std::tuple; + using ResultTuple = std::tuple; std::vector queryValues = {{"poo", "40", 3}, {"bar", "blah", 1}}; ReadStatement statement("SELECT name, number, value FROM test WHERE name= ? AND number=? AND value=?", database); - auto values = statement.tupleValues(3, queryValues); + auto values = statement.values(3, queryValues); - ASSERT_THAT(values, ElementsAre(Tuple2{"poo", 40, 3}, - Tuple2{"bar", 0, 1})); + ASSERT_THAT(values, ElementsAre(ResultTuple{"poo", 40, 3}, + ResultTuple{"bar", 0, 1})); } TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryTupleValues) @@ -444,7 +448,7 @@ TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndMultipleQueryValue) using Tuple = std::tuple; ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); - auto values = statement.tupleValues(3, "bar", "blah", 1); + auto values = statement.values(3, "bar", "blah", 1); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); } @@ -453,9 +457,9 @@ TEST_F(SqliteStatement, CallGetValuesForMultipleOutputValuesAndMultipleQueryValu { using Tuple = std::tuple; ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=?", database); - statement.tupleValues(3, "bar", "blah"); + statement.values(3, "bar", "blah"); - auto values = statement.tupleValues(3, "bar", "blah"); + auto values = statement.values(3, "bar", "blah"); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); } @@ -464,7 +468,7 @@ TEST_F(SqliteStatement, GetStructOutputValuesAndMultipleQueryValue) { ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); - auto values = statement.structValues(3, "bar", "blah", 1); + auto values = statement.values(3, "bar", "blah", 1); ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1})); } @@ -474,7 +478,7 @@ TEST_F(SqliteStatement, GetStructOutputValuesAndContainerQueryValues) std::vector queryValues = {40, 23.3}; ReadStatement statement("SELECT name, number, value FROM test WHERE number=?", database); - auto values = statement.structValues(3, queryValues); + auto values = statement.values(3, queryValues); ASSERT_THAT(values, ElementsAre(Output{"poo", "40", 3}, Output{"foo", "23.3", 2})); @@ -486,12 +490,41 @@ TEST_F(SqliteStatement, GetStructOutputValuesAndContainerQueryTupleValues) std::vector queryValues = {{"poo", "40", 3}, {"bar", "blah", 1}}; ReadStatement statement("SELECT name, number, value FROM test WHERE name= ? AND number=? AND value=?", database); - auto values = statement.structValues(3, queryValues); + auto values = statement.values(3, queryValues); ASSERT_THAT(values, ElementsAre(Output{"poo", "40", 3}, Output{"bar", "blah", 1})); } +TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue) +{ + ReadStatement statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", database); + + auto value = statement.value("bar", "blah", 1); + + ASSERT_THAT(value.value(), Eq("bar")); +} + +TEST_F(SqliteStatement, GetOptionalOutputValueAndMultipleQueryValue) +{ + ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); + + auto value = statement.value("bar", "blah", 1); + + ASSERT_THAT(value.value(), Eq(Output{"bar", "blah", 1})); +} + +TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue) +{ + using Tuple = std::tuple; + ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); + + auto value = statement.value("bar", "blah", 1); + + ASSERT_THAT(value.value(), Eq(Tuple{"bar", "blah", 1})); +} + + void SqliteStatement::SetUp() { database.setJournalMode(JournalMode::Memory); diff --git a/tests/unit/unittest/sqliteteststatement.h b/tests/unit/unittest/sqliteteststatement.h index 43b6ab884c1..870180b5d05 100644 --- a/tests/unit/unittest/sqliteteststatement.h +++ b/tests/unit/unittest/sqliteteststatement.h @@ -46,7 +46,7 @@ public: using Statement::execute; using Statement::next; using Statement::text; - using Statement::value; + using Statement::fetchValue; protected: void checkIsWritableStatement(); diff --git a/tests/unit/unittest/symbolquery-test.cpp b/tests/unit/unittest/symbolquery-test.cpp index 2de8cc251b4..50925bd7f3c 100644 --- a/tests/unit/unittest/symbolquery-test.cpp +++ b/tests/unit/unittest/symbolquery-test.cpp @@ -63,9 +63,9 @@ protected: TEST_F(SymbolQuery, LocationsAt) { - EXPECT_CALL(selectLocationsForSymbolLocation, structValuesReturnStdVectorLocation(_, Eq("/path/to/file.cpp"), 14, 7)) + EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnStdVectorLocation(_, Eq("/path/to/file.cpp"), 14, 7)) .WillRepeatedly(Return(locations)); - EXPECT_CALL(selectSourcePathForId, structValuesReturnStdVectorSource(_, ElementsAre(1, 2, 4))); + EXPECT_CALL(selectSourcePathForId, valuesReturnStdVectorSource(_, ElementsAre(1, 2, 4))); query.locationsAt("/path/to/file.cpp", 14, 7); } From 526e217ce9cfb1f22ec9bbf0e9844803b72b4911 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 19 Sep 2017 12:31:19 +0200 Subject: [PATCH 39/63] Debugger: Centralize abort handling ... and apply even more force on the second trying by forcing ramp down of the runControl itself instead of hoping that it would pick up hints. Change-Id: I9d0f4130cb9a137b91c9fa81c3d255f236f98be0 Reviewed-by: Christian Stenger --- src/plugins/debugger/cdb/cdbengine.cpp | 12 ++---------- src/plugins/debugger/cdb/cdbengine.h | 2 +- src/plugins/debugger/debuggerengine.cpp | 13 +++++++++++-- src/plugins/debugger/debuggerengine.h | 5 ++++- src/plugins/debugger/gdb/gdbengine.cpp | 12 ++---------- src/plugins/debugger/gdb/gdbengine.h | 2 +- src/plugins/debugger/lldb/lldbengine.cpp | 12 ++---------- src/plugins/debugger/lldb/lldbengine.h | 2 +- src/plugins/debugger/qml/qmlcppengine.cpp | 4 ++-- src/plugins/debugger/qml/qmlcppengine.h | 2 +- 10 files changed, 27 insertions(+), 39 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 9c52ad0b9ed..6d64a7e4409 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -840,17 +840,9 @@ void CdbEngine::shutdownEngine() } } -void CdbEngine::abortDebugger() +void CdbEngine::abortDebuggerProcess() { - if (isDying()) { - // We already tried. Try harder. - showMessage("ABORTING DEBUGGER. SECOND TIME."); - m_process.kill(); - } else { - // Be friendly the first time. This will change targetState(). - showMessage("ABORTING DEBUGGER. FIRST TIME."); - quitDebugger(); - } + m_process.kill(); } void CdbEngine::processFinished() diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index 30bccb4a116..7a80e48dbac 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -70,7 +70,7 @@ public: void runEngine() override; void shutdownInferior() override; void shutdownEngine() override; - void abortDebugger() override; + void abortDebuggerProcess() override; void detachDebugger() override; bool hasCapability(unsigned cap) const override; void watchPoint(const QPoint &) override; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 47a62484173..671296d92e6 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -1353,8 +1353,17 @@ void DebuggerEngine::quitDebugger() void DebuggerEngine::abortDebugger() { - // Overridden in e.g. GdbEngine. - quitDebugger(); + if (!isDying()) { + // Be friendly the first time. This will change targetState(). + showMessage("ABORTING DEBUGGER. FIRST TIME."); + quitDebugger(); + } else { + // We already tried. Try harder. + showMessage("ABORTING DEBUGGER. SECOND TIME."); + abortDebuggerProcess(); + if (runControl()) + runControl()->initiateFinish(); + } } void DebuggerEngine::requestInterruptInferior() diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index f29b0318cfe..549f2b10cd8 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -360,7 +360,8 @@ public: virtual void resetLocation(); virtual void gotoLocation(const Internal::Location &location); virtual void quitDebugger(); // called when pressing the stop button - virtual void abortDebugger(); // called from the debug menu action + + void abortDebugger(); // called from the debug menu action void updateViews(); bool isSlaveEngine() const; @@ -450,6 +451,8 @@ protected: virtual void frameUp(); virtual void frameDown(); + virtual void abortDebuggerProcess() {} // second attempt + virtual void doUpdateLocals(const UpdateParameters ¶ms); void setMasterEngine(DebuggerEngine *masterEngine); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index cdd689cd46a..ece1d1c87c4 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -4062,17 +4062,9 @@ void GdbEngine::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus) notifyDebuggerProcessFinished(exitCode, exitStatus, "GDB"); } -void GdbEngine::abortDebugger() +void GdbEngine::abortDebuggerProcess() { - if (isDying()) { - // We already tried. Try harder. - showMessage("ABORTING DEBUGGER. SECOND TIME."); - m_gdbProc.kill(); - } else { - // Be friendly the first time. This will change targetState(). - showMessage("ABORTING DEBUGGER. FIRST TIME."); - quitDebugger(); - } + m_gdbProc.kill(); } void GdbEngine::resetInferior() diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index c7122340f06..a7537cfdebd 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -83,7 +83,7 @@ private: ////////// General Interface ////////// bool hasCapability(unsigned) const final; void detachDebugger() final; void shutdownInferior() final; - void abortDebugger() final; + void abortDebuggerProcess() final; void resetInferior() final; bool acceptsDebuggerCommands() const final; diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index c1c1225bdd4..6cc5234b3c2 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -160,17 +160,9 @@ void LldbEngine::shutdownEngine() notifyEngineShutdownOk(); } -void LldbEngine::abortDebugger() +void LldbEngine::abortDebuggerProcess() { - if (isDying()) { - // We already tried. Try harder. - showMessage("ABORTING DEBUGGER. SECOND TIME."); - m_lldbProc.kill(); - } else { - // Be friendly the first time. This will change targetState(). - showMessage("ABORTING DEBUGGER. FIRST TIME."); - quitDebugger(); - } + m_lldbProc.kill(); } void LldbEngine::setupEngine() diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 19932d56c76..dff437497b6 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -78,7 +78,7 @@ private: void runEngine() override; void shutdownInferior() override; void shutdownEngine() override; - void abortDebugger() override; + void abortDebuggerProcess() override; bool canHandleToolTip(const DebuggerToolTipContext &) const override; diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 63ff26c1565..a5a9810b9ba 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -410,10 +410,10 @@ void QmlCppEngine::quitDebugger() m_cppEngine->quitDebugger(); } -void QmlCppEngine::abortDebugger() +void QmlCppEngine::abortDebuggerProcess() { EDEBUG("\nMASTER ABORT DEBUGGER"); - m_cppEngine->abortDebugger(); + m_cppEngine->abortDebuggerProcess(); } void QmlCppEngine::setState(DebuggerState newState, bool forced) diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index 38a3c00d566..9dcfb3284a4 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -112,7 +112,7 @@ protected: void shutdownInferior() override; void shutdownEngine() override; void quitDebugger() override; - void abortDebugger() override; + void abortDebuggerProcess() override; void loadAdditionalQmlStack() override; From 63e2f9ccdb4edf6fdf9bdbf7deb33d290aeab85c Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 19 Sep 2017 17:36:12 +0200 Subject: [PATCH 40/63] Debugger: Remove non-const access to RunParameters The idea is that they shouldn't change after start() to be re-usable for an additional run later. Change-Id: I272fc975657b0d8b5b13a07d58bd0b626868d32e Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerengine.cpp | 67 ++++++++------------- src/plugins/debugger/debuggerengine.h | 7 ++- src/plugins/debugger/debuggerruncontrol.cpp | 6 ++ 3 files changed, 35 insertions(+), 45 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 671296d92e6..ecf31ab8410 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -533,14 +533,11 @@ void DebuggerEngine::start() fp->setKeepOnFinish(FutureProgress::HideOnFinish); d->m_progress.reportStarted(); - DebuggerRunParameters &rp = runParameters(); + const DebuggerRunParameters &rp = runParameters(); d->m_inferiorPid = rp.attachPID.isValid() ? rp.attachPID : ProcessHandle(); if (d->m_inferiorPid.isValid()) runControl()->setApplicationProcessHandle(d->m_inferiorPid); - if (isNativeMixedActive()) - rp.inferior.environment.set("QV4_FORCE_INTERPRETER", "1"); - action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability)); QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished, @@ -631,11 +628,6 @@ const DebuggerRunParameters &DebuggerEngine::runParameters() const return runTool()->runParameters(); } -DebuggerRunParameters &DebuggerEngine::runParameters() -{ - return runTool()->runParameters(); -} - DebuggerState DebuggerEngine::state() const { return d->m_state; @@ -728,7 +720,6 @@ void DebuggerEnginePrivate::doSetupEngine() { m_engine->showMessage("CALL: SETUP ENGINE"); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state()); - m_engine->validateExecutable(); m_engine->setupEngine(); } @@ -1754,42 +1745,30 @@ void DebuggerEngine::setStateDebugging(bool on) d->m_isStateDebugging = on; } -void DebuggerEngine::validateExecutable() +void DebuggerRunParameters::validateExecutable() { - DebuggerRunParameters *sp = &runParameters(); - if (sp->skipExecutableValidation) - return; - if (!sp->isCppDebugging) - return; - - QString symbolFile = sp->symbolFile; - if (symbolFile.isEmpty()) - symbolFile = sp->inferior.executable; - if (symbolFile.isEmpty()) - return; - const bool warnOnRelease = boolSetting(WarnOnReleaseBuilds); bool warnOnInappropriateDebugger = false; QString detailedWarning; - switch (sp->toolChainAbi.binaryFormat()) { + switch (toolChainAbi.binaryFormat()) { case Abi::PEFormat: { QString preferredDebugger; - if (sp->toolChainAbi.osFlavor() == Abi::WindowsMSysFlavor) { - if (sp->cppEngineType == CdbEngineType) + if (toolChainAbi.osFlavor() == Abi::WindowsMSysFlavor) { + if (cppEngineType == CdbEngineType) preferredDebugger = "GDB"; - } else if (sp->cppEngineType != CdbEngineType) { + } else if (cppEngineType != CdbEngineType) { // osFlavor() is MSVC, so the recommended debugger is CDB preferredDebugger = "CDB"; } if (!preferredDebugger.isEmpty()) { warnOnInappropriateDebugger = true; - detailedWarning = tr( + detailedWarning = DebuggerEngine::tr( "The inferior is in the Portable Executable format.\n" "Selecting %1 as debugger would improve the debugging " "experience for this binary format.").arg(preferredDebugger); break; } - if (warnOnRelease && sp->cppEngineType == CdbEngineType) { + if (warnOnRelease && cppEngineType == CdbEngineType) { if (!symbolFile.endsWith(".exe", Qt::CaseInsensitive)) symbolFile.append(".exe"); QString errorMessage; @@ -1806,9 +1785,9 @@ void DebuggerEngine::validateExecutable() break; } case Abi::ElfFormat: { - if (sp->cppEngineType == CdbEngineType) { + if (cppEngineType == CdbEngineType) { warnOnInappropriateDebugger = true; - detailedWarning = tr( + detailedWarning = DebuggerEngine::tr( "The inferior is in the ELF format.\n" "Selecting GDB or LLDB as debugger would improve the debugging " "experience for this binary format."); @@ -1881,7 +1860,7 @@ void DebuggerEngine::validateExecutable() QRegExp exp = itExp->first; int index = exp.indexIn(string); if (index != -1) { - sp->sourcePathMap.insert(string.left(index) + exp.cap(1), itExp->second); + sourcePathMap.insert(string.left(index) + exp.cap(1), itExp->second); found = true; break; } @@ -1900,8 +1879,9 @@ void DebuggerEngine::validateExecutable() return; foreach (const QByteArray &name, interesting) { - const QString found = seen.contains(name) ? tr("Found.") : tr("Not found."); - detailedWarning.append('\n' + tr("Section %1: %2").arg(QString::fromUtf8(name)).arg(found)); + const QString found = seen.contains(name) ? DebuggerEngine::tr("Found.") + : DebuggerEngine::tr("Not found."); + detailedWarning.append('\n' + DebuggerEngine::tr("Section %1: %2").arg(QString::fromUtf8(name)).arg(found)); } break; } @@ -1909,14 +1889,14 @@ void DebuggerEngine::validateExecutable() return; } if (warnOnInappropriateDebugger) { - AsynchronousMessageBox::information(tr("Warning"), - tr("The selected debugger may be inappropriate for the inferior.\n" + AsynchronousMessageBox::information(DebuggerEngine::tr("Warning"), + DebuggerEngine::tr("The selected debugger may be inappropriate for the inferior.\n" "Examining symbols and setting breakpoints by file name and line number " "may fail.\n") + '\n' + detailedWarning); } else if (warnOnRelease) { - AsynchronousMessageBox::information(tr("Warning"), - tr("This does not seem to be a \"Debug\" build.\n" + AsynchronousMessageBox::information(DebuggerEngine::tr("Warning"), + DebuggerEngine::tr("This does not seem to be a \"Debug\" build.\n" "Setting breakpoints by file name and line number may fail.") + '\n' + detailedWarning); } @@ -2011,10 +1991,8 @@ void DebuggerEngine::checkState(DebuggerState state, const char *file, int line) bool DebuggerEngine::isNativeMixedEnabled() const { - if (DebuggerRunTool *rt = runTool()) { - const DebuggerRunParameters &runParams = rt->runParameters(); - return runParams.nativeMixedEnabled && runParams.isQmlDebugging; - } + if (DebuggerRunTool *rt = runTool()) + return rt->runParameters().isNativeMixedDebugging(); return false; } @@ -2033,6 +2011,11 @@ bool DebuggerEngine::isNativeMixedActiveFrame() const return frame.language == QmlLanguage; } +bool DebuggerRunParameters::isNativeMixedDebugging() const +{ + return nativeMixedEnabled && isCppDebugging && isQmlDebugging; +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 549f2b10cd8..89723096d06 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -156,6 +156,9 @@ public: bool nativeMixedEnabled = false; + bool isNativeMixedDebugging() const; + void validateExecutable(); + Utils::MacroExpander *macroExpander = 0; // For Debugger testing. @@ -239,7 +242,7 @@ public: virtual ~DebuggerEngine(); const DebuggerRunParameters &runParameters() const; - DebuggerRunParameters &runParameters(); + virtual void setRunTool(DebuggerRunTool *runTool); DebuggerRunTool *runTool() const; @@ -471,8 +474,6 @@ protected: bool isStateDebugging() const; void setStateDebugging(bool on); - void validateExecutable(); - virtual void setupSlaveInferior(); virtual void setupSlaveEngine(); virtual void runSlaveEngine(); diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index fb31b611001..eeff836bc2f 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -728,6 +728,12 @@ bool DebuggerRunTool::fixupParameters() rp.useTerminal = false; } + if (rp.isNativeMixedDebugging()) + rp.inferior.environment.set("QV4_FORCE_INTERPRETER", "1"); + + if (rp.isCppDebugging && !rp.skipExecutableValidation) + rp.validateExecutable(); + return true; } From 63a99936abef299a94b73af3475823e36aa68c24 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 21 Sep 2017 12:59:44 +0200 Subject: [PATCH 41/63] QmlProfiler: Unify local and tcp connection mechanism Use the URL scheme to distinguish between them, check that in QmlProfilerClientManager and test all possible combinations of URL parts. Change-Id: I6583e5bf18eda0344a299a279c12578c4ebc7ffe Reviewed-by: hjk --- src/plugins/android/androidrunner.cpp | 1 + src/plugins/projectexplorer/runnables.cpp | 6 ++ src/plugins/projectexplorer/runnables.h | 1 + .../qmlprofiler/qmlprofilerclientmanager.cpp | 13 ++- .../qmlprofiler/qmlprofilerclientmanager.h | 7 +- .../qmlprofiler/qmlprofilerruncontrol.cpp | 21 +++-- .../tests/localqmlprofilerrunner_test.cpp | 1 + .../tests/qmlprofilerclientmanager_test.cpp | 81 +++++++------------ 8 files changed, 63 insertions(+), 68 deletions(-) diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp index eb676d9bc8d..5eaaaf5241d 100644 --- a/src/plugins/android/androidrunner.cpp +++ b/src/plugins/android/androidrunner.cpp @@ -293,6 +293,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunControl *runControl, const AndroidRu QTC_ASSERT(server.listen(QHostAddress::LocalHost) || server.listen(QHostAddress::LocalHostIPv6), qDebug() << tr("No free ports available on host for QML debugging.")); + m_qmlServer.setScheme(urlTcpScheme()); m_qmlServer.setHost(server.serverAddress().toString()); m_qmlServer.setPort(server.serverPort()); } diff --git a/src/plugins/projectexplorer/runnables.cpp b/src/plugins/projectexplorer/runnables.cpp index 3ac15f53ef7..33d612f0adc 100644 --- a/src/plugins/projectexplorer/runnables.cpp +++ b/src/plugins/projectexplorer/runnables.cpp @@ -46,6 +46,7 @@ QUrl urlFromLocalHostAndFreePort() { QUrl serverUrl; QTcpServer server; + serverUrl.setScheme(urlTcpScheme()); if (server.listen(QHostAddress::LocalHost) || server.listen(QHostAddress::LocalHostIPv6)) { serverUrl.setHost(server.serverAddress().toString()); serverUrl.setPort(server.serverPort()); @@ -68,4 +69,9 @@ QString urlSocketScheme() return QString("socket"); } +QString urlTcpScheme() +{ + return QString("tcp"); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/runnables.h b/src/plugins/projectexplorer/runnables.h index f28aefeda4b..a893545d23a 100644 --- a/src/plugins/projectexplorer/runnables.h +++ b/src/plugins/projectexplorer/runnables.h @@ -56,5 +56,6 @@ PROJECTEXPLORER_EXPORT bool operator==(const StandardRunnable &r1, const Standar PROJECTEXPLORER_EXPORT QUrl urlFromLocalHostAndFreePort(); PROJECTEXPLORER_EXPORT QUrl urlFromLocalSocket(); PROJECTEXPLORER_EXPORT QString urlSocketScheme(); +PROJECTEXPLORER_EXPORT QString urlTcpScheme(); } // namespace ProjectExplorer diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index 2b919e7f429..0152d994e4a 100644 --- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -29,6 +29,7 @@ #include "qmlprofilerstatemanager.h" #include +#include namespace QmlProfiler { namespace Internal { @@ -65,13 +66,19 @@ void QmlProfilerClientManager::setRetryParams(int interval, int maxAttempts) m_maximumRetries = maxAttempts; } -void QmlProfilerClientManager::setServerUrl(const QUrl &server) +void QmlProfilerClientManager::connectToServer(const QUrl &server) { if (m_server != server) { m_server = server; disconnectClient(); stopConnectionTimer(); } + if (server.scheme() == ProjectExplorer::urlTcpScheme()) + connectToTcpServer(); + else if (server.scheme() == ProjectExplorer::urlSocketScheme()) + startLocalServer(); + else + QTC_ASSERT(false, emit connectionFailed()); } void QmlProfilerClientManager::clearConnection() @@ -166,9 +173,9 @@ void QmlProfilerClientManager::stopRecording() void QmlProfilerClientManager::retryConnect() { - if (m_server.scheme() == "socket") { + if (m_server.scheme() == ProjectExplorer::urlSocketScheme()) { startLocalServer(); - } else if (!m_server.host().isEmpty() && m_server.port() > 0) { + } else if (m_server.scheme() == ProjectExplorer::urlTcpScheme()) { disconnectClient(); connectToTcpServer(); } else { diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h index 61a9d178004..c64429abc70 100644 --- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -47,7 +47,7 @@ public: ~QmlProfilerClientManager(); void setProfilerStateManager(QmlProfilerStateManager *profilerState); - void setServerUrl(const QUrl &server); + void connectToServer(const QUrl &server); void clearConnection(); void clearBufferedData(); @@ -58,8 +58,6 @@ public: void setRetryParams(int interval, int maxAttempts); void retryConnect(); - void connectToTcpServer(); - void startLocalServer(); void stopRecording(); @@ -69,6 +67,9 @@ signals: void connectionClosed(); private: + void connectToTcpServer(); + void startLocalServer(); + QPointer m_profilerState; QPointer m_modelManager; QScopedPointer m_connection; diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp index 143e317cd75..7a24026e93e 100644 --- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp @@ -127,17 +127,10 @@ void QmlProfilerRunner::start() }); infoBox->show(); - }); - - clientManager->setServerUrl(serverUrl); - if (serverUrl.port() != -1) { - clientManager->connectToTcpServer(); - } else { - clientManager->startLocalServer(); - } + }, Qt::QueuedConnection); // Queue any connection failures after reportStarted() + clientManager->connectToServer(serverUrl); d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning); - reportStarted(); } @@ -284,9 +277,13 @@ LocalQmlProfilerSupport::LocalQmlProfilerSupport(RunControl *runControl, const Q StandardRunnable debuggee = runnable().as(); - QString code = serverUrl.scheme() == "socket" - ? QString("file:%1").arg(serverUrl.path()) - : QString("port:%1").arg(serverUrl.port()); + QString code; + if (serverUrl.scheme() == urlSocketScheme()) + code = QString("file:%1").arg(serverUrl.path()); + else if (serverUrl.scheme() == urlTcpScheme()) + code = QString("port:%1").arg(serverUrl.port()); + else + QTC_CHECK(false); QString arguments = QmlDebug::qmlDebugCommandLineArguments(QmlDebug::QmlProfilerServices, code, true); diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp index 53489eaee8b..754455c86b4 100644 --- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp +++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp @@ -56,6 +56,7 @@ void LocalQmlProfilerRunnerTest::testRunner() debuggee.environment = Utils::Environment::systemEnvironment(); // should not be used anywhere but cannot be empty + serverUrl.setScheme(ProjectExplorer::urlSocketScheme()); serverUrl.setPath("invalid"); runControl = new ProjectExplorer::RunControl(nullptr, diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp index d2347d42640..0318a6b6185 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp @@ -73,38 +73,32 @@ void QmlProfilerClientManagerTest::testConnectionFailure_data() QUrl localUrl = urlFromLocalHostAndFreePort(); QTest::addColumn("serverUrl"); - QVarLengthArray hosts({"", "/-/|\\-\\|/-", localUrl.host()}); - QVarLengthArray ports({-1, 5, localUrl.port()}); - QVarLengthArray sockets({"", "/-/|\\-\\|/-", urlFromLocalSocket().path()}); + const QVarLengthArray hosts({"", "/-/|\\-\\|/-", localUrl.host()}); + const QVarLengthArray ports({-1, 5, localUrl.port()}); + const QVarLengthArray sockets({"", "/-/|\\-\\|/-", urlFromLocalSocket().path()}); + const QVarLengthArray schemes({"", urlSocketScheme(), urlTcpScheme()}); - foreach (QmlProfilerModelManager *modelManager, modelManagers) { - foreach (QmlProfilerStateManager *stateManager, stateManagers) { - foreach (QString host, hosts) { - foreach (int port, ports) { - QString tag = QString::fromLatin1("%1, %2, %3, %4, %5") - .arg(QLatin1String(modelManager ? "modelManager" : "")) - .arg(QLatin1String(stateManager ? "stateManager" : "")) - .arg(host.isEmpty() ? "" : host) - .arg(Utils::Port(port).isValid() ? port : 0) - .arg(""); - QUrl url; - url.setHost(host); - url.setPort(port); - QTest::newRow(tag.toLatin1().constData()) << modelManager << stateManager << url; + for (QmlProfilerModelManager *modelManager : modelManagers) { + for (QmlProfilerStateManager *stateManager : stateManagers) { + for (const QString &host : hosts) { + for (int port : ports) { + for (const QString &socket : sockets) { + for (const QString &scheme : schemes ) { + QUrl url; + url.setScheme(scheme); + url.setHost(host); + url.setPort(port); + url.setPath(socket); + QString tag = QString::fromLatin1("%1, %2, %3") + .arg(QLatin1String(modelManager ? "modelManager" : "")) + .arg(QLatin1String(stateManager ? "stateManager" : "")) + .arg(url.toString()); + QTest::newRow(tag.toLatin1().constData()) << modelManager + << stateManager << url; + } + } } } - foreach (QString socket, sockets) { - QString tag = QString::fromLatin1("%1, %2, %3, %4, %5") - .arg(QLatin1String(modelManager ? "modelManager" : "")) - .arg(QLatin1String(stateManager ? "stateManager" : "")) - .arg("") - .arg(0) - .arg(socket); - QUrl url; - url.setScheme(urlSocketScheme()); - url.setPath(socket); - QTest::newRow(tag.toLatin1().constData()) << modelManager << stateManager << url; - } } } } @@ -137,24 +131,17 @@ void QmlProfilerClientManagerTest::testConnectionFailure() clientManager.setModelManager(modelManager); clientManager.setProfilerStateManager(stateManager); - clientManager.setServerUrl(serverUrl); QVERIFY(!clientManager.isConnected()); - clientManager.connectToTcpServer(); + clientManager.connectToServer(serverUrl); QTRY_COMPARE(failedSpy.count(), 1); QCOMPARE(closedSpy.count(), 0); QCOMPARE(openedSpy.count(), 0); QVERIFY(!clientManager.isConnected()); - clientManager.startLocalServer(); - QTRY_COMPARE(failedSpy.count(), 2); - QCOMPARE(closedSpy.count(), 0); - QCOMPARE(openedSpy.count(), 0); - QVERIFY(!clientManager.isConnected()); - clientManager.retryConnect(); - QTRY_COMPARE(failedSpy.count(), 3); + QTRY_COMPARE(failedSpy.count(), 2); QCOMPARE(closedSpy.count(), 0); QCOMPARE(openedSpy.count(), 0); QVERIFY(!clientManager.isConnected()); @@ -181,8 +168,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveTcp() server.listen(QHostAddress(serverUrl.host()), serverUrl.port()); QSignalSpy connectionSpy(&server, SIGNAL(newConnection())); - clientManager.setServerUrl(serverUrl); - clientManager.connectToTcpServer(); + clientManager.connectToServer(serverUrl); QTRY_VERIFY(connectionSpy.count() > 0); QTRY_COMPARE(failedSpy.count(), 1); @@ -208,8 +194,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveLocal() QLocalSocket socket; QSignalSpy connectionSpy(&socket, SIGNAL(connected())); - clientManager.setServerUrl(socketUrl); - clientManager.startLocalServer(); + clientManager.connectToServer(socketUrl); socket.connectToServer(socketUrl.path()); QTRY_COMPARE(connectionSpy.count(), 1); @@ -280,8 +265,7 @@ void QmlProfilerClientManagerTest::testResponsiveTcp() connect(&clientManager, &QmlProfilerClientManager::connectionFailed, &clientManager, &QmlProfilerClientManager::retryConnect); - clientManager.setServerUrl(serverUrl); - clientManager.connectToTcpServer(); + clientManager.connectToServer(serverUrl); QTRY_COMPARE(openedSpy.count(), 1); QCOMPARE(closedSpy.count(), 0); @@ -329,8 +313,7 @@ void QmlProfilerClientManagerTest::testResponsiveLocal() connect(&clientManager, &QmlProfilerClientManager::connectionFailed, &clientManager, &QmlProfilerClientManager::retryConnect); - clientManager.setServerUrl(socketUrl); - clientManager.startLocalServer(); + clientManager.connectToServer(socketUrl); { QScopedPointer socket(new QLocalSocket(this)); @@ -397,8 +380,7 @@ void QmlProfilerClientManagerTest::testInvalidData() server.listen(QHostAddress(serverUrl.host()), serverUrl.port()); - clientManager.setServerUrl(serverUrl); - clientManager.connectToTcpServer(); + clientManager.connectToServer(serverUrl); QTRY_VERIFY(dataSent); QTRY_COMPARE(failedSpy.count(), 1); @@ -427,8 +409,7 @@ void QmlProfilerClientManagerTest::testStopRecording() connect(&clientManager, &QmlProfilerClientManager::connectionFailed, &clientManager, &QmlProfilerClientManager::retryConnect); - clientManager.setServerUrl(socketUrl); - clientManager.startLocalServer(); + clientManager.connectToServer(socketUrl); QScopedPointer socket(new QLocalSocket(this)); socket->connectToServer(socketUrl.path()); From be868863e5f8e1a50e9c8b5ae383b3134b75907f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 20 Sep 2017 13:52:56 +0200 Subject: [PATCH 42/63] Clang: Enhance Jobs::cancelJobRequest for FollowSymbol ...which did not exist in the 4.4 branch. Change-Id: I70fa2ca2e4aa4a422b10883b69eb4d8e4ebce523 Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen --- src/tools/clangbackend/ipcsource/clangjobs.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tools/clangbackend/ipcsource/clangjobs.cpp b/src/tools/clangbackend/ipcsource/clangjobs.cpp index f241593ec62..ea7fde80ab4 100644 --- a/src/tools/clangbackend/ipcsource/clangjobs.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobs.cpp @@ -30,6 +30,7 @@ #include "projects.h" #include +#include #include #include @@ -223,6 +224,12 @@ void Jobs::cancelJobRequest(const JobRequest &jobRequest) CompletionCorrection::NoCorrection, jobRequest.ticketNumber)); break; + case JobRequest::Type::FollowSymbol: + m_client.followSymbol(FollowSymbolMessage(FileContainer(), + SourceRangeContainer(), + true, + jobRequest.ticketNumber)); + break; default: break; } From 3b415dbd04bc87540ea212f2972264d559fd2b4d Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 20 Sep 2017 16:38:22 +0200 Subject: [PATCH 43/63] Clang: Centralize job related switch code ...and where applicable, ensure that a warning is printed once a jobrequest type is not handled. Change-Id: Ida0b5a175947ebf75c1c4e5116a77f0270825336 Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen --- .../clangbackend/ipcsource/clangiasyncjob.cpp | 39 ---------- .../clangbackend/ipcsource/clangiasyncjob.h | 2 - .../ipcsource/clangjobrequest.cpp | 78 +++++++++++++++++++ .../clangbackend/ipcsource/clangjobrequest.h | 5 ++ .../clangbackend/ipcsource/clangjobs.cpp | 39 +--------- src/tools/clangbackend/ipcsource/clangjobs.h | 1 - 6 files changed, 85 insertions(+), 79 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangiasyncjob.cpp b/src/tools/clangbackend/ipcsource/clangiasyncjob.cpp index 45fe842dda3..c325c494c9b 100644 --- a/src/tools/clangbackend/ipcsource/clangiasyncjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangiasyncjob.cpp @@ -25,49 +25,10 @@ #include "clangiasyncjob.h" -#include "clangcompletecodejob.h" -#include "clangcreateinitialdocumentpreamblejob.h" -#include "clangfollowsymboljob.h" -#include "clangparsesupportivetranslationunitjob.h" -#include "clangreparsesupportivetranslationunitjob.h" -#include "clangrequestdocumentannotationsjob.h" -#include "clangrequestreferencesjob.h" -#include "clangresumedocumentjob.h" -#include "clangsuspenddocumentjob.h" -#include "clangupdatedocumentannotationsjob.h" - Q_LOGGING_CATEGORY(jobsLog, "qtc.clangbackend.jobs"); namespace ClangBackEnd { -IAsyncJob *IAsyncJob::create(JobRequest::Type type) -{ - switch (type) { - case JobRequest::Type::UpdateDocumentAnnotations: - return new UpdateDocumentAnnotationsJob(); - case JobRequest::Type::ParseSupportiveTranslationUnit: - return new ParseSupportiveTranslationUnitJob(); - case JobRequest::Type::ReparseSupportiveTranslationUnit: - return new ReparseSupportiveTranslationUnitJob(); - case JobRequest::Type::CreateInitialDocumentPreamble: - return new CreateInitialDocumentPreambleJob(); - case JobRequest::Type::CompleteCode: - return new CompleteCodeJob(); - case JobRequest::Type::RequestDocumentAnnotations: - return new RequestDocumentAnnotationsJob(); - case JobRequest::Type::RequestReferences: - return new RequestReferencesJob(); - case JobRequest::Type::FollowSymbol: - return new FollowSymbolJob(); - case JobRequest::Type::SuspendDocument: - return new SuspendDocumentJob(); - case JobRequest::Type::ResumeDocument: - return new ResumeDocumentJob(); - } - - return nullptr; -} - IAsyncJob::IAsyncJob() : m_context(JobContext()) { diff --git a/src/tools/clangbackend/ipcsource/clangiasyncjob.h b/src/tools/clangbackend/ipcsource/clangiasyncjob.h index 98f61e857ab..e4481fcbf5d 100644 --- a/src/tools/clangbackend/ipcsource/clangiasyncjob.h +++ b/src/tools/clangbackend/ipcsource/clangiasyncjob.h @@ -39,8 +39,6 @@ namespace ClangBackEnd { class IAsyncJob { public: - static IAsyncJob *create(JobRequest::Type type); - struct AsyncPrepareResult { operator bool() const { return !translationUnitId.isEmpty(); } Utf8String translationUnitId; diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp index 5ce175f1a5a..7f83d3bd956 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp @@ -25,6 +25,22 @@ #include "clangjobrequest.h" +#include "clangcompletecodejob.h" +#include "clangcreateinitialdocumentpreamblejob.h" +#include "clangfollowsymboljob.h" +#include "clangparsesupportivetranslationunitjob.h" +#include "clangreparsesupportivetranslationunitjob.h" +#include "clangrequestdocumentannotationsjob.h" +#include "clangrequestreferencesjob.h" +#include "clangresumedocumentjob.h" +#include "clangsuspenddocumentjob.h" +#include "clangupdatedocumentannotationsjob.h" + +#include +#include +#include +#include + #include #include @@ -102,6 +118,68 @@ JobRequest::JobRequest() id = ++idCounter; } +IAsyncJob *JobRequest::createJob() const +{ + switch (type) { + case JobRequest::Type::UpdateDocumentAnnotations: + return new UpdateDocumentAnnotationsJob(); + case JobRequest::Type::ParseSupportiveTranslationUnit: + return new ParseSupportiveTranslationUnitJob(); + case JobRequest::Type::ReparseSupportiveTranslationUnit: + return new ReparseSupportiveTranslationUnitJob(); + case JobRequest::Type::CreateInitialDocumentPreamble: + return new CreateInitialDocumentPreambleJob(); + case JobRequest::Type::CompleteCode: + return new CompleteCodeJob(); + case JobRequest::Type::RequestDocumentAnnotations: + return new RequestDocumentAnnotationsJob(); + case JobRequest::Type::RequestReferences: + return new RequestReferencesJob(); + case JobRequest::Type::FollowSymbol: + return new FollowSymbolJob(); + case JobRequest::Type::SuspendDocument: + return new SuspendDocumentJob(); + case JobRequest::Type::ResumeDocument: + return new ResumeDocumentJob(); + } + + return nullptr; +} + +void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const +{ + // If a job request with a ticket number is cancelled, the plugin side + // must get back some results in order to clean up the state there. + + switch (type) { + case JobRequest::Type::UpdateDocumentAnnotations: + case JobRequest::Type::ParseSupportiveTranslationUnit: + case JobRequest::Type::ReparseSupportiveTranslationUnit: + case JobRequest::Type::CreateInitialDocumentPreamble: + case JobRequest::Type::RequestDocumentAnnotations: + case JobRequest::Type::SuspendDocument: + case JobRequest::Type::ResumeDocument: + break; + case JobRequest::Type::RequestReferences: + client.references(ReferencesMessage(FileContainer(), + QVector(), + false, + ticketNumber)); + break; + case JobRequest::Type::CompleteCode: + client.codeCompleted(CodeCompletedMessage(CodeCompletions(), + CompletionCorrection::NoCorrection, + ticketNumber)); + break; + case JobRequest::Type::FollowSymbol: + client.followSymbol(FollowSymbolMessage(FileContainer(), + SourceRangeContainer(), + true, + ticketNumber)); + break; + } +} + bool JobRequest::operator==(const JobRequest &other) const { return type == other.type diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.h b/src/tools/clangbackend/ipcsource/clangjobrequest.h index 954ac6122e0..cca6c344d6e 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.h +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.h @@ -39,7 +39,9 @@ namespace ClangBackEnd { +class ClangCodeModelClientInterface; class Document; +class IAsyncJob; class JobRequest { @@ -91,6 +93,9 @@ public: JobRequest(); + IAsyncJob *createJob() const; + void cancelJob(ClangCodeModelClientInterface &client) const; + bool operator==(const JobRequest &other) const; public: diff --git a/src/tools/clangbackend/ipcsource/clangjobs.cpp b/src/tools/clangbackend/ipcsource/clangjobs.cpp index ea7fde80ab4..9fce7894b98 100644 --- a/src/tools/clangbackend/ipcsource/clangjobs.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobs.cpp @@ -29,10 +29,6 @@ #include "clangiasyncjob.h" #include "projects.h" -#include -#include -#include - #include #include #include @@ -59,7 +55,7 @@ Jobs::Jobs(Documents &documents, return isJobRunningForJobRequest(jobRequest); }); m_queue.setCancelJobRequest([this](const JobRequest &jobRequest) { - return cancelJobRequest(jobRequest); + jobRequest.cancelJob(m_client); }); } @@ -132,7 +128,7 @@ JobRequests Jobs::runJobs(const JobRequests &jobsRequests) bool Jobs::runJob(const JobRequest &jobRequest) { - IAsyncJob *asyncJob = IAsyncJob::create(jobRequest.type); + IAsyncJob *asyncJob = jobRequest.createJob(); QTC_ASSERT(asyncJob, return false); JobContext context(jobRequest, &m_documents, &m_unsavedFiles, &m_client); @@ -204,35 +200,4 @@ bool Jobs::isJobRunningForJobRequest(const JobRequest &jobRequest) const return Utils::anyOf(m_running.values(), hasJobRequest); } -void Jobs::cancelJobRequest(const JobRequest &jobRequest) -{ - // TODO: Consider to refactor this. Jobs should not know anything about - // concrete messages. On the other hand, having this here avoids - // duplication in multiple job classes. - - // If a job request with a ticket number is cancelled, the plugin side - // must get back some results in order to clean up the state there. - switch (jobRequest.type) { - case JobRequest::Type::RequestReferences: - m_client.references(ReferencesMessage(FileContainer(), - QVector(), - false, - jobRequest.ticketNumber)); - break; - case JobRequest::Type::CompleteCode: - m_client.codeCompleted(CodeCompletedMessage(CodeCompletions(), - CompletionCorrection::NoCorrection, - jobRequest.ticketNumber)); - break; - case JobRequest::Type::FollowSymbol: - m_client.followSymbol(FollowSymbolMessage(FileContainer(), - SourceRangeContainer(), - true, - jobRequest.ticketNumber)); - break; - default: - break; - } -} - } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangjobs.h b/src/tools/clangbackend/ipcsource/clangjobs.h index c91758566b8..d154d401e88 100644 --- a/src/tools/clangbackend/ipcsource/clangjobs.h +++ b/src/tools/clangbackend/ipcsource/clangjobs.h @@ -80,7 +80,6 @@ public /*for tests*/: bool isJobRunningForJobRequest(const JobRequest &jobRequest) const; private: - void cancelJobRequest(const JobRequest &jobRequest); JobRequests runJobs(const JobRequests &jobRequest); bool runJob(const JobRequest &jobRequest); void onJobFinished(IAsyncJob *asyncJob); From 4c571f405688afd7fd0a97227c1337922badd8b4 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 20 Sep 2017 17:12:06 +0200 Subject: [PATCH 44/63] Clang: Simplify creation of JobRequest Do what can be done in the constructor instead of relying on the clients. Change-Id: I5f475b5309afb37e34d228e54ad3c12f1698d72b Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen --- .../ipcsource/clangjobrequest.cpp | 93 +++++++++++-------- .../clangbackend/ipcsource/clangjobrequest.h | 7 +- .../clangbackend/ipcsource/clangjobs.cpp | 5 +- tests/unit/unittest/clangasyncjob-base.cpp | 5 +- tests/unit/unittest/clangjobqueue-test.cpp | 5 +- 5 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp index 7f83d3bd956..90e1a966817 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp @@ -41,6 +41,8 @@ #include #include +#include + #include #include @@ -51,6 +53,7 @@ namespace ClangBackEnd { static const char *JobRequestTypeToText(JobRequest::Type type) { switch (type) { + RETURN_TEXT_FOR_CASE(Invalid); RETURN_TEXT_FOR_CASE(UpdateDocumentAnnotations); RETURN_TEXT_FOR_CASE(ParseSupportiveTranslationUnit); RETURN_TEXT_FOR_CASE(ReparseSupportiveTranslationUnit); @@ -112,15 +115,66 @@ QDebug operator<<(QDebug debug, const JobRequest &jobRequest) return debug.space(); } -JobRequest::JobRequest() +static JobRequest::ExpirationReasons expirationReasonsForType(JobRequest::Type type) +{ + using Type = JobRequest::Type; + using ExpirationReason = JobRequest::ExpirationReason; + using ExpirationReasons = JobRequest::ExpirationReasons; + + switch (type) { + case Type::UpdateDocumentAnnotations: + return ExpirationReasons(ExpirationReason::AnythingChanged); + case Type::RequestReferences: + case Type::RequestDocumentAnnotations: + case Type::FollowSymbol: + return ExpirationReasons(ExpirationReason::DocumentClosed) + | ExpirationReasons(ExpirationReason::DocumentRevisionChanged); + default: + return ExpirationReason::DocumentClosed; + } +} + +static JobRequest::Conditions conditionsForType(JobRequest::Type type) +{ + using Type = JobRequest::Type; + using Condition = JobRequest::Condition; + using Conditions = JobRequest::Conditions; + + if (type == Type::SuspendDocument) { + return Conditions(Condition::DocumentUnsuspended) + | Conditions(Condition::DocumentNotVisible); + } + + if (type == Type::ResumeDocument) { + return Conditions(Condition::DocumentSuspended) + | Conditions(Condition::DocumentVisible); + } + + Conditions conditions = Conditions(Condition::DocumentUnsuspended) + | Conditions(Condition::DocumentVisible); + + if (type == Type::RequestReferences) + conditions |= Condition::CurrentDocumentRevision; + + return conditions; +} + +JobRequest::JobRequest(Type type) { static quint64 idCounter = 0; + id = ++idCounter; + this->type = type; + conditions = conditionsForType(type); + expirationReasons = expirationReasonsForType(type); } IAsyncJob *JobRequest::createJob() const { switch (type) { + case JobRequest::Type::Invalid: + QTC_CHECK(false && "Cannot create job for invalid job request."); + break; case JobRequest::Type::UpdateDocumentAnnotations: return new UpdateDocumentAnnotationsJob(); case JobRequest::Type::ParseSupportiveTranslationUnit: @@ -152,6 +206,7 @@ void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const // must get back some results in order to clean up the state there. switch (type) { + case JobRequest::Type::Invalid: case JobRequest::Type::UpdateDocumentAnnotations: case JobRequest::Type::ParseSupportiveTranslationUnit: case JobRequest::Type::ReparseSupportiveTranslationUnit: @@ -198,40 +253,4 @@ bool JobRequest::operator==(const JobRequest &other) const && ticketNumber == other.ticketNumber; } -JobRequest::ExpirationReasons JobRequest::expirationReasonsForType(Type type) -{ - switch (type) { - case Type::UpdateDocumentAnnotations: - return ExpirationReasons(ExpirationReason::AnythingChanged); - case Type::RequestReferences: - case Type::RequestDocumentAnnotations: - case Type::FollowSymbol: - return ExpirationReasons(ExpirationReason::DocumentClosed) - | ExpirationReasons(ExpirationReason::DocumentRevisionChanged); - default: - return ExpirationReason::DocumentClosed; - } -} - -JobRequest::Conditions JobRequest::conditionsForType(JobRequest::Type type) -{ - if (type == Type::SuspendDocument) { - return Conditions(Condition::DocumentUnsuspended) - | Conditions(Condition::DocumentNotVisible); - } - - if (type == Type::ResumeDocument) { - return Conditions(Condition::DocumentSuspended) - | Conditions(Condition::DocumentVisible); - } - - Conditions conditions = Conditions(Condition::DocumentUnsuspended) - | Conditions(Condition::DocumentVisible); - - if (type == Type::RequestReferences) - conditions |= Condition::CurrentDocumentRevision; - - return conditions; -} - } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.h b/src/tools/clangbackend/ipcsource/clangjobrequest.h index cca6c344d6e..54d2ef6fed8 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.h +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.h @@ -47,6 +47,8 @@ class JobRequest { public: enum class Type { + Invalid, + UpdateDocumentAnnotations, CreateInitialDocumentPreamble, @@ -88,10 +90,7 @@ public: Q_DECLARE_FLAGS(ExpirationReasons, ExpirationReason) public: - static ExpirationReasons expirationReasonsForType(Type type); - static Conditions conditionsForType(Type type); - - JobRequest(); + JobRequest(Type type = Type::Invalid); IAsyncJob *createJob() const; void cancelJob(ClangCodeModelClientInterface &client) const; diff --git a/src/tools/clangbackend/ipcsource/clangjobs.cpp b/src/tools/clangbackend/ipcsource/clangjobs.cpp index 9fce7894b98..033dc4ef1a4 100644 --- a/src/tools/clangbackend/ipcsource/clangjobs.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobs.cpp @@ -76,10 +76,7 @@ JobRequest Jobs::createJobRequest(const Document &document, JobRequest::Type type, PreferredTranslationUnit preferredTranslationUnit) const { - JobRequest jobRequest; - jobRequest.type = type; - jobRequest.expirationReasons = JobRequest::expirationReasonsForType(type); - jobRequest.conditions = JobRequest::conditionsForType(type); + JobRequest jobRequest(type); jobRequest.filePath = document.filePath(); jobRequest.projectPartId = document.projectPart().id(); jobRequest.unsavedFilesChangeTimePoint = m_unsavedFiles.lastChangeTimePoint(); diff --git a/tests/unit/unittest/clangasyncjob-base.cpp b/tests/unit/unittest/clangasyncjob-base.cpp index 81593c9ac3a..6535a15ef7c 100644 --- a/tests/unit/unittest/clangasyncjob-base.cpp +++ b/tests/unit/unittest/clangasyncjob-base.cpp @@ -49,10 +49,7 @@ void ClangAsyncJobTest::BaseSetUp(ClangBackEnd::JobRequest::Type jobRequestType, JobRequest ClangAsyncJobTest::createJobRequest(const Utf8String &filePath, JobRequest::Type type) const { - JobRequest jobRequest; - jobRequest.type = type; - jobRequest.expirationReasons = JobRequest::expirationReasonsForType(type); - jobRequest.conditions = JobRequest::conditionsForType(type); + JobRequest jobRequest(type); jobRequest.filePath = filePath; jobRequest.projectPartId = projectPartId; jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint(); diff --git a/tests/unit/unittest/clangjobqueue-test.cpp b/tests/unit/unittest/clangjobqueue-test.cpp index c3236a4d6da..dd3f4fc0364 100644 --- a/tests/unit/unittest/clangjobqueue-test.cpp +++ b/tests/unit/unittest/clangjobqueue-test.cpp @@ -538,10 +538,7 @@ JobRequest JobQueue::createJobRequest( JobRequest::Type type, PreferredTranslationUnit preferredTranslationUnit) const { - JobRequest jobRequest; - jobRequest.type = type; - jobRequest.expirationReasons = JobRequest::expirationReasonsForType(type); - jobRequest.conditions = JobRequest::conditionsForType(type); + JobRequest jobRequest(type); jobRequest.filePath = filePath; jobRequest.projectPartId = projectPartId; jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint(); From ee6a911deffd7959023f30b2cea0ed795ee3f1f8 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 20 Sep 2017 17:17:44 +0200 Subject: [PATCH 45/63] Clang: Add a clarifying comment in JobRequest::operator== Change-Id: I5961afbef0408c9993e5cf8300d905683e3e1e80 Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen --- src/tools/clangbackend/ipcsource/clangjobrequest.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp index 90e1a966817..ef44115eb31 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp @@ -251,6 +251,9 @@ bool JobRequest::operator==(const JobRequest &other) const && line == other.line && column == other.column && ticketNumber == other.ticketNumber; + + // Additional members that are not compared here explicitly are + // supposed to depend on the already compared ones. } } // namespace ClangBackEnd From 93ef552d79385e275beb8dec3767434f575a49d4 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 20 Sep 2017 17:28:25 +0200 Subject: [PATCH 46/63] Clang: Rename some enums in JobRequest ...because both are conditions: ExpirationReason --> ExpirationCondition Condition --> RunCondition Change-Id: Iae79b11c20618574fac8142710b11b5c16339127 Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen --- .../clangbackend/ipcsource/clangjobqueue.cpp | 20 ++++++------- .../ipcsource/clangjobrequest.cpp | 28 +++++++++---------- .../clangbackend/ipcsource/clangjobrequest.h | 12 ++++---- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangjobqueue.cpp b/src/tools/clangbackend/ipcsource/clangjobqueue.cpp index 383c2ecaa45..4ea098db3ac 100644 --- a/src/tools/clangbackend/ipcsource/clangjobqueue.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobqueue.cpp @@ -105,11 +105,11 @@ void JobQueue::removeExpiredRequests() bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest) { - const JobRequest::ExpirationReasons expirationReasons = jobRequest.expirationReasons; + const JobRequest::ExpirationConditions conditions = jobRequest.expirationConditions; const UnsavedFiles unsavedFiles = m_documents.unsavedFiles(); - using ExpirationReason = JobRequest::ExpirationReason; + using Condition = JobRequest::ExpirationCondition; - if (expirationReasons.testFlag(ExpirationReason::UnsavedFilesChanged)) { + if (conditions.testFlag(Condition::UnsavedFilesChanged)) { if (jobRequest.unsavedFilesChangeTimePoint != unsavedFiles.lastChangeTimePoint()) { qCDebug(jobsLog) << "Removing due to outdated unsaved files:" << jobRequest; return true; @@ -118,7 +118,7 @@ bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest) bool projectCheckedAndItExists = false; - if (expirationReasons.testFlag(ExpirationReason::DocumentClosed)) { + if (conditions.testFlag(Condition::DocumentClosed)) { if (!m_documents.hasDocument(jobRequest.filePath, jobRequest.projectPartId)) { qCDebug(jobsLog) << "Removing due to already closed document:" << jobRequest; return true; @@ -138,7 +138,7 @@ bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest) return true; } - if (expirationReasons.testFlag(ExpirationReason::DocumentRevisionChanged)) { + if (conditions.testFlag(Condition::DocumentRevisionChanged)) { if (document.documentRevision() > jobRequest.documentRevision) { qCDebug(jobsLog) << "Removing due to changed document revision:" << jobRequest; return true; @@ -146,7 +146,7 @@ bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest) } } - if (expirationReasons.testFlag(ExpirationReason::ProjectChanged)) { + if (conditions.testFlag(Condition::ProjectChanged)) { if (!projectCheckedAndItExists && !m_projectParts.hasProjectPart(jobRequest.projectPartId)) { qCDebug(jobsLog) << "Removing due to already closed project:" << jobRequest; return true; @@ -194,10 +194,10 @@ void JobQueue::cancelJobRequest(const JobRequest &jobRequest) m_cancelJobRequest(jobRequest); } -static bool passesPreconditions(const JobRequest &request, const Document &document) +static bool areRunConditionsMet(const JobRequest &request, const Document &document) { - using Condition = JobRequest::Condition; - const JobRequest::Conditions conditions = request.conditions; + using Condition = JobRequest::RunCondition; + const JobRequest::RunConditions conditions = request.runConditions; if (conditions.testFlag(Condition::DocumentSuspended) && !document.isSuspended()) { qCDebug(jobsLog) << "Not choosing due to unsuspended document:" << request; @@ -250,7 +250,7 @@ JobRequests JobQueue::takeJobRequestsToRunNow() const Document &document = m_documents.document(request.filePath, request.projectPartId); - if (!passesPreconditions(request, document)) + if (!areRunConditionsMet(request, document)) continue; const Utf8String id = document.translationUnit(request.preferredTranslationUnit).id(); diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp index ef44115eb31..4130557ee67 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp @@ -115,30 +115,30 @@ QDebug operator<<(QDebug debug, const JobRequest &jobRequest) return debug.space(); } -static JobRequest::ExpirationReasons expirationReasonsForType(JobRequest::Type type) +static JobRequest::ExpirationConditions expirationConditionsForType(JobRequest::Type type) { using Type = JobRequest::Type; - using ExpirationReason = JobRequest::ExpirationReason; - using ExpirationReasons = JobRequest::ExpirationReasons; + using Condition = JobRequest::ExpirationCondition; + using Conditions = JobRequest::ExpirationConditions; switch (type) { case Type::UpdateDocumentAnnotations: - return ExpirationReasons(ExpirationReason::AnythingChanged); + return Conditions(Condition::AnythingChanged); case Type::RequestReferences: case Type::RequestDocumentAnnotations: case Type::FollowSymbol: - return ExpirationReasons(ExpirationReason::DocumentClosed) - | ExpirationReasons(ExpirationReason::DocumentRevisionChanged); + return Conditions(Condition::DocumentClosed) + | Conditions(Condition::DocumentRevisionChanged); default: - return ExpirationReason::DocumentClosed; + return Condition::DocumentClosed; } } -static JobRequest::Conditions conditionsForType(JobRequest::Type type) +static JobRequest::RunConditions conditionsForType(JobRequest::Type type) { using Type = JobRequest::Type; - using Condition = JobRequest::Condition; - using Conditions = JobRequest::Conditions; + using Condition = JobRequest::RunCondition; + using Conditions = JobRequest::RunConditions; if (type == Type::SuspendDocument) { return Conditions(Condition::DocumentUnsuspended) @@ -165,8 +165,8 @@ JobRequest::JobRequest(Type type) id = ++idCounter; this->type = type; - conditions = conditionsForType(type); - expirationReasons = expirationReasonsForType(type); + runConditions = conditionsForType(type); + expirationConditions = expirationConditionsForType(type); } IAsyncJob *JobRequest::createJob() const @@ -238,8 +238,8 @@ void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const bool JobRequest::operator==(const JobRequest &other) const { return type == other.type - && expirationReasons == other.expirationReasons - && conditions == other.conditions + && expirationConditions == other.expirationConditions + && runConditions == other.runConditions && filePath == other.filePath && projectPartId == other.projectPartId diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.h b/src/tools/clangbackend/ipcsource/clangjobrequest.h index 54d2ef6fed8..a73eda7beeb 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.h +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.h @@ -64,7 +64,7 @@ public: ResumeDocument, }; - enum class Condition { + enum class RunCondition { NoCondition = 1 << 0, DocumentVisible = 1 << 1, DocumentNotVisible = 1 << 2, @@ -72,9 +72,9 @@ public: DocumentUnsuspended = 1 << 4, CurrentDocumentRevision = 1 << 5, }; - Q_DECLARE_FLAGS(Conditions, Condition) + Q_DECLARE_FLAGS(RunConditions, RunCondition) - enum class ExpirationReason { + enum class ExpirationCondition { Never = 1 << 0, DocumentClosed = 1 << 1, @@ -87,7 +87,7 @@ public: | UnsavedFilesChanged | ProjectChanged, }; - Q_DECLARE_FLAGS(ExpirationReasons, ExpirationReason) + Q_DECLARE_FLAGS(ExpirationConditions, ExpirationCondition) public: JobRequest(Type type = Type::Invalid); @@ -100,8 +100,8 @@ public: public: quint64 id = 0; Type type; - ExpirationReasons expirationReasons; - Conditions conditions; + ExpirationConditions expirationConditions; + RunConditions runConditions; // General Utf8String filePath; From 8d84e591689b88a51fde1c2052af4ad759ba9fc1 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 21 Sep 2017 00:03:43 -0700 Subject: [PATCH 47/63] Update QML type descriptions for qbs Change-Id: I208e7e96b5a430ae55ca073abee7954c4f2382e1 Reviewed-by: Joerg Bornemann --- share/qtcreator/qml-type-descriptions/qbs.qmltypes | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/qml-type-descriptions/qbs.qmltypes b/share/qtcreator/qml-type-descriptions/qbs.qmltypes index 20d36bf5326..718baa6a04b 100644 --- a/share/qtcreator/qml-type-descriptions/qbs.qmltypes +++ b/share/qtcreator/qml-type-descriptions/qbs.qmltypes @@ -20,7 +20,7 @@ Module { prototype: "QQuickItem" Property { name: "condition"; type: "bool" } Property { name: "limitToSubProject"; type: "bool" } - Property { name: "multiplexConfigurationId"; type: "string" } + Property { name: "multiplexConfigurationIds"; type: "string"; isList: true } Property { name: "name"; type: "string" } Property { name: "productTypes"; type: "string"; isList: true } Property { name: "profiles"; type: "string"; isList: true } @@ -49,6 +49,7 @@ Module { Property { name: "condition"; type: "bool" } Property { name: "fileTags"; type: "string"; isList: true } Property { name: "patterns"; type: "string"; isList: true } + Property { name: "priority"; type: "int" } } Component { name: "Group" @@ -118,6 +119,14 @@ Module { Property { name: "type"; type: "string"; isList: true } Property { name: "version"; type: "string" } } + Component { + name: "Profile" + exports: [ "qbs/Profile 1.0" ] + prototype: "QQuickItem" + Property { name: "baseProfile"; type: "string" } + Property { name: "condition"; type: "bool" } + Property { name: "name"; type: "string" } + } Component { name: "Project" exports: [ "qbs/Project 1.0" ] From d7678124b332301cd07d134e2c938dc1cb84a29f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 21 Sep 2017 14:38:50 +0200 Subject: [PATCH 48/63] Clang: Extract base class DocumentJob ...to remove some duplication. Change-Id: If3e792031dd232687a8f83883783fc55eefee0c7 Reviewed-by: Tim Jenssen --- .../ipcsource/clangbackendclangipc-source.pri | 1 + .../ipcsource/clangcompletecodejob.h | 8 +--- .../clangcreateinitialdocumentpreamblejob.h | 9 +--- .../clangbackend/ipcsource/clangdocumentjob.h | 43 +++++++++++++++++++ .../ipcsource/clangfollowsymboljob.h | 9 +--- .../clangparsesupportivetranslationunitjob.h | 9 +--- ...clangreparsesupportivetranslationunitjob.h | 9 +--- .../clangrequestdocumentannotationsjob.h | 9 +--- .../ipcsource/clangrequestreferencesjob.h | 11 +---- .../ipcsource/clangsuspenddocumentjob.h | 9 +--- .../clangupdatedocumentannotationsjob.h | 12 +----- 11 files changed, 62 insertions(+), 67 deletions(-) create mode 100644 src/tools/clangbackend/ipcsource/clangdocumentjob.h diff --git a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri index c12ba232543..6919db68399 100644 --- a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri +++ b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri @@ -9,6 +9,7 @@ HEADERS += \ $$PWD/clangcompletecodejob.h \ $$PWD/clangcreateinitialdocumentpreamblejob.h \ $$PWD/clangdocument.h \ + $$PWD/clangdocumentjob.h \ $$PWD/clangdocumentprocessor.h \ $$PWD/clangdocumentprocessors.h \ $$PWD/clangdocuments.h \ diff --git a/src/tools/clangbackend/ipcsource/clangcompletecodejob.h b/src/tools/clangbackend/ipcsource/clangcompletecodejob.h index 54b0ae5ec34..4e9c274faf9 100644 --- a/src/tools/clangbackend/ipcsource/clangcompletecodejob.h +++ b/src/tools/clangbackend/ipcsource/clangcompletecodejob.h @@ -25,8 +25,7 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" +#include "clangdocumentjob.h" #include @@ -38,16 +37,13 @@ struct CompleteCodeJobResult CompletionCorrection correction = CompletionCorrection::NoCorrection; }; -class CompleteCodeJob : public AsyncJob +class CompleteCodeJob : public DocumentJob { public: using AsyncResult = CompleteCodeJobResult; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - Document m_pinnedDocument; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.h b/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.h index 570b746460e..f8b790ea36d 100644 --- a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.h +++ b/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.h @@ -25,20 +25,15 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" +#include "clangdocumentjob.h" namespace ClangBackEnd { -class CreateInitialDocumentPreambleJob : public AsyncJob +class CreateInitialDocumentPreambleJob : public DocumentJob { public: AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - Document m_pinnedDocument; - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangdocumentjob.h b/src/tools/clangbackend/ipcsource/clangdocumentjob.h new file mode 100644 index 00000000000..caa2eb6f0f5 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/clangdocumentjob.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "clangasyncjob.h" +#include "clangdocument.h" + +#include + +namespace ClangBackEnd { + +template +class DocumentJob : public AsyncJob +{ +protected: + Document m_pinnedDocument; + FileContainer m_pinnedFileContainer; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h index ce2ca4e06c0..7c8391fb9b2 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h +++ b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h @@ -25,8 +25,7 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" +#include "clangdocumentjob.h" #include @@ -51,16 +50,12 @@ public: bool failedToFollow = false; }; -class FollowSymbolJob : public AsyncJob +class FollowSymbolJob : public DocumentJob { public: using AsyncResult = FollowSymbolResult; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - Document m_pinnedDocument; - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h index 6d4d01131e2..b733dc72b74 100644 --- a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h +++ b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h @@ -25,8 +25,7 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" +#include "clangdocumentjob.h" namespace ClangBackEnd { @@ -35,17 +34,13 @@ struct ParseSupportiveTranslationUnitJobResult TranslationUnitUpdateResult updateResult; }; -class ParseSupportiveTranslationUnitJob : public AsyncJob +class ParseSupportiveTranslationUnitJob : public DocumentJob { public: using AsyncResult = ParseSupportiveTranslationUnitJobResult; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - Document m_pinnedDocument; - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.h b/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.h index 1b352c2c361..cb146299c72 100644 --- a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.h +++ b/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.h @@ -25,8 +25,7 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" +#include "clangdocumentjob.h" namespace ClangBackEnd { @@ -35,17 +34,13 @@ struct ReparseSupportiveTranslationUnitJobResult TranslationUnitUpdateResult updateResult; }; -class ReparseSupportiveTranslationUnitJob : public AsyncJob +class ReparseSupportiveTranslationUnitJob : public DocumentJob { public: using AsyncResult = ReparseSupportiveTranslationUnitJobResult; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - Document m_pinnedDocument; - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h index dcbe42b6e45..d3d88a03df4 100644 --- a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h +++ b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h @@ -25,8 +25,7 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" +#include "clangdocumentjob.h" #include #include @@ -42,7 +41,7 @@ struct RequestDocumentAnnotationsJobResult QVector skippedSourceRanges; }; -class RequestDocumentAnnotationsJob : public AsyncJob +class RequestDocumentAnnotationsJob : public DocumentJob { public: using AsyncResult = RequestDocumentAnnotationsJobResult; @@ -52,10 +51,6 @@ public: private: void sendAnnotations(const AsyncResult &result); - -private: - Document m_pinnedDocument; - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.h b/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.h index 13a904bddc1..d92d869a9bb 100644 --- a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.h +++ b/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.h @@ -25,25 +25,18 @@ #pragma once -#include "clangasyncjob.h" +#include "clangdocumentjob.h" #include "clangreferencescollector.h" -#include "clangdocument.h" - -#include namespace ClangBackEnd { -class RequestReferencesJob : public AsyncJob +class RequestReferencesJob : public DocumentJob { public: using AsyncResult = ReferencesResult; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - Document m_pinnedDocument; - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.h b/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.h index 16d5b52a1ea..5948f8226f1 100644 --- a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.h +++ b/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.h @@ -25,20 +25,15 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" +#include "clangdocumentjob.h" namespace ClangBackEnd { -class SuspendDocumentJob : public AsyncJob +class SuspendDocumentJob : public DocumentJob { public: AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - Document m_pinnedDocument; - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h index a49e9b45b51..b7f56318f05 100644 --- a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h +++ b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h @@ -25,9 +25,7 @@ #pragma once -#include "clangasyncjob.h" -#include "clangdocument.h" -#include "clangtranslationunitupdater.h" +#include "clangdocumentjob.h" #include #include @@ -45,7 +43,7 @@ struct UpdateDocumentAnnotationsJobResult QVector skippedSourceRanges; }; -class UpdateDocumentAnnotationsJob : public AsyncJob +class UpdateDocumentAnnotationsJob : public DocumentJob { public: using AsyncResult = UpdateDocumentAnnotationsJobResult; @@ -60,12 +58,6 @@ protected: private: void incorporateUpdaterResult(const AsyncResult &result); void sendAnnotations(const AsyncResult &result); - -protected: - Document m_pinnedDocument; - -private: - FileContainer m_pinnedFileContainer; }; } // namespace ClangBackEnd From 774b9c010dc49a6dd5c77f41100adb0d25999455 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 21 Sep 2017 15:08:45 +0200 Subject: [PATCH 49/63] Clang: Move acquisition of document data into DocumentJob ...to remove more boiler plate code in the job classes. Change-Id: I21b07c1c74c9e2c1cd1cbf302ac801ed583642ed Reviewed-by: Tim Jenssen --- .../ipcsource/clangcompletecodejob.cpp | 33 +++++++---------- .../clangcreateinitialdocumentpreamblejob.cpp | 23 ++++-------- .../clangbackend/ipcsource/clangdocumentjob.h | 21 +++++++++++ .../ipcsource/clangfollowsymboljob.cpp | 37 +++++++------------ ...clangparsesupportivetranslationunitjob.cpp | 23 ++++-------- ...angreparsesupportivetranslationunitjob.cpp | 23 ++++-------- .../clangrequestdocumentannotationsjob.cpp | 20 +++------- .../ipcsource/clangrequestreferencesjob.cpp | 24 ++++-------- .../ipcsource/clangsuspenddocumentjob.cpp | 20 +++------- .../clangupdatedocumentannotationsjob.cpp | 22 ++++------- 10 files changed, 96 insertions(+), 150 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp b/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp index 2b767604121..433923b3387 100644 --- a/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp +++ b/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp @@ -57,28 +57,21 @@ IAsyncJob::AsyncPrepareResult CompleteCodeJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::CompleteCode, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); + const TranslationUnit translationUnit = *m_translationUnit; + const UnsavedFiles unsavedFiles = *context().unsavedFiles; + const quint32 line = jobRequest.line; + const quint32 column = jobRequest.column; + const qint32 funcNameStartLine = jobRequest.funcNameStartLine; + const qint32 funcNameStartColumn = jobRequest.funcNameStartColumn; + setRunner([translationUnit, unsavedFiles, line, column, + funcNameStartLine, funcNameStartColumn]() { + return runAsyncHelper(translationUnit, unsavedFiles, line, column, + funcNameStartLine, funcNameStartColumn); + }); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - const UnsavedFiles unsavedFiles = *context().unsavedFiles; - const quint32 line = jobRequest.line; - const quint32 column = jobRequest.column; - const qint32 funcNameStartLine = jobRequest.funcNameStartLine; - const qint32 funcNameStartColumn = jobRequest.funcNameStartColumn; - setRunner([translationUnit, unsavedFiles, line, column, - funcNameStartLine, funcNameStartColumn]() { - return runAsyncHelper(translationUnit, unsavedFiles, line, column, - funcNameStartLine, funcNameStartColumn); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in CompleteCodeJob::prepareAsyncRun:" << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void CompleteCodeJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp b/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp index 62ae318f61d..2d623e25187 100644 --- a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp +++ b/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp @@ -43,24 +43,15 @@ IAsyncJob::AsyncPrepareResult CreateInitialDocumentPreambleJob::prepareAsyncRun( { const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::CreateInitialDocumentPreamble, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + const TranslationUnit translationUnit = *m_translationUnit; + const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); + setRunner([translationUnit, updateInput]() { + return runAsyncHelper(translationUnit, updateInput); + }); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); - setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in CreateInitialDocumentPreambleJob::prepareAsyncRun:" - << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void CreateInitialDocumentPreambleJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangdocumentjob.h b/src/tools/clangbackend/ipcsource/clangdocumentjob.h index caa2eb6f0f5..7808286ce0b 100644 --- a/src/tools/clangbackend/ipcsource/clangdocumentjob.h +++ b/src/tools/clangbackend/ipcsource/clangdocumentjob.h @@ -30,14 +30,35 @@ #include +#include + namespace ClangBackEnd { template class DocumentJob : public AsyncJob { +protected: + bool acquireDocument() + { + try { + m_pinnedDocument = IAsyncJob::context().documentForJobRequest(); + m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + + const PreferredTranslationUnit preferredTranslationUnit + = IAsyncJob::context().jobRequest.preferredTranslationUnit; + m_translationUnit.reset( + new TranslationUnit(m_pinnedDocument.translationUnit(preferredTranslationUnit))); + return true; + } catch (const std::exception &) { + return false; + } + } + protected: Document m_pinnedDocument; FileContainer m_pinnedFileContainer; + + std::unique_ptr m_translationUnit; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp index 2a04be1b0e7..c93b83d6480 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp +++ b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp @@ -51,32 +51,23 @@ IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun() return AsyncPrepareResult()); // Is too slow because of IPC timings, no implementation for now QTC_ASSERT(jobRequest.resolveTarget, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + const TranslationUnit translationUnit = *m_translationUnit; + const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); + const CommandLineArguments currentArgs(updateInput.filePath.constData(), + updateInput.projectArguments, + updateInput.fileArguments, + false); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); + const quint32 line = jobRequest.line; + const quint32 column = jobRequest.column; + const QVector &dependentFiles = jobRequest.dependentFiles; + setRunner([translationUnit, line, column, dependentFiles, currentArgs]() { + return runAsyncHelperFollow(translationUnit, line, column, dependentFiles, currentArgs); + }); - const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); - const CommandLineArguments currentArgs(updateInput.filePath.constData(), - updateInput.projectArguments, - updateInput.fileArguments, - false); - - const quint32 line = jobRequest.line; - const quint32 column = jobRequest.column; - const QVector &dependentFiles = jobRequest.dependentFiles; - setRunner([translationUnit, line, column, dependentFiles, currentArgs]() { - return runAsyncHelperFollow(translationUnit, line, column, dependentFiles, currentArgs); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in FollowSymbolJob::prepareAsyncRun:" << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void FollowSymbolJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp index c7646f5834b..02cf524da49 100644 --- a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp @@ -50,24 +50,15 @@ IAsyncJob::AsyncPrepareResult ParseSupportiveTranslationUnitJob::prepareAsyncRun { const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::ParseSupportiveTranslationUnit, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + const TranslationUnit translationUnit = *m_translationUnit; + const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); + setRunner([translationUnit, updateInput]() { + return runAsyncHelper(translationUnit, updateInput); + }); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); - setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in ParseForSupportiveTranslationUnitJob::prepareAsyncRun:" - << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void ParseSupportiveTranslationUnitJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp index 833b8fe2b9d..680693514b9 100644 --- a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp @@ -50,24 +50,15 @@ IAsyncJob::AsyncPrepareResult ReparseSupportiveTranslationUnitJob::prepareAsyncR { const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::ReparseSupportiveTranslationUnit, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + const TranslationUnit translationUnit = *m_translationUnit; + const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); + setRunner([translationUnit, updateInput]() { + return runAsyncHelper(translationUnit, updateInput); + }); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); - setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in ReparseSupportiveTranslationUnitJob::prepareAsyncRun:" - << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void ReparseSupportiveTranslationUnitJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp index f0f7f78210c..6f8e3eecb3f 100644 --- a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp @@ -53,22 +53,14 @@ IAsyncJob::AsyncPrepareResult RequestDocumentAnnotationsJob::prepareAsyncRun() const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestDocumentAnnotations, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + const TranslationUnit translationUnit = *m_translationUnit; + setRunner([translationUnit]() { + return runAsyncHelper(translationUnit); + }); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - setRunner([translationUnit]() { - return runAsyncHelper(translationUnit); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in RequestDocumentAnnotationsJob::prepareAsyncRun:" << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void RequestDocumentAnnotationsJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp b/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp index 1ebc22c9713..b7e60aa19db 100644 --- a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp @@ -47,24 +47,16 @@ IAsyncJob::AsyncPrepareResult RequestReferencesJob::prepareAsyncRun() const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestReferences, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + const TranslationUnit translationUnit = *m_translationUnit; + const quint32 line = jobRequest.line; + const quint32 column = jobRequest.column; + setRunner([translationUnit, line, column]() { + return runAsyncHelper(translationUnit, line, column); + }); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - const quint32 line = jobRequest.line; - const quint32 column = jobRequest.column; - setRunner([translationUnit, line, column]() { - return runAsyncHelper(translationUnit, line, column); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in RequestReferencesJob::prepareAsyncRun:" << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void RequestReferencesJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp b/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp index 0e71813ba20..27b204cc77f 100644 --- a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp @@ -42,22 +42,14 @@ IAsyncJob::AsyncPrepareResult SuspendDocumentJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::SuspendDocument, return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + TranslationUnit translationUnit = *m_translationUnit; + setRunner([translationUnit]() { + return runAsyncHelper(translationUnit); + }); - TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - setRunner([translationUnit]() { - return runAsyncHelper(translationUnit); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in SuspendDocumentJob::prepareAsyncRun:" << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void SuspendDocumentJob::finalizeAsyncRun() diff --git a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp index 3698d1c40c8..835377f73ac 100644 --- a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp @@ -57,23 +57,15 @@ IAsyncJob::AsyncPrepareResult UpdateDocumentAnnotationsJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(isExpectedJobRequestType(jobRequest), return AsyncPrepareResult()); + QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); - try { - m_pinnedDocument = context().documentForJobRequest(); - m_pinnedFileContainer = m_pinnedDocument.fileContainer(); + const TranslationUnit translationUnit = *m_translationUnit; + const TranslationUnitUpdateInput updateInput = createUpdateInput(m_pinnedDocument); + setRunner([translationUnit, updateInput]() { + return runAsyncHelper(translationUnit, updateInput); + }); - const TranslationUnit translationUnit - = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit); - const TranslationUnitUpdateInput updateInput = createUpdateInput(m_pinnedDocument); - setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); - }); - return AsyncPrepareResult{translationUnit.id()}; - - } catch (const std::exception &exception) { - qWarning() << "Error in UpdateDocumentAnnotationsJob::prepareAsyncRun:" << exception.what(); - return AsyncPrepareResult(); - } + return AsyncPrepareResult{translationUnit.id()}; } void UpdateDocumentAnnotationsJob::finalizeAsyncRun() From 2f5e1e6cec345b0be756be841acac48eb154a15b Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 21 Sep 2017 15:33:05 +0200 Subject: [PATCH 50/63] Clang: Inline functions and structures in job classes Change-Id: I0c6af378c35d768de535546ab07aac546780e954 Reviewed-by: Tim Jenssen --- .../ipcsource/clangcompletecodejob.cpp | 34 ++++------- .../clangcreateinitialdocumentpreamblejob.cpp | 11 +--- .../ipcsource/clangfollowsymboljob.cpp | 14 +---- ...clangparsesupportivetranslationunitjob.cpp | 22 ++----- .../clangparsesupportivetranslationunitjob.h | 10 +--- ...angreparsesupportivetranslationunitjob.cpp | 25 +++----- .../clangrequestdocumentannotationsjob.cpp | 43 +++++--------- .../clangrequestdocumentannotationsjob.h | 3 - .../ipcsource/clangrequestreferencesjob.cpp | 12 +--- .../ipcsource/clangsuspenddocumentjob.cpp | 10 +--- .../clangupdatedocumentannotationsjob.cpp | 59 +++++++------------ .../clangupdatedocumentannotationsjob.h | 4 -- 12 files changed, 72 insertions(+), 175 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp b/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp index 433923b3387..9970d59269b 100644 --- a/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp +++ b/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp @@ -33,26 +33,6 @@ namespace ClangBackEnd { -static CompleteCodeJob::AsyncResult runAsyncHelper(const TranslationUnit &translationUnit, - UnsavedFiles unsavedFiles, - quint32 line, - quint32 column, - qint32 funcNameStartLine, - qint32 funcNameStartColumn) -{ - TIME_SCOPE_DURATION("CompleteCodeJobRunner"); - - const TranslationUnit::CodeCompletionResult results - = translationUnit.complete(unsavedFiles, line, column, - funcNameStartLine, funcNameStartColumn); - - CompleteCodeJob::AsyncResult asyncResult; - asyncResult.completions = results.completions; - asyncResult.correction = results.correction; - - return asyncResult; -} - IAsyncJob::AsyncPrepareResult CompleteCodeJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -67,8 +47,18 @@ IAsyncJob::AsyncPrepareResult CompleteCodeJob::prepareAsyncRun() const qint32 funcNameStartColumn = jobRequest.funcNameStartColumn; setRunner([translationUnit, unsavedFiles, line, column, funcNameStartLine, funcNameStartColumn]() { - return runAsyncHelper(translationUnit, unsavedFiles, line, column, - funcNameStartLine, funcNameStartColumn); + TIME_SCOPE_DURATION("CompleteCodeJobRunner"); + + UnsavedFiles theUnsavedFiles = unsavedFiles; + const TranslationUnit::CodeCompletionResult results + = translationUnit.complete(theUnsavedFiles, line, column, + funcNameStartLine, funcNameStartColumn); + + CompleteCodeJob::AsyncResult asyncResult; + asyncResult.completions = results.completions; + asyncResult.correction = results.correction; + + return asyncResult; }); return AsyncPrepareResult{translationUnit.id()}; diff --git a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp b/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp index 2d623e25187..b60a5ca613f 100644 --- a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp +++ b/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp @@ -31,14 +31,6 @@ namespace ClangBackEnd { -static void runAsyncHelper(const TranslationUnit &translationUnit, - const TranslationUnitUpdateInput &translationUnitUpdateInput) -{ - TIME_SCOPE_DURATION("CreateInitialDocumentPreambleJobRunner"); - - translationUnit.reparse(translationUnitUpdateInput); -} - IAsyncJob::AsyncPrepareResult CreateInitialDocumentPreambleJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -48,7 +40,8 @@ IAsyncJob::AsyncPrepareResult CreateInitialDocumentPreambleJob::prepareAsyncRun( const TranslationUnit translationUnit = *m_translationUnit; const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); + TIME_SCOPE_DURATION("CreateInitialDocumentPreambleJobRunner"); + return translationUnit.reparse(updateInput); }); return AsyncPrepareResult{translationUnit.id()}; diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp index c93b83d6480..83f67158756 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp +++ b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp @@ -33,17 +33,6 @@ namespace ClangBackEnd { -static FollowSymbolJob::AsyncResult runAsyncHelperFollow(const TranslationUnit &translationUnit, - quint32 line, - quint32 column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) -{ - TIME_SCOPE_DURATION("FollowSymbolJobRunner"); - - return translationUnit.followSymbol(line, column, dependentFiles, currentArgs); -} - IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -64,7 +53,8 @@ IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun() const quint32 column = jobRequest.column; const QVector &dependentFiles = jobRequest.dependentFiles; setRunner([translationUnit, line, column, dependentFiles, currentArgs]() { - return runAsyncHelperFollow(translationUnit, line, column, dependentFiles, currentArgs); + TIME_SCOPE_DURATION("FollowSymbolJobRunner"); + return translationUnit.followSymbol(line, column, dependentFiles, currentArgs); }); return AsyncPrepareResult{translationUnit.id()}; diff --git a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp index 02cf524da49..017426ab021 100644 --- a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp @@ -31,21 +31,6 @@ namespace ClangBackEnd { -static ParseSupportiveTranslationUnitJob::AsyncResult runAsyncHelper( - const TranslationUnit &translationUnit, - const TranslationUnitUpdateInput &translationUnitUpdateInput) -{ - TIME_SCOPE_DURATION("ParseSupportiveTranslationUnitJob"); - - TranslationUnitUpdateInput updateInput = translationUnitUpdateInput; - updateInput.parseNeeded = true; - - ParseSupportiveTranslationUnitJob::AsyncResult asyncResult; - asyncResult.updateResult = translationUnit.update(updateInput); - - return asyncResult; -} - IAsyncJob::AsyncPrepareResult ParseSupportiveTranslationUnitJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -55,7 +40,12 @@ IAsyncJob::AsyncPrepareResult ParseSupportiveTranslationUnitJob::prepareAsyncRun const TranslationUnit translationUnit = *m_translationUnit; const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); + TIME_SCOPE_DURATION("ParseSupportiveTranslationUnitJob"); + + TranslationUnitUpdateInput theUpdateInput = updateInput; + theUpdateInput.parseNeeded = true; + + return translationUnit.update(updateInput); }); return AsyncPrepareResult{translationUnit.id()}; diff --git a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h index b733dc72b74..5a0cfec1837 100644 --- a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h +++ b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h @@ -26,18 +26,14 @@ #pragma once #include "clangdocumentjob.h" +#include "clangtranslationunitupdater.h" namespace ClangBackEnd { -struct ParseSupportiveTranslationUnitJobResult -{ - TranslationUnitUpdateResult updateResult; -}; - -class ParseSupportiveTranslationUnitJob : public DocumentJob +class ParseSupportiveTranslationUnitJob : public DocumentJob { public: - using AsyncResult = ParseSupportiveTranslationUnitJobResult; + using AsyncResult = TranslationUnitUpdateResult; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; diff --git a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp index 680693514b9..a02821fff48 100644 --- a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp @@ -31,21 +31,6 @@ namespace ClangBackEnd { -static ReparseSupportiveTranslationUnitJob::AsyncResult runAsyncHelper( - const TranslationUnit &translationUnit, - const TranslationUnitUpdateInput &translationUnitUpdateInput) -{ - TIME_SCOPE_DURATION("ReparseSupportiveTranslationUnitJob"); - - TranslationUnitUpdateInput updateInput = translationUnitUpdateInput; - updateInput.reparseNeeded = true; - - ReparseSupportiveTranslationUnitJob::AsyncResult asyncResult; - asyncResult.updateResult = translationUnit.reparse(updateInput); - - return asyncResult; -} - IAsyncJob::AsyncPrepareResult ReparseSupportiveTranslationUnitJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -55,7 +40,15 @@ IAsyncJob::AsyncPrepareResult ReparseSupportiveTranslationUnitJob::prepareAsyncR const TranslationUnit translationUnit = *m_translationUnit; const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput(); setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); + TIME_SCOPE_DURATION("ReparseSupportiveTranslationUnitJob"); + + TranslationUnitUpdateInput theUpdateInput = updateInput; + theUpdateInput.reparseNeeded = true; + + ReparseSupportiveTranslationUnitJob::AsyncResult asyncResult; + asyncResult.updateResult = translationUnit.reparse(theUpdateInput); + + return asyncResult; }); return AsyncPrepareResult{translationUnit.id()}; diff --git a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp index 6f8e3eecb3f..99ac98eec2a 100644 --- a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp @@ -33,21 +33,6 @@ namespace ClangBackEnd { -static RequestDocumentAnnotationsJob::AsyncResult runAsyncHelper( - const TranslationUnit &translationUnit) -{ - TIME_SCOPE_DURATION("RequestDocumentAnnotationsJobRunner"); - - RequestDocumentAnnotationsJob::AsyncResult asyncResult; - - translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic, - asyncResult.diagnostics, - asyncResult.highlightingMarks, - asyncResult.skippedSourceRanges); - - return asyncResult; -} - IAsyncJob::AsyncPrepareResult RequestDocumentAnnotationsJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -57,7 +42,14 @@ IAsyncJob::AsyncPrepareResult RequestDocumentAnnotationsJob::prepareAsyncRun() const TranslationUnit translationUnit = *m_translationUnit; setRunner([translationUnit]() { - return runAsyncHelper(translationUnit); + TIME_SCOPE_DURATION("RequestDocumentAnnotationsJobRunner"); + + RequestDocumentAnnotationsJob::AsyncResult asyncResult; + translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic, + asyncResult.diagnostics, + asyncResult.highlightingMarks, + asyncResult.skippedSourceRanges); + return asyncResult; }); return AsyncPrepareResult{translationUnit.id()}; @@ -67,20 +59,13 @@ void RequestDocumentAnnotationsJob::finalizeAsyncRun() { if (context().isDocumentOpen()) { const AsyncResult result = asyncResult(); - sendAnnotations(result); + context().client->documentAnnotationsChanged( + DocumentAnnotationsChangedMessage(m_pinnedFileContainer, + result.diagnostics, + result.firstHeaderErrorDiagnostic, + result.highlightingMarks, + result.skippedSourceRanges)); } } -void RequestDocumentAnnotationsJob::sendAnnotations( - const RequestDocumentAnnotationsJob::AsyncResult &result) -{ - const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer, - result.diagnostics, - result.firstHeaderErrorDiagnostic, - result.highlightingMarks, - result.skippedSourceRanges); - - context().client->documentAnnotationsChanged(message); -} - } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h index d3d88a03df4..1c78621119e 100644 --- a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h +++ b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h @@ -48,9 +48,6 @@ public: AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; - -private: - void sendAnnotations(const AsyncResult &result); }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp b/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp index b7e60aa19db..39b3319488e 100644 --- a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp @@ -33,15 +33,6 @@ namespace ClangBackEnd { -static RequestReferencesJob::AsyncResult runAsyncHelper(const TranslationUnit &translationUnit, - quint32 line, - quint32 column) -{ - TIME_SCOPE_DURATION("RequestReferencesJobRunner"); - - return translationUnit.references(line, column); -} - IAsyncJob::AsyncPrepareResult RequestReferencesJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -53,7 +44,8 @@ IAsyncJob::AsyncPrepareResult RequestReferencesJob::prepareAsyncRun() const quint32 line = jobRequest.line; const quint32 column = jobRequest.column; setRunner([translationUnit, line, column]() { - return runAsyncHelper(translationUnit, line, column); + TIME_SCOPE_DURATION("RequestReferencesJobRunner"); + return translationUnit.references(line, column); }); return AsyncPrepareResult{translationUnit.id()}; diff --git a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp b/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp index 27b204cc77f..87fe54bfae9 100644 --- a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp @@ -31,13 +31,6 @@ namespace ClangBackEnd { -static bool runAsyncHelper(const TranslationUnit &translationUnit) -{ - TIME_SCOPE_DURATION("SuspendDocumentJobRunner"); - - return translationUnit.suspend(); -} - IAsyncJob::AsyncPrepareResult SuspendDocumentJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -46,7 +39,8 @@ IAsyncJob::AsyncPrepareResult SuspendDocumentJob::prepareAsyncRun() TranslationUnit translationUnit = *m_translationUnit; setRunner([translationUnit]() { - return runAsyncHelper(translationUnit); + TIME_SCOPE_DURATION("SuspendDocumentJobRunner"); + return translationUnit.suspend(); }); return AsyncPrepareResult{translationUnit.id()}; diff --git a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp index 835377f73ac..7333ca68787 100644 --- a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp +++ b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp @@ -33,26 +33,6 @@ namespace ClangBackEnd { -static UpdateDocumentAnnotationsJob::AsyncResult runAsyncHelper( - const TranslationUnit &translationUnit, - const TranslationUnitUpdateInput &translationUnitUpdatInput) -{ - TIME_SCOPE_DURATION("UpdateDocumentAnnotationsJobRunner"); - - UpdateDocumentAnnotationsJob::AsyncResult asyncResult; - - // Update - asyncResult.updateResult = translationUnit.update(translationUnitUpdatInput); - - // Collect - translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic, - asyncResult.diagnostics, - asyncResult.highlightingMarks, - asyncResult.skippedSourceRanges); - - return asyncResult; -} - IAsyncJob::AsyncPrepareResult UpdateDocumentAnnotationsJob::prepareAsyncRun() { const JobRequest jobRequest = context().jobRequest; @@ -62,7 +42,19 @@ IAsyncJob::AsyncPrepareResult UpdateDocumentAnnotationsJob::prepareAsyncRun() const TranslationUnit translationUnit = *m_translationUnit; const TranslationUnitUpdateInput updateInput = createUpdateInput(m_pinnedDocument); setRunner([translationUnit, updateInput]() { - return runAsyncHelper(translationUnit, updateInput); + TIME_SCOPE_DURATION("UpdateDocumentAnnotationsJobRunner"); + + // Update + UpdateDocumentAnnotationsJob::AsyncResult asyncResult; + asyncResult.updateResult = translationUnit.update(updateInput); + + // Collect + translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic, + asyncResult.diagnostics, + asyncResult.highlightingMarks, + asyncResult.skippedSourceRanges); + + return asyncResult; }); return AsyncPrepareResult{translationUnit.id()}; @@ -73,8 +65,13 @@ void UpdateDocumentAnnotationsJob::finalizeAsyncRun() if (!context().isOutdated()) { const AsyncResult result = asyncResult(); - incorporateUpdaterResult(result); - sendAnnotations(result); + m_pinnedDocument.incorporateUpdaterResult(result.updateResult); + context().client->documentAnnotationsChanged( + DocumentAnnotationsChangedMessage(m_pinnedFileContainer, + result.diagnostics, + result.firstHeaderErrorDiagnostic, + result.highlightingMarks, + result.skippedSourceRanges)); } } @@ -89,21 +86,5 @@ UpdateDocumentAnnotationsJob::createUpdateInput(const Document &document) const return document.createUpdateInput(); } -void UpdateDocumentAnnotationsJob::incorporateUpdaterResult(const AsyncResult &result) -{ - m_pinnedDocument.incorporateUpdaterResult(result.updateResult); -} - -void UpdateDocumentAnnotationsJob::sendAnnotations(const AsyncResult &result) -{ - const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer, - result.diagnostics, - result.firstHeaderErrorDiagnostic, - result.highlightingMarks, - result.skippedSourceRanges); - - context().client->documentAnnotationsChanged(message); -} - } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h index b7f56318f05..141b3535a09 100644 --- a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h +++ b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h @@ -54,10 +54,6 @@ public: protected: virtual bool isExpectedJobRequestType(const JobRequest &jobRequest) const; virtual TranslationUnitUpdateInput createUpdateInput(const Document &document) const; - -private: - void incorporateUpdaterResult(const AsyncResult &result); - void sendAnnotations(const AsyncResult &result); }; } // namespace ClangBackEnd From c73793414b1bc8901413862972db8ced1ccb9151 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 22 Sep 2017 10:41:22 +0200 Subject: [PATCH 51/63] Clang: Replace override with final in AsyncJob Change-Id: Ie3e2acf4ee81154e9e6d7c785bd773879f9eda38 Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen --- src/tools/clangbackend/ipcsource/clangasyncjob.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangasyncjob.h b/src/tools/clangbackend/ipcsource/clangasyncjob.h index c8a7b799473..58b6a1f8455 100644 --- a/src/tools/clangbackend/ipcsource/clangasyncjob.h +++ b/src/tools/clangbackend/ipcsource/clangasyncjob.h @@ -47,7 +47,7 @@ public: Result asyncResult() const { return m_futureWatcher.future().result(); } - QFuture runAsync() override + QFuture runAsync() final { const auto onFinished = [this]() { finalizeAsyncRun(); @@ -64,7 +64,7 @@ public: return future; } - void preventFinalization() override + void preventFinalization() final { m_futureWatcher.disconnect(); } From f130de2400b8fa6bc98110b721e12e9e02a5fc09 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 8 Sep 2017 09:33:35 +0200 Subject: [PATCH 52/63] Clang: use HighlightingMarks for hover with Ctrl highlighting Make this highlighting work without builtin code model but based on the HighlightingMarks that we already have from ClangCodeModel. Redundant parameters are removed by this change. Change-Id: I73b5dab46ba59d2f813236831818f0a9bc94c5bc Reviewed-by: Nikolai Kosjar --- src/libs/clangsupport/followsymbolmessage.cpp | 4 +- src/libs/clangsupport/followsymbolmessage.h | 13 +-- .../highlightingmarkcontainer.cpp | 6 +- .../clangsupport/highlightingmarkcontainer.h | 32 +++++- .../requestfollowsymbolmessage.cpp | 2 - .../clangsupport/requestfollowsymbolmessage.h | 13 +-- .../clangbackendipcintegration.cpp | 7 +- .../clangbackendipcintegration.h | 3 +- .../clangeditordocumentprocessor.cpp | 12 ++- .../clangeditordocumentprocessor.h | 7 +- .../clangcodemodel/clangfollowsymbol.cpp | 97 +++++++++++++++---- .../clanghighlightingmarksreporter.cpp | 9 +- src/plugins/cppeditor/cppeditorwidget.cpp | 9 -- .../cpptools/baseeditordocumentprocessor.h | 2 +- .../cpptools/builtineditordocumentprocessor.h | 2 +- src/plugins/cpptools/cppsymbolinfo.h | 1 - .../ipcsource/clangcodemodelserver.cpp | 1 - .../ipcsource/clangfollowsymbol.cpp | 93 +++++++++--------- .../ipcsource/clangfollowsymbol.h | 15 +-- .../ipcsource/clangfollowsymboljob.cpp | 5 +- .../ipcsource/clangfollowsymboljob.h | 23 +---- .../ipcsource/clangjobrequest.cpp | 1 - .../clangbackend/ipcsource/clangjobrequest.h | 1 - .../ipcsource/clangtranslationunit.cpp | 12 +-- .../ipcsource/clangtranslationunit.h | 9 +- .../ipcsource/highlightingmark.cpp | 8 +- .../clangbackend/ipcsource/highlightingmark.h | 2 + .../ipcsource/highlightingmarks.cpp | 9 +- .../unit/unittest/clangfollowsymbol-test.cpp | 19 +--- .../unit/unittest/highlightingmarks-test.cpp | 36 +++++++ .../readandwritemessageblock-test.cpp | 3 +- 31 files changed, 265 insertions(+), 191 deletions(-) diff --git a/src/libs/clangsupport/followsymbolmessage.cpp b/src/libs/clangsupport/followsymbolmessage.cpp index 929199bef5b..cafd22aa4bc 100644 --- a/src/libs/clangsupport/followsymbolmessage.cpp +++ b/src/libs/clangsupport/followsymbolmessage.cpp @@ -36,8 +36,7 @@ QDebug operator<<(QDebug debug, const FollowSymbolMessage &message) debug.nospace() << "FollowSymbolMessage(" << message.m_fileContainer << ", " << message.m_ticketNumber - << ", " << message.m_sourceRange - << ", " << message.m_failedToFollow; + << ", " << message.m_sourceRange; debug.nospace() << ")"; @@ -50,7 +49,6 @@ std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message) << message.m_fileContainer << ", " << message.m_ticketNumber << ", " << message.m_sourceRange << ", " - << message.m_failedToFollow << ", " << ")"; return os; diff --git a/src/libs/clangsupport/followsymbolmessage.h b/src/libs/clangsupport/followsymbolmessage.h index ad8f7348f39..3893a6e49c3 100644 --- a/src/libs/clangsupport/followsymbolmessage.h +++ b/src/libs/clangsupport/followsymbolmessage.h @@ -39,12 +39,10 @@ public: FollowSymbolMessage() = default; FollowSymbolMessage(const FileContainer &fileContainer, const SourceRangeContainer &range, - bool failedToFollow, quint64 ticketNumber) : m_fileContainer(fileContainer) , m_sourceRange(range) , m_ticketNumber(ticketNumber) - , m_failedToFollow(failedToFollow) { } const FileContainer &fileContainer() const @@ -57,11 +55,6 @@ public: return m_sourceRange; } - bool failedToFollow() const - { - return m_failedToFollow; - } - quint64 ticketNumber() const { return m_ticketNumber; @@ -72,7 +65,6 @@ public: out << message.m_fileContainer; out << message.m_sourceRange; out << message.m_ticketNumber; - out << message.m_failedToFollow; return out; } @@ -81,7 +73,6 @@ public: in >> message.m_fileContainer; in >> message.m_sourceRange; in >> message.m_ticketNumber; - in >> message.m_failedToFollow; return in; } @@ -89,8 +80,7 @@ public: { return first.m_ticketNumber == second.m_ticketNumber && first.m_fileContainer == second.m_fileContainer - && first.m_sourceRange == second.m_sourceRange - && first.m_failedToFollow == second.m_failedToFollow; + && first.m_sourceRange == second.m_sourceRange; } friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message); @@ -99,7 +89,6 @@ private: FileContainer m_fileContainer; SourceRangeContainer m_sourceRange; quint64 m_ticketNumber = 0; - bool m_failedToFollow = false; }; DECLARE_MESSAGE(FollowSymbolMessage); diff --git a/src/libs/clangsupport/highlightingmarkcontainer.cpp b/src/libs/clangsupport/highlightingmarkcontainer.cpp index ab679c8d890..ec460a14a6f 100644 --- a/src/libs/clangsupport/highlightingmarkcontainer.cpp +++ b/src/libs/clangsupport/highlightingmarkcontainer.cpp @@ -65,6 +65,8 @@ QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container) << container.column() << ", " << container.length() << ", " << highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", " + << container.isIdentifier() << ", " + << container.isIncludeDirectivePath() << ")"; return debug; @@ -94,7 +96,9 @@ std::ostream &operator<<(std::ostream &os, const HighlightingMarkContainer &cont << container.line() << ", " << container.column() << ", " << container.length() << ", " - << container.types() + << container.types() << ", " + << container.isIdentifier() << ", " + << container.isIncludeDirectivePath() << ")"; return os; diff --git a/src/libs/clangsupport/highlightingmarkcontainer.h b/src/libs/clangsupport/highlightingmarkcontainer.h index 0bc3ab0b555..8b6e585e501 100644 --- a/src/libs/clangsupport/highlightingmarkcontainer.h +++ b/src/libs/clangsupport/highlightingmarkcontainer.h @@ -44,11 +44,14 @@ class HighlightingMarkContainer { public: HighlightingMarkContainer() = default; - HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types) + HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types, + bool isIdentifier = false, bool isIncludeDirectivePath = false) : line_(line), column_(column), length_(length), - types_(types) + types_(types), + isIdentifier_(isIdentifier), + isIncludeDirectivePath_(isIncludeDirectivePath) { } @@ -80,12 +83,29 @@ public: return types_; } + bool isInvalid() const + { + return line_ == 0 && column_ == 0 && length_ == 0; + } + + bool isIdentifier() const + { + return isIdentifier_; + } + + bool isIncludeDirectivePath() const + { + return isIncludeDirectivePath_; + } + friend QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container) { out << container.line_; out << container.column_; out << container.length_; out << container.types_; + out << container.isIdentifier_; + out << container.isIncludeDirectivePath_; return out; } @@ -96,6 +116,8 @@ public: in >> container.column_; in >> container.length_; in >> container.types_; + in >> container.isIdentifier_; + in >> container.isIncludeDirectivePath_; return in; } @@ -105,7 +127,9 @@ public: return first.line_ == second.line_ && first.column_ == second.column_ && first.length_ == second.length_ - && first.types_ == second.types_; + && first.types_ == second.types_ + && first.isIdentifier_ == second.isIdentifier_ + && first.isIncludeDirectivePath_ == second.isIncludeDirectivePath_; } private: @@ -113,6 +137,8 @@ private: uint column_ = 0; uint length_ = 0; HighlightingTypes types_; + bool isIdentifier_ = false; + bool isIncludeDirectivePath_ = false; }; inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType) diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.cpp b/src/libs/clangsupport/requestfollowsymbolmessage.cpp index 9d31139840a..dcb0b5cd2ef 100644 --- a/src/libs/clangsupport/requestfollowsymbolmessage.cpp +++ b/src/libs/clangsupport/requestfollowsymbolmessage.cpp @@ -42,7 +42,6 @@ QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message) debug.nospace() << message.m_ticketNumber << ", "; debug.nospace() << message.m_line << ", "; debug.nospace() << message.m_column << ", "; - debug.nospace() << message.m_resolveTarget << ", "; debug.nospace() << ")"; @@ -57,7 +56,6 @@ std::ostream &operator<<(std::ostream &os, const RequestFollowSymbolMessage &mes << message.m_ticketNumber << ", " << message.m_line << ", " << message.m_column << ", " - << message.m_resolveTarget << ", " << ")"; return os; diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.h b/src/libs/clangsupport/requestfollowsymbolmessage.h index a9c37e101a5..1305abfba81 100644 --- a/src/libs/clangsupport/requestfollowsymbolmessage.h +++ b/src/libs/clangsupport/requestfollowsymbolmessage.h @@ -40,14 +40,12 @@ public: RequestFollowSymbolMessage(const FileContainer &fileContainer, const QVector &dependentFiles, quint32 line, - quint32 column, - bool resolveTarget = true) + quint32 column) : m_fileContainer(fileContainer) , m_ticketNumber(++ticketCounter) , m_line(line) , m_column(column) , m_dependentFiles(dependentFiles) - , m_resolveTarget(resolveTarget) { } @@ -71,11 +69,6 @@ public: return m_column; } - bool resolveTarget() const - { - return m_resolveTarget; - } - quint64 ticketNumber() const { return m_ticketNumber; @@ -88,7 +81,6 @@ public: out << message.m_ticketNumber; out << message.m_line; out << message.m_column; - out << message.m_resolveTarget; return out; } @@ -100,7 +92,6 @@ public: in >> message.m_ticketNumber; in >> message.m_line; in >> message.m_column; - in >> message.m_resolveTarget; return in; } @@ -112,7 +103,6 @@ public: && first.m_line == second.m_line && first.m_column == second.m_column && first.m_fileContainer == second.m_fileContainer - && first.m_resolveTarget == second.m_resolveTarget && first.m_dependentFiles == second.m_dependentFiles; } @@ -124,7 +114,6 @@ private: quint32 m_line = 0; quint32 m_column = 0; QVector m_dependentFiles; - bool m_resolveTarget = true; static CMBIPC_EXPORT quint64 ticketCounter; }; diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 065ea0fe4b3..ff1cf8f0750 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -275,7 +275,6 @@ CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message) result.endLine = static_cast(end.line()); result.endColumn = static_cast(end.column()); result.fileName = start.filePath(); - result.failedToFollow = message.failedToFollow(); return result; } @@ -748,14 +747,12 @@ QFuture IpcCommunicator::requestFollowSymbol( const FileContainer &curFileContainer, const QVector &dependentFiles, quint32 line, - quint32 column, - bool resolveTarget) + quint32 column) { const RequestFollowSymbolMessage message(curFileContainer, dependentFiles, line, - column, - resolveTarget); + column); m_ipcSender->requestFollowSymbol(message); return m_ipcReceiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber()); diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index 94be668114e..63c9d768017 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -169,8 +169,7 @@ public: QFuture requestFollowSymbol(const FileContainer &curFileContainer, const QVector &dependentFiles, quint32 line, - quint32 column, - bool resolveTarget); + quint32 column); void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath, quint32 line, quint32 column, diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 593d3cb9c72..24d26adcfde 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -225,6 +225,12 @@ toTextEditorBlocks(QTextDocument *textDocument, } } +const QVector +&ClangEditorDocumentProcessor::highlightingMarks() const +{ + return m_highlightingMarks; +} + void ClangEditorDocumentProcessor::updateHighlighting( const QVector &highlightingMarks, const QVector &skippedPreprocessorRanges, @@ -234,6 +240,7 @@ void ClangEditorDocumentProcessor::updateHighlighting( const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges); emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks); + m_highlightingMarks = highlightingMarks; m_semanticHighlighter.setHighlightingRunner( [highlightingMarks]() { auto *reporter = new HighlightingMarksReporter(highlightingMarks); @@ -376,7 +383,7 @@ static QVector prioritizeByBaseName(const QString &curPath, } QFuture -ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool resolveTarget) +ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column) { QVector dependentFiles; CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); @@ -390,8 +397,7 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool res return m_ipcCommunicator.requestFollowSymbol(simpleFileContainer(), dependentFiles, static_cast(line), - static_cast(column), - resolveTarget); + static_cast(column)); } ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 6255608dc23..d7f7f966f50 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -86,14 +86,14 @@ public: void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override; QFuture cursorInfo(const CppTools::CursorInfoParams ¶ms) override; - QFuture requestFollowSymbol(int line, - int column, - bool resolveTarget) override; + QFuture requestFollowSymbol(int line, int column) override; ClangBackEnd::FileContainer fileContainerWithArguments() const; void clearDiagnosticsWithFixIts(); + const QVector &highlightingMarks() const; + public: static ClangEditorDocumentProcessor *get(const QString &filePath); @@ -122,6 +122,7 @@ private: QTimer m_updateTranslationUnitTimer; unsigned m_parserRevision; + QVector m_highlightingMarks; CppTools::SemanticHighlighter m_semanticHighlighter; CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor; }; diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp index ede9cac8245..bffa6fbcbfb 100644 --- a/src/plugins/clangcodemodel/clangfollowsymbol.cpp +++ b/src/plugins/clangcodemodel/clangfollowsymbol.cpp @@ -23,14 +23,78 @@ ** ****************************************************************************/ -#include "clangfollowsymbol.h" #include "clangeditordocumentprocessor.h" -#include "texteditor/texteditor.h" -#include "texteditor/convenience.h" +#include "clangfollowsymbol.h" + +#include +#include + +#include + +#include namespace ClangCodeModel { namespace Internal { +// Returns invalid Mark if it is not found at (line, column) +static bool findMark(const QVector &marks, + uint line, + uint column, + ClangBackEnd::HighlightingMarkContainer &mark) +{ + mark = Utils::findOrDefault(marks, + [line, column](const ClangBackEnd::HighlightingMarkContainer &curMark) { + if (curMark.line() != line) + return false; + if (curMark.column() == column) + return true; + if (curMark.column() < column && curMark.column() + curMark.length() >= column) + return true; + return false; + }); + if (mark.isInvalid()) + return false; + return true; +} + +static int getMarkPos(QTextCursor cursor, const ClangBackEnd::HighlightingMarkContainer &mark) +{ + cursor.setPosition(0); + cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, mark.line() - 1); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, mark.column() - 1); + return cursor.position(); +} + +static TextEditor::TextEditorWidget::Link linkAtCursor(QTextCursor cursor, + const QString &filePath, + uint line, + uint column, + ClangEditorDocumentProcessor *processor) +{ + using Link = TextEditor::TextEditorWidget::Link; + + const QVector &marks + = processor->highlightingMarks(); + ClangBackEnd::HighlightingMarkContainer mark; + if (!findMark(marks, line, column, mark)) + return Link(); + + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + const QString tokenStr = cursor.selectedText(); + + Link token(filePath, mark.line(), mark.column()); + token.linkTextStart = getMarkPos(cursor, mark); + token.linkTextEnd = token.linkTextStart + mark.length(); + if (mark.isIncludeDirectivePath()) { + if (tokenStr != "include" && tokenStr != "#" && tokenStr != "<") + return token; + return Link(); + } + if (mark.isIdentifier() || tokenStr == "operator") + return token; + return Link(); +} + TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink( const CppTools::CursorInEditor &data, bool resolveTarget, @@ -39,42 +103,39 @@ TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink( CppTools::SymbolFinder *, bool) { - Link link; - int lineNumber = 0, positionInBlock = 0; QTextCursor cursor = TextEditor::Convenience::wordStartCursor(data.cursor()); TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &lineNumber, &positionInBlock); - const unsigned line = lineNumber; - const unsigned column = positionInBlock + 1; - if (!resolveTarget) - return link; + const uint line = lineNumber; + const uint column = positionInBlock + 1; + ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get( data.filePath().toString()); if (!processor) - return link; + return Link(); + + if (!resolveTarget) + return linkAtCursor(cursor, data.filePath().toString(), line, column, processor); QFuture info = processor->requestFollowSymbol(static_cast(line), - static_cast(column), - resolveTarget); + static_cast(column)); + if (info.isCanceled()) - return link; + return Link(); while (!info.isFinished()) { if (info.isCanceled()) - return link; + return Link(); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } CppTools::SymbolInfo result = info.result(); - if (result.failedToFollow) - return link; - // We did not fail but the result is empty if (result.fileName.isEmpty()) - return link; + return Link(); return Link(result.fileName, result.startLine, result.startColumn - 1); } diff --git a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp index 6090b73f415..747070a317a 100644 --- a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp +++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp @@ -158,8 +158,15 @@ void HighlightingMarksReporter::run_internal() if (isCanceled()) return; - for (const auto &highlightingMark : m_highlightingMarks) + using ClangBackEnd::HighlightingType; + + for (const auto &highlightingMark : m_highlightingMarks) { + const HighlightingType mainType = highlightingMark.types().mainHighlightingType; + if (mainType == HighlightingType::StringLiteral) + continue; + reportChunkWise(toHighlightingResult(highlightingMark)); + } if (isCanceled()) return; diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 28f49380244..75938351712 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -649,15 +649,6 @@ CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor, return Link(); const Utils::FileName &filePath = textDocument()->filePath(); - if (!resolveTarget) { - // TODO: get that part also from clang - return d->m_builtinFollowSymbol.findLink(CppTools::CursorInEditor{cursor, filePath, this}, - resolveTarget, - d->m_modelManager->snapshot(), - d->m_lastSemanticInfo.doc, - d->m_modelManager->symbolFinder(), - inNextSplit); - } return followSymbolInterface()->findLink(CppTools::CursorInEditor{cursor, filePath, this}, resolveTarget, diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h index 342979dae35..1ac31a6ebc8 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.h +++ b/src/plugins/cpptools/baseeditordocumentprocessor.h @@ -76,7 +76,7 @@ public: virtual void setParserConfig(const BaseEditorDocumentParser::Configuration config); virtual QFuture cursorInfo(const CursorInfoParams ¶ms) = 0; - virtual QFuture requestFollowSymbol(int line, int column, bool resolveTarget) = 0; + virtual QFuture requestFollowSymbol(int line, int column) = 0; public: using HeaderErrorDiagnosticWidgetCreator = std::function; diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.h b/src/plugins/cpptools/builtineditordocumentprocessor.h index 7d3d96f992f..800bff085a6 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.h +++ b/src/plugins/cpptools/builtineditordocumentprocessor.h @@ -52,7 +52,7 @@ public: bool isParserRunning() const override; QFuture cursorInfo(const CursorInfoParams ¶ms) override; - QFuture requestFollowSymbol(int, int, bool) override + QFuture requestFollowSymbol(int, int) override { return QFuture(); } private: diff --git a/src/plugins/cpptools/cppsymbolinfo.h b/src/plugins/cpptools/cppsymbolinfo.h index 17d2713bc37..dcd00dd3c21 100644 --- a/src/plugins/cpptools/cppsymbolinfo.h +++ b/src/plugins/cpptools/cppsymbolinfo.h @@ -39,7 +39,6 @@ public: int endLine = 0; int endColumn = 0; QString fileName; - bool failedToFollow = false; }; } // namespace CppTools diff --git a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp index d3f0726aff2..9def46b2dba 100644 --- a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp @@ -281,7 +281,6 @@ void ClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::FollowSymbol); fillJobRequest(jobRequest, message); jobRequest.dependentFiles = message.dependentFiles(); - jobRequest.resolveTarget = message.resolveTarget(); processor.addJob(jobRequest); processor.process(); } catch (const std::exception &exception) { diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp b/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp index ab6bd824bb6..bc151bc93c4 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp +++ b/src/tools/clangbackend/ipcsource/clangfollowsymbol.cpp @@ -41,10 +41,16 @@ namespace { struct Tokens { + Tokens(const Tokens &) = delete; Tokens(const Cursor &cursor) { tu = cursor.cxTranslationUnit(); clang_tokenize(tu, cursor.cxSourceRange(), &data, &tokenCount); } + Tokens(const CXTranslationUnit &tu) { + const CXSourceRange range + = clang_getCursorExtent(clang_getTranslationUnitCursor(tu)); + clang_tokenize(tu, range, &data, &tokenCount); + } ~Tokens() { clang_disposeTokens(tu, data, tokenCount); } @@ -198,11 +204,11 @@ static IndexerCallbacks createIndexerCallbacks() }; } -static FollowSymbolResult followSymbolInDependentFiles(CXIndex index, - const Cursor &cursor, - const Utf8String &tokenSpelling, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) +static SourceRangeContainer followSymbolInDependentFiles(CXIndex index, + const Cursor &cursor, + const Utf8String &tokenSpelling, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) { int argsCount = 0; if (currentArgs.data()) @@ -250,63 +256,61 @@ static FollowSymbolResult followSymbolInDependentFiles(CXIndex index, for (const std::future &future: indexFutures) future.wait(); - FollowSymbolResult result; for (const FollowSymbolData &data: dataVector) { if (!data.result().start().filePath().isEmpty()) { - result.range = data.result(); - break; + return data.result(); } } - return result; + return SourceRangeContainer(); } -FollowSymbolResult FollowSymbol::followSymbol(CXIndex index, - const Cursor &fullCursor, - uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) +SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu, + CXIndex index, + const Cursor &fullCursor, + uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) { - FollowSymbolResult result; - Tokens tokens(fullCursor); - if (!tokens.tokenCount) { - result.failedToFollow = true; - return result; - } + std::unique_ptr tokens(new Tokens(fullCursor)); - const CXTranslationUnit tu = fullCursor.cxTranslationUnit(); + if (!tokens->tokenCount) + tokens.reset(new Tokens(tu)); - QVector cursors(static_cast(tokens.tokenCount)); - clang_annotateTokens(tu, tokens.data, tokens.tokenCount, cursors.data()); - int tokenIndex = getTokenIndex(tu, tokens, line, column); - QTC_ASSERT(tokenIndex >= 0, return result); + if (!tokens->tokenCount) + return SourceRangeContainer(); - const Utf8String tokenSpelling = ClangString(clang_getTokenSpelling(tu, tokens.data[tokenIndex])); + QVector cursors(static_cast(tokens->tokenCount)); + clang_annotateTokens(tu, tokens->data, tokens->tokenCount, cursors.data()); + int tokenIndex = getTokenIndex(tu, *tokens, line, column); + QTC_ASSERT(tokenIndex >= 0, return SourceRangeContainer()); + + const Utf8String tokenSpelling = ClangString( + clang_getTokenSpelling(tu, tokens->data[tokenIndex])); if (tokenSpelling.isEmpty()) - return result; + return SourceRangeContainer(); Cursor cursor{cursors[tokenIndex]}; + if (cursor.kind() == CXCursor_InclusionDirective) { CXFile file = clang_getIncludedFile(cursors[tokenIndex]); const ClangString filename(clang_getFileName(file)); const SourceLocation loc(tu, filename, 1, 1); - result.range = SourceRange(loc, loc); - return result; + return SourceRange(loc, loc); } - if (cursor.isDefinition()) { - // For definitions we can always find a declaration in current TU - result.range = extractMatchingTokenRange(cursor.canonical(), tokenSpelling); - return result; - } + // For definitions we can always find a declaration in current TU + if (cursor.isDefinition()) + return extractMatchingTokenRange(cursor.canonical(), tokenSpelling); + SourceRangeContainer result; if (!cursor.isDeclaration()) { // This is the symbol usage // We want to return definition or at least declaration of this symbol const Cursor referencedCursor = cursor.referenced(); if (referencedCursor.isNull() || referencedCursor == cursor) - return result; - result.range = extractMatchingTokenRange(referencedCursor, tokenSpelling); + return SourceRangeContainer(); + result = extractMatchingTokenRange(referencedCursor, tokenSpelling); // We've already found what we need if (referencedCursor.isDefinition()) @@ -317,17 +321,16 @@ FollowSymbolResult FollowSymbol::followSymbol(CXIndex index, const Cursor definitionCursor = cursor.definition(); if (!definitionCursor.isNull() && definitionCursor != cursor) { // If we are able to find a definition in current TU - result.range = extractMatchingTokenRange(definitionCursor, tokenSpelling); - return result; + return extractMatchingTokenRange(definitionCursor, tokenSpelling); } // Search for the definition in the dependent files - FollowSymbolResult dependentFilesResult = followSymbolInDependentFiles(index, - cursor, - tokenSpelling, - dependentFiles, - currentArgs); - return dependentFilesResult.range.start().filePath().isEmpty() ? + SourceRangeContainer dependentFilesResult = followSymbolInDependentFiles(index, + cursor, + tokenSpelling, + dependentFiles, + currentArgs); + return dependentFilesResult.start().filePath().isEmpty() ? result : dependentFilesResult; } diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymbol.h b/src/tools/clangbackend/ipcsource/clangfollowsymbol.h index c3c0c5c2092..a881bd9631d 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymbol.h +++ b/src/tools/clangbackend/ipcsource/clangfollowsymbol.h @@ -34,18 +34,19 @@ class Utf8String; namespace ClangBackEnd { class Cursor; -class FollowSymbolResult; +class SourceRangeContainer; class CommandLineArguments; class FollowSymbol { public: - static FollowSymbolResult followSymbol(CXIndex index, - const Cursor &fullCursor, - uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs); + static SourceRangeContainer followSymbol(CXTranslationUnit tu, + CXIndex index, + const Cursor &fullCursor, + uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs); }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp index 83f67158756..7136db34326 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp +++ b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.cpp @@ -38,8 +38,6 @@ IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun() const JobRequest jobRequest = context().jobRequest; QTC_ASSERT(jobRequest.type == JobRequest::Type::FollowSymbol, return AsyncPrepareResult()); - // Is too slow because of IPC timings, no implementation for now - QTC_ASSERT(jobRequest.resolveTarget, return AsyncPrepareResult()); QTC_ASSERT(acquireDocument(), return AsyncPrepareResult()); const TranslationUnit translationUnit = *m_translationUnit; @@ -66,8 +64,7 @@ void FollowSymbolJob::finalizeAsyncRun() const AsyncResult result = asyncResult(); const FollowSymbolMessage message(m_pinnedFileContainer, - result.range, - result.failedToFollow, + result, context().jobRequest.ticketNumber); context().client->followSymbol(message); } diff --git a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h index 7c8391fb9b2..3a8741db1c6 100644 --- a/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h +++ b/src/tools/clangbackend/ipcsource/clangfollowsymboljob.h @@ -31,29 +31,10 @@ namespace ClangBackEnd { -class FollowSymbolResult +class FollowSymbolJob : public DocumentJob { public: - FollowSymbolResult() = default; - FollowSymbolResult(const SourceRangeContainer &range, bool failedToFollow = false) - : range(range) - , failedToFollow(failedToFollow) - {} - - friend bool operator==(const FollowSymbolResult &first, const FollowSymbolResult &second) - { - return first.range == second.range - && first.failedToFollow == second.failedToFollow; - } - - SourceRangeContainer range; - bool failedToFollow = false; -}; - -class FollowSymbolJob : public DocumentJob -{ -public: - using AsyncResult = FollowSymbolResult; + using AsyncResult = SourceRangeContainer; AsyncPrepareResult prepareAsyncRun() override; void finalizeAsyncRun() override; diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp index 4130557ee67..9f8eb55f77f 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.cpp @@ -229,7 +229,6 @@ void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const case JobRequest::Type::FollowSymbol: client.followSymbol(FollowSymbolMessage(FileContainer(), SourceRangeContainer(), - true, ticketNumber)); break; } diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.h b/src/tools/clangbackend/ipcsource/clangjobrequest.h index a73eda7beeb..78aaed6618a 100644 --- a/src/tools/clangbackend/ipcsource/clangjobrequest.h +++ b/src/tools/clangbackend/ipcsource/clangjobrequest.h @@ -118,7 +118,6 @@ public: qint32 funcNameStartColumn = -1; quint64 ticketNumber = 0; Utf8StringVector dependentFiles; - bool resolveTarget = true; }; using JobRequests = QVector; diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp index adc732118eb..720bfb92555 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp @@ -243,13 +243,13 @@ void TranslationUnit::extractDiagnostics(DiagnosticContainer &firstHeaderErrorDi } } -FollowSymbolResult TranslationUnit::followSymbol(uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) const +SourceRangeContainer TranslationUnit::followSymbol(uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) const { - return FollowSymbol::followSymbol(m_cxIndex, cursorAt(line, column), line, column, - dependentFiles, currentArgs); + return FollowSymbol::followSymbol(m_cxTranslationUnit, m_cxIndex, cursorAt(line, column), line, + column, dependentFiles, currentArgs); } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.h b/src/tools/clangbackend/ipcsource/clangtranslationunit.h index 3ae020478ee..9634c8cb510 100644 --- a/src/tools/clangbackend/ipcsource/clangtranslationunit.h +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.h @@ -37,7 +37,6 @@ class DiagnosticSet; class HighlightingMarkContainer; class HighlightingMarks; class ReferencesResult; -class FollowSymbolResult; class SkippedSourceRanges; class SourceLocation; class SourceRange; @@ -101,10 +100,10 @@ public: HighlightingMarks highlightingMarksInRange(const SourceRange &range) const; SkippedSourceRanges skippedSourceRanges() const; - FollowSymbolResult followSymbol(uint line, - uint column, - const QVector &dependentFiles, - const CommandLineArguments ¤tArgs) const; + SourceRangeContainer followSymbol(uint line, + uint column, + const QVector &dependentFiles, + const CommandLineArguments ¤tArgs) const; private: const Utf8String m_id; diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.cpp b/src/tools/clangbackend/ipcsource/highlightingmark.cpp index 510192b6e70..9339d4ba9e7 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmark.cpp +++ b/src/tools/clangbackend/ipcsource/highlightingmark.cpp @@ -105,7 +105,8 @@ bool HighlightingMark::hasFunctionArguments() const HighlightingMark::operator HighlightingMarkContainer() const { - return HighlightingMarkContainer(m_line, m_column, m_length, m_types); + return HighlightingMarkContainer(m_line, m_column, m_length, m_types, m_isIdentifier, + m_isInclusion); } namespace { @@ -288,6 +289,8 @@ void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion) void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion) { + m_isIdentifier = (cursor.kind() != CXCursor_PreprocessingDirective); + switch (cursor.kind()) { case CXCursor_Destructor: case CXCursor_Constructor: @@ -352,6 +355,7 @@ HighlightingType literalKind(const Cursor &cursor) switch (cursor.kind()) { case CXCursor_CharacterLiteral: case CXCursor_StringLiteral: + case CXCursor_InclusionDirective: case CXCursor_ObjCStringLiteral: return HighlightingType::StringLiteral; case CXCursor_IntegerLiteral: case CXCursor_ImaginaryLiteral: @@ -438,6 +442,8 @@ void HighlightingMark::collectKinds(CXTranslationUnit cxTranslationUnit, case CXToken_Comment: m_types.mainHighlightingType = HighlightingType::Comment; break; case CXToken_Literal: m_types.mainHighlightingType = literalKind(cursor); break; } + + m_isInclusion = (cursor.kind() == CXCursor_InclusionDirective); } std::ostream &operator<<(std::ostream &os, const HighlightingMark& highlightingMark) diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.h b/src/tools/clangbackend/ipcsource/highlightingmark.h index 151bd263d25..b322391c49d 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmark.h +++ b/src/tools/clangbackend/ipcsource/highlightingmark.h @@ -87,6 +87,8 @@ private: uint m_length; uint m_offset = 0; HighlightingTypes m_types; + bool m_isIdentifier = false; + bool m_isInclusion = false; }; diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp index 2e157ff835e..ed8ddfdd656 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp +++ b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp @@ -68,15 +68,12 @@ QVector HighlightingMarks::toHighlightingMarksContain const auto isValidHighlightMark = [] (const HighlightingMark &highlightMark) { return !highlightMark.hasInvalidMainType() - && !highlightMark.hasMainType(HighlightingType::StringLiteral) - && !highlightMark.hasMainType(HighlightingType::NumberLiteral) - && !highlightMark.hasMainType(HighlightingType::Comment); + && !highlightMark.hasMainType(HighlightingType::NumberLiteral) + && !highlightMark.hasMainType(HighlightingType::Comment); }; - - for (const HighlightingMark &highlightMark : *this) { + for (const HighlightingMark &highlightMark : *this) if (isValidHighlightMark(highlightMark)) containers.push_back(highlightMark); - } return containers; } diff --git a/tests/unit/unittest/clangfollowsymbol-test.cpp b/tests/unit/unittest/clangfollowsymbol-test.cpp index 046932034f0..566c02b0e5d 100644 --- a/tests/unit/unittest/clangfollowsymbol-test.cpp +++ b/tests/unit/unittest/clangfollowsymbol-test.cpp @@ -56,20 +56,11 @@ using ::ClangBackEnd::UnsavedFiles; using ::ClangBackEnd::ReferencesResult; using ::ClangBackEnd::SourceRangeContainer; -using ClangBackEnd::FollowSymbolResult; - namespace { const Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_main.cpp"); const Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_header.h"); const Utf8String cursorPath = Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp"); -std::ostream &operator<<(std::ostream &os, const FollowSymbolResult &result) -{ - os << result.range; - - return os; -} - MATCHER_P3(MatchesHeaderSourceRange, line, column, length, std::string(negation ? "isn't " : "is ") + PrintToString(SourceRangeContainer { @@ -83,7 +74,7 @@ MATCHER_P3(MatchesHeaderSourceRange, line, column, length, SourceLocationContainer(headerFilePath, line, column + length) }; - return arg == FollowSymbolResult {expected, false}; + return arg == expected; } MATCHER_P3(MatchesSourceRange, line, column, length, @@ -99,7 +90,7 @@ MATCHER_P3(MatchesSourceRange, line, column, length, SourceLocationContainer(sourceFilePath, line, column + length) }; - return arg == FollowSymbolResult {expected, false}; + return arg == expected; } MATCHER_P4(MatchesFileSourceRange, filename, line, column, length, @@ -115,7 +106,7 @@ MATCHER_P4(MatchesFileSourceRange, filename, line, column, length, SourceLocationContainer(filename, line, column + length) }; - return arg == FollowSymbolResult {expected, false}; + return arg == expected; } class Data { @@ -150,7 +141,7 @@ private: class FollowSymbol : public ::testing::Test { protected: - FollowSymbolResult followSymbol(uint line, uint column) + SourceRangeContainer followSymbol(uint line, uint column) { ClangBackEnd::TranslationUnitUpdateInput updateInput = d->document().createUpdateInput(); const ClangBackEnd::CommandLineArguments currentArgs(updateInput.filePath.constData(), @@ -162,7 +153,7 @@ protected: currentArgs); } - FollowSymbolResult followHeaderSymbol(uint line, uint column) + SourceRangeContainer followHeaderSymbol(uint line, uint column) { ClangBackEnd::TranslationUnitUpdateInput updateInput = d->headerDocument().createUpdateInput(); diff --git a/tests/unit/unittest/highlightingmarks-test.cpp b/tests/unit/unittest/highlightingmarks-test.cpp index 16c7bc59e60..1aeeb734feb 100644 --- a/tests/unit/unittest/highlightingmarks-test.cpp +++ b/tests/unit/unittest/highlightingmarks-test.cpp @@ -1184,6 +1184,42 @@ TEST_F(HighlightingMarks, UsingTemplateFunction) ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Function)); } +TEST_F(HighlightingMarks, HeaderNameIsInclusion) +{ + const auto infos = translationUnit.highlightingMarksInRange(sourceRange(239, 31)); + ClangBackEnd::HighlightingMarkContainer container(infos[2]); + ASSERT_THAT(container.isIncludeDirectivePath(), true); +} + +TEST_F(HighlightingMarks, HeaderNameIsInclusionWithAngleBrackets) +{ + const auto infos = translationUnit.highlightingMarksInRange(sourceRange(289, 31)); + ClangBackEnd::HighlightingMarkContainer container(infos[2]); + ASSERT_THAT(container.isIncludeDirectivePath(), true); +} + + +TEST_F(HighlightingMarks, NotInclusion) +{ + const auto infos = translationUnit.highlightingMarksInRange(sourceRange(241, 13)); + ClangBackEnd::HighlightingMarkContainer container(infos[1]); + ASSERT_THAT(container.isIncludeDirectivePath(), false); +} + +TEST_F(HighlightingMarks, MacroIsIdentifier) +{ + const auto infos = translationUnit.highlightingMarksInRange(sourceRange(232, 30)); + ClangBackEnd::HighlightingMarkContainer container(infos[2]); + ASSERT_THAT(container.isIdentifier(), true); +} + +TEST_F(HighlightingMarks, DefineIsNotIdentifier) +{ + const auto infos = translationUnit.highlightingMarksInRange(sourceRange(232, 30)); + ClangBackEnd::HighlightingMarkContainer container(infos[1]); + ASSERT_THAT(container.isIncludeDirectivePath(), false); +} + Data *HighlightingMarks::d; void HighlightingMarks::SetUpTestCase() diff --git a/tests/unit/unittest/readandwritemessageblock-test.cpp b/tests/unit/unittest/readandwritemessageblock-test.cpp index ac57f833986..445743543a7 100644 --- a/tests/unit/unittest/readandwritemessageblock-test.cpp +++ b/tests/unit/unittest/readandwritemessageblock-test.cpp @@ -208,8 +208,7 @@ TEST_F(ReadAndWriteMessageBlock, CompareRequestFollowSymbol) QVector dependentFiles; dependentFiles.push_back(QString("somefile.cpp")); dependentFiles.push_back(QString("otherfile.cpp")); - CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, dependentFiles, 13, 37, - false}); + CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, dependentFiles, 13, 37}); } TEST_F(ReadAndWriteMessageBlock, CompareReferences) From 55a5ffc1ec0096076f4726a25c08d5902f24d46d Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Mon, 18 Sep 2017 10:19:27 +0200 Subject: [PATCH 53/63] C++: remove builtin FollowSymbol dependency from CppEditor Move FollowSymbolUnderCursor to CppTools and builtin member ownership to internal model manager. Change-Id: I97a4f744ec1709ccc0b34fb67b58680973ef566f Reviewed-by: Nikolai Kosjar --- .../clangmodelmanagersupport.cpp | 7 ++- .../clangcodemodel/clangmodelmanagersupport.h | 7 ++- src/plugins/cppeditor/cppeditor.pro | 6 --- src/plugins/cppeditor/cppeditor.qbs | 6 --- src/plugins/cppeditor/cppeditorwidget.cpp | 18 ++++---- src/plugins/cppeditor/cppeditorwidget.h | 13 ++++-- src/plugins/cppeditor/cppquickfixes.cpp | 2 +- .../cppeditor/cpprefactoringengine.cpp | 4 +- .../followsymbol_switchmethoddecldef_test.cpp | 12 ++--- .../cpptools/cppeditorwidgetinterface.h | 46 +++++++++++++++++++ .../cppfollowsymbolundercursor.cpp | 36 +++++++-------- .../cppfollowsymbolundercursor.h | 10 ++-- src/plugins/cpptools/cppmodelmanager.cpp | 2 +- src/plugins/cpptools/cppmodelmanager.h | 2 +- src/plugins/cpptools/cppmodelmanagersupport.h | 2 +- .../cppmodelmanagersupportinternal.cpp | 8 ++-- .../cpptools/cppmodelmanagersupportinternal.h | 3 +- src/plugins/cpptools/cpptools.pro | 9 +++- src/plugins/cpptools/cpptools.qbs | 7 +++ .../cppvirtualfunctionassistprovider.cpp | 18 ++++---- .../cppvirtualfunctionassistprovider.h | 10 ++-- .../cppvirtualfunctionproposalitem.cpp | 6 ++- .../cppvirtualfunctionproposalitem.h | 8 ++-- src/plugins/cpptools/cursorineditor.h | 13 +++--- 24 files changed, 156 insertions(+), 99 deletions(-) create mode 100644 src/plugins/cpptools/cppeditorwidgetinterface.h rename src/plugins/{cppeditor => cpptools}/cppfollowsymbolundercursor.cpp (96%) rename src/plugins/{cppeditor => cpptools}/cppfollowsymbolundercursor.h (90%) rename src/plugins/{cppeditor => cpptools}/cppvirtualfunctionassistprovider.cpp (96%) rename src/plugins/{cppeditor => cpptools}/cppvirtualfunctionassistprovider.h (93%) rename src/plugins/{cppeditor => cpptools}/cppvirtualfunctionproposalitem.cpp (96%) rename src/plugins/{cppeditor => cpptools}/cppvirtualfunctionproposalitem.h (92%) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 547f27276bc..c5d85045c51 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -31,6 +31,7 @@ #include "clangfollowsymbol.h" #include +#include #include #include #include @@ -72,6 +73,8 @@ ModelManagerSupportClang::ModelManagerSupportClang() if (useClangFollowSymbol()) m_followSymbol.reset(new ClangFollowSymbol); + else + m_followSymbol.reset(new CppTools::FollowSymbolUnderCursor); Core::EditorManager *editorManager = Core::EditorManager::instance(); connect(editorManager, &Core::EditorManager::editorOpened, @@ -106,9 +109,9 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis return &m_completionAssistProvider; } -CppTools::FollowSymbolInterface *ModelManagerSupportClang::followSymbolInterface() +CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface() { - return m_followSymbol.get(); + return *m_followSymbol; } CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor( diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 8728704e1c6..78e5cd5694a 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -42,12 +42,11 @@ QT_END_NAMESPACE namespace Core { class IDocument; } namespace TextEditor { class TextEditorWidget; } +namespace CppTools { class FollowSymbolInterface; } namespace ClangCodeModel { namespace Internal { -class ClangFollowSymbol; - class ModelManagerSupportClang: public QObject, public CppTools::ModelManagerSupport @@ -61,7 +60,7 @@ public: CppTools::CppCompletionAssistProvider *completionAssistProvider() override; CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) override; - CppTools::FollowSymbolInterface *followSymbolInterface() override; + CppTools::FollowSymbolInterface &followSymbolInterface() override; IpcCommunicator &ipcCommunicator(); QString dummyUiHeaderOnDiskDirPath() const; @@ -105,7 +104,7 @@ private: UiHeaderOnDiskManager m_uiHeaderOnDiskManager; IpcCommunicator m_ipcCommunicator; ClangCompletionAssistProvider m_completionAssistProvider; - std::unique_ptr m_followSymbol; + std::unique_ptr m_followSymbol; }; class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index 2b68cf74218..e2746f15a65 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -13,7 +13,6 @@ HEADERS += \ cppeditorplugin.h \ cppeditorwidget.h \ cppelementevaluator.h \ - cppfollowsymbolundercursor.h \ cppfunctiondecldeflink.h \ cpphighlighter.h \ cpphoverhandler.h \ @@ -30,8 +29,6 @@ HEADERS += \ cpprefactoringengine.h \ cpptypehierarchy.h \ cppuseselectionsupdater.h \ - cppvirtualfunctionassistprovider.h \ - cppvirtualfunctionproposalitem.h \ resourcepreviewhoverhandler.h SOURCES += \ @@ -43,7 +40,6 @@ SOURCES += \ cppeditorplugin.cpp \ cppeditorwidget.cpp \ cppelementevaluator.cpp \ - cppfollowsymbolundercursor.cpp \ cppfunctiondecldeflink.cpp \ cpphighlighter.cpp \ cpphoverhandler.cpp \ @@ -60,8 +56,6 @@ SOURCES += \ cpprefactoringengine.cpp \ cpptypehierarchy.cpp \ cppuseselectionsupdater.cpp \ - cppvirtualfunctionassistprovider.cpp \ - cppvirtualfunctionproposalitem.cpp \ resourcepreviewhoverhandler.cpp FORMS += \ diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index a5c017665a0..52b65a99fbc 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -41,8 +41,6 @@ QtcPlugin { "cppeditorplugin.h", "cppelementevaluator.cpp", "cppelementevaluator.h", - "cppfollowsymbolundercursor.cpp", - "cppfollowsymbolundercursor.h", "cppfunctiondecldeflink.cpp", "cppfunctiondecldeflink.h", "cpphighlighter.cpp", @@ -76,10 +74,6 @@ QtcPlugin { "cpptypehierarchy.h", "cppuseselectionsupdater.cpp", "cppuseselectionsupdater.h", - "cppvirtualfunctionassistprovider.cpp", - "cppvirtualfunctionassistprovider.h", - "cppvirtualfunctionproposalitem.cpp", - "cppvirtualfunctionproposalitem.h", "resourcepreviewhoverhandler.cpp", "resourcepreviewhoverhandler.h", ] diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 75938351712..4d1d862a32f 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -30,7 +30,6 @@ #include "cppeditorconstants.h" #include "cppeditordocument.h" #include "cppeditorplugin.h" -#include "cppfollowsymbolundercursor.h" #include "cppfunctiondecldeflink.h" #include "cpphighlighter.h" #include "cpplocalrenaming.h" @@ -63,6 +62,7 @@ #include #include #include +#include #include #include @@ -130,7 +130,6 @@ public: CppLocalRenaming m_localRenaming; CppUseSelectionsUpdater m_useSelectionsUpdater; CppSelectionChanger m_cppSelectionChanger; - FollowSymbolUnderCursor m_builtinFollowSymbol; CppRefactoringEngine m_builtinRefactoringEngine; }; @@ -650,7 +649,7 @@ CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor, const Utils::FileName &filePath = textDocument()->filePath(); - return followSymbolInterface()->findLink(CppTools::CursorInEditor{cursor, filePath, this}, + return followSymbolInterface().findLink(CppTools::CursorInEditor{cursor, filePath, this}, resolveTarget, d->m_modelManager->snapshot(), d->m_lastSemanticInfo.doc, @@ -690,12 +689,9 @@ RefactoringEngineInterface *CppEditorWidget::refactoringEngine() const : static_cast(&d->m_builtinRefactoringEngine); } -CppTools::FollowSymbolInterface *CppEditorWidget::followSymbolInterface() const +CppTools::FollowSymbolInterface &CppEditorWidget::followSymbolInterface() const { - CppTools::FollowSymbolInterface *followSymbol - = CppTools::CppModelManager::instance()->followSymbolInterface(); - return followSymbol ? followSymbol - : static_cast(&d->m_builtinFollowSymbol); + return CppTools::CppModelManager::instance()->followSymbolInterface(); } bool CppEditorWidget::isSemanticInfoValidExceptLocalUses() const @@ -1041,5 +1037,11 @@ void CppEditorWidget::showPreProcessorWidget() } } +void CppEditorWidget::invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind, + TextEditor::IAssistProvider *provider) +{ + invokeAssist(assistKind, provider); +} + } // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppeditorwidget.h b/src/plugins/cppeditor/cppeditorwidget.h index d67b1f4b8c4..34604c40cdf 100644 --- a/src/plugins/cppeditor/cppeditorwidget.h +++ b/src/plugins/cppeditor/cppeditorwidget.h @@ -27,6 +27,8 @@ #include +#include + #include namespace CppTools { @@ -45,7 +47,8 @@ class CppEditorDocument; class CppEditorWidgetPrivate; class FunctionDeclDefLink; -class CppEditorWidget : public TextEditor::TextEditorWidget +class CppEditorWidget : public TextEditor::TextEditorWidget, + public CppTools::CppEditorWidgetInterface { Q_OBJECT @@ -74,7 +77,7 @@ public: void selectAll() override; void switchDeclarationDefinition(bool inNextSplit); - void showPreProcessorWidget(); + void showPreProcessorWidget() override; void findUsages(); void renameSymbolUnderCursor(); @@ -86,9 +89,10 @@ public: static void updateWidgetHighlighting(QWidget *widget, bool highlight); static bool isWidgetHighlighted(QWidget *widget); - void updateSemanticInfo(); + void updateSemanticInfo() override; + void invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind, + TextEditor::IAssistProvider *provider) override; - CppTools::FollowSymbolInterface *followSymbolInterface() const; protected: bool event(QEvent *e) override; void contextMenuEvent(QContextMenuEvent *) override; @@ -133,6 +137,7 @@ private: TextEditor::RefactorMarkers refactorMarkersWithoutClangMarkers() const; + CppTools::FollowSymbolInterface &followSymbolInterface() const; CppTools::RefactoringEngineInterface *refactoringEngine() const; CppTools::ProjectPart *projectPart() const; diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index fc4ed5a2ac6..9f51f15febb 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -29,12 +29,12 @@ #include "cppeditordocument.h" #include "cppfunctiondecldeflink.h" #include "cppquickfixassistant.h" -#include "cppvirtualfunctionassistprovider.h" #include "cppinsertvirtualmethods.h" #include #include +#include #include #include #include diff --git a/src/plugins/cppeditor/cpprefactoringengine.cpp b/src/plugins/cppeditor/cpprefactoringengine.cpp index c9bfceb49c2..534506069ff 100644 --- a/src/plugins/cppeditor/cpprefactoringengine.cpp +++ b/src/plugins/cppeditor/cpprefactoringengine.cpp @@ -35,7 +35,7 @@ void CppRefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &da CppTools::ProjectPart *, RenameCallback &&renameSymbolsCallback) { - CppEditorWidget *editorWidget = static_cast(data.editorWidget()); + CppEditorWidget *editorWidget = dynamic_cast(data.editorWidget()); QTC_ASSERT(editorWidget, renameSymbolsCallback(QString(), ClangBackEnd::SourceLocationsContainer(), 0); return;); @@ -48,7 +48,7 @@ void CppRefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &da void CppRefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &data) { - CppEditorWidget *editorWidget = static_cast(data.editorWidget()); + CppEditorWidget *editorWidget = dynamic_cast(data.editorWidget()); if (!editorWidget) return; editorWidget->renameUsages(); diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 9c45cea0559..1f7576c49b1 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -28,10 +28,10 @@ #include "cppeditorplugin.h" #include "cppeditortestcase.h" #include "cppelementevaluator.h" -#include "cppfollowsymbolundercursor.h" -#include "cppvirtualfunctionassistprovider.h" -#include "cppvirtualfunctionproposalitem.h" +#include +#include +#include #include #include @@ -327,10 +327,8 @@ F2TestCase::F2TestCase(CppEditorAction action, switch (action) { case FollowSymbolUnderCursorAction: { CppEditorWidget *widget = initialTestFile->m_editorWidget; - FollowSymbolInterface* delegate = widget->followSymbolInterface(); - if (!delegate) - QFAIL("No follow symbol interface"); - auto* builtinFollowSymbol = dynamic_cast(delegate); + FollowSymbolInterface &delegate = CppModelManager::instance()->followSymbolInterface(); + auto* builtinFollowSymbol = dynamic_cast(&delegate); if (!builtinFollowSymbol) { if (filePaths.size() > 1) QSKIP("Clang FollowSymbol does not currently support multiple files (except cpp+header)"); diff --git a/src/plugins/cpptools/cppeditorwidgetinterface.h b/src/plugins/cpptools/cppeditorwidgetinterface.h new file mode 100644 index 00000000000..d7fbefbd69c --- /dev/null +++ b/src/plugins/cpptools/cppeditorwidgetinterface.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "cpptools_global.h" + +#include + +namespace TextEditor { class IAssistProvider; } + +namespace CppTools { + +class CPPTOOLS_EXPORT CppEditorWidgetInterface +{ +public: + virtual void showPreProcessorWidget() = 0; + virtual void updateSemanticInfo() = 0; + + virtual void invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind, + TextEditor::IAssistProvider *provider) = 0; +}; + +} // namespace CppTools diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp similarity index 96% rename from src/plugins/cppeditor/cppfollowsymbolundercursor.cpp rename to src/plugins/cpptools/cppfollowsymbolundercursor.cpp index 6bc1cfa30e3..b8ffce90ef6 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp @@ -24,9 +24,11 @@ ****************************************************************************/ #include "cppfollowsymbolundercursor.h" -#include "cppeditorwidget.h" -#include "cppeditordocument.h" #include "cppvirtualfunctionassistprovider.h" +#include "cppmodelmanager.h" +#include "functionutils.h" +#include "cpptoolsreuse.h" +#include "symbolfinder.h" #include #include @@ -34,10 +36,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -46,13 +44,12 @@ #include using namespace CPlusPlus; -using namespace CppTools; -using namespace CppEditor; -using namespace CppEditor::Internal; using namespace TextEditor; typedef TextEditorWidget::Link Link; +namespace CppTools { + namespace { class VirtualFunctionHelper { @@ -299,9 +296,9 @@ inline LookupItem skipForwardDeclarations(const QList &resolvedSymbo return result; } -CppEditorWidget::Link attemptFuncDeclDef(const QTextCursor &cursor, Snapshot snapshot, - const Document::Ptr &document, - SymbolFinder *symbolFinder) +Link attemptFuncDeclDef(const QTextCursor &cursor, Snapshot snapshot, + const Document::Ptr &document, + SymbolFinder *symbolFinder) { Link result; QTC_ASSERT(document, return result); @@ -610,11 +607,11 @@ Link FollowSymbolUnderCursor::findLink( } } - CppEditorWidget *editorWidget = static_cast(data.editorWidget()); + CppEditorWidgetInterface *editorWidget = data.editorWidget(); if (!editorWidget) return link; // Now we prefer the doc from the snapshot with macros expanded. - Document::Ptr doc = snapshot.document(editorWidget->textDocument()->filePath()); + Document::Ptr doc = snapshot.document(data.filePath()); if (!doc) { doc = documentFromSemanticInfo; if (!doc) @@ -697,7 +694,7 @@ Link FollowSymbolUnderCursor::findLink( if (Symbol *d = r.declaration()) { if (d->isDeclaration() || d->isFunction()) { const QString fileName = QString::fromUtf8(d->fileName(), d->fileNameLength()); - if (editorWidget->textDocument()->filePath().toString() == fileName) { + if (data.filePath().toString() == fileName) { if (unsigned(lineNumber) == d->line() && unsigned(positionInBlock) >= d->column()) { // TODO: check the end result = r; // take the symbol under cursor. @@ -706,8 +703,8 @@ Link FollowSymbolUnderCursor::findLink( } } else if (d->isUsingDeclaration()) { int tokenBeginLineNumber = 0, tokenBeginColumnNumber = 0; - editorWidget->convertPosition(beginOfToken, &tokenBeginLineNumber, - &tokenBeginColumnNumber); + TextEditor::Convenience::convertPosition(document, beginOfToken, &tokenBeginLineNumber, + &tokenBeginColumnNumber); if (unsigned(tokenBeginLineNumber) > d->line() || (unsigned(tokenBeginLineNumber) == d->line() && unsigned(tokenBeginColumnNumber) > d->column())) { @@ -736,7 +733,8 @@ Link FollowSymbolUnderCursor::findLink( params.openInNextSplit = inNextSplit; if (m_virtualFunctionAssistProvider->configure(params)) { - editorWidget->invokeAssist(FollowSymbol, m_virtualFunctionAssistProvider.data()); + editorWidget->invokeTextEditorWidgetAssist( + FollowSymbol,m_virtualFunctionAssistProvider.data()); m_virtualFunctionAssistProvider->clearParams(); } @@ -795,3 +793,5 @@ void FollowSymbolUnderCursor::setVirtualFunctionAssistProvider( { m_virtualFunctionAssistProvider = provider; } + +} // namespace CppTools diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.h b/src/plugins/cpptools/cppfollowsymbolundercursor.h similarity index 90% rename from src/plugins/cppeditor/cppfollowsymbolundercursor.h rename to src/plugins/cpptools/cppfollowsymbolundercursor.h index 54c500aaa5b..8e93a7097d6 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.h +++ b/src/plugins/cpptools/cppfollowsymbolundercursor.h @@ -25,14 +25,13 @@ #pragma once -#include +#include "followsymbolinterface.h" -namespace CppEditor { -namespace Internal { +namespace CppTools { class VirtualFunctionAssistProvider; -class FollowSymbolUnderCursor : public CppTools::FollowSymbolInterface +class CPPTOOLS_EXPORT FollowSymbolUnderCursor : public CppTools::FollowSymbolInterface { public: FollowSymbolUnderCursor(); @@ -52,5 +51,4 @@ private: QSharedPointer m_virtualFunctionAssistProvider; }; -} // namespace Internal -} // namespace CppEditor +} // namespace CppTools diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 5a6db12be0b..7385d5ea6e0 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -275,7 +275,7 @@ RefactoringEngineInterface *CppModelManager::refactoringEngine() return instance()->d->m_refactoringEngine; } -FollowSymbolInterface *CppModelManager::followSymbolInterface() const +FollowSymbolInterface &CppModelManager::followSymbolInterface() const { return d->m_activeModelManagerSupport->followSymbolInterface(); } diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 229cfcef7de..dca98954878 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -153,7 +153,7 @@ public: CppCompletionAssistProvider *completionAssistProvider() const; BaseEditorDocumentProcessor *editorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) const; - FollowSymbolInterface *followSymbolInterface() const; + FollowSymbolInterface &followSymbolInterface() const; void setIndexingSupport(CppIndexingSupport *indexingSupport); CppIndexingSupport *indexingSupport(); diff --git a/src/plugins/cpptools/cppmodelmanagersupport.h b/src/plugins/cpptools/cppmodelmanagersupport.h index 0a56de102c9..cb74f00efdd 100644 --- a/src/plugins/cpptools/cppmodelmanagersupport.h +++ b/src/plugins/cpptools/cppmodelmanagersupport.h @@ -49,7 +49,7 @@ public: virtual CppCompletionAssistProvider *completionAssistProvider() = 0; virtual BaseEditorDocumentProcessor *editorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) = 0; - virtual FollowSymbolInterface *followSymbolInterface() = 0; + virtual FollowSymbolInterface &followSymbolInterface() = 0; }; class CPPTOOLS_EXPORT ModelManagerSupportProvider diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp index a7c48674c9c..c03e2ed57e9 100644 --- a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp +++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp @@ -25,6 +25,7 @@ #include "cppcompletionassist.h" #include "cppmodelmanagersupportinternal.h" +#include "cppfollowsymbolundercursor.h" #include "builtineditordocumentprocessor.h" #include @@ -51,7 +52,8 @@ ModelManagerSupport::Ptr ModelManagerSupportProviderInternal::createModelManager } ModelManagerSupportInternal::ModelManagerSupportInternal() - : m_completionAssistProvider(new InternalCompletionAssistProvider) + : m_completionAssistProvider(new InternalCompletionAssistProvider), + m_followSymbol(new FollowSymbolUnderCursor) { } @@ -70,7 +72,7 @@ CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvid return m_completionAssistProvider.data(); } -FollowSymbolInterface *ModelManagerSupportInternal::followSymbolInterface() +FollowSymbolInterface &ModelManagerSupportInternal::followSymbolInterface() { - return nullptr; + return *m_followSymbol; } diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.h b/src/plugins/cpptools/cppmodelmanagersupportinternal.h index b205ab47ecd..cd35ea5abce 100644 --- a/src/plugins/cpptools/cppmodelmanagersupportinternal.h +++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.h @@ -43,10 +43,11 @@ public: CppCompletionAssistProvider *completionAssistProvider() final; BaseEditorDocumentProcessor *editorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) final; - FollowSymbolInterface *followSymbolInterface() final; + FollowSymbolInterface &followSymbolInterface() final; private: QScopedPointer m_completionAssistProvider; + QScopedPointer m_followSymbol; }; class ModelManagerSupportProviderInternal : public ModelManagerSupportProvider diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 20ed13d4cff..1328d376867 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -29,11 +29,13 @@ HEADERS += \ cppcompletionassistprovider.h \ cppcursorinfo.h \ cppcurrentdocumentfilter.h \ - cppeditoroutline.h \ cppdoxygen.h \ + cppeditoroutline.h \ + cppeditorwidgetinterface.h \ cppfileiterationorder.h \ cppfilesettingspage.h \ cppfindreferences.h \ + cppfollowsymbolundercursor.h \ cppfunctionsfilter.h \ cppincludesfilter.h \ cppindexingsupport.h \ @@ -60,6 +62,8 @@ HEADERS += \ cpptoolsplugin.h \ cpptoolsreuse.h \ cpptoolssettings.h \ + cppvirtualfunctionassistprovider.h \ + cppvirtualfunctionproposalitem.h \ cppworkingcopy.h \ doxygengenerator.h \ editordocumenthandle.h \ @@ -123,6 +127,7 @@ SOURCES += \ cppfileiterationorder.cpp \ cppfilesettingspage.cpp \ cppfindreferences.cpp \ + cppfollowsymbolundercursor.cpp \ cppfunctionsfilter.cpp \ cppincludesfilter.cpp \ cppindexingsupport.cpp \ @@ -145,6 +150,8 @@ SOURCES += \ cpptoolsplugin.cpp \ cpptoolsreuse.cpp \ cpptoolssettings.cpp \ + cppvirtualfunctionassistprovider.cpp \ + cppvirtualfunctionproposalitem.cpp \ cppworkingcopy.cpp \ doxygengenerator.cpp \ editordocumenthandle.cpp \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index 35cb74c2630..3fc050744da 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -90,6 +90,7 @@ Project { "cppdoxygen.h", "cppeditoroutline.cpp", "cppeditoroutline.h", + "cppeditorwidgetinterface.h", "cppfileiterationorder.cpp", "cppfileiterationorder.h", "cppfilesettingspage.cpp", @@ -97,6 +98,8 @@ Project { "cppfilesettingspage.ui", "cppfindreferences.cpp", "cppfindreferences.h", + "cppfollowsymbolundercursor.cpp", + "cppfollowsymbolundercursor.h", "cppfunctionsfilter.cpp", "cppfunctionsfilter.h", "cppincludesfilter.cpp", @@ -157,6 +160,10 @@ Project { "cpptoolsreuse.h", "cpptoolssettings.cpp", "cpptoolssettings.h", + "cppvirtualfunctionassistprovider.cpp", + "cppvirtualfunctionassistprovider.h", + "cppvirtualfunctionproposalitem.cpp", + "cppvirtualfunctionproposalitem.h", "cppworkingcopy.cpp", "cppworkingcopy.h", "cursorineditor.h", diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cpptools/cppvirtualfunctionassistprovider.cpp similarity index 96% rename from src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp rename to src/plugins/cpptools/cppvirtualfunctionassistprovider.cpp index e2e3accffe3..5711eb912ca 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cpptools/cppvirtualfunctionassistprovider.cpp @@ -24,21 +24,19 @@ ****************************************************************************/ #include "cppvirtualfunctionassistprovider.h" - -#include "cppeditorconstants.h" #include "cppvirtualfunctionproposalitem.h" +#include "cpptoolsreuse.h" +#include "functionutils.h" +#include "symbolfinder.h" +#include "typehierarchybuilder.h" + #include #include #include #include -#include -#include -#include -#include - #include #include #include @@ -50,10 +48,10 @@ #include using namespace CPlusPlus; -using namespace CppEditor::Internal; -using namespace CppTools; using namespace TextEditor; +namespace CppTools { + /// Activate current item with the same shortcut that is configured for Follow Symbol Under Cursor. /// This is limited to single-key shortcuts without modifiers. class VirtualFunctionProposalWidget : public GenericProposalWidget @@ -211,3 +209,5 @@ IAssistProcessor *VirtualFunctionAssistProvider::createProcessor() const { return new VirtualFunctionAssistProcessor(m_params); } + +} // namespace CppTools diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cpptools/cppvirtualfunctionassistprovider.h similarity index 93% rename from src/plugins/cppeditor/cppvirtualfunctionassistprovider.h rename to src/plugins/cpptools/cppvirtualfunctionassistprovider.h index 363981b7ca6..08ff2018d49 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h +++ b/src/plugins/cpptools/cppvirtualfunctionassistprovider.h @@ -25,6 +25,8 @@ #pragma once +#include "cpptools_global.h" + #include #include @@ -34,10 +36,9 @@ #include #include -namespace CppEditor { -namespace Internal { +namespace CppTools { -class VirtualFunctionAssistProvider : public TextEditor::IAssistProvider +class CPPTOOLS_EXPORT VirtualFunctionAssistProvider : public TextEditor::IAssistProvider { public: VirtualFunctionAssistProvider(); @@ -64,5 +65,4 @@ private: Parameters m_params; }; -} // namespace Internal -} // namespace CppEditor +} // namespace CppTools diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp b/src/plugins/cpptools/cppvirtualfunctionproposalitem.cpp similarity index 96% rename from src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp rename to src/plugins/cpptools/cppvirtualfunctionproposalitem.cpp index 44bd8d01cfe..474aecac467 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp +++ b/src/plugins/cpptools/cppvirtualfunctionproposalitem.cpp @@ -25,11 +25,11 @@ #include "cppvirtualfunctionproposalitem.h" -#include "cppeditorconstants.h" +#include #include -using namespace CppEditor::Internal; +namespace CppTools { VirtualFunctionProposalItem::VirtualFunctionProposalItem( const TextEditor::TextEditorWidget::Link &link, bool openInSplit) @@ -52,3 +52,5 @@ void VirtualFunctionProposalItem::apply(TextEditor::TextDocumentManipulatorInter CppEditor::Constants::CPPEDITOR_ID, flags); } + +} // namespace CppTools diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h b/src/plugins/cpptools/cppvirtualfunctionproposalitem.h similarity index 92% rename from src/plugins/cppeditor/cppvirtualfunctionproposalitem.h rename to src/plugins/cpptools/cppvirtualfunctionproposalitem.h index 5d86d4b3906..19bb7715ea1 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h +++ b/src/plugins/cpptools/cppvirtualfunctionproposalitem.h @@ -25,13 +25,14 @@ #pragma once +#include "cpptools_global.h" + #include #include -namespace CppEditor { -namespace Internal { +namespace CppTools { -class VirtualFunctionProposalItem final : public TextEditor::AssistProposalItem +class CPPTOOLS_EXPORT VirtualFunctionProposalItem final : public TextEditor::AssistProposalItem { public: VirtualFunctionProposalItem(const TextEditor::TextEditorWidget::Link &link, @@ -46,5 +47,4 @@ private: bool m_openInSplit; }; -} // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cpptools/cursorineditor.h b/src/plugins/cpptools/cursorineditor.h index c93f9e83382..18097e5dbd3 100644 --- a/src/plugins/cpptools/cursorineditor.h +++ b/src/plugins/cpptools/cursorineditor.h @@ -25,12 +25,11 @@ #pragma once -#include +#include "cppeditorwidgetinterface.h" + #include -namespace TextEditor { -class TextEditorWidget; -} // namespace TextEditor +#include namespace CppTools { @@ -38,18 +37,18 @@ class CursorInEditor { public: CursorInEditor(const QTextCursor &cursor, const Utils::FileName &filePath, - TextEditor::TextEditorWidget *editorWidget = nullptr) + CppEditorWidgetInterface *editorWidget = nullptr) : m_cursor(cursor) , m_filePath(filePath) , m_editorWidget(editorWidget) {} - TextEditor::TextEditorWidget *editorWidget() const { return m_editorWidget; } + CppEditorWidgetInterface *editorWidget() const { return m_editorWidget; } const QTextCursor &cursor() const { return m_cursor; } const Utils::FileName &filePath() const { return m_filePath; } private: QTextCursor m_cursor; Utils::FileName m_filePath; - TextEditor::TextEditorWidget *m_editorWidget = nullptr; + CppEditorWidgetInterface *m_editorWidget = nullptr; }; } // namespace CppTools From a959fe59da71289cb52b6c006d8ec7bc70362ad8 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Mon, 18 Sep 2017 11:29:55 +0200 Subject: [PATCH 54/63] C++: remove builtin RefactoringEngine dependency from CppEditor Move CppRefactoringEngine to CppTools and builtin member ownership to model manager. Change-Id: I3e72308559fd2928229f9f25d4dd09beb3f56c34 Reviewed-by: Nikolai Kosjar --- .../clangrefactoring/clangrefactoringplugin.cpp | 1 + src/plugins/cppeditor/cppeditor.pro | 2 -- src/plugins/cppeditor/cppeditor.qbs | 2 -- src/plugins/cppeditor/cppeditorwidget.cpp | 16 ++++++---------- src/plugins/cppeditor/cppeditorwidget.h | 5 +++-- src/plugins/cpptools/cppeditorwidgetinterface.h | 8 ++++++++ src/plugins/cpptools/cppmodelmanager.cpp | 13 +++++++++---- src/plugins/cpptools/cppmodelmanager.h | 2 +- .../cpprefactoringengine.cpp | 15 ++++++--------- .../cpprefactoringengine.h | 10 +++------- src/plugins/cpptools/cpptools.pro | 2 ++ src/plugins/cpptools/cpptools.qbs | 2 ++ .../cpptools/refactoringengineinterface.h | 4 +++- 13 files changed, 44 insertions(+), 38 deletions(-) rename src/plugins/{cppeditor => cpptools}/cpprefactoringengine.cpp (84%) rename src/plugins/{cppeditor => cpptools}/cpprefactoringengine.h (88%) diff --git a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp index ea17409faca..a2638212d65 100644 --- a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp +++ b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp @@ -96,6 +96,7 @@ void ClangRefactoringPlugin::extensionsInitialized() ExtensionSystem::IPlugin::ShutdownFlag ClangRefactoringPlugin::aboutToShutdown() { ExtensionSystem::PluginManager::removeObject(&d->qtCreatorfindFilter); + CppTools::CppModelManager::setRefactoringEngine(nullptr); d->refactoringClient.setRefactoringConnectionClient(nullptr); d->refactoringClient.setRefactoringEngine(nullptr); diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index e2746f15a65..0bc3391ce81 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -26,7 +26,6 @@ HEADERS += \ cppquickfix.h \ cppquickfixassistant.h \ cppquickfixes.h \ - cpprefactoringengine.h \ cpptypehierarchy.h \ cppuseselectionsupdater.h \ resourcepreviewhoverhandler.h @@ -53,7 +52,6 @@ SOURCES += \ cppquickfix.cpp \ cppquickfixassistant.cpp \ cppquickfixes.cpp \ - cpprefactoringengine.cpp \ cpptypehierarchy.cpp \ cppuseselectionsupdater.cpp \ resourcepreviewhoverhandler.cpp diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index 52b65a99fbc..5d8b17adb41 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -68,8 +68,6 @@ QtcPlugin { "cppquickfixassistant.h", "cppquickfixes.cpp", "cppquickfixes.h", - "cpprefactoringengine.cpp", - "cpprefactoringengine.h", "cpptypehierarchy.cpp", "cpptypehierarchy.h", "cppuseselectionsupdater.cpp", diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 4d1d862a32f..1542c55691f 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -36,7 +36,6 @@ #include "cppminimizableinfobars.h" #include "cpppreprocessordialog.h" #include "cppquickfixassistant.h" -#include "cpprefactoringengine.h" #include "cppuseselectionsupdater.h" #include @@ -130,7 +129,6 @@ public: CppLocalRenaming m_localRenaming; CppUseSelectionsUpdater m_useSelectionsUpdater; CppSelectionChanger m_cppSelectionChanger; - CppRefactoringEngine m_builtinRefactoringEngine; }; CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q) @@ -361,7 +359,7 @@ void CppEditorWidget::findUsages() } } -void CppEditorWidget::renameUsages(const QString &replacement) +void CppEditorWidget::renameUsagesInternal(const QString &replacement) { if (!d->m_modelManager) return; @@ -522,7 +520,7 @@ void CppEditorWidget::renameSymbolUnderCursor() using ClangBackEnd::SourceLocationsContainer; ProjectPart *projPart = projectPart(); - if (!refactoringEngine()->isUsable() || !projPart) + if (!refactoringEngine().isUsable() || !projPart) return; d->m_useSelectionsUpdater.abortSchedule(); @@ -546,14 +544,14 @@ void CppEditorWidget::renameSymbolUnderCursor() d->m_localRenaming.updateSelectionsForVariableUnderCursor(selections); } if (!d->m_localRenaming.start()) { - refactoringEngine()->startGlobalRenaming( + refactoringEngine().startGlobalRenaming( CppTools::CursorInEditor{textCursor(), textDocument()->filePath(), this}); } } }; viewport()->setCursor(Qt::BusyCursor); - refactoringEngine()->startLocalRenaming(CppTools::CursorInEditor{textCursor(), + refactoringEngine().startLocalRenaming(CppTools::CursorInEditor{textCursor(), textDocument()->filePath(), this}, projPart, @@ -682,11 +680,9 @@ RefactorMarkers CppEditorWidget::refactorMarkersWithoutClangMarkers() const return clearedRefactorMarkers; } -RefactoringEngineInterface *CppEditorWidget::refactoringEngine() const +RefactoringEngineInterface &CppEditorWidget::refactoringEngine() const { - RefactoringEngineInterface *engine = CppTools::CppModelManager::refactoringEngine(); - return engine ? engine - : static_cast(&d->m_builtinRefactoringEngine); + return CppTools::CppModelManager::refactoringEngine(); } CppTools::FollowSymbolInterface &CppEditorWidget::followSymbolInterface() const diff --git a/src/plugins/cppeditor/cppeditorwidget.h b/src/plugins/cppeditor/cppeditorwidget.h index 34604c40cdf..166ff10557d 100644 --- a/src/plugins/cppeditor/cppeditorwidget.h +++ b/src/plugins/cppeditor/cppeditorwidget.h @@ -81,7 +81,6 @@ public: void findUsages(); void renameSymbolUnderCursor(); - void renameUsages(const QString &replacement = QString()); bool selectBlockUp() override; bool selectBlockDown() override; @@ -106,6 +105,8 @@ protected: void slotCodeStyleSettingsChanged(const QVariant &) override; + void renameUsagesInternal(const QString &replacement) override; + private: void updateFunctionDeclDefLink(); void updateFunctionDeclDefLinkNow(); @@ -138,7 +139,7 @@ private: TextEditor::RefactorMarkers refactorMarkersWithoutClangMarkers() const; CppTools::FollowSymbolInterface &followSymbolInterface() const; - CppTools::RefactoringEngineInterface *refactoringEngine() const; + CppTools::RefactoringEngineInterface &refactoringEngine() const; CppTools::ProjectPart *projectPart() const; diff --git a/src/plugins/cpptools/cppeditorwidgetinterface.h b/src/plugins/cpptools/cppeditorwidgetinterface.h index d7fbefbd69c..309fa581cdd 100644 --- a/src/plugins/cpptools/cppeditorwidgetinterface.h +++ b/src/plugins/cpptools/cppeditorwidgetinterface.h @@ -29,6 +29,8 @@ #include +#include + namespace TextEditor { class IAssistProvider; } namespace CppTools { @@ -36,8 +38,14 @@ namespace CppTools { class CPPTOOLS_EXPORT CppEditorWidgetInterface { public: + void renameUsages(const QString &replacement = QString()) + { + return renameUsagesInternal(replacement); + } + virtual void showPreProcessorWidget() = 0; virtual void updateSemanticInfo() = 0; + virtual void renameUsagesInternal(const QString &replacement) = 0; virtual void invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind, TextEditor::IAssistProvider *provider) = 0; diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 7385d5ea6e0..da453017822 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -33,6 +33,7 @@ #include "cppindexingsupport.h" #include "cppmodelmanagersupportinternal.h" #include "cpprefactoringchanges.h" +#include "cpprefactoringengine.h" #include "cppsourceprocessor.h" #include "cpptoolsconstants.h" #include "cpptoolsplugin.h" @@ -165,7 +166,8 @@ public: QTimer m_delayedGcTimer; // Refactoring - RefactoringEngineInterface *m_refactoringEngine = nullptr; + CppRefactoringEngine m_builtInRefactoringEngine; + RefactoringEngineInterface *m_refactoringEngine { &m_builtInRefactoringEngine }; }; } // namespace Internal @@ -267,12 +269,15 @@ QString CppModelManager::editorConfigurationFileName() void CppModelManager::setRefactoringEngine(RefactoringEngineInterface *refactoringEngine) { - instance()->d->m_refactoringEngine = refactoringEngine; + if (refactoringEngine) + instance()->d->m_refactoringEngine = refactoringEngine; + else + instance()->d->m_refactoringEngine = &instance()->d->m_builtInRefactoringEngine; } -RefactoringEngineInterface *CppModelManager::refactoringEngine() +RefactoringEngineInterface &CppModelManager::refactoringEngine() { - return instance()->d->m_refactoringEngine; + return *instance()->d->m_refactoringEngine; } FollowSymbolInterface &CppModelManager::followSymbolInterface() const diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index dca98954878..df04beec3a1 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -180,7 +180,7 @@ public: static QString editorConfigurationFileName(); static void setRefactoringEngine(RefactoringEngineInterface *refactoringEngine); - static RefactoringEngineInterface *refactoringEngine(); + static RefactoringEngineInterface &refactoringEngine(); void renameIncludes(const QString &oldFileName, const QString &newFileName); diff --git a/src/plugins/cppeditor/cpprefactoringengine.cpp b/src/plugins/cpptools/cpprefactoringengine.cpp similarity index 84% rename from src/plugins/cppeditor/cpprefactoringengine.cpp rename to src/plugins/cpptools/cpprefactoringengine.cpp index 534506069ff..705a8ecc99e 100644 --- a/src/plugins/cppeditor/cpprefactoringengine.cpp +++ b/src/plugins/cpptools/cpprefactoringengine.cpp @@ -24,18 +24,17 @@ ****************************************************************************/ #include "cpprefactoringengine.h" -#include "cppeditorwidget.h" +#include "texteditor/texteditor.h" #include "utils/qtcassert.h" -namespace CppEditor { -namespace Internal { +namespace CppTools { void CppRefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data, CppTools::ProjectPart *, RenameCallback &&renameSymbolsCallback) { - CppEditorWidget *editorWidget = dynamic_cast(data.editorWidget()); + CppEditorWidgetInterface *editorWidget = data.editorWidget(); QTC_ASSERT(editorWidget, renameSymbolsCallback(QString(), ClangBackEnd::SourceLocationsContainer(), 0); return;); @@ -43,16 +42,14 @@ void CppRefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &da // Call empty callback renameSymbolsCallback(QString(), ClangBackEnd::SourceLocationsContainer(), - editorWidget->document()->revision()); + data.cursor().document()->revision()); } void CppRefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &data) { - CppEditorWidget *editorWidget = dynamic_cast(data.editorWidget()); - if (!editorWidget) - return; + CppEditorWidgetInterface *editorWidget = data.editorWidget(); + QTC_ASSERT(editorWidget, return;); editorWidget->renameUsages(); } -} // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cppeditor/cpprefactoringengine.h b/src/plugins/cpptools/cpprefactoringengine.h similarity index 88% rename from src/plugins/cppeditor/cpprefactoringengine.h rename to src/plugins/cpptools/cpprefactoringengine.h index 02deeffc27a..acbf02e5e65 100644 --- a/src/plugins/cppeditor/cpprefactoringengine.h +++ b/src/plugins/cpptools/cpprefactoringengine.h @@ -25,14 +25,11 @@ #pragma once -#include +#include "refactoringengineinterface.h" -namespace CppEditor { -namespace Internal { +namespace CppTools { -class CppEditorWidget; - -class CppRefactoringEngine : public CppTools::RefactoringEngineInterface +class CPPTOOLS_EXPORT CppRefactoringEngine : public RefactoringEngineInterface { public: void startLocalRenaming(const CppTools::CursorInEditor &data, @@ -43,5 +40,4 @@ public: bool isUsable() const override { return true; } }; -} // namespace Internal } // namespace CppEditor diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 1328d376867..c9ca4e4c18d 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -51,6 +51,7 @@ HEADERS += \ cppqtstyleindenter.h \ cpprawprojectpart.h \ cpprefactoringchanges.h \ + cpprefactoringengine.h \ cppselectionchanger.h \ cppsemanticinfo.h \ cppsemanticinfoupdater.h \ @@ -143,6 +144,7 @@ SOURCES += \ cppqtstyleindenter.cpp \ cpprawprojectpart.cpp \ cpprefactoringchanges.cpp \ + cpprefactoringengine.cpp \ cppselectionchanger.cpp \ cppsemanticinfoupdater.cpp \ cppsourceprocessor.cpp \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index 3fc050744da..cad4da41a56 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -136,6 +136,8 @@ Project { "cpprawprojectpart.h", "cpprefactoringchanges.cpp", "cpprefactoringchanges.h", + "cpprefactoringengine.cpp", + "cpprefactoringengine.h", "cppselectionchanger.cpp", "cppselectionchanger.h", "cppsemanticinfo.h", diff --git a/src/plugins/cpptools/refactoringengineinterface.h b/src/plugins/cpptools/refactoringengineinterface.h index 85fee7ac3a7..afb6025c036 100644 --- a/src/plugins/cpptools/refactoringengineinterface.h +++ b/src/plugins/cpptools/refactoringengineinterface.h @@ -25,7 +25,9 @@ #pragma once +#include "cpptools_global.h" #include "cursorineditor.h" + #include #include @@ -46,7 +48,7 @@ enum class CallType }; // NOTE: This interface is not supposed to be owned as an interface pointer -class RefactoringEngineInterface +class CPPTOOLS_EXPORT RefactoringEngineInterface { public: using RenameCallback = ClangBackEnd::RefactoringClientInterface::RenameCallback; From 80a472740d62f0e0b1ffc177c75641691e99e213 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Sep 2017 12:35:24 +0200 Subject: [PATCH 55/63] TextEditor: move convenience from texteditor to utils Allows to use this header without texteditor dependency. Change-Id: I706f42799c3ea42473a716fa9ef9f3cfbef6fdd4 Reviewed-by: Nikolai Kosjar --- .../utils/textutils.cpp} | 10 +++---- .../convenience.h => libs/utils/textutils.h} | 30 +++++++++---------- src/libs/utils/utils-lib.pri | 6 ++-- src/libs/utils/utils.qbs | 2 ++ src/plugins/beautifier/beautifierplugin.cpp | 4 +-- .../clangcompletionassistprocessor.cpp | 7 ++--- .../clangcodemodel/clangdiagnosticmanager.cpp | 4 +-- .../clangeditordocumentprocessor.cpp | 16 +++++----- .../clangcodemodel/clangfollowsymbol.cpp | 8 ++--- src/plugins/cppeditor/cppeditorwidget.cpp | 6 ++-- src/plugins/cppeditor/cpphoverhandler.cpp | 6 ++-- .../cppeditor/cppuseselectionsupdater.cpp | 6 ++-- src/plugins/cpptools/builtincursorinfo.cpp | 6 ++-- .../builtineditordocumentprocessor.cpp | 4 +-- src/plugins/cpptools/cppcanonicalsymbol.cpp | 5 ++-- src/plugins/cpptools/cppcompletion_test.cpp | 5 ++-- src/plugins/cpptools/cppcompletionassist.cpp | 10 ++++--- .../cpptools/cppfollowsymbolundercursor.cpp | 9 +++--- src/plugins/cpptools/cppselectionchanger.cpp | 4 +-- src/plugins/cpptools/cpptoolsreuse.cpp | 4 +-- src/plugins/cpptools/doxygengenerator.cpp | 9 ++---- .../designercore/model/textmodifier.cpp | 5 ++-- .../texteditor/codeassist/assistinterface.cpp | 4 +-- src/plugins/texteditor/textdocument.cpp | 4 +-- src/plugins/texteditor/texteditor.cpp | 10 +++---- src/plugins/texteditor/texteditor.pro | 2 -- src/plugins/texteditor/texteditor.qbs | 2 -- 27 files changed, 89 insertions(+), 99 deletions(-) rename src/{plugins/texteditor/convenience.cpp => libs/utils/textutils.cpp} (97%) rename src/{plugins/texteditor/convenience.h => libs/utils/textutils.h} (64%) diff --git a/src/plugins/texteditor/convenience.cpp b/src/libs/utils/textutils.cpp similarity index 97% rename from src/plugins/texteditor/convenience.cpp rename to src/libs/utils/textutils.cpp index f18511d518e..65b7093c5a6 100644 --- a/src/plugins/texteditor/convenience.cpp +++ b/src/libs/utils/textutils.cpp @@ -23,14 +23,14 @@ ** ****************************************************************************/ -#include "convenience.h" +#include "textutils.h" #include #include #include -namespace TextEditor { -namespace Convenience { +namespace Utils { +namespace Text { bool convertPosition(const QTextDocument *document, int pos, int *line, int *column) { @@ -121,5 +121,5 @@ QTextCursor wordStartCursor(const QTextCursor &textCursor) return cursor; } -} // Util -} // TextEditor +} // Text +} // Utils diff --git a/src/plugins/texteditor/convenience.h b/src/libs/utils/textutils.h similarity index 64% rename from src/plugins/texteditor/convenience.h rename to src/libs/utils/textutils.h index f4302cd5f31..9e818842711 100644 --- a/src/plugins/texteditor/convenience.h +++ b/src/libs/utils/textutils.h @@ -25,30 +25,28 @@ #pragma once -#include "texteditor_global.h" +#include "utils_global.h" #include -QT_BEGIN_NAMESPACE -class QTextDocument; -class QTextCursor; -QT_END_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QTextDocument) +QT_FORWARD_DECLARE_CLASS(QTextCursor) -namespace TextEditor { -namespace Convenience { +namespace Utils { +namespace Text { // line is 1-based, column is 0-based -TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document, - int pos, - int *line, int *column); +QTCREATOR_UTILS_EXPORT bool convertPosition(const QTextDocument *document, + int pos, + int *line, int *column); -TEXTEDITOR_EXPORT QString textAt(QTextCursor tc, int pos, int length); +QTCREATOR_UTILS_EXPORT QString textAt(QTextCursor tc, int pos, int length); -TEXTEDITOR_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length); +QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length); -TEXTEDITOR_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor); +QTCREATOR_UTILS_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor); -TEXTEDITOR_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor); +QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor); -} // Util -} // TextEditor +} // Text +} // Utils diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index c6d30f4712b..c181a8e25ae 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -115,7 +115,8 @@ SOURCES += $$PWD/environment.cpp \ $$PWD/utilsicons.cpp \ $$PWD/guard.cpp \ $$PWD/highlightingitemdelegate.cpp \ - $$PWD/camelhumpmatcher.cpp + $$PWD/camelhumpmatcher.cpp \ + $$PWD/textutils.cpp win32:SOURCES += $$PWD/consoleprocess_win.cpp else:SOURCES += $$PWD/consoleprocess_unix.cpp @@ -244,7 +245,8 @@ HEADERS += \ $$PWD/../3rdparty/optional/optional.hpp \ $$PWD/qtcfallthrough.h \ $$PWD/highlightingitemdelegate.h \ - $$PWD/camelhumpmatcher.h + $$PWD/camelhumpmatcher.h \ + $$PWD/textutils.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/projectintropage.ui \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index c6e7f7c0395..56b1b31e608 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -232,6 +232,8 @@ Project { "textfieldcombobox.h", "textfileformat.cpp", "textfileformat.h", + "textutils.cpp", + "textutils.h", "treemodel.cpp", "treemodel.h", "treeviewcombobox.cpp", diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index e2715af1464..ec0065ed954 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -45,12 +45,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -169,7 +169,7 @@ QString sourceData(TextEditorWidget *editor, int startPos, int endPos) { return (startPos < 0) ? editor->toPlainText() - : Convenience::textAt(editor->textCursor(), startPos, (endPos - startPos)); + : Utils::Text::textAt(editor->textCursor(), startPos, (endPos - startPos)); } bool isAutoFormatApplicable(const Core::IDocument *document, diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 13d8f5531d8..e60ac37ec6c 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -52,6 +51,7 @@ #include #include +#include #include #include @@ -556,10 +556,7 @@ ClangCompletionAssistProcessor::extractLineColumn(int position) return {-1, -1}; int line = -1, column = -1; - TextEditor::Convenience::convertPosition(m_interface->textDocument(), - position, - &line, - &column); + ::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column); const QTextBlock block = m_interface->textDocument()->findBlock(position); column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1; return {line, column}; diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index 1dd003c7c11..eb43f6556ee 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -33,11 +33,11 @@ #include -#include #include #include #include +#include #include #include #include @@ -176,7 +176,7 @@ void addErrorSelections(const QVector &diagno ClangBackEnd::SourceLocationContainer toSourceLocation(QTextDocument *textDocument, int position) { int line, column; - if (TextEditor::Convenience::convertPosition(textDocument, position, &line, &column)) + if (Utils::Text::convertPosition(textDocument, position, &line, &column)) return ClangBackEnd::SourceLocationContainer(Utf8String(), line, column); return ClangBackEnd::SourceLocationContainer(); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 24d26adcfde..81053cef60e 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -47,7 +47,6 @@ #include #include -#include #include #include #include @@ -56,6 +55,7 @@ #include +#include #include #include @@ -253,10 +253,8 @@ void ClangEditorDocumentProcessor::updateHighlighting( static int currentLine(const TextEditor::AssistInterface &assistInterface) { int line, column; - TextEditor::Convenience::convertPosition(assistInterface.textDocument(), - assistInterface.position(), - &line, - &column); + ::Utils::Text::convertPosition(assistInterface.textDocument(), assistInterface.position(), + &line, &column); return line; } @@ -322,10 +320,10 @@ static QFuture defaultCursorInfoFuture() static bool convertPosition(const QTextCursor &textCursor, int *line, int *column) { - const bool converted = TextEditor::Convenience::convertPosition(textCursor.document(), - textCursor.position(), - line, - column); + const bool converted = ::Utils::Text::convertPosition(textCursor.document(), + textCursor.position(), + line, + column); QTC_CHECK(converted); return converted; } diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp index bffa6fbcbfb..66db810e4a4 100644 --- a/src/plugins/clangcodemodel/clangfollowsymbol.cpp +++ b/src/plugins/clangcodemodel/clangfollowsymbol.cpp @@ -26,11 +26,11 @@ #include "clangeditordocumentprocessor.h" #include "clangfollowsymbol.h" -#include #include #include +#include #include namespace ClangCodeModel { @@ -104,9 +104,9 @@ TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink( bool) { int lineNumber = 0, positionInBlock = 0; - QTextCursor cursor = TextEditor::Convenience::wordStartCursor(data.cursor()); - TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &lineNumber, - &positionInBlock); + QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor()); + Utils::Text::convertPosition(cursor.document(), cursor.position(), &lineNumber, + &positionInBlock); const uint line = lineNumber; const uint column = positionInBlock + 1; diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 1542c55691f..37f152fe58a 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -69,7 +69,6 @@ #include #include #include -#include #include #include #include @@ -81,6 +80,7 @@ #include #include #include +#include #include #include @@ -474,7 +474,7 @@ ProjectPart *CppEditorWidget::projectPart() const namespace { using ClangBackEnd::V2::SourceLocationContainer; -using TextEditor::Convenience::selectAt; +using Utils::Text::selectAt; QTextCharFormat occurrencesTextCharFormat() { @@ -910,7 +910,7 @@ void CppEditorWidget::onRefactorMarkerClicked(const RefactorMarker &marker) applyDeclDefLinkChanges(true); } else if (isClangFixItAvailableMarker(marker)) { int line, column; - if (Convenience::convertPosition(document(), marker.cursor.position(), &line, &column)) { + if (Utils::Text::convertPosition(document(), marker.cursor.position(), &line, &column)) { setTextCursor(marker.cursor); invokeAssist(TextEditor::QuickFix); } diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index 75b5913f17b..dcb182435d4 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -32,9 +32,9 @@ #include #include #include -#include #include +#include #include #include @@ -63,7 +63,7 @@ bool editorDocumentProcessorHasDiagnosticAt(TextEditorWidget *editorWidget, int { if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) { int line, column; - if (Convenience::convertPosition(editorWidget->document(), pos, &line, &column)) + if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column)) return processor->hasDiagnosticsAt(line, column); } @@ -77,7 +77,7 @@ void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget, { if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) { int line, column; - if (Convenience::convertPosition(editorWidget->document(), position, &line, &column)) { + if (Utils::Text::convertPosition(editorWidget->document(), position, &line, &column)) { auto layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(2); diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp index a254ed7eae7..5b8d1d27dfe 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp +++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp @@ -29,7 +29,7 @@ #include "cppeditordocument.h" #include -#include +#include #include #include @@ -76,7 +76,7 @@ void CppUseSelectionsUpdater::update(CallType callType) CppTools::CursorInfoParams params; params.semanticInfo = cppEditorWidget->semanticInfo(); - params.textCursor = TextEditor::Convenience::wordStartCursor(cppEditorWidget->textCursor()); + params.textCursor = Utils::Text::wordStartCursor(cppEditorWidget->textCursor()); if (callType == CallType::Asynchronous) { if (isSameIdentifierAsBefore(params.textCursor)) @@ -145,7 +145,7 @@ void CppUseSelectionsUpdater::onFindUsesFinished() if (m_runnerRevision != m_editorWidget->document()->revision()) return; if (m_runnerWordStartPosition - != TextEditor::Convenience::wordStartCursor(m_editorWidget->textCursor()).position()) { + != Utils::Text::wordStartCursor(m_editorWidget->textCursor()).position()) { return; } diff --git a/src/plugins/cpptools/builtincursorinfo.cpp b/src/plugins/cpptools/builtincursorinfo.cpp index 8902fa05ca9..17f40c7d26d 100644 --- a/src/plugins/cpptools/builtincursorinfo.cpp +++ b/src/plugins/cpptools/builtincursorinfo.cpp @@ -32,12 +32,11 @@ #include "cppsemanticinfo.h" #include "cpptoolsreuse.h" -#include - #include #include #include +#include #include #include @@ -346,8 +345,7 @@ QFuture BuiltinCursorInfo::run(const CursorInfoParams &cursorInfoPar const QTextCursor &textCursor = cursorInfoParams.textCursor; int line, column; - TextEditor::Convenience::convertPosition(textCursor.document(), textCursor.position(), - &line, &column); + Utils::Text::convertPosition(textCursor.document(), textCursor.position(), &line, &column); CanonicalSymbol canonicalSymbol(document, snapshot); QString expression; Scope *scope = canonicalSymbol.getScopeAndExpression(textCursor, &expression); diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp index 95f4932e085..bfdabe53629 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.cpp +++ b/src/plugins/cpptools/builtineditordocumentprocessor.cpp @@ -33,7 +33,6 @@ #include "cpptoolsreuse.h" #include "cppworkingcopy.h" -#include #include #include #include @@ -41,6 +40,7 @@ #include #include +#include #include #include @@ -105,7 +105,7 @@ CppTools::CheckSymbols *createHighlighter(const CPlusPlus::Document::Ptr &doc, typedef TextEditor::HighlightingResult Result; QList macroUses; - using TextEditor::Convenience::convertPosition; + using Utils::Text::convertPosition; // Get macro definitions foreach (const CPlusPlus::Macro& macro, doc->definedMacros()) { diff --git a/src/plugins/cpptools/cppcanonicalsymbol.cpp b/src/plugins/cpptools/cppcanonicalsymbol.cpp index 0532ae8b2d2..3f1869de63b 100644 --- a/src/plugins/cpptools/cppcanonicalsymbol.cpp +++ b/src/plugins/cpptools/cppcanonicalsymbol.cpp @@ -26,10 +26,11 @@ #include "cppcanonicalsymbol.h" #include -#include #include +#include + #include #include @@ -58,7 +59,7 @@ Scope *CanonicalSymbol::getScopeAndExpression(const QTextCursor &cursor, QString QTextCursor tc = cursor; int line, column; - TextEditor::Convenience::convertPosition(cursor.document(), tc.position(), &line, &column); + Utils::Text::convertPosition(cursor.document(), tc.position(), &line, &column); ++column; // 1-based line and 1-based column int pos = tc.position(); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index b4944763515..147ae4e4554 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -30,12 +30,12 @@ #include "cpptoolstestcase.h" #include -#include #include #include #include #include +#include #include #include @@ -127,8 +127,7 @@ public: const int pos = proposal.d->basePosition(); const int length = m_position - pos; - const QString prefix = Convenience::textAt(QTextCursor(m_textDocument), pos, - length); + const QString prefix = Utils::Text::textAt(QTextCursor(m_textDocument), pos, length); if (!prefix.isEmpty()) listmodel->filter(prefix); if (listmodel->isSortable(prefix)) diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index 3e1c19399e6..9b7cdc45127 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -38,11 +38,11 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -1091,7 +1091,7 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper() } int line = 0, column = 0; - Convenience::convertPosition(m_interface->textDocument(), startOfExpression, &line, &column); + Utils::Text::convertPosition(m_interface->textDocument(), startOfExpression, &line, &column); const QString fileName = m_interface->fileName(); return startCompletionInternal(fileName, line, column, expression, endOfExpression); } @@ -1124,7 +1124,8 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion() m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot()); int line = 0, column = 0; - Convenience::convertPosition(m_interface->textDocument(), m_interface->position(), &line, &column); + Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(), &line, + &column); Scope *scope = thisDocument->scopeAt(line, column); if (!scope) return false; @@ -2014,7 +2015,8 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q // get current line and column int lineSigned = 0, columnSigned = 0; - Convenience::convertPosition(m_interface->textDocument(), m_interface->position(), &lineSigned, &columnSigned); + Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(), + &lineSigned, &columnSigned); unsigned line = lineSigned, column = columnSigned; // find a scope that encloses the current location, starting from the lastVisibileSymbol diff --git a/src/plugins/cpptools/cppfollowsymbolundercursor.cpp b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp index b8ffce90ef6..ed82a3f9a84 100644 --- a/src/plugins/cpptools/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include @@ -493,8 +493,7 @@ Link FollowSymbolUnderCursor::findLink( int lineNumber = 0, positionInBlock = 0; QTextCursor cursor = data.cursor(); QTextDocument *document = cursor.document(); - TextEditor::Convenience::convertPosition(document, cursor.position(), &lineNumber, - &positionInBlock); + Utils::Text::convertPosition(document, cursor.position(), &lineNumber, &positionInBlock); const unsigned line = lineNumber; const unsigned column = positionInBlock + 1; @@ -703,8 +702,8 @@ Link FollowSymbolUnderCursor::findLink( } } else if (d->isUsingDeclaration()) { int tokenBeginLineNumber = 0, tokenBeginColumnNumber = 0; - TextEditor::Convenience::convertPosition(document, beginOfToken, &tokenBeginLineNumber, - &tokenBeginColumnNumber); + Utils::Text::convertPosition(document, beginOfToken, &tokenBeginLineNumber, + &tokenBeginColumnNumber); if (unsigned(tokenBeginLineNumber) > d->line() || (unsigned(tokenBeginLineNumber) == d->line() && unsigned(tokenBeginColumnNumber) > d->column())) { diff --git a/src/plugins/cpptools/cppselectionchanger.cpp b/src/plugins/cpptools/cppselectionchanger.cpp index cee56aa21f5..5ac29f97cac 100644 --- a/src/plugins/cpptools/cppselectionchanger.cpp +++ b/src/plugins/cpptools/cppselectionchanger.cpp @@ -25,7 +25,7 @@ #include "cppselectionchanger.h" -#include +#include #include #include @@ -34,7 +34,7 @@ #include using namespace CPlusPlus; -using namespace TextEditor::Convenience; +using namespace Utils::Text; enum { debug = false diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp index fcb3c8b878e..bd011c0c05d 100644 --- a/src/plugins/cpptools/cpptoolsreuse.cpp +++ b/src/plugins/cpptools/cpptoolsreuse.cpp @@ -32,11 +32,11 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -216,7 +216,7 @@ const Macro *findCanonicalMacro(const QTextCursor &cursor, Document::Ptr documen QTC_ASSERT(document, return 0); int line, column; - TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &line, &column); + Utils::Text::convertPosition(cursor.document(), cursor.position(), &line, &column); if (const Macro *macro = document->findMacroDefinitionAt(line)) { QTextCursor macroCursor = cursor; diff --git a/src/plugins/cpptools/doxygengenerator.cpp b/src/plugins/cpptools/doxygengenerator.cpp index e94ce3468e0..39e2e252757 100644 --- a/src/plugins/cpptools/doxygengenerator.cpp +++ b/src/plugins/cpptools/doxygengenerator.cpp @@ -25,11 +25,10 @@ #include "doxygengenerator.h" -#include - #include #include +#include #include #include @@ -73,10 +72,8 @@ void DoxygenGenerator::setAddLeadingAsterisks(bool add) static int lineBeforeCursor(const QTextCursor &cursor) { int line, column; - const bool converted = TextEditor::Convenience::convertPosition(cursor.document(), - cursor.position(), - &line, - &column); + const bool converted = Utils::Text::convertPosition(cursor.document(), cursor.position(), &line, + &column); QTC_ASSERT(converted, return std::numeric_limits::max()); return line - 1; diff --git a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp index 8b5ea35ff1c..9016619f6db 100644 --- a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp @@ -26,7 +26,8 @@ #include "textmodifier.h" #include -#include + +#include using namespace QmlDesigner; @@ -38,7 +39,7 @@ int TextModifier::getLineInDocument(QTextDocument *document, int offset) { int line = -1; int column = -1; - TextEditor::Convenience::convertPosition(document, offset, &line, &column); + Utils::Text::convertPosition(document, offset, &line, &column); return line; } diff --git a/src/plugins/texteditor/codeassist/assistinterface.cpp b/src/plugins/texteditor/codeassist/assistinterface.cpp index 42670678895..3577718dfb4 100644 --- a/src/plugins/texteditor/codeassist/assistinterface.cpp +++ b/src/plugins/texteditor/codeassist/assistinterface.cpp @@ -91,7 +91,7 @@ using namespace TextEditor; #include "assistinterface.h" -#include +#include #include #include @@ -125,7 +125,7 @@ QChar AssistInterface::characterAt(int position) const QString AssistInterface::textAt(int pos, int length) const { - return Convenience::textAt(QTextCursor(m_textDocument), pos, length); + return Utils::Text::textAt(QTextCursor(m_textDocument), pos, length); } void AssistInterface::prepareForAsyncUse() diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index 7c53c812962..1bb79b9e83a 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -25,7 +25,6 @@ #include "textdocument.h" -#include "convenience.h" #include "extraencodingsettings.h" #include "fontsettings.h" #include "indenter.h" @@ -39,6 +38,7 @@ #include #include #include +#include #include #include @@ -303,7 +303,7 @@ QString TextDocument::plainText() const QString TextDocument::textAt(int pos, int length) const { - return Convenience::textAt(QTextCursor(document()), pos, length); + return Utils::Text::textAt(QTextCursor(document()), pos, length); } QChar TextDocument::characterAt(int pos) const diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 34594795670..48a28707204 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -37,7 +37,6 @@ #include "circularclipboardassist.h" #include "codecselector.h" #include "completionsettings.h" -#include "convenience.h" #include "highlighterutils.h" #include "icodestylepreferences.h" #include "indenter.h" @@ -77,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -267,7 +267,7 @@ public: // Does the last handler still applies? const int documentRevision = textCursor.document()->revision(); - const int position = Convenience::wordStartCursor(textCursor).position(); + const int position = Text::wordStartCursor(textCursor).position(); if (m_lastHandlerInfo.applies(documentRevision, position)) { m_lastHandlerInfo.handler->showToolTip(m_widget, point, /*decorate=*/ false); return; @@ -1448,7 +1448,7 @@ bool TextEditorWidget::selectBlockUp() if (!TextBlockUserData::findNextClosingParenthesis(&cursor, true)) return false; - setTextCursor(Convenience::flippedCursor(cursor)); + setTextCursor(Text::flippedCursor(cursor)); d->_q_matchParentheses(); return true; } @@ -1473,7 +1473,7 @@ bool TextEditorWidget::selectBlockDown() if ( cursor != d->m_selectBlockAnchor) TextBlockUserData::findNextClosingParenthesis(&cursor, true); - setTextCursor(Convenience::flippedCursor(cursor)); + setTextCursor(Text::flippedCursor(cursor)); d->_q_matchParentheses(); return true; } @@ -2802,7 +2802,7 @@ QRect TextEditorWidget::cursorRect(int pos) const void TextEditorWidget::convertPosition(int pos, int *line, int *column) const { - Convenience::convertPosition(document(), pos, line, column); + Text::convertPosition(document(), pos, line, column); } bool TextEditorWidget::event(QEvent *e) diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro index 1ef00e05174..d83d1654432 100644 --- a/src/plugins/texteditor/texteditor.pro +++ b/src/plugins/texteditor/texteditor.pro @@ -77,7 +77,6 @@ SOURCES += texteditorplugin.cpp \ snippets/snippetassistcollector.cpp \ codeassist/assistinterface.cpp \ codeassist/assistproposalitem.cpp \ - convenience.cpp \ codeassist/runner.cpp \ codeassist/completionassistprovider.cpp \ codeassist/genericproposalmodel.cpp \ @@ -187,7 +186,6 @@ HEADERS += texteditorplugin.h \ snippets/snippetassistcollector.h \ codeassist/assistinterface.h \ codeassist/assistproposalitem.h \ - convenience.h \ codeassist/assistenums.h \ codeassist/runner.h \ codeassist/assistproposaliteminterface.h \ diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index 2b5f43e2478..1dfbde68a85 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -58,8 +58,6 @@ Project { "completionsettingspage.cpp", "completionsettingspage.h", "completionsettingspage.ui", - "convenience.cpp", - "convenience.h", "displaysettings.cpp", "displaysettings.h", "displaysettingspage.cpp", From 736e568d942ead4bd3bddd40eeb3d58775a0c33b Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Fri, 22 Sep 2017 15:51:45 +0200 Subject: [PATCH 56/63] Clang: fix clang version extracting In case it has string ending. Example: 5.0.0svn Change-Id: Ie3e154f389a515290e4b09d0fe21e23b9e4c7558 Reviewed-by: Nikolai Kosjar --- src/shared/clang/clang_installation.pri | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri index 517ded4e4b4..f7428c0be3c 100644 --- a/src/shared/clang/clang_installation.pri +++ b/src/shared/clang/clang_installation.pri @@ -3,10 +3,10 @@ LLVM_INSTALL_DIR = $$clean_path($$LLVM_INSTALL_DIR) isEmpty(LLVM_INSTALL_DIR): error("No LLVM_INSTALL_DIR provided") !exists($$LLVM_INSTALL_DIR): error("LLVM_INSTALL_DIR does not exist: $$LLVM_INSTALL_DIR") -defineReplace(extractVersion) { return($$replace(1, ^(\\d+\\.\\d+\\.\\d+)$, \\1)) } -defineReplace(extractMajorVersion) { return($$replace(1, ^(\\d+)\\.\\d+\\.\\d+$, \\1)) } -defineReplace(extractMinorVersion) { return($$replace(1, ^\\d+\\.(\\d+)\\.\\d+$, \\1)) } -defineReplace(extractPatchVersion) { return($$replace(1, ^\\d+\\.\\d+\\.(\\d+)$, \\1)) } +defineReplace(extractVersion) { return($$replace(1, ^(\\d+\\.\\d+\\.\\d+)\\w*$, \\1)) } +defineReplace(extractMajorVersion) { return($$replace(1, ^(\\d+)\\.\\d+\\.\\d+\\w*$, \\1)) } +defineReplace(extractMinorVersion) { return($$replace(1, ^\\d+\\.(\\d+)\\.\\d+\\w*$, \\1)) } +defineReplace(extractPatchVersion) { return($$replace(1, ^\\d+\\.\\d+\\.(\\d+)\\w*$, \\1)) } defineTest(versionIsAtLeast) { actual_major_version = $$extractMajorVersion($$1) From 68a49c79da0ae709e2e4e0fd6584587a6e2d8473 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Mon, 11 Sep 2017 14:08:00 +0200 Subject: [PATCH 57/63] Clang: Unify compiler options builders Make build command the same for all builders. Minimize differences. Change-Id: I1cfe5071b3afb4944ed178fff1e57d3aee45d8a9 Reviewed-by: Nikolai Kosjar --- scripts/deployqt.py | 2 - src/plugins/clangcodemodel/clangutils.cpp | 47 ++--- .../clangpchmanager/projectupdater.cpp | 32 +--- .../clangqueryprojectsfindfilter.cpp | 27 +-- .../clangrefactoring/refactoringengine.cpp | 8 +- ...taticanalyzerpreconfiguredsessiontests.cpp | 2 +- .../clangstaticanalyzerruncontrol.cpp | 170 +++--------------- .../clangstaticanalyzerunittests.cpp | 2 +- .../clangstaticanalyzerutils.cpp | 10 +- .../clangstaticanalyzerutils.h | 2 +- .../cpptools/clangcompileroptionsbuilder.cpp | 117 ++++++------ .../cpptools/clangcompileroptionsbuilder.h | 27 +-- .../cpptools/compileroptionsbuilder.cpp | 17 +- src/plugins/cpptools/compileroptionsbuilder.h | 4 +- .../unit/unittest/refactoringengine-test.cpp | 10 +- 15 files changed, 120 insertions(+), 357 deletions(-) diff --git a/scripts/deployqt.py b/scripts/deployqt.py index 8e7fa8ba47a..5559587f990 100755 --- a/scripts/deployqt.py +++ b/scripts/deployqt.py @@ -223,8 +223,6 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin): os.path.join(install_dir, 'bin'))) deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang.exe'), clangbindirtarget)) - deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang-cl.exe'), - clangbindirtarget)) resourcetarget = os.path.join(clanglibdirtarget, 'clang') else: libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*')) diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index e436ec275fb..0058ee4023b 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -70,46 +70,21 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, const QString &fil return createClangOptions(pPart, fileKind); } -class LibClangOptionsBuilder : public ClangCompilerOptionsBuilder +class LibClangOptionsBuilder final : public ClangCompilerOptionsBuilder { public: - static QStringList build(const ProjectPart::Ptr &projectPart, ProjectFile::Kind fileKind) - { - if (projectPart.isNull()) - return QStringList(); - - LibClangOptionsBuilder optionsBuilder(*projectPart.data()); - - optionsBuilder.addWordWidth(); - optionsBuilder.addTargetTriple(); - optionsBuilder.addLanguageOption(fileKind); - optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); - optionsBuilder.enableExceptions(); - - optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); - optionsBuilder.addDefineFloat128ForMingw(); - optionsBuilder.addToolchainAndProjectDefines(); - optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); - - optionsBuilder.addPredefinedMacrosAndHeaderPathsOptions(); - optionsBuilder.addWrappedQtHeadersIncludePath(); - optionsBuilder.addHeaderPathOptions(); - optionsBuilder.addDummyUiHeaderOnDiskIncludePath(); - optionsBuilder.addProjectConfigFileInclude(); - - optionsBuilder.addMsvcCompatibilityVersion(); - - optionsBuilder.addExtraOptions(); - - return optionsBuilder.options(); - } - -private: - LibClangOptionsBuilder(const CppTools::ProjectPart &projectPart) + LibClangOptionsBuilder(const ProjectPart &projectPart) : ClangCompilerOptionsBuilder(projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR) { } + void addExtraOptions() final + { + addDummyUiHeaderOnDiskIncludePath(); + ClangCompilerOptionsBuilder::addExtraOptions(); + } + +private: void addDummyUiHeaderOnDiskIncludePath() { const QString path = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskDirPath(); @@ -125,7 +100,9 @@ private: */ QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind fileKind) { - return LibClangOptionsBuilder::build(pPart, fileKind); + if (!pPart) + return QStringList(); + return LibClangOptionsBuilder(*pPart).build(fileKind, CompilerOptionsBuilder::PchUsage::None); } ProjectPart::Ptr projectPartForFile(const QString &filePath) diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp index 046c5f769fc..8327f85a221 100644 --- a/src/plugins/clangpchmanager/projectupdater.cpp +++ b/src/plugins/clangpchmanager/projectupdater.cpp @@ -108,35 +108,9 @@ HeaderAndSources ProjectUpdater::headerAndSourcesFromProjectPart( QStringList ProjectUpdater::compilerArguments(CppTools::ProjectPart *projectPart) { - using CppTools::ClangCompilerOptionsBuilder; - - ClangCompilerOptionsBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR); - - builder.addWordWidth(); - builder.addTargetTriple(); - builder.addLanguageOption(CppTools::ProjectFile::CXXHeader); - builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); - builder.enableExceptions(); - - builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); - builder.addDefineFloat128ForMingw(); - builder.addToolchainAndProjectDefines(); - builder.undefineCppLanguageFeatureMacrosForMsvc2015(); - - builder.addPredefinedMacrosAndHeaderPathsOptions(); - builder.addWrappedQtHeadersIncludePath(); - builder.addPrecompiledHeaderOptions(ClangCompilerOptionsBuilder::PchUsage::None); - builder.addHeaderPathOptions(); - builder.addProjectConfigFileInclude(); - - builder.addMsvcCompatibilityVersion(); - - builder.add("-fmessage-length=0"); - builder.add("-fmacro-backtrace-limit=0"); - builder.add("-w"); - builder.add("-ferror-limit=100000"); - - return builder.options(); + using ClangCOBuilder = CppTools::ClangCompilerOptionsBuilder; + ClangCOBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR); + return builder.build(CppTools::ProjectFile::CXXHeader, ClangCOBuilder::PchUsage::None); } ClangBackEnd::V2::ProjectPartContainer ProjectUpdater::toProjectPartContainer( diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp index d4e210c04e8..14d8a1620ec 100644 --- a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp @@ -155,31 +155,8 @@ Utils::SmallStringVector ClangQueryProjectsFindFilter::compilerArguments(CppTool ClangCompilerOptionsBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR); - builder.addWordWidth(); - builder.addTargetTriple(); - builder.addLanguageOption(fileKind); - builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); - builder.enableExceptions(); - - builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); - builder.addDefineFloat128ForMingw(); - builder.addToolchainAndProjectDefines(); - builder.undefineCppLanguageFeatureMacrosForMsvc2015(); - - builder.addPredefinedMacrosAndHeaderPathsOptions(); - builder.addWrappedQtHeadersIncludePath(); - builder.addPrecompiledHeaderOptions(ClangCompilerOptionsBuilder::PchUsage::None); - builder.addHeaderPathOptions(); - builder.addProjectConfigFileInclude(); - - builder.addMsvcCompatibilityVersion(); - - builder.add("-fmessage-length=0"); - builder.add("-fmacro-backtrace-limit=0"); - builder.add("-w"); - builder.add("-ferror-limit=1000000"); - - return Utils::SmallStringVector(builder.options()); + return Utils::SmallStringVector(builder.build(fileKind, + ClangCompilerOptionsBuilder::PchUsage::None)); } QWidget *ClangQueryProjectsFindFilter::widget() const diff --git a/src/plugins/clangrefactoring/refactoringengine.cpp b/src/plugins/clangrefactoring/refactoringengine.cpp index 1d964fe8938..696e38c468c 100644 --- a/src/plugins/clangrefactoring/refactoringengine.cpp +++ b/src/plugins/clangrefactoring/refactoringengine.cpp @@ -64,12 +64,10 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data, QString filePath = data.filePath().toString(); QTextCursor textCursor = data.cursor(); - Utils::SmallStringVector commandLine{ClangCompilerOptionsBuilder::build( - projectPart, + ClangCompilerOptionsBuilder clangCOBuilder{*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR}; + Utils::SmallStringVector commandLine{clangCOBuilder.build( fileKindInProjectPart(projectPart, filePath), - CppTools::getPchUsage(), - CLANG_VERSION, - CLANG_RESOURCE_DIR)}; + CppTools::getPchUsage())}; commandLine.push_back(filePath); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp index 0cb7c976ee1..c9ff00558db 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp @@ -167,7 +167,7 @@ static QList validTargets(Project *project) const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); QTC_ASSERT(toolchain, return false); bool hasClangExecutable; - clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable); + clangExecutableFromSettings(&hasClangExecutable); if (!hasClangExecutable) { qWarning("Project \"%s\": Skipping target \"%s\" since no suitable clang was found for the toolchain.", qPrintable(projectFileName), diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 0cfafa08e11..94468e913e4 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include #include @@ -161,8 +161,7 @@ static void prependTargetTripleIfNotIncludedAndNotEmpty(QStringList *arguments, } // Removes (1) inputFile (2) -o . -QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStringList &arguments, - bool isMsvc) +QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStringList &arguments) { QStringList newArguments; @@ -174,9 +173,6 @@ QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStri } else if (argument == QLatin1String("-o")) { skip = true; continue; - } else if (isMsvc && argument == QLatin1String("-target")) { - skip = true; - continue; } else if (QDir::fromNativeSeparators(argument) == inputFile) { continue; // TODO: Let it in? } @@ -188,55 +184,11 @@ QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStri return newArguments; } -static QString createLanguageOptionMsvc(ProjectFile::Kind fileKind) -{ - switch (fileKind) { - case ProjectFile::CHeader: - case ProjectFile::CSource: - return QLatin1String("/TC"); - break; - case ProjectFile::CXXHeader: - case ProjectFile::CXXSource: - return QLatin1String("/TP"); - break; - default: - break; - } - return QString(); -} - -class ClangStaticAnalyzerOptionsBuilder : public CompilerOptionsBuilder +class ClangStaticAnalyzerOptionsBuilder final : public ClangCompilerOptionsBuilder { public: - static QStringList build(const CppTools::ProjectPart &projectPart, - CppTools::ProjectFile::Kind fileKind, - PchUsage pchUsage) - { - ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart); - - optionsBuilder.addWordWidth(); - optionsBuilder.addTargetTriple(); - optionsBuilder.addLanguageOption(fileKind); - optionsBuilder.addOptionsForLanguage(false); - optionsBuilder.enableExceptions(); - - optionsBuilder.addDefineFloat128ForMingw(); - optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); - const Core::Id type = projectPart.toolchainType; - if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) - optionsBuilder.addMacros(projectPart.toolChainMacros); - optionsBuilder.addMacros(projectPart.projectMacros); - optionsBuilder.undefineClangVersionMacrosForMsvc(); - optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); - optionsBuilder.addHeaderPathOptions(); - optionsBuilder.addPrecompiledHeaderOptions(pchUsage); - optionsBuilder.addMsvcCompatibilityVersion(); - - return optionsBuilder.options(); - } - ClangStaticAnalyzerOptionsBuilder(const CppTools::ProjectPart &projectPart) - : CompilerOptionsBuilder(projectPart) + : ClangCompilerOptionsBuilder(projectPart) , m_isMsvcToolchain(m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) , m_isMinGWToolchain(m_projectPart.toolchainType @@ -244,91 +196,28 @@ public: { } -public: - bool excludeHeaderPath(const QString &headerPath) const override + bool excludeHeaderPath(const QString &headerPath) const final { - if (CompilerOptionsBuilder::excludeHeaderPath(headerPath)) - return true; if (m_isMinGWToolchain && headerPath.contains(m_projectPart.toolChainTargetTriple)) return true; - return false; + return ClangCompilerOptionsBuilder::excludeHeaderPath(headerPath); } - void undefineClangVersionMacrosForMsvc() + void addPredefinedHeaderPathsOptions() final { - if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) { - static QStringList macroNames { - "__clang__", - "__clang_major__", - "__clang_minor__", - "__clang_patchlevel__", - "__clang_version__" - }; - - foreach (const QString ¯oName, macroNames) - add(QLatin1String("/U") + macroName); + add("-undef"); + if (m_isMsvcToolchain) { + // exclude default clang path to use msvc includes + add("-nostdinc"); + add("-nostdlibinc"); } } -private: - void addTargetTriple() override - { - // For MSVC toolchains we use clang-cl.exe, so there is nothing to do here since - // 1) clang-cl.exe does not understand the "-triple" option - // 2) clang-cl.exe already hardcodes the right triple value (even if built with mingw) - if (!m_isMsvcToolchain) - CompilerOptionsBuilder::addTargetTriple(); - } + void addExtraOptions() final {} - void addLanguageOption(ProjectFile::Kind fileKind) override + void addWrappedQtHeadersIncludePath() final { - if (m_isMsvcToolchain) - add(createLanguageOptionMsvc(fileKind)); - else - CompilerOptionsBuilder::addLanguageOption(fileKind); - } - - void addOptionsForLanguage(bool checkForBorlandExtensions) override - { - if (m_isMsvcToolchain) - return; - CompilerOptionsBuilder::addOptionsForLanguage(checkForBorlandExtensions); - } - - QString includeOption() const override - { - if (m_isMsvcToolchain) - return QLatin1String("/FI"); - return CompilerOptionsBuilder::includeOption(); - } - - QString includeDirOption() const override - { - if (m_isMsvcToolchain) - return QLatin1String("/I"); - return CompilerOptionsBuilder::includeDirOption(); - } - - QString defineOption() const override - { - if (m_isMsvcToolchain) - return QLatin1String("/D"); - return CompilerOptionsBuilder::defineOption(); - } - - QString undefineOption() const override - { - if (m_isMsvcToolchain) - return QLatin1String("/U"); - return CompilerOptionsBuilder::undefineOption(); - } - - void enableExceptions() override - { - if (m_isMsvcToolchain) - add(QLatin1String("/EHsc")); - else - CompilerOptionsBuilder::enableExceptions(); + // Empty, analyzer doesn't need them } private: @@ -383,7 +272,7 @@ static QStringList tweakedArguments(const ProjectPart &projectPart, { const bool isMsvc = projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID; - QStringList newArguments = inputAndOutputArgumentsRemoved(filePath, arguments, isMsvc); + QStringList newArguments = inputAndOutputArgumentsRemoved(filePath, arguments); prependWordWidthArgumentIfNotIncluded(&newArguments, projectPart.toolChainWordWidth); if (!isMsvc) prependTargetTripleIfNotIncludedAndNotEmpty(&newArguments, targetTriple); @@ -434,7 +323,7 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVectorselectedForBuilding) + if (!projectPart->selectedForBuilding || !projectPart.data()) continue; foreach (const ProjectFile &file, projectPart->files) { @@ -445,7 +334,7 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVectortypeId(), &hasClangExecutable); + clangExecutableFromSettings(&hasClangExecutable); if (!hasClangExecutable) QSKIP("No clang suitable for analyzing found"); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp index 073adac6798..7a433aac49f 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp @@ -50,7 +50,7 @@ static bool isFileExecutable(const QString &executablePath) namespace ClangStaticAnalyzer { namespace Internal { -QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid) +QString clangExecutableFromSettings(bool *isValid) { QString executable = ClangStaticAnalyzerSettings::instance()->clangExecutable(); if (executable.isEmpty()) { @@ -62,14 +62,6 @@ QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid) const Qt::CaseSensitivity caseSensitivity = Utils::HostOsInfo::fileNameCaseSensitivity(); const bool hasSuffix = executable.endsWith(hostExeSuffix, caseSensitivity); - if (toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) { - if (hasSuffix) - executable.chop(hostExeSuffix.length()); - executable.append(QLatin1String("-cl")); - if (hasSuffix) - executable.append(hostExeSuffix); - } - const QFileInfo fileInfo = QFileInfo(executable); if (fileInfo.isAbsolute()) { if (!hasSuffix) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h index e170d8b7f01..c18317237c6 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h @@ -41,7 +41,7 @@ namespace Internal { bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0); -QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid); +QString clangExecutableFromSettings(bool *isValid); QString createFullLocationString(const Debugger::DiagnosticLocation &location); diff --git a/src/plugins/cpptools/clangcompileroptionsbuilder.cpp b/src/plugins/cpptools/clangcompileroptionsbuilder.cpp index 160bf6b4c6c..0b2209cc628 100644 --- a/src/plugins/cpptools/clangcompileroptionsbuilder.cpp +++ b/src/plugins/cpptools/clangcompileroptionsbuilder.cpp @@ -26,7 +26,6 @@ #include "clangcompileroptionsbuilder.h" #include - #include #include @@ -37,6 +36,15 @@ namespace CppTools { static QString creatorResourcePath() { +#ifndef UNIT_TESTS + return Core::ICore::instance()->resourcePath(); +#else + return QString(); +#endif +} + +static QString creatorLibexecPath() +{ #ifndef UNIT_TESTS return Core::ICore::instance()->libexecPath(); #else @@ -44,40 +52,31 @@ static QString creatorResourcePath() #endif } -QStringList ClangCompilerOptionsBuilder::build(const CppTools::ProjectPart *projectPart, - CppTools::ProjectFile::Kind fileKind, - PchUsage pchUsage, - const QString &clangVersion, - const QString &clangResourceDirectory) +QStringList ClangCompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind, + PchUsage pchUsage) { - if (projectPart) { - ClangCompilerOptionsBuilder builder(*projectPart, clangVersion, clangResourceDirectory); + addWordWidth(); + addTargetTriple(); + addLanguageOption(fileKind); + addOptionsForLanguage(/*checkForBorlandExtensions*/ true); + enableExceptions(); - builder.addWordWidth(); - builder.addTargetTriple(); - builder.addLanguageOption(fileKind); - builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); - builder.enableExceptions(); + addDefineFloat128ForMingw(); + addToolchainAndProjectMacros(); + undefineClangVersionMacrosForMsvc(); + undefineCppLanguageFeatureMacrosForMsvc2015(); - builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); - builder.addDefineFloat128ForMingw(); - builder.addToolchainAndProjectDefines(); - builder.undefineCppLanguageFeatureMacrosForMsvc2015(); + addPredefinedHeaderPathsOptions(); + addWrappedQtHeadersIncludePath(); + addPrecompiledHeaderOptions(pchUsage); + addHeaderPathOptions(); + addProjectConfigFileInclude(); - builder.addPredefinedMacrosAndHeaderPathsOptions(); - builder.addWrappedQtHeadersIncludePath(); - builder.addPrecompiledHeaderOptions(pchUsage); - builder.addHeaderPathOptions(); - builder.addProjectConfigFileInclude(); + addMsvcCompatibilityVersion(); - builder.addMsvcCompatibilityVersion(); + addExtraOptions(); - builder.addExtraOptions(); - - return builder.options(); - } - - return QStringList(); + return options(); } ClangCompilerOptionsBuilder::ClangCompilerOptionsBuilder(const CppTools::ProjectPart &projectPart, @@ -91,47 +90,35 @@ ClangCompilerOptionsBuilder::ClangCompilerOptionsBuilder(const CppTools::Project bool ClangCompilerOptionsBuilder::excludeHeaderPath(const QString &path) const { - if (m_projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) { - if (path.contains("lib/gcc/i686-apple-darwin")) - return true; + if (m_projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID + && path.contains("lib/gcc/i686-apple-darwin")) { + return true; } return CompilerOptionsBuilder::excludeHeaderPath(path); } -void ClangCompilerOptionsBuilder::addPredefinedMacrosAndHeaderPathsOptions() +void ClangCompilerOptionsBuilder::addPredefinedHeaderPathsOptions() { - if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) - addPredefinedMacrosAndHeaderPathsOptionsForMsvc(); - else - addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc(); -} - -void ClangCompilerOptionsBuilder::addPredefinedMacrosAndHeaderPathsOptionsForMsvc() -{ - add("-nostdinc"); add("-undef"); -} + add("-nostdinc"); + add("-nostdlibinc"); -void ClangCompilerOptionsBuilder::addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc() -{ - static const QString resourceDir = clangIncludeDirectory(); - if (QTC_GUARD(!resourceDir.isEmpty())) { - add("-nostdlibinc"); - add("-I" + QDir::toNativeSeparators(resourceDir)); - add("-undef"); - } + if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) + add(includeDirOption() + clangIncludeDirectory()); } void ClangCompilerOptionsBuilder::addWrappedQtHeadersIncludePath() { - static const QString wrappedQtHeadersPath = creatorResourcePath() - + "/cplusplus/wrappedQtHeaders"; + static const QString resourcePath = creatorResourcePath(); + static QString wrappedQtHeadersPath = resourcePath + "/cplusplus/wrappedQtHeaders"; + QDir dir(wrappedQtHeadersPath); + QTC_ASSERT(QDir(wrappedQtHeadersPath).exists(), return;); if (m_projectPart.qtVersion != CppTools::ProjectPart::NoQt) { const QString wrappedQtCoreHeaderPath = wrappedQtHeadersPath + "/QtCore"; - add("-I" + QDir::toNativeSeparators(wrappedQtHeadersPath)); - add("-I" + QDir::toNativeSeparators(wrappedQtCoreHeaderPath)); + add(includeDirOption() + QDir::toNativeSeparators(wrappedQtHeadersPath)); + add(includeDirOption() + QDir::toNativeSeparators(wrappedQtCoreHeaderPath)); } } @@ -154,12 +141,26 @@ void ClangCompilerOptionsBuilder::addExtraOptions() QString ClangCompilerOptionsBuilder::clangIncludeDirectory() const { - QDir dir(creatorResourcePath() + "/clang/lib/clang/" + m_clangVersion + "/include"); - + QDir dir(creatorLibexecPath() + "/clang/lib/clang/" + m_clangVersion + "/include"); if (!dir.exists() || !QFileInfo(dir, "stdint.h").exists()) dir = QDir(m_clangResourceDirectory); + return QDir::toNativeSeparators(dir.canonicalPath()); +} - return dir.canonicalPath(); +void ClangCompilerOptionsBuilder::undefineClangVersionMacrosForMsvc() +{ + if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) { + static QStringList macroNames { + "__clang__", + "__clang_major__", + "__clang_minor__", + "__clang_patchlevel__", + "__clang_version__" + }; + + foreach (const QString ¯oName, macroNames) + add(undefineOption() + macroName); + } } } // namespace CppTools diff --git a/src/plugins/cpptools/clangcompileroptionsbuilder.h b/src/plugins/cpptools/clangcompileroptionsbuilder.h index 4dadb6bed96..fbe2a5baad2 100644 --- a/src/plugins/cpptools/clangcompileroptionsbuilder.h +++ b/src/plugins/cpptools/clangcompileroptionsbuilder.h @@ -34,33 +34,24 @@ namespace CppTools { class CPPTOOLS_EXPORT ClangCompilerOptionsBuilder : public CompilerOptionsBuilder { public: - static QStringList build(const ProjectPart *projectPart, - ProjectFile::Kind fileKind, - PchUsage pchUsage, - const QString &clangVersion, - const QString &clangResourceDirectory); + QStringList build(ProjectFile::Kind fileKind, + PchUsage pchUsage); ClangCompilerOptionsBuilder(const ProjectPart &projectPart, - const QString &clangVersion, - const QString &clangResourceDirectory); + const QString &clangVersion = QString(), + const QString &clangResourceDirectory = QString()); + + virtual void addPredefinedHeaderPathsOptions(); + virtual void addExtraOptions(); bool excludeHeaderPath(const QString &path) const override; - void addPredefinedMacrosAndHeaderPathsOptions(); - - void addPredefinedMacrosAndHeaderPathsOptionsForMsvc(); - - void addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc(); - - void addWrappedQtHeadersIncludePath(); - + virtual void addWrappedQtHeadersIncludePath(); void addProjectConfigFileInclude(); - void addExtraOptions(); + void undefineClangVersionMacrosForMsvc(); private: QString clangIncludeDirectory() const; - -private: QString m_clangVersion; QString m_clangResourceDirectory; }; diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 079f76fc6aa..88a85e17cda 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -125,7 +125,7 @@ void CompilerOptionsBuilder::addPrecompiledHeaderOptions(PchUsage pchUsage) m_options.append(result); } -void CompilerOptionsBuilder::addToolchainAndProjectDefines() +void CompilerOptionsBuilder::addToolchainAndProjectMacros() { addMacros(m_projectPart.toolChainMacros); addMacros(m_projectPart.projectMacros); @@ -258,21 +258,6 @@ void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtension m_options.append(opts); } -void CompilerOptionsBuilder::addDefineToAvoidIncludingGccOrMinGwIntrinsics() -{ - // In gcc headers, lots of built-ins are referenced that clang does not understand. - // Therefore, prevent the inclusion of the header that references them. Of course, this - // will break if code actually requires stuff from there, but that should be the less common - // case. - - const Core::Id type = m_projectPart.toolchainType; - if (type == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID - || type == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID) { - addDefine({"_X86INTRIN_H_INCLUDED"}); - addDefine({"BOOST_UUID_NO_SIMD"}); - } -} - static QByteArray toMsCompatibilityVersionFormat(const QByteArray &mscFullVer) { return mscFullVer.left(2) diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index 48c23b3e912..8ca985dc28c 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -54,13 +54,11 @@ public: virtual void enableExceptions(); void addHeaderPathOptions(); void addPrecompiledHeaderOptions(PchUsage pchUsage); - void addToolchainAndProjectDefines(); + void addToolchainAndProjectMacros(); void addMacros(const ProjectExplorer::Macros ¯os); virtual void addLanguageOption(ProjectFile::Kind fileKind); virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true); - void addDefineToAvoidIncludingGccOrMinGwIntrinsics(); - void addMsvcCompatibilityVersion(); void undefineCppLanguageFeatureMacrosForMsvc2015(); diff --git a/tests/unit/unittest/refactoringengine-test.cpp b/tests/unit/unittest/refactoringengine-test.cpp index 7367a33cdf2..a4f7d32d04a 100644 --- a/tests/unit/unittest/refactoringengine-test.cpp +++ b/tests/unit/unittest/refactoringengine-test.cpp @@ -129,12 +129,12 @@ void RefactoringEngine::SetUp() projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); projectPart->files.push_back(projectFile); - commandLine = Utils::SmallStringVector(ClangCompilerOptionsBuilder::build( - projectPart.data(), - projectFile.kind, - CppTools::CompilerOptionsBuilder::PchUsage::None, + ClangCompilerOptionsBuilder clangCOBuilder(*projectPart, CLANG_VERSION, - CLANG_RESOURCE_DIR)); + CLANG_RESOURCE_DIR); + commandLine = Utils::SmallStringVector(clangCOBuilder.build( + projectFile.kind, + CppTools::CompilerOptionsBuilder::PchUsage::None)); commandLine.push_back(qStringFilePath); } From 100cd10d6ececb014a0541f45b1a580bcf557e10 Mon Sep 17 00:00:00 2001 From: Claus Steuer Date: Sun, 17 Sep 2017 20:01:41 +0200 Subject: [PATCH 58/63] CMake: Set CMakeRunConfiguration executable and working directory Since 131c7a1 the executable and base working directory property of CMakeRunConfiguration objects is no longer set when the project data is updated. At least the executable is required in the AutoTest plugin. Change-Id: I31c4cb37983d3983664d178c0f8c08d491f719ad Reviewed-by: Tobias Hunger --- .../cmakeprojectmanager/cmakeproject.cpp | 30 ++++++++++++++++++- .../cmakeprojectmanager/cmakeproject.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 211f564cc83..57de95ad1fa 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -152,7 +152,7 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc) } updateApplicationAndDeploymentTargets(); - t->updateDefaultRunConfigurations(); + updateTargetRunConfigurations(t); createGeneratedCodeModelSupport(); @@ -448,6 +448,34 @@ QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const } } +void CMakeProject::updateTargetRunConfigurations(Target *t) +{ + // *Update* existing runconfigurations (no need to update new ones!): + QHash buildTargetHash; + const QList buildTargetList = buildTargets(); + foreach (const CMakeBuildTarget &bt, buildTargetList) { + if (bt.targetType != ExecutableType || bt.executable.isEmpty()) + continue; + + buildTargetHash.insert(bt.title, &bt); + } + + foreach (RunConfiguration *rc, t->runConfigurations()) { + auto cmakeRc = qobject_cast(rc); + if (!cmakeRc) + continue; + + auto btIt = buildTargetHash.constFind(cmakeRc->title()); + if (btIt != buildTargetHash.constEnd()) { + cmakeRc->setExecutable(btIt.value()->executable.toString()); + cmakeRc->setBaseWorkingDirectory(btIt.value()->workingDirectory); + } + } + + // create new and remove obsolete RCs using the factories + t->updateDefaultRunConfigurations(); +} + void CMakeProject::updateApplicationAndDeploymentTargets() { Target *t = activeTarget(); diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 8083cf9dec1..1d3e047683f 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -123,6 +123,7 @@ private: void createGeneratedCodeModelSupport(); QStringList filesGeneratedFrom(const QString &sourceFile) const final; + void updateTargetRunConfigurations(ProjectExplorer::Target *t); void updateApplicationAndDeploymentTargets(); ProjectExplorer::Target *m_connectedTarget = nullptr; From 98862af779563d7232bf04ea033c7d86892722c7 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Wed, 20 Sep 2017 17:42:28 +0200 Subject: [PATCH 59/63] QMake: Improve following of links in .pro/.pri files * Activate on all characters of $$PWD, and not just on the PWD part * Handle $${PWD} (also on all characters) Task-number: QTCREATORBUG-18719 Change-Id: I52db23a671cc78ca4fcaa8a6905bba48b1ecd91b Reviewed-by: Tim Jenssen --- .../qmakeprojectmanager/profileeditor.cpp | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp index 97c119c456e..637cb1b239c 100644 --- a/src/plugins/qmakeprojectmanager/profileeditor.cpp +++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp @@ -46,6 +46,8 @@ #include #include +#include + using namespace TextEditor; using namespace Utils; @@ -89,7 +91,40 @@ ProFileEditorWidget::Link ProFileEditorWidget::findLinkAt(const QTextCursor &cur // find the beginning of a filename QString buffer; int beginPos = positionInBlock - 1; - while (beginPos >= 0) { + int endPos = positionInBlock; + + // Check is cursor is somewhere on $${PWD}: + const int chunkStart = std::max(0, positionInBlock - 7); + const int chunkLength = 14 + std::min(0, positionInBlock - 7); + QString chunk = block.mid(chunkStart, chunkLength); + + const QString curlyPwd = "$${PWD}"; + const QString pwd = "$$PWD"; + const int posCurlyPwd = chunk.indexOf(curlyPwd); + const int posPwd = chunk.indexOf(pwd); + bool doBackwardScan = true; + + if (posCurlyPwd >= 0) { + const int end = chunkStart + posCurlyPwd + curlyPwd.count(); + const int start = chunkStart + posCurlyPwd; + if (start <= positionInBlock && end >= positionInBlock) { + buffer = pwd; + beginPos = chunkStart + posCurlyPwd - 1; + endPos = end; + doBackwardScan = false; + } + } else if (posPwd >= 0) { + const int end = chunkStart + posPwd + pwd.count(); + const int start = chunkStart + posPwd; + if (start <= positionInBlock && end >= positionInBlock) { + buffer = pwd; + beginPos = start - 1; + endPos = end; + doBackwardScan = false; + } + } + + while (doBackwardScan && beginPos >= 0) { QChar c = block.at(beginPos); if (isValidFileNameChar(c)) { buffer.prepend(c); @@ -99,8 +134,20 @@ ProFileEditorWidget::Link ProFileEditorWidget::findLinkAt(const QTextCursor &cur } } + if (doBackwardScan + && beginPos > 0 + && block.mid(beginPos - 1, pwd.count()) == pwd + && (block.at(beginPos + pwd.count() - 1) == '/' || block.at(beginPos + pwd.count() - 1) == '\\')) { + buffer.prepend("$$"); + beginPos -= 2; + } else if (doBackwardScan + && beginPos >= curlyPwd.count() - 1 + && block.mid(beginPos - curlyPwd.count() + 1, curlyPwd.count()) == curlyPwd) { + buffer.prepend(pwd); + beginPos -= curlyPwd.count(); + } + // find the end of a filename - int endPos = positionInBlock; while (endPos < block.count()) { QChar c = block.at(endPos); if (isValidFileNameChar(c)) { @@ -121,13 +168,8 @@ ProFileEditorWidget::Link ProFileEditorWidget::findLinkAt(const QTextCursor &cur } // if the buffer starts with $$PWD accept it - if (buffer.startsWith(QLatin1String("PWD/")) || - buffer.startsWith(QLatin1String("PWD\\"))) { - if (beginPos > 0 && block.mid(beginPos - 1, 2) == QLatin1String("$$")) { - beginPos -=2; - buffer = buffer.mid(4); - } - } + if (buffer.startsWith("$$PWD/") || buffer.startsWith("$$PWD\\")) + buffer = buffer.mid(6); QDir dir(textDocument()->filePath().toFileInfo().absolutePath()); QString fileName = dir.filePath(buffer); From fb39de6a78628bb921a2bc75c22665f48cd0f981 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 14 Sep 2017 20:26:20 +0300 Subject: [PATCH 60/63] Android: Remove outdated condition Before e57ed31c33ceb9f4f8eadedd15c7396952f7963d the path was retrieved from the root project node. In that commit this was changed and it is now read from the Id. Remove the argument and always read the path from id. Also de-duplicate pathFromId. Change-Id: I6aeef1106bc101ecb130f2c2ccb7226bfc7d0903 Reviewed-by: hjk Reviewed-by: Tobias Hunger Reviewed-by: Vikas Pachdha --- .../qmakeandroidrunconfiguration.cpp | 15 ++++++++++----- .../qmakeandroidrunconfiguration.h | 4 +++- .../qmakeandroidrunfactories.cpp | 9 +-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp index ad968d38202..deb380e49ce 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp @@ -49,19 +49,19 @@ namespace Internal { static const char ANDROID_RC_ID_PREFIX[] = "Qt4ProjectManager.AndroidRunConfiguration:"; -static QString pathFromId(const Core::Id id) +static Utils::FileName pathFromId(const Core::Id id) { - return id.suffixAfter(ANDROID_RC_ID_PREFIX); + return Utils::FileName::fromString(id.suffixAfter(ANDROID_RC_ID_PREFIX)); } QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *target) : AndroidRunConfiguration(target) {} -void QmakeAndroidRunConfiguration::initialize(Core::Id id, const Utils::FileName &path) +void QmakeAndroidRunConfiguration::initialize(Core::Id id) { AndroidRunConfiguration::initialize(id); - m_proFilePath = path; + m_proFilePath = pathFromId(id); ctor(); } @@ -110,7 +110,7 @@ QString QmakeAndroidRunConfiguration::defaultDisplayName() return node->displayName(); } - return QFileInfo(pathFromId(id())).completeBaseName(); + return displayNameForId(id()); } QString QmakeAndroidRunConfiguration::disabledReason() const @@ -129,6 +129,11 @@ QString QmakeAndroidRunConfiguration::buildSystemTarget() const return qmakeProject()->mapProFilePathToTarget(m_proFilePath); } +QString QmakeAndroidRunConfiguration::displayNameForId(Core::Id id) +{ + return pathFromId(id).toFileInfo().completeBaseName(); +} + QmakeProject *QmakeAndroidRunConfiguration::qmakeProject() const { Target *t = target(); diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h index 817a78e2bac..c0265b9abbc 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h @@ -50,9 +50,11 @@ public: QString buildSystemTarget() const final; + static QString displayNameForId(Core::Id id); + private: friend class ProjectExplorer::IRunConfigurationFactory; - void initialize(Core::Id id, const Utils::FileName &path = Utils::FileName()); + void initialize(Core::Id id); void copyFrom(const QmakeAndroidRunConfiguration *source); bool fromMap(const QVariantMap &map) override; diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp index e048479a420..4fd903972ce 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp @@ -46,11 +46,6 @@ namespace Internal { static const char ANDROID_RC_ID_PREFIX[] = "Qt4ProjectManager.AndroidRunConfiguration:"; -static Utils::FileName pathFromId(const Core::Id id) -{ - return Utils::FileName::fromString(id.suffixAfter(ANDROID_RC_ID_PREFIX)); -} - QmakeAndroidRunConfigurationFactory::QmakeAndroidRunConfigurationFactory(QObject *parent) : IRunConfigurationFactory(parent) { @@ -58,7 +53,7 @@ QmakeAndroidRunConfigurationFactory::QmakeAndroidRunConfigurationFactory(QObject QString QmakeAndroidRunConfigurationFactory::displayNameForId(Core::Id id) const { - return pathFromId(id).toFileInfo().completeBaseName(); + return QmakeAndroidRunConfiguration::displayNameForId(id); } bool QmakeAndroidRunConfigurationFactory::canCreate(Target *parent, Core::Id id) const @@ -92,8 +87,6 @@ QList QmakeAndroidRunConfigurationFactory::availableCreationIds(Target RunConfiguration *QmakeAndroidRunConfigurationFactory::doCreate(Target *parent, Core::Id id) { - if (parent->project()->rootProjectNode()) - return createHelper(parent, id, pathFromId(id)); return createHelper(parent, id); } From b21742b4641be7895f9ae67372d2c306920daf38 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 21 Sep 2017 12:33:36 +0200 Subject: [PATCH 61/63] Valgrind: Merge memcheck{engine,tool}.* files This is purely mechanical in preparation of moving some per-run items from the MemCheckTool singleton to MemCheckToolRunner. Change-Id: I0fcaf6e90b2d63ca8f3c3eb7130ed73ed494f35b Reviewed-by: Christian Stenger --- src/plugins/valgrind/memcheckengine.cpp | 185 --------------------- src/plugins/valgrind/memcheckengine.h | 69 -------- src/plugins/valgrind/memchecktool.cpp | 211 +++++++++++++++++++++--- src/plugins/valgrind/valgrind.pro | 2 - src/plugins/valgrind/valgrind.qbs | 1 - 5 files changed, 191 insertions(+), 277 deletions(-) delete mode 100644 src/plugins/valgrind/memcheckengine.cpp delete mode 100644 src/plugins/valgrind/memcheckengine.h diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp deleted file mode 100644 index 8e6202e4d88..00000000000 --- a/src/plugins/valgrind/memcheckengine.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.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 "memcheckengine.h" -#include "memchecktool.h" -#include "valgrindsettings.h" -#include "xmlprotocol/error.h" -#include "xmlprotocol/status.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -using namespace Debugger; -using namespace ProjectExplorer; -using namespace Valgrind::XmlProtocol; - -namespace Valgrind { -namespace Internal { - -class LocalAddressFinder : public RunWorker -{ -public: - LocalAddressFinder(RunControl *runControl, QHostAddress *localServerAddress) - : RunWorker(runControl), connection(device()->sshParameters()) - { - connect(&connection, &QSsh::SshConnection::connected, this, [this, localServerAddress] { - *localServerAddress = connection.connectionInfo().localAddress; - reportStarted(); - }); - connect(&connection, &QSsh::SshConnection::error, this, [this] { - reportFailure(); - }); - } - - void start() override - { - connection.connectToHost(); - } - - QSsh::SshConnection connection; -}; - -MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb) - : ValgrindToolRunner(runControl), - m_withGdb(withGdb), - m_localServerAddress(QHostAddress::LocalHost) -{ - setDisplayName("MemcheckToolRunner"); - connect(m_runner.parser(), &XmlProtocol::ThreadedParser::error, - this, &MemcheckToolRunner::parserError); - connect(m_runner.parser(), &XmlProtocol::ThreadedParser::suppressionCount, - this, &MemcheckToolRunner::suppressionCount); - - if (withGdb) { - connect(&m_runner, &ValgrindRunner::valgrindStarted, - this, &MemcheckToolRunner::startDebugger); - connect(&m_runner, &ValgrindRunner::logMessageReceived, - this, &MemcheckToolRunner::appendLog); -// m_runner.disableXml(); - } else { - connect(m_runner.parser(), &XmlProtocol::ThreadedParser::internalError, - this, &MemcheckToolRunner::internalParserError); - } - - // We need a real address to connect to from the outside. - if (device()->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) - addStartDependency(new LocalAddressFinder(runControl, &m_localServerAddress)); -} - -QString MemcheckToolRunner::progressTitle() const -{ - return tr("Analyzing Memory"); -} - -void MemcheckToolRunner::start() -{ - m_runner.setLocalServerAddress(m_localServerAddress); - ValgrindToolRunner::start(); -} - -void MemcheckToolRunner::stop() -{ - disconnect(m_runner.parser(), &ThreadedParser::internalError, - this, &MemcheckToolRunner::internalParserError); - ValgrindToolRunner::stop(); -} - -QStringList MemcheckToolRunner::toolArguments() const -{ - QStringList arguments = {"--tool=memcheck", "--gen-suppressions=all"}; - - QTC_ASSERT(m_settings, return arguments); - - if (m_settings->trackOrigins()) - arguments << "--track-origins=yes"; - - if (m_settings->showReachable()) - arguments << "--show-reachable=yes"; - - QString leakCheckValue; - switch (m_settings->leakCheckOnFinish()) { - case ValgrindBaseSettings::LeakCheckOnFinishNo: - leakCheckValue = "no"; - break; - case ValgrindBaseSettings::LeakCheckOnFinishYes: - leakCheckValue = "full"; - break; - case ValgrindBaseSettings::LeakCheckOnFinishSummaryOnly: - default: - leakCheckValue = "summary"; - break; - } - arguments << "--leak-check=" + leakCheckValue; - - foreach (const QString &file, m_settings->suppressionFiles()) - arguments << QString("--suppressions=%1").arg(file); - - arguments << QString("--num-callers=%1").arg(m_settings->numCallers()); - - if (m_withGdb) - arguments << "--vgdb=yes" << "--vgdb-error=0"; - - return arguments; -} - -QStringList MemcheckToolRunner::suppressionFiles() const -{ - return m_settings->suppressionFiles(); -} - -void MemcheckToolRunner::startDebugger(qint64 valgrindPid) -{ - auto debugger = new Debugger::DebuggerRunTool(runControl()); - debugger->setStartMode(Debugger::AttachToRemoteServer); - debugger->setRunControlName(QString("VGdb %1").arg(valgrindPid)); - debugger->setRemoteChannel(QString("| vgdb --pid=%1").arg(valgrindPid)); - debugger->setUseContinueInsteadOfRun(true); - debugger->addExpectedSignal("SIGTRAP"); - - connect(runControl(), &RunControl::stopped, debugger, &RunControl::deleteLater); - - debugger->initiateStart(); -} - -void MemcheckToolRunner::appendLog(const QByteArray &data) -{ - appendMessage(QString::fromUtf8(data), Utils::StdOutFormat); -} - -} // namespace Internal -} // namespace Valgrind diff --git a/src/plugins/valgrind/memcheckengine.h b/src/plugins/valgrind/memcheckengine.h deleted file mode 100644 index 6113390e91c..00000000000 --- a/src/plugins/valgrind/memcheckengine.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.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 "valgrindengine.h" - -#include "valgrindrunner.h" -#include "xmlprotocol/threadedparser.h" - -#include - -namespace Valgrind { -namespace Internal { - -class MemcheckToolRunner : public ValgrindToolRunner -{ - Q_OBJECT - -public: - explicit MemcheckToolRunner(ProjectExplorer::RunControl *runControl, - bool withGdb = false); - - void start() override; - void stop() override; - - QStringList suppressionFiles() const; - -signals: - void internalParserError(const QString &errorString); - void parserError(const Valgrind::XmlProtocol::Error &error); - void suppressionCount(const QString &name, qint64 count); - -private: - QString progressTitle() const override; - QStringList toolArguments() const override; - - void startDebugger(qint64 valgrindPid); - void appendLog(const QByteArray &data); - - const bool m_withGdb; - QHostAddress m_localServerAddress; -}; - -} // namespace Internal -} // namespace Valgrind diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index 917bafa888e..f668ee3a5fb 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -25,36 +25,44 @@ ****************************************************************************/ #include "memchecktool.h" -#include "memcheckengine.h" + #include "memcheckerrorview.h" #include "valgrindsettings.h" #include "valgrindplugin.h" +#include "valgrindengine.h" +#include "valgrindsettings.h" +#include "valgrindrunner.h" +#include "xmlprotocol/error.h" +#include "xmlprotocol/error.h" +#include "xmlprotocol/errorlistmodel.h" +#include "xmlprotocol/frame.h" +#include "xmlprotocol/stack.h" +#include "xmlprotocol/stackmodel.h" +#include "xmlprotocol/status.h" +#include "xmlprotocol/suppression.h" +#include "xmlprotocol/threadedparser.h" + +#include +#include #include #include -#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include - #include #include #include @@ -67,20 +75,20 @@ #include #include -#include #include #include #include #include #include -#include #include +#include using namespace Core; using namespace Debugger; using namespace ProjectExplorer; using namespace Utils; using namespace Valgrind::XmlProtocol; + using namespace std::placeholders; namespace Valgrind { @@ -92,6 +100,167 @@ const char MEMCHECK_WITH_GDB_RUN_MODE[] = "MemcheckTool.MemcheckWithGdbRunMode"; const char MemcheckPerspectiveId[] = "Memcheck.Perspective"; const char MemcheckErrorDockId[] = "Memcheck.Dock.Error"; + +class MemcheckToolRunner : public ValgrindToolRunner +{ + Q_OBJECT + +public: + explicit MemcheckToolRunner(ProjectExplorer::RunControl *runControl, + bool withGdb = false); + + void start() override; + void stop() override; + + QStringList suppressionFiles() const; + +signals: + void internalParserError(const QString &errorString); + void parserError(const Valgrind::XmlProtocol::Error &error); + void suppressionCount(const QString &name, qint64 count); + +private: + QString progressTitle() const override; + QStringList toolArguments() const override; + + void startDebugger(qint64 valgrindPid); + void appendLog(const QByteArray &data); + + const bool m_withGdb; + QHostAddress m_localServerAddress; +}; + +class LocalAddressFinder : public RunWorker +{ +public: + LocalAddressFinder(RunControl *runControl, QHostAddress *localServerAddress) + : RunWorker(runControl), connection(device()->sshParameters()) + { + connect(&connection, &QSsh::SshConnection::connected, this, [this, localServerAddress] { + *localServerAddress = connection.connectionInfo().localAddress; + reportStarted(); + }); + connect(&connection, &QSsh::SshConnection::error, this, [this] { + reportFailure(); + }); + } + + void start() override + { + connection.connectToHost(); + } + + QSsh::SshConnection connection; +}; + +MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb) + : ValgrindToolRunner(runControl), + m_withGdb(withGdb), + m_localServerAddress(QHostAddress::LocalHost) +{ + setDisplayName("MemcheckToolRunner"); + connect(m_runner.parser(), &XmlProtocol::ThreadedParser::error, + this, &MemcheckToolRunner::parserError); + connect(m_runner.parser(), &XmlProtocol::ThreadedParser::suppressionCount, + this, &MemcheckToolRunner::suppressionCount); + + if (withGdb) { + connect(&m_runner, &ValgrindRunner::valgrindStarted, + this, &MemcheckToolRunner::startDebugger); + connect(&m_runner, &ValgrindRunner::logMessageReceived, + this, &MemcheckToolRunner::appendLog); +// m_runner.disableXml(); + } else { + connect(m_runner.parser(), &XmlProtocol::ThreadedParser::internalError, + this, &MemcheckToolRunner::internalParserError); + } + + // We need a real address to connect to from the outside. + if (device()->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + addStartDependency(new LocalAddressFinder(runControl, &m_localServerAddress)); +} + +QString MemcheckToolRunner::progressTitle() const +{ + return tr("Analyzing Memory"); +} + +void MemcheckToolRunner::start() +{ + m_runner.setLocalServerAddress(m_localServerAddress); + ValgrindToolRunner::start(); +} + +void MemcheckToolRunner::stop() +{ + disconnect(m_runner.parser(), &ThreadedParser::internalError, + this, &MemcheckToolRunner::internalParserError); + ValgrindToolRunner::stop(); +} + +QStringList MemcheckToolRunner::toolArguments() const +{ + QStringList arguments = {"--tool=memcheck", "--gen-suppressions=all"}; + + QTC_ASSERT(m_settings, return arguments); + + if (m_settings->trackOrigins()) + arguments << "--track-origins=yes"; + + if (m_settings->showReachable()) + arguments << "--show-reachable=yes"; + + QString leakCheckValue; + switch (m_settings->leakCheckOnFinish()) { + case ValgrindBaseSettings::LeakCheckOnFinishNo: + leakCheckValue = "no"; + break; + case ValgrindBaseSettings::LeakCheckOnFinishYes: + leakCheckValue = "full"; + break; + case ValgrindBaseSettings::LeakCheckOnFinishSummaryOnly: + default: + leakCheckValue = "summary"; + break; + } + arguments << "--leak-check=" + leakCheckValue; + + foreach (const QString &file, m_settings->suppressionFiles()) + arguments << QString("--suppressions=%1").arg(file); + + arguments << QString("--num-callers=%1").arg(m_settings->numCallers()); + + if (m_withGdb) + arguments << "--vgdb=yes" << "--vgdb-error=0"; + + return arguments; +} + +QStringList MemcheckToolRunner::suppressionFiles() const +{ + return m_settings->suppressionFiles(); +} + +void MemcheckToolRunner::startDebugger(qint64 valgrindPid) +{ + auto debugger = new Debugger::DebuggerRunTool(runControl()); + debugger->setStartMode(Debugger::AttachToRemoteServer); + debugger->setRunControlName(QString("VGdb %1").arg(valgrindPid)); + debugger->setRemoteChannel(QString("| vgdb --pid=%1").arg(valgrindPid)); + debugger->setUseContinueInsteadOfRun(true); + debugger->addExpectedSignal("SIGTRAP"); + + connect(runControl(), &RunControl::stopped, debugger, &RunControl::deleteLater); + + debugger->initiateStart(); +} + +void MemcheckToolRunner::appendLog(const QByteArray &data) +{ + appendMessage(QString::fromUtf8(data), Utils::StdOutFormat); +} + + static ErrorListModel::RelevantFrameFinder makeFrameFinder(const QStringList &projectFiles) { return [projectFiles](const Error &error) { @@ -711,3 +880,5 @@ void destroyMemcheckTool() } // namespace Internal } // namespace Valgrind + +#include "memchecktool.moc" diff --git a/src/plugins/valgrind/valgrind.pro b/src/plugins/valgrind/valgrind.pro index 4bbd41fc5c7..216e3568173 100644 --- a/src/plugins/valgrind/valgrind.pro +++ b/src/plugins/valgrind/valgrind.pro @@ -21,7 +21,6 @@ HEADERS += \ workarounds.h \ callgrindtextmark.h \ memchecktool.h \ - memcheckengine.h \ memcheckerrorview.h \ suppressiondialog.h @@ -41,7 +40,6 @@ SOURCES += \ workarounds.cpp \ callgrindtextmark.cpp \ memchecktool.cpp \ - memcheckengine.cpp \ memcheckerrorview.cpp \ suppressiondialog.cpp diff --git a/src/plugins/valgrind/valgrind.qbs b/src/plugins/valgrind/valgrind.qbs index 44814d0ce6f..5b7fb8f040c 100644 --- a/src/plugins/valgrind/valgrind.qbs +++ b/src/plugins/valgrind/valgrind.qbs @@ -27,7 +27,6 @@ QtcPlugin { "callgrindtextmark.cpp", "callgrindtextmark.h", "callgrindtool.cpp", "callgrindtool.h", "callgrindvisualisation.cpp", "callgrindvisualisation.h", - "memcheckengine.cpp", "memcheckengine.h", "memcheckerrorview.cpp", "memcheckerrorview.h", "memchecktool.cpp", "memchecktool.h", "suppressiondialog.cpp", "suppressiondialog.h", From 40ba7ac16ffbf44800f59e0e2459382f07824e5f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 15 Sep 2017 15:16:33 +0200 Subject: [PATCH 62/63] CppEditor: Avoid blocking context menu invocation Show the menu always immediately. If the needed use selections are not up to date for the refactoring actions, then trigger an async run and if that one finishes, then update the refactoring menu. In the meanwhile, show a place holder menu item showing on-going progress (Utils::ProgressIndicator). Change-Id: Iae7ab37738d79c20aeb1ccda2b1781091e90fdc3 Reviewed-by: Ivan Donchevskii Reviewed-by: Tim Jenssen --- src/plugins/cppeditor/cppeditorwidget.cpp | 54 ++++++++++++++++--- .../cppeditor/cppuseselectionsupdater.cpp | 32 +++++++---- .../cppeditor/cppuseselectionsupdater.h | 5 +- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 37f152fe58a..c14bb541bef 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -80,8 +80,9 @@ #include #include #include -#include +#include #include +#include #include #include @@ -93,6 +94,7 @@ #include #include #include +#include enum { UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL = 200 }; @@ -176,9 +178,11 @@ void CppEditorWidget::finalizeInitialization() &CppLocalRenaming::updateSelectionsForVariableUnderCursor); connect(&d->m_useSelectionsUpdater, &CppUseSelectionsUpdater::finished, this, - [this] (SemanticInfo::LocalUseMap localUses) { - d->m_lastSemanticInfo.localUsesUpdated = true; - d->m_lastSemanticInfo.localUses = localUses; + [this] (SemanticInfo::LocalUseMap localUses, bool success) { + if (success) { + d->m_lastSemanticInfo.localUsesUpdated = true; + d->m_lastSemanticInfo.localUses = localUses; + } }); connect(document(), &QTextDocument::contentsChange, @@ -750,6 +754,20 @@ static void addRefactoringActions(QMenu *menu, AssistInterface *iface) } } +class ProgressIndicatorMenuItem : public QWidgetAction +{ + Q_OBJECT + +public: + ProgressIndicatorMenuItem(QObject *parent) : QWidgetAction(parent) {} + +protected: + QWidget *createWidget(QWidget *parent = nullptr) override + { + return new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Small, parent); + } +}; + QMenu *CppEditorWidget::createRefactorMenu(QWidget *parent) const { auto *menu = new QMenu(tr("&Refactor"), parent); @@ -759,8 +777,30 @@ QMenu *CppEditorWidget::createRefactorMenu(QWidget *parent) const // updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource())); if (isSemanticInfoValidExceptLocalUses()) { - d->m_useSelectionsUpdater.update(CppUseSelectionsUpdater::CallType::Synchronous); - addRefactoringActions(menu, createAssistInterface(QuickFix, ExplicitlyInvoked)); + d->m_useSelectionsUpdater.abortSchedule(); + + const CppUseSelectionsUpdater::RunnerInfo runnerInfo = d->m_useSelectionsUpdater.update(); + switch (runnerInfo) { + case CppUseSelectionsUpdater::RunnerInfo::AlreadyUpToDate: + addRefactoringActions(menu, createAssistInterface(QuickFix, ExplicitlyInvoked)); + break; + case CppUseSelectionsUpdater::RunnerInfo::Started: { + // Update the refactor menu once we get the results. + auto *progressIndicatorMenuItem = new ProgressIndicatorMenuItem(menu); + menu->addAction(progressIndicatorMenuItem); + + connect(&d->m_useSelectionsUpdater, &CppUseSelectionsUpdater::finished, + menu, [=] (SemanticInfo::LocalUseMap, bool success) { + QTC_CHECK(success); + menu->removeAction(progressIndicatorMenuItem); + addRefactoringActions(menu, createAssistInterface(QuickFix, ExplicitlyInvoked)); + }); + break; + } + case CppUseSelectionsUpdater::RunnerInfo::FailedToStart: + case CppUseSelectionsUpdater::RunnerInfo::Invalid: + QTC_CHECK(false && "Unexpected CppUseSelectionsUpdater runner result"); + } } return menu; @@ -1041,3 +1081,5 @@ void CppEditorWidget::invokeTextEditorWidgetAssist(TextEditor::AssistKind assist } // namespace Internal } // namespace CppEditor + +#include "cppeditorwidget.moc" diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp index 5b8d1d27dfe..da7a7a1d92a 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp +++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp @@ -66,13 +66,13 @@ void CppUseSelectionsUpdater::abortSchedule() m_timer.stop(); } -void CppUseSelectionsUpdater::update(CallType callType) +CppUseSelectionsUpdater::RunnerInfo CppUseSelectionsUpdater::update(CallType callType) { auto *cppEditorWidget = qobject_cast(m_editorWidget); - QTC_ASSERT(cppEditorWidget, return); + QTC_ASSERT(cppEditorWidget, return RunnerInfo::FailedToStart); auto *cppEditorDocument = qobject_cast(cppEditorWidget->textDocument()); - QTC_ASSERT(cppEditorDocument, return); + QTC_ASSERT(cppEditorDocument, return RunnerInfo::FailedToStart); CppTools::CursorInfoParams params; params.semanticInfo = cppEditorWidget->semanticInfo(); @@ -80,7 +80,7 @@ void CppUseSelectionsUpdater::update(CallType callType) if (callType == CallType::Asynchronous) { if (isSameIdentifierAsBefore(params.textCursor)) - return; + return RunnerInfo::AlreadyUpToDate; if (m_runnerWatcher) m_runnerWatcher->cancel(); @@ -93,25 +93,28 @@ void CppUseSelectionsUpdater::update(CallType callType) m_runnerWordStartPosition = params.textCursor.position(); m_runnerWatcher->setFuture(cppEditorDocument->cursorInfo(params)); + return RunnerInfo::Started; } else { // synchronous case abortSchedule(); const int startRevision = cppEditorDocument->document()->revision(); QFuture future = cppEditorDocument->cursorInfo(params); if (future.isCanceled()) - return; + return RunnerInfo::Invalid; // QFuture::waitForFinished seems to block completely, not even // allowing to process events from QLocalSocket. while (!future.isFinished()) { if (future.isCanceled()) - return; + return RunnerInfo::Invalid; - QTC_ASSERT(startRevision == cppEditorDocument->document()->revision(), return); + QTC_ASSERT(startRevision == cppEditorDocument->document()->revision(), + return RunnerInfo::Invalid); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } processResults(future.result()); + return RunnerInfo::Invalid; } } @@ -134,18 +137,25 @@ void CppUseSelectionsUpdater::processResults(const CursorInfo &result) updateUnusedSelections(result.unusedVariablesRanges); emit selectionsForVariableUnderCursorUpdated(localVariableSelections); - emit finished(result.localUses); + emit finished(result.localUses, true); } void CppUseSelectionsUpdater::onFindUsesFinished() { - QTC_ASSERT(m_runnerWatcher, return); - if (m_runnerWatcher->isCanceled()) + QTC_ASSERT(m_runnerWatcher, + emit finished(CppTools::SemanticInfo::LocalUseMap(), false); return); + + if (m_runnerWatcher->isCanceled()) { + emit finished(CppTools::SemanticInfo::LocalUseMap(), false); return; - if (m_runnerRevision != m_editorWidget->document()->revision()) + } + if (m_runnerRevision != m_editorWidget->document()->revision()) { + emit finished(CppTools::SemanticInfo::LocalUseMap(), false); return; + } if (m_runnerWordStartPosition != Utils::Text::wordStartCursor(m_editorWidget->textCursor()).position()) { + emit finished(CppTools::SemanticInfo::LocalUseMap(), false); return; } diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.h b/src/plugins/cppeditor/cppuseselectionsupdater.h index 7e10eeb680c..ec18b222f45 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.h +++ b/src/plugins/cppeditor/cppuseselectionsupdater.h @@ -50,10 +50,11 @@ public: void abortSchedule(); enum class CallType { Synchronous, Asynchronous }; - void update(CallType callType = CallType::Asynchronous); + enum class RunnerInfo { AlreadyUpToDate, Started, FailedToStart, Invalid }; // For async case. + RunnerInfo update(CallType callType = CallType::Asynchronous); signals: - void finished(CppTools::SemanticInfo::LocalUseMap localUses); + void finished(CppTools::SemanticInfo::LocalUseMap localUses, bool success); void selectionsForVariableUnderCursorUpdated(const QList &); private: From 75f13f200b9930fb0da0384f6364a703a3ce7e9f Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 24 Sep 2017 21:34:19 +0300 Subject: [PATCH 63/63] Utils: Fix comment in optional.h Change-Id: I082c939469d0161d5ed5f9da810bd6b553750ce0 Reviewed-by: Eike Ziller --- src/libs/utils/optional.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/utils/optional.h b/src/libs/utils/optional.h index be07015d3d5..e4f943259f7 100644 --- a/src/libs/utils/optional.h +++ b/src/libs/utils/optional.h @@ -41,7 +41,7 @@ namespace Utils { using std::experimental::optional; // --> Utils::nullopt using std::experimental::nullopt; -// --> Utils::inplace +// --> Utils::in_place using std::experimental::in_place; // TODO: make_optional is a copy, since there is no sensible way to import functions in C++