Clang: Use FilePathId in ChangedFilePathCompressor

Change-Id: I622d9196ec12c6fe6e07ef9c953586f2f40b9a5c
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2017-12-13 17:35:00 +01:00
parent bb07cc280c
commit 98fa7cbb3f
9 changed files with 86 additions and 101 deletions

View File

@@ -27,10 +27,13 @@
#include "clangsupport_global.h" #include "clangsupport_global.h"
#include <filepath.h> #include <filepathid.h>
#include <filepathcache.h>
#include <QTimer> #include <QTimer>
#include <filepathcachinginterface.h>
#include <functional> #include <functional>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -39,7 +42,8 @@ template <typename Timer>
class ChangedFilePathCompressor class ChangedFilePathCompressor
{ {
public: public:
ChangedFilePathCompressor() ChangedFilePathCompressor(FilePathCachingInterface &filePathCache)
: m_filePathCache(filePathCache)
{ {
m_timer.setSingleShot(true); m_timer.setSingleShot(true);
} }
@@ -50,21 +54,26 @@ public:
void addFilePath(const QString &filePath) void addFilePath(const QString &filePath)
{ {
m_filePaths.emplace_back(filePath); FilePathId filePathId = m_filePathCache.filePathId(FilePath(filePath));
auto found = std::lower_bound(m_filePaths.begin(), m_filePaths.end(), filePathId);
if (found == m_filePaths.end() || *found != filePathId)
m_filePaths.insert(found, filePathId);
restartTimer(); restartTimer();
} }
FilePaths takeFilePaths() FilePathIds takeFilePathIds()
{ {
return std::move(m_filePaths); return std::move(m_filePaths);
} }
virtual void setCallback(std::function<void(ClangBackEnd::FilePaths &&)> &&callback) virtual void setCallback(std::function<void(ClangBackEnd::FilePathIds &&)> &&callback)
{ {
QObject::connect(&m_timer, QObject::connect(&m_timer,
&Timer::timeout, &Timer::timeout,
[this, callback=std::move(callback)] { callback(takeFilePaths()); }); [this, callback=std::move(callback)] { callback(takeFilePathIds()); });
} }
unittest_public: unittest_public:
@@ -79,8 +88,9 @@ unittest_public:
} }
private: private:
FilePaths m_filePaths; FilePathIds m_filePaths;
Timer m_timer; Timer m_timer;
FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -77,21 +77,22 @@ class ClangPathWatcher : public ClangPathWatcherInterface
public: public:
ClangPathWatcher(FilePathCachingInterface &pathCache, ClangPathWatcher(FilePathCachingInterface &pathCache,
ClangPathWatcherNotifier *notifier=nullptr) ClangPathWatcherNotifier *notifier=nullptr)
: m_pathCache(pathCache), : m_changedFilePathCompressor(pathCache),
m_pathCache(pathCache),
m_notifier(notifier) m_notifier(notifier)
{ {
QObject::connect(&m_fileSystemWatcher, QObject::connect(&m_fileSystemWatcher,
&FileSystemWatcher::fileChanged, &FileSystemWatcher::fileChanged,
[&] (const QString &filePath) { compressChangedFilePath(filePath); }); [&] (const QString &filePath) { compressChangedFilePath(filePath); });
m_changedFilePathCompressor.setCallback([&] (ClangBackEnd::FilePaths &&filePaths) { m_changedFilePathCompressor.setCallback([&] (ClangBackEnd::FilePathIds &&filePathIds) {
addChangedPathForFilePath(std::move(filePaths)); addChangedPathForFilePath(std::move(filePathIds));
}); });
} }
~ClangPathWatcher() ~ClangPathWatcher()
{ {
m_changedFilePathCompressor.setCallback([&] (FilePaths &&) {}); m_changedFilePathCompressor.setCallback([&] (FilePathIds &&) {});
} }
void updateIdPaths(const std::vector<IdPaths> &idPaths) override void updateIdPaths(const std::vector<IdPaths> &idPaths) override
@@ -376,14 +377,12 @@ unittest_public:
m_changedFilePathCompressor.addFilePath(filePath); m_changedFilePathCompressor.addFilePath(filePath);
} }
WatcherEntries watchedEntriesForPaths(ClangBackEnd::FilePaths &&filePaths) WatcherEntries watchedEntriesForPaths(ClangBackEnd::FilePathIds &&filePathIds)
{ {
FilePathIds pathIds = m_pathCache.filePathIds(filePaths);
WatcherEntries foundEntries; WatcherEntries foundEntries;
foundEntries.reserve(pathIds.size()); foundEntries.reserve(filePathIds.size());
for (FilePathId pathId : pathIds) { for (FilePathId pathId : filePathIds) {
auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId); auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId);
foundEntries.insert(foundEntries.end(), range.first, range.second); foundEntries.insert(foundEntries.end(), range.first, range.second);
} }
@@ -415,10 +414,10 @@ unittest_public:
return std::move(ids); return std::move(ids);
} }
void addChangedPathForFilePath(ClangBackEnd::FilePaths &&filePaths) void addChangedPathForFilePath(ClangBackEnd::FilePathIds &&filePathIds)
{ {
if (m_notifier) { if (m_notifier) {
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(filePaths)); WatcherEntries foundEntries = watchedEntriesForPaths(std::move(filePathIds));
Utils::SmallStringVector changedIds = idsForWatcherEntries(foundEntries); Utils::SmallStringVector changedIds = idsForWatcherEntries(foundEntries);
@@ -439,7 +438,7 @@ unittest_public:
private: private:
IdCache m_idCache; IdCache m_idCache;
WatcherEntries m_watchedEntries; WatcherEntries m_watchedEntries;
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor; ChangedFilePathCompressor<Timer> m_changedFilePathCompressor{};
FileSystemWatcher m_fileSystemWatcher; FileSystemWatcher m_fileSystemWatcher;
FilePathCachingInterface &m_pathCache; FilePathCachingInterface &m_pathCache;
ClangPathWatcherNotifier *m_notifier; ClangPathWatcherNotifier *m_notifier;

View File

@@ -25,7 +25,11 @@
#include "googletest.h" #include "googletest.h"
#include <mockchangedfilepathcompressor.h> #include "mocktimer.h"
#include <changedfilepathcompressor.h>
#include <filepathcaching.h>
#include <refactoringdatabaseinitializer.h>
namespace { namespace {
@@ -35,56 +39,65 @@ using testing::IsEmpty;
using testing::NiceMock; using testing::NiceMock;
using ClangBackEnd::FilePath; using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathId;
class ChangedFilePathCompressor : public testing::Test class ChangedFilePathCompressor : public testing::Test
{ {
protected: protected:
void SetUp(); void SetUp()
{
compressor.setCallback(mockCompressor.AsStdFunction());
}
FilePathId filePathId(const QString &filePath)
{
Utils::SmallString utf8FilePath{filePath};
return filePathCache.filePathId(ClangBackEnd::FilePathView{utf8FilePath});
}
protected: protected:
NiceMock<MockChangedFilePathCompressor> mockCompressor; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::ChangedFilePathCompressor<FakeTimer> compressor; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
NiceMock<MockFunction<void (const ClangBackEnd::FilePathIds &filePathIds)>> mockCompressor;
ClangBackEnd::ChangedFilePathCompressor<NiceMock<MockTimer>> compressor{filePathCache};
NiceMock<MockTimer> &mockTimer = compressor.timer();
QString filePath1{"filePath1"}; QString filePath1{"filePath1"};
QString filePath2{"filePath2"}; QString filePath2{"filePath2"};
}; };
TEST_F(ChangedFilePathCompressor, AddFilePath) TEST_F(ChangedFilePathCompressor, AddFilePath)
{ {
mockCompressor.addFilePath(filePath1); compressor.addFilePath(filePath1);
ASSERT_THAT(mockCompressor.takeFilePaths(), ElementsAre(FilePath{filePath1})); ASSERT_THAT(compressor.takeFilePathIds(), ElementsAre(filePathId(filePath1)));
} }
TEST_F(ChangedFilePathCompressor, NoFilePathsAferTakenThem) TEST_F(ChangedFilePathCompressor, NoFilePathsAferTakenThem)
{ {
mockCompressor.addFilePath(filePath1); compressor.addFilePath(filePath1);
mockCompressor.takeFilePaths(); compressor.takeFilePathIds();
ASSERT_THAT(mockCompressor.takeFilePaths(), IsEmpty()); ASSERT_THAT(compressor.takeFilePathIds(), IsEmpty());
} }
TEST_F(ChangedFilePathCompressor, CallRestartTimerAfterAddingPath) TEST_F(ChangedFilePathCompressor, CallRestartTimerAfterAddingPath)
{ {
EXPECT_CALL(mockCompressor, restartTimer()); EXPECT_CALL(mockTimer, start(20));
mockCompressor.addFilePath(filePath1); compressor.addFilePath(filePath1);
} }
TEST_F(ChangedFilePathCompressor, CallTimeOutAfterAddingPath) TEST_F(ChangedFilePathCompressor, CallTimeOutAfterAddingPath)
{ {
EXPECT_CALL(mockCompressor, callbackCalled(ElementsAre(FilePath{filePath1}, FilePath{filePath2}))); auto id1 = filePathId(filePath1);
auto id2 = filePathId(filePath2);
EXPECT_CALL(mockCompressor, Call(ElementsAre(id1, id2)));
compressor.addFilePath(filePath1); compressor.addFilePath(filePath1);
compressor.addFilePath(filePath2); compressor.addFilePath(filePath2);
} }
void ChangedFilePathCompressor::SetUp()
{
compressor.setCallback([&] (ClangBackEnd::FilePaths &&filePaths) {
mockCompressor.callbackCalled(filePaths);
});
}
} }

View File

@@ -25,7 +25,7 @@
#include "googletest.h" #include "googletest.h"
#include "faketimer.h" #include "mocktimer.h"
#include "mockfilepathcaching.h" #include "mockfilepathcaching.h"
#include "mockqfilesystemwatcher.h" #include "mockqfilesystemwatcher.h"
#include "mockclangpathwatchernotifier.h" #include "mockclangpathwatchernotifier.h"
@@ -42,7 +42,7 @@ using testing::IsEmpty;
using testing::SizeIs; using testing::SizeIs;
using testing::NiceMock; using testing::NiceMock;
using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>; using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, NiceMock<MockTimer>>;
using ClangBackEnd::WatcherEntry; using ClangBackEnd::WatcherEntry;
using ClangBackEnd::FilePath; using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathView; using ClangBackEnd::FilePathView;

View File

@@ -31,6 +31,7 @@ using testing::_;
using testing::AllOf; using testing::AllOf;
using testing::AnyNumber; using testing::AnyNumber;
using testing::AnyOf; using testing::AnyOf;
using testing::Assign;
using testing::Contains; using testing::Contains;
using testing::ElementsAre; using testing::ElementsAre;
using testing::Field; using testing::Field;
@@ -38,6 +39,7 @@ using testing::HasSubstr;
using testing::InSequence; using testing::InSequence;
using testing::IsEmpty; using testing::IsEmpty;
using testing::Mock; using testing::Mock;
using testing::MockFunction;
using testing::NiceMock; using testing::NiceMock;
using testing::Not; using testing::Not;
using testing::Pair; using testing::Pair;

View File

@@ -1,43 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 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.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include "faketimer.h"
#include <changedfilepathcompressor.h>
class MockChangedFilePathCompressor : public ClangBackEnd::ChangedFilePathCompressor<FakeTimer>
{
public:
MOCK_METHOD0(restartTimer,
void ());
MOCK_METHOD1(callbackCalled,
void (const ClangBackEnd::FilePaths &filePaths));
};

View File

@@ -23,23 +23,23 @@
** **
****************************************************************************/ ****************************************************************************/
#include "faketimer.h" #include "mocktimer.h"
FakeTimer::~FakeTimer() MockTimer::MockTimer()
{
ON_CALL(*this, start(_)).WillByDefault(Assign(&m_isStarted, true));
}
MockTimer::~MockTimer()
{ {
emitTimoutIfStarted(); emitTimoutIfStarted();
} }
void FakeTimer::start(int) void MockTimer::setSingleShot(bool)
{
m_isStarted = true;
}
void FakeTimer::setSingleShot(bool)
{ {
} }
void FakeTimer::emitTimoutIfStarted() void MockTimer::emitTimoutIfStarted()
{ {
if (m_isStarted) if (m_isStarted)
emit timeout(); emit timeout();

View File

@@ -24,16 +24,21 @@
****************************************************************************/ ****************************************************************************/
#pragma once #pragma once
#include "googletest.h"
#include <QObject> #include <QObject>
class FakeTimer : public QObject class MockTimer : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
~FakeTimer(); MockTimer();
~MockTimer();
MOCK_METHOD1(start,
void (int));
void start(int interval);
void setSingleShot(bool); void setSingleShot(bool);
void emitTimoutIfStarted(); void emitTimoutIfStarted();

View File

@@ -48,7 +48,6 @@ SOURCES += \
cppprojectinfogenerator-test.cpp \ cppprojectinfogenerator-test.cpp \
cppprojectpartchooser-test.cpp \ cppprojectpartchooser-test.cpp \
fakeprocess.cpp \ fakeprocess.cpp \
faketimer.cpp \
filepath-test.cpp \ filepath-test.cpp \
filepathview-test.cpp \ filepathview-test.cpp \
gtest-creator-printing.cpp \ gtest-creator-printing.cpp \
@@ -85,7 +84,8 @@ SOURCES += \
filepathstoragesqlitestatementfactory-test.cpp \ filepathstoragesqlitestatementfactory-test.cpp \
processcreator-test.cpp \ processcreator-test.cpp \
nativefilepath-test.cpp \ nativefilepath-test.cpp \
nativefilepathview-test.cpp nativefilepathview-test.cpp \
mocktimer.cpp
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
SOURCES += \ SOURCES += \
@@ -180,13 +180,11 @@ HEADERS += \
dynamicastmatcherdiagnosticcontainer-matcher.h \ dynamicastmatcherdiagnosticcontainer-matcher.h \
eventspy.h \ eventspy.h \
fakeprocess.h \ fakeprocess.h \
faketimer.h \
filesystem-utilities.h \ filesystem-utilities.h \
googletest.h \ googletest.h \
gtest-creator-printing.h \ gtest-creator-printing.h \
gtest-qt-printing.h \ gtest-qt-printing.h \
mimedatabase-utilities.h \ mimedatabase-utilities.h \
mockchangedfilepathcompressor.h \
mockclangcodemodelclient.h \ mockclangcodemodelclient.h \
mockclangcodemodelserver.h \ mockclangcodemodelserver.h \
mockclangpathwatcher.h \ mockclangpathwatcher.h \
@@ -221,7 +219,8 @@ HEADERS += \
unittest-utility-functions.h \ unittest-utility-functions.h \
mocksymbolquery.h \ mocksymbolquery.h \
runprojectcreateorupdate-utility.h \ runprojectcreateorupdate-utility.h \
rundocumentparse-utility.h rundocumentparse-utility.h \
mocktimer.h
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
HEADERS += \ HEADERS += \
chunksreportedmonitor.h \ chunksreportedmonitor.h \