2017-01-30 11:24:46 +01:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** 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 "clangpathwatcherinterface.h"
|
|
|
|
|
#include "clangpathwatchernotifier.h"
|
2017-01-31 11:14:54 +01:00
|
|
|
#include "changedfilepathcompressor.h"
|
2017-10-25 17:51:39 +02:00
|
|
|
#include "filepathcachinginterface.h"
|
|
|
|
|
#include "stringcache.h"
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
#include <QTimer>
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
namespace ClangBackEnd {
|
|
|
|
|
|
|
|
|
|
class WatcherEntry
|
|
|
|
|
{
|
|
|
|
|
public:
|
2017-09-21 11:43:59 +02:00
|
|
|
int id;
|
|
|
|
|
FilePathId pathId;
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
friend bool operator==(const WatcherEntry &first, const WatcherEntry &second)
|
|
|
|
|
{
|
2017-09-21 11:43:59 +02:00
|
|
|
return first.id == second.id && first.pathId == second.pathId;
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
friend bool operator<(const WatcherEntry &first, const WatcherEntry &second)
|
|
|
|
|
{
|
2017-09-21 11:43:59 +02:00
|
|
|
return std::tie(first.pathId, first.id) < std::tie(second.pathId, second.id);
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
friend bool operator<(const WatcherEntry &entry, FilePathId pathId)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2017-09-21 11:43:59 +02:00
|
|
|
return entry.pathId < pathId;
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
friend bool operator<(FilePathId pathId, const WatcherEntry &entry)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2017-09-21 11:43:59 +02:00
|
|
|
return pathId < entry.pathId;
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
using WatcherEntries = std::vector<WatcherEntry>;
|
|
|
|
|
|
2017-08-22 13:05:31 +02:00
|
|
|
using IdCache = StringCache<Utils::SmallString,
|
2017-09-21 11:43:59 +02:00
|
|
|
int,
|
2017-08-22 13:05:31 +02:00
|
|
|
NonLockingMutex,
|
|
|
|
|
decltype(&Utils::compare),
|
|
|
|
|
Utils::compare>;
|
2017-08-21 12:00:27 +02:00
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
template <typename FileSystemWatcher,
|
|
|
|
|
typename Timer>
|
2017-01-30 11:24:46 +01:00
|
|
|
class ClangPathWatcher : public ClangPathWatcherInterface
|
|
|
|
|
{
|
|
|
|
|
public:
|
2017-09-21 11:43:59 +02:00
|
|
|
ClangPathWatcher(FilePathCachingInterface &pathCache,
|
2017-01-30 11:24:46 +01:00
|
|
|
ClangPathWatcherNotifier *notifier=nullptr)
|
2017-12-13 17:35:00 +01:00
|
|
|
: m_changedFilePathCompressor(pathCache),
|
|
|
|
|
m_pathCache(pathCache),
|
2017-01-30 11:24:46 +01:00
|
|
|
m_notifier(notifier)
|
|
|
|
|
{
|
|
|
|
|
QObject::connect(&m_fileSystemWatcher,
|
|
|
|
|
&FileSystemWatcher::fileChanged,
|
2017-01-31 11:14:54 +01:00
|
|
|
[&] (const QString &filePath) { compressChangedFilePath(filePath); });
|
|
|
|
|
|
2017-12-13 17:35:00 +01:00
|
|
|
m_changedFilePathCompressor.setCallback([&] (ClangBackEnd::FilePathIds &&filePathIds) {
|
|
|
|
|
addChangedPathForFilePath(std::move(filePathIds));
|
2017-01-31 11:14:54 +01:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ClangPathWatcher()
|
|
|
|
|
{
|
2017-12-13 17:35:00 +01:00
|
|
|
m_changedFilePathCompressor.setCallback([&] (FilePathIds &&) {});
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateIdPaths(const std::vector<IdPaths> &idPaths) override
|
|
|
|
|
{
|
|
|
|
|
auto entriesAndIds = convertIdPathsToWatcherEntriesAndIds(idPaths);
|
|
|
|
|
|
|
|
|
|
addEntries(entriesAndIds.first);
|
|
|
|
|
removeUnusedEntries(entriesAndIds.first, entriesAndIds.second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void removeIds(const Utils::SmallStringVector &ids) override
|
|
|
|
|
{
|
|
|
|
|
auto removedEntries = removeIdsFromWatchedEntries(convertToIdNumbers(ids));
|
|
|
|
|
|
|
|
|
|
auto filteredPaths = filterNotWatchedPaths(removedEntries);
|
|
|
|
|
|
|
|
|
|
if (!filteredPaths.empty())
|
|
|
|
|
m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setNotifier(ClangPathWatcherNotifier *notifier) override
|
|
|
|
|
{
|
|
|
|
|
m_notifier = notifier;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-02 17:14:53 +01:00
|
|
|
unittest_public:
|
2017-01-30 11:24:46 +01:00
|
|
|
static std::vector<uint> idsFromIdPaths(const std::vector<IdPaths> &idPaths)
|
|
|
|
|
{
|
|
|
|
|
std::vector<uint> ids;
|
|
|
|
|
ids.reserve(idPaths.size());
|
|
|
|
|
|
|
|
|
|
auto extractId = [] (const IdPaths &idPath) {
|
|
|
|
|
return idPath.id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::transform(idPaths.begin(),
|
|
|
|
|
idPaths.end(),
|
|
|
|
|
std::back_inserter(ids),
|
|
|
|
|
extractId);
|
|
|
|
|
|
|
|
|
|
std::sort(ids.begin(), ids.end());
|
|
|
|
|
|
|
|
|
|
return ids;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
std::vector<int> convertToIdNumbers(const Utils::SmallStringVector &ids)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2017-09-21 11:43:59 +02:00
|
|
|
std::vector<int> idNumbers = m_idCache.stringIds(ids);
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
std::sort(idNumbers.begin(), idNumbers.end());
|
|
|
|
|
|
|
|
|
|
return idNumbers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
|
|
|
|
|
{
|
|
|
|
|
auto sumSize = [] (std::size_t size, const IdPaths &idPath) {
|
2017-09-21 11:43:59 +02:00
|
|
|
return size + idPath.filePathIds.size();
|
2017-01-30 11:24:46 +01:00
|
|
|
};
|
|
|
|
|
|
2017-04-26 11:47:38 +03:00
|
|
|
return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize);
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
std::pair<WatcherEntries, std::vector<int>>
|
2017-01-30 11:24:46 +01:00
|
|
|
convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
|
|
|
|
|
{
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries entries;
|
2017-01-30 11:24:46 +01:00
|
|
|
entries.reserve(sizeOfIdPaths(idPaths));
|
2017-09-21 11:43:59 +02:00
|
|
|
std::vector<int> ids;
|
2017-01-30 11:24:46 +01:00
|
|
|
ids.reserve(ids.size());
|
|
|
|
|
|
|
|
|
|
auto outputIterator = std::back_inserter(entries);
|
|
|
|
|
|
|
|
|
|
for (const IdPaths &idPath : idPaths)
|
|
|
|
|
{
|
2017-09-21 11:43:59 +02:00
|
|
|
int id = m_idCache.stringId(idPath.id);
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
ids.push_back(id);
|
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
outputIterator = std::transform(idPath.filePathIds.begin(),
|
|
|
|
|
idPath.filePathIds.end(),
|
2017-01-30 11:24:46 +01:00
|
|
|
outputIterator,
|
2017-09-21 11:43:59 +02:00
|
|
|
[&] (FilePathId pathId) { return WatcherEntry{id, pathId}; });
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::sort(entries.begin(), entries.end());
|
|
|
|
|
std::sort(ids.begin(), ids.end());
|
|
|
|
|
|
|
|
|
|
return {entries, ids};
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
void addEntries(const WatcherEntries &entries)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
auto newEntries = notWatchedEntries(entries);
|
|
|
|
|
|
|
|
|
|
auto filteredPaths = filterNotWatchedPaths(newEntries);
|
|
|
|
|
|
|
|
|
|
mergeToWatchedEntries(newEntries);
|
|
|
|
|
|
|
|
|
|
if (!filteredPaths.empty())
|
|
|
|
|
m_fileSystemWatcher.addPaths(convertWatcherEntriesToQStringList(filteredPaths));
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
void removeUnusedEntries(const WatcherEntries &entries,
|
2017-09-21 11:43:59 +02:00
|
|
|
const std::vector<int> &ids)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
|
|
|
|
|
|
|
|
|
|
removeFromWatchedEntries(oldEntries);
|
|
|
|
|
|
|
|
|
|
auto filteredPaths = filterNotWatchedPaths(oldEntries);
|
|
|
|
|
|
|
|
|
|
if (!filteredPaths.empty())
|
|
|
|
|
m_fileSystemWatcher.removePaths(convertWatcherEntriesToQStringList(filteredPaths));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileSystemWatcher &fileSystemWatcher()
|
|
|
|
|
{
|
|
|
|
|
return m_fileSystemWatcher;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList convertWatcherEntriesToQStringList(
|
2017-01-31 11:14:54 +01:00
|
|
|
const WatcherEntries &watcherEntries)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
QStringList paths;
|
|
|
|
|
paths.reserve(int(watcherEntries.size()));
|
|
|
|
|
|
|
|
|
|
std::transform(watcherEntries.begin(),
|
|
|
|
|
watcherEntries.end(),
|
|
|
|
|
std::back_inserter(paths),
|
2017-09-21 11:43:59 +02:00
|
|
|
[&] (const WatcherEntry &entry) {
|
|
|
|
|
return QString(m_pathCache.filePath(entry.pathId).path());
|
|
|
|
|
});
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
return paths;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename Compare>
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries notWatchedEntries(const WatcherEntries &entries,
|
2017-01-30 11:24:46 +01:00
|
|
|
Compare compare) const
|
|
|
|
|
{
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries notWatchedEntries;
|
2017-01-30 11:24:46 +01:00
|
|
|
notWatchedEntries.reserve(entries.size());
|
|
|
|
|
|
|
|
|
|
std::set_difference(entries.begin(),
|
|
|
|
|
entries.end(),
|
|
|
|
|
m_watchedEntries.cbegin(),
|
|
|
|
|
m_watchedEntries.cend(),
|
|
|
|
|
std::back_inserter(notWatchedEntries),
|
|
|
|
|
compare);
|
|
|
|
|
|
|
|
|
|
return notWatchedEntries;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries notWatchedEntries(const WatcherEntries &entries) const
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
return notWatchedEntries(entries, std::less<WatcherEntry>());
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries notWatchedPaths(const WatcherEntries &entries) const
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
|
2017-09-21 11:43:59 +02:00
|
|
|
return first.pathId < second.pathId;
|
2017-01-30 11:24:46 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return notWatchedEntries(entries, compare);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename Compare>
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries notAnymoreWatchedEntries(
|
|
|
|
|
const WatcherEntries &newEntries,
|
2017-01-30 11:24:46 +01:00
|
|
|
Compare compare) const
|
|
|
|
|
{
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries notAnymoreWatchedEntries;
|
2017-01-30 11:24:46 +01:00
|
|
|
notAnymoreWatchedEntries.reserve(m_watchedEntries.size());
|
|
|
|
|
|
|
|
|
|
std::set_difference(m_watchedEntries.cbegin(),
|
|
|
|
|
m_watchedEntries.cend(),
|
|
|
|
|
newEntries.begin(),
|
|
|
|
|
newEntries.end(),
|
|
|
|
|
std::back_inserter(notAnymoreWatchedEntries),
|
|
|
|
|
compare);
|
|
|
|
|
|
|
|
|
|
return notAnymoreWatchedEntries;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries notAnymoreWatchedEntriesWithIds(
|
|
|
|
|
const WatcherEntries &newEntries,
|
2017-09-21 11:43:59 +02:00
|
|
|
const std::vector<int> &ids) const
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
|
|
|
|
|
|
|
|
|
|
auto newEnd = std::remove_if(oldEntries.begin(),
|
|
|
|
|
oldEntries.end(),
|
|
|
|
|
[&] (WatcherEntry entry) {
|
|
|
|
|
return !std::binary_search(ids.begin(), ids.end(), entry.id);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
oldEntries.erase(newEnd, oldEntries.end());
|
|
|
|
|
|
|
|
|
|
return oldEntries;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
void mergeToWatchedEntries(const WatcherEntries &newEntries)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries newWatchedEntries;
|
2017-01-30 11:24:46 +01:00
|
|
|
newWatchedEntries.reserve(m_watchedEntries.size() + newEntries.size());
|
|
|
|
|
|
|
|
|
|
std::merge(m_watchedEntries.cbegin(),
|
|
|
|
|
m_watchedEntries.cend(),
|
|
|
|
|
newEntries.begin(),
|
|
|
|
|
newEntries.end(),
|
|
|
|
|
std::back_inserter(newWatchedEntries));
|
|
|
|
|
|
|
|
|
|
m_watchedEntries = std::move(newWatchedEntries);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries uniquePaths(const WatcherEntries &pathEntries)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries uniqueEntries;
|
2017-10-25 15:58:02 +02:00
|
|
|
uniqueEntries.reserve(pathEntries.size());
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
|
2017-09-21 11:43:59 +02:00
|
|
|
return first.pathId == second.pathId;
|
2017-01-30 11:24:46 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::unique_copy(pathEntries.begin(),
|
|
|
|
|
pathEntries.end(),
|
|
|
|
|
std::back_inserter(uniqueEntries),
|
|
|
|
|
compare);
|
|
|
|
|
|
|
|
|
|
return uniqueEntries;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries filterNotWatchedPaths(const WatcherEntries &entries)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
return notWatchedPaths(uniquePaths(entries));
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
const WatcherEntries &watchedEntries() const
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
return m_watchedEntries;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
WatcherEntries removeIdsFromWatchedEntries(const std::vector<int> &ids)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
auto keep = [&] (const WatcherEntry &entry) {
|
|
|
|
|
return !std::binary_search(ids.begin(), ids.end(), entry.id);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto found = std::stable_partition(m_watchedEntries.begin(),
|
|
|
|
|
m_watchedEntries.end(),
|
|
|
|
|
keep);
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries removedEntries(found, m_watchedEntries.end());
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
m_watchedEntries.erase(found, m_watchedEntries.end());
|
|
|
|
|
|
|
|
|
|
return removedEntries;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
void removeFromWatchedEntries(const WatcherEntries &oldEntries)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries newWatchedEntries;
|
2017-01-30 11:24:46 +01:00
|
|
|
newWatchedEntries.reserve(m_watchedEntries.size() - oldEntries.size());
|
|
|
|
|
|
|
|
|
|
std::set_difference(m_watchedEntries.cbegin(),
|
|
|
|
|
m_watchedEntries.cend(),
|
|
|
|
|
oldEntries.begin(),
|
|
|
|
|
oldEntries.end(),
|
|
|
|
|
std::back_inserter(newWatchedEntries));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_watchedEntries = newWatchedEntries;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
void compressChangedFilePath(const QString &filePath)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2017-01-31 11:14:54 +01:00
|
|
|
m_changedFilePathCompressor.addFilePath(filePath);
|
|
|
|
|
}
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2017-12-13 17:35:00 +01:00
|
|
|
WatcherEntries watchedEntriesForPaths(ClangBackEnd::FilePathIds &&filePathIds)
|
2017-01-31 11:14:54 +01:00
|
|
|
{
|
|
|
|
|
WatcherEntries foundEntries;
|
2017-12-13 17:35:00 +01:00
|
|
|
foundEntries.reserve(filePathIds.size());
|
2017-01-31 11:14:54 +01:00
|
|
|
|
2017-12-13 17:35:00 +01:00
|
|
|
for (FilePathId pathId : filePathIds) {
|
2017-01-31 11:14:54 +01:00
|
|
|
auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId);
|
|
|
|
|
foundEntries.insert(foundEntries.end(), range.first, range.second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return foundEntries;
|
|
|
|
|
}
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
Utils::SmallStringVector idsForWatcherEntries(const WatcherEntries &foundEntries)
|
|
|
|
|
{
|
|
|
|
|
Utils::SmallStringVector ids;
|
2017-10-25 15:58:02 +02:00
|
|
|
ids.reserve(foundEntries.size());
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
std::transform(foundEntries.begin(),
|
|
|
|
|
foundEntries.end(),
|
|
|
|
|
std::back_inserter(ids),
|
2017-01-30 11:24:46 +01:00
|
|
|
[&] (const WatcherEntry &entry) {
|
2017-08-17 15:24:11 +02:00
|
|
|
return Utils::SmallString(m_idCache.string(entry.id));
|
2017-01-30 11:24:46 +01:00
|
|
|
});
|
|
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
return ids;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Utils::SmallStringVector uniqueIds(Utils::SmallStringVector &&ids)
|
|
|
|
|
{
|
|
|
|
|
std::sort(ids.begin(), ids.end());
|
|
|
|
|
auto newEnd = std::unique(ids.begin(), ids.end());
|
|
|
|
|
ids.erase(newEnd, ids.end());
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2017-01-31 11:14:54 +01:00
|
|
|
return std::move(ids);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 17:35:00 +01:00
|
|
|
void addChangedPathForFilePath(ClangBackEnd::FilePathIds &&filePathIds)
|
2017-01-31 11:14:54 +01:00
|
|
|
{
|
|
|
|
|
if (m_notifier) {
|
2017-12-13 17:35:00 +01:00
|
|
|
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(filePathIds));
|
2017-01-31 11:14:54 +01:00
|
|
|
|
|
|
|
|
Utils::SmallStringVector changedIds = idsForWatcherEntries(foundEntries);
|
|
|
|
|
|
|
|
|
|
m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds)));
|
|
|
|
|
}
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
FilePathCachingInterface &pathCache()
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
return m_pathCache;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-21 12:00:27 +02:00
|
|
|
IdCache &idCache()
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
|
|
|
|
return m_idCache;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2017-08-21 12:00:27 +02:00
|
|
|
IdCache m_idCache;
|
2017-01-31 11:14:54 +01:00
|
|
|
WatcherEntries m_watchedEntries;
|
2017-12-13 17:35:00 +01:00
|
|
|
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor{};
|
2017-01-30 11:24:46 +01:00
|
|
|
FileSystemWatcher m_fileSystemWatcher;
|
2017-09-21 11:43:59 +02:00
|
|
|
FilePathCachingInterface &m_pathCache;
|
2017-01-30 11:24:46 +01:00
|
|
|
ClangPathWatcherNotifier *m_notifier;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace ClangBackEnd
|