Merge remote-tracking branch 'origin/master' into 4.4

Change-Id: I00fe351ee5f2689366c63ba94b042609c47da777
This commit is contained in:
Eike Ziller
2017-07-04 13:55:35 +02:00
68 changed files with 733 additions and 389 deletions

View File

@@ -155,6 +155,7 @@ HEADERS += \
$$PWD/pchmanagerclientproxy.h \ $$PWD/pchmanagerclientproxy.h \
$$PWD/projectpartpch.h \ $$PWD/projectpartpch.h \
$$PWD/precompiledheadersupdatedmessage.h \ $$PWD/precompiledheadersupdatedmessage.h \
$$PWD/stringcache.h \
$$PWD/removepchprojectpartsmessage.h \ $$PWD/removepchprojectpartsmessage.h \
$$PWD/clangcodemodelclientmessages.h \ $$PWD/clangcodemodelclientmessages.h \
$$PWD/clangcodemodelservermessages.h \ $$PWD/clangcodemodelservermessages.h \

View File

@@ -37,66 +37,62 @@ class FilePath
{ {
public: public:
FilePath() = default; 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(); auto found = foundReverse.base();
--found;
Utils::SmallString fileName(found, filePath.end()); m_slashIndex = std::size_t(std::distance(m_path.begin(), found));
if (foundReverse != filePath.rend()) }
filePath.resize(std::size_t(std::distance(filePath.begin(), --found)));
directory_ = std::move(filePath); explicit FilePath(const Utils::PathString &filePath)
name_ = std::move(fileName); : 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) explicit FilePath(const QString &filePath)
: FilePath(Utils::SmallString(filePath)) : FilePath(Utils::PathString(filePath))
{ {
} }
FilePath(Utils::SmallString &&directory, Utils::SmallString &&name) FilePath(const Utils::PathString &directory, const Utils::PathString &name)
: directory_(std::move(directory)), : m_path({std::move(directory), "/", std::move(name)}),
name_(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_; return m_path;
}
Utils::SmallString takeName()
{
return std::move(name_);
}
Utils::PathString path() const
{
return {directory_, "/", name_};
} }
friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath) friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath)
{ {
out << filePath.directory_; out << filePath.m_path;
out << filePath.name_;
return out; return out;
} }
friend QDataStream &operator>>(QDataStream &in, FilePath &filePath) friend QDataStream &operator>>(QDataStream &in, FilePath &filePath)
{ {
in >> filePath.directory_; in >> filePath.m_path;
in >> filePath.name_;
return in; return in;
} }
@@ -110,24 +106,22 @@ public:
friend bool operator==(const FilePath &first, const FilePath &second) friend bool operator==(const FilePath &first, const FilePath &second)
{ {
return first.name_ == second.name_ return first.m_path == second.m_path;
&& first.directory_ == second.directory_;
} }
friend bool operator<(const FilePath &first, const FilePath &second) friend bool operator<(const FilePath &first, const FilePath &second)
{ {
return std::tie(first.name_, first.directory_) return first.m_path < second.m_path;
< std::tie(second.name_, second.directory_);
} }
FilePath clone() const FilePath clone() const
{ {
return FilePath(directory_.clone(), name_.clone()); return FilePath(m_path.clone(), m_slashIndex);
} }
private: private:
Utils::SmallString directory_; Utils::PathString m_path = "/";
Utils::SmallString name_; std::size_t m_slashIndex = 0;
}; };
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath); CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath);

View File

@@ -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()) { if (m_filePathHash.find(fileId) == m_filePathHash.end())
m_filePathHash.emplace(std::piecewise_construct, m_filePathHash.emplace(fileId, FilePath(std::move(filePath)));
std::forward_as_tuple(fileId),
std::forward_as_tuple(std::move(fileDirectory), std::move(fileName)));
}
} }
void reserve(std::size_t size) void reserve(std::size_t size)

View File

@@ -46,10 +46,10 @@ QDebug operator<<(QDebug debug, const SourceLocationContainer &container)
std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container) std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container)
{ {
os << "(" os << "("
<< container.fileHash() << ", "
<< container.line() << ", " << container.line() << ", "
<< container.column() << ", " << container.column() << ", "
<< container.offset() << ", " << container.offset()
<< container.fileHash()
<< ")"; << ")";
return os; return os;

View File

@@ -47,6 +47,11 @@ public:
return sourceRangesContainer; return sourceRangesContainer;
} }
SourceRangesContainer &sourceRanges()
{
return sourceRangesContainer;
}
const std::vector<DynamicASTMatcherDiagnosticContainer> &diagnostics() const const std::vector<DynamicASTMatcherDiagnosticContainer> &diagnostics() const
{ {
return diagnosticContainers; return diagnosticContainers;

View File

@@ -54,6 +54,11 @@ public:
return m_sourceRangeWithTextContainers; return m_sourceRangeWithTextContainers;
} }
std::vector<SourceRangeWithTextContainer> &sourceRangeWithTextContainers()
{
return m_sourceRangeWithTextContainers;
}
std::vector<SourceRangeWithTextContainer> takeSourceRangeWithTextContainers() std::vector<SourceRangeWithTextContainer> takeSourceRangeWithTextContainers()
{ {
return std::move(m_sourceRangeWithTextContainers); return std::move(m_sourceRangeWithTextContainers);

View File

@@ -110,6 +110,25 @@ private:
Utils::SmallString m_text; Utils::SmallString m_text;
}; };
using SourceRangeWithTextContainers = std::vector<SourceRangeWithTextContainer>;
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container); CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container);
std::ostream &operator<<(std::ostream &os, const SourceRangeWithTextContainer &container); std::ostream &operator<<(std::ostream &os, const SourceRangeWithTextContainer &container);
} // namespace ClangBackEnd } // namespace ClangBackEnd
namespace std
{
template<> struct hash<ClangBackEnd::SourceRangeWithTextContainer>
{
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<uint>{}(container.fileHash())};
const result_type h2{std::hash<uint>{}(container.start().offset())};
const result_type h3{std::hash<uint>{}(container.end().offset())};
return h1 ^ (h2 << 8) ^ (h3 << 16);
}
};
}

View File

@@ -25,16 +25,26 @@
#pragma once #pragma once
#include "clangpchmanagerbackend_global.h"
#include <utils/smallstringview.h> #include <utils/smallstringview.h>
#include <algorithm> #include <algorithm>
#include <mutex>
#include <vector> #include <vector>
namespace ClangBackEnd { namespace ClangBackEnd {
template <typename StringType> class NonLockingMutex
{
public:
constexpr NonLockingMutex() noexcept {}
NonLockingMutex(const NonLockingMutex&) = delete;
NonLockingMutex& operator=(const NonLockingMutex&) = delete;
void lock() {}
void unlock() {}
};
template <typename StringType,
typename Mutex = NonLockingMutex>
class StringCache class StringCache
{ {
class StringCacheEntry class StringCacheEntry
@@ -79,6 +89,8 @@ public:
uint stringId(Utils::SmallStringView stringView) uint stringId(Utils::SmallStringView stringView)
{ {
std::lock_guard<Mutex> lock(m_mutex);
Found found = find(stringView); Found found = find(stringView);
if (!found.wasFound) if (!found.wasFound)
@@ -89,6 +101,8 @@ public:
std::vector<uint> stringIds(const std::vector<StringType> &strings) std::vector<uint> stringIds(const std::vector<StringType> &strings)
{ {
std::lock_guard<Mutex> lock(m_mutex);
std::vector<uint> ids; std::vector<uint> ids;
ids.reserve(strings.size()); ids.reserve(strings.size());
@@ -102,11 +116,15 @@ public:
const StringType &string(uint id) const const StringType &string(uint id) const
{ {
std::lock_guard<Mutex> lock(m_mutex);
return m_strings.at(m_indices.at(id)).string; return m_strings.at(m_indices.at(id)).string;
} }
std::vector<StringType> strings(const std::vector<uint> &ids) const std::vector<StringType> strings(const std::vector<uint> &ids) const
{ {
std::lock_guard<Mutex> lock(m_mutex);
std::vector<StringType> strings; std::vector<StringType> strings;
strings.reserve(ids.size()); strings.reserve(ids.size());
@@ -155,6 +173,7 @@ private:
private: private:
StringCacheEntries m_strings; StringCacheEntries m_strings;
std::vector<uint> m_indices; std::vector<uint> m_indices;
mutable Mutex m_mutex;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -395,18 +395,13 @@ FileSaverBase::FileSaverBase()
{ {
} }
FileSaverBase::~FileSaverBase() FileSaverBase::~FileSaverBase() = default;
{
delete m_file;
}
bool FileSaverBase::finalize() bool FileSaverBase::finalize()
{ {
m_file->close(); m_file->close();
setResult(m_file->error() == QFile::NoError); setResult(m_file->error() == QFile::NoError);
// We delete the object, so it is really closed even if it is a QTemporaryFile. m_file.reset();
delete m_file;
m_file = 0;
return !m_hasError; return !m_hasError;
} }
@@ -444,8 +439,13 @@ bool FileSaverBase::write(const QByteArray &bytes)
bool FileSaverBase::setResult(bool ok) bool FileSaverBase::setResult(bool ok)
{ {
if (!ok && !m_hasError) { if (!ok && !m_hasError) {
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( m_errorString = tr("Cannot write file %1. Disk full?").arg(
QDir::toNativeSeparators(m_fileName)); QDir::toNativeSeparators(m_fileName));
}
m_hasError = true; m_hasError = true;
} }
return ok; return ok;
@@ -488,10 +488,10 @@ FileSaver::FileSaver(const QString &filename, QIODevice::OpenMode mode)
} }
} }
if (mode & (QIODevice::ReadOnly | QIODevice::Append)) { if (mode & (QIODevice::ReadOnly | QIODevice::Append)) {
m_file = new QFile(filename); m_file.reset(new QFile{filename});
m_isSafe = false; m_isSafe = false;
} else { } else {
m_file = new SaveFile(filename); m_file.reset(new SaveFile{filename});
m_isSafe = true; m_isSafe = true;
} }
if (!m_file->open(QIODevice::WriteOnly | mode)) { if (!m_file->open(QIODevice::WriteOnly | mode)) {
@@ -507,22 +507,22 @@ bool FileSaver::finalize()
if (!m_isSafe) if (!m_isSafe)
return FileSaverBase::finalize(); return FileSaverBase::finalize();
SaveFile *sf = static_cast<SaveFile *>(m_file); SaveFile *sf = static_cast<SaveFile *>(m_file.get());
if (m_hasError) { if (m_hasError) {
if (sf->isOpen()) if (sf->isOpen())
sf->rollback(); sf->rollback();
} else { } else {
setResult(sf->commit()); setResult(sf->commit());
} }
delete sf; m_file.reset();
m_file = 0;
return !m_hasError; return !m_hasError;
} }
TempFileSaver::TempFileSaver(const QString &templ) TempFileSaver::TempFileSaver(const QString &templ)
: m_autoRemove(true) : m_autoRemove(true)
{ {
QTemporaryFile *tempFile = new QTemporaryFile(); m_file.reset(new QTemporaryFile{});
QTemporaryFile *tempFile = static_cast<QTemporaryFile *>(m_file.get());
if (!templ.isEmpty()) if (!templ.isEmpty())
tempFile->setFileTemplate(templ); tempFile->setFileTemplate(templ);
tempFile->setAutoRemove(false); tempFile->setAutoRemove(false);
@@ -532,14 +532,12 @@ TempFileSaver::TempFileSaver(const QString &templ)
tempFile->errorString()); tempFile->errorString());
m_hasError = true; m_hasError = true;
} }
m_file = tempFile;
m_fileName = tempFile->fileName(); m_fileName = tempFile->fileName();
} }
TempFileSaver::~TempFileSaver() TempFileSaver::~TempFileSaver()
{ {
delete m_file; m_file.reset();
m_file = 0;
if (m_autoRemove) if (m_autoRemove)
QFile::remove(m_fileName); QFile::remove(m_fileName);
} }

View File

@@ -35,6 +35,7 @@
#include <QStringList> #include <QStringList>
#include <functional> #include <functional>
#include <memory>
namespace Utils {class FileName; } namespace Utils {class FileName; }
@@ -190,8 +191,10 @@ public:
bool setResult(QXmlStreamWriter *stream); bool setResult(QXmlStreamWriter *stream);
bool setResult(bool ok); bool setResult(bool ok);
QFile *file() { return m_file.get(); }
protected: protected:
QFile *m_file; std::unique_ptr<QFile> m_file;
QString m_fileName; QString m_fileName;
QString m_errorString; QString m_errorString;
bool m_hasError; bool m_hasError;
@@ -208,7 +211,6 @@ public:
virtual bool finalize(); virtual bool finalize();
using FileSaverBase::finalize; using FileSaverBase::finalize;
QFile *file() { return m_file; }
private: private:
bool m_isSafe; bool m_isSafe;
@@ -221,8 +223,6 @@ public:
explicit TempFileSaver(const QString &templ = QString()); explicit TempFileSaver(const QString &templ = QString());
~TempFileSaver(); ~TempFileSaver();
QTemporaryFile *file() { return reinterpret_cast<QTemporaryFile *>(m_file); }
void setAutoRemove(bool on) { m_autoRemove = on; } void setAutoRemove(bool on) { m_autoRemove = on; }
private: private:

View File

@@ -113,10 +113,19 @@ bool SaveFile::commit()
QString finalFileName QString finalFileName
= FileUtils::resolveSymlinks(FileName::fromString(m_finalFileName)).toString(); = FileUtils::resolveSymlinks(FileName::fromString(m_finalFileName)).toString();
QString bakname = finalFileName + QLatin1Char('~'); QString bakname = finalFileName + QLatin1Char('~');
if (QFile::exists(finalFileName)) {
QFile::remove(bakname); // Kill old backup QFile::remove(bakname); // Kill old backup
QFile::rename(finalFileName, bakname); // Backup current file // 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 if (!rename(finalFileName)) { // Replace current file
QFile::rename(bakname, finalFileName); // Rollback to current file QFile::rename(bakname, finalFileName); // Rollback to current file
remove();
return false; return false;
} }
if (!m_backup) if (!m_backup)

View File

@@ -68,12 +68,12 @@ QDataStream &operator>>(QDataStream &in, BasicSmallString<Size> &string)
return in; return in;
} }
inline template <typename String>
QDebug &operator<<(QDebug &debug, const SmallString &string) QDebug &operator<<(QDebug &debug, const String &string)
{ {
using QT_PREPEND_NAMESPACE(operator<<); using QT_PREPEND_NAMESPACE(operator<<);
debug.nospace() << "\"" << string.data() << "\""; debug.nospace().quote() << QByteArray::fromRawData(string.data(), int(string.size()));
return debug; return debug;
} }

View File

@@ -104,6 +104,11 @@ public:
return const_reverse_iterator(begin() - static_cast<std::size_t>(1)); return const_reverse_iterator(begin() - static_cast<std::size_t>(1));
} }
operator std::string() const
{
return std::string(data(), size());
}
private: private:
const char *m_pointer; const char *m_pointer;
size_type m_size; size_type m_size;

View File

@@ -67,6 +67,12 @@ QStringList QtTestConfiguration::argumentsForTestRunner() const
if (!metricsOption.isEmpty()) if (!metricsOption.isEmpty())
arguments << metricsOption; arguments << metricsOption;
if (qtSettings->verboseBench)
arguments << "-vb";
if (qtSettings->logSignalsSlots)
arguments << "-vs";
if (runMode() == DebuggableTestConfiguration::Debug) { if (runMode() == DebuggableTestConfiguration::Debug) {
if (qtSettings->noCrashHandler) if (qtSettings->noCrashHandler)
arguments << "-nocrashhandler"; arguments << "-nocrashhandler";

View File

@@ -31,6 +31,8 @@ namespace Internal {
static const char metricsKey[] = "Metrics"; static const char metricsKey[] = "Metrics";
static const char noCrashhandlerKey[] = "NoCrashhandlerOnDebug"; static const char noCrashhandlerKey[] = "NoCrashhandlerOnDebug";
static const char useXMLOutputKey[] = "UseXMLOutput"; static const char useXMLOutputKey[] = "UseXMLOutput";
static const char verboseBenchKey[] = "VerboseBench";
static const char logSignalsSlotsKey[] = "LogSignalsSlots";
static MetricsType intToMetrics(int value) static MetricsType intToMetrics(int value)
{ {
@@ -60,6 +62,8 @@ void QtTestSettings::fromFrameworkSettings(const QSettings *s)
metrics = intToMetrics(s->value(metricsKey, Walltime).toInt()); metrics = intToMetrics(s->value(metricsKey, Walltime).toInt());
noCrashHandler = s->value(noCrashhandlerKey, true).toBool(); noCrashHandler = s->value(noCrashhandlerKey, true).toBool();
useXMLOutput = s->value(useXMLOutputKey, 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 void QtTestSettings::toFrameworkSettings(QSettings *s) const
@@ -67,6 +71,8 @@ void QtTestSettings::toFrameworkSettings(QSettings *s) const
s->setValue(metricsKey, metrics); s->setValue(metricsKey, metrics);
s->setValue(noCrashhandlerKey, noCrashHandler); s->setValue(noCrashhandlerKey, noCrashHandler);
s->setValue(useXMLOutputKey, useXMLOutput); s->setValue(useXMLOutputKey, useXMLOutput);
s->setValue(verboseBenchKey, verboseBench);
s->setValue(logSignalsSlotsKey, logSignalsSlots);
} }
QString QtTestSettings::metricsTypeToOption(const MetricsType type) QString QtTestSettings::metricsTypeToOption(const MetricsType type)

View File

@@ -49,6 +49,8 @@ public:
MetricsType metrics = Walltime; MetricsType metrics = Walltime;
bool noCrashHandler = true; bool noCrashHandler = true;
bool useXMLOutput = true; bool useXMLOutput = true;
bool verboseBench = false;
bool logSignalsSlots = false;
protected: protected:
void fromFrameworkSettings(const QSettings *s) override; void fromFrameworkSettings(const QSettings *s) override;

View File

@@ -47,6 +47,8 @@ void QtTestSettingsWidget::setSettings(const QtTestSettings &settings)
{ {
m_ui.disableCrashhandlerCB->setChecked(settings.noCrashHandler); m_ui.disableCrashhandlerCB->setChecked(settings.noCrashHandler);
m_ui.useXMLOutputCB->setChecked(settings.useXMLOutput); m_ui.useXMLOutputCB->setChecked(settings.useXMLOutput);
m_ui.verboseBenchmarksCB->setChecked(settings.verboseBench);
m_ui.logSignalsAndSlotsCB->setChecked(settings.logSignalsSlots);
switch (settings.metrics) { switch (settings.metrics) {
case MetricsType::Walltime: case MetricsType::Walltime:
m_ui.walltimeRB->setChecked(true); m_ui.walltimeRB->setChecked(true);
@@ -74,6 +76,8 @@ QtTestSettings QtTestSettingsWidget::settings() const
result.noCrashHandler = m_ui.disableCrashhandlerCB->isChecked(); result.noCrashHandler = m_ui.disableCrashhandlerCB->isChecked();
result.useXMLOutput = m_ui.useXMLOutputCB->isChecked(); result.useXMLOutput = m_ui.useXMLOutputCB->isChecked();
result.verboseBench = m_ui.verboseBenchmarksCB->isChecked();
result.logSignalsSlots = m_ui.logSignalsAndSlotsCB->isChecked();
if (m_ui.walltimeRB->isChecked()) if (m_ui.walltimeRB->isChecked())
result.metrics = MetricsType::Walltime; result.metrics = MetricsType::Walltime;
else if (m_ui.tickcounterRB->isChecked()) else if (m_ui.tickcounterRB->isChecked())

View File

@@ -46,6 +46,23 @@ Warning: Plain text output is missing some information (e.g. duration)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="verboseBenchmarksCB">
<property name="text">
<string>Verbose benchmarks</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="logSignalsAndSlotsCB">
<property name="toolTip">
<string>Log every signal emission and resulting slot invocations.</string>
</property>
<property name="text">
<string>Log signals and slots</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">

View File

@@ -104,19 +104,6 @@ void RefactoringClient::setRefactoringConnectionClient(
this->connectionClient = connectionClient; 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<uint, QString> RefactoringClient::convertFilePaths( std::unordered_map<uint, QString> RefactoringClient::convertFilePaths(
const ClangBackEnd::FilePathDict &filePaths) const ClangBackEnd::FilePathDict &filePaths)
{ {
@@ -126,7 +113,7 @@ std::unordered_map<uint, QString> RefactoringClient::convertFilePaths(
auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) { auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) {
return std::make_pair(dictonaryEntry.first, return std::make_pair(dictonaryEntry.first,
concatenateFilePath(dictonaryEntry.second).toQString()); dictonaryEntry.second.path().toQString());
}; };
std::transform(filePaths.begin(), std::transform(filePaths.begin(),

View File

@@ -55,7 +55,7 @@
</layout> </layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="searchLabel">
<property name="text"> <property name="text">
<string>Sear&amp;ch for:</string> <string>Sear&amp;ch for:</string>
</property> </property>
@@ -73,7 +73,16 @@
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
@@ -103,9 +112,18 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QWidget" name="widget" native="true"> <widget class="QWidget" name="optionsWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>

View File

@@ -147,6 +147,13 @@ void FindToolWindow::updateButtonStates()
if (m_configWidget) if (m_configWidget)
m_configWidget->setEnabled(filterEnabled); 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_ui.matchCase->setEnabled(filterEnabled
&& (m_currentFilter->supportedFindFlags() & FindCaseSensitively)); && (m_currentFilter->supportedFindFlags() & FindCaseSensitively));
m_ui.wholeWords->setEnabled(filterEnabled m_ui.wholeWords->setEnabled(filterEnabled

View File

@@ -142,6 +142,14 @@
your find filter supports global search and replace. 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) \fn void IFindFilter::findAll(const QString &txt, Core::FindFlags findFlags)
This function is called when the user selected this find scope and This function is called when the user selected this find scope and
@@ -227,7 +235,8 @@ QKeySequence IFindFilter::defaultShortcut() const
FindFlags IFindFilter::supportedFindFlags() const FindFlags IFindFilter::supportedFindFlags() const
{ {
return FindCaseSensitively return FindCaseSensitively
| FindRegularExpression | FindWholeWords; | FindRegularExpression
| FindWholeWords;
} }
QPixmap IFindFilter::pixmapForFindFlags(FindFlags flags) QPixmap IFindFilter::pixmapForFindFlags(FindFlags flags)

View File

@@ -50,6 +50,7 @@ public:
virtual bool isValid() const { return true; } virtual bool isValid() const { return true; }
virtual QKeySequence defaultShortcut() const; virtual QKeySequence defaultShortcut() const;
virtual bool isReplaceSupported() const { return false; } virtual bool isReplaceSupported() const { return false; }
virtual bool showSearchTermInput() const { return true; }
virtual FindFlags supportedFindFlags() const; virtual FindFlags supportedFindFlags() const;
virtual void findAll(const QString &txt, FindFlags findFlags) = 0; virtual void findAll(const QString &txt, FindFlags findFlags) = 0;

View File

@@ -100,11 +100,6 @@ void SymbolsFindFilter::setPaused(bool paused)
watcher->setPaused(paused); watcher->setPaused(paused);
} }
FindFlags SymbolsFindFilter::supportedFindFlags() const
{
return FindCaseSensitively | FindRegularExpression | FindWholeWords;
}
void SymbolsFindFilter::findAll(const QString &txt, FindFlags findFlags) void SymbolsFindFilter::findAll(const QString &txt, FindFlags findFlags)
{ {
SearchResultWindow *window = SearchResultWindow::instance(); SearchResultWindow *window = SearchResultWindow::instance();

View File

@@ -56,7 +56,6 @@ public:
QString id() const; QString id() const;
QString displayName() const; QString displayName() const;
bool isEnabled() const; bool isEnabled() const;
Core::FindFlags supportedFindFlags() const;
void findAll(const QString &txt, Core::FindFlags findFlags); void findAll(const QString &txt, Core::FindFlags findFlags);

View File

@@ -30,11 +30,7 @@
#include "../debuggermainwindow.h" #include "../debuggermainwindow.h"
#include <coreplugin/id.h> #include <QWidget>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runconfiguration.h>
#include <QCoreApplication> #include <QCoreApplication>

View File

@@ -3416,19 +3416,10 @@ static bool buildTypeAccepted(QFlags<ToolMode> toolMode, BuildConfiguration::Bui
return false; return false;
} }
RunConfiguration *startupRunConfiguration()
{
if (Project *pro = SessionManager::startupProject()) {
if (const Target *target = pro->activeTarget())
return target->activeRunConfiguration();
}
return nullptr;
}
static BuildConfiguration::BuildType startupBuildType() static BuildConfiguration::BuildType startupBuildType()
{ {
BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown; BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
if (RunConfiguration *runConfig = startupRunConfiguration()) { if (RunConfiguration *runConfig = RunConfiguration::startupRunConfiguration()) {
if (const BuildConfiguration *buildConfig = runConfig->target()->activeBuildConfiguration()) if (const BuildConfiguration *buildConfig = runConfig->target()->activeBuildConfiguration())
buildType = buildConfig->buildType(); buildType = buildConfig->buildType();
} }

View File

@@ -33,6 +33,7 @@
#include "environmentaspect.h" #include "environmentaspect.h"
#include "kitinformation.h" #include "kitinformation.h"
#include "runnables.h" #include "runnables.h"
#include "session.h"
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
@@ -243,6 +244,20 @@ void RunConfiguration::ctor()
[this] { return displayName(); }, false); [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. Checks whether a run configuration is enabled.
*/ */

View File

@@ -281,6 +281,8 @@ public:
void addExtraAspect(IRunConfigurationAspect *aspect); void addExtraAspect(IRunConfigurationAspect *aspect);
static RunConfiguration *startupRunConfiguration();
signals: signals:
void enabledChanged(); void enabledChanged();
void requestRunActionsUpdate(); void requestRunActionsUpdate();

View File

@@ -587,8 +587,8 @@ void QmlProfilerTool::attachToWaitingApplication()
Debugger::selectPerspective(Constants::QmlProfilerPerspectiveId); Debugger::selectPerspective(Constants::QmlProfilerPerspectiveId);
RunConfiguration *rc = Debugger::startupRunConfiguration(); auto runConfig = RunConfiguration::startupRunConfiguration();
auto runControl = new RunControl(rc, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE); auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
auto profiler = new QmlProfilerRunner(runControl); auto profiler = new QmlProfilerRunner(runControl);
profiler->setServerUrl(serverUrl); profiler->setServerUrl(serverUrl);

View File

@@ -8,7 +8,6 @@ SOURCES += qnxplugin.cpp \
qnxdevicefactory.cpp \ qnxdevicefactory.cpp \
qnxdevicewizard.cpp \ qnxdevicewizard.cpp \
qnxrunconfiguration.cpp \ qnxrunconfiguration.cpp \
qnxruncontrolfactory.cpp \
qnxanalyzesupport.cpp \ qnxanalyzesupport.cpp \
qnxdebugsupport.cpp \ qnxdebugsupport.cpp \
qnxdeploystepfactory.cpp \ qnxdeploystepfactory.cpp \
@@ -41,7 +40,6 @@ HEADERS += qnxplugin.h\
qnxdevicefactory.h \ qnxdevicefactory.h \
qnxdevicewizard.h \ qnxdevicewizard.h \
qnxrunconfiguration.h \ qnxrunconfiguration.h \
qnxruncontrolfactory.h \
qnxanalyzesupport.h \ qnxanalyzesupport.h \
qnxdebugsupport.h \ qnxdebugsupport.h \
qnxdeploystepfactory.h \ qnxdeploystepfactory.h \

View File

@@ -76,8 +76,6 @@ QtcPlugin {
"qnxrunconfiguration.h", "qnxrunconfiguration.h",
"qnxrunconfigurationfactory.cpp", "qnxrunconfigurationfactory.cpp",
"qnxrunconfigurationfactory.h", "qnxrunconfigurationfactory.h",
"qnxruncontrolfactory.cpp",
"qnxruncontrolfactory.h",
"qnxutils.cpp", "qnxutils.cpp",
"qnxutils.h", "qnxutils.h",
"qnx_export.h", "qnx_export.h",

View File

@@ -75,9 +75,11 @@ private:
// QnxDebugSupport // QnxDebugSupport
QnxAnalyzeSupport::QnxAnalyzeSupport(RunControl *runControl) QnxQmlProfilerSupport::QnxQmlProfilerSupport(RunControl *runControl)
: RunWorker(runControl) : RunWorker(runControl)
{ {
runControl->createWorker(runControl->runMode());
setDisplayName("QnxAnalyzeSupport"); setDisplayName("QnxAnalyzeSupport");
appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat); appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat);
@@ -99,7 +101,7 @@ QnxAnalyzeSupport::QnxAnalyzeSupport(RunControl *runControl)
// m_outputParser.processOutput(msg); // m_outputParser.processOutput(msg);
} }
void QnxAnalyzeSupport::start() void QnxQmlProfilerSupport::start()
{ {
// runControl()->notifyRemoteSetupDone(m_qmlPort); // runControl()->notifyRemoteSetupDone(m_qmlPort);
reportStarted(); reportStarted();

View File

@@ -30,14 +30,12 @@
namespace Qnx { namespace Qnx {
namespace Internal { namespace Internal {
class Slog2InfoRunner; class QnxQmlProfilerSupport : public ProjectExplorer::RunWorker
class QnxAnalyzeSupport : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit QnxAnalyzeSupport(ProjectExplorer::RunControl *runControl); explicit QnxQmlProfilerSupport(ProjectExplorer::RunControl *runControl);
private: private:
void start() override; void start() override;

View File

@@ -25,38 +25,49 @@
#include "qnxplugin.h" #include "qnxplugin.h"
#include "qnxconstants.h" #include "qnxanalyzesupport.h"
#include "qnxattachdebugsupport.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 "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 "qnxtoolchain.h"
#include "qnxattachdebugsupport.h" #include "qnxutils.h"
#include <coreplugin/actionmanager/actioncontainer.h> #include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h> #include <coreplugin/icontext.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskhub.h> #include <projectexplorer/taskhub.h>
#include <projectexplorer/kitmanager.h> #include <projectexplorer/kitmanager.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>
#include <qtsupport/qtkitinformation.h>
#include <QAction> #include <QAction>
#include <QtPlugin> #include <QtPlugin>
using namespace ProjectExplorer; 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) 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 QnxConfigurationManager);
addAutoReleasedObject(new QnxQtVersionFactory); addAutoReleasedObject(new QnxQtVersionFactory);
addAutoReleasedObject(new QnxDeviceFactory); addAutoReleasedObject(new QnxDeviceFactory);
addAutoReleasedObject(new QnxRunControlFactory);
addAutoReleasedObject(new QnxDeployStepFactory); addAutoReleasedObject(new QnxDeployStepFactory);
addAutoReleasedObject(new QnxDeployConfigurationFactory); addAutoReleasedObject(new QnxDeployConfigurationFactory);
addAutoReleasedObject(new QnxRunConfigurationFactory); addAutoReleasedObject(new QnxRunConfigurationFactory);
addAutoReleasedObject(new QnxSettingsPage); 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<const QnxDevice>();
return !dev.isNull();
};
RunControl::registerWorker<SimpleTargetRunner>
(ProjectExplorer::Constants::NORMAL_RUN_MODE, constraint);
RunControl::registerWorker<QnxDebugSupport>
(ProjectExplorer::Constants::DEBUG_RUN_MODE, constraint);
RunControl::registerWorker<QnxQmlProfilerSupport>
(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, constraint);
addAutoReleasedObject(new QnxToolChainFactory); addAutoReleasedObject(new QnxToolChainFactory);
return true; return true;
@@ -118,3 +145,6 @@ void QnxPlugin::updateDebuggerActions()
m_attachToQnxApplication->setVisible(false && hasValidQnxKit); // FIXME m_attachToQnxApplication->setVisible(false && hasValidQnxKit); // FIXME
m_debugSeparator->setVisible(false && hasValidQnxKit); // FIXME QTCREATORBUG-16608 m_debugSeparator->setVisible(false && hasValidQnxKit); // FIXME QTCREATORBUG-16608
} }
} // Internal
} // Qnx

View File

@@ -40,18 +40,17 @@ class QnxPlugin : public ExtensionSystem::IPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Qnx.json") Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Qnx.json")
public: public:
QnxPlugin(); QnxPlugin() {}
bool initialize(const QStringList &arguments, QString *errorString); bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized(); void extensionsInitialized();
ShutdownFlag aboutToShutdown(); ShutdownFlag aboutToShutdown();
private slots: private:
void updateDebuggerActions(); void updateDebuggerActions();
private: QAction *m_debugSeparator = nullptr;
QAction *m_debugSeparator; QAction *m_attachToQnxApplication = nullptr;
QAction *m_attachToQnxApplication;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -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 <debugger/debuggerruncontrol.h>
#include <debugger/debuggerrunconfigurationaspect.h>
#include <debugger/debuggerstartparameters.h>
#include <debugger/debuggerkitinformation.h>
#include <debugger/analyzer/analyzermanager.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/portlist.h>
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<const QnxDevice>();
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

View File

@@ -37,6 +37,7 @@ QT_END_NAMESPACE
namespace TextEditor { namespace TextEditor {
namespace Convenience { namespace Convenience {
// line is 1-based, column is 0-based
TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document, TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document,
int pos, int pos,
int *line, int *column); int *line, int *column);

View File

@@ -6316,7 +6316,8 @@ void TextEditorWidgetPrivate::autocompleterHighlight(const QTextCursor &cursor)
m_autoCompleteHighlightPos.clear(); m_autoCompleteHighlightPos.clear();
} else if (m_highlightAutoComplete) { } else if (m_highlightAutoComplete) {
m_autoCompleteHighlightPos.push_back(cursor); m_autoCompleteHighlightPos.push_back(cursor);
} else if (m_animateAutoComplete) { }
if (m_animateAutoComplete) {
const QTextCharFormat &matchFormat const QTextCharFormat &matchFormat
= q->textDocument()->fontSettings().toTextCharFormat(C_AUTOCOMPLETE); = q->textDocument()->fontSettings().toTextCharFormat(C_AUTOCOMPLETE);
cancelCurrentAnimations();// one animation is enough cancelCurrentAnimations();// one animation is enough

View File

@@ -272,7 +272,7 @@ CallgrindTool::CallgrindTool()
menu->addAction(ActionManager::registerAction(action, CallgrindRemoteActionId), menu->addAction(ActionManager::registerAction(action, CallgrindRemoteActionId),
Debugger::Constants::G_ANALYZER_REMOTE_TOOLS); Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
QObject::connect(action, &QAction::triggered, this, [this, action] { QObject::connect(action, &QAction::triggered, this, [this, action] {
RunConfiguration *runConfig = startupRunConfiguration(); auto runConfig = RunConfiguration::startupRunConfiguration();
if (!runConfig) { if (!runConfig) {
showCannotStartDialog(action->text()); showCannotStartDialog(action->text());
return; return;

View File

@@ -435,7 +435,7 @@ MemcheckTool::MemcheckTool()
menu->addAction(ActionManager::registerAction(action, "Memcheck.Remote"), menu->addAction(ActionManager::registerAction(action, "Memcheck.Remote"),
Debugger::Constants::G_ANALYZER_REMOTE_TOOLS); Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
QObject::connect(action, &QAction::triggered, this, [this, action] { QObject::connect(action, &QAction::triggered, this, [this, action] {
RunConfiguration *runConfig = startupRunConfiguration(); auto runConfig = RunConfiguration::startupRunConfiguration();
if (!runConfig) { if (!runConfig) {
showCannotStartDialog(action->text()); showCannotStartDialog(action->text());
return; return;

View File

@@ -19,7 +19,6 @@ HEADERS += \
$$PWD/environment.h \ $$PWD/environment.h \
$$PWD/clangpathwatcher.h \ $$PWD/clangpathwatcher.h \
$$PWD/projectparts.h \ $$PWD/projectparts.h \
$$PWD/stringcache.h \
$$PWD/idpaths.h \ $$PWD/idpaths.h \
$$PWD/pchcreatorinterface.h \ $$PWD/pchcreatorinterface.h \
$$PWD/clangpathwatcherinterface.h \ $$PWD/clangpathwatcherinterface.h \

View File

@@ -30,27 +30,15 @@
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#include <QTime> #include <stringcache.h>
#if defined(__GNUC__) #include <QTime>
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning( disable : 4100 )
#endif
#include <clang/ASTMatchers/ASTMatchers.h> #include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/ASTMatchers/ASTMatchFinder.h> #include <clang/ASTMatchers/ASTMatchFinder.h>
#include <clang/ASTMatchers/Dynamic/Diagnostics.h> #include <clang/ASTMatchers/Dynamic/Diagnostics.h>
#include <clang/ASTMatchers/Dynamic/Parser.h> #include <clang/ASTMatchers/Dynamic/Parser.h>
#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::Diagnostics;
using clang::ast_matchers::dynamic::Parser; using clang::ast_matchers::dynamic::Parser;
using clang::ast_matchers::BoundNodes; using clang::ast_matchers::BoundNodes;
@@ -66,8 +54,10 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
} }
}; };
ClangQuery::ClangQuery(Utils::SmallString &&query) ClangQuery::ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache,
: query(std::move(query)) Utils::SmallString &&query)
: query(std::move(query)),
filePathCache(filePathCache)
{ {
} }
@@ -226,6 +216,7 @@ void ClangQuery::matchLocation(
SourceRangeExtractor extractor(ast->getSourceManager(), SourceRangeExtractor extractor(ast->getSourceManager(),
ast->getLangOpts(), ast->getLangOpts(),
filePathCache,
sourceRangesContainer); sourceRangesContainer);
extractor.addSourceRanges(sourceRanges); extractor.addSourceRanges(sourceRanges);

View File

@@ -30,6 +30,8 @@
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#include <dynamicastmatcherdiagnosticcontainer.h> #include <dynamicastmatcherdiagnosticcontainer.h>
#include <stringcache.h>
namespace clang { namespace clang {
namespace ast_matchers { namespace ast_matchers {
namespace dynamic { namespace dynamic {
@@ -49,7 +51,7 @@ namespace ClangBackEnd {
class ClangQuery : public ClangTool class ClangQuery : public ClangTool
{ {
public: public:
ClangQuery(Utils::SmallString &&query={}); ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, Utils::SmallString &&query={});
void setQuery(Utils::SmallString &&query); void setQuery(Utils::SmallString &&query);
@@ -67,6 +69,7 @@ private:
SourceRangesContainer sourceRangesContainer; SourceRangesContainer sourceRangesContainer;
Utils::SmallString query; Utils::SmallString query;
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_; std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_;
StringCache<Utils::PathString, std::mutex> &filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,10 +29,13 @@
namespace ClangBackEnd { namespace ClangBackEnd {
ClangQueryGatherer::ClangQueryGatherer(std::vector<V2::FileContainer> &&sources, ClangQueryGatherer::ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache,
std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query) 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_unsaved(std::move(unsaved)),
m_query(std::move(query)) m_query(std::move(query))
{ {
@@ -40,11 +43,12 @@ ClangQueryGatherer::ClangQueryGatherer(std::vector<V2::FileContainer> &&sources,
SourceRangesAndDiagnosticsForQueryMessage SourceRangesAndDiagnosticsForQueryMessage
ClangQueryGatherer::createSourceRangesAndDiagnosticsForSource( ClangQueryGatherer::createSourceRangesAndDiagnosticsForSource(
StringCache<Utils::PathString, std::mutex> *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query) Utils::SmallString &&query)
{ {
ClangQuery clangQuery(std::move(query)); ClangQuery clangQuery(*filePathCache, std::move(query));
clangQuery.addFile(source.filePath().directory(), clangQuery.addFile(source.filePath().directory(),
source.filePath().name(), source.filePath().name(),
@@ -65,7 +69,8 @@ bool ClangQueryGatherer::canCreateSourceRangesAndDiagnostics() const
SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createNextSourceRangesAndDiagnostics() SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createNextSourceRangesAndDiagnostics()
{ {
auto message = createSourceRangesAndDiagnosticsForSource(std::move(m_sources.back()), auto message = createSourceRangesAndDiagnosticsForSource(m_filePathCache,
std::move(m_sources.back()),
m_unsaved, m_unsaved,
m_query.clone()); m_query.clone());
m_sources.pop_back(); m_sources.pop_back();
@@ -77,6 +82,7 @@ ClangQueryGatherer::Future ClangQueryGatherer::startCreateNextSourceRangesAndDia
{ {
Future future = std::async(std::launch::async, Future future = std::async(std::launch::async,
createSourceRangesAndDiagnosticsForSource, createSourceRangesAndDiagnosticsForSource,
m_filePathCache,
std::move(m_sources.back()), std::move(m_sources.back()),
m_unsaved, m_unsaved,
m_query.clone()); m_query.clone());
@@ -120,7 +126,7 @@ std::vector<SourceRangesAndDiagnosticsForQueryMessage> ClangQueryGatherer::allCu
std::vector<SourceRangesAndDiagnosticsForQueryMessage> messages; std::vector<SourceRangesAndDiagnosticsForQueryMessage> messages;
for (Future &future : m_sourceFutures) for (Future &future : m_sourceFutures)
messages.push_back(future.get()); messages.push_back(m_sourceRangeFilter.removeDuplicates(future.get()));
return messages; return messages;
} }
@@ -130,7 +136,7 @@ std::vector<SourceRangesAndDiagnosticsForQueryMessage> ClangQueryGatherer::finis
std::vector<SourceRangesAndDiagnosticsForQueryMessage> messages; std::vector<SourceRangesAndDiagnosticsForQueryMessage> messages;
for (auto &&future : finishedFutures()) for (auto &&future : finishedFutures())
messages.push_back(future.get()); messages.push_back(m_sourceRangeFilter.removeDuplicates(future.get()));
return messages; return messages;
} }

View File

@@ -25,8 +25,11 @@
#pragma once #pragma once
#include "sourcerangefilter.h"
#include <sourcerangesanddiagnosticsforquerymessage.h> #include <sourcerangesanddiagnosticsforquerymessage.h>
#include <filecontainerv2.h> #include <filecontainerv2.h>
#include <stringcache.h>
#include <future> #include <future>
@@ -38,16 +41,16 @@ public:
using Future = std::future<SourceRangesAndDiagnosticsForQueryMessage>; using Future = std::future<SourceRangesAndDiagnosticsForQueryMessage>;
ClangQueryGatherer() = default; ClangQueryGatherer() = default;
ClangQueryGatherer(std::vector<V2::FileContainer> &&sources, ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache,
std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
static static SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource(
SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource( StringCache<Utils::PathString, std::mutex> *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
bool canCreateSourceRangesAndDiagnostics() const; bool canCreateSourceRangesAndDiagnostics() const;
SourceRangesAndDiagnosticsForQueryMessage createNextSourceRangesAndDiagnostics(); SourceRangesAndDiagnosticsForQueryMessage createNextSourceRangesAndDiagnostics();
Future startCreateNextSourceRangesAndDiagnosticsMessage(); Future startCreateNextSourceRangesAndDiagnosticsMessage();
@@ -66,6 +69,8 @@ protected:
std::vector<Future> finishedFutures(); std::vector<Future> finishedFutures();
private: private:
StringCache<Utils::PathString, std::mutex> *m_filePathCache = nullptr;
SourceRangeFilter m_sourceRangeFilter;
std::vector<V2::FileContainer> m_sources; std::vector<V2::FileContainer> m_sources;
std::vector<V2::FileContainer> m_unsaved; std::vector<V2::FileContainer> m_unsaved;
Utils::SmallString m_query; Utils::SmallString m_query;

View File

@@ -1,7 +1,8 @@
INCLUDEPATH += $$PWD INCLUDEPATH += $$PWD
HEADERS += \ HEADERS += \
$$PWD/clangrefactoringbackend_global.h $$PWD/clangrefactoringbackend_global.h \
$$PWD/sourcerangefilter.h
!isEmpty(LIBTOOLING_LIBS) { !isEmpty(LIBTOOLING_LIBS) {
SOURCES += \ SOURCES += \
@@ -33,3 +34,6 @@ HEADERS += \
$$PWD/locationsourcefilecallbacks.h \ $$PWD/locationsourcefilecallbacks.h \
$$PWD/clangquerygatherer.h $$PWD/clangquerygatherer.h
} }
SOURCES += \
$$PWD/sourcerangefilter.cpp

View File

@@ -84,23 +84,12 @@ template
void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths, void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths,
const Utils::SmallStringVector &arguments); 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) void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
{ {
unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size()); unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size());
auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) { auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) {
return UnsavedFileContent{toNativeFilePath(unsavedFile.filePath()), return UnsavedFileContent{toNativePath(unsavedFile.filePath().path().clone()),
unsavedFile.unsavedFileContent().clone()}; unsavedFile.unsavedFileContent().clone()};
}; };
@@ -111,7 +100,8 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
} }
namespace { namespace {
llvm::StringRef toStringRef(const Utils::SmallString &string) template <typename String>
llvm::StringRef toStringRef(const String &string)
{ {
return llvm::StringRef(string.data(), string.size()); return llvm::StringRef(string.data(), string.size());
} }

View File

@@ -77,13 +77,13 @@ struct FileContent
struct UnsavedFileContent struct UnsavedFileContent
{ {
UnsavedFileContent(Utils::SmallString &&filePath, UnsavedFileContent(Utils::PathString &&filePath,
Utils::SmallString &&content) Utils::SmallString &&content)
: filePath(std::move(filePath)), : filePath(std::move(filePath)),
content(std::move(content)) content(std::move(content))
{} {}
Utils::SmallString filePath; Utils::PathString filePath;
Utils::SmallString content; Utils::SmallString content;
}; };

View File

@@ -37,6 +37,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <functional> #include <functional>
#include <atomic>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -114,6 +115,11 @@ bool RefactoringServer::pollTimerIsActive() const
return m_pollTimer.isActive(); return m_pollTimer.isActive();
} }
void RefactoringServer::setGathererProcessingSlotCount(uint count)
{
m_gatherer.setProcessingSlotCount(count);
}
void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessages( void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessages(
std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
@@ -125,7 +131,7 @@ void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessages(
uint freeProcessors = std::thread::hardware_concurrency(); uint freeProcessors = std::thread::hardware_concurrency();
#endif #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_gatherer.setProcessingSlotCount(freeProcessors);
m_pollTimer.start(); m_pollTimer.start();

View File

@@ -30,7 +30,12 @@
#include <refactoringserverinterface.h> #include <refactoringserverinterface.h>
#include <QTimer> #include <QTimer>
#include <stringcache.h>
#include <utils/smallstring.h>
#include <future>
#include <mutex>
#include <vector> #include <vector>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -59,12 +64,15 @@ public:
bool pollTimerIsActive() const; bool pollTimerIsActive() const;
void setGathererProcessingSlotCount(uint count);
private: private:
void gatherSourceRangesAndDiagnosticsForQueryMessages(std::vector<V2::FileContainer> &&sources, void gatherSourceRangesAndDiagnosticsForQueryMessages(std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
private: private:
StringCache<Utils::PathString, std::mutex> m_filePathCache;
ClangQueryGatherer m_gatherer; ClangQueryGatherer m_gatherer;
QTimer m_pollTimer; QTimer m_pollTimer;
}; };

View File

@@ -53,7 +53,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
inline inline
llvm::SmallString<256> absolutePath(const llvm::StringRef &path) llvm::SmallString<256> absolutePath(clang::StringRef path)
{ {
llvm::SmallString<256> absolutePath(path); llvm::SmallString<256> absolutePath(path);
@@ -64,9 +64,9 @@ llvm::SmallString<256> absolutePath(const llvm::StringRef &path)
} }
template <typename Container> template <typename Container>
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 #ifdef _WIN32
std::replace(path.begin(), path.end(), '\\', '/'); std::replace(path.begin(), path.end(), '\\', '/');
@@ -89,13 +89,9 @@ void appendSourceLocationsToSourceLocationsContainer(
const auto fileId = decomposedLoction.first; const auto fileId = decomposedLoction.first;
const auto offset = decomposedLoction.second; const auto offset = decomposedLoction.second;
const auto fileEntry = sourceManager.getFileEntryForID(fileId); 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(), sourceLocationsContainer.insertFilePath(fileId.getHashValue(),
fromNativePath(filePath), fromNativePath(fileEntry->tryGetRealPathName()));
fromNativePath(fileName));
sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(), sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(),
fullSourceLocation.getSpellingLineNumber(), fullSourceLocation.getSpellingLineNumber(),
fullSourceLocation.getSpellingColumnNumber(), fullSourceLocation.getSpellingColumnNumber(),

View File

@@ -51,11 +51,14 @@
namespace ClangBackEnd { namespace ClangBackEnd {
SourceRangeExtractor::SourceRangeExtractor(const clang::SourceManager &sourceManager, SourceRangeExtractor::SourceRangeExtractor(
const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer) SourceRangesContainer &sourceRangesContainer)
: sourceManager(sourceManager), : sourceManager(sourceManager),
languageOptions(languageOptions), languageOptions(languageOptions),
filePathCache(filePathCache),
sourceRangesContainer(sourceRangesContainer) sourceRangesContainer(sourceRangesContainer)
{ {
} }
@@ -123,19 +126,16 @@ const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(c
return {sourceRange.getBegin(), endLocation}; return {sourceRange.getBegin(), endLocation};
} }
void SourceRangeExtractor::insertSourceRange(uint fileHash, void SourceRangeExtractor::insertSourceRange(uint fileId,
Utils::SmallString &&directoryPath, Utils::PathString &&filePath,
Utils::SmallString &&fileName,
const clang::FullSourceLoc &startLocation, const clang::FullSourceLoc &startLocation,
uint startOffset, uint startOffset,
const clang::FullSourceLoc &endLocation, const clang::FullSourceLoc &endLocation,
uint endOffset, uint endOffset,
Utils::SmallString &&lineSnippet) Utils::SmallString &&lineSnippet)
{ {
sourceRangesContainer.insertFilePath(fileHash, sourceRangesContainer.insertFilePath(fileId, std::move(filePath));
std::move(directoryPath), sourceRangesContainer.insertSourceRange(fileId,
std::move(fileName));
sourceRangesContainer.insertSourceRange(fileHash,
startLocation.getSpellingLineNumber(), startLocation.getSpellingLineNumber(),
startLocation.getSpellingColumnNumber(), startLocation.getSpellingColumnNumber(),
startOffset, startOffset,
@@ -145,6 +145,17 @@ void SourceRangeExtractor::insertSourceRange(uint fileHash,
std::move(lineSnippet)); 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) void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
{ {
auto extendedSourceRange = extendSourceRangeToLastTokenEnd(sourceRange); auto extendedSourceRange = extendSourceRangeToLastTokenEnd(sourceRange);
@@ -158,15 +169,13 @@ void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
const auto startOffset = startDecomposedLoction.second; const auto startOffset = startDecomposedLoction.second;
const auto endOffset = endDecomposedLoction.second; const auto endOffset = endDecomposedLoction.second;
const auto fileEntry = sourceManager.getFileEntryForID(fileId); 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(), Utils::SmallString lineSnippet = getExpandedText(startSourceLocation.getBufferData(),
startOffset, startOffset,
endOffset); endOffset);
insertSourceRange(fileId.getHashValue(),
fromNativePath(filePath), insertSourceRange(findFileId(fileId, fileEntry),
{fileName.data(), fileName.size()}, fromNativePath(fileEntry->tryGetRealPathName()),
startSourceLocation, startSourceLocation,
startOffset, startOffset,
endSourceLocation, endSourceLocation,

View File

@@ -25,9 +25,14 @@
#pragma once #pragma once
#include <stringcache.h>
#include <filepath.h>
#include <utils/smallstringfwd.h> #include <utils/smallstringfwd.h>
#include <vector> #include <vector>
#include <unordered_map>
using uint = unsigned int; using uint = unsigned int;
@@ -40,6 +45,8 @@ class SourceManager;
class LangOptions; class LangOptions;
class SourceRange; class SourceRange;
class FullSourceLoc; class FullSourceLoc;
class FileID;
class FileEntry;
} }
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -52,6 +59,7 @@ class SourceRangeExtractor
public: public:
SourceRangeExtractor(const clang::SourceManager &sourceManager, SourceRangeExtractor(const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer); SourceRangesContainer &sourceRangesContainer);
void addSourceRange(const clang::SourceRange &sourceRange); void addSourceRange(const clang::SourceRange &sourceRange);
@@ -66,18 +74,21 @@ public:
const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange); const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange);
private: private:
void insertSourceRange(uint fileHash, void insertSourceRange(uint fileId,
Utils::SmallString &&directoryPath, Utils::PathString &&filePath,
Utils::SmallString &&fileName,
const clang::FullSourceLoc &startLocation, const clang::FullSourceLoc &startLocation,
uint startOffset, uint startOffset,
const clang::FullSourceLoc &endLocation, const clang::FullSourceLoc &endLocation,
uint endOffset, uint endOffset,
Utils::SmallString &&lineSnippet); Utils::SmallString &&lineSnippet);
uint findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
private: private:
mutable std::unordered_map<uint, uint> m_fileIdMapping;
const clang::SourceManager &sourceManager; const clang::SourceManager &sourceManager;
const clang::LangOptions &languageOptions; const clang::LangOptions &languageOptions;
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache;
SourceRangesContainer &sourceRangesContainer; SourceRangesContainer &sourceRangesContainer;
}; };

View File

@@ -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 <algorithm>
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

View File

@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 BlackBerry Limited. All rights reserved. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: KDAB (info@kdab.com) ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
** **
@@ -25,23 +25,23 @@
#pragma once #pragma once
#include <projectexplorer/runconfiguration.h> #include <unordered_set>
namespace Qnx { #include <sourcerangesanddiagnosticsforquerymessage.h>
namespace Internal {
class QnxRunControlFactory : public ProjectExplorer::IRunControlFactory namespace ClangBackEnd {
class SourceRangeFilter
{ {
Q_OBJECT
public: public:
explicit QnxRunControlFactory(QObject *parent = 0); SourceRangeFilter(std::size_t sourcesCount = 0);
bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, SourceRangesAndDiagnosticsForQueryMessage
Core::Id mode) const override; removeDuplicates(SourceRangesAndDiagnosticsForQueryMessage &&message);
ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, void removeDuplicates(SourceRangeWithTextContainers &sourceRanges);
Core::Id mode, QString *errorMessage) override;
private:
std::unordered_set<SourceRangeWithTextContainer> m_collectedSourceRanges;
}; };
} // namespace Internal } // namespace ClangBackEnd
} // namespace Qnx

View File

@@ -29,7 +29,10 @@
#include <clangquery.h> #include <clangquery.h>
#include <mutex>
using ClangBackEnd::ClangQuery; using ClangBackEnd::ClangQuery;
using ClangBackEnd::StringCache;
using testing::IsEmpty; using testing::IsEmpty;
using testing::Not; using testing::Not;
@@ -43,8 +46,9 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
::ClangQuery simpleFunctionQuery; StringCache<Utils::PathString, std::mutex> filePathCache;
::ClangQuery simpleClassQuery; ::ClangQuery simpleFunctionQuery{filePathCache};
::ClangQuery simpleClassQuery{filePathCache};
}; };
using ClangQuerySlowTest = ClangQuery; using ClangQuerySlowTest = ClangQuery;
@@ -77,7 +81,7 @@ TEST_F(ClangQuerySlowTest, RootSourceRangeForSimpleFunctionDeclarationRange)
TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) 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.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "#include \"unsaved.h\"", {"cc", "query_simplefunction.cpp", "-std=c++14"});
query.setQuery("functionDecl()"); query.setQuery("functionDecl()");
ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, "void unsaved();", {}}; 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 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.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "void f() {}", {"cc", "query_simplefunction.cpp", "-std=c++14"});
query.setQuery("functionDecl()"); query.setQuery("functionDecl()");
ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void unsaved();", {}}; ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void unsaved();", {}};

View File

@@ -25,6 +25,8 @@
#include "googletest.h" #include "googletest.h"
#include "filesystem-utilities.h"
#include "sourcerangecontainer-matcher.h" #include "sourcerangecontainer-matcher.h"
#include <filecontainerv2.h> #include <filecontainerv2.h>
@@ -38,6 +40,7 @@ using testing::AtLeast;
using testing::AtMost; using testing::AtMost;
using testing::Contains; using testing::Contains;
using testing::Each; using testing::Each;
using testing::ElementsAre;
using testing::Eq; using testing::Eq;
using testing::Ge; using testing::Ge;
using testing::IsEmpty; using testing::IsEmpty;
@@ -47,6 +50,7 @@ using testing::Pair;
using testing::PrintToString; using testing::PrintToString;
using testing::Property; using testing::Property;
using testing::SizeIs; using testing::SizeIs;
using testing::UnorderedElementsAre;
using testing::_; using testing::_;
using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::FileContainer;
@@ -71,34 +75,42 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f()\n {}"}; ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache;
Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(), 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();"}; Utils::SmallString unsavedContent{"void f();"};
FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"},
unsavedContent.clone(), unsavedContent.clone(),
{}}; {}};
Utils::SmallString query{"functionDecl()"}; Utils::SmallString query{"functionDecl()"};
ClangBackEnd::ClangQueryGatherer gatherer{{source.clone()}, {unsaved.clone()}, query.clone()}; ClangBackEnd::ClangQueryGatherer gatherer{&filePathCache, {source.clone()}, {unsaved.clone()}, query.clone()};
ClangBackEnd::ClangQueryGatherer manyGatherer{{source.clone(), source.clone(), source.clone()}, ClangBackEnd::ClangQueryGatherer manyGatherer{&filePathCache,
{source3.clone(), source2.clone(), source.clone()},
{unsaved.clone()}, {unsaved.clone()},
query.clone()}; query.clone()};
}; };
TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnostics) 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, ASSERT_THAT(sourceRangesAndDiagnostics,
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers, Property(&SourceRangesContainer::sourceRangeWithTextContainers,
Contains(IsSourceRangeWithText(2, 1, 3, 4, "void f()\n {}"))))); Contains(IsSourceRangeWithText(2, 1, 2, 12, "void f() {}")))));
} }
TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnosticssWithUnsavedContent) 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, ASSERT_THAT(sourceRangesAndDiagnostics,
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
@@ -113,7 +125,7 @@ TEST_F(ClangQueryGatherer, CanCreateSourceRangesAndDiagnosticsIfItHasSources)
TEST_F(ClangQueryGatherer, CanNotCreateSourceRangesAndDiagnosticsIfItHasNoSources) TEST_F(ClangQueryGatherer, CanNotCreateSourceRangesAndDiagnosticsIfItHasNoSources)
{ {
ClangBackEnd::ClangQueryGatherer empthyGatherer{{}, {unsaved.clone()}, query.clone()}; ClangBackEnd::ClangQueryGatherer empthyGatherer{&filePathCache, {}, {unsaved.clone()}, query.clone()};
ASSERT_FALSE(empthyGatherer.canCreateSourceRangesAndDiagnostics()); ASSERT_FALSE(empthyGatherer.canCreateSourceRangesAndDiagnostics());
} }
@@ -174,14 +186,18 @@ TEST_F(ClangQueryGatherer, AfterStartCreateSourceRangesAndDiagnosticsMessagesGet
manyGatherer.startCreateNextSourceRangesAndDiagnosticsMessages(); manyGatherer.startCreateNextSourceRangesAndDiagnosticsMessages();
ASSERT_THAT(manyGatherer.allCurrentProcessedMessages(), ASSERT_THAT(manyGatherer.allCurrentProcessedMessages(),
Each( UnorderedElementsAre(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers, 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) TEST_F(ClangQueryGatherer, GetFinishedMessages)
{ {
manyGatherer.startCreateNextSourceRangesAndDiagnosticsMessages(); manyGatherer.startCreateNextSourceRangesAndDiagnosticsMessages();
@@ -191,10 +207,17 @@ TEST_F(ClangQueryGatherer, GetFinishedMessages)
ASSERT_THAT(messages, ASSERT_THAT(messages,
AllOf(SizeIs(2), AllOf(SizeIs(2),
Each( UnorderedElementsAre(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers, 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) TEST_F(ClangQueryGatherer, GetFinishedMessagesAfterSecondPass)
@@ -209,10 +232,38 @@ TEST_F(ClangQueryGatherer, GetFinishedMessagesAfterSecondPass)
ASSERT_THAT(messages, ASSERT_THAT(messages,
AllOf(SizeIs(1), AllOf(SizeIs(1),
Each( ElementsAre(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers, 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) TEST_F(ClangQueryGatherer, AfterGetFinishedMessagesFuturesAreReduced)

View File

@@ -0,0 +1,4 @@
#include "query_simplefunction2.h"
int function();

View File

@@ -0,0 +1,2 @@
int header();

View File

@@ -0,0 +1,4 @@
#include "query_simplefunction2.h"
int function();

View File

@@ -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 <filepath.h>
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(), "");
}
}

View File

@@ -73,7 +73,7 @@ protected:
PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h";
PathString header2Path = TESTDATA_DIR "/includecollector_header2.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"; PathString generatedFilePath = TESTDATA_DIR "/includecollector_generated_file.h";
ProjectPartContainer projectPart1{"project1", ProjectPartContainer projectPart1{"project1",
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},

View File

@@ -25,6 +25,7 @@
#include "googletest.h" #include "googletest.h"
#include "filesystem-utilities.h"
#include "mockrefactoringclient.h" #include "mockrefactoringclient.h"
#include "sourcerangecontainer-matcher.h" #include "sourcerangecontainer-matcher.h"
@@ -40,6 +41,7 @@ namespace {
using testing::AllOf; using testing::AllOf;
using testing::Contains; using testing::Contains;
using testing::NiceMock; using testing::NiceMock;
using testing::Not;
using testing::Pair; using testing::Pair;
using testing::PrintToString; using testing::PrintToString;
using testing::Property; using testing::Property;
@@ -77,7 +79,8 @@ protected:
Utils::SmallString sourceContent{"void f()\n {}"}; Utils::SmallString sourceContent{"void f()\n {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(), sourceContent.clone(),
{"cc", "query_simplefunction.cpp"}}; {"cc", toNativePath(TESTDATA_DIR"/query_simplefunction.cpp")}};
int processingSlotCount = 2;
}; };
using RefactoringServerSlowTest = RefactoringServer; using RefactoringServerSlowTest = RefactoringServer;
@@ -153,8 +156,12 @@ TEST_F(RefactoringServerSlowTest, RequestTwoSourceRangesAndDiagnosticsForQueryMe
sourceRangesAndDiagnosticsForQueryMessage( sourceRangesAndDiagnosticsForQueryMessage(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers, Property(&SourceRangesContainer::sourceRangeWithTextContainers,
Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))) Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent))))));
.Times(2); EXPECT_CALL(mockRefactoringClient,
sourceRangesAndDiagnosticsForQueryMessage(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
Not(Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))));
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
} }
@@ -163,7 +170,7 @@ TEST_F(RefactoringServerVerySlowTest, RequestManySourceRangesAndDiagnosticsForQu
{ {
std::vector<FileContainer> sources; std::vector<FileContainer> sources;
std::fill_n(std::back_inserter(sources), std::fill_n(std::back_inserter(sources),
std::thread::hardware_concurrency() + 3, processingSlotCount + 3,
source.clone()); source.clone());
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
std::move(sources), std::move(sources),
@@ -173,8 +180,13 @@ TEST_F(RefactoringServerVerySlowTest, RequestManySourceRangesAndDiagnosticsForQu
sourceRangesAndDiagnosticsForQueryMessage( sourceRangesAndDiagnosticsForQueryMessage(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers, Property(&SourceRangesContainer::sourceRangeWithTextContainers,
Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))) Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent))))));
.Times(std::thread::hardware_concurrency() + 3); 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)); refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
} }
@@ -237,6 +249,7 @@ void RefactoringServer::SetUp()
void RefactoringServer::TearDown() void RefactoringServer::TearDown()
{ {
refactoringServer.setGathererProcessingSlotCount(uint(processingSlotCount));
refactoringServer.waitThatSourceRangesAndDiagnosticsForQueryMessagesAreFinished(); refactoringServer.waitThatSourceRangesAndDiagnosticsForQueryMessagesAreFinished();
} }

View File

@@ -28,23 +28,12 @@
#include <sourcerangeextractor.h> #include <sourcerangeextractor.h>
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#include <stringcache.h>
#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 <clang/Basic/SourceManager.h> #include <clang/Basic/SourceManager.h>
#include <clang/Lex/Lexer.h> #include <clang/Lex/Lexer.h>
#if defined(__GNUC__) #include <mutex>
# pragma GCC diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
using testing::Contains; using testing::Contains;
using ::testing::Eq; using ::testing::Eq;
@@ -65,7 +54,8 @@ protected:
TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}};
ClangBackEnd::SourceRangesContainer sourceRangesContainer; ClangBackEnd::SourceRangesContainer sourceRangesContainer;
const clang::SourceManager &sourceManager{clangTool.sourceManager()}; const clang::SourceManager &sourceManager{clangTool.sourceManager()};
ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), sourceRangesContainer}; ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache;
ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), filePathCache, sourceRangesContainer};
clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()); clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID());
clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4);
clang::SourceRange sourceRange{startLocation, endLocation}; clang::SourceRange sourceRange{startLocation, endLocation};
@@ -76,7 +66,7 @@ using SourceRangeExtractorSlowTest = SourceRangeExtractor;
TEST_F(SourceRangeExtractorSlowTest, ExtractSourceRangeContainer) 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); extractor.addSourceRange(sourceRange);

View File

@@ -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 <sourcerangefilter.h>
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));
}
}

View File

@@ -63,6 +63,8 @@ SOURCES += \
projectupdater-test.cpp \ projectupdater-test.cpp \
pchmanagerserver-test.cpp \ pchmanagerserver-test.cpp \
pchmanagerclientserverinprocess-test.cpp \ pchmanagerclientserverinprocess-test.cpp \
filepath-test.cpp \
sourcerangefilter-test.cpp
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
SOURCES += \ SOURCES += \