diff options
author | Eike Ziller <[email protected]> | 2018-11-09 13:30:40 +0100 |
---|---|---|
committer | Eike Ziller <[email protected]> | 2018-11-09 13:30:40 +0100 |
commit | 3666e3aaeb26f91097a473491ea4cf58219029ca (patch) | |
tree | 2d1387557e243eacfe78698371c7726aa9a19350 /src/plugins | |
parent | 951eb885af8692c2c4aac67d18e3cbf033b7e912 (diff) | |
parent | dc82e49b62d6b851900689321828aee95f8eab54 (diff) |
Merge remote-tracking branch 'origin/4.8'
Conflicts:
tests/unit/unittest/unittest.pro
Change-Id: I4f0ab05f96ee60900a3a35fad4c7331238367593
Diffstat (limited to 'src/plugins')
84 files changed, 741 insertions, 285 deletions
diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 8bd4dd0cea8..f1213959bd7 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -38,7 +38,7 @@ namespace { -Q_LOGGING_CATEGORY(androidTCLog, "qtc.android.toolchainmanagement"); +Q_LOGGING_CATEGORY(androidTCLog, "qtc.android.toolchainmanagement", QtWarningMsg); } namespace Android { diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp index 8087639d3a3..d42390ef8dc 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.cpp +++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp @@ -62,7 +62,7 @@ GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futu } } -void GTestOutputReader::processOutput(const QByteArray &outputLine) +void GTestOutputReader::processOutputLine(const QByteArray &outputLineWithNewLine) { static QRegExp newTestStarts("^\\[-{10}\\] \\d+ tests? from (.*)$"); static QRegExp testEnds("^\\[-{10}\\] \\d+ tests? from (.*) \\((.*)\\)$"); @@ -74,7 +74,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine) static QRegExp errorLocation("^(.*)\\((\\d+)\\): error:.*$"); static QRegExp iterations("^Repeating all tests \\(iteration (\\d+)\\) \\. \\. \\.$"); - const QString line = QString::fromLatin1(outputLine); + const QString line = QString::fromLatin1(chopLineBreak(outputLineWithNewLine)); if (line.trimmed().isEmpty()) return; diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h index fd60b9fbedd..8f29ae73e17 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.h +++ b/src/plugins/autotest/gtest/gtestoutputreader.h @@ -44,7 +44,7 @@ public: QProcess *testApplication, const QString &buildDirectory, const QString &projectFile); protected: - void processOutput(const QByteArray &outputLine) override; + void processOutputLine(const QByteArray &outputLineWithNewLine) override; TestResultPtr createDefaultResult() const override; private: diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index 864d2190973..de46727b09e 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -139,7 +139,7 @@ QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &fu { } -void QtTestOutputReader::processOutput(const QByteArray &outputLine) +void QtTestOutputReader::processOutputLine(const QByteArray &outputLine) { static const QByteArray qmlDebug = "QML Debugger: Waiting for connection on port"; switch (m_mode) { @@ -329,7 +329,7 @@ static QStringList extractFunctionInformation(const QString &testClassName, return result; } -void QtTestOutputReader::processPlainTextOutput(const QByteArray &outputLine) +void QtTestOutputReader::processPlainTextOutput(const QByteArray &outputLineWithNewLine) { static QRegExp start("^[*]{9} Start testing of (.*) [*]{9}$"); static QRegExp config("^Config: Using QtTest library (.*), (Qt (\\d+(\\.\\d+){2}) \\(.*\\))$"); @@ -346,7 +346,7 @@ void QtTestOutputReader::processPlainTextOutput(const QByteArray &outputLine) if (m_futureInterface.isCanceled()) return; - const QString &line = QString::fromLatin1(outputLine); + const QString line = QString::fromLatin1(chopLineBreak(outputLineWithNewLine)); if (result.exactMatch(line)) { processResultOutput(result.cap(1).toLower().trimmed(), result.cap(2)); diff --git a/src/plugins/autotest/qtest/qttestoutputreader.h b/src/plugins/autotest/qtest/qttestoutputreader.h index 3487cce066c..89da00a8b91 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.h +++ b/src/plugins/autotest/qtest/qttestoutputreader.h @@ -51,12 +51,12 @@ public: QProcess *testApplication, const QString &buildDirectory, const QString &projectFile, OutputMode mode, TestType type); protected: - void processOutput(const QByteArray &outputLine) override; + void processOutputLine(const QByteArray &outputLine) override; TestResultPtr createDefaultResult() const override; private: - void processXMLOutput(const QByteArray &outputLine); - void processPlainTextOutput(const QByteArray &outputLine); + void processXMLOutput(const QByteArray &outputLineWithNewline); + void processPlainTextOutput(const QByteArray &outputLineWithNewline); void processResultOutput(const QString &result, const QString &message); void processLocationOutput(const QString &fileWithLine); void processSummaryFinishOutput(); diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp index f888f7b34c0..ff96d10e793 100644 --- a/src/plugins/autotest/testoutputreader.cpp +++ b/src/plugins/autotest/testoutputreader.cpp @@ -27,6 +27,8 @@ #include "testresult.h" #include "testresultspane.h" +#include <utils/qtcassert.h> + #include <QDebug> #include <QProcess> @@ -44,27 +46,28 @@ TestOutputReader::TestOutputReader(const QFutureInterface<TestResultPtr> &future connect(m_testApplication, &QProcess::readyRead, this, [this] () { while (m_testApplication->canReadLine()) { - QByteArray output = m_testApplication->readLine(); - output.chop(1); // remove the newline from the output - if (output.endsWith('\r')) - output.chop(1); - - emit newOutputAvailable(output); + const QByteArray output = m_testApplication->readLine(); processOutput(output); } }); connect(m_testApplication, &QProcess::readyReadStandardError, this, [this] () { const QByteArray output = m_testApplication->readAllStandardError(); - emit newOutputAvailable(output); processStdError(output); }); } } -void TestOutputReader::processStdError(const QByteArray &output) +void TestOutputReader::processOutput(const QByteArray &output) +{ + processOutputLine(output); + emit newOutputAvailable(output); +} + +void TestOutputReader::processStdError(const QByteArray &outputLineWithNewLine) { - qWarning() << "AutoTest.Run: Ignored plain output:" << output; + qWarning() << "AutoTest.Run: Ignored plain output:" << outputLineWithNewLine; + emit newOutputAvailable(outputLineWithNewLine); } void TestOutputReader::reportCrash() @@ -83,6 +86,16 @@ void TestOutputReader::createAndReportResult(const QString &message, Result::Typ reportResult(result); } +QByteArray TestOutputReader::chopLineBreak(const QByteArray &original) +{ + QTC_ASSERT(original.endsWith('\n'), return original); + QByteArray output(original); + output.chop(1); // remove the newline from the output + if (output.endsWith('\r')) + output.chop(1); + return output; +} + void TestOutputReader::reportResult(const TestResultPtr &result) { m_futureInterface.reportResult(result); diff --git a/src/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h index 225ad3de33a..7c1f7d0f137 100644 --- a/src/plugins/autotest/testoutputreader.h +++ b/src/plugins/autotest/testoutputreader.h @@ -42,17 +42,20 @@ public: TestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface, QProcess *testApplication, const QString &buildDirectory); - virtual void processOutput(const QByteArray &outputLine) = 0; - virtual void processStdError(const QByteArray &output); + void processOutput(const QByteArray &output); + virtual void processStdError(const QByteArray &outputLineWithNewLine); void reportCrash(); void createAndReportResult(const QString &message, Result::Type type); bool hadValidOutput() const { return m_hadValidOutput; } void setId(const QString &id) { m_id = id; } QString id() const { return m_id; } + static QByteArray chopLineBreak(const QByteArray &original); + signals: - void newOutputAvailable(const QByteArray &output); + void newOutputAvailable(const QByteArray &outputWithLineBreak); protected: + virtual void processOutputLine(const QByteArray &outputLineWithNewLine) = 0; virtual TestResultPtr createDefaultResult() const = 0; void reportResult(const TestResultPtr &result); diff --git a/src/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp index 277109b600a..c67cd15ae56 100644 --- a/src/plugins/autotest/testresultspane.cpp +++ b/src/plugins/autotest/testresultspane.cpp @@ -33,6 +33,7 @@ #include "testtreemodel.h" #include "testcodeparser.h" #include "testeditormark.h" +#include "testoutputreader.h" #include <aggregation/aggregate.h> #include <coreplugin/actionmanager/actionmanager.h> @@ -236,7 +237,7 @@ void TestResultsPane::addTestResult(const TestResultPtr &result) void TestResultsPane::addOutput(const QByteArray &output) { - m_textOutput->appendPlainText(QString::fromLatin1(output)); + m_textOutput->appendPlainText(QString::fromLatin1(TestOutputReader::chopLineBreak(output))); } QWidget *TestResultsPane::outputWidget(QWidget *parent) diff --git a/src/plugins/autotest/testresultspane.h b/src/plugins/autotest/testresultspane.h index 7dcd1f94be7..862270534c3 100644 --- a/src/plugins/autotest/testresultspane.h +++ b/src/plugins/autotest/testresultspane.h @@ -92,7 +92,7 @@ public: void goToPrev() override; void addTestResult(const TestResultPtr &result); - void addOutput(const QByteArray &output); + void addOutput(const QByteArray &outputWithNewLine); void showTestResult(const QModelIndex &index); private: diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 78780f4a03f..6792b96cb38 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -471,25 +471,35 @@ void TestRunner::runTests() static void processOutput(TestOutputReader *outputreader, const QString &msg, Utils::OutputFormat format) { + QByteArray message = msg.toUtf8(); switch (format) { case Utils::OutputFormat::StdOutFormatSameLine: case Utils::OutputFormat::DebugFormat: { - static const QString gdbSpecialOut = "Qt: gdb: -nograb added to command-line options.\n" - "\t Use the -dograb option to enforce grabbing."; - int start = msg.startsWith(gdbSpecialOut) ? gdbSpecialOut.length() + 1 : 0; + static const QByteArray gdbSpecialOut = "Qt: gdb: -nograb added to command-line options.\n" + "\t Use the -dograb option to enforce grabbing."; + int start = message.startsWith(gdbSpecialOut) ? gdbSpecialOut.length() + 1 : 0; if (start) { - int maxIndex = msg.length() - 1; + int maxIndex = message.length() - 1; while (start < maxIndex && msg.at(start + 1) == '\n') ++start; - if (start >= msg.length()) // we cut out the whole message + if (start >= message.length()) // we cut out the whole message break; } - for (const QString &line : msg.mid(start).split('\n')) - outputreader->processOutput(line.toUtf8()); + + int index = message.indexOf('\n', start); + while (index != -1) { + const QByteArray line = message.mid(start, index - start + 1); + outputreader->processOutput(line); + start = index + 1; + index = message.indexOf('\n', start); + } + if (!QTC_GUARD(start == message.length())) // paranoia + outputreader->processOutput(message.mid(start).append('\n')); + break; } case Utils::OutputFormat::StdErrFormatSameLine: - outputreader->processStdError(msg.toUtf8()); + outputreader->processStdError(message); break; default: break; // channels we're not caring about diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp index d7af5ab8ec7..d92b5d67ac2 100644 --- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp +++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp @@ -98,6 +98,7 @@ public: bool enableClickableFixits; bool limitWidth; bool hideTooltipAfterLinkActivation; + bool allowTextSelection; }; static QWidget *create(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, @@ -122,7 +123,12 @@ private: auto *label = new QLabel; label->setTextFormat(Qt::RichText); label->setText(text); - label->setTextInteractionFlags(Qt::TextBrowserInteraction); + if (m_displayHints.allowTextSelection) { + label->setTextInteractionFlags(Qt::TextBrowserInteraction); + } else { + label->setTextInteractionFlags(Qt::LinksAccessibleByMouse + | Qt::LinksAccessibleByKeyboard); + } if (m_displayHints.limitWidth) { const int limit = widthLimit(); @@ -457,6 +463,7 @@ QWidget *ClangDiagnosticWidget::create( hints.enableClickableFixits = true; hints.limitWidth = true; hints.hideTooltipAfterLinkActivation = true; + hints.allowTextSelection = false; } else { // Info Bar hints.showCategoryAndEnableOption = false; hints.showFileNameInMainDiagnostic = true; @@ -464,6 +471,7 @@ QWidget *ClangDiagnosticWidget::create( hints.enableClickableFixits = false; hints.limitWidth = false; hints.hideTooltipAfterLinkActivation = false; + hints.allowTextSelection = true; } return WidgetFromDiagnostics::create(diagnostics, hints); diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp index 3e85ebc8d93..c430c810c30 100644 --- a/src/plugins/clangcodemodel/clangfollowsymbol.cpp +++ b/src/plugins/clangcodemodel/clangfollowsymbol.cpp @@ -163,13 +163,10 @@ void ClangFollowSymbol::findLink(const CppTools::CursorInEditor &data, CppTools::SymbolFinder *symbolFinder, bool inNextSplit) { - int lineNumber = 0, positionInBlock = 0; + int line = 0; + int column = 0; QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor()); - Utils::Text::convertPosition(cursor.document(), cursor.position(), &lineNumber, - &positionInBlock); - - const uint line = lineNumber; - const uint column = positionInBlock + 1; + Utils::Text::convertPosition(cursor.document(), cursor.position(), &line, &column); ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get( data.filePath().toString()); @@ -177,7 +174,10 @@ void ClangFollowSymbol::findLink(const CppTools::CursorInEditor &data, return processLinkCallback(Utils::Link()); if (!resolveTarget) { - processLinkCallback(linkAtCursor(cursor, data.filePath().toString(), line, column, + processLinkCallback(linkAtCursor(cursor, + data.filePath().toString(), + static_cast<uint>(line), + static_cast<uint>(column), processor)); return; } diff --git a/src/plugins/clangformat/clangformat.pro b/src/plugins/clangformat/clangformat.pro index 74331b9e5f6..70eefe17f46 100644 --- a/src/plugins/clangformat/clangformat.pro +++ b/src/plugins/clangformat/clangformat.pro @@ -18,7 +18,8 @@ QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS SOURCES = \ clangformatconfigwidget.cpp \ clangformatindenter.cpp \ - clangformatplugin.cpp + clangformatplugin.cpp \ + clangformatutils.cpp HEADERS = \ clangformatconfigwidget.h \ diff --git a/src/plugins/clangformat/clangformat.qbs b/src/plugins/clangformat/clangformat.qbs index 37bb4c1f647..66e481785e5 100644 --- a/src/plugins/clangformat/clangformat.qbs +++ b/src/plugins/clangformat/clangformat.qbs @@ -33,5 +33,6 @@ QtcPlugin { "clangformatplugin.cpp", "clangformatplugin.h", "clangformatutils.h", + "clangformatutils.cpp", ] } diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 620989d02b0..213fd88a1a2 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -138,7 +138,7 @@ void ClangFormatConfigWidget::initialize() connect(m_ui->createFileButton, &QPushButton::clicked, this, [this]() { - createStyleFileIfNeeded(m_project->projectDirectory()); + createStyleFileIfNeeded(m_project->projectDirectory(), false); initialize(); }); return; @@ -146,10 +146,8 @@ void ClangFormatConfigWidget::initialize() m_ui->createFileButton->hide(); - std::string testFilePath; if (m_project) { m_ui->projectHasClangFormat->hide(); - testFilePath = m_project->projectDirectory().appendPath("t.cpp").toString().toStdString(); connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply); } else { const Project *currentProject = SessionManager::startupProject(); @@ -162,34 +160,20 @@ void ClangFormatConfigWidget::initialize() "and can be configured in Projects > Clang Format.")); } const QString settingsDir = Core::ICore::userResourcePath(); - createStyleFileIfNeeded(Utils::FileName::fromString(settingsDir)); - testFilePath = settingsDir.toStdString() + "/t.cpp"; + createStyleFileIfNeeded(Utils::FileName::fromString(settingsDir), true); m_ui->applyButton->hide(); } - fillTable(testFilePath); + fillTable(); } -void ClangFormatConfigWidget::fillTable(const std::string &testFilePath) +void ClangFormatConfigWidget::fillTable() { - llvm::Expected<clang::format::FormatStyle> formatStyle = - clang::format::getStyle("file", testFilePath, "LLVM"); - std::string configText; - bool brokenConfig = false; - if (!formatStyle) { - handleAllErrors(formatStyle.takeError(), [](const llvm::ErrorInfoBase &) { - // do nothing - }); - configText = clang::format::configurationAsText(clang::format::getLLVMStyle()); - brokenConfig = true; - } else { - configText = clang::format::configurationAsText(*formatStyle); - } + clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle(); + std::string configText = clang::format::configurationAsText(style); std::istringstream stream(configText); readTable(m_ui->clangFormatOptionsTable, stream); - if (brokenConfig) - apply(); } diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h index 5694bd820b7..951e0cc4088 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.h +++ b/src/plugins/clangformat/clangformatconfigwidget.h @@ -49,7 +49,7 @@ public: private: void initialize(); - void fillTable(const std::string &testFilePath); + void fillTable(); ProjectExplorer::Project *m_project; std::unique_ptr<Ui::ClangFormatConfigWidget> m_ui; diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp index b8c1ebbb9a0..ddd786fc22f 100644 --- a/src/plugins/clangformat/clangformatindenter.cpp +++ b/src/plugins/clangformat/clangformatindenter.cpp @@ -30,10 +30,7 @@ #include <clang/Format/Format.h> #include <clang/Tooling/Core/Replacement.h> -#include <coreplugin/icore.h> #include <cpptools/cppmodelmanager.h> -#include <projectexplorer/project.h> -#include <projectexplorer/session.h> #include <texteditor/textdocument.h> #include <texteditor/texteditor.h> @@ -78,7 +75,7 @@ Replacements filteredReplacements(const Replacements &replacements, Replacements filtered; for (const Replacement &replacement : replacements) { int replacementOffset = static_cast<int>(replacement.getOffset()); - if (replacementOffset > offset + lengthForFilter) + if (replacementOffset >= offset + lengthForFilter) break; if (replacementOffset + 1 >= offset) @@ -95,31 +92,6 @@ Replacements filteredReplacements(const Replacements &replacements, return filtered; } -Utils::FileName styleConfigPath() -{ - const Project *project = SessionManager::startupProject(); - if (project && project->projectDirectory().appendPath(".clang-format").exists()) - return project->projectDirectory(); - - return Utils::FileName::fromString(Core::ICore::userResourcePath()); -} - -FormatStyle formatStyle(Utils::FileName styleConfigPath) -{ - createStyleFileIfNeeded(styleConfigPath); - - Expected<FormatStyle> style = format::getStyle( - "file", styleConfigPath.appendPath("test.cpp").toString().toStdString(), "LLVM"); - if (style) - return *style; - - handleAllErrors(style.takeError(), [](const ErrorInfoBase &) { - // do nothing - }); - - return format::getLLVMStyle(); -} - void trimFirstNonEmptyBlock(const QTextBlock ¤tBlock) { QTextBlock prevBlock = currentBlock.previous(); @@ -198,8 +170,7 @@ Replacements replacements(QByteArray buffer, const QTextBlock *block = nullptr, const QChar &typedChar = QChar::Null) { - Utils::FileName stylePath = styleConfigPath(); - FormatStyle style = formatStyle(stylePath); + FormatStyle style = currentStyle(); int extraOffset = 0; if (block) { @@ -227,6 +198,7 @@ Replacements replacements(QByteArray buffer, static_cast<unsigned int>(utf8Length)}}; FormattingAttemptStatus status; + Utils::FileName stylePath = currentStyleConfigPath(); const std::string assumedFilePath = stylePath.appendPath("test.cpp").toString().toStdString(); Replacements replacements = reformat(style, buffer.data(), ranges, assumedFilePath, &status); @@ -234,13 +206,9 @@ Replacements replacements(QByteArray buffer, if (!status.FormatComplete) Replacements(); - int lengthForFilter = 0; - if (block == nullptr) - lengthForFilter = utf8Length; - return filteredReplacements(replacements, utf8Offset, - lengthForFilter, + utf8Length, extraOffset); } @@ -330,6 +298,17 @@ void applyReplacements(const QTextBlock &block, } } +QString selectedLines(QTextDocument *doc, const QTextBlock &startBlock, const QTextBlock &endBlock) +{ + QString text = Utils::Text::textAt( + QTextCursor(doc), + startBlock.position(), + std::max(0, endBlock.position() + endBlock.length() - startBlock.position() - 1)); + while (!text.isEmpty() && text.rbegin()->isSpace()) + text.chop(1); + return text; +} + } // anonymous namespace bool ClangFormatIndenter::isElectricCharacter(const QChar &ch) const @@ -366,12 +345,7 @@ void ClangFormatIndenter::indent(QTextDocument *doc, const QTextBlock end = doc->findBlock(cursor.selectionEnd()); utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, start.blockNumber() + 1); QTC_ASSERT(utf8Offset >= 0, return;); - utf8Length = - Utils::Text::textAt( - QTextCursor(doc), - start.position(), - std::max(0, end.position() + end.length() - start.position() - 1)) - .toUtf8().size(); + utf8Length = selectedLines(doc, start, end).toUtf8().size(); applyReplacements(start, utf8Offset, buffer, @@ -449,7 +423,7 @@ int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::Ta TabSettings ClangFormatIndenter::tabSettings() const { - FormatStyle style = formatStyle(styleConfigPath()); + FormatStyle style = currentStyle(); TabSettings tabSettings; switch (style.UseTab) { @@ -466,8 +440,8 @@ TabSettings ClangFormatIndenter::tabSettings() const tabSettings.m_tabSize = static_cast<int>(style.TabWidth); tabSettings.m_indentSize = static_cast<int>(style.IndentWidth); - if (style.AlignAfterOpenBracket) - tabSettings.m_continuationAlignBehavior = TabSettings::ContinuationAlignWithSpaces; + if (style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign) + tabSettings.m_continuationAlignBehavior = TabSettings::NoContinuationAlign; else tabSettings.m_continuationAlignBehavior = TabSettings::ContinuationAlignWithIndent; diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp index f421b686aca..0c51a5ed2c6 100644 --- a/src/plugins/clangformat/clangformatplugin.cpp +++ b/src/plugins/clangformat/clangformatplugin.cpp @@ -45,8 +45,12 @@ #include <projectexplorer/projectpanelfactory.h> #include <projectexplorer/target.h> +#include <texteditor/texteditorsettings.h> + #include <clang/Format/Format.h> +#include <utils/algorithm.h> + #include <QAction> #include <QDebug> #include <QMainWindow> @@ -95,6 +99,26 @@ private: ClangFormatPlugin::ClangFormatPlugin() = default; ClangFormatPlugin::~ClangFormatPlugin() = default; +#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED +static void disableCppCodeStyle() +{ + using namespace TextEditor; + TextEditorSettings::unregisterCodeStyleFactory(CppTools::Constants::CPP_SETTINGS_ID); + TextEditorSettings::unregisterCodeStylePool(CppTools::Constants::CPP_SETTINGS_ID); + TextEditorSettings::unregisterCodeStyle(CppTools::Constants::CPP_SETTINGS_ID); + + QList<Core::IOptionsPage *> pages = Core::IOptionsPage::allOptionsPages(); + int codeStylePageIndex = Utils::indexOf(pages, [](Core::IOptionsPage *page) { + return page->id() == CppTools::Constants::CPP_CODE_STYLE_SETTINGS_ID; + }); + if (codeStylePageIndex >= 0) { + auto *page = pages[codeStylePageIndex]; + page->finish(); + page->deleteLater(); + } +} +#endif + bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorString) { Q_UNUSED(arguments); @@ -113,6 +137,8 @@ bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorS CppTools::CppModelManager::instance()->setCppIndenterCreator([]() { return new ClangFormatIndenter(); }); + + disableCppCodeStyle(); #endif return true; } diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp new file mode 100644 index 00000000000..4e901ab5631 --- /dev/null +++ b/src/plugins/clangformat/clangformatutils.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "clangformatutils.h" + +#include <coreplugin/icore.h> +#include <cpptools/cppcodestylesettings.h> +#include <texteditor/tabsettings.h> +#include <projectexplorer/project.h> +#include <projectexplorer/session.h> + +using namespace clang; +using namespace format; +using namespace llvm; +using namespace CppTools; +using namespace ProjectExplorer; +using namespace TextEditor; + +namespace ClangFormat { + +static void applyTabSettings(clang::format::FormatStyle &style, const TabSettings &settings) +{ + style.IndentWidth = static_cast<unsigned>(settings.m_indentSize); + style.TabWidth = static_cast<unsigned>(settings.m_tabSize); + + if (settings.m_tabPolicy == TabSettings::TabsOnlyTabPolicy) + style.UseTab = FormatStyle::UT_Always; + else if (settings.m_tabPolicy == TabSettings::SpacesOnlyTabPolicy) + style.UseTab = FormatStyle::UT_Never; + else + style.UseTab = FormatStyle::UT_ForContinuationAndIndentation; + + if (settings.m_continuationAlignBehavior == TabSettings::NoContinuationAlign) { + style.ContinuationIndentWidth = 0; + style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; + } else { + style.ContinuationIndentWidth = style.IndentWidth; + style.AlignAfterOpenBracket = FormatStyle::BAS_Align; + } +} + +static void applyCppCodeStyleSettings(clang::format::FormatStyle &style, + const CppCodeStyleSettings &settings) +{ + style.IndentCaseLabels = settings.indentSwitchLabels; + style.AlignOperands = settings.alignAssignments; + style.NamespaceIndentation = FormatStyle::NI_None; + if (settings.indentNamespaceBody) + style.NamespaceIndentation = FormatStyle::NI_All; + + style.BraceWrapping.IndentBraces = false; + if (settings.indentBlockBraces) { + if (settings.indentClassBraces && settings.indentEnumBraces + && settings.indentNamespaceBraces && settings.indentFunctionBraces) { + style.BraceWrapping.IndentBraces = true; + } else { + style.BreakBeforeBraces = FormatStyle::BS_GNU; + } + } + + if (settings.bindStarToIdentifier || settings.bindStarToRightSpecifier) + style.PointerAlignment = FormatStyle::PAS_Right; + else + style.PointerAlignment = FormatStyle::PAS_Left; + + style.AccessModifierOffset = settings.indentAccessSpecifiers + ? 0 + : - static_cast<int>(style.IndentWidth); +} + +static Utils::FileName projectStylePath() +{ + const Project *project = SessionManager::startupProject(); + if (project) + return project->projectDirectory(); + + return Utils::FileName(); +} + +static Utils::FileName globalStylePath() +{ + return Utils::FileName::fromString(Core::ICore::userResourcePath()); +} + +Utils::FileName currentStyleConfigPath() +{ + Utils::FileName path = projectStylePath(); + if (!path.isEmpty()) + return path; + + return globalStylePath(); +} + +static clang::format::FormatStyle constructStyle(bool isGlobal) +{ + FormatStyle style = getLLVMStyle(); + const CppCodeStyleSettings codeStyleSettings = isGlobal + ? CppCodeStyleSettings::currentGlobalCodeStyle() + : CppCodeStyleSettings::currentProjectCodeStyle(); + const TabSettings tabSettings = isGlobal + ? CppCodeStyleSettings::currentGlobalTabSettings() + : CppCodeStyleSettings::currentProjectTabSettings(); + + applyTabSettings(style, tabSettings); + applyCppCodeStyleSettings(style, codeStyleSettings); + + return style; +} + +void createStyleFileIfNeeded(Utils::FileName styleConfigPath, bool isGlobal) +{ + const QString configFile = styleConfigPath.appendPath(".clang-format").toString(); + if (QFile::exists(configFile)) + return; + + std::fstream newStyleFile(configFile.toStdString(), std::fstream::out); + if (newStyleFile.is_open()) { + newStyleFile << clang::format::configurationAsText(constructStyle(isGlobal)); + newStyleFile.close(); + } +} + +static clang::format::FormatStyle currentStyle(bool isGlobal) +{ + Utils::FileName styleConfigPath = isGlobal ? globalStylePath() : projectStylePath(); + createStyleFileIfNeeded(styleConfigPath, isGlobal); + + Expected<FormatStyle> style = format::getStyle( + "file", styleConfigPath.appendPath("test.cpp").toString().toStdString(), "LLVM"); + if (style) + return *style; + + handleAllErrors(style.takeError(), [](const ErrorInfoBase &) { + // do nothing + }); + + return constructStyle(isGlobal); +} + +clang::format::FormatStyle currentProjectStyle() +{ + return currentStyle(false); +} + +clang::format::FormatStyle currentGlobalStyle() +{ + return currentStyle(true); +} + +clang::format::FormatStyle currentStyle() +{ + const bool isGlobal = (CppCodeStyleSettings::currentProjectCodeStyle() + == CppCodeStyleSettings::currentGlobalCodeStyle()); + return currentStyle(isGlobal); +} + +} diff --git a/src/plugins/clangformat/clangformatutils.h b/src/plugins/clangformat/clangformatutils.h index ad4e21f8899..8634685971e 100644 --- a/src/plugins/clangformat/clangformatutils.h +++ b/src/plugins/clangformat/clangformatutils.h @@ -34,18 +34,12 @@ namespace ClangFormat { -inline void createStyleFileIfNeeded(Utils::FileName styleConfigPath) -{ - const QString configFile = styleConfigPath.appendPath(".clang-format").toString(); - if (QFile::exists(configFile)) - return; - - clang::format::FormatStyle newStyle = clang::format::getLLVMStyle(); - std::fstream newStyleFile(configFile.toStdString(), std::fstream::out); - if (newStyleFile.is_open()) { - newStyleFile << clang::format::configurationAsText(newStyle); - newStyleFile.close(); - } -} +void createStyleFileIfNeeded(Utils::FileName styleConfigPath, bool isGlobal); + +clang::format::FormatStyle currentProjectStyle(); +clang::format::FormatStyle currentGlobalStyle(); + +Utils::FileName currentStyleConfigPath(); +clang::format::FormatStyle currentStyle(); } diff --git a/src/plugins/clangrefactoring/querysqlitestatementfactory.h b/src/plugins/clangrefactoring/querysqlitestatementfactory.h index 21a1f022ec3..14fc27149d2 100644 --- a/src/plugins/clangrefactoring/querysqlitestatementfactory.h +++ b/src/plugins/clangrefactoring/querysqlitestatementfactory.h @@ -40,7 +40,7 @@ public: {} Database &database; ReadStatement selectLocationsForSymbolLocation{ - "SELECT directoryId, sourceId, line, column FROM locations JOIN sources USING(sourceId) WHERE symbolId = " + "SELECT sourceId, line, column FROM locations WHERE symbolId = " " (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) " "ORDER BY sourceId, line, column", database}; @@ -59,7 +59,7 @@ public: "SELECT symbolId, symbolName, signature FROM symbols WHERE symbolKind IN (?,?,?) AND symbolName LIKE ?", database}; ReadStatement selectLocationOfSymbol{ - "SELECT (SELECT directoryId FROM sources WHERE sourceId = l.sourceId), sourceId, line, column FROM locations AS l WHERE symbolId = ? AND locationKind = ?", + "SELECT sourceId, line, column FROM locations AS l WHERE symbolId = ? AND locationKind = ?", database}; }; diff --git a/src/plugins/clangrefactoring/sourcelocations.h b/src/plugins/clangrefactoring/sourcelocations.h index 9766a779b5d..80fc0d89c00 100644 --- a/src/plugins/clangrefactoring/sourcelocations.h +++ b/src/plugins/clangrefactoring/sourcelocations.h @@ -45,8 +45,8 @@ public: SourceLocation(ClangBackEnd::FilePathId filePathId, int line, int column) : filePathId{filePathId}, lineColumn{line, column} {} - SourceLocation(int directoryId, int sourceId, int line, int column) - : filePathId{directoryId, sourceId}, lineColumn{line, column} + SourceLocation(int sourceId, int line, int column) + : filePathId{sourceId}, lineColumn{line, column} {} friend bool operator==(SourceLocation first, SourceLocation second) diff --git a/src/plugins/clangrefactoring/symbolquery.h b/src/plugins/clangrefactoring/symbolquery.h index 507d032f06f..b5a46ab7e60 100644 --- a/src/plugins/clangrefactoring/symbolquery.h +++ b/src/plugins/clangrefactoring/symbolquery.h @@ -55,7 +55,7 @@ public: const std::size_t reserveSize = 128; - return locationsStatement.template values<SourceLocation, 4>(reserveSize, + return locationsStatement.template values<SourceLocation, 3>(reserveSize, filePathId.filePathId, line, utf8Column); @@ -120,7 +120,7 @@ public: { ReadStatement &statement = m_statementFactory.selectLocationOfSymbol; - return statement.template value<SourceLocation, 4>(symbolId, int(kind)); + return statement.template value<SourceLocation, 3>(symbolId, int(kind)); } private: StatementFactory &m_statementFactory; diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp index eab10ebc607..00a945c1240 100644 --- a/src/plugins/clangtools/clangtidyclazyrunner.cpp +++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp @@ -79,7 +79,8 @@ QStringList ClangTidyClazyRunner::constructCommandLineArguments(const QStringLis arguments << QString("-fsyntax-only") << QString("-serialize-diagnostics") << QString(m_logFile) - << ClangDiagnosticConfigsModel::globalDiagnosticOptions(); + << ClangDiagnosticConfigsModel::globalDiagnosticOptions() + << m_diagnosticConfig.clangOptions(); const ClangDiagnosticConfig::TidyMode tidyMode = m_diagnosticConfig.clangTidyMode(); if (tidyMode != ClangDiagnosticConfig::TidyMode::Disabled) { diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp index 9d099820650..d00343ccb3b 100644 --- a/src/plugins/classview/classviewmanager.cpp +++ b/src/plugins/classview/classviewmanager.cpp @@ -421,7 +421,7 @@ void Manager::onDocumentUpdated(CPlusPlus::Document::Ptr doc) /*! Opens the text editor for the file \a fileName on \a line (1-based) and - \a column (1-based). + \a column (0-based). */ void Manager::gotoLocation(const QString &fileName, int line, int column) @@ -466,7 +466,8 @@ void Manager::gotoLocations(const QList<QVariant> &list) } } } - gotoLocation(loc.fileName(), loc.line(), loc.column()); + // line is 1-based, column is 0-based + gotoLocation(loc.fileName(), loc.line(), loc.column() - 1); } /*! diff --git a/src/plugins/classview/classviewparser.cpp b/src/plugins/classview/classviewparser.cpp index 5dc37c528cf..14034b46a38 100644 --- a/src/plugins/classview/classviewparser.cpp +++ b/src/plugins/classview/classviewparser.cpp @@ -366,9 +366,9 @@ void Parser::addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol if (itemAdd.isNull()) itemAdd = ParserTreeItem::Ptr(new ParserTreeItem()); - // locations are 1-based in Symbol, start with 0 for the editor + // locations have 1-based column in Symbol, use the same here. SymbolLocation location(QString::fromUtf8(symbol->fileName() , symbol->fileNameLength()), - symbol->line(), symbol->column() - 1); + symbol->line(), symbol->column()); itemAdd->addSymbolLocation(location); // prevent showing a content of the functions diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index a1b529e3e98..122569616e1 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp @@ -146,8 +146,10 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor, { Utils::Link link; - int lineNumber = 0, positionInBlock = 0; - convertPosition(cursor.position(), &lineNumber, &positionInBlock); + int line = 0; + int column = 0; + convertPosition(cursor.position(), &line, &column); + const int positionInBlock = column - 1; const QString block = cursor.block().text(); diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index 155ed5185aa..f8c19219886 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -75,6 +75,7 @@ QStringList jsonObjectFlags(const QJsonObject &object) if (arguments.isEmpty()) { flags = splitCommandLine(object["command"].toString()); } else { + flags.reserve(arguments.size()); for (const QJsonValue &arg : arguments) flags.append(arg.toString()); } @@ -284,27 +285,43 @@ FolderNode *createFoldersIfNeeded(FolderNode *root, const Utils::FileName &folde return parent; } -void createFolders(FolderNode *root, const Utils::FileName &rootPath) +FileType fileTypeForName(const QString &fileName) { - root->setAbsoluteFilePathAndLine(rootPath, -1); + CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(fileName); + if (CppTools::ProjectFile::isHeader(fileKind)) + return FileType::Header; + return FileType::Source; +} - for (Node *child : root->nodes()) { - FileNode *fileNode = child->asFileNode(); - if (!fileNode) - continue; +void createTree(FolderNode *root, + const Utils::FileName &rootPath, + const CppTools::RawProjectParts &rpps) +{ + root->setAbsoluteFilePathAndLine(rootPath, -1); - FolderNode *parentNode = createFoldersIfNeeded(root, - fileNode->filePath().parentDir()); - child->setParentFolderNode(nullptr); - std::unique_ptr<Node> childNode = root->takeNode(child); - if (!parentNode->fileNode(child->filePath())) - parentNode->addNode(std::move(childNode)); + for (const CppTools::RawProjectPart &rpp : rpps) { + for (const QString &filePath : rpp.files) { + Utils::FileName fileName = Utils::FileName::fromString(filePath); + FolderNode *parentNode = createFoldersIfNeeded(root, fileName.parentDir()); + if (!parentNode->fileNode(fileName)) { + parentNode->addNode(std::make_unique<FileNode>(fileName, + fileTypeForName(fileName.fileName()), + false)); + } + } } } -std::vector<QJsonObject> readJsonObjects(const QString &filePath) +struct Entry +{ + QStringList flags; + Utils::FileName fileName; + QString workingDir; +}; + +std::vector<Entry> readJsonObjects(const QString &filePath) { - std::vector<QJsonObject> result; + std::vector<Entry> result; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) return result; @@ -322,7 +339,12 @@ std::vector<QJsonObject> readJsonObjects(const QString &filePath) continue; } - result.push_back(document.object()); + const QJsonObject object = document.object(); + const Utils::FileName fileName = jsonObjectFilename(object); + const QStringList flags + = filterFromFileName(jsonObjectFlags(object), fileName.toFileInfo().baseName()); + result.push_back({flags, fileName, object["directory"].toString()}); + objectStart = contents.indexOf('{', objectEnd + 1); objectEnd = contents.indexOf('}', objectStart + 1); } @@ -334,7 +356,7 @@ std::vector<QJsonObject> readJsonObjects(const QString &filePath) void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName &projectFile) { - std::vector<QJsonObject> array = readJsonObjects(projectFilePath().toString()); + std::vector<Entry> array = readJsonObjects(projectFilePath().toString()); if (array.empty()) { emitParsingFinished(false); return; @@ -346,37 +368,37 @@ void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName Utils::FileName commonPath; ToolChain *cToolchain = nullptr; ToolChain *cxxToolchain = nullptr; - for (const QJsonObject &object : array) { - Utils::FileName fileName = jsonObjectFilename(object); - const QStringList flags = jsonObjectFlags(object); - commonPath = rpps.empty() - ? fileName.parentDir() - : Utils::FileUtils::commonPath(commonPath, fileName); + std::sort(array.begin(), array.end(), [](const Entry &lhs, const Entry &rhs) { + return std::lexicographical_compare(lhs.flags.begin(), lhs.flags.end(), + rhs.flags.begin(), rhs.flags.end()); + }); - ProjectExplorer::FileType type = ProjectExplorer::FileType::Unknown; - root->addNode(std::make_unique<FileNode>(fileName, type, false)); + const Entry *prevEntry = nullptr; + for (const Entry &entry : array) { + if (prevEntry && prevEntry->flags == entry.flags) { + rpps.back().files.append(entry.fileName.toString()); + continue; + } + + prevEntry = &entry; + + commonPath = rpps.empty() + ? entry.fileName.parentDir() + : Utils::FileUtils::commonPath(commonPath, entry.fileName); CppTools::RawProjectPart rpp = makeRawProjectPart(projectFile, m_kit.get(), cToolchain, cxxToolchain, - object["directory"].toString(), - fileName, - flags); - int rppIndex = Utils::indexOf(rpps, [&rpp](const CppTools::RawProjectPart ¤tRpp) { - return rpp.buildSystemTarget == currentRpp.buildSystemTarget - && rpp.headerPaths == currentRpp.headerPaths - && rpp.projectMacros == currentRpp.projectMacros - && rpp.flagsForCxx.commandLineFlags == currentRpp.flagsForCxx.commandLineFlags; - }); - if (rppIndex == -1) - rpps.append(rpp); - else - rpps[rppIndex].files.append(rpp.files); + entry.workingDir, + entry.fileName, + entry.flags); + + rpps.append(rpp); } - createFolders(root.get(), commonPath); + createTree(root.get(), commonPath, rpps); root->addNode(std::make_unique<FileNode>( projectFile, diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp index 2dd20dd9e5f..1884aa1c6d3 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp @@ -81,6 +81,19 @@ static CppTools::ProjectFile::Kind fileKindFromString(QString flag) return ProjectFile::Unclassified; } +QStringList filterFromFileName(const QStringList &flags, QString baseName) +{ + baseName.append('.'); // to match name.c, name.o, etc. + QStringList result; + result.reserve(flags.size()); + for (const QString &flag : flags) { + if (!flag.contains(baseName)) + result.push_back(flag); + } + + return result; +} + void filteredFlags(const QString &fileName, const QString &workingDir, QStringList &flags, @@ -88,13 +101,13 @@ void filteredFlags(const QString &fileName, Macros ¯os, CppTools::ProjectFile::Kind &fileKind) { - if (flags.isEmpty()) + if (flags.empty()) return; // Skip compiler call if present. bool skipNext = Utils::HostOsInfo::isWindowsHost() - ? (!flags.first().startsWith('/') && !flags.first().startsWith('-')) - : (!flags.first().startsWith('-')); + ? (!flags.front().startsWith('/') && !flags.front().startsWith('-')) + : (!flags.front().startsWith('-')); Utils::optional<HeaderPathType> includePathType; Utils::optional<MacroType> macroType; bool fileKindIsNext = false; @@ -121,11 +134,6 @@ void filteredFlags(const QString &fileName, continue; } - if (flag == "-o") { - skipNext = true; - continue; - } - if (flag != "-x" && (fileKindIsNext || flag == "/TC" || flag == "/TP" || flag.startsWith("/Tc") || flag.startsWith("/Tp") || flag.startsWith("-x"))) { @@ -139,16 +147,13 @@ void filteredFlags(const QString &fileName, continue; } - if (flag == "-c" || flag == "-pedantic" + if (flag == "-o" || flag == "-MF" || flag == "-c" || flag == "-pedantic" || flag.startsWith("-O") || flag.startsWith("-W") || flag.startsWith("-w") || QString::compare(flag, "-fpic", Qt::CaseInsensitive) == 0 || QString::compare(flag, "-fpie", Qt::CaseInsensitive) == 0) { continue; } - if (flag.endsWith(fileName)) - continue; - if ((flag.startsWith("-I") || flag.startsWith("-isystem") || flag.startsWith("/I")) && flag != "-I" && flag != "-isystem" && flag != "/I") { bool userInclude = flag.startsWith("-I"); diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h index 5e123a8c271..e465b6ba23c 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.h @@ -38,6 +38,8 @@ class Macro; namespace CompilationDatabaseProjectManager { +QStringList filterFromFileName(const QStringList &flags, QString baseName); + void filteredFlags(const QString &fileName, const QString &workingDir, QStringList &flags, diff --git a/src/plugins/cppeditor/cppuseselections_test.cpp b/src/plugins/cppeditor/cppuseselections_test.cpp index 8de8048a892..99674b2e3c7 100644 --- a/src/plugins/cppeditor/cppuseselections_test.cpp +++ b/src/plugins/cppeditor/cppuseselections_test.cpp @@ -31,6 +31,7 @@ #include <QElapsedTimer> #include <QtTest> +// Uses 1-based line and 0-based column. struct Selection { Selection(int line, int column, int length) : line(line), column(column), length(length) {} int line; @@ -116,7 +117,7 @@ SelectionList UseSelectionsTestCase::toSelectionList( int line, column; const int position = qMin(selection.cursor.position(), selection.cursor.anchor()); m_editorWidget->convertPosition(position, &line, &column); - result << Selection(line, column, selection.cursor.selectedText().length()); + result << Selection(line, column - 1, selection.cursor.selectedText().length()); } return result; } diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 3ac121d918e..8d30cfbd437 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -317,7 +317,7 @@ F2TestCase::F2TestCase(CppEditorAction action, initialTestFile->m_editor->setCursorPosition(initialTestFile->m_cursorPosition); // qDebug() << "Initial line:" << initialTestFile->editor->currentLine(); -// qDebug() << "Initial column:" << initialTestFile->editor->currentColumn() - 1; +// qDebug() << "Initial column:" << initialTestFile->editor->currentColumn(); OverrideItemList immediateVirtualSymbolResults; OverrideItemList finalVirtualSymbolResults; @@ -338,7 +338,7 @@ F2TestCase::F2TestCase(CppEditorAction action, QSKIP((curTestName + " is not supported by Clang FollowSymbol").toLatin1()); } - initialTestFile->m_editorWidget->openLinkUnderCursor(); + widget->openLinkUnderCursor(); break; } @@ -349,7 +349,7 @@ F2TestCase::F2TestCase(CppEditorAction action, QSharedPointer<VirtualFunctionTestAssistProvider> testProvider( new VirtualFunctionTestAssistProvider(widget)); builtinFollowSymbol->setVirtualFunctionAssistProvider(testProvider); - initialTestFile->m_editorWidget->openLinkUnderCursor(); + widget->openLinkUnderCursor(); immediateVirtualSymbolResults = testProvider->m_immediateItems; finalVirtualSymbolResults = testProvider->m_finalItems; @@ -382,7 +382,7 @@ F2TestCase::F2TestCase(CppEditorAction action, QEXPECT_FAIL("globalVarFromEnum", "Contributor works on a fix.", Abort); QEXPECT_FAIL("matchFunctionSignature_Follow_5", "foo(int) resolved as CallAST", Abort); QCOMPARE(currentTextEditor->currentLine(), expectedLine); - QCOMPARE(currentTextEditor->currentColumn() - 1, expectedColumn); + QCOMPARE(currentTextEditor->currentColumn(), expectedColumn); // qDebug() << immediateVirtualSymbolResults; // qDebug() << finalVirtualSymbolResults; diff --git a/src/plugins/cpptools/builtincursorinfo.cpp b/src/plugins/cpptools/builtincursorinfo.cpp index 4522af15a96..85603ba0902 100644 --- a/src/plugins/cpptools/builtincursorinfo.cpp +++ b/src/plugins/cpptools/builtincursorinfo.cpp @@ -184,8 +184,9 @@ private: { CursorInfo result; + // findLocalUses operates with 1-based line and 0-based column const CppTools::SemanticInfo::LocalUseMap localUses - = BuiltinCursorInfo::findLocalUses(m_document, m_line, m_column); + = BuiltinCursorInfo::findLocalUses(m_document, m_line, m_column - 1); result.localUses = localUses; splitLocalUses(localUses, &result.useRanges, &result.unusedVariablesRanges); @@ -216,8 +217,7 @@ private: bool good = false; foreach (const CppTools::SemanticInfo::Use &use, uses) { unsigned l = static_cast<unsigned>(m_line); - // convertCursorPosition() returns a 0-based column number. - unsigned c = static_cast<unsigned>(m_column + 1); + unsigned c = static_cast<unsigned>(m_column); if (l == use.line && c >= use.column && c <= (use.column + use.length)) { good = true; break; diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp index 684f765eace..d5bfa510203 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.cpp +++ b/src/plugins/cpptools/builtineditordocumentprocessor.cpp @@ -112,7 +112,6 @@ CppTools::CheckSymbols *createHighlighter(const CPlusPlus::Document::Ptr &doc, int line, column; convertPosition(textDocument, macro.utf16CharOffset(), &line, &column); - ++column; //Highlighting starts at (column-1) --> compensate here Result use(line, column, macro.nameToQString().size(), SemanticHighlighter::MacroUse); macroUses.append(use); } diff --git a/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp index 70432047cf9..06d8478b508 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp +++ b/src/plugins/cpptools/clangdiagnosticconfigsselectionwidget.cpp @@ -126,6 +126,9 @@ void ClangDiagnosticConfigsSelectionWidget::connectToClangDiagnosticConfigsDialo = settings->clangCustomDiagnosticConfigs(); const ClangDiagnosticConfigs currentDiagnosticConfigs = widget->customConfigs(); if (oldDiagnosticConfigs != currentDiagnosticConfigs) { + const ClangDiagnosticConfigsModel configsModel(currentDiagnosticConfigs); + if (!configsModel.hasConfigWithId(settings->clangDiagnosticConfigId())) + settings->resetClangDiagnosticConfigId(); settings->setClangCustomDiagnosticConfigs(currentDiagnosticConfigs); settings->toSettings(Core::ICore::settings()); } diff --git a/src/plugins/cpptools/cppcanonicalsymbol.cpp b/src/plugins/cpptools/cppcanonicalsymbol.cpp index 3f1869de63b..fa5d0749213 100644 --- a/src/plugins/cpptools/cppcanonicalsymbol.cpp +++ b/src/plugins/cpptools/cppcanonicalsymbol.cpp @@ -60,7 +60,6 @@ Scope *CanonicalSymbol::getScopeAndExpression(const QTextCursor &cursor, QString QTextCursor tc = cursor; int line, column; Utils::Text::convertPosition(cursor.document(), tc.position(), &line, &column); - ++column; // 1-based line and 1-based column int pos = tc.position(); QTextDocument *textDocument = cursor.document(); @@ -74,7 +73,7 @@ Scope *CanonicalSymbol::getScopeAndExpression(const QTextCursor &cursor, QString ExpressionUnderCursor expressionUnderCursor(m_document->languageFeatures()); *code = expressionUnderCursor(tc); - return m_document->scopeAt(line, column); + return m_document->scopeAt(line, column - 1); } Symbol *CanonicalSymbol::operator()(const QTextCursor &cursor) diff --git a/src/plugins/cpptools/cppcodemodelsettings.cpp b/src/plugins/cpptools/cppcodemodelsettings.cpp index 00c57c81733..c5aee2089bc 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.cpp +++ b/src/plugins/cpptools/cppcodemodelsettings.cpp @@ -118,6 +118,12 @@ void CppCodeModelSettings::fromSettings(QSettings *s) setClangCustomDiagnosticConfigs(customDiagnosticConfigsFromSettings(s)); setClangDiagnosticConfigId(clangDiagnosticConfigIdFromSettings(s)); + { // Before Qt Creator 4.8, inconsistent settings might have been written. + const ClangDiagnosticConfigsModel model(m_clangCustomDiagnosticConfigs); + if (!model.hasConfigWithId(m_clangDiagnosticConfigId)) + setClangDiagnosticConfigId(initialClangDiagnosticConfigId()); + } + const QVariant pchUsageVariant = s->value(pchUsageKey(), initialPchUsage()); setPCHUsage(static_cast<PCHUsage>(pchUsageVariant.toInt())); @@ -189,6 +195,11 @@ void CppCodeModelSettings::setClangDiagnosticConfigId(const Core::Id &configId) m_clangDiagnosticConfigId = configId; } +void CppCodeModelSettings::resetClangDiagnosticConfigId() +{ + m_clangDiagnosticConfigId = initialClangDiagnosticConfigId(); +} + const ClangDiagnosticConfig CppCodeModelSettings::clangDiagnosticConfig() const { const ClangDiagnosticConfigsModel configsModel(m_clangCustomDiagnosticConfigs); diff --git a/src/plugins/cpptools/cppcodemodelsettings.h b/src/plugins/cpptools/cppcodemodelsettings.h index ca1a3cf155c..d1783711f19 100644 --- a/src/plugins/cpptools/cppcodemodelsettings.h +++ b/src/plugins/cpptools/cppcodemodelsettings.h @@ -55,6 +55,7 @@ public: public: Core::Id clangDiagnosticConfigId() const; void setClangDiagnosticConfigId(const Core::Id &configId); + void resetClangDiagnosticConfigId(); const ClangDiagnosticConfig clangDiagnosticConfig() const; ClangDiagnosticConfigs clangCustomDiagnosticConfigs() const; diff --git a/src/plugins/cpptools/cppcodestylesettings.cpp b/src/plugins/cpptools/cppcodestylesettings.cpp index 06d396e59c8..723ae2c2222 100644 --- a/src/plugins/cpptools/cppcodestylesettings.cpp +++ b/src/plugins/cpptools/cppcodestylesettings.cpp @@ -33,6 +33,8 @@ #include <projectexplorer/project.h> #include <projectexplorer/projecttree.h> +#include <texteditor/tabsettings.h> + #include <cplusplus/Overview.h> #include <utils/qtcassert.h> @@ -226,6 +228,31 @@ CppCodeStyleSettings CppCodeStyleSettings::currentGlobalCodeStyle() return cppCodeStylePreferences->currentCodeStyleSettings(); } +TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings() +{ + ProjectExplorer::Project *project = ProjectExplorer::ProjectTree::currentProject(); + if (!project) + return currentGlobalTabSettings(); + + ProjectExplorer::EditorConfiguration *editorConfiguration = project->editorConfiguration(); + QTC_ASSERT(editorConfiguration, return currentGlobalTabSettings()); + + TextEditor::ICodeStylePreferences *codeStylePreferences + = editorConfiguration->codeStyle(CppTools::Constants::CPP_SETTINGS_ID); + QTC_ASSERT(codeStylePreferences, return currentGlobalTabSettings()); + return codeStylePreferences->tabSettings(); +} + +TextEditor::TabSettings CppCodeStyleSettings::currentGlobalTabSettings() +{ + CppTools::CppCodeStylePreferences *cppCodeStylePreferences + = CppTools::CppToolsSettings::instance()->cppCodeStyle(); + QTC_ASSERT(cppCodeStylePreferences, return TextEditor::TabSettings()); + + return cppCodeStylePreferences->tabSettings(); +} + + static void configureOverviewWithCodeStyleSettings(CPlusPlus::Overview &overview, const CppCodeStyleSettings &settings) { diff --git a/src/plugins/cpptools/cppcodestylesettings.h b/src/plugins/cpptools/cppcodestylesettings.h index f69d72d0ab8..4af18fbdbc1 100644 --- a/src/plugins/cpptools/cppcodestylesettings.h +++ b/src/plugins/cpptools/cppcodestylesettings.h @@ -34,6 +34,7 @@ class QSettings; QT_END_NAMESPACE namespace CPlusPlus { class Overview; } +namespace TextEditor { class TabSettings; } namespace CppTools { @@ -94,6 +95,8 @@ public: static CppCodeStyleSettings currentProjectCodeStyle(); static CppCodeStyleSettings currentGlobalCodeStyle(); + static TextEditor::TabSettings currentProjectTabSettings(); + static TextEditor::TabSettings currentGlobalTabSettings(); /*! Returns an Overview configured by the current project's code style. diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index af4372a4580..87bc2df0b4d 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -1092,7 +1092,7 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper() int line = 0, column = 0; Utils::Text::convertPosition(m_interface->textDocument(), startOfExpression, &line, &column); const QString fileName = m_interface->fileName(); - return startCompletionInternal(fileName, line, column, expression, endOfExpression); + return startCompletionInternal(fileName, line, column - 1, expression, endOfExpression); } bool InternalCppCompletionAssistProcessor::tryObjCCompletion() @@ -1125,7 +1125,7 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion() int line = 0, column = 0; Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(), &line, &column); - Scope *scope = thisDocument->scopeAt(line, column); + Scope *scope = thisDocument->scopeAt(line, column - 1); if (!scope) return false; @@ -1319,7 +1319,8 @@ bool InternalCppCompletionAssistProcessor::objcKeywordsWanted() const } int InternalCppCompletionAssistProcessor::startCompletionInternal(const QString &fileName, - unsigned line, unsigned column, + unsigned line, + unsigned positionInBlock, const QString &expr, int endOfExpression) { @@ -1331,7 +1332,7 @@ int InternalCppCompletionAssistProcessor::startCompletionInternal(const QString m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot()); - Scope *scope = thisDocument->scopeAt(line, column); + Scope *scope = thisDocument->scopeAt(line, positionInBlock); QTC_ASSERT(scope != 0, return -1); if (expression.isEmpty()) { @@ -2016,7 +2017,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q int lineSigned = 0, columnSigned = 0; Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(), &lineSigned, &columnSigned); - unsigned line = lineSigned, column = columnSigned; + unsigned line = lineSigned, column = columnSigned - 1; // find a scope that encloses the current location, starting from the lastVisibileSymbol // and moving outwards diff --git a/src/plugins/cpptools/cppcompletionassist.h b/src/plugins/cpptools/cppcompletionassist.h index 8e0097b2fa8..7bb7776940c 100644 --- a/src/plugins/cpptools/cppcompletionassist.h +++ b/src/plugins/cpptools/cppcompletionassist.h @@ -113,7 +113,7 @@ private: bool tryObjCCompletion(); bool objcKeywordsWanted() const; int startCompletionInternal(const QString &fileName, - unsigned line, unsigned column, + unsigned line, unsigned positionInBlock, const QString &expression, int endOfExpression); diff --git a/src/plugins/cpptools/cppelementevaluator.cpp b/src/plugins/cpptools/cppelementevaluator.cpp index 90fb21a34c4..afd8944bde9 100644 --- a/src/plugins/cpptools/cppelementevaluator.cpp +++ b/src/plugins/cpptools/cppelementevaluator.cpp @@ -373,7 +373,7 @@ void CppElementEvaluator::execute() // Fetch the expression's code ExpressionUnderCursor expressionUnderCursor(doc->languageFeatures()); const QString &expression = expressionUnderCursor(m_tc); - Scope *scope = doc->scopeAt(line, column); + Scope *scope = doc->scopeAt(line, column - 1); TypeOfExpression typeOfExpression; typeOfExpression.init(doc, snapshot); diff --git a/src/plugins/cpptools/cppfollowsymbolundercursor.cpp b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp index 65bfd310a55..a66c357986b 100644 --- a/src/plugins/cpptools/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp @@ -491,12 +491,12 @@ void FollowSymbolUnderCursor::findLink( { Link link; - int lineNumber = 0, positionInBlock = 0; + int line = 0; + int column = 0; QTextCursor cursor = data.cursor(); QTextDocument *document = cursor.document(); - Utils::Text::convertPosition(document, cursor.position(), &lineNumber, &positionInBlock); - const unsigned line = lineNumber; - const unsigned column = positionInBlock + 1; + Utils::Text::convertPosition(document, cursor.position(), &line, &column); + const int positionInBlock = column - 1; Snapshot snapshot = theSnapshot; @@ -541,8 +541,8 @@ void FollowSymbolUnderCursor::findLink( for (int i = 0; i < tokens.size(); ++i) { const Token &tk = tokens.at(i); - if (((unsigned) positionInBlock) >= tk.utf16charsBegin() - && ((unsigned) positionInBlock) < tk.utf16charsEnd()) { + if (static_cast<unsigned>(positionInBlock) >= tk.utf16charsBegin() + && static_cast<unsigned>(positionInBlock) < tk.utf16charsEnd()) { int closingParenthesisPos = tokens.size(); if (i >= 2 && tokens.at(i).is(T_IDENTIFIER) && tokens.at(i - 1).is(T_LPAREN) && (tokens.at(i - 2).is(T_SIGNAL) || tokens.at(i - 2).is(T_SLOT))) { @@ -584,8 +584,8 @@ void FollowSymbolUnderCursor::findLink( // In this case we want to look at one token before the current position to recognize // an operator if the cursor is inside the actual operator: operator[$] - if (unsigned(positionInBlock) >= tk.utf16charsBegin() - && unsigned(positionInBlock) <= tk.utf16charsEnd()) { + if (static_cast<unsigned>(positionInBlock) >= tk.utf16charsBegin() + && static_cast<unsigned>(positionInBlock) <= tk.utf16charsEnd()) { cursorRegionReached = true; if (tk.is(T_OPERATOR)) { link = attemptFuncDeclDef(cursor, theSnapshot, @@ -675,7 +675,7 @@ void FollowSymbolUnderCursor::findLink( } // Find the last symbol up to the cursor position - Scope *scope = doc->scopeAt(line, column); + Scope *scope = doc->scopeAt(line, positionInBlock); if (!scope) return processLinkCallback(link); @@ -698,19 +698,21 @@ void FollowSymbolUnderCursor::findLink( if (d->isDeclaration() || d->isFunction()) { const QString fileName = QString::fromUtf8(d->fileName(), d->fileNameLength()); if (data.filePath().toString() == fileName) { - if (unsigned(lineNumber) == d->line() - && unsigned(positionInBlock) >= d->column()) { // TODO: check the end + if (static_cast<unsigned>(line) == d->line() + && static_cast<unsigned>(positionInBlock) >= d->column()) { + // TODO: check the end result = r; // take the symbol under cursor. break; } } } else if (d->isUsingDeclaration()) { - int tokenBeginLineNumber = 0, tokenBeginColumnNumber = 0; + int tokenBeginLineNumber = 0; + int tokenBeginColumnNumber = 0; Utils::Text::convertPosition(document, beginOfToken, &tokenBeginLineNumber, &tokenBeginColumnNumber); - if (unsigned(tokenBeginLineNumber) > d->line() - || (unsigned(tokenBeginLineNumber) == d->line() - && unsigned(tokenBeginColumnNumber) > d->column())) { + if (static_cast<unsigned>(tokenBeginLineNumber) > d->line() + || (static_cast<unsigned>(tokenBeginLineNumber) == d->line() + && static_cast<unsigned>(tokenBeginColumnNumber) >= d->column())) { result = r; // take the symbol under cursor. break; } diff --git a/src/plugins/debugger/analyzer/analyzerutils.cpp b/src/plugins/debugger/analyzer/analyzerutils.cpp index ec181953951..4c6e92ddbcc 100644 --- a/src/plugins/debugger/analyzer/analyzerutils.cpp +++ b/src/plugins/debugger/analyzer/analyzerutils.cpp @@ -74,7 +74,7 @@ CPlusPlus::Symbol *AnalyzerUtils::findSymbolUnderCursor() CPlusPlus::ExpressionUnderCursor expressionUnderCursor(doc->languageFeatures()); moveCursorToEndOfName(&tc); const QString &expression = expressionUnderCursor(tc); - CPlusPlus::Scope *scope = doc->scopeAt(line, column); + CPlusPlus::Scope *scope = doc->scopeAt(line, column - 1); CPlusPlus::TypeOfExpression typeOfExpression; typeOfExpression.init(doc, snapshot); diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 7ac4671ed8b..bf340113275 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -1408,8 +1408,9 @@ void BreakHandler::handleAlienBreakpoint(const QString &responseId, const Breakp } else { bp = new BreakpointItem(nullptr); bp->m_responseId = responseId; - bp->setState(BreakpointInserted); - bp->setParameters(params); + bp->m_parameters = params; + bp->m_state = BreakpointInserted; + bp->updateMarker(); rootItem()->appendChild(bp); // This has no global breakpoint, so there's nothing to update here. } diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 7ee5dcec54c..e425138a2ae 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -793,8 +793,8 @@ void DebuggerEnginePrivate::setupViews() m_perspective->addWindow(m_modulesWindow, Perspective::AddToTab, m_threadsWindow, false); m_perspective->addWindow(m_sourceFilesWindow, Perspective::AddToTab, m_modulesWindow, false); m_perspective->addWindow(m_localsAndInspectorWindow, Perspective::AddToTab, nullptr, true, Qt::RightDockWidgetArea); - m_perspective->addWindow(m_watchersWindow, Perspective::AddToTab, m_localsAndInspectorWindow, true, Qt::RightDockWidgetArea); - m_perspective->addWindow(m_registerWindow, Perspective::AddToTab, m_watchersWindow, false, Qt::RightDockWidgetArea); + m_perspective->addWindow(m_watchersWindow, Perspective::SplitVertical, m_localsAndInspectorWindow, true, Qt::RightDockWidgetArea); + m_perspective->addWindow(m_registerWindow, Perspective::AddToTab, m_localsAndInspectorWindow, false, Qt::RightDockWidgetArea); m_perspective->addWindow(m_logWindow, Perspective::AddToTab, nullptr, false, Qt::TopDockWidgetArea); m_perspective->select(); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 81c6ac8ee33..7447d46916a 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1471,7 +1471,7 @@ void DebuggerPluginPrivate::updatePresetState() // No engine running -- or -- we have a running engine but it does not // correspond to the current start up project. m_startAction.setEnabled(canRun); - m_startAction.setIcon(startIcon(false)); + m_startAction.setIcon(startIcon(true)); m_startAction.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); m_startAction.setVisible(true); m_debugWithoutDeployAction.setEnabled(canRun); diff --git a/src/plugins/debugger/enginemanager.cpp b/src/plugins/debugger/enginemanager.cpp index 8e829c7cfb0..9ac2e31b11e 100644 --- a/src/plugins/debugger/enginemanager.cpp +++ b/src/plugins/debugger/enginemanager.cpp @@ -133,7 +133,10 @@ public: EngineManagerPrivate() { m_engineModel.setHeader({EngineManager::tr("Name"), EngineManager::tr("File")}); - m_engineModel.rootItem()->appendChild(new EngineItem); // The preset case. + // The preset case: + auto preset = new EngineItem; + m_engineModel.rootItem()->appendChild(preset); + m_currentItem = preset; m_engineChooser = new QComboBox; m_engineChooser->setModel(&m_engineModel); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index ad4b484d684..fb417f5540c 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1456,6 +1456,8 @@ void GdbEngine::handleStop2(const GdbMi &data) // stopping debugging. if (name == stopSignal(rp.toolChainAbi) || rp.expectedSignals.contains(name)) { showMessage(name + " CONSIDERED HARMLESS. CONTINUING."); + } else if (m_isQnxGdb && name == "0" && meaning == "Signal 0") { + showMessage("SIGNAL 0 CONSIDERED BOGUS."); } else { showMessage("HANDLING SIGNAL " + name); if (boolSetting(UseMessageBoxForSignals) && !isStopperThread) diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 9d13f1d2ebe..f6e81e069ea 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -253,20 +253,15 @@ void LldbEngine::setupEngine() const DebuggerRunParameters &rp = runParameters(); - QString executable; - QtcProcess::Arguments args; - QtcProcess::prepareCommand(QFileInfo(rp.inferior.executable).absoluteFilePath(), - rp.inferior.commandLineArguments, &executable, &args); - DebuggerCommand cmd2("setupInferior"); - cmd2.arg("executable", executable); + cmd2.arg("executable", rp.inferior.executable); cmd2.arg("breakonmain", rp.breakOnMain); cmd2.arg("useterminal", bool(terminal())); cmd2.arg("startmode", rp.startMode); cmd2.arg("nativemixed", isNativeMixedActive()); cmd2.arg("workingdirectory", rp.inferior.workingDirectory); cmd2.arg("environment", rp.inferior.environment.toStringList()); - cmd2.arg("processargs", args.toUnixArgs()); + cmd2.arg("processargs", toHex(rp.inferior.commandLineArguments)); if (terminal()) { const qint64 attachedPID = terminal()->applicationPid(); diff --git a/src/plugins/debugger/threadshandler.cpp b/src/plugins/debugger/threadshandler.cpp index 205790eb401..de58f7b6155 100644 --- a/src/plugins/debugger/threadshandler.cpp +++ b/src/plugins/debugger/threadshandler.cpp @@ -221,13 +221,11 @@ ThreadsHandler::ThreadsHandler(DebuggerEngine *engine) tr("Address"), tr("Function"), tr("File"), tr("Line"), tr("State"), tr("Name"), tr("Target ID"), tr("Details"), tr("Core"), }); +} - m_comboBox = new QComboBox; - m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); - m_comboBox->setModel(this); - connect(m_comboBox, QOverload<int>::of(&QComboBox::activated), this, [this](int row) { - setData(index(row, 0), {}, BaseTreeView::ItemActivatedRole); - }); +ThreadsHandler::~ThreadsHandler() +{ + delete m_comboBox; } QVariant ThreadsHandler::data(const QModelIndex &index, int role) const @@ -249,7 +247,7 @@ bool ThreadsHandler::setData(const QModelIndex &idx, const QVariant &data, int r const Thread thread = itemForIndexAtLevel<1>(idx); if (thread != m_currentThread) { m_currentThread = thread; - m_comboBox->setCurrentIndex(idx.row()); + threadSwitcher()->setCurrentIndex(idx.row()); m_engine->selectThread(thread); } return true; @@ -364,6 +362,19 @@ void ThreadsHandler::notifyStopped(const QString &id) thread->notifyStopped(); } +QPointer<QComboBox> ThreadsHandler::threadSwitcher() +{ + if (!m_comboBox) { + m_comboBox = new QComboBox; + m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_comboBox->setModel(this); + connect(m_comboBox, QOverload<int>::of(&QComboBox::activated), this, [this](int row) { + setData(index(row, 0), {}, BaseTreeView::ItemActivatedRole); + }); + } + return m_comboBox; +} + void ThreadsHandler::setThreads(const GdbMi &data) { rootItem()->removeChildren(); diff --git a/src/plugins/debugger/threadshandler.h b/src/plugins/debugger/threadshandler.h index 5c8cb189c4f..e365c8e462e 100644 --- a/src/plugins/debugger/threadshandler.h +++ b/src/plugins/debugger/threadshandler.h @@ -77,6 +77,7 @@ class ThreadsHandler : public ThreadsHandlerModel public: explicit ThreadsHandler(DebuggerEngine *engine); + ~ThreadsHandler(); Thread currentThread() const; Thread threadForId(const QString &id) const; @@ -95,7 +96,7 @@ public: void notifyRunning(const QString &id); void notifyStopped(const QString &id); - QComboBox *threadSwitcher() { return m_comboBox; } + QPointer<QComboBox> threadSwitcher(); private: void sort(int column, Qt::SortOrder order) override; @@ -105,7 +106,7 @@ private: DebuggerEngine *m_engine; Thread m_currentThread; QHash<QString, QString> m_pidForGroupId; - QComboBox *m_comboBox; + QPointer<QComboBox> m_comboBox; }; } // namespace Internal diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp index 703fac1434d..9d3f9919a0a 100644 --- a/src/plugins/designer/qtcreatorintegration.cpp +++ b/src/plugins/designer/qtcreatorintegration.cpp @@ -329,7 +329,8 @@ static Document::Ptr addDefinition(const Snapshot &docTable, const QString contents = editor->textDocument()->plainText(); int column; editor->convertPosition(contents.length(), line, &column); - editor->gotoLine(*line, column); + // gotoLine accepts 0-based column. + editor->gotoLine(*line, column - 1); editor->insert(definition); *line += 1; } diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp index 8c9db00828a..b045953e180 100644 --- a/src/plugins/git/branchmodel.cpp +++ b/src/plugins/git/branchmodel.cpp @@ -318,7 +318,7 @@ Qt::ItemFlags BranchModel::flags(const QModelIndex &index) const if (!node) return Qt::NoItemFlags; Qt::ItemFlags res = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if (node->isLeaf() && node->isLocal()) + if (node->isLeaf() && node->isLocal() && index.column() == 0) res |= Qt::ItemIsEditable; return res; } diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index c29b39d2ca4..f0469b9c472 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -544,7 +544,8 @@ QStringList GccToolChain::gccPrepareArguments(const QStringList &flags, allFlags << platformCodeGenFlags << flags; for (int i = 0; i < allFlags.size(); ++i) { const QString &flag = allFlags.at(i); - if (flag.startsWith("-stdlib=") || flag.startsWith("--gcctoolchain=")) { + if (flag.startsWith("-stdlib=") || flag.startsWith("--gcctoolchain=") + || flag.startsWith("-B")) { arguments << flag; } else if (!hasKitSysroot) { // pass build system's sysroot to compiler, if we didn't pass one from kit diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp index ea8223e60c1..504892c1494 100644 --- a/src/plugins/projectexplorer/makestep.cpp +++ b/src/plugins/projectexplorer/makestep.cpp @@ -196,14 +196,23 @@ void MakeStep::setJobCountOverrideMakeflags(bool override) m_overrideMakeflags = override; } +static bool argsContainsJobCount(const QString &str) +{ + const QStringList args = Utils::QtcProcess::splitArgs(str, Utils::HostOsInfo::hostOs()); + return Utils::anyOf(args, [](const QString &arg) { return arg.startsWith("-j"); }); +} + bool MakeStep::makeflagsContainsJobCount() const { const Utils::Environment env = environment(buildConfiguration()); if (!env.hasKey(MAKEFLAGS)) return false; - const QStringList args = Utils::QtcProcess::splitArgs(env.value(MAKEFLAGS), - Utils::HostOsInfo::hostOs()); - return Utils::anyOf(args, [](const QString &arg) { return arg.startsWith("-j"); }); + return argsContainsJobCount(env.value(MAKEFLAGS)); +} + +bool MakeStep::userArgsContainsJobCount() const +{ + return argsContainsJobCount(m_makeArguments); } Utils::Environment MakeStep::environment(BuildConfiguration *bc) const @@ -262,8 +271,10 @@ int MakeStep::defaultJobCount() QStringList MakeStep::jobArguments() const { - if (!isJobCountSupported() || (makeflagsContainsJobCount() && !jobCountOverridesMakeflags())) + if (!isJobCountSupported() || userArgsContainsJobCount() + || (makeflagsContainsJobCount() && !jobCountOverridesMakeflags())) { return {}; + } return {"-j" + QString::number(m_userJobCount)}; } @@ -408,6 +419,13 @@ void MakeStepConfigWidget::setUserJobCountVisible(bool visible) m_ui->overrideMakeflags->setVisible(visible); } +void MakeStepConfigWidget::setUserJobCountEnabled(bool enabled) +{ + m_ui->jobsLabel->setEnabled(enabled); + m_ui->userJobCount->setEnabled(enabled); + m_ui->overrideMakeflags->setEnabled(enabled); +} + void MakeStepConfigWidget::updateDetails() { BuildConfiguration *bc = m_makeStep->buildConfiguration(); @@ -428,6 +446,7 @@ void MakeStepConfigWidget::updateDetails() } setUserJobCountVisible(m_makeStep->isJobCountSupported()); + setUserJobCountEnabled(!m_makeStep->userArgsContainsJobCount()); m_ui->userJobCount->setValue(m_makeStep->jobCount()); m_ui->overrideMakeflags->setCheckState( m_makeStep->jobCountOverridesMakeflags() ? Qt::Checked : Qt::Unchecked); diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h index 94e71376f7f..0b4541b2116 100644 --- a/src/plugins/projectexplorer/makestep.h +++ b/src/plugins/projectexplorer/makestep.h @@ -73,6 +73,7 @@ public: bool jobCountOverridesMakeflags() const; void setJobCountOverrideMakeflags(bool override); bool makeflagsContainsJobCount() const; + bool userArgsContainsJobCount() const; Utils::Environment environment(BuildConfiguration *bc) const; @@ -105,6 +106,7 @@ private: void makeArgumentsLineEditTextEdited(); void updateDetails(); void setUserJobCountVisible(bool visible); + void setUserJobCountEnabled(bool enabled); Internal::Ui::MakeStep *m_ui; MakeStep *m_makeStep; diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp index fb854311a75..cb261427674 100644 --- a/src/plugins/qmakeprojectmanager/profileeditor.cpp +++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp @@ -81,8 +81,10 @@ void ProFileEditorWidget::findLinkAt(const QTextCursor &cursor, { Link link; - int lineNumber = 0, positionInBlock = 0; - convertPosition(cursor.position(), &lineNumber, &positionInBlock); + int line = 0; + int column = 0; + convertPosition(cursor.position(), &line, &column); + const int positionInBlock = column - 1; const QString block = cursor.block().text(); diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp index 6e3a3e43ad4..3af228874a7 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp @@ -128,7 +128,8 @@ void QmakeManager::addLibraryImpl(const QString &fileName, BaseTextEditor *edito // add extra \n in case the last line is not empty int line, column; editor->convertPosition(endOfDoc, &line, &column); - if (!editor->textAt(endOfDoc - column, column).simplified().isEmpty()) + const int positionInBlock = column - 1; + if (!editor->textAt(endOfDoc - positionInBlock, positionInBlock).simplified().isEmpty()) snippet = QLatin1Char('\n') + snippet; editor->insert(snippet); diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp index 8bf98d79c97..240fe160d4b 100644 --- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp +++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp @@ -133,9 +133,10 @@ void TextEditorWidget::jumpTextCursorToSelectedModelNode() const int nodeOffset = rewriterView->nodeOffset(selectedNode); if (nodeOffset > 0) { - int line, column; - m_textEditor->editorWidget()->convertPosition(nodeOffset, &line, &column); - m_textEditor->editorWidget()->gotoLine(line, column); + int line, column; + m_textEditor->editorWidget()->convertPosition(nodeOffset, &line, &column); + // line has to be 1 based, column 0 based! + m_textEditor->editorWidget()->gotoLine(line, column - 1); } } m_updateSelectionTimer.stop(); diff --git a/src/plugins/qmldesigner/componentsplugin/images/column-layouts-icon-16px.png b/src/plugins/qmldesigner/componentsplugin/images/column-layouts-icon-16px.png Binary files differindex 9e17cc85bf8..1113e8148b8 100644 --- a/src/plugins/qmldesigner/componentsplugin/images/column-layouts-icon-16px.png +++ b/src/plugins/qmldesigner/componentsplugin/images/column-layouts-icon-16px.png diff --git a/src/plugins/qmldesigner/componentsplugin/images/row-layouts-icon-16px.png b/src/plugins/qmldesigner/componentsplugin/images/row-layouts-icon-16px.png Binary files differindex 706194278ea..9e17cc85bf8 100644 --- a/src/plugins/qmldesigner/componentsplugin/images/row-layouts-icon-16px.png +++ b/src/plugins/qmldesigner/componentsplugin/images/row-layouts-icon-16px.png diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 4eb4f056666..4136be46725 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -259,6 +259,7 @@ public: virtual void contextHelpId(const Core::IContext::HelpIdCallback &callback) const; + void activateTimeline(const ModelNode &timeline); void activateTimelineRecording(const ModelNode &timeline); void deactivateTimelineRecording(); diff --git a/src/plugins/qmldesigner/designercore/include/qmltimeline.h b/src/plugins/qmldesigner/designercore/include/qmltimeline.h index 75280ba5f75..a92a2921198 100644 --- a/src/plugins/qmldesigner/designercore/include/qmltimeline.h +++ b/src/plugins/qmldesigner/designercore/include/qmltimeline.h @@ -67,6 +67,11 @@ public: void destroyKeyframesForTarget(const ModelNode &target); static bool hasActiveTimeline(AbstractView *view); + bool isRecording() const; + void toogleRecording(bool b) const; + + void resetGroupRecording() const; + private: void addKeyframeGroupIfNotExists(const ModelNode &node, const PropertyName &propertyName); bool hasKeyframeGroup(const ModelNode &node, const PropertyName &propertyName) const; diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index cc2f1412eea..5d536fb0c41 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -586,17 +586,37 @@ void AbstractView::contextHelpId(const Core::IContext::HelpIdCallback &callback) #endif } -void AbstractView::activateTimelineRecording(const ModelNode &timeline) +void AbstractView::activateTimeline(const ModelNode &timeline) { + if (currentTimeline().isValid()) + currentTimeline().toogleRecording(false); + Internal::WriteLocker locker(m_model.data()); + if (model()) model()->d->notifyCurrentTimelineChanged(timeline); +} + +void AbstractView::activateTimelineRecording(const ModelNode &timeline) +{ + if (currentTimeline().isValid()) + currentTimeline().toogleRecording(true); + Internal::WriteLocker locker(m_model.data()); + + if (model()) + model()->d->notifyCurrentTimelineChanged(timeline); } void AbstractView::deactivateTimelineRecording() { + if (currentTimeline().isValid()) { + currentTimeline().toogleRecording(false); + currentTimeline().resetGroupRecording(); + } + Internal::WriteLocker locker(m_model.data()); + if (model()) model()->d->notifyCurrentTimelineChanged(ModelNode()); } diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp index 650d1e73059..ad7cf13efc0 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp @@ -52,7 +52,7 @@ void QmlObjectNode::setVariantProperty(const PropertyName &name, const QVariant if (!isValid()) throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__); - if (timelineIsActive()) { + if (timelineIsActive() && currentTimeline().isRecording()) { modelNode().validId(); QmlTimelineKeyframeGroup timelineFrames(currentTimeline().keyframeGroup(modelNode(), name)); @@ -63,6 +63,18 @@ void QmlObjectNode::setVariantProperty(const PropertyName &name, const QVariant timelineFrames.setValue(value, frame); return; + } else if (timelineIsActive()) { + + QmlTimelineKeyframeGroup timelineFrames(currentTimeline().keyframeGroup(modelNode(), name)); + + Q_ASSERT(timelineFrames.isValid()); + + if (timelineFrames.isRecording()) { + qreal frame = currentTimeline().modelNode().auxiliaryData("currentFrame@NodeInstance").toReal(); + timelineFrames.setValue(value, frame); + + return; + } } if (isInBaseState()) { diff --git a/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp b/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp index 1cc44716640..04139385d28 100644 --- a/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmltimeline.cpp @@ -224,6 +224,37 @@ bool QmlTimeline::hasActiveTimeline(AbstractView *view) return false; } +bool QmlTimeline::isRecording() const +{ + QTC_ASSERT(isValid(), return false); + + return modelNode().hasAuxiliaryData("Record@Internal"); +} + +void QmlTimeline::toogleRecording(bool record) const +{ + QTC_ASSERT(isValid(), return); + + if (!record) { + if (isRecording()) + modelNode().removeAuxiliaryData("Record@Internal"); + } else { + modelNode().setAuxiliaryData("Record@Internal", true); + } +} + +void QmlTimeline::resetGroupRecording() const +{ + QTC_ASSERT(isValid(), return); + + for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) { + if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(childNode)) { + const QmlTimelineKeyframeGroup frames(childNode); + frames.toogleRecording(false); + } + } +} + void QmlTimeline::addKeyframeGroupIfNotExists(const ModelNode &node, const PropertyName &propertyName) { if (!isValid()) diff --git a/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp index e105fb279b9..35ff98710ca 100644 --- a/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframegroup.cpp @@ -129,7 +129,7 @@ bool QmlTimelineKeyframeGroup::isRecording() const { QTC_ASSERT(isValid(), return false); - return modelNode().hasAuxiliaryData("REC@Internal"); + return modelNode().hasAuxiliaryData("Record@Internal"); } void QmlTimelineKeyframeGroup::toogleRecording(bool record) const @@ -138,9 +138,9 @@ void QmlTimelineKeyframeGroup::toogleRecording(bool record) const if (!record) { if (isRecording()) - modelNode().removeAuxiliaryData("REC@Internal"); + modelNode().removeAuxiliaryData("Record@Internal"); } else { - modelNode().setAuxiliaryData("REC@Internal", true); + modelNode().setAuxiliaryData("Record@Internal", true); } } diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 877010a3b72..9ab39cce379 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -374,7 +374,8 @@ void QmlDesignerPlugin::jumpTextCursorToSelectedModelNode() if (currentSelectedNode != selectedNode) { int line, column; currentDesignDocument()->textEditor()->convertPosition(nodeOffset, &line, &column); - currentDesignDocument()->textEditor()->gotoLine(line, column); + // line has to be 1 based, column 0 based! + currentDesignDocument()->textEditor()->gotoLine(line, column - 1); } } } diff --git a/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon-16px.png Binary files differindex 9e17cc85bf8..1113e8148b8 100644 --- a/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon-16px.png +++ b/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon-16px.png diff --git a/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon.png b/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon.png Binary files differindex a75ee209d5c..df4b60327e0 100644 --- a/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon.png +++ b/src/plugins/qmldesigner/qtquickplugin/images/column-positioner-icon.png diff --git a/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon-16px.png b/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon-16px.png Binary files differindex 1113e8148b8..9e17cc85bf8 100644 --- a/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon-16px.png +++ b/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon-16px.png diff --git a/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon.png b/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon.png Binary files differindex df4b60327e0..a75ee209d5c 100644 --- a/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon.png +++ b/src/plugins/qmldesigner/qtquickplugin/images/row-positioner-icon.png diff --git a/src/plugins/qmldesigner/qtquickplugin/images/[email protected] b/src/plugins/qmldesigner/qtquickplugin/images/[email protected] Binary files differindex ffef790cdc0..c70f845e708 100644 --- a/src/plugins/qmldesigner/qtquickplugin/images/[email protected] +++ b/src/plugins/qmldesigner/qtquickplugin/images/[email protected] diff --git a/src/plugins/serialterminal/serialoutputpane.cpp b/src/plugins/serialterminal/serialoutputpane.cpp index 12613d447df..0ae2cf1e42f 100644 --- a/src/plugins/serialterminal/serialoutputpane.cpp +++ b/src/plugins/serialterminal/serialoutputpane.cpp @@ -55,7 +55,7 @@ namespace SerialTerminal { namespace Internal { -static Q_LOGGING_CATEGORY(log, Constants::LOGGING_CATEGORY) +static Q_LOGGING_CATEGORY(log, Constants::LOGGING_CATEGORY, QtWarningMsg) // Tab Widget helper for middle click tab close class TabWidget : public QTabWidget diff --git a/src/plugins/serialterminal/serialterminalsettings.cpp b/src/plugins/serialterminal/serialterminalsettings.cpp index 8136ea3ffa4..7c66d01e2b7 100644 --- a/src/plugins/serialterminal/serialterminalsettings.cpp +++ b/src/plugins/serialterminal/serialterminalsettings.cpp @@ -32,7 +32,7 @@ namespace SerialTerminal { namespace Internal { -static Q_LOGGING_CATEGORY(log, Constants::LOGGING_CATEGORY) +static Q_LOGGING_CATEGORY(log, Constants::LOGGING_CATEGORY, QtWarningMsg) // Set 'value' only if the key exists in the settings template <typename T> diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 9abbe3a8f19..1290199a54d 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -104,6 +104,7 @@ private: IAssistProposalWidget *m_proposalWidget = nullptr; QScopedPointer<IAssistProposal> m_proposal; bool m_receivedContentWhileWaiting = false; + bool m_proposalItemProcessed = false; QTimer m_automaticProposalTimer; CompletionSettings m_settings; int m_abortedBasePosition = -1; @@ -192,6 +193,13 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, if (m_editorWidget->hasBlockSelection()) return; // TODO + if (m_proposalItemProcessed + && reason == IdleEditor + && m_assistKind == TextEditor::Completion + && !identifyActivationSequence()) { + return; + } + if (!provider) { if (kind == Completion) provider = m_editorWidget->textDocument()->completionAssistProvider(); @@ -358,6 +366,15 @@ void CodeAssistantPrivate::processProposalItem(AssistProposalItemInterface *prop if (!proposalItem->isSnippet()) process(); m_editorWidget->encourageApply(); + m_proposalItemProcessed = true; + + auto connection = std::make_shared<QMetaObject::Connection>(); + *connection = connect(m_editorWidget->textDocument(), + &Core::IDocument::contentsChanged, + this, [this, connection] { + m_proposalItemProcessed = false; + disconnect(*connection); + }); } void CodeAssistantPrivate::handlePrefixExpansion(const QString &newPrefix) diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp index 35e82384b21..1c05e1f1eae 100644 --- a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp @@ -167,29 +167,57 @@ static QString cleanText(const QString &original) return clean; } +static bool textStartsWith(CaseSensitivity cs, const QString &text, const QString &prefix) +{ + switch (cs) { + case TextEditor::CaseInsensitive: + return text.startsWith(prefix, Qt::CaseInsensitive); + case TextEditor::CaseSensitive: + return text.startsWith(prefix, Qt::CaseSensitive); + case TextEditor::FirstLetterCaseSensitive: + return prefix.at(0) == text.at(0) + && prefix.midRef(1).startsWith(text.midRef(1), Qt::CaseInsensitive); + } + + return false; +} + +enum class PerfectMatchType { + None, + StartsWith, + Full, +}; + +static PerfectMatchType perfectMatch(CaseSensitivity cs, const QString &text, const QString &prefix) +{ + if (textStartsWith(cs, text, prefix)) + return prefix.size() == text.size() ? PerfectMatchType::Full : PerfectMatchType::StartsWith; + + return PerfectMatchType::None; +} + bool GenericProposalModel::isPerfectMatch(const QString &prefix) const { if (prefix.isEmpty()) return false; + const CaseSensitivity cs = TextEditorSettings::completionSettings().m_caseSensitivity; + bool hasFullMatch = false; + for (int i = 0; i < size(); ++i) { const QString ¤t = cleanText(text(i)); - if (!current.isEmpty()) { - CaseSensitivity cs = TextEditorSettings::completionSettings().m_caseSensitivity; - if (cs == TextEditor::CaseSensitive) { - if (prefix == current) - return true; - } else if (cs == TextEditor::CaseInsensitive) { - if (prefix.compare(current, Qt::CaseInsensitive) == 0) - return true; - } else if (cs == TextEditor::FirstLetterCaseSensitive) { - if (prefix.at(0) == current.at(0) - && prefix.midRef(1).compare(current.midRef(1), Qt::CaseInsensitive) == 0) - return true; - } - } + if (current.isEmpty()) + continue; + + const PerfectMatchType match = perfectMatch(cs, current, prefix); + if (match == PerfectMatchType::StartsWith) + return false; + + if (!hasFullMatch && match == PerfectMatchType::Full) + hasFullMatch = true; } - return false; + + return hasFullMatch; } bool GenericProposalModel::isPrefiltered(const QString &prefix) const diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp index f7004e878ca..e4d07adef91 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.cpp +++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp @@ -337,6 +337,13 @@ void Highlighter::iterateThroughRules(const QString &text, const bool childRule, const QList<QSharedPointer<Rule> > &rules) { + if (!childRule) { + if (progress->detectRecursion(m_currentContext->id())) { + progress->setOffset(length); + return; + } + } + typedef QList<QSharedPointer<Rule> >::const_iterator RuleIterator; bool contextChanged = false; diff --git a/src/plugins/texteditor/generichighlighter/progressdata.cpp b/src/plugins/texteditor/generichighlighter/progressdata.cpp index d79d5b01524..a6453c83998 100644 --- a/src/plugins/texteditor/generichighlighter/progressdata.cpp +++ b/src/plugins/texteditor/generichighlighter/progressdata.cpp @@ -113,3 +113,18 @@ void ProgressData::unTrackRule(Rule *rule) { m_trackedRules.removeAll(rule); } + +bool ProgressData::detectRecursion(const QString &contextId) +{ + if (m_offset != m_iterationOffset) { + m_iterationOffset = m_offset; + m_iterationContextIds.clear(); + } + + if (m_iterationContextIds.contains(contextId)) + return true; + + m_iterationContextIds.append(contextId); + + return false; +} diff --git a/src/plugins/texteditor/generichighlighter/progressdata.h b/src/plugins/texteditor/generichighlighter/progressdata.h index d2b158146d5..7350eb0d047 100644 --- a/src/plugins/texteditor/generichighlighter/progressdata.h +++ b/src/plugins/texteditor/generichighlighter/progressdata.h @@ -67,6 +67,8 @@ public: void trackRule(Rule *rule); void unTrackRule(Rule *rule); + bool detectRecursion(const QString &contextId); + private: int m_offset; int m_savedOffset; @@ -76,6 +78,8 @@ private: bool m_willContinueLine; QStringList m_captures; QList<Rule *> m_trackedRules; + int m_iterationOffset = -1; + QStringList m_iterationContextIds; }; } // namespace Internal diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 3141a126208..37a57412bf7 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -3104,14 +3104,14 @@ bool TextEditorWidget::restoreState(const QByteArray &state) int version; int vval; int hval; - int lval; - int cval; + int lineVal; + int columnVal; QDataStream stream(state); stream >> version; stream >> vval; stream >> hval; - stream >> lval; - stream >> cval; + stream >> lineVal; + stream >> columnVal; if (version >= 1) { QList<int> collapsedBlocks; @@ -3137,7 +3137,8 @@ bool TextEditorWidget::restoreState(const QByteArray &state) } d->m_lastCursorChangeWasInteresting = false; // avoid adding last position to history - gotoLine(lval, cval); + // line is 1-based, column is 0-based + gotoLine(lineVal, columnVal - 1); verticalScrollBar()->setValue(vval); horizontalScrollBar()->setValue(hval); d->saveCurrentCursorPositionForNavigation(); diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp index d0633caa837..e0f308ebaab 100644 --- a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp +++ b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp @@ -225,11 +225,11 @@ void CallgrindController::getLocalDataFile() // this, &CallgrindController::foundRemoteFile); // m_findRemoteFile->start(); } else { - QDir dir(workingDir, QString::fromLatin1("%1.*").arg(baseFileName), QDir::Time); - QStringList outputFiles = dir.entryList(); + const QDir dir(workingDir, QString::fromLatin1("%1.*").arg(baseFileName), QDir::Time); + const QStringList outputFiles = dir.entryList(); // if there are files like callgrind.out.PID.NUM, set it to the most recent one of those if (!outputFiles.isEmpty()) - fileName = workingDir + QLatin1Char('/') + dir.entryList().first(); + fileName = workingDir + QLatin1Char('/') + outputFiles.first(); emit localParseDataAvailable(fileName); } |