aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2019-06-19 15:34:24 +0200
committerMarco Bubke <marco.bubke@qt.io>2019-06-27 12:32:22 +0000
commite777ad57c547abe31b457a95a9dc0b5e39891a79 (patch)
tree8146b34c6e33d70d422879fea9ca88e9381f7eed /src/libs
parente031ada154ba94e13af104a1e32be0f94754ba12 (diff)
Clang: Add reset to ModifiedTimeChecker
We can reset some file once to flag a file dirty if the included file has changed. Change-Id: I8763bb80f65882fba4e70057f569234e77097927 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/clangsupport/clangsupport-lib.pri1
-rw-r--r--src/libs/clangsupport/filestatuscache.cpp54
-rw-r--r--src/libs/clangsupport/modifiedtimechecker.h183
-rw-r--r--src/libs/clangsupport/set_algorithm.h101
-rw-r--r--src/libs/clangsupport/sourceentry.h4
5 files changed, 176 insertions, 167 deletions
diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri
index 9b6bbdf3ee..dc66408e58 100644
--- a/src/libs/clangsupport/clangsupport-lib.pri
+++ b/src/libs/clangsupport/clangsupport-lib.pri
@@ -157,6 +157,7 @@ HEADERS += \
$$PWD/refactoringserverinterface.h \
$$PWD/refactoringserverproxy.h \
$$PWD/referencesmessage.h \
+ $$PWD/set_algorithm.h \
$$PWD/unsavedfilesupdatedmessage.h \
$$PWD/removeprojectpartsmessage.h \
$$PWD/requestannotationsmessage.h \
diff --git a/src/libs/clangsupport/filestatuscache.cpp b/src/libs/clangsupport/filestatuscache.cpp
index 480b745525..e8ed50a833 100644
--- a/src/libs/clangsupport/filestatuscache.cpp
+++ b/src/libs/clangsupport/filestatuscache.cpp
@@ -26,6 +26,8 @@
#include "filestatuscache.h"
#include "filesystem.h"
+#include <set_algorithm.h>
+
#include <utils/algorithm.h>
#include <QDateTime>
@@ -51,49 +53,15 @@ void FileStatusCache::update(FilePathId filePathId)
found->lastModified = m_fileSystem.lastModified(filePathId);
}
-namespace {
-template<class InputIt1, class InputIt2, class Callable>
-void set_intersection_call(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable callable)
-{
- while (first1 != last1 && first2 != last2) {
- if (*first1 < *first2) {
- ++first1;
- } else {
- if (!(*first2 < *first1))
- callable(*first1++);
- ++first2;
- }
- }
-}
-
-template<class InputIt1, class InputIt2, class Callable>
-void set_difference_call(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable callable)
-{
- while (first1 != last1) {
- if (first2 == last2) {
- std::for_each(first1, last1, callable);
- return;
- }
- if (*first1 < *first2) {
- callable(*first1++);
- } else {
- if (!(*first2 < *first1))
- ++first1;
- ++first2;
- }
- }
-}
-} // namespace
-
void FileStatusCache::update(FilePathIds filePathIds)
{
- set_intersection_call(m_cacheEntries.begin(),
+ std::set_intersection(m_cacheEntries.begin(),
m_cacheEntries.end(),
filePathIds.begin(),
filePathIds.end(),
- [&](auto &entry) {
+ make_iterator([&](auto &entry) {
entry.lastModified = m_fileSystem.lastModified(entry.filePathId);
- });
+ }));
}
FilePathIds FileStatusCache::modified(FilePathIds filePathIds) const
@@ -101,30 +69,30 @@ FilePathIds FileStatusCache::modified(FilePathIds filePathIds) const
FilePathIds modifiedFilePathIds;
modifiedFilePathIds.reserve(filePathIds.size());
- set_intersection_call(m_cacheEntries.begin(),
+ std::set_intersection(m_cacheEntries.begin(),
m_cacheEntries.end(),
filePathIds.begin(),
filePathIds.end(),
- [&](auto &entry) {
+ make_iterator([&](auto &entry) {
auto newLastModified = m_fileSystem.lastModified(entry.filePathId);
if (newLastModified > entry.lastModified) {
modifiedFilePathIds.push_back(entry.filePathId);
entry.lastModified = newLastModified;
}
- });
+ }));
Internal::FileStatusCacheEntries newEntries;
newEntries.reserve(filePathIds.size());
- set_difference_call(filePathIds.begin(),
+ std::set_difference(filePathIds.begin(),
filePathIds.end(),
m_cacheEntries.begin(),
m_cacheEntries.end(),
- [&](FilePathId newFilePathId) {
+ make_iterator([&](FilePathId newFilePathId) {
newEntries.emplace_back(newFilePathId,
m_fileSystem.lastModified(newFilePathId));
modifiedFilePathIds.push_back(newFilePathId);
- });
+ }));
if (newEntries.size()) {
Internal::FileStatusCacheEntries mergedEntries;
diff --git a/src/libs/clangsupport/modifiedtimechecker.h b/src/libs/clangsupport/modifiedtimechecker.h
index 9247933b18..00e8e3ebac 100644
--- a/src/libs/clangsupport/modifiedtimechecker.h
+++ b/src/libs/clangsupport/modifiedtimechecker.h
@@ -25,24 +25,23 @@
#pragma once
-#include "clangpathwatcher.h"
-#include "filepathcachinginterface.h"
+#include "filesysteminterface.h"
#include "modifiedtimecheckerinterface.h"
+#include "set_algorithm.h"
#include <algorithm>
#include <iterator>
namespace ClangBackEnd {
+
template<typename SourceEntries = ::ClangBackEnd::SourceEntries>
class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries>
{
using SourceEntry = typename SourceEntries::value_type;
public:
- using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>;
- ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache)
- : m_getModifiedTime(getModifiedTime)
- , m_filePathCache(filePathCache)
+ ModifiedTimeChecker(FileSystemInterface &fileSystem)
+ : m_fileSystem(fileSystem)
{}
bool isUpToDate(const SourceEntries &sourceEntries) const
@@ -52,165 +51,101 @@ public:
updateCurrentSourceTimeStamps(sourceEntries);
- return compareEntries(sourceEntries);
+ return compareEntries(sourceEntries) && notReseted(sourceEntries);
}
void pathsChanged(const FilePathIds &filePathIds) override
{
- using SourceTimeStampReferences = std::vector<std::reference_wrapper<SourceTimeStamp>>;
-
- SourceTimeStampReferences timeStampsToUpdate;
- timeStampsToUpdate.reserve(filePathIds.size());
-
std::set_intersection(m_currentSourceTimeStamps.begin(),
m_currentSourceTimeStamps.end(),
filePathIds.begin(),
filePathIds.end(),
- std::back_inserter(timeStampsToUpdate));
+ make_iterator([&](SourceTimeStamp &sourceTimeStamp) {
+ sourceTimeStamp.timeStamp = m_fileSystem.lastModified(
+ sourceTimeStamp.sourceId);
+ }));
+ }
+
+ void reset(const FilePathIds &filePathIds)
+ {
+ FilePathIds newResetFilePathIds;
+ newResetFilePathIds.reserve(newResetFilePathIds.size() + m_resetFilePathIds.size());
+
+ std::set_union(m_resetFilePathIds.begin(),
+ m_resetFilePathIds.end(),
+ filePathIds.begin(),
+ filePathIds.end(),
+ std::back_inserter(newResetFilePathIds));
- for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) {
- sourceTimeStamp.timeStamp = m_getModifiedTime(
- m_filePathCache.filePath(sourceTimeStamp.sourceId));
- }
+ m_resetFilePathIds = std::move(newResetFilePathIds);
}
private:
bool compareEntries(const SourceEntries &sourceEntries) const
{
- class CompareSourceId
- {
- public:
- bool operator()(SourceTimeStamp first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
- };
-
- SourceTimeStamps currentSourceTimeStamp;
- currentSourceTimeStamp.reserve(sourceEntries.size());
- std::set_intersection(m_currentSourceTimeStamps.begin(),
- m_currentSourceTimeStamps.end(),
- sourceEntries.begin(),
- sourceEntries.end(),
- std::back_inserter(currentSourceTimeStamp),
- CompareSourceId{});
-
- class CompareTime
- {
- public:
- bool operator()(SourceTimeStamp first, SourceTimeStamp second)
- {
- return first.timeStamp <= second.timeStamp;
- }
-
- bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
- {
- return first.timeStamp <= second.timeStamp;
- }
-
- bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
- {
- return first.timeStamp <= second.timeStamp;
- }
-
- bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
- {
- return first.timeStamp <= second.timeStamp;
- }
- };
-
- return std::lexicographical_compare(currentSourceTimeStamp.begin(),
- currentSourceTimeStamp.end(),
- sourceEntries.begin(),
- sourceEntries.end(),
- CompareTime{});
+ return set_intersection_compare(
+ m_currentSourceTimeStamps.begin(),
+ m_currentSourceTimeStamps.end(),
+ sourceEntries.begin(),
+ sourceEntries.end(),
+ [](auto first, auto second) { return second.timeStamp > first.timeStamp; },
+ [](auto first, auto second) { return first.sourceId < second.sourceId; });
}
void updateCurrentSourceTimeStamps(const SourceEntries &sourceEntries) const
{
SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries);
- for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) {
- newSourceTimeStamp.timeStamp = m_getModifiedTime(
- m_filePathCache.filePath(newSourceTimeStamp.sourceId));
- }
-
auto split = sourceTimeStamps.insert(sourceTimeStamps.end(),
m_currentSourceTimeStamps.begin(),
m_currentSourceTimeStamps.end());
std::inplace_merge(sourceTimeStamps.begin(), split, sourceTimeStamps.end());
- m_currentSourceTimeStamps = sourceTimeStamps;
+ m_currentSourceTimeStamps = std::move(sourceTimeStamps);
}
SourceTimeStamps newSourceTimeStamps(const SourceEntries &sourceEntries) const
{
- SourceEntries newSourceEntries;
- newSourceEntries.reserve(sourceEntries.size());
-
- class CompareSourceId
- {
- public:
- bool operator()(SourceTimeStamp first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second)
- {
- return first.sourceId < second.sourceId;
- }
-
- bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second)
- {
- return first.sourceId < second.sourceId;
- }
- };
+ SourceTimeStamps newTimeStamps;
+ newTimeStamps.reserve(sourceEntries.size());
std::set_difference(sourceEntries.begin(),
sourceEntries.end(),
m_currentSourceTimeStamps.begin(),
m_currentSourceTimeStamps.end(),
- std::back_inserter(newSourceEntries),
- CompareSourceId{});
+ make_iterator([&](const SourceEntry &sourceEntry) {
+ newTimeStamps.emplace_back(sourceEntry.sourceId,
+ m_fileSystem.lastModified(
+ sourceEntry.sourceId));
+ }),
+ [](auto first, auto second) {
+ return first.sourceId < second.sourceId && first.timeStamp > 0;
+ });
- SourceTimeStamps newTimeStamps;
- newTimeStamps.reserve(newSourceEntries.size());
+ return newTimeStamps;
+ }
- std::transform(newSourceEntries.begin(),
- newSourceEntries.end(),
- std::back_inserter(newTimeStamps),
- [](SourceEntry entry) {
- return SourceTimeStamp{entry.sourceId, {}};
- });
+ bool notReseted(const SourceEntries &sourceEntries) const
+ {
+ auto oldSize = m_resetFilePathIds.size();
+ FilePathIds newResetFilePathIds;
+ newResetFilePathIds.reserve(newResetFilePathIds.size());
- return newTimeStamps;
+ std::set_difference(m_resetFilePathIds.begin(),
+ m_resetFilePathIds.end(),
+ sourceEntries.begin(),
+ sourceEntries.end(),
+ std::back_inserter(newResetFilePathIds));
+
+ m_resetFilePathIds = std::move(newResetFilePathIds);
+
+ return oldSize == m_resetFilePathIds.size();
}
private:
mutable SourceTimeStamps m_currentSourceTimeStamps;
- GetModifiedTime &m_getModifiedTime;
- FilePathCachingInterface &m_filePathCache;
+ mutable FilePathIds m_resetFilePathIds;
+ FileSystemInterface &m_fileSystem;
};
} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/set_algorithm.h b/src/libs/clangsupport/set_algorithm.h
new file mode 100644
index 0000000000..39bd3a2055
--- /dev/null
+++ b/src/libs/clangsupport/set_algorithm.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <algorithm>
+
+namespace ClangBackEnd {
+
+template<class Callable>
+class function_output_iterator
+{
+public:
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ explicit function_output_iterator() {}
+
+ explicit function_output_iterator(const Callable &callable)
+ : m_callable(&callable)
+ {}
+
+ function_output_iterator &operator=(const function_output_iterator &iterator)
+ {
+ m_callable = iterator.m_callable;
+
+ return *this;
+ }
+
+ struct helper
+ {
+ helper(const Callable *callable)
+ : m_callable(callable)
+ {}
+ template<class T>
+ helper &operator=(T &&value)
+ {
+ (*m_callable)(std::forward<T>(value));
+ return *this;
+ }
+ const Callable *m_callable;
+ };
+
+ helper operator*() { return helper(m_callable); }
+ function_output_iterator &operator++() { return *this; }
+ function_output_iterator &operator++(int) { return *this; }
+
+private:
+ const Callable *m_callable;
+};
+
+template<typename Callable>
+function_output_iterator<Callable> make_iterator(const Callable &callable)
+{
+ return function_output_iterator<Callable>(callable);
+}
+
+template<class InputIt1, class InputIt2, class Callable, class Compare>
+bool set_intersection_compare(
+ InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable call, Compare comp)
+{
+ while (first1 != last1 && first2 != last2) {
+ if (comp(*first1, *first2)) {
+ ++first1;
+ } else {
+ if (!comp(*first2, *first1)) {
+ if (call(*first2, *first1++))
+ return false;
+ }
+ ++first2;
+ }
+ }
+
+ return true;
+}
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/sourceentry.h b/src/libs/clangsupport/sourceentry.h
index c593f1fcd3..5e8769d14f 100644
--- a/src/libs/clangsupport/sourceentry.h
+++ b/src/libs/clangsupport/sourceentry.h
@@ -131,6 +131,10 @@ public:
return first.sourceId < second.sourceId;
}
+ friend bool operator<(SourceEntry first, FilePathId second) { return first.sourceId < second; }
+
+ friend bool operator<(FilePathId first, SourceEntry second) { return first < second.sourceId; }
+
friend bool operator==(SourceEntry first, SourceEntry second)
{
return first.sourceId == second.sourceId && first.sourceType == second.sourceType