From 4334c119cfefb7ef41cdc5a145f9e6226425a3c4 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 12 Mar 2015 16:57:11 +0100 Subject: [PATCH 01/22] Clear old analyzer issues on tool start. Change-Id: I54f7791c15e05ca5c85c8b4059f80b050de57282 Reviewed-by: hjk --- src/plugins/analyzerbase/analyzermanager.cpp | 2 ++ src/plugins/valgrind/memcheckengine.cpp | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plugins/analyzerbase/analyzermanager.cpp b/src/plugins/analyzerbase/analyzermanager.cpp index 42bddb42141..278c0bd551b 100644 --- a/src/plugins/analyzerbase/analyzermanager.cpp +++ b/src/plugins/analyzerbase/analyzermanager.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -420,6 +421,7 @@ bool AnalyzerManagerPrivate::showPromptDialog(const QString &title, const QStrin void AnalyzerManagerPrivate::startTool() { QTC_ASSERT(m_currentAction, return); + TaskHub::clearTasks(Constants::ANALYZERTASK_ID); m_currentAction->toolStarter()(); } diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp index f2925e0d8d9..61c4af2e816 100644 --- a/src/plugins/valgrind/memcheckengine.cpp +++ b/src/plugins/valgrind/memcheckengine.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include #include @@ -82,9 +81,6 @@ bool MemcheckRunControl::startEngine() { m_runner.setParser(&m_parser); - // Clear about-to-be-outdated tasks. - TaskHub::clearTasks(Analyzer::Constants::ANALYZERTASK_ID); - appendMessage(tr("Analyzing memory of %1").arg(executable()) + QLatin1Char('\n'), Utils::NormalMessageFormat); return ValgrindRunControl::startEngine(); From 9c5a56a38bc41a28e5a92ace243342ab0073207a Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 12 Mar 2015 08:37:33 +0100 Subject: [PATCH 02/22] Cdb: Reduce usage of deprecated WatchData. Change-Id: Ie3d3355e51761cea7e0284bbb3e0177d5a443f36 Reviewed-by: Christian Stenger --- src/plugins/debugger/cdb/cdbengine.cpp | 52 ++++++++------------------ src/plugins/debugger/cdb/cdbengine.h | 1 - 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 8726650cb6f..0c7ef6663a5 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -347,7 +347,6 @@ void CdbEngine::init() m_watchPointX = m_watchPointY = 0; m_ignoreCdbOutput = false; m_autoBreakPointCorrection = false; - m_watchInameToName.clear(); m_wow64State = wow64Uninitialized; m_outputBuffer.clear(); @@ -986,14 +985,10 @@ void CdbEngine::updateWatchData(const WatchData &dataIn) return; // New watch item? - if (isWatchIName(dataIn.iname) && dataIn.isValueNeeded()) { + if (dataIn.isWatcher() && dataIn.isValueNeeded()) { QByteArray args; ByteArrayInputStream str(args); str << dataIn.iname << " \"" << dataIn.exp << '"'; - // Store the name since the CDB extension library - // does not maintain the names of watches. - if (!dataIn.name.isEmpty() && dataIn.name != QLatin1String(dataIn.exp)) - m_watchInameToName.insert(dataIn.iname, dataIn.name); postExtensionCommand("addwatch", args, 0, [this, dataIn](const CdbResponse &r) { handleAddWatch(r, dataIn); }); return; @@ -1866,40 +1861,25 @@ void CdbEngine::handleLocals(const CdbResponse &response, bool newFrame) if (response.success) { if (boolSetting(VerboseLog)) showMessage(QLatin1String("Locals: ") + QString::fromLatin1(response.extensionReply), LogDebug); - QList watchData; WatchHandler *handler = watchHandler(); + GdbMi all; + all.fromString(response.extensionReply); + QTC_ASSERT(all.type() == GdbMi::List, return); + + QSet toDelete; if (newFrame) { - watchData.append(*handler->findData("local")); - watchData.append(*handler->findData("watch")); + foreach (WatchItem *item, handler->model()->treeLevelItems(2)) + toDelete.insert(item->d.iname); } - GdbMi root; - root.fromString(response.extensionReply); - QTC_ASSERT(root.type() == GdbMi::List, return); - if (debugLocals) - qDebug() << root.toString(true, 4); - // Courtesy of GDB engine - foreach (const GdbMi &child, root.children()) { - WatchData dummy; - dummy.iname = child["iname"].data(); - dummy.name = QLatin1String(child["name"].data()); - parseWatchData(dummy, child, &watchData); - } - // Fix the names of watch data. - for (int i =0; i < watchData.size(); ++i) { - if (watchData.at(i).iname.startsWith('w')) { - const QHash::const_iterator it - = m_watchInameToName.find(watchData.at(i).iname); - if (it != m_watchInameToName.constEnd()) - watchData[i].name = it.value(); - } - } - handler->insertDataList(watchData); - if (debugLocals) { - QDebug nsp = qDebug().nospace(); - nsp << "Obtained " << watchData.size() << " items:\n"; - foreach (const WatchData &wd, watchData) - nsp << wd.toString() <<'\n'; + + foreach (const GdbMi &child, all.children()) { + WatchItem *item = new WatchItem(child); + handler->insertItem(item); + toDelete.remove(item->d.iname); } + + handler->purgeOutdatedItems(toDelete); + if (newFrame) { emit stackFrameCompleted(); DebuggerToolTipManager::updateEngine(this); diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index 540bfd740bb..76ecd6a472c 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -293,7 +293,6 @@ private: bool m_autoBreakPointCorrection; QHash m_fileNameModuleHash; QMultiHash m_symbolAddressCache; - QHash m_watchInameToName; bool m_ignoreCdbOutput; QVariantList m_customSpecialStopData; QList m_sourcePathMappings; From a053724c28d128a44b36d26eb1f3257b9046879a Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 6 Mar 2015 15:13:21 +0100 Subject: [PATCH 03/22] Debugger: Refresh list of debuggers in kits options page on changes Task-number: QTCREATORBUG-13991 Change-Id: I06ff6daea88e14b4193e4f1a71d768b528d80bf9 Reviewed-by: hjk --- .../debugger/debuggerkitconfigwidget.cpp | 18 +++++-- .../debugger/debuggerkitconfigwidget.h | 1 + .../kitinformationconfigwidget.cpp | 47 +++++-------------- .../kitinformationconfigwidget.h | 4 +- .../kitmanagerconfigwidget.cpp | 7 +++ .../projectexplorer/kitmanagerconfigwidget.h | 1 + 6 files changed, 34 insertions(+), 44 deletions(-) diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp index bf6009867ce..111f228d7df 100644 --- a/src/plugins/debugger/debuggerkitconfigwidget.cpp +++ b/src/plugins/debugger/debuggerkitconfigwidget.cpp @@ -69,14 +69,11 @@ namespace Internal { // ----------------------------------------------------------------------- DebuggerKitConfigWidget::DebuggerKitConfigWidget(Kit *workingCopy, const KitInformation *ki) - : KitConfigWidget(workingCopy, ki) + : KitConfigWidget(workingCopy, ki), + m_ignoreChanges(false) { m_comboBox = new QComboBox; m_comboBox->setEnabled(true); - m_comboBox->setToolTip(toolTip()); - m_comboBox->addItem(tr("None"), QString()); - foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) - m_comboBox->addItem(item.displayName(), item.id()); refresh(); connect(m_comboBox, static_cast(&QComboBox::currentIndexChanged), @@ -112,8 +109,16 @@ void DebuggerKitConfigWidget::makeReadOnly() void DebuggerKitConfigWidget::refresh() { + m_ignoreChanges = true; + m_comboBox->clear(); + m_comboBox->setToolTip(toolTip()); + m_comboBox->addItem(tr("None"), QString()); + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) + m_comboBox->addItem(item.displayName(), item.id()); + const DebuggerItem *item = DebuggerKitInformation::debugger(m_kit); updateComboBox(item ? item->id() : QVariant()); + m_ignoreChanges = false; } QWidget *DebuggerKitConfigWidget::buttonWidget() const @@ -134,6 +139,9 @@ void DebuggerKitConfigWidget::manageDebuggers() void DebuggerKitConfigWidget::currentDebuggerChanged(int) { + if (m_ignoreChanges) + return; + int currentIndex = m_comboBox->currentIndex(); QVariant id = m_comboBox->itemData(currentIndex); m_kit->setValue(DebuggerKitInformation::id(), id); diff --git a/src/plugins/debugger/debuggerkitconfigwidget.h b/src/plugins/debugger/debuggerkitconfigwidget.h index cbe4e8b5948..285ce87dc95 100644 --- a/src/plugins/debugger/debuggerkitconfigwidget.h +++ b/src/plugins/debugger/debuggerkitconfigwidget.h @@ -79,6 +79,7 @@ private: void updateComboBox(const QVariant &id); bool m_isReadOnly; + bool m_ignoreChanges; QComboBox *m_comboBox; QPushButton *m_manageButton; }; diff --git a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp b/src/plugins/projectexplorer/kitinformationconfigwidget.cpp index 1004c704c97..1d92e031f4f 100644 --- a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp +++ b/src/plugins/projectexplorer/kitinformationconfigwidget.cpp @@ -126,31 +126,19 @@ void SysRootInformationConfigWidget::pathWasChanged() // -------------------------------------------------------------------------- ToolChainInformationConfigWidget::ToolChainInformationConfigWidget(Kit *k, const KitInformation *ki) : - KitConfigWidget(k, ki) + KitConfigWidget(k, ki), + m_ignoreChanges(false) { m_comboBox = new QComboBox; m_comboBox->setEnabled(false); m_comboBox->setToolTip(toolTip()); - foreach (ToolChain *tc, ToolChainManager::toolChains()) - toolChainAdded(tc); - - updateComboBox(); - refresh(); connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(currentToolChainChanged(int))); m_manageButton = new QPushButton(KitConfigWidget::msgManage()); m_manageButton->setContentsMargins(0, 0, 0, 0); connect(m_manageButton, SIGNAL(clicked()), this, SLOT(manageToolChains())); - - QObject *tcm = ToolChainManager::instance(); - connect(tcm, SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), - this, SLOT(toolChainAdded(ProjectExplorer::ToolChain*))); - connect(tcm, SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), - this, SLOT(toolChainRemoved(ProjectExplorer::ToolChain*))); - connect(tcm, SIGNAL(toolChainUpdated(ProjectExplorer::ToolChain*)), - this, SLOT(toolChainUpdated(ProjectExplorer::ToolChain*))); } ToolChainInformationConfigWidget::~ToolChainInformationConfigWidget() @@ -173,7 +161,13 @@ QString ToolChainInformationConfigWidget::toolTip() const void ToolChainInformationConfigWidget::refresh() { + m_ignoreChanges = true; + m_comboBox->clear(); + foreach (ToolChain *tc, ToolChainManager::toolChains()) + m_comboBox->addItem(tc->displayName(), tc->id()); + m_comboBox->setCurrentIndex(indexOf(ToolChainKitInformation::toolChain(m_kit))); + m_ignoreChanges = false; } void ToolChainInformationConfigWidget::makeReadOnly() @@ -191,28 +185,6 @@ QWidget *ToolChainInformationConfigWidget::buttonWidget() const return m_manageButton; } -void ToolChainInformationConfigWidget::toolChainAdded(ToolChain *tc) -{ - m_comboBox->addItem(tc->displayName(), tc->id()); - updateComboBox(); -} - -void ToolChainInformationConfigWidget::toolChainRemoved(ToolChain *tc) -{ - const int pos = indexOf(tc); - if (pos < 0) - return; - m_comboBox->removeItem(pos); - updateComboBox(); -} -void ToolChainInformationConfigWidget::toolChainUpdated(ToolChain *tc) -{ - const int pos = indexOf(tc); - if (pos < 0) - return; - m_comboBox->setItemText(pos, tc->displayName()); -} - void ToolChainInformationConfigWidget::manageToolChains() { ICore::showOptionsDialog(Constants::TOOLCHAIN_SETTINGS_PAGE_ID, buttonWidget()); @@ -220,6 +192,9 @@ void ToolChainInformationConfigWidget::manageToolChains() void ToolChainInformationConfigWidget::currentToolChainChanged(int idx) { + if (m_ignoreChanges) + return; + const QString id = m_comboBox->itemData(idx).toString(); ToolChainKitInformation::setToolChain(m_kit, ToolChainManager::findToolChain(id)); } diff --git a/src/plugins/projectexplorer/kitinformationconfigwidget.h b/src/plugins/projectexplorer/kitinformationconfigwidget.h index 774ffad2b32..40b47152f5c 100644 --- a/src/plugins/projectexplorer/kitinformationconfigwidget.h +++ b/src/plugins/projectexplorer/kitinformationconfigwidget.h @@ -100,9 +100,6 @@ public: QString toolTip() const; private slots: - void toolChainAdded(ProjectExplorer::ToolChain *tc); - void toolChainRemoved(ProjectExplorer::ToolChain *tc); - void toolChainUpdated(ProjectExplorer::ToolChain *tc); void manageToolChains(); void currentToolChainChanged(int idx); @@ -112,6 +109,7 @@ private: QComboBox *m_comboBox; QPushButton *m_manageButton; + bool m_ignoreChanges; }; // -------------------------------------------------------------------------- diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp index 56476a45432..de3e9043ad0 100644 --- a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp +++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp @@ -366,6 +366,13 @@ void KitManagerConfigWidget::kitWasUpdated(Kit *k) updateVisibility(); } +void KitManagerConfigWidget::showEvent(QShowEvent *event) +{ + Q_UNUSED(event); + foreach (KitConfigWidget *widget, m_widgets) + widget->refresh(); +} + QLabel *KitManagerConfigWidget::createLabel(const QString &name, const QString &toolTip) { QLabel *label = new QLabel(name); diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.h b/src/plugins/projectexplorer/kitmanagerconfigwidget.h index 2d00ef0c6b1..70e13398e36 100644 --- a/src/plugins/projectexplorer/kitmanagerconfigwidget.h +++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.h @@ -93,6 +93,7 @@ private: ButtonColumn }; + void showEvent(QShowEvent *event); QLabel *createLabel(const QString &name, const QString &toolTip); void paintEvent(QPaintEvent *ev); From c9dc686a040d8ae7d54bccb7712362dc6ff45414 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 13 Mar 2015 10:50:32 +0100 Subject: [PATCH 04/22] CdbExt: Fix compile warning Change-Id: I52bbf904a3a6a3cd3d5dcab34e649a44d406af98 Reviewed-by: David Schulz --- src/libs/qtcreatorcdbext/symbolgroupvalue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index 8de0c2bb0b7..44e6aaf8ed9 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -2231,7 +2231,7 @@ static bool dumpQDateTime(const SymbolGroupValue &v, std::wostream &str) << offset << separator << std::hex; if (timeZoneString.length() > 2) { - for (int i = 1; i < timeZoneString.length() - 1; ++i) // remove '"' + for (unsigned i = 1; i < timeZoneString.length() - 1; ++i) // remove '"' str << (int)timeZoneString.at(i); } str << std::dec << separator << status; From cfe69e690213bbb010d6e255e627956885ead72c Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Thu, 12 Mar 2015 19:08:11 +0100 Subject: [PATCH 05/22] AndroidManifestWidget: Fix resizing behavior This time for real. Change layout from QScrollArea -> QStackedWidget -> GeneralPage -> EditorPage to QStackedWidget -> QScrollArea -> GeneralPage -> EditorPage Change-Id: Id0d4baca297a5b4d58292fa72faa62b66c91a2dd Task-number: QTCREATORBUG-14127 Reviewed-by: Alessandro Portale --- .../android/androidmanifesteditorwidget.cpp | 22 +++++++++---------- .../android/androidmanifesteditorwidget.h | 4 +--- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index c8995f21610..9d69516c36b 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -70,6 +70,7 @@ #include #include #include +#include #include @@ -103,7 +104,7 @@ Project *androidProject(const Utils::FileName &fileName) } // anonymous namespace AndroidManifestEditorWidget::AndroidManifestEditorWidget() - : QScrollArea(), + : QStackedWidget(), m_dirty(false), m_stayClean(false), m_setAppName(false), @@ -118,8 +119,6 @@ AndroidManifestEditorWidget::AndroidManifestEditorWidget() m_editor = new AndroidManifestEditor(this); - setWidgetResizable(true); - connect(&m_timerParseCheck, SIGNAL(timeout()), this, SLOT(delayedParseCheck())); @@ -129,11 +128,8 @@ AndroidManifestEditorWidget::AndroidManifestEditorWidget() void AndroidManifestEditorWidget::initializePage() { - m_stackedWidget = new QStackedWidget(this); - setWidget(m_stackedWidget); - Core::IContext *myContext = new Core::IContext(this); - myContext->setWidget(m_stackedWidget); + myContext->setWidget(this); myContext->setContext(Core::Context(androidManifestEditorGeneralPaneContextId)); // where is the context used? Core::ICore::addContextObject(myContext); @@ -458,8 +454,12 @@ void AndroidManifestEditorWidget::initializePage() topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding)); - m_stackedWidget->insertWidget(General, mainWidget); - m_stackedWidget->insertWidget(Source, m_textEditorWidget); + QScrollArea *mainWidgetScrollArea = new QScrollArea; + mainWidgetScrollArea->setWidgetResizable(true); + mainWidgetScrollArea->setWidget(mainWidget); + + insertWidget(General, mainWidgetScrollArea); + insertWidget(Source, m_textEditorWidget); } bool AndroidManifestEditorWidget::eventFilter(QObject *obj, QEvent *event) @@ -540,7 +540,7 @@ bool AndroidManifestEditorWidget::isModified() const AndroidManifestEditorWidget::EditorPage AndroidManifestEditorWidget::activePage() const { - return AndroidManifestEditorWidget::EditorPage(m_stackedWidget->currentIndex()); + return AndroidManifestEditorWidget::EditorPage(currentIndex()); } bool AndroidManifestEditorWidget::setActivePage(EditorPage page) @@ -564,7 +564,7 @@ bool AndroidManifestEditorWidget::setActivePage(EditorPage page) // m_packageNameLineEdit->setFocus(); } - m_stackedWidget->setCurrentIndex(page); + setCurrentIndex(page); return true; } diff --git a/src/plugins/android/androidmanifesteditorwidget.h b/src/plugins/android/androidmanifesteditorwidget.h index 2d0ebdf1acc..80fa29c6692 100644 --- a/src/plugins/android/androidmanifesteditorwidget.h +++ b/src/plugins/android/androidmanifesteditorwidget.h @@ -35,7 +35,6 @@ #include #include -#include #include QT_BEGIN_NAMESPACE @@ -86,7 +85,7 @@ public: explicit AndroidManifestTextEditorWidget(AndroidManifestEditorWidget *parent); }; -class AndroidManifestEditorWidget : public QScrollArea +class AndroidManifestEditorWidget : public QStackedWidget { Q_OBJECT public: @@ -196,7 +195,6 @@ private: QTimer m_timerParseCheck; TextEditor::TextEditorWidget *m_textEditorWidget; - QStackedWidget *m_stackedWidget; AndroidManifestEditor *m_editor; }; } // namespace Internal From c9b71a268b9f60b31b03e84de76d51ef668c0dfb Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 13 Mar 2015 10:54:57 +0200 Subject: [PATCH 06/22] C++: Provide better output on preprocessor test failure Make the expected output copyable to the test. Change-Id: I4fc61682f14d0de054a11d2ffa4a0f36ede0e500 Reviewed-by: Francois Ferrand Reviewed-by: Nikolai Kosjar --- .../preprocessor/tst_preprocessor.cpp | 59 +++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index c9e417c59b4..12d6979c109 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -69,6 +69,24 @@ void saveData(const QByteArray &data, const QString &fileName) inf.close(); } +static QByteArray stringify(QByteArray code) +{ + QByteArray res = code.replace('"', "\\\"").replace("\n", "\\n\"\n\""); + if (res.endsWith("\"\n\"")) + res.chop(3); + return res; +} + +static bool compare(const QByteArray &actual, const QByteArray &expected) +{ + if (actual == expected) + return true; + qDebug() << "Compared strings are not the same\n" + " Actual:\n" << stringify(actual) + << " Expected:\n" << stringify(expected); + return false; +} + struct Include { Include(const QString &fileName, Client::IncludeType type, unsigned line) @@ -344,7 +362,7 @@ protected: client.sourceNeeded("data/" + fileName, nolines); return output; } - static QString simplified(QByteArray buf); + static QByteArray simplified(const QByteArray &buf); private: void compare_input_output(bool keepComments = false); @@ -396,7 +414,7 @@ private slots: // Remove all #... lines, and 'simplify' string, to allow easily comparing the result // Also, remove all unneeded spaces: keep only to ensure identifiers are separated. // NOTE: may not correctly handle underscore in identifiers -QString tst_Preprocessor::simplified(QByteArray buf) +QByteArray tst_Preprocessor::simplified(const QByteArray &buf) { QString out; QList lines = buf.split('\n'); @@ -417,7 +435,7 @@ QString tst_Preprocessor::simplified(QByteArray buf) i++; } - return out; + return out.toUtf8(); } void tst_Preprocessor::va_args() @@ -435,7 +453,7 @@ void tst_Preprocessor::va_args() preprocessed = preprocessed.simplified(); // DUMP_OUTPUT(preprocessed); - QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);")); + QVERIFY(compare(simplified(preprocessed), "int f();int f(int a);int f(int a,int b);")); } void tst_Preprocessor::named_va_args() @@ -452,7 +470,7 @@ void tst_Preprocessor::named_va_args() true, false); preprocessed = preprocessed.simplified(); - QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);")); + QVERIFY(compare(simplified(preprocessed), "int f();int f(int a);int f(int a,int b);")); } void tst_Preprocessor::extra_va_args() @@ -469,7 +487,7 @@ void tst_Preprocessor::extra_va_args() true, false); preprocessed = preprocessed.simplified(); - QCOMPARE(simplified(preprocessed), QString("int f();float f(int b);long f(int b,int c);")); + QVERIFY(compare(simplified(preprocessed), "int f();float f(int b);long f(int b,int c);")); } void tst_Preprocessor::empty_macro_args() @@ -489,8 +507,7 @@ void tst_Preprocessor::empty_macro_args() preprocessed = preprocessed.simplified(); // DUMP_OUTPUT(preprocessed); - QCOMPARE(simplified(preprocessed), - QString("const int cVal;int Val;int Val2;int;int;")); + QVERIFY(compare(simplified(preprocessed), "const int cVal;int Val;int Val2;int;int;")); } void tst_Preprocessor::macro_args_count() @@ -626,7 +643,7 @@ void tst_Preprocessor::macro_uses() Preprocessor preprocess(&client, &env); QByteArray preprocessed = preprocess.run(QLatin1String(""), buffer); - QCOMPARE(simplified(preprocessed), QString("void test(){int x=8;int y=9;}")); + QVERIFY(compare(simplified(preprocessed), "void test(){int x=8;int y=9;}")); QCOMPARE(client.expandedMacros(), QList() << QByteArray("FOO") << QByteArray("BAR")); QCOMPARE(client.expandedMacrosOffset(), QList() << buffer.indexOf("FOO;") << buffer.indexOf("BAR;")); QCOMPARE(client.definedMacros(), QList() << QByteArray("FOO") << QByteArray("BAR")); @@ -801,7 +818,7 @@ void tst_Preprocessor::unfinished_function_like_macro_call() "# 4 \"\"\n"); // DUMP_OUTPUT(preprocessed); - QCOMPARE(preprocessed, expected__); + QVERIFY(compare(preprocessed, expected__)); } void tst_Preprocessor::nasty_macro_expansion() @@ -881,7 +898,7 @@ void tst_Preprocessor::glib_attribute() "}\n"; // DUMP_OUTPUT(preprocessed); - QCOMPARE(preprocessed, result____); + QVERIFY(compare(preprocessed, result____)); } void tst_Preprocessor::builtin__FILE__() @@ -898,7 +915,7 @@ void tst_Preprocessor::builtin__FILE__() "# 1 \"some-file.c\"\n" "const char *f = \"some-file.c\"\n"; - QCOMPARE(preprocessed, result____); + QVERIFY(compare(preprocessed, result____)); } void tst_Preprocessor::comparisons_data() @@ -957,15 +974,12 @@ void tst_Preprocessor::comparisons() // These weird underscores are here to make the name as long as // "preprocessed", so the QCOMPARE error messages are nicely aligned. QByteArray output____ = loadSource("data/" + outfile); - // QCOMPARE(preprocessed, output____); - QCOMPARE(QString::fromUtf8(preprocessed.constData()), - QString::fromUtf8(output____.constData())); + QVERIFY(compare(preprocessed, output____)); } if (!errorfile.isEmpty()) { QByteArray errorFileContents = loadSource("data/" + errorfile); - QCOMPARE(QString::fromUtf8(errors.constData()), - QString::fromUtf8(errorFileContents.constData())); + QVERIFY(compare(errors, errorFileContents)); } } @@ -1252,10 +1266,10 @@ void tst_Preprocessor::comments_within() Preprocessor preprocess(0, &env); preprocess.setKeepComments(false); QByteArray prep = preprocess.run(QLatin1String(""), input); - QCOMPARE(prep.constData(), without_comments.constData()); + QVERIFY(compare(prep, without_comments)); preprocess.setKeepComments(true); prep = preprocess.run(QLatin1String(""), input); - QCOMPARE(prep.constData(), with_comments.constData()); + QVERIFY(compare(prep, with_comments)); } void tst_Preprocessor::comments_within_data() @@ -1637,8 +1651,7 @@ void tst_Preprocessor::comments_before_args() preprocessed = preprocessed.simplified(); // DUMP_OUTPUT(preprocessed); - QCOMPARE(simplified(preprocessed), - QString("int a=1;int b=2;int c=3;int d=4;int e=5;")); + QVERIFY(compare(simplified(preprocessed), "int a=1;int b=2;int c=3;int d=4;int e=5;")); } void tst_Preprocessor::multiline_strings() @@ -1899,7 +1912,7 @@ void tst_Preprocessor::concat() "# 5 \"\"\n" " ;\n" ); - QCOMPARE(prep.constData(), output.constData()); + QVERIFY(compare(prep, output)); } void tst_Preprocessor::excessive_nesting() @@ -1928,7 +1941,7 @@ void tst_Preprocessor::compare_input_output(bool keepComments) Preprocessor preprocess(0, &env); preprocess.setKeepComments(keepComments); QByteArray prep = preprocess.run(QLatin1String(""), input); - QCOMPARE(prep.constData(), output.constData()); + QVERIFY(compare(prep, output)); } QTEST_APPLESS_MAIN(tst_Preprocessor) From a320daff865cefa6a880c80f3bae897dd7557345 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 13 Mar 2015 11:46:08 +0200 Subject: [PATCH 07/22] CppTools: Add a failing test for partial template specialization Task-number: QTCREATORBUG-14036 Change-Id: I7545bfa40ec3e1399d57bf5ab2486318aa1fcb9f Reviewed-by: Nikolai Kosjar --- src/plugins/cpptools/cppcompletion_test.cpp | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index f2eebca8672..405867148d0 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -319,6 +319,7 @@ void CppToolsPlugin::test_completion() QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort); QEXPECT_FAIL("enum_in_class_accessed_in_member_func_cxx11", "QTCREATORBUG-13757", Abort); QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort); + QEXPECT_FAIL("pointer_partial_specialization", "QTCREATORBUG-14036", Abort); QCOMPARE(actualCompletions, expectedCompletions); } @@ -2654,6 +2655,35 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("operator ->") << QLatin1String("t") << QLatin1String("iterator")); + + QTest::newRow("pointer_partial_specialization") << _( + "template\n" + "struct Traits { typedef typename T::pointer pointer; };\n" + "\n" + "template\n" + "struct Traits<_Tp*> { typedef _Tp *pointer; };\n" + "\n" + "template\n" + "class Temp\n" + "{\n" + "protected:\n" + " typedef Traits TraitsT;\n" + "\n" + "public:\n" + " typedef typename TraitsT::pointer pointer;\n" + " pointer p;\n" + "};\n" + "\n" + "struct Foo { int bar; };\n" + "\n" + "void func()\n" + "{\n" + " Temp t;\n" + " @\n" + "}\n" + ) << _("t.p->") << (QStringList() + << QLatin1String("Foo") + << QLatin1String("bar")); } void CppToolsPlugin::test_completion_member_access_operator() From ca41c24cc68ea51733ec329b50da219d99d533b4 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 10 Mar 2015 11:35:09 +0100 Subject: [PATCH 08/22] Find: Show number of replaced items after replace all Show a fading indicator over the editor, or over the main window in case of global search & replace. Change-Id: I84a982bcfed558c0f84c08c3625a0cad4c5409d6 Task-number: QTCREATORBUG-3494 Reviewed-by: Orgad Shaneh --- src/libs/utils/fadingindicator.cpp | 12 ++++++------ src/libs/utils/fadingindicator.h | 8 +++++++- src/plugins/coreplugin/find/currentdocumentfind.cpp | 9 ++++++++- src/plugins/texteditor/basefilefind.cpp | 8 ++++++-- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/libs/utils/fadingindicator.cpp b/src/libs/utils/fadingindicator.cpp index bfef6771856..aae0600be08 100644 --- a/src/libs/utils/fadingindicator.cpp +++ b/src/libs/utils/fadingindicator.cpp @@ -48,7 +48,7 @@ class FadingIndicatorPrivate : public QWidget Q_OBJECT public: - FadingIndicatorPrivate(QWidget *parent = 0) + FadingIndicatorPrivate(QWidget *parent, FadingIndicator::TextSize size) : QWidget(parent) { m_effect = new QGraphicsOpacityEffect(this); @@ -57,7 +57,7 @@ public: m_label = new QLabel; QFont font = m_label->font(); - font.setPixelSize(45); + font.setPixelSize(size == FadingIndicator::LargeText ? 45 : 22); m_label->setFont(font); QPalette pal = palette(); pal.setColor(QPalette::Foreground, pal.color(QPalette::Background)); @@ -126,16 +126,16 @@ private: namespace FadingIndicator { -void showText(QWidget *parent, const QString &text) +void showText(QWidget *parent, const QString &text, TextSize size) { - auto indicator = new Internal::FadingIndicatorPrivate(parent); + auto indicator = new Internal::FadingIndicatorPrivate(parent, size); indicator->setText(text); - indicator->run(1000); // deletes itself + indicator->run(2500); // deletes itself } void showPixmap(QWidget *parent, const QString &pixmap) { - auto indicator = new Internal::FadingIndicatorPrivate(parent); + auto indicator = new Internal::FadingIndicatorPrivate(parent, LargeText); indicator->setPixmap(pixmap); indicator->run(300); // deletes itself } diff --git a/src/libs/utils/fadingindicator.h b/src/libs/utils/fadingindicator.h index 7738e751a64..3266feb66ad 100644 --- a/src/libs/utils/fadingindicator.h +++ b/src/libs/utils/fadingindicator.h @@ -40,7 +40,13 @@ namespace Utils { namespace FadingIndicator { -QTCREATOR_UTILS_EXPORT void showText(QWidget *parent, const QString &text); +enum TextSize { + SmallText, + LargeText +}; + +QTCREATOR_UTILS_EXPORT void showText(QWidget *parent, const QString &text, + TextSize size = LargeText); QTCREATOR_UTILS_EXPORT void showPixmap(QWidget *parent, const QString &pixmap); } // FadingIndicator diff --git a/src/plugins/coreplugin/find/currentdocumentfind.cpp b/src/plugins/coreplugin/find/currentdocumentfind.cpp index dea2b315815..a08ee98f8c4 100644 --- a/src/plugins/coreplugin/find/currentdocumentfind.cpp +++ b/src/plugins/coreplugin/find/currentdocumentfind.cpp @@ -32,6 +32,8 @@ #include #include + +#include #include #include @@ -134,7 +136,12 @@ bool CurrentDocumentFind::replaceStep(const QString &before, const QString &afte int CurrentDocumentFind::replaceAll(const QString &before, const QString &after, FindFlags findFlags) { QTC_ASSERT(m_currentFind, return 0); - return m_currentFind->replaceAll(before, after, findFlags); + QTC_CHECK(m_currentWidget); + int count = m_currentFind->replaceAll(before, after, findFlags); + Utils::FadingIndicator::showText(m_currentWidget, + tr("%1 occurrences replaced.").arg(count), + Utils::FadingIndicator::SmallText); + return count; } void CurrentDocumentFind::defineFindScope() diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 9e00297faf5..49bf4f4b913 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -42,9 +42,10 @@ #include #include #include -#include -#include +#include #include +#include +#include #include #include @@ -208,6 +209,9 @@ void BaseFileFind::doReplace(const QString &text, { QStringList files = replaceAll(text, items, preserveCase); if (!files.isEmpty()) { + Utils::FadingIndicator::showText(ICore::mainWindow(), + tr("%1 occurrences replaced.").arg(items.size()), + Utils::FadingIndicator::SmallText); DocumentManager::notifyFilesChangedInternally(files); SearchResultWindow::instance()->hide(); } From 1c8b691620afb32dce65381b9c31573d756b2e23 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 12 Mar 2015 15:46:16 +0100 Subject: [PATCH 09/22] DiffEditor: Do not soft-assert when saving Do not soft-assert when saving a diff that was saved before. Change-Id: Iebe06f2bf2ab966869181e0237ed6cc69b2f6045 Reviewed-by: Jarek Kobus --- src/plugins/diffeditor/diffeditordocument.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp index b091c3eecec..510401e95a6 100644 --- a/src/plugins/diffeditor/diffeditordocument.cpp +++ b/src/plugins/diffeditor/diffeditordocument.cpp @@ -76,10 +76,11 @@ DiffEditorDocument::~DiffEditorDocument() */ void DiffEditorDocument::setController(DiffEditorController *controller) { - QTC_ASSERT(isTemporary(), return); if (m_controller == controller) return; + QTC_ASSERT(isTemporary(), return); + if (m_controller) m_controller->deleteLater(); m_controller = controller; From cbc62a2905118eee342622676cf1e1f9c18dea8e Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Fri, 13 Mar 2015 13:22:55 +0100 Subject: [PATCH 10/22] FlatModel: Fix a crash on restoring session Still wondering how exactly it happens. This results in parent() returning a invalid QModelIndex() for a valid QModelIndex() which should not happen, but this prevents the crash. Also add some minimal logging. Change-Id: I36559c1f9cda39e8b8a80f487651ad58f7c2cc05 Task-number: QTCREATORBUG-14134 Reviewed-by: Orgad Shaneh Reviewed-by: Christian Stenger Reviewed-by: Daniel Teske --- src/plugins/projectexplorer/projectmodels.cpp | 56 +++++++++++-------- src/plugins/projectexplorer/projectmodels.h | 4 +- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp index f99e99d2e8c..ade67e94900 100644 --- a/src/plugins/projectexplorer/projectmodels.cpp +++ b/src/plugins/projectexplorer/projectmodels.cpp @@ -42,6 +42,7 @@ #include #include #include +#include namespace ProjectExplorer { @@ -241,27 +242,9 @@ QModelIndex FlatModel::parent(const QModelIndex &idx) const QModelIndex parentIndex; if (Node *node = nodeForIndex(idx)) { FolderNode *parentNode = visibleFolderNode(node->parentFolderNode()); - if (parentNode) { - FolderNode *grandParentNode = visibleFolderNode(parentNode->parentFolderNode()); - if (grandParentNode) { - QHash >::const_iterator it = m_childNodes.constFind(grandParentNode); - if (it == m_childNodes.constEnd()) { - fetchMore(grandParentNode); - it = m_childNodes.constFind(grandParentNode); - } - Q_ASSERT(it != m_childNodes.constEnd()); - const int row = it.value().indexOf(parentNode); - Q_ASSERT(row >= 0); - parentIndex = createIndex(row, 0, parentNode); - } else { - // top level node, parent is session - parentIndex = index(0, 0, QModelIndex()); - } - } + if (parentNode) + return indexForNode(parentNode); } - -// qDebug() << "parent of " << idx.data(Project::FilePathRole) << " is " << parentIndex.data(Project::FilePathRole); - return parentIndex; } @@ -444,6 +427,7 @@ void FlatModel::recursiveAddFileNodes(FolderNode *startNode, QList *list QList FlatModel::childNodes(FolderNode *parentNode, const QSet &blackList) const { + qCDebug(logger()) << "FlatModel::childNodes for " << parentNode->displayName(); QList nodeList; if (parentNode->nodeType() == SessionNodeType) { @@ -458,6 +442,7 @@ QList FlatModel::childNodes(FolderNode *parentNode, const QSet &bl recursiveAddFileNodes(parentNode, &nodeList, blackList + nodeList.toSet()); } Utils::sort(nodeList, sortNodes); + qCDebug(logger()) << " found" << nodeList.size() << "nodes"; return nodeList; } @@ -519,7 +504,7 @@ QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const return data; } -QModelIndex FlatModel::indexForNode(const Node *node_) +QModelIndex FlatModel::indexForNode(const Node *node_) const { // We assume that we are only called for nodes that are represented @@ -610,6 +595,12 @@ bool FlatModel::filter(Node *node) const return isHidden; } +const QLoggingCategory &FlatModel::logger() +{ + static QLoggingCategory logger("qtc.projectexplorer.flatmodel"); + return logger; +} + bool isSorted(const QList &nodes) { int size = nodes.size(); @@ -623,11 +614,21 @@ bool isSorted(const QList &nodes) /// slots and all the fun void FlatModel::added(FolderNode* parentNode, const QList &newNodeList) { + qCDebug(logger()) << "FlatModel::added" << parentNode->path() << newNodeList.size() << "nodes"; QModelIndex parentIndex = indexForNode(parentNode); // Old list QHash >::const_iterator it = m_childNodes.constFind(parentNode); - if (it == m_childNodes.constEnd()) + if (it == m_childNodes.constEnd()) { + if (!parentIndex.isValid()) { + qCDebug(logger()) << " parent not mapped returning"; + return; + } + qCDebug(logger()) << " updated m_childNodes"; + beginInsertRows(parentIndex, 0, newNodeList.size() - 1); + m_childNodes.insert(parentNode, newNodeList); + endInsertRows(); return; + } QList oldNodeList = it.value(); // Compare lists and emit signals, and modify m_childNodes on the fly @@ -658,6 +659,7 @@ void FlatModel::added(FolderNode* parentNode, const QList &newNodeList) beginInsertRows(parentIndex, 0, newNodeList.size() - 1); m_childNodes.insert(parentNode, newNodeList); endInsertRows(); + qCDebug(logger()) << " updated m_childNodes"; return; } @@ -705,15 +707,19 @@ void FlatModel::added(FolderNode* parentNode, const QList &newNodeList) endInsertRows(); oldIter = oldNodeList.constBegin() + pos; } + qCDebug(logger()) << " updated m_childNodes"; } void FlatModel::removed(FolderNode* parentNode, const QList &newNodeList) { + qCDebug(logger()) << "FlatModel::removed" << parentNode->path() << newNodeList.size() << "nodes"; QModelIndex parentIndex = indexForNode(parentNode); // Old list QHash >::const_iterator it = m_childNodes.constFind(parentNode); - if (it == m_childNodes.constEnd()) + if (it == m_childNodes.constEnd()) { + qCDebug(logger()) << " unmapped node"; return; + } QList oldNodeList = it.value(); // Compare lists and emit signals, and modify m_childNodes on the fly @@ -743,6 +749,7 @@ void FlatModel::removed(FolderNode* parentNode, const QList &newNodeList) beginRemoveRows(parentIndex, 0, oldNodeList.size() - 1); m_childNodes.insert(parentNode, newNodeList); endRemoveRows(); + qCDebug(logger()) << " updated m_childNodes"; return; } @@ -789,6 +796,7 @@ void FlatModel::removed(FolderNode* parentNode, const QList &newNodeList) endRemoveRows(); oldIter = oldNodeList.constBegin() + pos; } + qCDebug(logger()) << " updated m_childNodes"; } void FlatModel::aboutToShowInSimpleTreeChanged(FolderNode* node) @@ -818,6 +826,7 @@ void FlatModel::showInSimpleTreeChanged(FolderNode *node) void FlatModel::foldersAboutToBeAdded(FolderNode *parentFolder, const QList &newFolders) { + qCDebug(logger()) << "FlatModel::foldersAboutToBeAdded"; Q_UNUSED(newFolders) m_parentFolderForChange = parentFolder; } @@ -886,6 +895,7 @@ void FlatModel::foldersRemoved() void FlatModel::filesAboutToBeAdded(FolderNode *folder, const QList &newFiles) { + qCDebug(logger()) << "FlatModel::filesAboutToBeAdded"; Q_UNUSED(newFiles) m_parentFolderForChange = folder; } diff --git a/src/plugins/projectexplorer/projectmodels.h b/src/plugins/projectexplorer/projectmodels.h index baa146ae23b..0938ac01173 100644 --- a/src/plugins/projectexplorer/projectmodels.h +++ b/src/plugins/projectexplorer/projectmodels.h @@ -75,7 +75,7 @@ public: void setStartupProject(ProjectNode *projectNode); Node *nodeForIndex(const QModelIndex &index) const; - QModelIndex indexForNode(const Node *node); + QModelIndex indexForNode(const Node *node) const; bool projectFilterEnabled(); bool generatedFilesFilterEnabled(); @@ -133,6 +133,8 @@ private: FolderNode *m_parentFolderForChange; Node *m_nodeForSortKeyChange; + static const QLoggingCategory &logger(); + friend class FlatModelManager; }; From 66c29ea8ec306768d9210df7e99142eb1cd616f5 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 12 Mar 2015 15:55:58 +0100 Subject: [PATCH 11/22] Squish: Fix tst_CSUP03 Change-Id: I6556440ebcf77ae3164c4f659ff1c4b6e189d6ea Reviewed-by: Robert Loehning --- tests/system/suite_CSUP/tst_CSUP03/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/suite_CSUP/tst_CSUP03/test.py b/tests/system/suite_CSUP/tst_CSUP03/test.py index c8eb1339381..2c6dc9b854e 100644 --- a/tests/system/suite_CSUP/tst_CSUP03/test.py +++ b/tests/system/suite_CSUP/tst_CSUP03/test.py @@ -88,7 +88,7 @@ def main(): if current != models[0]: selectCodeModel(current) test.log("Testing code model: %s" % current) - openDocument("untitled.Sources.main\\.cpp") + openDocument("%s.Sources.main\\.cpp" % projectName) editor = getEditorForFileSuffix("main.cpp") if not editor: test.fatal("Failed to get an editor - leaving test.") From 4e1d281963cd8002c812c05597a64219577b07f5 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 13 Mar 2015 11:25:12 +0100 Subject: [PATCH 12/22] C++: Fix crash on invalid function qualified name Task-number: QTCREATORBUG-14135 Change-Id: I94e850f729bd3dbf4212960c7a980a1f118030b4 Reviewed-by: Orgad Shaneh --- src/libs/cplusplus/LookupContext.cpp | 5 ++++- .../cplusplus/checksymbols/tst_checksymbols.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 35be29d6f23..56119f245b4 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -1706,7 +1706,10 @@ bool CreateBindings::visit(Declaration *decl) bool CreateBindings::visit(Function *function) { ClassOrNamespace *previous = _currentClassOrNamespace; - _currentClassOrNamespace = lookupType(function, previous); + ClassOrNamespace *binding = lookupType(function, previous); + if (!binding) + return false; + _currentClassOrNamespace = binding; for (unsigned i = 0, count = function->memberCount(); i < count; ++i) { Symbol *s = function->memberAt(i); if (Block *b = s->asBlock()) diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index 89e2e624f73..e688fb7e021 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -194,6 +194,8 @@ private slots: void test_checksymbols_infiniteLoop_data(); void test_checksymbols_infiniteLoop(); + + void test_parentOfBlock(); }; void tst_CheckSymbols::test_checksymbols() @@ -1774,6 +1776,19 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop() TestCase::runCheckSymbols(document1, snapshot); } +void tst_CheckSymbols::test_parentOfBlock() +{ + const QByteArray source = "void C::f()\n" + "{\n" + " enum E { e1 };\n" + "}\n"; + + const Document::Ptr document = TestCase::createDocument(QLatin1String("file1.cpp"), source); + Snapshot snapshot; + snapshot.insert(document); + TestCase::runCheckSymbols(document, snapshot); +} + void tst_CheckSymbols::test_checksymbols_infiniteLoop_data() { QTest::addColumn("source1"); From 3ab5e5231c14717bb9e5a3f003e662d74f972b3f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 11 Mar 2015 11:21:45 +0100 Subject: [PATCH 13/22] CppEditor: Extract some functions Change-Id: Ie564c35b106981d986881f12495ca3cab578c720 Reviewed-by: Erik Verbruggen --- .../cppeditor/cppfollowsymbolundercursor.cpp | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index 1f493242463..793d0312067 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -395,6 +395,36 @@ Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *s return symbolFinder->findMatchingDefinition(symbol, snapshot); } +void maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor) +{ + QTC_ASSERT(expression, return); + QTextDocument *textDocument = textCursor.document(); + QTC_ASSERT(textDocument, return); + + // Skip white space + QTextCursor cursor(textCursor); + while (textDocument->characterAt(cursor.position()).isSpace() + && cursor.movePosition(QTextCursor::NextCharacter)) { + } + + // Find/Include (...) + if (textDocument->characterAt(cursor.position()) == QLatin1Char('(')) { + if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) + expression->append(cursor.selectedText()); + } +} + +QString expressionUnderCursorAsString(const QTextCursor &textCursor, + const LanguageFeatures &features) +{ + ExpressionUnderCursor expressionUnderCursor(features); + QString expression = expressionUnderCursor(textCursor); + + maybeAppendArgumentOrParameterList(&expression, textCursor); + + return expression; +} + } // anonymous namespace FollowSymbolUnderCursor::FollowSymbolUnderCursor(CppEditorWidget *widget) @@ -613,22 +643,8 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs return link; // Evaluate the type of the expression under the cursor - ExpressionUnderCursor expressionUnderCursor(features); - QString expression = expressionUnderCursor(tc); - - for (int pos = tc.position();; ++pos) { - const QChar ch = document->characterAt(pos); - if (ch.isSpace()) - continue; - if (ch == QLatin1Char('(') && !expression.isEmpty()) { - tc.setPosition(pos); - if (TextBlockUserData::findNextClosingParenthesis(&tc, true)) - expression.append(tc.selectedText()); - } - - break; - } - + QTC_CHECK(document == tc.document()); + const QString expression = expressionUnderCursorAsString(tc, features); const QSharedPointer typeOfExpression(new TypeOfExpression); typeOfExpression->init(doc, snapshot); // make possible to instantiate templates From 251b444cfd4618d49135458f0d9a766e43c8309f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 11 Mar 2015 13:45:11 +0100 Subject: [PATCH 14/22] CppEditor: Fix Follow Symbol on trailing return type For the function auto foo() -> @Foo {} whereas '@' denotes the cursor position, we detected the expression under cursor as "foo() -> Foo" and tried to resolve the member "Foo" within the type of "foo()". ExpressionUnderCursor can't detect whether we are on a trailing return type since it only looks at the tokens. Thus, check also the AST. Task-number: QTCREATORBUG-13096 Change-Id: Ifc14e402fb70e722940e5fa13f1eaaa9973362e4 Reviewed-by: Erik Verbruggen --- .../cppeditor/cppfollowsymbolundercursor.cpp | 57 ++++++++++++++++--- .../followsymbol_switchmethoddecldef_test.cpp | 5 ++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index 793d0312067..92498eef9aa 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -395,11 +395,11 @@ Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *s return symbolFinder->findMatchingDefinition(symbol, snapshot); } -void maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor) +bool maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor) { - QTC_ASSERT(expression, return); + QTC_ASSERT(expression, return false); QTextDocument *textDocument = textCursor.document(); - QTC_ASSERT(textDocument, return); + QTC_ASSERT(textDocument, return false); // Skip white space QTextCursor cursor(textCursor); @@ -407,20 +407,62 @@ void maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor & && cursor.movePosition(QTextCursor::NextCharacter)) { } - // Find/Include (...) + // Find/Include "(arg1, arg2, ...)" if (textDocument->characterAt(cursor.position()) == QLatin1Char('(')) { - if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) + if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) { expression->append(cursor.selectedText()); + return true; + } + } + + return false; +} + +bool isCursorOnTrailingReturnType(const QList &astPath) +{ + for (auto it = astPath.cend() - 1, begin = astPath.cbegin(); it >= begin; --it) { + const auto nextIt = it + 1; + const auto nextNextIt = nextIt + 1; + if (nextNextIt != astPath.cend() && (*it)->asTrailingReturnType()) { + return (*nextIt)->asNamedTypeSpecifier() + && ((*nextNextIt)->asSimpleName() + || (*nextNextIt)->asQualifiedName() + || (*nextNextIt)->asTemplateId()); + } + } + + return false; +} + +void maybeFixExpressionInTrailingReturnType(QString *expression, + const QTextCursor &textCursor, + const Document::Ptr documentFromSemanticInfo) +{ + QTC_ASSERT(expression, return); + + if (!documentFromSemanticInfo) + return; + + const QString arrow = QLatin1String("->"); + const int arrowPosition = expression->lastIndexOf(arrow); + if (arrowPosition != -1) { + ASTPath astPathFinder(documentFromSemanticInfo); + const QList astPath = astPathFinder(textCursor); + + if (isCursorOnTrailingReturnType(astPath)) + *expression = expression->mid(arrowPosition + arrow.size()).trimmed(); } } QString expressionUnderCursorAsString(const QTextCursor &textCursor, + const Document::Ptr documentFromSemanticInfo, const LanguageFeatures &features) { ExpressionUnderCursor expressionUnderCursor(features); QString expression = expressionUnderCursor(textCursor); - maybeAppendArgumentOrParameterList(&expression, textCursor); + if (!maybeAppendArgumentOrParameterList(&expression, textCursor)) + maybeFixExpressionInTrailingReturnType(&expression, textCursor, documentFromSemanticInfo); return expression; } @@ -644,7 +686,8 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs // Evaluate the type of the expression under the cursor QTC_CHECK(document == tc.document()); - const QString expression = expressionUnderCursorAsString(tc, features); + const QString expression = expressionUnderCursorAsString(tc, documentFromSemanticInfo, + features); const QSharedPointer typeOfExpression(new TypeOfExpression); typeOfExpression->init(doc, snapshot); // make possible to instantiate templates diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 6fad7736c89..960ea4cec78 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -955,6 +955,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data() "class Foo { void $" TEST_UNICODE_IDENTIFIER "(); };\n" "void Foo::@" TEST_UNICODE_IDENTIFIER "() {}\n" ); + + QTest::newRow("trailingReturnType") << _( + "struct $Foo {};\n" + "auto foo() -> @Foo {}\n" + ); } void CppEditorPlugin::test_FollowSymbolUnderCursor() From 6a94f7e3554ec0e4a5017fac8ff350267a7cdf01 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 12 Mar 2015 16:25:45 +0100 Subject: [PATCH 15/22] CppEditor: Add basic test for ExtractFunction Change-Id: I44f2edb2905e202669630ab5da85066011491fae Reviewed-by: Erik Verbruggen --- src/plugins/cppeditor/cppeditorplugin.h | 3 + src/plugins/cppeditor/cppeditortestcase.cpp | 24 +++++++- src/plugins/cppeditor/cppeditortestcase.h | 4 ++ src/plugins/cppeditor/cppquickfix_test.cpp | 67 +++++++++++++++++++-- src/plugins/cppeditor/cppquickfix_test.h | 11 +++- src/plugins/cppeditor/cppquickfixes.cpp | 16 ++++- src/plugins/cppeditor/cppquickfixes.h | 9 ++- 7 files changed, 122 insertions(+), 12 deletions(-) diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index 318edfc5c3f..a2773621892 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -192,6 +192,9 @@ private slots: void test_quickfix_AssignToLocalVariable_templates(); + void test_quickfix_ExtractFunction_data(); + void test_quickfix_ExtractFunction(); + void test_quickfix_ExtractLiteralAsParameter_typeDeduction_data(); void test_quickfix_ExtractLiteralAsParameter_typeDeduction(); void test_quickfix_ExtractLiteralAsParameter_freeFunction_separateFiles(); diff --git a/src/plugins/cppeditor/cppeditortestcase.cpp b/src/plugins/cppeditor/cppeditortestcase.cpp index 84f3f0ad7f0..e276eb46ae9 100644 --- a/src/plugins/cppeditor/cppeditortestcase.cpp +++ b/src/plugins/cppeditor/cppeditortestcase.cpp @@ -40,6 +40,8 @@ #include +#include + using namespace CppEditor::Internal; namespace CppEditor { @@ -48,14 +50,34 @@ namespace Tests { TestDocument::TestDocument(const QByteArray &fileName, const QByteArray &source, char cursorMarker) : CppTools::Tests::TestDocument(fileName, source, cursorMarker) - , m_cursorPosition(m_source.indexOf(QLatin1Char(m_cursorMarker))) + , m_cursorPosition(-1) + , m_anchorPosition(-1) + , m_selectionStartMarker(QLatin1Char(m_cursorMarker) + QLatin1String("{start}")) + , m_selectionEndMarker(QLatin1Char(m_cursorMarker) + QLatin1String("{end}")) , m_editor(0) , m_editorWidget(0) { + // Try to find selection markers + const int selectionStartIndex = m_source.indexOf(m_selectionStartMarker); + const int selectionEndIndex = m_source.indexOf(m_selectionEndMarker); + const bool bothSelectionMarkersFound = selectionStartIndex != -1 && selectionEndIndex != -1; + const bool noneSelectionMarkersFounds = selectionStartIndex == -1 && selectionEndIndex == -1; + QTC_ASSERT(bothSelectionMarkersFound || noneSelectionMarkersFounds, return); + + if (selectionStartIndex != -1) { + m_cursorPosition = selectionEndIndex; + m_anchorPosition = selectionStartIndex; + + // No selection markers found, so check for simple cursorMarker + } else { + m_cursorPosition = m_source.indexOf(QLatin1Char(cursorMarker)); + } } bool TestDocument::hasCursorMarker() const { return m_cursorPosition != -1; } +bool TestDocument::hasAnchorMarker() const { return m_anchorPosition != -1; } + TestCase::TestCase(bool runGarbageCollector) : CppTools::Tests::TestCase(runGarbageCollector) { diff --git a/src/plugins/cppeditor/cppeditortestcase.h b/src/plugins/cppeditor/cppeditortestcase.h index 94c65434393..fdcbf73741c 100644 --- a/src/plugins/cppeditor/cppeditortestcase.h +++ b/src/plugins/cppeditor/cppeditortestcase.h @@ -50,9 +50,13 @@ public: TestDocument(const QByteArray &fileName, const QByteArray &source, char cursorMarker = '@'); bool hasCursorMarker() const; + bool hasAnchorMarker() const; public: int m_cursorPosition; + int m_anchorPosition; + QString m_selectionStartMarker; + QString m_selectionEndMarker; CppEditor *m_editor; CppEditorWidget *m_editorWidget; }; diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 4a203153d36..aebba96ec0e 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -73,8 +73,27 @@ QuickFixTestDocument::QuickFixTestDocument(const QByteArray &fileName, : TestDocument(fileName, source) , m_expectedSource(QString::fromUtf8(expectedSource)) { - if (m_cursorPosition > -1) + removeMarkers(); +} + +void QuickFixTestDocument::removeMarkers() +{ + // Remove selection markers + if (m_anchorPosition != -1) { + if (m_anchorPosition < m_cursorPosition) { + m_source.remove(m_anchorPosition, m_selectionStartMarker.size()); + m_cursorPosition -= m_selectionStartMarker.size(); + m_source.remove(m_cursorPosition, m_selectionEndMarker.size()); + } else { + m_source.remove(m_cursorPosition, m_selectionEndMarker.size()); + m_anchorPosition -= m_selectionEndMarker.size(); + m_source.remove(m_anchorPosition, m_selectionStartMarker.size()); + } + + // Remove simple cursor marker + } else if (m_cursorPosition != -1) { m_source.remove(m_cursorPosition, 1); + } const int cursorPositionInExpectedSource = m_expectedSource.indexOf(QLatin1Char(m_cursorMarker)); @@ -135,9 +154,16 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QListm_editor); // Set cursor position - const int cursorPosition = document->hasCursorMarker() - ? document->m_cursorPosition : 0; - document->m_editor->setCursorPosition(cursorPosition); + if (document->hasCursorMarker()) { + if (document->hasAnchorMarker()) { + document->m_editor->setCursorPosition(document->m_anchorPosition); + document->m_editor->select(document->m_cursorPosition); + } else { + document->m_editor->setCursorPosition(document->m_cursorPosition); + } + } else { + document->m_editor->setCursorPosition(0); + } // Rehighlight waitForRehighlightedSemanticDocument(document->m_editorWidget); @@ -4349,6 +4375,39 @@ void CppEditorPlugin::test_quickfix_AssignToLocalVariable_templates() QuickFixOperationTest(testDocuments, &factory); } +void CppEditorPlugin::test_quickfix_ExtractFunction_data() +{ + QTest::addColumn("original"); + QTest::addColumn("expected"); + + QTest::newRow("basic") + << _("void f()\n" + "{\n" + " @{start}g();@{end}\n" + "}\n") + << _("void extracted()\n" + "{\n" + " g();\n" + "}\n" + "\n" + "void f()\n" + "{\n" + " extracted();\n" + "}\n"); +} + +void CppEditorPlugin::test_quickfix_ExtractFunction() +{ + QFETCH(QByteArray, original); + QFETCH(QByteArray, expected); + + QList testDocuments; + testDocuments << QuickFixTestDocument::create("file.h", original, expected); + + ExtractFunction factory([]() { return QLatin1String("extracted"); }); + QuickFixOperationTest(testDocuments, &factory); +} + void CppEditorPlugin::test_quickfix_ExtractLiteralAsParameter_typeDeduction_data() { QTest::addColumn("typeString"); diff --git a/src/plugins/cppeditor/cppquickfix_test.h b/src/plugins/cppeditor/cppquickfix_test.h index 2950a0be4db..14c3d415d06 100644 --- a/src/plugins/cppeditor/cppquickfix_test.h +++ b/src/plugins/cppeditor/cppquickfix_test.h @@ -50,8 +50,9 @@ namespace Tests { /// Represents a test document before and after applying the quick fix. /// /// A TestDocument's source may contain an '@' character to denote -/// the cursor position. This marker is removed before the Editor reads -/// the document. +/// the cursor position. For selections the markers "@{start}" and +/// "@{end}" can be used. The markers are removed before the editor +/// reads the document. /// class QuickFixTestDocument : public TestDocument @@ -65,6 +66,9 @@ public: static Ptr create(const QByteArray &fileName, const QByteArray &source, const QByteArray &expectedSource); +private: + void removeMarkers(); + public: QString m_expectedSource; }; @@ -74,7 +78,8 @@ typedef QList QuickFixTestDocuments; class BaseQuickFixTestCase : public TestCase { public: - /// Exactly one QuickFixTestDocument must contain the cursor position marker '@'. + /// Exactly one QuickFixTestDocument must contain the cursor position marker '@' + /// or "@{start}" and "@{end}" BaseQuickFixTestCase(const QList &testDocuments, const CppTools::ProjectPart::HeaderPaths &headerPaths = CppTools::ProjectPart::HeaderPaths()); diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index d71303eb25e..483720d5808 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -3118,13 +3118,16 @@ public: int extractionEnd, FunctionDefinitionAST *refFuncDef, Symbol *funcReturn, - QList > relevantDecls) + QList > relevantDecls, + ExtractFunction::FunctionNameGetter functionNameGetter + = ExtractFunction::FunctionNameGetter()) : CppQuickFixOperation(interface) , m_extractionStart(extractionStart) , m_extractionEnd(extractionEnd) , m_refFuncDef(refFuncDef) , m_funcReturn(funcReturn) , m_relevantDecls(relevantDecls) + , m_functionNameGetter(functionNameGetter) { setDescription(QCoreApplication::translate("QuickFix::ExtractFunction", "Extract Function")); } @@ -3135,7 +3138,7 @@ public: CppRefactoringChanges refactoring(snapshot()); CppRefactoringFilePtr currentFile = refactoring.file(fileName()); - const QString &funcName = getFunctionName(); + const QString &funcName = m_functionNameGetter ? m_functionNameGetter() : getFunctionName(); if (funcName.isEmpty()) return; @@ -3302,6 +3305,7 @@ public: FunctionDefinitionAST *m_refFuncDef; Symbol *m_funcReturn; QList > m_relevantDecls; + ExtractFunction::FunctionNameGetter m_functionNameGetter; }; QPair assembleDeclarationData(const QString &specifiers, DeclaratorAST *decltr, @@ -3505,6 +3509,11 @@ public: } // anonymous namespace +ExtractFunction::ExtractFunction(FunctionNameGetter functionNameGetter) + : m_functionNameGetter(functionNameGetter) +{ +} + void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOperations &result) { CppRefactoringFilePtr file = interface.currentFile(); @@ -3632,7 +3641,8 @@ void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOpera analyser.m_extractionEnd, refFuncDef, funcReturn, - relevantDecls)); + relevantDecls, + m_functionNameGetter)); } namespace { diff --git a/src/plugins/cppeditor/cppquickfixes.h b/src/plugins/cppeditor/cppquickfixes.h index b51cf185364..2068593efe8 100644 --- a/src/plugins/cppeditor/cppquickfixes.h +++ b/src/plugins/cppeditor/cppquickfixes.h @@ -34,11 +34,12 @@ #include "cppquickfix.h" #include - #include #include +#include + QT_BEGIN_NAMESPACE class QByteArray; template class QList; @@ -435,7 +436,13 @@ public: class ExtractFunction : public CppQuickFixFactory { public: + typedef std::function FunctionNameGetter; + + ExtractFunction(FunctionNameGetter functionNameGetter = FunctionNameGetter()); void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result); + +private: + FunctionNameGetter m_functionNameGetter; // For tests to avoid GUI pop-up. }; /*! From 3b2a13e9c967a07dd5c68f63f8af50791b94eb4d Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 16 Jan 2015 14:50:06 +0100 Subject: [PATCH 16/22] Clang: Offer snippets in completion Change-Id: I3d0cce5d408d11998aec024b23d9a218a75df3a3 Task-number: QTCREATORBUG-12935 Reviewed-by: Erik Verbruggen --- src/plugins/clangcodemodel/clangcompletion.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/clangcodemodel/clangcompletion.cpp b/src/plugins/clangcodemodel/clangcompletion.cpp index 6cc1eba3952..f066be4c3e9 100644 --- a/src/plugins/clangcodemodel/clangcompletion.cpp +++ b/src/plugins/clangcodemodel/clangcompletion.cpp @@ -1061,6 +1061,8 @@ int ClangCompletionAssistProcessor::startCompletionInternal(const QString fileNa foreach (ClangAssistProposalItem *item, items.values()) m_completions.append(item); + addSnippets(); + return m_startPosition; } From 58ffa2cf5f07fccc37c1a983999e578a54b89d3b Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 13 Mar 2015 14:56:04 +0100 Subject: [PATCH 17/22] Never save Welcome as the mode to restore for sessions With the recent fix for restoring the mode when restoring sessions (0d10ecd66817632c85470dff7bd701e8f3bf31d2), it would save and later restore Welcome mode when switching sessions on Welcome mode. Change-Id: I285dc1f25734b8358ca04cfdb887aafa93576c3d Reviewed-by: Daniel Teske --- src/plugins/projectexplorer/session.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 55425a9de28..7b0716ffc24 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -178,7 +178,8 @@ bool SessionManager::isDefaultSession(const QString &session) void SessionManager::saveActiveMode(IMode *mode) { - setValue(QLatin1String("ActiveMode"), mode->id().toString()); + if (mode->id() != Id(Core::Constants::MODE_WELCOME)) + setValue(QLatin1String("ActiveMode"), mode->id().toString()); } void SessionManager::clearProjectFileCache() From 2a2d0a0c44b3b527a976683cd5c3c51f1f76940f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 13 Mar 2015 14:56:17 +0100 Subject: [PATCH 18/22] Remove unused constants. Change-Id: I95073d8b0b73398bc48b7937d50a1bcced1e8cc1 Reviewed-by: Daniel Teske --- src/plugins/coreplugin/coreconstants.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 1c43fd7dfc5..e3d3ecb7857 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -38,11 +38,8 @@ namespace Constants { // Modes const char MODE_WELCOME[] = "Welcome"; -const char MODE_WELCOME_TYPE[] = "Type.Welcome"; const char MODE_EDIT[] = "Edit"; -const char MODE_EDIT_TYPE[] = "Type.Edit"; const char MODE_DESIGN[] = "Design"; -const char MODE_DESIGN_TYPE[] = "Type.Design"; const int P_MODE_WELCOME = 100; const int P_MODE_EDIT = 90; const int P_MODE_DESIGN = 89; From a341094a684fa304a2da1003aa8edd1d9226c58d Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 13 Mar 2015 10:37:36 +0200 Subject: [PATCH 19/22] C++: Fix preprocessing of comments within function-like macro Task-number: QTCREATORBUG-9535 Change-Id: Ifd94f674214314b3694be74cca297ddab873cd8c Reviewed-by: Nikolai Kosjar --- src/libs/cplusplus/pp-engine.cpp | 62 ++++++-- src/libs/cplusplus/pp-engine.h | 2 + .../preprocessor/tst_preprocessor.cpp | 148 +++++++++++++++++- 3 files changed, 188 insertions(+), 24 deletions(-) diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index ba8470e50e1..93c743133ed 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -900,11 +900,7 @@ void Preprocessor::skipPreprocesorDirective(PPToken *tk) ScopedBoolSwap s(m_state.m_inPreprocessorDirective, true); while (isContinuationToken(*tk)) { - if (tk->isComment()) { - synchronizeOutputLines(*tk); - enforceSpacing(*tk, true); - currentOutputBuffer().append(tk->tokenStart(), tk->bytes()); - } + scanComment(tk); lex(tk); } } @@ -1461,6 +1457,23 @@ void Preprocessor::preprocess(const QString &fileName, const QByteArray &source, m_state.popTokenBuffer(); } +bool Preprocessor::scanComment(Preprocessor::PPToken *tk) +{ + if (!tk->isComment()) + return false; + synchronizeOutputLines(*tk); + enforceSpacing(*tk, true); + currentOutputBuffer().append(tk->tokenStart(), tk->bytes()); + return true; +} + +bool Preprocessor::consumeComments(PPToken *tk) +{ + while (scanComment(tk)) + lex(tk); + return tk->isNot(T_EOF_SYMBOL); +} + bool Preprocessor::collectActualArguments(PPToken *tk, QVector > *actuals) { Q_ASSERT(tk); @@ -1468,12 +1481,22 @@ bool Preprocessor::collectActualArguments(PPToken *tk, QVector lex(tk); // consume the identifier - // consume comments - while (tk->isComment()) { + bool lastCommentIsCpp = false; + while (scanComment(tk)) { + /* After C++ comments we need to add a new line + e.g. + #define foo(a, b) int a = b + foo // comment + (x, 3); + can result in + // commentint + x = 3; + */ + lastCommentIsCpp = tk->is(T_CPP_COMMENT) || tk->is(T_CPP_DOXY_COMMENT); lex(tk); - if (!tk) - return false; } + if (lastCommentIsCpp) + maybeStartOutputLine(); if (tk->isNot(T_LPAREN)) //### TODO: error message @@ -1639,6 +1662,9 @@ void Preprocessor::handleDefineDirective(PPToken *tk) const unsigned defineOffset = tk->byteOffset; lex(tk); // consume "define" token + if (!consumeComments(tk)) + return; + if (tk->isNot(T_IDENTIFIER)) return; @@ -1658,6 +1684,8 @@ void Preprocessor::handleDefineDirective(PPToken *tk) macro.setFunctionLike(true); lex(tk); // skip `(' + if (!consumeComments(tk)) + return; bool hasIdentifier = false; if (isContinuationToken(*tk) && tk->is(T_IDENTIFIER)) { @@ -1665,13 +1693,19 @@ void Preprocessor::handleDefineDirective(PPToken *tk) macro.addFormal(tk->asByteArrayRef().toByteArray()); lex(tk); + if (!consumeComments(tk)) + return; while (isContinuationToken(*tk) && tk->is(T_COMMA)) { lex(tk); + if (!consumeComments(tk)) + return; if (isContinuationToken(*tk) && tk->is(T_IDENTIFIER)) { macro.addFormal(tk->asByteArrayRef().toByteArray()); lex(tk); + if (!consumeComments(tk)) + return; } else { hasIdentifier = false; } @@ -1683,6 +1717,8 @@ void Preprocessor::handleDefineDirective(PPToken *tk) if (!hasIdentifier) macro.addFormal("__VA_ARGS__"); lex(tk); // consume elipsis token + if (!consumeComments(tk)) + return; } if (isContinuationToken(*tk) && tk->is(T_RPAREN)) lex(tk); // consume ")" token @@ -1727,14 +1763,8 @@ void Preprocessor::handleDefineDirective(PPToken *tk) previousUtf16charsOffset = tk->utf16charOffset; previousLine = tk->lineno; - // Discard comments in macro definitions (keep comments flag doesn't apply here). - if (tk->isComment()) { - synchronizeOutputLines(*tk); - enforceSpacing(*tk, true); - currentOutputBuffer().append(tk->tokenStart(), tk->bytes()); - } else { + if (!scanComment(tk)) bodyTokens.push_back(*tk); - } lex(tk); } diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index c394a77cfcf..c994df473de 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -218,6 +218,8 @@ private: QVector tokenize(const QByteArray &text) const; + bool scanComment(PPToken *tk); + bool consumeComments(PPToken *tk); bool collectActualArguments(PPToken *tk, QVector > *actuals); void scanActualArgument(PPToken *tk, QVector *tokens); diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 12d6979c109..376716a9e78 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -1631,6 +1631,123 @@ void tst_Preprocessor::comments_within_data() "# 12 \"\"\n" "int foo = 4;" ); + + QTest::newRow("inside_function_like_macro") << _( + "#define /* comment */ ASSIGN1(VAR, VALUE) VAR = VALUE\n" + "#define ASSIGN2(/* comment */ VAR, VALUE) VAR = VALUE\n" + "#define ASSIGN3(VAR /* comment */, VALUE) VAR = VALUE\n" + "#define ASSIGN4(VAR, /* comment */ VALUE) VAR = VALUE\n" + "#define ASSIGN5(VAR, VALUE /* comment */) VAR = VALUE\n" + "#define ASSIGN6(VAR, VALUE) /* comment */ VAR = VALUE\n" + "#define ASSIGN7(VAR, ... /* comment */) VAR\n" + "void func()\n" + "{\n" + " int i;\n" + " ASSIGN1(i, 3);\n" + " ASSIGN2(i, 3);\n" + " ASSIGN3(i, 3);\n" + " ASSIGN4(i, 3);\n" + " ASSIGN5(i, 3);\n" + " ASSIGN6(i, 3);\n" + " ASSIGN7(i, 3);\n" + "}\n" + ) << _( + "# 1 \"\"\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "void func()\n" + "{\n" + " int i;\n" + "# expansion begin 397,7 11:12 ~1 11:15\n" + "i = 3\n" + "# expansion end\n" + "# 11 \"\"\n" + " ;\n" + "# expansion begin 416,7 12:12 ~1 12:15\n" + "i = 3\n" + "# expansion end\n" + "# 12 \"\"\n" + " ;\n" + "# expansion begin 435,7 13:12 ~1 13:15\n" + "i = 3\n" + "# expansion end\n" + "# 13 \"\"\n" + " ;\n" + "# expansion begin 454,7 14:12 ~1 14:15\n" + "i = 3\n" + "# expansion end\n" + "# 14 \"\"\n" + " ;\n" + "# expansion begin 473,7 15:12 ~1 15:15\n" + "i = 3\n" + "# expansion end\n" + "# 15 \"\"\n" + " ;\n" + "# expansion begin 492,7 16:12 ~1 16:15\n" + "i = 3\n" + "# expansion end\n" + "# 16 \"\"\n" + " ;\n" + "# expansion begin 511,7 17:12\n" + "i\n" + "# expansion end\n" + "# 17 \"\"\n" + " ;\n" + "}\n" + ) << _( + "# 1 \"\"\n" + " /* comment */\n" + " /* comment */\n" + " /* comment */\n" + " /* comment */\n" + " /* comment */\n" + " /* comment */\n" + " /* comment */\n" + "void func()\n" + "{\n" + " int i;\n" + "# expansion begin 397,7 11:12 ~1 11:15\n" + "i = 3\n" + "# expansion end\n" + "# 11 \"\"\n" + " ;\n" + "# expansion begin 416,7 12:12 ~1 12:15\n" + "i = 3\n" + "# expansion end\n" + "# 12 \"\"\n" + " ;\n" + "# expansion begin 435,7 13:12 ~1 13:15\n" + "i = 3\n" + "# expansion end\n" + "# 13 \"\"\n" + " ;\n" + "# expansion begin 454,7 14:12 ~1 14:15\n" + "i = 3\n" + "# expansion end\n" + "# 14 \"\"\n" + " ;\n" + "# expansion begin 473,7 15:12 ~1 15:15\n" + "i = 3\n" + "# expansion end\n" + "# 15 \"\"\n" + " ;\n" + "# expansion begin 492,7 16:12 ~1 16:15\n" + "i = 3\n" + "# expansion end\n" + "# 16 \"\"\n" + " ;\n" + "# expansion begin 511,7 17:12\n" + "i\n" + "# expansion end\n" + "# 17 \"\"\n" + " ;\n" + "}\n" + ); } void tst_Preprocessor::comments_before_args() @@ -1641,17 +1758,32 @@ void tst_Preprocessor::comments_before_args() Preprocessor preprocess(client, &env); preprocess.setKeepComments(true); QByteArray preprocessed = preprocess.run(QLatin1String(""), - "\n#define foo(a,b) int a = b;" - "\nfoo/*C comment*/(a,1)\n" - "\nfoo/**Doxygen comment*/(b,2)\n" - "\nfoo//C++ comment\n(c,3)\n" - "\nfoo///Doxygen C++ comment\n(d,4)\n" - "\nfoo/*multiple*///comments\n/**as well*/(e,5)\n", + "#define foo(a,b) int a = b;\n" + "foo/*C comment*/(a,1)\n" + "foo/**Doxygen comment*/(b,2)\n" + "foo//C++ comment\n" + "(c,3)\n" + "foo///Doxygen C++ comment\n" + "(d,4)\n" + "foo/*multiple*///comments\n" + "/**as well*/(e,5)\n", true, false); - preprocessed = preprocessed.simplified(); // DUMP_OUTPUT(preprocessed); - QVERIFY(compare(simplified(preprocessed), "int a=1;int b=2;int c=3;int d=4;int e=5;")); + QByteArray expected = + "\n" + " /*C comment*/int a = 1;\n" + " /**Doxygen comment*/int b = 2;\n" + " //C++ comment\n" + "int\n" + "c = 3;\n" + " ///Doxygen C++ comment\n" + "int\n" + "d = 4;\n" + " /*multiple*/ //comments\n" + "/**as well*/ int\n" + "e = 5;\n"; + QVERIFY(compare(preprocessed, expected)); } void tst_Preprocessor::multiline_strings() From cde50f23fc0e50c9a714ecbfe42c565e894528ad Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sat, 14 Mar 2015 19:24:46 +0200 Subject: [PATCH 20/22] Tests: Fix compilation Change-Id: I7cb3b5636413abfc52578e8ae0c43f745efa2f0d Reviewed-by: Orgad Shaneh --- tests/auto/utils/stringutils/stringutils.pro | 6 +----- tests/auto/utils/treemodel/treemodel.pro | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/auto/utils/stringutils/stringutils.pro b/tests/auto/utils/stringutils/stringutils.pro index b6c0874a444..f9c4fe25648 100644 --- a/tests/auto/utils/stringutils/stringutils.pro +++ b/tests/auto/utils/stringutils/stringutils.pro @@ -3,8 +3,4 @@ include(../../qttest.pri) DEFINES -= QT_USE_FAST_OPERATOR_PLUS QT_USE_FAST_CONCATENATION -SOURCES += tst_stringutils.cpp \ -# $$UTILS_PATH/stringutils.cpp - -#HEADERS += $$UTILS_PATH/stringutils.h \ -# $$UTILS_PATH/utils_global.h +SOURCES += tst_stringutils.cpp diff --git a/tests/auto/utils/treemodel/treemodel.pro b/tests/auto/utils/treemodel/treemodel.pro index ae913b31b5f..647f63ce500 100644 --- a/tests/auto/utils/treemodel/treemodel.pro +++ b/tests/auto/utils/treemodel/treemodel.pro @@ -3,4 +3,4 @@ include(../../qttest.pri) SOURCES += tst_treemodel.cpp -HEADERS += $$UTILS_PATH/treemodel.h +HEADERS += $$IDE_SOURCE_TREE/src/libs/utils/treemodel.h From f34773e9f2883a3032fa1ee911dbc3721205a8f3 Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Fri, 13 Mar 2015 16:00:55 +0100 Subject: [PATCH 21/22] QmakeProjectManager: Don't offer kits with invalid qts Change-Id: Ic30a9eba40c5a3934a65006f730ae52de3eab852 Task-number: QTCREATORBUG-14001 Reviewed-by: Orgad Shaneh --- src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index 1dd793b1b53..4f5e27d2e4b 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -630,7 +630,8 @@ int QmakeBuildConfigurationFactory::priority(const Kit *k, const QString &projec QList QmakeBuildConfigurationFactory::availableSetups(const Kit *k, const QString &projectPath) const { QList result; - if (!QtSupport::QtKitInformation::qtVersion(k)) + QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k); + if (!qtVersion || !qtVersion->isValid()) return result; result << createBuildInfo(k, projectPath, ProjectExplorer::BuildConfiguration::Debug); result << createBuildInfo(k, projectPath, ProjectExplorer::BuildConfiguration::Release); From 302148e2c5ab89d8171ee0bfb91db6074799b4ae Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 13 Mar 2015 13:07:56 +0100 Subject: [PATCH 22/22] Utils: Remove assert when hiding progress indicator. Just return silently when trying to hide a progress indicator that wasn't initialized by showProgressIndicator. Change-Id: If8c68dbc9de481c8b1cc6b8dd38c9d8e70b00065 Reviewed-by: Eike Ziller --- src/libs/utils/basetreeview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp index f87a7ba7f02..326f407cf4e 100644 --- a/src/libs/utils/basetreeview.cpp +++ b/src/libs/utils/basetreeview.cpp @@ -326,8 +326,8 @@ void BaseTreeView::showProgressIndicator() */ void BaseTreeView::hideProgressIndicator() { - QTC_ASSERT(d->m_progressIndicator, return); - d->m_progressIndicator->hide(); + if (d->m_progressIndicator) + d->m_progressIndicator->hide(); } void BaseTreeView::setSettings(QSettings *settings, const QByteArray &key)