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/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/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; 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) 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/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/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 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; } 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; 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/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/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index 1f493242463..92498eef9aa 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -395,6 +395,78 @@ Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *s return symbolFinder->findMatchingDefinition(symbol, snapshot); } +bool maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor) +{ + QTC_ASSERT(expression, return false); + QTextDocument *textDocument = textCursor.document(); + QTC_ASSERT(textDocument, return false); + + // Skip white space + QTextCursor cursor(textCursor); + while (textDocument->characterAt(cursor.position()).isSpace() + && cursor.movePosition(QTextCursor::NextCharacter)) { + } + + // Find/Include "(arg1, arg2, ...)" + if (textDocument->characterAt(cursor.position()) == QLatin1Char('(')) { + 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); + + if (!maybeAppendArgumentOrParameterList(&expression, textCursor)) + maybeFixExpressionInTrailingReturnType(&expression, textCursor, documentFromSemanticInfo); + + return expression; +} + } // anonymous namespace FollowSymbolUnderCursor::FollowSymbolUnderCursor(CppEditorWidget *widget) @@ -613,22 +685,9 @@ 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, documentFromSemanticInfo, + features); const QSharedPointer typeOfExpression(new TypeOfExpression); typeOfExpression->init(doc, snapshot); // make possible to instantiate templates 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. }; /*! 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() 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() 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; 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/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; 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); 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; }; 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() 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); 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(); } 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(); 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"); diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index c9e417c59b4..376716a9e78 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() @@ -1617,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() @@ -1627,18 +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); - QCOMPARE(simplified(preprocessed), - QString("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() @@ -1899,7 +2044,7 @@ void tst_Preprocessor::concat() "# 5 \"\"\n" " ;\n" ); - QCOMPARE(prep.constData(), output.constData()); + QVERIFY(compare(prep, output)); } void tst_Preprocessor::excessive_nesting() @@ -1928,7 +2073,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) 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 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.")