diff --git a/src/libs/clangbackendipc/clangbackendipc-lib.pri b/src/libs/clangbackendipc/clangbackendipc-lib.pri index 36afd9ae70f..9664775dd1d 100644 --- a/src/libs/clangbackendipc/clangbackendipc-lib.pri +++ b/src/libs/clangbackendipc/clangbackendipc-lib.pri @@ -155,6 +155,7 @@ HEADERS += \ $$PWD/pchmanagerclientproxy.h \ $$PWD/projectpartpch.h \ $$PWD/precompiledheadersupdatedmessage.h \ + $$PWD/stringcache.h \ $$PWD/removepchprojectpartsmessage.h \ $$PWD/clangcodemodelclientmessages.h \ $$PWD/clangcodemodelservermessages.h \ diff --git a/src/libs/clangbackendipc/filepath.h b/src/libs/clangbackendipc/filepath.h index d435441a133..717d0207905 100644 --- a/src/libs/clangbackendipc/filepath.h +++ b/src/libs/clangbackendipc/filepath.h @@ -37,66 +37,62 @@ class FilePath { public: FilePath() = default; - explicit FilePath(Utils::SmallString &&filePath) + explicit FilePath(Utils::PathString &&filePath) + : m_path(std::move(filePath)) { - auto foundReverse = std::find(filePath.rbegin(), filePath.rend(), '/'); + auto foundReverse = std::find(m_path.rbegin(), m_path.rend(), '/'); auto found = foundReverse.base(); + --found; - Utils::SmallString fileName(found, filePath.end()); - if (foundReverse != filePath.rend()) - filePath.resize(std::size_t(std::distance(filePath.begin(), --found))); + m_slashIndex = std::size_t(std::distance(m_path.begin(), found)); + } - directory_ = std::move(filePath); - name_ = std::move(fileName); + explicit FilePath(const Utils::PathString &filePath) + : FilePath(filePath.clone()) + { + } + + explicit FilePath(Utils::PathString &&filePath, std::size_t slashIndex) + : m_path(std::move(filePath)), + m_slashIndex(slashIndex) + { } explicit FilePath(const QString &filePath) - : FilePath(Utils::SmallString(filePath)) + : FilePath(Utils::PathString(filePath)) { } - FilePath(Utils::SmallString &&directory, Utils::SmallString &&name) - : directory_(std::move(directory)), - name_(std::move(name)) + FilePath(const Utils::PathString &directory, const Utils::PathString &name) + : m_path({std::move(directory), "/", std::move(name)}), + m_slashIndex(directory.size()) {} - const Utils::SmallString &directory() const + Utils::SmallStringView directory() const { - return directory_; + return m_path.mid(0, m_slashIndex); } - Utils::SmallString takeDirectory() + Utils::SmallStringView name() const { - return std::move(directory_); + return m_path.mid(m_slashIndex + 1, m_path.size() - m_slashIndex - 1); } - const Utils::SmallString &name() const + const Utils::PathString &path() const { - return name_; - } - - Utils::SmallString takeName() - { - return std::move(name_); - } - - Utils::PathString path() const - { - return {directory_, "/", name_}; + return m_path; } friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath) { - out << filePath.directory_; - out << filePath.name_; + out << filePath.m_path; return out; } friend QDataStream &operator>>(QDataStream &in, FilePath &filePath) { - in >> filePath.directory_; - in >> filePath.name_; + in >> filePath.m_path; return in; } @@ -110,24 +106,22 @@ public: friend bool operator==(const FilePath &first, const FilePath &second) { - return first.name_ == second.name_ - && first.directory_ == second.directory_; + return first.m_path == second.m_path; } friend bool operator<(const FilePath &first, const FilePath &second) { - return std::tie(first.name_, first.directory_) - < std::tie(second.name_, second.directory_); + return first.m_path < second.m_path; } FilePath clone() const { - return FilePath(directory_.clone(), name_.clone()); + return FilePath(m_path.clone(), m_slashIndex); } private: - Utils::SmallString directory_; - Utils::SmallString name_; + Utils::PathString m_path = "/"; + std::size_t m_slashIndex = 0; }; CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath); diff --git a/src/libs/clangbackendipc/sourcefilepathcontainerbase.h b/src/libs/clangbackendipc/sourcefilepathcontainerbase.h index af5f8b570c6..ebf717f15e6 100644 --- a/src/libs/clangbackendipc/sourcefilepathcontainerbase.h +++ b/src/libs/clangbackendipc/sourcefilepathcontainerbase.h @@ -42,13 +42,10 @@ public: { } - void insertFilePath(uint fileId, Utils::SmallString &&fileDirectory, Utils::SmallString &&fileName) + void insertFilePath(uint fileId, Utils::PathString &&filePath) { - if (m_filePathHash.find(fileId) == m_filePathHash.end()) { - m_filePathHash.emplace(std::piecewise_construct, - std::forward_as_tuple(fileId), - std::forward_as_tuple(std::move(fileDirectory), std::move(fileName))); - } + if (m_filePathHash.find(fileId) == m_filePathHash.end()) + m_filePathHash.emplace(fileId, FilePath(std::move(filePath))); } void reserve(std::size_t size) diff --git a/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp b/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp index b65803e7c65..3206daf2b58 100644 --- a/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp +++ b/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp @@ -46,10 +46,10 @@ QDebug operator<<(QDebug debug, const SourceLocationContainer &container) std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container) { os << "(" + << container.fileHash() << ", " << container.line() << ", " << container.column() << ", " - << container.offset() << ", " - << container.fileHash() + << container.offset() << ")"; return os; diff --git a/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.h b/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.h index f6c17a95290..6634d501956 100644 --- a/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.h +++ b/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.h @@ -47,6 +47,11 @@ public: return sourceRangesContainer; } + SourceRangesContainer &sourceRanges() + { + return sourceRangesContainer; + } + const std::vector &diagnostics() const { return diagnosticContainers; diff --git a/src/libs/clangbackendipc/sourcerangescontainer.h b/src/libs/clangbackendipc/sourcerangescontainer.h index 11ea542136a..147b7cb53ae 100644 --- a/src/libs/clangbackendipc/sourcerangescontainer.h +++ b/src/libs/clangbackendipc/sourcerangescontainer.h @@ -54,6 +54,11 @@ public: return m_sourceRangeWithTextContainers; } + std::vector &sourceRangeWithTextContainers() + { + return m_sourceRangeWithTextContainers; + } + std::vector takeSourceRangeWithTextContainers() { return std::move(m_sourceRangeWithTextContainers); diff --git a/src/libs/clangbackendipc/sourcerangewithtextcontainer.h b/src/libs/clangbackendipc/sourcerangewithtextcontainer.h index 12b25084c3d..8a92086319b 100644 --- a/src/libs/clangbackendipc/sourcerangewithtextcontainer.h +++ b/src/libs/clangbackendipc/sourcerangewithtextcontainer.h @@ -110,6 +110,25 @@ private: Utils::SmallString m_text; }; +using SourceRangeWithTextContainers = std::vector; + CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container); std::ostream &operator<<(std::ostream &os, const SourceRangeWithTextContainer &container); } // namespace ClangBackEnd + +namespace std +{ +template<> struct hash +{ + using argument_type = ClangBackEnd::SourceRangeWithTextContainer; + using result_type = std::size_t; + result_type operator()(const argument_type &container) const + { + const result_type h1{std::hash{}(container.fileHash())}; + const result_type h2{std::hash{}(container.start().offset())}; + const result_type h3{std::hash{}(container.end().offset())}; + + return h1 ^ (h2 << 8) ^ (h3 << 16); + } +}; +} diff --git a/src/tools/clangpchmanagerbackend/source/stringcache.h b/src/libs/clangbackendipc/stringcache.h similarity index 89% rename from src/tools/clangpchmanagerbackend/source/stringcache.h rename to src/libs/clangbackendipc/stringcache.h index a85c314700b..7b4230b5770 100644 --- a/src/tools/clangpchmanagerbackend/source/stringcache.h +++ b/src/libs/clangbackendipc/stringcache.h @@ -25,16 +25,26 @@ #pragma once -#include "clangpchmanagerbackend_global.h" - #include #include +#include #include namespace ClangBackEnd { -template +class NonLockingMutex +{ +public: + constexpr NonLockingMutex() noexcept {} + NonLockingMutex(const NonLockingMutex&) = delete; + NonLockingMutex& operator=(const NonLockingMutex&) = delete; + void lock() {} + void unlock() {} +}; + +template class StringCache { class StringCacheEntry @@ -79,6 +89,8 @@ public: uint stringId(Utils::SmallStringView stringView) { + std::lock_guard lock(m_mutex); + Found found = find(stringView); if (!found.wasFound) @@ -89,6 +101,8 @@ public: std::vector stringIds(const std::vector &strings) { + std::lock_guard lock(m_mutex); + std::vector ids; ids.reserve(strings.size()); @@ -102,11 +116,15 @@ public: const StringType &string(uint id) const { + std::lock_guard lock(m_mutex); + return m_strings.at(m_indices.at(id)).string; } std::vector strings(const std::vector &ids) const { + std::lock_guard lock(m_mutex); + std::vector strings; strings.reserve(ids.size()); @@ -155,6 +173,7 @@ private: private: StringCacheEntries m_strings; std::vector m_indices; + mutable Mutex m_mutex; }; } // namespace ClangBackEnd diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index d90775e5033..02065a06ac0 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -395,18 +395,13 @@ FileSaverBase::FileSaverBase() { } -FileSaverBase::~FileSaverBase() -{ - delete m_file; -} +FileSaverBase::~FileSaverBase() = default; bool FileSaverBase::finalize() { m_file->close(); setResult(m_file->error() == QFile::NoError); - // We delete the object, so it is really closed even if it is a QTemporaryFile. - delete m_file; - m_file = 0; + m_file.reset(); return !m_hasError; } @@ -444,8 +439,13 @@ bool FileSaverBase::write(const QByteArray &bytes) bool FileSaverBase::setResult(bool ok) { if (!ok && !m_hasError) { - m_errorString = tr("Cannot write file %1. Disk full?").arg( - QDir::toNativeSeparators(m_fileName)); + if (!m_file->errorString().isEmpty()) { + m_errorString = tr("Cannot write file %1: %2").arg( + QDir::toNativeSeparators(m_fileName), m_file->errorString()); + } else { + m_errorString = tr("Cannot write file %1. Disk full?").arg( + QDir::toNativeSeparators(m_fileName)); + } m_hasError = true; } return ok; @@ -488,10 +488,10 @@ FileSaver::FileSaver(const QString &filename, QIODevice::OpenMode mode) } } if (mode & (QIODevice::ReadOnly | QIODevice::Append)) { - m_file = new QFile(filename); + m_file.reset(new QFile{filename}); m_isSafe = false; } else { - m_file = new SaveFile(filename); + m_file.reset(new SaveFile{filename}); m_isSafe = true; } if (!m_file->open(QIODevice::WriteOnly | mode)) { @@ -507,22 +507,22 @@ bool FileSaver::finalize() if (!m_isSafe) return FileSaverBase::finalize(); - SaveFile *sf = static_cast(m_file); + SaveFile *sf = static_cast(m_file.get()); if (m_hasError) { if (sf->isOpen()) sf->rollback(); } else { setResult(sf->commit()); } - delete sf; - m_file = 0; + m_file.reset(); return !m_hasError; } TempFileSaver::TempFileSaver(const QString &templ) : m_autoRemove(true) { - QTemporaryFile *tempFile = new QTemporaryFile(); + m_file.reset(new QTemporaryFile{}); + QTemporaryFile *tempFile = static_cast(m_file.get()); if (!templ.isEmpty()) tempFile->setFileTemplate(templ); tempFile->setAutoRemove(false); @@ -532,14 +532,12 @@ TempFileSaver::TempFileSaver(const QString &templ) tempFile->errorString()); m_hasError = true; } - m_file = tempFile; m_fileName = tempFile->fileName(); } TempFileSaver::~TempFileSaver() { - delete m_file; - m_file = 0; + m_file.reset(); if (m_autoRemove) QFile::remove(m_fileName); } diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index 43f7fc2e86e..f891e2d15f8 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -35,6 +35,7 @@ #include #include +#include namespace Utils {class FileName; } @@ -190,8 +191,10 @@ public: bool setResult(QXmlStreamWriter *stream); bool setResult(bool ok); + QFile *file() { return m_file.get(); } + protected: - QFile *m_file; + std::unique_ptr m_file; QString m_fileName; QString m_errorString; bool m_hasError; @@ -208,7 +211,6 @@ public: virtual bool finalize(); using FileSaverBase::finalize; - QFile *file() { return m_file; } private: bool m_isSafe; @@ -221,8 +223,6 @@ public: explicit TempFileSaver(const QString &templ = QString()); ~TempFileSaver(); - QTemporaryFile *file() { return reinterpret_cast(m_file); } - void setAutoRemove(bool on) { m_autoRemove = on; } private: diff --git a/src/libs/utils/savefile.cpp b/src/libs/utils/savefile.cpp index b514d6233d0..aeac15a6273 100644 --- a/src/libs/utils/savefile.cpp +++ b/src/libs/utils/savefile.cpp @@ -113,10 +113,19 @@ bool SaveFile::commit() QString finalFileName = FileUtils::resolveSymlinks(FileName::fromString(m_finalFileName)).toString(); QString bakname = finalFileName + QLatin1Char('~'); - QFile::remove(bakname); // Kill old backup - QFile::rename(finalFileName, bakname); // Backup current file + + if (QFile::exists(finalFileName)) { + QFile::remove(bakname); // Kill old backup + // Try to back up current file + if (!QFile::rename(finalFileName, bakname)) { + remove(); + setErrorString(tr("File might be locked.")); + return false; + } + } if (!rename(finalFileName)) { // Replace current file QFile::rename(bakname, finalFileName); // Rollback to current file + remove(); return false; } if (!m_backup) diff --git a/src/libs/utils/smallstringio.h b/src/libs/utils/smallstringio.h index 26424b22fe0..e212fc85672 100644 --- a/src/libs/utils/smallstringio.h +++ b/src/libs/utils/smallstringio.h @@ -68,12 +68,12 @@ QDataStream &operator>>(QDataStream &in, BasicSmallString &string) return in; } -inline -QDebug &operator<<(QDebug &debug, const SmallString &string) +template +QDebug &operator<<(QDebug &debug, const String &string) { using QT_PREPEND_NAMESPACE(operator<<); - debug.nospace() << "\"" << string.data() << "\""; + debug.nospace().quote() << QByteArray::fromRawData(string.data(), int(string.size())); return debug; } diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index 2d445501c2e..3e11497ed3e 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -104,6 +104,11 @@ public: return const_reverse_iterator(begin() - static_cast(1)); } + operator std::string() const + { + return std::string(data(), size()); + } + private: const char *m_pointer; size_type m_size; diff --git a/src/plugins/autotest/qtest/qttestconfiguration.cpp b/src/plugins/autotest/qtest/qttestconfiguration.cpp index 2329bfe6bc5..0875ec18a63 100644 --- a/src/plugins/autotest/qtest/qttestconfiguration.cpp +++ b/src/plugins/autotest/qtest/qttestconfiguration.cpp @@ -67,6 +67,12 @@ QStringList QtTestConfiguration::argumentsForTestRunner() const if (!metricsOption.isEmpty()) arguments << metricsOption; + if (qtSettings->verboseBench) + arguments << "-vb"; + + if (qtSettings->logSignalsSlots) + arguments << "-vs"; + if (runMode() == DebuggableTestConfiguration::Debug) { if (qtSettings->noCrashHandler) arguments << "-nocrashhandler"; diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index aa86681a486..acf435fd88c 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -319,7 +319,7 @@ void QtTestOutputReader::processPlainTextOutput(const QByteArray &outputLine) static QRegExp finish("^[*]{9} Finished testing of (.*) [*]{9}$"); static QRegExp result("^(PASS |FAIL! |XFAIL |XPASS |SKIP |BPASS |BFAIL |RESULT " - "|INFO |QWARN |WARNING|QDEBUG ): (.*)$"); + "|INFO |QWARN |WARNING|QDEBUG ): (.*)$"); static QRegExp benchDetails("^\\s+([\\d,.]+ .* per iteration \\(total: [\\d,.]+, iterations: \\d+\\))$"); static QRegExp locationUnix("^ Loc: \\[(.*)\\]$"); diff --git a/src/plugins/autotest/qtest/qttestsettings.cpp b/src/plugins/autotest/qtest/qttestsettings.cpp index 1b672cd29dd..dba1be98e27 100644 --- a/src/plugins/autotest/qtest/qttestsettings.cpp +++ b/src/plugins/autotest/qtest/qttestsettings.cpp @@ -31,6 +31,8 @@ namespace Internal { static const char metricsKey[] = "Metrics"; static const char noCrashhandlerKey[] = "NoCrashhandlerOnDebug"; static const char useXMLOutputKey[] = "UseXMLOutput"; +static const char verboseBenchKey[] = "VerboseBench"; +static const char logSignalsSlotsKey[] = "LogSignalsSlots"; static MetricsType intToMetrics(int value) { @@ -60,6 +62,8 @@ void QtTestSettings::fromFrameworkSettings(const QSettings *s) metrics = intToMetrics(s->value(metricsKey, Walltime).toInt()); noCrashHandler = s->value(noCrashhandlerKey, true).toBool(); useXMLOutput = s->value(useXMLOutputKey, true).toBool(); + verboseBench = s->value(verboseBenchKey, false).toBool(); + logSignalsSlots = s->value(logSignalsSlotsKey, false).toBool(); } void QtTestSettings::toFrameworkSettings(QSettings *s) const @@ -67,6 +71,8 @@ void QtTestSettings::toFrameworkSettings(QSettings *s) const s->setValue(metricsKey, metrics); s->setValue(noCrashhandlerKey, noCrashHandler); s->setValue(useXMLOutputKey, useXMLOutput); + s->setValue(verboseBenchKey, verboseBench); + s->setValue(logSignalsSlotsKey, logSignalsSlots); } QString QtTestSettings::metricsTypeToOption(const MetricsType type) diff --git a/src/plugins/autotest/qtest/qttestsettings.h b/src/plugins/autotest/qtest/qttestsettings.h index 9418059243b..8f2c0954b9b 100644 --- a/src/plugins/autotest/qtest/qttestsettings.h +++ b/src/plugins/autotest/qtest/qttestsettings.h @@ -49,6 +49,8 @@ public: MetricsType metrics = Walltime; bool noCrashHandler = true; bool useXMLOutput = true; + bool verboseBench = false; + bool logSignalsSlots = false; protected: void fromFrameworkSettings(const QSettings *s) override; diff --git a/src/plugins/autotest/qtest/qttestsettingspage.cpp b/src/plugins/autotest/qtest/qttestsettingspage.cpp index 8258440ec4e..8aa4c6cc133 100644 --- a/src/plugins/autotest/qtest/qttestsettingspage.cpp +++ b/src/plugins/autotest/qtest/qttestsettingspage.cpp @@ -47,6 +47,8 @@ void QtTestSettingsWidget::setSettings(const QtTestSettings &settings) { m_ui.disableCrashhandlerCB->setChecked(settings.noCrashHandler); m_ui.useXMLOutputCB->setChecked(settings.useXMLOutput); + m_ui.verboseBenchmarksCB->setChecked(settings.verboseBench); + m_ui.logSignalsAndSlotsCB->setChecked(settings.logSignalsSlots); switch (settings.metrics) { case MetricsType::Walltime: m_ui.walltimeRB->setChecked(true); @@ -74,6 +76,8 @@ QtTestSettings QtTestSettingsWidget::settings() const result.noCrashHandler = m_ui.disableCrashhandlerCB->isChecked(); result.useXMLOutput = m_ui.useXMLOutputCB->isChecked(); + result.verboseBench = m_ui.verboseBenchmarksCB->isChecked(); + result.logSignalsSlots = m_ui.logSignalsAndSlotsCB->isChecked(); if (m_ui.walltimeRB->isChecked()) result.metrics = MetricsType::Walltime; else if (m_ui.tickcounterRB->isChecked()) diff --git a/src/plugins/autotest/qtest/qttestsettingspage.ui b/src/plugins/autotest/qtest/qttestsettingspage.ui index 38837afee87..4991107a022 100644 --- a/src/plugins/autotest/qtest/qttestsettingspage.ui +++ b/src/plugins/autotest/qtest/qttestsettingspage.ui @@ -46,6 +46,23 @@ Warning: Plain text output is missing some information (e.g. duration) + + + + Verbose benchmarks + + + + + + + Log every signal emission and resulting slot invocations. + + + Log signals and slots + + + diff --git a/src/plugins/clangrefactoring/refactoringclient.cpp b/src/plugins/clangrefactoring/refactoringclient.cpp index 83b058d6263..4cb954e2313 100644 --- a/src/plugins/clangrefactoring/refactoringclient.cpp +++ b/src/plugins/clangrefactoring/refactoringclient.cpp @@ -104,19 +104,6 @@ void RefactoringClient::setRefactoringConnectionClient( this->connectionClient = connectionClient; } -namespace { - -Utils::SmallString concatenateFilePath(const ClangBackEnd::FilePath &filePath) -{ - Utils::SmallString concatenatedFilePath = filePath.directory().clone(); - concatenatedFilePath.append("/"); - concatenatedFilePath.append(filePath.name().clone()); - - return concatenatedFilePath; -} - -} - std::unordered_map RefactoringClient::convertFilePaths( const ClangBackEnd::FilePathDict &filePaths) { @@ -126,7 +113,7 @@ std::unordered_map RefactoringClient::convertFilePaths( auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) { return std::make_pair(dictonaryEntry.first, - concatenateFilePath(dictonaryEntry.second).toQString()); + dictonaryEntry.second.path().toQString()); }; std::transform(filePaths.begin(), diff --git a/src/plugins/coreplugin/find/finddialog.ui b/src/plugins/coreplugin/find/finddialog.ui index 1f3c900b3ff..7ada6ce0aa9 100644 --- a/src/plugins/coreplugin/find/finddialog.ui +++ b/src/plugins/coreplugin/find/finddialog.ui @@ -55,7 +55,7 @@ - + Sear&ch for: @@ -73,7 +73,16 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -103,9 +112,18 @@ - + - + + 0 + + + 0 + + + 0 + + 0 diff --git a/src/plugins/coreplugin/find/findtoolwindow.cpp b/src/plugins/coreplugin/find/findtoolwindow.cpp index b29dfbe4f8e..ffcf3855253 100644 --- a/src/plugins/coreplugin/find/findtoolwindow.cpp +++ b/src/plugins/coreplugin/find/findtoolwindow.cpp @@ -147,6 +147,13 @@ void FindToolWindow::updateButtonStates() if (m_configWidget) m_configWidget->setEnabled(filterEnabled); + if (m_currentFilter) { + m_ui.searchTerm->setVisible(m_currentFilter->showSearchTermInput()); + m_ui.searchLabel->setVisible(m_currentFilter->showSearchTermInput()); + m_ui.optionsWidget->setVisible(m_currentFilter->supportedFindFlags() + & (FindCaseSensitively | FindWholeWords | FindRegularExpression)); + } + m_ui.matchCase->setEnabled(filterEnabled && (m_currentFilter->supportedFindFlags() & FindCaseSensitively)); m_ui.wholeWords->setEnabled(filterEnabled diff --git a/src/plugins/coreplugin/find/ifindfilter.cpp b/src/plugins/coreplugin/find/ifindfilter.cpp index e080e249f0c..d57a16370e1 100644 --- a/src/plugins/coreplugin/find/ifindfilter.cpp +++ b/src/plugins/coreplugin/find/ifindfilter.cpp @@ -142,6 +142,14 @@ your find filter supports global search and replace. */ +/*! + \fn bool showSearchTermInput() const + Returns whether the find filter wants to show the search term line edit. + + The default value is \c true, override this function to return \c false, if + your find filter does not want to show the search term line edit. +*/ + /*! \fn void IFindFilter::findAll(const QString &txt, Core::FindFlags findFlags) This function is called when the user selected this find scope and @@ -227,7 +235,8 @@ QKeySequence IFindFilter::defaultShortcut() const FindFlags IFindFilter::supportedFindFlags() const { return FindCaseSensitively - | FindRegularExpression | FindWholeWords; + | FindRegularExpression + | FindWholeWords; } QPixmap IFindFilter::pixmapForFindFlags(FindFlags flags) diff --git a/src/plugins/coreplugin/find/ifindfilter.h b/src/plugins/coreplugin/find/ifindfilter.h index 41a920379d9..9c67c29fc2e 100644 --- a/src/plugins/coreplugin/find/ifindfilter.h +++ b/src/plugins/coreplugin/find/ifindfilter.h @@ -50,6 +50,7 @@ public: virtual bool isValid() const { return true; } virtual QKeySequence defaultShortcut() const; virtual bool isReplaceSupported() const { return false; } + virtual bool showSearchTermInput() const { return true; } virtual FindFlags supportedFindFlags() const; virtual void findAll(const QString &txt, FindFlags findFlags) = 0; diff --git a/src/plugins/cpptools/symbolsfindfilter.cpp b/src/plugins/cpptools/symbolsfindfilter.cpp index 104cac2ba87..9286a61138d 100644 --- a/src/plugins/cpptools/symbolsfindfilter.cpp +++ b/src/plugins/cpptools/symbolsfindfilter.cpp @@ -100,11 +100,6 @@ void SymbolsFindFilter::setPaused(bool paused) watcher->setPaused(paused); } -FindFlags SymbolsFindFilter::supportedFindFlags() const -{ - return FindCaseSensitively | FindRegularExpression | FindWholeWords; -} - void SymbolsFindFilter::findAll(const QString &txt, FindFlags findFlags) { SearchResultWindow *window = SearchResultWindow::instance(); diff --git a/src/plugins/cpptools/symbolsfindfilter.h b/src/plugins/cpptools/symbolsfindfilter.h index 827bef9f7a2..b4e72b2a320 100644 --- a/src/plugins/cpptools/symbolsfindfilter.h +++ b/src/plugins/cpptools/symbolsfindfilter.h @@ -56,7 +56,6 @@ public: QString id() const; QString displayName() const; bool isEnabled() const; - Core::FindFlags supportedFindFlags() const; void findAll(const QString &txt, Core::FindFlags findFlags); diff --git a/src/plugins/debugger/analyzer/analyzermanager.h b/src/plugins/debugger/analyzer/analyzermanager.h index 9a3dedd9d99..5907c819aa5 100644 --- a/src/plugins/debugger/analyzer/analyzermanager.h +++ b/src/plugins/debugger/analyzer/analyzermanager.h @@ -30,11 +30,7 @@ #include "../debuggermainwindow.h" -#include - -#include -#include -#include +#include #include diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 16622638f37..72b69ab41b1 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -3416,19 +3416,10 @@ static bool buildTypeAccepted(QFlags toolMode, BuildConfiguration::Bui return false; } -RunConfiguration *startupRunConfiguration() -{ - if (Project *pro = SessionManager::startupProject()) { - if (const Target *target = pro->activeTarget()) - return target->activeRunConfiguration(); - } - return nullptr; -} - static BuildConfiguration::BuildType startupBuildType() { BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown; - if (RunConfiguration *runConfig = startupRunConfiguration()) { + if (RunConfiguration *runConfig = RunConfiguration::startupRunConfiguration()) { if (const BuildConfiguration *buildConfig = runConfig->target()->activeBuildConfiguration()) buildType = buildConfig->buildType(); } diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index af7121ef246..8408be9a895 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -33,6 +33,7 @@ #include "environmentaspect.h" #include "kitinformation.h" #include "runnables.h" +#include "session.h" #include @@ -243,6 +244,20 @@ void RunConfiguration::ctor() [this] { return displayName(); }, false); } +/*! + * Returns the RunConfiguration of the currently active target + * of the startup project, if such exists, or \c nullptr otherwise. + */ + +RunConfiguration *RunConfiguration::startupRunConfiguration() +{ + if (Project *pro = SessionManager::startupProject()) { + if (const Target *target = pro->activeTarget()) + return target->activeRunConfiguration(); + } + return nullptr; +} + /*! Checks whether a run configuration is enabled. */ diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index ab3ce3b58a0..08d6161ed9f 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -281,6 +281,8 @@ public: void addExtraAspect(IRunConfigurationAspect *aspect); + static RunConfiguration *startupRunConfiguration(); + signals: void enabledChanged(); void requestRunActionsUpdate(); diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index b661fab197f..8a655b955c6 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -587,8 +587,8 @@ void QmlProfilerTool::attachToWaitingApplication() Debugger::selectPerspective(Constants::QmlProfilerPerspectiveId); - RunConfiguration *rc = Debugger::startupRunConfiguration(); - auto runControl = new RunControl(rc, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE); + auto runConfig = RunConfiguration::startupRunConfiguration(); + auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE); auto profiler = new QmlProfilerRunner(runControl); profiler->setServerUrl(serverUrl); diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro index b50f4b27fb4..bcfad2f36e1 100644 --- a/src/plugins/qnx/qnx.pro +++ b/src/plugins/qnx/qnx.pro @@ -8,7 +8,6 @@ SOURCES += qnxplugin.cpp \ qnxdevicefactory.cpp \ qnxdevicewizard.cpp \ qnxrunconfiguration.cpp \ - qnxruncontrolfactory.cpp \ qnxanalyzesupport.cpp \ qnxdebugsupport.cpp \ qnxdeploystepfactory.cpp \ @@ -41,7 +40,6 @@ HEADERS += qnxplugin.h\ qnxdevicefactory.h \ qnxdevicewizard.h \ qnxrunconfiguration.h \ - qnxruncontrolfactory.h \ qnxanalyzesupport.h \ qnxdebugsupport.h \ qnxdeploystepfactory.h \ diff --git a/src/plugins/qnx/qnx.qbs b/src/plugins/qnx/qnx.qbs index eee52f0f5d1..b617fc1b6a9 100644 --- a/src/plugins/qnx/qnx.qbs +++ b/src/plugins/qnx/qnx.qbs @@ -76,8 +76,6 @@ QtcPlugin { "qnxrunconfiguration.h", "qnxrunconfigurationfactory.cpp", "qnxrunconfigurationfactory.h", - "qnxruncontrolfactory.cpp", - "qnxruncontrolfactory.h", "qnxutils.cpp", "qnxutils.h", "qnx_export.h", diff --git a/src/plugins/qnx/qnxanalyzesupport.cpp b/src/plugins/qnx/qnxanalyzesupport.cpp index 52150107906..c4a0d71d940 100644 --- a/src/plugins/qnx/qnxanalyzesupport.cpp +++ b/src/plugins/qnx/qnxanalyzesupport.cpp @@ -75,9 +75,11 @@ private: // QnxDebugSupport -QnxAnalyzeSupport::QnxAnalyzeSupport(RunControl *runControl) +QnxQmlProfilerSupport::QnxQmlProfilerSupport(RunControl *runControl) : RunWorker(runControl) { + runControl->createWorker(runControl->runMode()); + setDisplayName("QnxAnalyzeSupport"); appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat); @@ -99,7 +101,7 @@ QnxAnalyzeSupport::QnxAnalyzeSupport(RunControl *runControl) // m_outputParser.processOutput(msg); } -void QnxAnalyzeSupport::start() +void QnxQmlProfilerSupport::start() { // runControl()->notifyRemoteSetupDone(m_qmlPort); reportStarted(); diff --git a/src/plugins/qnx/qnxanalyzesupport.h b/src/plugins/qnx/qnxanalyzesupport.h index cb049866f8e..9fbd11d0fe7 100644 --- a/src/plugins/qnx/qnxanalyzesupport.h +++ b/src/plugins/qnx/qnxanalyzesupport.h @@ -30,14 +30,12 @@ namespace Qnx { namespace Internal { -class Slog2InfoRunner; - -class QnxAnalyzeSupport : public ProjectExplorer::RunWorker +class QnxQmlProfilerSupport : public ProjectExplorer::RunWorker { Q_OBJECT public: - explicit QnxAnalyzeSupport(ProjectExplorer::RunControl *runControl); + explicit QnxQmlProfilerSupport(ProjectExplorer::RunControl *runControl); private: void start() override; diff --git a/src/plugins/qnx/qnxplugin.cpp b/src/plugins/qnx/qnxplugin.cpp index 2826b24cee7..a1f1cffc9c1 100644 --- a/src/plugins/qnx/qnxplugin.cpp +++ b/src/plugins/qnx/qnxplugin.cpp @@ -25,38 +25,49 @@ #include "qnxplugin.h" -#include "qnxconstants.h" +#include "qnxanalyzesupport.h" #include "qnxattachdebugsupport.h" -#include "qnxdevicefactory.h" -#include "qnxruncontrolfactory.h" -#include "qnxdeploystepfactory.h" -#include "qnxdeployconfigurationfactory.h" -#include "qnxrunconfigurationfactory.h" -#include "qnxqtversionfactory.h" -#include "qnxsettingspage.h" #include "qnxconfigurationmanager.h" +#include "qnxconstants.h" +#include "qnxdebugsupport.h" +#include "qnxdeployconfigurationfactory.h" +#include "qnxdeploystepfactory.h" +#include "qnxdevice.h" +#include "qnxdevicefactory.h" +#include "qnxqtversion.h" +#include "qnxqtversionfactory.h" +#include "qnxrunconfiguration.h" +#include "qnxrunconfigurationfactory.h" +#include "qnxsettingspage.h" #include "qnxtoolchain.h" -#include "qnxattachdebugsupport.h" +#include "qnxutils.h" #include #include #include #include #include + #include #include #include #include #include +#include +#include +#include +#include +#include + +#include #include #include using namespace ProjectExplorer; -using namespace Qnx::Internal; -QnxPlugin::QnxPlugin() : m_debugSeparator(0) , m_attachToQnxApplication(0) -{ } +namespace Qnx { +namespace Internal { bool QnxPlugin::initialize(const QStringList &arguments, QString *errorString) { @@ -67,13 +78,29 @@ bool QnxPlugin::initialize(const QStringList &arguments, QString *errorString) addAutoReleasedObject(new QnxConfigurationManager); addAutoReleasedObject(new QnxQtVersionFactory); addAutoReleasedObject(new QnxDeviceFactory); - addAutoReleasedObject(new QnxRunControlFactory); addAutoReleasedObject(new QnxDeployStepFactory); addAutoReleasedObject(new QnxDeployConfigurationFactory); addAutoReleasedObject(new QnxRunConfigurationFactory); addAutoReleasedObject(new QnxSettingsPage); - // Handle Qcc Compiler + auto constraint = [](RunConfiguration *runConfig) { + if (!runConfig->isEnabled() + || !runConfig->id().name().startsWith(Constants::QNX_QNX_RUNCONFIGURATION_PREFIX)) { + return false; + } + + auto dev = DeviceKitInformation::device(runConfig->target()->kit()) + .dynamicCast(); + return !dev.isNull(); + }; + + RunControl::registerWorker + (ProjectExplorer::Constants::NORMAL_RUN_MODE, constraint); + RunControl::registerWorker + (ProjectExplorer::Constants::DEBUG_RUN_MODE, constraint); + RunControl::registerWorker + (ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, constraint); + addAutoReleasedObject(new QnxToolChainFactory); return true; @@ -118,3 +145,6 @@ void QnxPlugin::updateDebuggerActions() m_attachToQnxApplication->setVisible(false && hasValidQnxKit); // FIXME m_debugSeparator->setVisible(false && hasValidQnxKit); // FIXME QTCREATORBUG-16608 } + +} // Internal +} // Qnx diff --git a/src/plugins/qnx/qnxplugin.h b/src/plugins/qnx/qnxplugin.h index 1fd1367cb8d..798251810c0 100644 --- a/src/plugins/qnx/qnxplugin.h +++ b/src/plugins/qnx/qnxplugin.h @@ -40,18 +40,17 @@ class QnxPlugin : public ExtensionSystem::IPlugin Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Qnx.json") public: - QnxPlugin(); + QnxPlugin() {} bool initialize(const QStringList &arguments, QString *errorString); void extensionsInitialized(); ShutdownFlag aboutToShutdown(); -private slots: +private: void updateDebuggerActions(); -private: - QAction *m_debugSeparator; - QAction *m_attachToQnxApplication; + QAction *m_debugSeparator = nullptr; + QAction *m_attachToQnxApplication = nullptr; }; } // namespace Internal diff --git a/src/plugins/qnx/qnxruncontrolfactory.cpp b/src/plugins/qnx/qnxruncontrolfactory.cpp deleted file mode 100644 index 18a44abd0b0..00000000000 --- a/src/plugins/qnx/qnxruncontrolfactory.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 BlackBerry Limited. All rights reserved. -** Contact: KDAB (info@kdab.com) -** -** 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 "qnxruncontrolfactory.h" -#include "qnxconstants.h" -#include "qnxrunconfiguration.h" -#include "qnxdebugsupport.h" -#include "qnxdevice.h" -#include "qnxanalyzesupport.h" -#include "qnxqtversion.h" -#include "slog2inforunner.h" -#include "qnxutils.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Debugger; -using namespace ProjectExplorer; - -namespace Qnx { -namespace Internal { - -QnxRunControlFactory::QnxRunControlFactory(QObject *parent) - : IRunControlFactory(parent) -{ -} - -bool QnxRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id mode) const -{ - if (mode != ProjectExplorer::Constants::NORMAL_RUN_MODE - && mode != ProjectExplorer::Constants::DEBUG_RUN_MODE - && mode != ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { - return false; - } - - if (!runConfiguration->isEnabled() - || !runConfiguration->id().name().startsWith(Constants::QNX_QNX_RUNCONFIGURATION_PREFIX)) { - return false; - } - - const QnxDevice::ConstPtr dev = DeviceKitInformation::device(runConfiguration->target()->kit()) - .dynamicCast(); - if (dev.isNull()) - return false; - - return true; -} - -RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, Core::Id mode, QString *) -{ - QTC_ASSERT(canRun(runConfig, mode), return 0); - - if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) { - auto runControl = new RunControl(runConfig, mode); - (void) new SimpleTargetRunner(runControl); - return runControl; - } - - if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE) { - auto runControl = new RunControl(runConfig, mode); - (void) new QnxDebugSupport(runControl); - return runControl; - } - - if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { - RunControl *runControl = new RunControl(runConfig, mode); - runControl->createWorker(mode); - (void) new QnxAnalyzeSupport(runControl); - return runControl; - } - - QTC_CHECK(false); - return 0; -} - -} // namespace Internal -} // namespace Qnx diff --git a/src/plugins/texteditor/convenience.h b/src/plugins/texteditor/convenience.h index e4f5f0480bc..f4302cd5f31 100644 --- a/src/plugins/texteditor/convenience.h +++ b/src/plugins/texteditor/convenience.h @@ -37,6 +37,7 @@ QT_END_NAMESPACE namespace TextEditor { namespace Convenience { +// line is 1-based, column is 0-based TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document, int pos, int *line, int *column); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 8d60e286f73..d08d79e14a7 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -6316,7 +6316,8 @@ void TextEditorWidgetPrivate::autocompleterHighlight(const QTextCursor &cursor) m_autoCompleteHighlightPos.clear(); } else if (m_highlightAutoComplete) { m_autoCompleteHighlightPos.push_back(cursor); - } else if (m_animateAutoComplete) { + } + if (m_animateAutoComplete) { const QTextCharFormat &matchFormat = q->textDocument()->fontSettings().toTextCharFormat(C_AUTOCOMPLETE); cancelCurrentAnimations();// one animation is enough diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index 689a986d8c8..b5fa8b6a030 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -272,7 +272,7 @@ CallgrindTool::CallgrindTool() menu->addAction(ActionManager::registerAction(action, CallgrindRemoteActionId), Debugger::Constants::G_ANALYZER_REMOTE_TOOLS); QObject::connect(action, &QAction::triggered, this, [this, action] { - RunConfiguration *runConfig = startupRunConfiguration(); + auto runConfig = RunConfiguration::startupRunConfiguration(); if (!runConfig) { showCannotStartDialog(action->text()); return; diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index 9b5223c895e..a69e2eac606 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -435,7 +435,7 @@ MemcheckTool::MemcheckTool() menu->addAction(ActionManager::registerAction(action, "Memcheck.Remote"), Debugger::Constants::G_ANALYZER_REMOTE_TOOLS); QObject::connect(action, &QAction::triggered, this, [this, action] { - RunConfiguration *runConfig = startupRunConfiguration(); + auto runConfig = RunConfiguration::startupRunConfiguration(); if (!runConfig) { showCannotStartDialog(action->text()); return; diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri index 2bb0d0ab7b2..926280a5fa8 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri +++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri @@ -19,7 +19,6 @@ HEADERS += \ $$PWD/environment.h \ $$PWD/clangpathwatcher.h \ $$PWD/projectparts.h \ - $$PWD/stringcache.h \ $$PWD/idpaths.h \ $$PWD/pchcreatorinterface.h \ $$PWD/clangpathwatcherinterface.h \ diff --git a/src/tools/clangrefactoringbackend/source/clangquery.cpp b/src/tools/clangrefactoringbackend/source/clangquery.cpp index d24b981f458..be93b61a1a6 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquery.cpp @@ -30,27 +30,15 @@ #include -#include +#include -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif +#include #include #include #include #include -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - using clang::ast_matchers::dynamic::Diagnostics; using clang::ast_matchers::dynamic::Parser; using clang::ast_matchers::BoundNodes; @@ -66,8 +54,10 @@ struct CollectBoundNodes : MatchFinder::MatchCallback { } }; -ClangQuery::ClangQuery(Utils::SmallString &&query) - : query(std::move(query)) +ClangQuery::ClangQuery(StringCache &filePathCache, + Utils::SmallString &&query) + : query(std::move(query)), + filePathCache(filePathCache) { } @@ -226,6 +216,7 @@ void ClangQuery::matchLocation( SourceRangeExtractor extractor(ast->getSourceManager(), ast->getLangOpts(), + filePathCache, sourceRangesContainer); extractor.addSourceRanges(sourceRanges); diff --git a/src/tools/clangrefactoringbackend/source/clangquery.h b/src/tools/clangrefactoringbackend/source/clangquery.h index 93190449a5d..20b38a7ab10 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.h +++ b/src/tools/clangrefactoringbackend/source/clangquery.h @@ -30,6 +30,8 @@ #include #include +#include + namespace clang { namespace ast_matchers { namespace dynamic { @@ -49,7 +51,7 @@ namespace ClangBackEnd { class ClangQuery : public ClangTool { public: - ClangQuery(Utils::SmallString &&query={}); + ClangQuery(StringCache &filePathCache, Utils::SmallString &&query={}); void setQuery(Utils::SmallString &&query); @@ -67,6 +69,7 @@ private: SourceRangesContainer sourceRangesContainer; Utils::SmallString query; std::vector diagnosticContainers_; + StringCache &filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp index cbf9a9c70c2..219011eff2a 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp @@ -29,10 +29,13 @@ namespace ClangBackEnd { -ClangQueryGatherer::ClangQueryGatherer(std::vector &&sources, +ClangQueryGatherer::ClangQueryGatherer(StringCache *filePathCache, + std::vector &&sources, std::vector &&unsaved, Utils::SmallString &&query) - : m_sources(std::move(sources)), + : m_filePathCache(filePathCache), + m_sourceRangeFilter(sources.size()), + m_sources(std::move(sources)), m_unsaved(std::move(unsaved)), m_query(std::move(query)) { @@ -40,11 +43,12 @@ ClangQueryGatherer::ClangQueryGatherer(std::vector &&sources, SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createSourceRangesAndDiagnosticsForSource( + StringCache *filePathCache, V2::FileContainer &&source, const std::vector &unsaved, Utils::SmallString &&query) { - ClangQuery clangQuery(std::move(query)); + ClangQuery clangQuery(*filePathCache, std::move(query)); clangQuery.addFile(source.filePath().directory(), source.filePath().name(), @@ -65,7 +69,8 @@ bool ClangQueryGatherer::canCreateSourceRangesAndDiagnostics() const SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createNextSourceRangesAndDiagnostics() { - auto message = createSourceRangesAndDiagnosticsForSource(std::move(m_sources.back()), + auto message = createSourceRangesAndDiagnosticsForSource(m_filePathCache, + std::move(m_sources.back()), m_unsaved, m_query.clone()); m_sources.pop_back(); @@ -77,6 +82,7 @@ ClangQueryGatherer::Future ClangQueryGatherer::startCreateNextSourceRangesAndDia { Future future = std::async(std::launch::async, createSourceRangesAndDiagnosticsForSource, + m_filePathCache, std::move(m_sources.back()), m_unsaved, m_query.clone()); @@ -120,7 +126,7 @@ std::vector ClangQueryGatherer::allCu std::vector messages; for (Future &future : m_sourceFutures) - messages.push_back(future.get()); + messages.push_back(m_sourceRangeFilter.removeDuplicates(future.get())); return messages; } @@ -130,7 +136,7 @@ std::vector ClangQueryGatherer::finis std::vector messages; for (auto &&future : finishedFutures()) - messages.push_back(future.get()); + messages.push_back(m_sourceRangeFilter.removeDuplicates(future.get())); return messages; } diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h index a7ba8fac790..67e662bd86c 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h @@ -25,8 +25,11 @@ #pragma once +#include "sourcerangefilter.h" + #include #include +#include #include @@ -38,16 +41,16 @@ public: using Future = std::future; ClangQueryGatherer() = default; - ClangQueryGatherer(std::vector &&sources, + ClangQueryGatherer(StringCache *filePathCache, + std::vector &&sources, std::vector &&unsaved, Utils::SmallString &&query); - static - SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource( + static SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource( + StringCache *filePathCache, V2::FileContainer &&source, const std::vector &unsaved, Utils::SmallString &&query); - bool canCreateSourceRangesAndDiagnostics() const; SourceRangesAndDiagnosticsForQueryMessage createNextSourceRangesAndDiagnostics(); Future startCreateNextSourceRangesAndDiagnosticsMessage(); @@ -66,6 +69,8 @@ protected: std::vector finishedFutures(); private: + StringCache *m_filePathCache = nullptr; + SourceRangeFilter m_sourceRangeFilter; std::vector m_sources; std::vector m_unsaved; Utils::SmallString m_query; diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index 7a695e5ca4d..8af6b89974c 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -1,7 +1,8 @@ INCLUDEPATH += $$PWD HEADERS += \ - $$PWD/clangrefactoringbackend_global.h + $$PWD/clangrefactoringbackend_global.h \ + $$PWD/sourcerangefilter.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ @@ -33,3 +34,6 @@ HEADERS += \ $$PWD/locationsourcefilecallbacks.h \ $$PWD/clangquerygatherer.h } + +SOURCES += \ + $$PWD/sourcerangefilter.cpp diff --git a/src/tools/clangrefactoringbackend/source/clangtool.cpp b/src/tools/clangrefactoringbackend/source/clangtool.cpp index dd4b6c57a3f..2ffad739655 100644 --- a/src/tools/clangrefactoringbackend/source/clangtool.cpp +++ b/src/tools/clangrefactoringbackend/source/clangtool.cpp @@ -84,23 +84,12 @@ template void ClangTool::addFiles(const Utils::PathStringVector &filePaths, const Utils::SmallStringVector &arguments); -namespace { -Utils::SmallString toNativeFilePath(const FilePath &filePath) -{ - Utils::SmallString filePathString = filePath.directory().clone(); - filePathString.append("/"); - filePathString.append(filePath.name()); - - return toNativePath(std::move(filePathString)); -} -} - void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles) { unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size()); auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) { - return UnsavedFileContent{toNativeFilePath(unsavedFile.filePath()), + return UnsavedFileContent{toNativePath(unsavedFile.filePath().path().clone()), unsavedFile.unsavedFileContent().clone()}; }; @@ -111,7 +100,8 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles) } namespace { -llvm::StringRef toStringRef(const Utils::SmallString &string) +template +llvm::StringRef toStringRef(const String &string) { return llvm::StringRef(string.data(), string.size()); } diff --git a/src/tools/clangrefactoringbackend/source/clangtool.h b/src/tools/clangrefactoringbackend/source/clangtool.h index c7ee2a83e02..c6439209143 100644 --- a/src/tools/clangrefactoringbackend/source/clangtool.h +++ b/src/tools/clangrefactoringbackend/source/clangtool.h @@ -77,13 +77,13 @@ struct FileContent struct UnsavedFileContent { - UnsavedFileContent(Utils::SmallString &&filePath, + UnsavedFileContent(Utils::PathString &&filePath, Utils::SmallString &&content) : filePath(std::move(filePath)), content(std::move(content)) {} - Utils::SmallString filePath; + Utils::PathString filePath; Utils::SmallString content; }; diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp index 58e944784df..80fdbe86e3e 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp @@ -37,6 +37,7 @@ #include #include +#include namespace ClangBackEnd { @@ -114,6 +115,11 @@ bool RefactoringServer::pollTimerIsActive() const return m_pollTimer.isActive(); } +void RefactoringServer::setGathererProcessingSlotCount(uint count) +{ + m_gatherer.setProcessingSlotCount(count); +} + void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessages( std::vector &&sources, std::vector &&unsaved, @@ -125,7 +131,7 @@ void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessages( uint freeProcessors = std::thread::hardware_concurrency(); #endif - m_gatherer = ClangQueryGatherer(std::move(sources), std::move(unsaved), std::move(query)); + m_gatherer = ClangQueryGatherer(&m_filePathCache, std::move(sources), std::move(unsaved), std::move(query)); m_gatherer.setProcessingSlotCount(freeProcessors); m_pollTimer.start(); diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h index e3b40d3c56f..8926ce7c017 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.h +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h @@ -30,7 +30,12 @@ #include #include +#include +#include + +#include +#include #include namespace ClangBackEnd { @@ -59,12 +64,15 @@ public: bool pollTimerIsActive() const; + void setGathererProcessingSlotCount(uint count); + private: void gatherSourceRangesAndDiagnosticsForQueryMessages(std::vector &&sources, std::vector &&unsaved, Utils::SmallString &&query); private: + StringCache m_filePathCache; ClangQueryGatherer m_gatherer; QTimer m_pollTimer; }; diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h index 78076f5f2bd..df07b42daa1 100644 --- a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h +++ b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h @@ -53,7 +53,7 @@ namespace ClangBackEnd { inline -llvm::SmallString<256> absolutePath(const llvm::StringRef &path) +llvm::SmallString<256> absolutePath(clang::StringRef path) { llvm::SmallString<256> absolutePath(path); @@ -64,9 +64,9 @@ llvm::SmallString<256> absolutePath(const llvm::StringRef &path) } template -Utils::SmallString fromNativePath(Container container) +Utils::PathString fromNativePath(Container container) { - Utils::SmallString path(container.data(), container.size()); + Utils::PathString path(container.data(), container.size()); #ifdef _WIN32 std::replace(path.begin(), path.end(), '\\', '/'); @@ -89,13 +89,9 @@ void appendSourceLocationsToSourceLocationsContainer( const auto fileId = decomposedLoction.first; const auto offset = decomposedLoction.second; const auto fileEntry = sourceManager.getFileEntryForID(fileId); - auto filePath = absolutePath(fileEntry->getName()); - const auto fileName = llvm::sys::path::filename(filePath); - llvm::sys::path::remove_filename(filePath); sourceLocationsContainer.insertFilePath(fileId.getHashValue(), - fromNativePath(filePath), - fromNativePath(fileName)); + fromNativePath(fileEntry->tryGetRealPathName())); sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(), fullSourceLocation.getSpellingLineNumber(), fullSourceLocation.getSpellingColumnNumber(), diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp index 18b6288cae5..e83f6a3c383 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp @@ -51,11 +51,14 @@ namespace ClangBackEnd { -SourceRangeExtractor::SourceRangeExtractor(const clang::SourceManager &sourceManager, - const clang::LangOptions &languageOptions, - SourceRangesContainer &sourceRangesContainer) +SourceRangeExtractor::SourceRangeExtractor( + const clang::SourceManager &sourceManager, + const clang::LangOptions &languageOptions, + ClangBackEnd::StringCache &filePathCache, + SourceRangesContainer &sourceRangesContainer) : sourceManager(sourceManager), languageOptions(languageOptions), + filePathCache(filePathCache), sourceRangesContainer(sourceRangesContainer) { } @@ -123,19 +126,16 @@ const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(c return {sourceRange.getBegin(), endLocation}; } -void SourceRangeExtractor::insertSourceRange(uint fileHash, - Utils::SmallString &&directoryPath, - Utils::SmallString &&fileName, +void SourceRangeExtractor::insertSourceRange(uint fileId, + Utils::PathString &&filePath, const clang::FullSourceLoc &startLocation, uint startOffset, const clang::FullSourceLoc &endLocation, uint endOffset, Utils::SmallString &&lineSnippet) { - sourceRangesContainer.insertFilePath(fileHash, - std::move(directoryPath), - std::move(fileName)); - sourceRangesContainer.insertSourceRange(fileHash, + sourceRangesContainer.insertFilePath(fileId, std::move(filePath)); + sourceRangesContainer.insertSourceRange(fileId, startLocation.getSpellingLineNumber(), startLocation.getSpellingColumnNumber(), startOffset, @@ -145,6 +145,17 @@ void SourceRangeExtractor::insertSourceRange(uint fileHash, std::move(lineSnippet)); } +uint SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const +{ + auto found = m_fileIdMapping.find(fileId.getHashValue()); + if (found != m_fileIdMapping.end()) { + return found->second; + } + + auto filePath = absolutePath(fileEntry->tryGetRealPathName()); + return filePathCache.stringId(fromNativePath(filePath)); +} + void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange) { auto extendedSourceRange = extendSourceRangeToLastTokenEnd(sourceRange); @@ -158,15 +169,13 @@ void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange) const auto startOffset = startDecomposedLoction.second; const auto endOffset = endDecomposedLoction.second; const auto fileEntry = sourceManager.getFileEntryForID(fileId); - auto filePath = absolutePath(fileEntry->getName()); - const auto fileName = llvm::sys::path::filename(filePath); - llvm::sys::path::remove_filename(filePath); + Utils::SmallString lineSnippet = getExpandedText(startSourceLocation.getBufferData(), startOffset, endOffset); - insertSourceRange(fileId.getHashValue(), - fromNativePath(filePath), - {fileName.data(), fileName.size()}, + + insertSourceRange(findFileId(fileId, fileEntry), + fromNativePath(fileEntry->tryGetRealPathName()), startSourceLocation, startOffset, endSourceLocation, diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h index 5bd6cf75ab7..7a07e5c3f87 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h @@ -25,9 +25,14 @@ #pragma once +#include + +#include + #include #include +#include using uint = unsigned int; @@ -40,6 +45,8 @@ class SourceManager; class LangOptions; class SourceRange; class FullSourceLoc; +class FileID; +class FileEntry; } namespace ClangBackEnd { @@ -52,6 +59,7 @@ class SourceRangeExtractor public: SourceRangeExtractor(const clang::SourceManager &sourceManager, const clang::LangOptions &languageOptions, + ClangBackEnd::StringCache &filePathCache, SourceRangesContainer &sourceRangesContainer); void addSourceRange(const clang::SourceRange &sourceRange); @@ -66,18 +74,21 @@ public: const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange); private: - void insertSourceRange(uint fileHash, - Utils::SmallString &&directoryPath, - Utils::SmallString &&fileName, + void insertSourceRange(uint fileId, + Utils::PathString &&filePath, const clang::FullSourceLoc &startLocation, uint startOffset, const clang::FullSourceLoc &endLocation, uint endOffset, Utils::SmallString &&lineSnippet); + uint findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; + private: + mutable std::unordered_map m_fileIdMapping; const clang::SourceManager &sourceManager; const clang::LangOptions &languageOptions; + ClangBackEnd::StringCache &filePathCache; SourceRangesContainer &sourceRangesContainer; }; diff --git a/src/tools/clangrefactoringbackend/source/sourcerangefilter.cpp b/src/tools/clangrefactoringbackend/source/sourcerangefilter.cpp new file mode 100644 index 00000000000..bc566ea7d40 --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/sourcerangefilter.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "sourcerangefilter.h" + +#include + +namespace ClangBackEnd { + +SourceRangeFilter::SourceRangeFilter(std::size_t sourcesCount) +{ + m_collectedSourceRanges.reserve(sourcesCount); +} + +SourceRangesAndDiagnosticsForQueryMessage SourceRangeFilter::removeDuplicates(SourceRangesAndDiagnosticsForQueryMessage &&message) +{ + removeDuplicates(message.sourceRanges().sourceRangeWithTextContainers()); + + return std::move(message); +} + +void SourceRangeFilter::removeDuplicates(SourceRangeWithTextContainers &sourceRanges) +{ + auto partitionPoint = std::stable_partition(sourceRanges.begin(), + sourceRanges.end(), + [&] (const SourceRangeWithTextContainer &sourceRange) { + return m_collectedSourceRanges.find(sourceRange) == m_collectedSourceRanges.end(); + }); + + sourceRanges.erase(partitionPoint, sourceRanges.end()); + + std::copy(sourceRanges.begin(), + sourceRanges.end(), + std::inserter(m_collectedSourceRanges, m_collectedSourceRanges.end())); +} + +} // namespace ClangBackEnd diff --git a/src/plugins/qnx/qnxruncontrolfactory.h b/src/tools/clangrefactoringbackend/source/sourcerangefilter.h similarity index 63% rename from src/plugins/qnx/qnxruncontrolfactory.h rename to src/tools/clangrefactoringbackend/source/sourcerangefilter.h index af19a7f3dd6..8c6c3ac42f8 100644 --- a/src/plugins/qnx/qnxruncontrolfactory.h +++ b/src/tools/clangrefactoringbackend/source/sourcerangefilter.h @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 BlackBerry Limited. All rights reserved. -** Contact: KDAB (info@kdab.com) +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** @@ -25,23 +25,23 @@ #pragma once -#include +#include -namespace Qnx { -namespace Internal { +#include -class QnxRunControlFactory : public ProjectExplorer::IRunControlFactory +namespace ClangBackEnd { + +class SourceRangeFilter { - Q_OBJECT - public: - explicit QnxRunControlFactory(QObject *parent = 0); + SourceRangeFilter(std::size_t sourcesCount = 0); - bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, - Core::Id mode) const override; - ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, - Core::Id mode, QString *errorMessage) override; + SourceRangesAndDiagnosticsForQueryMessage + removeDuplicates(SourceRangesAndDiagnosticsForQueryMessage &&message); + void removeDuplicates(SourceRangeWithTextContainers &sourceRanges); + +private: + std::unordered_set m_collectedSourceRanges; }; -} // namespace Internal -} // namespace Qnx +} // namespace ClangBackEnd diff --git a/tests/unit/unittest/clangquery-test.cpp b/tests/unit/unittest/clangquery-test.cpp index b71e267697d..39f82e09555 100644 --- a/tests/unit/unittest/clangquery-test.cpp +++ b/tests/unit/unittest/clangquery-test.cpp @@ -29,7 +29,10 @@ #include +#include + using ClangBackEnd::ClangQuery; +using ClangBackEnd::StringCache; using testing::IsEmpty; using testing::Not; @@ -43,8 +46,9 @@ protected: void SetUp() override; protected: - ::ClangQuery simpleFunctionQuery; - ::ClangQuery simpleClassQuery; + StringCache filePathCache; + ::ClangQuery simpleFunctionQuery{filePathCache}; + ::ClangQuery simpleClassQuery{filePathCache}; }; using ClangQuerySlowTest = ClangQuery; @@ -77,7 +81,7 @@ TEST_F(ClangQuerySlowTest, RootSourceRangeForSimpleFunctionDeclarationRange) TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) { - ::ClangQuery query; + ::ClangQuery query(filePathCache); query.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "#include \"unsaved.h\"", {"cc", "query_simplefunction.cpp", "-std=c++14"}); query.setQuery("functionDecl()"); ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, "void unsaved();", {}}; @@ -91,7 +95,7 @@ TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) TEST_F(ClangQuerySlowTest, DISABLED_SourceRangeInUnsavedFileDeclarationRangeOverride) // seems not to work in Clang { - ::ClangQuery query; + ::ClangQuery query(filePathCache); query.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "void f() {}", {"cc", "query_simplefunction.cpp", "-std=c++14"}); query.setQuery("functionDecl()"); ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void unsaved();", {}}; diff --git a/tests/unit/unittest/clangquerygatherer-test.cpp b/tests/unit/unittest/clangquerygatherer-test.cpp index 089f273f062..d1ff0a508e3 100644 --- a/tests/unit/unittest/clangquerygatherer-test.cpp +++ b/tests/unit/unittest/clangquerygatherer-test.cpp @@ -25,6 +25,8 @@ #include "googletest.h" +#include "filesystem-utilities.h" + #include "sourcerangecontainer-matcher.h" #include @@ -38,6 +40,7 @@ using testing::AtLeast; using testing::AtMost; using testing::Contains; using testing::Each; +using testing::ElementsAre; using testing::Eq; using testing::Ge; using testing::IsEmpty; @@ -47,6 +50,7 @@ using testing::Pair; using testing::PrintToString; using testing::Property; using testing::SizeIs; +using testing::UnorderedElementsAre; using testing::_; using ClangBackEnd::V2::FileContainer; @@ -71,34 +75,42 @@ protected: void SetUp() override; protected: - Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f()\n {}"}; + ClangBackEnd::StringCache filePathCache; + Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), - {"cc", "query_simplefunction.cpp"}}; + {"cc", toNativePath(TESTDATA_DIR"/query_simplefunction.cpp"), "-I", TESTDATA_DIR}}; + FileContainer source2{{TESTDATA_DIR, "query_simplefunction2.cpp"}, + {}, + {"cc", toNativePath(TESTDATA_DIR"/query_simplefunction2.cpp"), "-I", TESTDATA_DIR}}; + FileContainer source3{{TESTDATA_DIR, "query_simplefunction3.cpp"}, + {}, + {"cc", toNativePath(TESTDATA_DIR"/query_simplefunction3.cpp"), "-I", TESTDATA_DIR}}; Utils::SmallString unsavedContent{"void f();"}; FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, unsavedContent.clone(), {}}; Utils::SmallString query{"functionDecl()"}; - ClangBackEnd::ClangQueryGatherer gatherer{{source.clone()}, {unsaved.clone()}, query.clone()}; - ClangBackEnd::ClangQueryGatherer manyGatherer{{source.clone(), source.clone(), source.clone()}, + ClangBackEnd::ClangQueryGatherer gatherer{&filePathCache, {source.clone()}, {unsaved.clone()}, query.clone()}; + ClangBackEnd::ClangQueryGatherer manyGatherer{&filePathCache, + {source3.clone(), source2.clone(), source.clone()}, {unsaved.clone()}, query.clone()}; }; TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnostics) { - auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(source.clone(), {}, query.clone()); + auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(&filePathCache, source.clone(), {unsaved}, query.clone()); ASSERT_THAT(sourceRangesAndDiagnostics, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesContainer::sourceRangeWithTextContainers, - Contains(IsSourceRangeWithText(2, 1, 3, 4, "void f()\n {}"))))); + Contains(IsSourceRangeWithText(2, 1, 2, 12, "void f() {}"))))); } TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnosticssWithUnsavedContent) { - auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(source.clone(), {unsaved}, query.clone()); + auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(&filePathCache, source.clone(), {unsaved}, query.clone()); ASSERT_THAT(sourceRangesAndDiagnostics, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, @@ -113,7 +125,7 @@ TEST_F(ClangQueryGatherer, CanCreateSourceRangesAndDiagnosticsIfItHasSources) TEST_F(ClangQueryGatherer, CanNotCreateSourceRangesAndDiagnosticsIfItHasNoSources) { - ClangBackEnd::ClangQueryGatherer empthyGatherer{{}, {unsaved.clone()}, query.clone()}; + ClangBackEnd::ClangQueryGatherer empthyGatherer{&filePathCache, {}, {unsaved.clone()}, query.clone()}; ASSERT_FALSE(empthyGatherer.canCreateSourceRangesAndDiagnostics()); } @@ -174,14 +186,18 @@ TEST_F(ClangQueryGatherer, AfterStartCreateSourceRangesAndDiagnosticsMessagesGet manyGatherer.startCreateNextSourceRangesAndDiagnosticsMessages(); ASSERT_THAT(manyGatherer.allCurrentProcessedMessages(), - Each( + UnorderedElementsAre( Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesContainer::sourceRangeWithTextContainers, - Contains(IsSourceRangeWithText(1, 1, 1, 9, "void f();")))))); + UnorderedElementsAre(IsSourceRangeWithText(1, 1, 1, 9, "void f();"), + IsSourceRangeWithText(2, 1, 2, 12, "void f() {}")))), + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + UnorderedElementsAre( + IsSourceRangeWithText(1, 1, 1, 13, "int header();"), + IsSourceRangeWithText(3, 1, 3, 15, "int function();")))))); } - - TEST_F(ClangQueryGatherer, GetFinishedMessages) { manyGatherer.startCreateNextSourceRangesAndDiagnosticsMessages(); @@ -191,10 +207,17 @@ TEST_F(ClangQueryGatherer, GetFinishedMessages) ASSERT_THAT(messages, AllOf(SizeIs(2), - Each( + UnorderedElementsAre( Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesContainer::sourceRangeWithTextContainers, - Contains(IsSourceRangeWithText(1, 1, 1, 9, "void f();"))))))); + UnorderedElementsAre( + IsSourceRangeWithText(1, 1, 1, 9, "void f();"), + IsSourceRangeWithText(2, 1, 2, 12, "void f() {}")))), + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + UnorderedElementsAre( + IsSourceRangeWithText(1, 1, 1, 13, "int header();"), + IsSourceRangeWithText(3, 1, 3, 15, "int function();"))))))); } TEST_F(ClangQueryGatherer, GetFinishedMessagesAfterSecondPass) @@ -209,10 +232,38 @@ TEST_F(ClangQueryGatherer, GetFinishedMessagesAfterSecondPass) ASSERT_THAT(messages, AllOf(SizeIs(1), - Each( + ElementsAre( Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesContainer::sourceRangeWithTextContainers, - Contains(IsSourceRangeWithText(1, 1, 1, 9, "void f();"))))))); + UnorderedElementsAre( + IsSourceRangeWithText(3, 1, 3, 15, "int function();"))))))); +} + +TEST_F(ClangQueryGatherer, FilterDuplicates) +{ + manyGatherer.setProcessingSlotCount(3); + manyGatherer.startCreateNextSourceRangesAndDiagnosticsMessages(); + manyGatherer.waitForFinished(); + + auto messages = manyGatherer.finishedMessages(); + + ASSERT_THAT(messages, + AllOf(SizeIs(3), + UnorderedElementsAre( + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + UnorderedElementsAre( + IsSourceRangeWithText(1, 1, 1, 9, "void f();"), + IsSourceRangeWithText(2, 1, 2, 12, "void f() {}")))), + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + UnorderedElementsAre( + IsSourceRangeWithText(1, 1, 1, 13, "int header();"), + IsSourceRangeWithText(3, 1, 3, 15, "int function();")))), + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + UnorderedElementsAre( + IsSourceRangeWithText(3, 1, 3, 15, "int function();"))))))); } TEST_F(ClangQueryGatherer, AfterGetFinishedMessagesFuturesAreReduced) diff --git a/tests/unit/unittest/data/query_simplefunction2.cpp b/tests/unit/unittest/data/query_simplefunction2.cpp new file mode 100644 index 00000000000..fbf4d8d8fd0 --- /dev/null +++ b/tests/unit/unittest/data/query_simplefunction2.cpp @@ -0,0 +1,4 @@ +#include "query_simplefunction2.h" + +int function(); + diff --git a/tests/unit/unittest/data/query_simplefunction2.h b/tests/unit/unittest/data/query_simplefunction2.h new file mode 100644 index 00000000000..9251cf100a9 --- /dev/null +++ b/tests/unit/unittest/data/query_simplefunction2.h @@ -0,0 +1,2 @@ +int header(); + diff --git a/tests/unit/unittest/data/query_simplefunction3.cpp b/tests/unit/unittest/data/query_simplefunction3.cpp new file mode 100644 index 00000000000..fbf4d8d8fd0 --- /dev/null +++ b/tests/unit/unittest/data/query_simplefunction3.cpp @@ -0,0 +1,4 @@ +#include "query_simplefunction2.h" + +int function(); + diff --git a/tests/unit/unittest/filepath-test.cpp b/tests/unit/unittest/filepath-test.cpp new file mode 100644 index 00000000000..d82e94f2119 --- /dev/null +++ b/tests/unit/unittest/filepath-test.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include + +namespace { + +TEST(FilePath, CreateFromPathString) +{ + ClangBackEnd::FilePath filePath{Utils::PathString{"/file/pathOne"}}; + + ASSERT_THAT(filePath.directory(), "/file"); + ASSERT_THAT(filePath.name(), "pathOne"); +} + +TEST(FilePath, CreateFromQString) +{ + ClangBackEnd::FilePath filePath{QString{"/file/pathOne"}}; + + ASSERT_THAT(filePath.directory(), "/file"); + ASSERT_THAT(filePath.name(), "pathOne"); +} + +TEST(FilePath, EmptyFilePath) +{ + ClangBackEnd::FilePath filePath; + + ASSERT_THAT(filePath.directory(), ""); + ASSERT_THAT(filePath.name(), ""); +} + +} diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp index 0798e9d63c1..763521da420 100644 --- a/tests/unit/unittest/pchcreator-test.cpp +++ b/tests/unit/unittest/pchcreator-test.cpp @@ -73,7 +73,7 @@ protected: PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; PathString header2Path = TESTDATA_DIR "/includecollector_header2.h"; - SmallString generatedFileName = "includecollector_generated_file.h"; + PathString generatedFileName = "includecollector_generated_file.h"; PathString generatedFilePath = TESTDATA_DIR "/includecollector_generated_file.h"; ProjectPartContainer projectPart1{"project1", {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, diff --git a/tests/unit/unittest/refactoringserver-test.cpp b/tests/unit/unittest/refactoringserver-test.cpp index 33b63534e3f..40ca87031ea 100644 --- a/tests/unit/unittest/refactoringserver-test.cpp +++ b/tests/unit/unittest/refactoringserver-test.cpp @@ -25,6 +25,7 @@ #include "googletest.h" +#include "filesystem-utilities.h" #include "mockrefactoringclient.h" #include "sourcerangecontainer-matcher.h" @@ -40,6 +41,7 @@ namespace { using testing::AllOf; using testing::Contains; using testing::NiceMock; +using testing::Not; using testing::Pair; using testing::PrintToString; using testing::Property; @@ -77,7 +79,8 @@ protected: Utils::SmallString sourceContent{"void f()\n {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), - {"cc", "query_simplefunction.cpp"}}; + {"cc", toNativePath(TESTDATA_DIR"/query_simplefunction.cpp")}}; + int processingSlotCount = 2; }; using RefactoringServerSlowTest = RefactoringServer; @@ -153,8 +156,12 @@ TEST_F(RefactoringServerSlowTest, RequestTwoSourceRangesAndDiagnosticsForQueryMe sourceRangesAndDiagnosticsForQueryMessage( Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesContainer::sourceRangeWithTextContainers, - Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))) - .Times(2); + Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))); + EXPECT_CALL(mockRefactoringClient, + sourceRangesAndDiagnosticsForQueryMessage( + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + Not(Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent))))))); refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); } @@ -163,7 +170,7 @@ TEST_F(RefactoringServerVerySlowTest, RequestManySourceRangesAndDiagnosticsForQu { std::vector sources; std::fill_n(std::back_inserter(sources), - std::thread::hardware_concurrency() + 3, + processingSlotCount + 3, source.clone()); RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", std::move(sources), @@ -173,8 +180,13 @@ TEST_F(RefactoringServerVerySlowTest, RequestManySourceRangesAndDiagnosticsForQu sourceRangesAndDiagnosticsForQueryMessage( Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesContainer::sourceRangeWithTextContainers, - Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))) - .Times(std::thread::hardware_concurrency() + 3); + Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))); + EXPECT_CALL(mockRefactoringClient, + sourceRangesAndDiagnosticsForQueryMessage( + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + Not(Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent))))))) + .Times(processingSlotCount + 2); refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); } @@ -237,6 +249,7 @@ void RefactoringServer::SetUp() void RefactoringServer::TearDown() { + refactoringServer.setGathererProcessingSlotCount(uint(processingSlotCount)); refactoringServer.waitThatSourceRangesAndDiagnosticsForQueryMessagesAreFinished(); } diff --git a/tests/unit/unittest/sourcerangeextractor-test.cpp b/tests/unit/unittest/sourcerangeextractor-test.cpp index df527b4e620..8bf676b7962 100644 --- a/tests/unit/unittest/sourcerangeextractor-test.cpp +++ b/tests/unit/unittest/sourcerangeextractor-test.cpp @@ -28,23 +28,12 @@ #include #include - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif +#include #include #include -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif +#include using testing::Contains; using ::testing::Eq; @@ -65,7 +54,8 @@ protected: TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; ClangBackEnd::SourceRangesContainer sourceRangesContainer; const clang::SourceManager &sourceManager{clangTool.sourceManager()}; - ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), sourceRangesContainer}; + ClangBackEnd::StringCache filePathCache; + ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), filePathCache, sourceRangesContainer}; clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()); clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); clang::SourceRange sourceRange{startLocation, endLocation}; @@ -76,7 +66,7 @@ using SourceRangeExtractorSlowTest = SourceRangeExtractor; TEST_F(SourceRangeExtractorSlowTest, ExtractSourceRangeContainer) { - SourceRangeWithTextContainer sourceRangeContainer{1, 1, 1, 0, 1, 10, 9, Utils::SmallString("int value;")}; + SourceRangeWithTextContainer sourceRangeContainer{0, 1, 1, 0, 1, 10, 9, Utils::SmallString("int value;")}; extractor.addSourceRange(sourceRange); diff --git a/tests/unit/unittest/sourcerangefilter-test.cpp b/tests/unit/unittest/sourcerangefilter-test.cpp new file mode 100644 index 00000000000..059f9827f62 --- /dev/null +++ b/tests/unit/unittest/sourcerangefilter-test.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include + +namespace { + +using testing::ContainerEq; +using testing::IsEmpty; + +using ClangBackEnd::SourceRangeWithTextContainer; +using ClangBackEnd::SourceRangeWithTextContainers; +using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage; + +class SourceRangeFilter : public ::testing::Test +{ +protected: + + +protected: + SourceRangeWithTextContainers sourceRanges1{{1, 1, 1, 1, 2, 1, 4, "foo"}, + {2, 1, 1, 1, 2, 1, 4, "foo"}, + {1, 1, 1, 1, 2, 2, 5, "foo"}}; + SourceRangeWithTextContainers sourceRanges2{{1, 1, 1, 1, 2, 1, 4, "foo"}, + {3, 1, 1, 1, 2, 1, 4, "foo"}, + {1, 1, 1, 1, 2, 2, 6, "foo"}}; + SourceRangeWithTextContainers sourceRanges3{{3, 1, 1, 1, 2, 1, 4, "foo"}, + {1, 1, 1, 1, 2, 2, 6, "foo"}}; + SourceRangesAndDiagnosticsForQueryMessage message1{{{}, Utils::clone(sourceRanges1)}, {}}; + SourceRangesAndDiagnosticsForQueryMessage message2{{{}, Utils::clone(sourceRanges2)}, {}}; + ClangBackEnd::SourceRangeFilter filter{3}; +}; + +TEST_F(SourceRangeFilter, DontChangeForFirstTime) +{ + auto expectedSourceRanges = sourceRanges1; + + filter.removeDuplicates(sourceRanges1); + + ASSERT_THAT(sourceRanges1, ContainerEq(expectedSourceRanges)); +} + +TEST_F(SourceRangeFilter, DoNotFilterNonDuplicates) +{ + SourceRangeWithTextContainers expectedSourceRanges = sourceRanges3; + filter.removeDuplicates(sourceRanges1); + + filter.removeDuplicates(sourceRanges3); + + ASSERT_THAT(sourceRanges3, ContainerEq(expectedSourceRanges)); +} + +TEST_F(SourceRangeFilter, FilterDuplicates) +{ + filter.removeDuplicates(sourceRanges1); + + filter.removeDuplicates(sourceRanges2); + + ASSERT_THAT(sourceRanges2, ContainerEq(sourceRanges3)); +} + +TEST_F(SourceRangeFilter, FilterMoreDuplicates) +{ + filter.removeDuplicates(sourceRanges1); + filter.removeDuplicates(sourceRanges2); + + filter.removeDuplicates(sourceRanges3); + + ASSERT_THAT(sourceRanges3, IsEmpty()); +} + +TEST_F(SourceRangeFilter, FilterDuplicatesFromMessage) +{ + filter.removeDuplicates(std::move(message1)); + + auto filteredMessage = filter.removeDuplicates(std::move(message2)); + + ASSERT_THAT(filteredMessage.sourceRanges().sourceRangeWithTextContainers(), + ContainerEq(sourceRanges3)); +} + +} diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 73e0ed31a3f..ca7f4fdb74a 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -63,6 +63,8 @@ SOURCES += \ projectupdater-test.cpp \ pchmanagerserver-test.cpp \ pchmanagerclientserverinprocess-test.cpp \ + filepath-test.cpp \ + sourcerangefilter-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \