forked from qt-creator/qt-creator
Clang: Introduce parallel indexing
Change-Id: I522cb18e6d24b7dbed5d5dfa3a732e5b3b5113bb Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
@@ -27,7 +27,10 @@ HEADERS += \
|
|||||||
$$PWD/symbolindexertaskqueue.h \
|
$$PWD/symbolindexertaskqueue.h \
|
||||||
$$PWD/symbolindexertaskscheduler.h \
|
$$PWD/symbolindexertaskscheduler.h \
|
||||||
$$PWD/symbolscollectormanagerinterface.h \
|
$$PWD/symbolscollectormanagerinterface.h \
|
||||||
$$PWD/symbolindexertaskqueueinterface.h
|
$$PWD/symbolindexertaskqueueinterface.h \
|
||||||
|
$$PWD/symbolindexertaskschedulerinterface.h \
|
||||||
|
$$PWD/symbolscollectormanager.h \
|
||||||
|
$$PWD/symbolindexertask.h
|
||||||
|
|
||||||
!isEmpty(LIBTOOLING_LIBS) {
|
!isEmpty(LIBTOOLING_LIBS) {
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@@ -75,4 +78,5 @@ SOURCES += \
|
|||||||
$$PWD/filestatuscache.cpp \
|
$$PWD/filestatuscache.cpp \
|
||||||
$$PWD/projectpartqueue.cpp \
|
$$PWD/projectpartqueue.cpp \
|
||||||
$$PWD/symbolindexertaskqueue.cpp \
|
$$PWD/symbolindexertaskqueue.cpp \
|
||||||
$$PWD/symbolindexertaskscheduler.cpp
|
$$PWD/symbolindexertaskscheduler.cpp \
|
||||||
|
$$PWD/symbolscollectormanager.cpp
|
||||||
|
|||||||
@@ -25,15 +25,18 @@
|
|||||||
|
|
||||||
#include "symbolindexer.h"
|
#include "symbolindexer.h"
|
||||||
|
|
||||||
|
#include <symbolscollector.h>
|
||||||
|
#include <symbolindexertaskqueue.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
SymbolIndexer::SymbolIndexer(SymbolsCollectorInterface &symbolsCollector,
|
SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQueue,
|
||||||
SymbolStorageInterface &symbolStorage,
|
SymbolStorageInterface &symbolStorage,
|
||||||
ClangPathWatcherInterface &pathWatcher,
|
ClangPathWatcherInterface &pathWatcher,
|
||||||
FilePathCachingInterface &filePathCache,
|
FilePathCachingInterface &filePathCache,
|
||||||
FileStatusCache &fileStatusCache,
|
FileStatusCache &fileStatusCache,
|
||||||
Sqlite::TransactionInterface &transactionInterface)
|
Sqlite::TransactionInterface &transactionInterface)
|
||||||
: m_symbolsCollector(symbolsCollector),
|
: m_symbolIndexerTaskQueue(symbolIndexerTaskQueue),
|
||||||
m_symbolStorage(symbolStorage),
|
m_symbolStorage(symbolStorage),
|
||||||
m_pathWatcher(pathWatcher),
|
m_pathWatcher(pathWatcher),
|
||||||
m_filePathCache(filePathCache),
|
m_filePathCache(filePathCache),
|
||||||
@@ -52,41 +55,60 @@ void SymbolIndexer::updateProjectParts(V2::ProjectPartContainers &&projectParts,
|
|||||||
void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart,
|
void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart,
|
||||||
const V2::FileContainers &generatedFiles)
|
const V2::FileContainers &generatedFiles)
|
||||||
{
|
{
|
||||||
m_symbolsCollector.clear();
|
|
||||||
|
|
||||||
const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(
|
|
||||||
projectPart.projectPartId);
|
|
||||||
|
|
||||||
FilePathIds sourcePathIds = updatableFilePathIds(projectPart, optionalArtefact);
|
|
||||||
|
|
||||||
if (!sourcePathIds.empty()) {
|
|
||||||
m_symbolsCollector.addFiles(projectPart.sourcePathIds,
|
|
||||||
compilerArguments(projectPart, optionalArtefact));
|
|
||||||
|
|
||||||
m_symbolsCollector.addUnsavedFiles(generatedFiles);
|
|
||||||
|
|
||||||
m_symbolsCollector.collectSymbols();
|
|
||||||
|
|
||||||
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
|
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
|
||||||
|
const auto optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(projectPart.projectPartId);
|
||||||
m_symbolStorage.addSymbolsAndSourceLocations(m_symbolsCollector.symbols(),
|
int projectPartId = m_symbolStorage.insertOrUpdateProjectPart(projectPart.projectPartId,
|
||||||
m_symbolsCollector.sourceLocations());
|
|
||||||
|
|
||||||
m_symbolStorage.insertOrUpdateProjectPart(projectPart.projectPartId,
|
|
||||||
projectPart.arguments,
|
projectPart.arguments,
|
||||||
projectPart.compilerMacros,
|
projectPart.compilerMacros,
|
||||||
projectPart.includeSearchPaths);
|
projectPart.includeSearchPaths);
|
||||||
m_symbolStorage.updateProjectPartSources(projectPart.projectPartId,
|
transaction.commit();
|
||||||
m_symbolsCollector.sourceFiles());
|
|
||||||
|
|
||||||
m_symbolStorage.insertOrUpdateUsedMacros(m_symbolsCollector.usedMacros());
|
if (optionalArtefact)
|
||||||
|
projectPartId = optionalArtefact->projectPartId;
|
||||||
|
|
||||||
m_symbolStorage.insertFileStatuses(m_symbolsCollector.fileStatuses());
|
FilePathIds sourcePathIds = updatableFilePathIds(projectPart, optionalArtefact);
|
||||||
|
|
||||||
m_symbolStorage.insertOrUpdateSourceDependencies(m_symbolsCollector.sourceDependencies());
|
if (sourcePathIds.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Utils::SmallStringVector arguments = compilerArguments(projectPart, optionalArtefact);
|
||||||
|
|
||||||
|
std::vector<SymbolIndexerTask> symbolIndexerTask;
|
||||||
|
symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
|
||||||
|
|
||||||
|
for (FilePathId sourcePathId : projectPart.sourcePathIds) {
|
||||||
|
auto indexing = [projectPart, arguments, generatedFiles, sourcePathId]
|
||||||
|
(SymbolsCollectorInterface &symbolsCollector,
|
||||||
|
SymbolStorageInterface &symbolStorage,
|
||||||
|
Sqlite::TransactionInterface &transactionInterface) {
|
||||||
|
symbolsCollector.addFile(sourcePathId, arguments);
|
||||||
|
|
||||||
|
symbolsCollector.addUnsavedFiles(generatedFiles);
|
||||||
|
|
||||||
|
symbolsCollector.collectSymbols();
|
||||||
|
|
||||||
|
Sqlite::ImmediateTransaction transaction{transactionInterface};
|
||||||
|
|
||||||
|
symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
|
||||||
|
symbolsCollector.sourceLocations());
|
||||||
|
|
||||||
|
symbolStorage.updateProjectPartSources(projectPart.projectPartId,
|
||||||
|
symbolsCollector.sourceFiles());
|
||||||
|
|
||||||
|
symbolStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros());
|
||||||
|
|
||||||
|
symbolStorage.insertFileStatuses(symbolsCollector.fileStatuses());
|
||||||
|
|
||||||
|
symbolStorage.insertOrUpdateSourceDependencies(symbolsCollector.sourceDependencies());
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
|
};
|
||||||
|
|
||||||
|
symbolIndexerTask.emplace_back(sourcePathId, projectPartId, std::move(indexing));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
|
||||||
|
m_symbolIndexerTaskQueue.processTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolIndexer::pathsWithIdsChanged(const Utils::SmallStringVector &)
|
void SymbolIndexer::pathsWithIdsChanged(const Utils::SmallStringVector &)
|
||||||
@@ -95,40 +117,57 @@ void SymbolIndexer::pathsWithIdsChanged(const Utils::SmallStringVector &)
|
|||||||
|
|
||||||
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
|
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
|
||||||
{
|
{
|
||||||
|
std::vector<SymbolIndexerTask> symbolIndexerTask;
|
||||||
|
symbolIndexerTask.reserve(filePathIds.size());
|
||||||
|
|
||||||
for (FilePathId filePathId : filePathIds)
|
for (FilePathId filePathId : filePathIds)
|
||||||
updateChangedPath(filePathId);
|
updateChangedPath(filePathId, symbolIndexerTask);
|
||||||
|
|
||||||
|
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
|
||||||
|
m_symbolIndexerTaskQueue.processTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolIndexer::updateChangedPath(FilePathId filePathId)
|
void SymbolIndexer::updateChangedPath(FilePathId filePathId,
|
||||||
|
std::vector<SymbolIndexerTask> &symbolIndexerTask)
|
||||||
{
|
{
|
||||||
m_symbolsCollector.clear();
|
|
||||||
m_fileStatusCache.update(filePathId);
|
m_fileStatusCache.update(filePathId);
|
||||||
|
|
||||||
|
Sqlite::DeferredTransaction transaction{m_transactionInterface};
|
||||||
const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(filePathId);
|
const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(filePathId);
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
if (optionalArtefact && !optionalArtefact.value().compilerArguments.empty()) {
|
if (optionalArtefact && !optionalArtefact.value().compilerArguments.empty()) {
|
||||||
|
|
||||||
const ProjectPartArtefact &artefact = optionalArtefact.value();
|
const ProjectPartArtefact &artefact = optionalArtefact.value();
|
||||||
|
|
||||||
m_symbolsCollector.addFiles({filePathId},
|
Utils::SmallStringVector arguments = compilerArguments(artefact.compilerArguments,
|
||||||
compilerArguments(artefact.compilerArguments, artefact.projectPartId));
|
artefact.projectPartId);
|
||||||
|
|
||||||
m_symbolsCollector.collectSymbols();
|
auto indexing = [projectPartId=artefact.projectPartId, arguments, filePathId]
|
||||||
|
(SymbolsCollectorInterface &symbolsCollector,
|
||||||
|
SymbolStorageInterface &symbolStorage,
|
||||||
|
Sqlite::TransactionInterface &transactionInterface) {
|
||||||
|
symbolsCollector.addFile(filePathId, arguments);
|
||||||
|
|
||||||
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
|
symbolsCollector.collectSymbols();
|
||||||
|
|
||||||
m_symbolStorage.addSymbolsAndSourceLocations(m_symbolsCollector.symbols(),
|
Sqlite::ImmediateTransaction transaction{transactionInterface};
|
||||||
m_symbolsCollector.sourceLocations());
|
|
||||||
|
|
||||||
m_symbolStorage.updateProjectPartSources(artefact.projectPartId,
|
symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
|
||||||
m_symbolsCollector.sourceFiles());
|
symbolsCollector.sourceLocations());
|
||||||
|
|
||||||
m_symbolStorage.insertOrUpdateUsedMacros(m_symbolsCollector.usedMacros());
|
symbolStorage.updateProjectPartSources(projectPartId, symbolsCollector.sourceFiles());
|
||||||
|
|
||||||
m_symbolStorage.insertFileStatuses(m_symbolsCollector.fileStatuses());
|
symbolStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros());
|
||||||
|
|
||||||
m_symbolStorage.insertOrUpdateSourceDependencies(m_symbolsCollector.sourceDependencies());
|
symbolStorage.insertFileStatuses(symbolsCollector.fileStatuses());
|
||||||
|
|
||||||
|
symbolStorage.insertOrUpdateSourceDependencies(symbolsCollector.sourceDependencies());
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
|
};
|
||||||
|
|
||||||
|
symbolIndexerTask.emplace_back(filePathId, optionalArtefact->projectPartId, std::move(indexing));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "filestatuscache.h"
|
#include "filestatuscache.h"
|
||||||
#include "symbolscollectorinterface.h"
|
#include "symbolindexertaskqueueinterface.h"
|
||||||
#include "symbolstorageinterface.h"
|
#include "symbolstorageinterface.h"
|
||||||
#include "clangpathwatcher.h"
|
#include "clangpathwatcher.h"
|
||||||
|
|
||||||
@@ -35,10 +35,12 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class SymbolsCollectorInterface;
|
||||||
|
|
||||||
class SymbolIndexer : public ClangPathWatcherNotifier
|
class SymbolIndexer : public ClangPathWatcherNotifier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SymbolIndexer(SymbolsCollectorInterface &symbolsCollector,
|
SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQueue,
|
||||||
SymbolStorageInterface &symbolStorage,
|
SymbolStorageInterface &symbolStorage,
|
||||||
ClangPathWatcherInterface &pathWatcher,
|
ClangPathWatcherInterface &pathWatcher,
|
||||||
FilePathCachingInterface &filePathCache,
|
FilePathCachingInterface &filePathCache,
|
||||||
@@ -52,7 +54,8 @@ public:
|
|||||||
|
|
||||||
void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
|
void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
|
||||||
void pathsChanged(const FilePathIds &filePathIds) override;
|
void pathsChanged(const FilePathIds &filePathIds) override;
|
||||||
void updateChangedPath(FilePathId filePath);
|
void updateChangedPath(FilePathId filePath,
|
||||||
|
std::vector<SymbolIndexerTask> &symbolIndexerTask);
|
||||||
|
|
||||||
bool compilerMacrosOrIncludeSearchPathsAreDifferent(
|
bool compilerMacrosOrIncludeSearchPathsAreDifferent(
|
||||||
const V2::ProjectPartContainer &projectPart,
|
const V2::ProjectPartContainer &projectPart,
|
||||||
@@ -70,7 +73,7 @@ public:
|
|||||||
int projectPartId) const;
|
int projectPartId) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SymbolsCollectorInterface &m_symbolsCollector;
|
SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue;
|
||||||
SymbolStorageInterface &m_symbolStorage;
|
SymbolStorageInterface &m_symbolStorage;
|
||||||
ClangPathWatcherInterface &m_pathWatcher;
|
ClangPathWatcherInterface &m_pathWatcher;
|
||||||
FilePathCachingInterface &m_filePathCache;
|
FilePathCachingInterface &m_filePathCache;
|
||||||
|
|||||||
87
src/tools/clangrefactoringbackend/source/symbolindexertask.h
Normal file
87
src/tools/clangrefactoringbackend/source/symbolindexertask.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 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 <filepathid.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class TransactionInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class SymbolIndexerTaskSchedulerInterface;
|
||||||
|
class SymbolsCollectorInterface;
|
||||||
|
class SymbolStorageInterface;
|
||||||
|
|
||||||
|
class SymbolIndexerTask
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Callable = std::function<void(SymbolsCollectorInterface &symbolsCollector,
|
||||||
|
SymbolStorageInterface &symbolStorage,
|
||||||
|
Sqlite::TransactionInterface &transaction)>;
|
||||||
|
|
||||||
|
SymbolIndexerTask(FilePathId filePathId,
|
||||||
|
int projectPartId,
|
||||||
|
Callable &&callable)
|
||||||
|
: callable(std::move(callable)),
|
||||||
|
filePathId(filePathId),
|
||||||
|
projectPartId(projectPartId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolIndexerTask clone() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
bool operator==(const SymbolIndexerTask &first, const SymbolIndexerTask &second)
|
||||||
|
{
|
||||||
|
return first.filePathId == second.filePathId && first.projectPartId == second.projectPartId;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
bool operator<(const SymbolIndexerTask &first, const SymbolIndexerTask &second)
|
||||||
|
{
|
||||||
|
return std::tie(first.filePathId, first.projectPartId)
|
||||||
|
< std::tie(second.filePathId, second.projectPartId);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Callable&&()
|
||||||
|
{
|
||||||
|
return std::move(callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Callable callable;
|
||||||
|
FilePathId filePathId;
|
||||||
|
int projectPartId;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "symbolindexertaskqueue.h"
|
#include "symbolindexertaskqueue.h"
|
||||||
|
|
||||||
|
#include <symbolindexertaskschedulerinterface.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -60,11 +62,6 @@ OutputIt set_union_merge(InputIt1 first1,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolIndexerTaskQueue::SymbolIndexerTaskQueue()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SymbolIndexerTaskQueue::addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks)
|
void SymbolIndexerTaskQueue::addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks)
|
||||||
{
|
{
|
||||||
std::vector<SymbolIndexerTask> mergedTasks;
|
std::vector<SymbolIndexerTask> mergedTasks;
|
||||||
@@ -133,7 +130,12 @@ std::vector<std::size_t> SymbolIndexerTaskQueue::projectPartNumberIds(const Util
|
|||||||
|
|
||||||
void SymbolIndexerTaskQueue::processTasks()
|
void SymbolIndexerTaskQueue::processTasks()
|
||||||
{
|
{
|
||||||
|
int taskCount = m_symbolIndexerScheduler.freeSlots();
|
||||||
|
|
||||||
|
auto newEnd = std::prev(m_tasks.end(), std::min<int>(taskCount, int(m_tasks.size())));
|
||||||
|
m_symbolIndexerScheduler.addTasks({std::make_move_iterator(newEnd),
|
||||||
|
std::make_move_iterator(m_tasks.end())});
|
||||||
|
m_tasks.erase(newEnd, m_tasks.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "symbolindexertaskqueueinterface.h"
|
#include "symbolindexertaskqueueinterface.h"
|
||||||
|
#include "symbolindexertask.h"
|
||||||
|
|
||||||
#include <filepathid.h>
|
#include <filepathid.h>
|
||||||
|
|
||||||
@@ -34,59 +35,25 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class TransactionInterface;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class SymbolIndexerTaskSchedulerInterface;
|
||||||
class SymbolsCollectorInterface;
|
class SymbolsCollectorInterface;
|
||||||
class SymbolStorageInterface;
|
class SymbolStorageInterface;
|
||||||
|
|
||||||
class SymbolIndexerTask
|
class SymbolIndexerTaskQueue final : public SymbolIndexerTaskQueueInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Callable = std::function<void(SymbolsCollectorInterface &symbolsCollector,
|
SymbolIndexerTaskQueue(SymbolIndexerTaskSchedulerInterface &symbolIndexerTaskScheduler)
|
||||||
SymbolStorageInterface &symbolStorage)>;
|
: m_symbolIndexerScheduler(symbolIndexerTaskScheduler)
|
||||||
|
{}
|
||||||
|
|
||||||
SymbolIndexerTask(FilePathId filePathId,
|
void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks);
|
||||||
std::size_t projectPartId,
|
void removeTasks(const Utils::SmallStringVector &projectPartIds);
|
||||||
Callable &&callable)
|
|
||||||
: callable(std::move(callable)),
|
|
||||||
filePathId(filePathId),
|
|
||||||
projectPartId(projectPartId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SymbolIndexerTask clone() const
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool operator==(const SymbolIndexerTask &first, const SymbolIndexerTask &second)
|
|
||||||
{
|
|
||||||
return first.filePathId == second.filePathId && first.projectPartId == second.projectPartId;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool operator<(const SymbolIndexerTask &first, const SymbolIndexerTask &second)
|
|
||||||
{
|
|
||||||
return std::tie(first.filePathId, first.projectPartId)
|
|
||||||
< std::tie(second.filePathId, second.projectPartId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Callable callable;
|
|
||||||
FilePathId filePathId;
|
|
||||||
std::size_t projectPartId;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SymbolIndexerTaskQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SymbolIndexerTaskQueue();
|
|
||||||
|
|
||||||
void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks)
|
|
||||||
/* [[expects: std::is_sorted(tasks)]] */;
|
|
||||||
void removeTasks(const Utils::SmallStringVector &projectPartIds)
|
|
||||||
/* [[expects: std::is_sorted(projectPartIds)]] */;
|
|
||||||
|
|
||||||
const std::vector<SymbolIndexerTask> &tasks() const;
|
const std::vector<SymbolIndexerTask> &tasks() const;
|
||||||
|
|
||||||
@@ -95,10 +62,12 @@ public:
|
|||||||
/* [[ensures result: std::is_sorted(result)]] */;
|
/* [[ensures result: std::is_sorted(result)]] */;
|
||||||
|
|
||||||
void processTasks();
|
void processTasks();
|
||||||
|
void syncTasks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Utils::SmallString> m_projectPartIds;
|
std::vector<Utils::SmallString> m_projectPartIds;
|
||||||
std::vector<SymbolIndexerTask> m_tasks;
|
std::vector<SymbolIndexerTask> m_tasks;
|
||||||
|
SymbolIndexerTaskSchedulerInterface &m_symbolIndexerScheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
|||||||
@@ -25,11 +25,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <utils/smallstringvector.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class SymbolIndexerTask;
|
||||||
|
|
||||||
class SymbolIndexerTaskQueueInterface
|
class SymbolIndexerTaskQueueInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
SymbolIndexerTaskQueueInterface() = default;
|
||||||
|
SymbolIndexerTaskQueueInterface(const SymbolIndexerTaskQueueInterface &) = delete;
|
||||||
|
SymbolIndexerTaskQueueInterface &operator=(const SymbolIndexerTaskQueueInterface &) = delete;
|
||||||
|
|
||||||
|
virtual void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) = 0
|
||||||
|
/* [[expects: std::is_sorted(tasks)]] */;
|
||||||
|
virtual void removeTasks(const Utils::SmallStringVector &projectPartIds) = 0
|
||||||
|
/* [[expects: std::is_sorted(projectPartIds)]] */;
|
||||||
virtual void processTasks() = 0;
|
virtual void processTasks() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ void SymbolIndexerTaskScheduler::addTasks(std::vector<Task> &&tasks)
|
|||||||
auto callWrapper = [&, task=std::move(task)] (
|
auto callWrapper = [&, task=std::move(task)] (
|
||||||
std::reference_wrapper<SymbolsCollectorInterface> symbolsCollector)
|
std::reference_wrapper<SymbolsCollectorInterface> symbolsCollector)
|
||||||
-> SymbolsCollectorInterface& {
|
-> SymbolsCollectorInterface& {
|
||||||
task(symbolsCollector.get(), m_symbolStorage);
|
task(symbolsCollector.get(), m_symbolStorage, m_transactionInterface);
|
||||||
executeInLoop([&] {
|
executeInLoop([&] {
|
||||||
m_symbolIndexerTaskQueue.processTasks();
|
m_symbolIndexerTaskQueue.processTasks();
|
||||||
});
|
});
|
||||||
@@ -105,11 +105,14 @@ const std::vector<SymbolIndexerTaskScheduler::Future> &SymbolIndexerTaskSchedule
|
|||||||
return m_futures;
|
return m_futures;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SymbolIndexerTaskScheduler::freeSlots()
|
uint SymbolIndexerTaskScheduler::freeSlots()
|
||||||
{
|
{
|
||||||
removeFinishedFutures();
|
removeFinishedFutures();
|
||||||
|
|
||||||
return std::max(m_hardware_concurrency - int(m_futures.size()), 0);
|
if (m_isDisabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return uint(std::max(int(m_hardware_concurrency) - int(m_futures.size()), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolIndexerTaskScheduler::syncTasks()
|
void SymbolIndexerTaskScheduler::syncTasks()
|
||||||
@@ -118,6 +121,11 @@ void SymbolIndexerTaskScheduler::syncTasks()
|
|||||||
future.wait();
|
future.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SymbolIndexerTaskScheduler::disable()
|
||||||
|
{
|
||||||
|
m_isDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
void SymbolIndexerTaskScheduler::removeFinishedFutures()
|
void SymbolIndexerTaskScheduler::removeFinishedFutures()
|
||||||
{
|
{
|
||||||
auto notReady = [] (Future &future) {
|
auto notReady = [] (Future &future) {
|
||||||
@@ -127,7 +135,9 @@ void SymbolIndexerTaskScheduler::removeFinishedFutures()
|
|||||||
auto split = std::partition(m_futures.begin(), m_futures.end(), notReady);
|
auto split = std::partition(m_futures.begin(), m_futures.end(), notReady);
|
||||||
|
|
||||||
std::for_each(split, m_futures.end(), [] (Future &future) {
|
std::for_each(split, m_futures.end(), [] (Future &future) {
|
||||||
future.get().setIsUsed(false);
|
SymbolsCollectorInterface &symbolCollector = future.get();
|
||||||
|
symbolCollector.setIsUsed(false);
|
||||||
|
symbolCollector.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
m_futures.erase(split, m_futures.end());
|
m_futures.erase(split, m_futures.end());
|
||||||
|
|||||||
@@ -25,10 +25,17 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "symbolindexertaskschedulerinterface.h"
|
||||||
|
#include "symbolindexertask.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class TransactionInterface;
|
||||||
|
};
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class FilePathCachingInterface;
|
class FilePathCachingInterface;
|
||||||
@@ -37,20 +44,21 @@ class SymbolsCollectorManagerInterface;
|
|||||||
class SymbolIndexerTaskQueueInterface;
|
class SymbolIndexerTaskQueueInterface;
|
||||||
class SymbolStorageInterface;
|
class SymbolStorageInterface;
|
||||||
|
|
||||||
class SymbolIndexerTaskScheduler
|
class SymbolIndexerTaskScheduler final : public SymbolIndexerTaskSchedulerInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Task = std::function<void(SymbolsCollectorInterface &symbolsCollector,
|
using Task = SymbolIndexerTask::Callable;
|
||||||
SymbolStorageInterface &symbolStorage)>;
|
|
||||||
using Future = std::future<SymbolsCollectorInterface&>;
|
using Future = std::future<SymbolsCollectorInterface&>;
|
||||||
|
|
||||||
SymbolIndexerTaskScheduler(SymbolsCollectorManagerInterface &symbolsCollectorManager,
|
SymbolIndexerTaskScheduler(SymbolsCollectorManagerInterface &symbolsCollectorManager,
|
||||||
SymbolStorageInterface &symbolStorage,
|
SymbolStorageInterface &symbolStorage,
|
||||||
|
Sqlite::TransactionInterface &transactionInterface,
|
||||||
SymbolIndexerTaskQueueInterface &symbolIndexerTaskQueue,
|
SymbolIndexerTaskQueueInterface &symbolIndexerTaskQueue,
|
||||||
int hardware_concurrency,
|
uint hardware_concurrency,
|
||||||
std::launch launchPolicy = std::launch::async)
|
std::launch launchPolicy = std::launch::async)
|
||||||
: m_symbolsCollectorManager(symbolsCollectorManager),
|
: m_symbolsCollectorManager(symbolsCollectorManager),
|
||||||
m_symbolStorage(symbolStorage),
|
m_symbolStorage(symbolStorage),
|
||||||
|
m_transactionInterface(transactionInterface),
|
||||||
m_symbolIndexerTaskQueue(symbolIndexerTaskQueue),
|
m_symbolIndexerTaskQueue(symbolIndexerTaskQueue),
|
||||||
m_hardware_concurrency(hardware_concurrency),
|
m_hardware_concurrency(hardware_concurrency),
|
||||||
m_launchPolicy(launchPolicy)
|
m_launchPolicy(launchPolicy)
|
||||||
@@ -60,10 +68,12 @@ public:
|
|||||||
|
|
||||||
const std::vector<Future> &futures() const;
|
const std::vector<Future> &futures() const;
|
||||||
|
|
||||||
int freeSlots();
|
uint freeSlots();
|
||||||
|
|
||||||
void syncTasks();
|
void syncTasks();
|
||||||
|
|
||||||
|
void disable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void removeFinishedFutures();
|
void removeFinishedFutures();
|
||||||
|
|
||||||
@@ -71,9 +81,11 @@ private:
|
|||||||
std::vector<Future> m_futures;
|
std::vector<Future> m_futures;
|
||||||
SymbolsCollectorManagerInterface &m_symbolsCollectorManager;
|
SymbolsCollectorManagerInterface &m_symbolsCollectorManager;
|
||||||
SymbolStorageInterface &m_symbolStorage;
|
SymbolStorageInterface &m_symbolStorage;
|
||||||
|
Sqlite::TransactionInterface &m_transactionInterface;
|
||||||
SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue;
|
SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue;
|
||||||
int m_hardware_concurrency;
|
uint m_hardware_concurrency;
|
||||||
std::launch m_launchPolicy;
|
std::launch m_launchPolicy;
|
||||||
|
bool m_isDisabled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 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 <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class TransactionInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class SymbolsCollectorInterface;
|
||||||
|
class SymbolStorageInterface;
|
||||||
|
|
||||||
|
using uint = unsigned int;
|
||||||
|
|
||||||
|
class SymbolIndexerTaskSchedulerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Task = std::function<void(SymbolsCollectorInterface &symbolsCollector,
|
||||||
|
SymbolStorageInterface &symbolStorage,
|
||||||
|
Sqlite::TransactionInterface &transaction)>;
|
||||||
|
|
||||||
|
SymbolIndexerTaskSchedulerInterface() = default;
|
||||||
|
SymbolIndexerTaskSchedulerInterface(const SymbolIndexerTaskSchedulerInterface &) = delete;
|
||||||
|
SymbolIndexerTaskSchedulerInterface &operator=(const SymbolIndexerTaskSchedulerInterface &) = delete;
|
||||||
|
|
||||||
|
virtual void addTasks(std::vector<Task> &&tasks) = 0;
|
||||||
|
virtual uint freeSlots() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~SymbolIndexerTaskSchedulerInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
||||||
@@ -30,6 +30,9 @@
|
|||||||
#include "storagesqlitestatementfactory.h"
|
#include "storagesqlitestatementfactory.h"
|
||||||
#include "symbolindexer.h"
|
#include "symbolindexer.h"
|
||||||
#include "symbolscollector.h"
|
#include "symbolscollector.h"
|
||||||
|
#include "symbolscollectormanager.h"
|
||||||
|
#include "symbolindexertaskqueue.h"
|
||||||
|
#include "symbolindexertaskscheduler.h"
|
||||||
#include "symbolstorage.h"
|
#include "symbolstorage.h"
|
||||||
|
|
||||||
#include <refactoringdatabaseinitializer.h>
|
#include <refactoringdatabaseinitializer.h>
|
||||||
@@ -41,6 +44,8 @@
|
|||||||
|
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class SymbolIndexing final : public SymbolIndexingInterface
|
class SymbolIndexing final : public SymbolIndexingInterface
|
||||||
@@ -52,26 +57,44 @@ public:
|
|||||||
SymbolIndexing(Sqlite::Database &database,
|
SymbolIndexing(Sqlite::Database &database,
|
||||||
FilePathCachingInterface &filePathCache)
|
FilePathCachingInterface &filePathCache)
|
||||||
: m_filePathCache(filePathCache),
|
: m_filePathCache(filePathCache),
|
||||||
m_statementFactory(database)
|
m_statementFactory(database),
|
||||||
|
m_collectorManger(database),
|
||||||
|
m_indexerScheduler(m_collectorManger, m_symbolStorage, database, m_indexerQueue, std::thread::hardware_concurrency())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~SymbolIndexing()
|
||||||
|
{
|
||||||
|
syncTasks();
|
||||||
|
}
|
||||||
|
|
||||||
SymbolIndexer &indexer()
|
SymbolIndexer &indexer()
|
||||||
{
|
{
|
||||||
return m_indexer;
|
return m_indexer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void syncTasks()
|
||||||
|
{
|
||||||
|
m_indexerScheduler.disable();
|
||||||
|
while (!m_indexerScheduler.futures().empty()) {
|
||||||
|
m_indexerScheduler.syncTasks();
|
||||||
|
m_indexerScheduler.freeSlots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void updateProjectParts(V2::ProjectPartContainers &&projectParts,
|
void updateProjectParts(V2::ProjectPartContainers &&projectParts,
|
||||||
const V2::FileContainers &generatedFiles) override;
|
const V2::FileContainers &generatedFiles) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FilePathCachingInterface &m_filePathCache;
|
FilePathCachingInterface &m_filePathCache;
|
||||||
SymbolsCollector m_collector{m_filePathCache};
|
|
||||||
StatementFactory m_statementFactory;
|
StatementFactory m_statementFactory;
|
||||||
Storage m_symbolStorage{m_statementFactory};
|
Storage m_symbolStorage{m_statementFactory};
|
||||||
ClangPathWatcher<QFileSystemWatcher, QTimer> m_sourceWatcher{m_filePathCache};
|
ClangPathWatcher<QFileSystemWatcher, QTimer> m_sourceWatcher{m_filePathCache};
|
||||||
FileStatusCache m_fileStatusCache{m_filePathCache};
|
FileStatusCache m_fileStatusCache{m_filePathCache};
|
||||||
SymbolIndexer m_indexer{m_collector,
|
SymbolsCollectorManager<SymbolsCollector> m_collectorManger;
|
||||||
|
SymbolIndexerTaskScheduler m_indexerScheduler;
|
||||||
|
SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler};
|
||||||
|
SymbolIndexer m_indexer{m_indexerQueue,
|
||||||
m_symbolStorage,
|
m_symbolStorage,
|
||||||
m_sourceWatcher,
|
m_sourceWatcher,
|
||||||
m_filePathCache,
|
m_filePathCache,
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
SymbolsCollector::SymbolsCollector(FilePathCachingInterface &filePathCache)
|
SymbolsCollector::SymbolsCollector(Sqlite::Database &database)
|
||||||
: m_indexDataConsumer(std::make_shared<IndexDataConsumer>(m_symbolEntries, m_sourceLocationEntries, filePathCache, m_sourcesManager)),
|
: m_filePathCache(database),
|
||||||
|
m_indexDataConsumer(std::make_shared<IndexDataConsumer>(m_symbolEntries, m_sourceLocationEntries, m_filePathCache, m_sourcesManager)),
|
||||||
m_collectSymbolsAction(m_indexDataConsumer),
|
m_collectSymbolsAction(m_indexDataConsumer),
|
||||||
m_collectMacrosSourceFileCallbacks(m_symbolEntries, m_sourceLocationEntries, filePathCache, m_sourcesManager),
|
m_collectMacrosSourceFileCallbacks(m_symbolEntries, m_sourceLocationEntries, m_filePathCache, m_sourcesManager)
|
||||||
m_filePathCache(filePathCache)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +44,11 @@ void SymbolsCollector::addFiles(const FilePathIds &filePathIds,
|
|||||||
m_collectMacrosSourceFileCallbacks.addSourceFiles(filePathIds);
|
m_collectMacrosSourceFileCallbacks.addSourceFiles(filePathIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SymbolsCollector::addFile(FilePathId filePathId, const Utils::SmallStringVector &arguments)
|
||||||
|
{
|
||||||
|
addFiles({filePathId}, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
void SymbolsCollector::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
|
void SymbolsCollector::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
|
||||||
{
|
{
|
||||||
m_clangTool.addUnsavedFiles(unsavedFiles);
|
m_clangTool.addUnsavedFiles(unsavedFiles);
|
||||||
|
|||||||
@@ -31,17 +31,22 @@
|
|||||||
#include "sourcesmanager.h"
|
#include "sourcesmanager.h"
|
||||||
#include "symbolscollectorinterface.h"
|
#include "symbolscollectorinterface.h"
|
||||||
|
|
||||||
#include <filepathcachingfwd.h>
|
#include <filepathcaching.h>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class Database;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class SymbolsCollector final : public SymbolsCollectorInterface
|
class SymbolsCollector final : public SymbolsCollectorInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SymbolsCollector(FilePathCachingInterface &filePathCache);
|
SymbolsCollector(Sqlite::Database &database);
|
||||||
|
|
||||||
void addFiles(const FilePathIds &filePathIds,
|
void addFiles(const FilePathIds &filePathIds,
|
||||||
const Utils::SmallStringVector &arguments) override;
|
const Utils::SmallStringVector &arguments);
|
||||||
|
void addFile(FilePathId filePathId, const Utils::SmallStringVector &arguments) override;
|
||||||
|
|
||||||
void addUnsavedFiles(const V2::FileContainers &unsavedFiles) override;
|
void addUnsavedFiles(const V2::FileContainers &unsavedFiles) override;
|
||||||
|
|
||||||
@@ -60,6 +65,7 @@ public:
|
|||||||
void setIsUsed(bool isUsed) override;
|
void setIsUsed(bool isUsed) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FilePathCaching m_filePathCache;
|
||||||
ClangTool m_clangTool;
|
ClangTool m_clangTool;
|
||||||
SymbolEntries m_symbolEntries;
|
SymbolEntries m_symbolEntries;
|
||||||
SourceLocationEntries m_sourceLocationEntries;
|
SourceLocationEntries m_sourceLocationEntries;
|
||||||
@@ -67,7 +73,6 @@ private:
|
|||||||
CollectSymbolsAction m_collectSymbolsAction;
|
CollectSymbolsAction m_collectSymbolsAction;
|
||||||
CollectMacrosSourceFileCallbacks m_collectMacrosSourceFileCallbacks;
|
CollectMacrosSourceFileCallbacks m_collectMacrosSourceFileCallbacks;
|
||||||
SourcesManager m_sourcesManager;
|
SourcesManager m_sourcesManager;
|
||||||
FilePathCachingInterface &m_filePathCache;
|
|
||||||
bool m_isUsed = false;
|
bool m_isUsed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ class SymbolsCollectorInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SymbolsCollectorInterface() = default;
|
SymbolsCollectorInterface() = default;
|
||||||
|
virtual ~SymbolsCollectorInterface() = default;
|
||||||
SymbolsCollectorInterface(const SymbolsCollectorInterface &) = delete;
|
SymbolsCollectorInterface(const SymbolsCollectorInterface &) = delete;
|
||||||
SymbolsCollectorInterface &operator=(const SymbolsCollectorInterface &) = delete;
|
SymbolsCollectorInterface &operator=(const SymbolsCollectorInterface &) = delete;
|
||||||
|
|
||||||
virtual void addFiles(const FilePathIds &filePathIds,
|
virtual void addFile(FilePathId filePathId, const Utils::SmallStringVector &arguments) = 0;
|
||||||
const Utils::SmallStringVector &arguments) = 0;
|
|
||||||
|
|
||||||
virtual void addUnsavedFiles(const V2::FileContainers &unsavedFiles) = 0;
|
virtual void addUnsavedFiles(const V2::FileContainers &unsavedFiles) = 0;
|
||||||
|
|
||||||
@@ -65,9 +65,6 @@ public:
|
|||||||
|
|
||||||
virtual bool isUsed() const = 0;
|
virtual bool isUsed() const = 0;
|
||||||
virtual void setIsUsed(bool isUsed) = 0;
|
virtual void setIsUsed(bool isUsed) = 0;
|
||||||
|
|
||||||
protected:
|
|
||||||
~SymbolsCollectorInterface() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 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 "symbolscollectormanager.h"
|
||||||
|
|
||||||
|
#include "symbolscollector.h"
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 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 "symbolscollectormanagerinterface.h"
|
||||||
|
#include "symbolscollectorinterface.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class Database;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
class SymbolsCollector;
|
||||||
|
template<typename SymbolsCollector>
|
||||||
|
class SymbolsCollectorManager final : public SymbolsCollectorManagerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SymbolsCollectorManager(Sqlite::Database &database)
|
||||||
|
: m_database(database)
|
||||||
|
{}
|
||||||
|
|
||||||
|
SymbolsCollector &unusedSymbolsCollector() override
|
||||||
|
{
|
||||||
|
auto split = std::partition(m_collectors.begin(),
|
||||||
|
m_collectors.end(),
|
||||||
|
[] (const auto &collector) {
|
||||||
|
return collector->isUsed();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto freeCollectors = std::distance(split, m_collectors.end());
|
||||||
|
|
||||||
|
if (freeCollectors > 0)
|
||||||
|
return usedCollector(*split->get());
|
||||||
|
|
||||||
|
m_collectors.emplace_back(std::make_unique<SymbolsCollector>(m_database));
|
||||||
|
|
||||||
|
return usedCollector(*m_collectors.back().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::unique_ptr<SymbolsCollector>> &collectors() const
|
||||||
|
{
|
||||||
|
return m_collectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SymbolsCollector &usedCollector(SymbolsCollector &collector)
|
||||||
|
{
|
||||||
|
collector.setIsUsed(true);
|
||||||
|
return collector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<SymbolsCollector>> m_collectors;
|
||||||
|
Sqlite::Database &m_database;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ClangBackEnd
|
||||||
@@ -34,6 +34,10 @@ class SymbolsCollectorInterface;
|
|||||||
class SymbolsCollectorManagerInterface
|
class SymbolsCollectorManagerInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
SymbolsCollectorManagerInterface() = default;
|
||||||
|
SymbolsCollectorManagerInterface(const SymbolsCollectorManagerInterface &) = delete;
|
||||||
|
SymbolsCollectorManagerInterface &operator=(const SymbolsCollectorManagerInterface &) = delete;
|
||||||
|
|
||||||
virtual SymbolsCollectorInterface &unusedSymbolsCollector() = 0;
|
virtual SymbolsCollectorInterface &unusedSymbolsCollector() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
deleteNewLocationsTable();
|
deleteNewLocationsTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertOrUpdateProjectPart(Utils::SmallStringView projectPartName,
|
int insertOrUpdateProjectPart(Utils::SmallStringView projectPartName,
|
||||||
const Utils::SmallStringVector &commandLineArguments,
|
const Utils::SmallStringVector &commandLineArguments,
|
||||||
const CompilerMacros &compilerMacros,
|
const CompilerMacros &compilerMacros,
|
||||||
const Utils::SmallStringVector &includeSearchPaths) override
|
const Utils::SmallStringVector &includeSearchPaths) override
|
||||||
@@ -88,6 +88,8 @@ public:
|
|||||||
includeSearchPathsAsJason,
|
includeSearchPathsAsJason,
|
||||||
projectPartName);
|
projectPartName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return int(m_statementFactory.database.lastInsertedRowId());
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const override
|
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const override
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
|
|
||||||
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
|
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
|
||||||
const SourceLocationEntries &sourceLocations) = 0;
|
const SourceLocationEntries &sourceLocations) = 0;
|
||||||
virtual void insertOrUpdateProjectPart(Utils::SmallStringView projectPartName,
|
virtual int insertOrUpdateProjectPart(Utils::SmallStringView projectPartName,
|
||||||
const Utils::SmallStringVector &commandLineArguments,
|
const Utils::SmallStringVector &commandLineArguments,
|
||||||
const CompilerMacros &compilerMacros,
|
const CompilerMacros &compilerMacros,
|
||||||
const Utils::SmallStringVector &includeSearchPaths) = 0;
|
const Utils::SmallStringVector &includeSearchPaths) = 0;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ using testing::ElementsAre;
|
|||||||
using testing::Field;
|
using testing::Field;
|
||||||
using testing::HasSubstr;
|
using testing::HasSubstr;
|
||||||
using testing::InSequence;
|
using testing::InSequence;
|
||||||
|
using testing::Invoke;
|
||||||
using testing::IsEmpty;
|
using testing::IsEmpty;
|
||||||
using testing::Matcher;
|
using testing::Matcher;
|
||||||
using testing::Mock;
|
using testing::Mock;
|
||||||
|
|||||||
@@ -32,5 +32,9 @@
|
|||||||
class MockSymbolIndexerTaskQueue : public ClangBackEnd::SymbolIndexerTaskQueueInterface
|
class MockSymbolIndexerTaskQueue : public ClangBackEnd::SymbolIndexerTaskQueueInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
MOCK_METHOD1(addOrUpdateTasks,
|
||||||
|
void (std::vector< ClangBackEnd::SymbolIndexerTask> &&tasks));
|
||||||
|
MOCK_METHOD1(removeTasks,
|
||||||
|
void (const Utils::SmallStringVector &projectPartIds));
|
||||||
MOCK_METHOD0(processTasks, void());
|
MOCK_METHOD0(processTasks, void());
|
||||||
};
|
};
|
||||||
|
|||||||
44
tests/unit/unittest/mocksymbolindexertaskscheduler.h
Normal file
44
tests/unit/unittest/mocksymbolindexertaskscheduler.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 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 <symbolindexertaskschedulerinterface.h>
|
||||||
|
|
||||||
|
class MockSymbolIndexerTaskScheduler : public ClangBackEnd::SymbolIndexerTaskSchedulerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD1(addTasks,
|
||||||
|
void (const std::vector<ClangBackEnd::SymbolIndexerTaskSchedulerInterface::Task> &));
|
||||||
|
MOCK_METHOD0(freeSlots,
|
||||||
|
uint ());
|
||||||
|
|
||||||
|
void addTasks(std::vector<ClangBackEnd::SymbolIndexerTaskSchedulerInterface::Task> &&tasks) override
|
||||||
|
{
|
||||||
|
addTasks(tasks);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -29,14 +29,28 @@
|
|||||||
|
|
||||||
#include <symbolscollectorinterface.h>
|
#include <symbolscollectorinterface.h>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
class Database;
|
||||||
|
}
|
||||||
|
|
||||||
class MockSymbolsCollector : public ClangBackEnd::SymbolsCollectorInterface
|
class MockSymbolsCollector : public ClangBackEnd::SymbolsCollectorInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
MockSymbolsCollector()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MockSymbolsCollector(const Sqlite::Database &)
|
||||||
|
{
|
||||||
|
ON_CALL(*this, setIsUsed(_)).WillByDefault(Invoke(this, &MockSymbolsCollector::setIsUsed2));
|
||||||
|
ON_CALL(*this, isUsed()).WillByDefault(Invoke(this, &MockSymbolsCollector::isUsed2));
|
||||||
|
}
|
||||||
|
|
||||||
MOCK_METHOD0(collectSymbols,
|
MOCK_METHOD0(collectSymbols,
|
||||||
void());
|
void());
|
||||||
|
|
||||||
MOCK_METHOD2(addFiles,
|
MOCK_METHOD2(addFile,
|
||||||
void(const ClangBackEnd::FilePathIds &filePathIds,
|
void(ClangBackEnd::FilePathId filePathId,
|
||||||
const Utils::SmallStringVector &arguments));
|
const Utils::SmallStringVector &arguments));
|
||||||
|
|
||||||
MOCK_METHOD1(addUnsavedFiles,
|
MOCK_METHOD1(addUnsavedFiles,
|
||||||
@@ -68,4 +82,17 @@ public:
|
|||||||
|
|
||||||
MOCK_METHOD1(setIsUsed,
|
MOCK_METHOD1(setIsUsed,
|
||||||
void(bool));
|
void(bool));
|
||||||
|
|
||||||
|
void setIsUsed2(bool isUsed)
|
||||||
|
{
|
||||||
|
used = isUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isUsed2() const
|
||||||
|
{
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool used = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
void(const ClangBackEnd::SymbolEntries &symbolEentries,
|
void(const ClangBackEnd::SymbolEntries &symbolEentries,
|
||||||
const ClangBackEnd::SourceLocationEntries &sourceLocations));
|
const ClangBackEnd::SourceLocationEntries &sourceLocations));
|
||||||
MOCK_METHOD4(insertOrUpdateProjectPart,
|
MOCK_METHOD4(insertOrUpdateProjectPart,
|
||||||
void(Utils::SmallStringView projectPartName,
|
int(Utils::SmallStringView projectPartName,
|
||||||
const Utils::SmallStringVector &commandLineArgument,
|
const Utils::SmallStringVector &commandLineArgument,
|
||||||
const ClangBackEnd::CompilerMacros &compilerMacros,
|
const ClangBackEnd::CompilerMacros &compilerMacros,
|
||||||
const Utils::SmallStringVector &includeSearchPaths));
|
const Utils::SmallStringVector &includeSearchPaths));
|
||||||
|
|||||||
@@ -34,9 +34,13 @@
|
|||||||
#include <filestatuscache.h>
|
#include <filestatuscache.h>
|
||||||
#include <projectpartcontainerv2.h>
|
#include <projectpartcontainerv2.h>
|
||||||
#include <refactoringdatabaseinitializer.h>
|
#include <refactoringdatabaseinitializer.h>
|
||||||
|
#include <symbolscollectormanager.h>
|
||||||
#include <symbolindexer.h>
|
#include <symbolindexer.h>
|
||||||
|
#include <symbolindexertaskqueue.h>
|
||||||
|
#include <symbolindexertaskscheduler.h>
|
||||||
#include <updateprojectpartsmessage.h>
|
#include <updateprojectpartsmessage.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -54,6 +58,10 @@ using ClangBackEnd::V2::ProjectPartContainers;
|
|||||||
using ClangBackEnd::V2::FileContainers;
|
using ClangBackEnd::V2::FileContainers;
|
||||||
using ClangBackEnd::SymbolEntries;
|
using ClangBackEnd::SymbolEntries;
|
||||||
using ClangBackEnd::SymbolEntry;
|
using ClangBackEnd::SymbolEntry;
|
||||||
|
using ClangBackEnd::SymbolIndexerTask;
|
||||||
|
using ClangBackEnd::SymbolIndexerTaskQueue;
|
||||||
|
using ClangBackEnd::SymbolIndexerTaskScheduler;
|
||||||
|
using ClangBackEnd::SymbolsCollectorManager;
|
||||||
using ClangBackEnd::SourceDependencies;
|
using ClangBackEnd::SourceDependencies;
|
||||||
using ClangBackEnd::SourceLocationEntries;
|
using ClangBackEnd::SourceLocationEntries;
|
||||||
using ClangBackEnd::SourceLocationEntry;
|
using ClangBackEnd::SourceLocationEntry;
|
||||||
@@ -89,6 +97,21 @@ protected:
|
|||||||
ON_CALL(mockCollector, sourceDependencies()).WillByDefault(ReturnRef(sourceDependencies));
|
ON_CALL(mockCollector, sourceDependencies()).WillByDefault(ReturnRef(sourceDependencies));
|
||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(A<FilePathId>())).WillByDefault(Return(artefact));
|
ON_CALL(mockStorage, fetchProjectPartArtefact(A<FilePathId>())).WillByDefault(Return(artefact));
|
||||||
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(QDateTime::currentSecsSinceEpoch()));
|
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(QDateTime::currentSecsSinceEpoch()));
|
||||||
|
|
||||||
|
mockCollector.setIsUsed(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown()
|
||||||
|
{
|
||||||
|
syncTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncTasks()
|
||||||
|
{
|
||||||
|
while (!indexerQueue.tasks().empty() || !indexerScheduler.futures().empty()) {
|
||||||
|
indexerScheduler.syncTasks();
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetUpTestCase()
|
static void SetUpTestCase()
|
||||||
@@ -153,23 +176,26 @@ protected:
|
|||||||
ClangBackEnd::ProjectPartArtefact emptyArtefact{"", "", "", 74};
|
ClangBackEnd::ProjectPartArtefact emptyArtefact{"", "", "", 74};
|
||||||
ClangBackEnd::ProjectPartPch projectPartPch{"/path/to/pch", 4};
|
ClangBackEnd::ProjectPartPch projectPartPch{"/path/to/pch", 4};
|
||||||
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
|
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
|
||||||
NiceMock<MockSymbolsCollector> mockCollector;
|
|
||||||
NiceMock<MockSymbolStorage> mockStorage;
|
NiceMock<MockSymbolStorage> mockStorage;
|
||||||
NiceMock<MockClangPathWatcher> mockPathWatcher;
|
NiceMock<MockClangPathWatcher> mockPathWatcher;
|
||||||
ClangBackEnd::FileStatusCache fileStatusCache{filePathCache};
|
ClangBackEnd::FileStatusCache fileStatusCache{filePathCache};
|
||||||
ClangBackEnd::SymbolIndexer indexer{mockCollector,
|
SymbolsCollectorManager<NiceMock<MockSymbolsCollector>> collectorManger{data->database};
|
||||||
|
SymbolIndexerTaskScheduler indexerScheduler{collectorManger, mockStorage, mockSqliteTransactionBackend, indexerQueue, 1};
|
||||||
|
SymbolIndexerTaskQueue indexerQueue{indexerScheduler};
|
||||||
|
ClangBackEnd::SymbolIndexer indexer{indexerQueue,
|
||||||
mockStorage,
|
mockStorage,
|
||||||
mockPathWatcher,
|
mockPathWatcher,
|
||||||
filePathCache,
|
filePathCache,
|
||||||
fileStatusCache,
|
fileStatusCache,
|
||||||
mockSqliteTransactionBackend};
|
mockSqliteTransactionBackend};
|
||||||
|
NiceMock<MockSymbolsCollector> &mockCollector{collectorManger.unusedSymbolsCollector()};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Data> SymbolIndexer::data;
|
std::unique_ptr<Data> SymbolIndexer::data;
|
||||||
|
|
||||||
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
|
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds, projectPart1.arguments));
|
EXPECT_CALL(mockCollector, addFile(main1PathId, projectPart1.arguments));
|
||||||
|
|
||||||
indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
|
indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
|
||||||
}
|
}
|
||||||
@@ -179,7 +205,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInColl
|
|||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId))).WillByDefault(Return(emptyArtefact));
|
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId))).WillByDefault(Return(emptyArtefact));
|
||||||
ON_CALL(mockStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))).WillByDefault(Return(projectPartPch));
|
ON_CALL(mockStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))).WillByDefault(Return(projectPartPch));
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds,
|
EXPECT_CALL(mockCollector, addFile(main1PathId,
|
||||||
ElementsAre(Eq("-I"),
|
ElementsAre(Eq("-I"),
|
||||||
Eq(TESTDATA_DIR),
|
Eq(TESTDATA_DIR),
|
||||||
Eq("-Wno-pragma-once-outside-header"),
|
Eq("-Wno-pragma-once-outside-header"),
|
||||||
@@ -195,7 +221,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithoutPrecompiledHeaderInC
|
|||||||
{
|
{
|
||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId))).WillByDefault(Return(emptyArtefact));
|
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId))).WillByDefault(Return(emptyArtefact));
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds,
|
EXPECT_CALL(mockCollector, addFile(main1PathId,
|
||||||
ElementsAre(Eq("-I"),
|
ElementsAre(Eq("-I"),
|
||||||
Eq(TESTDATA_DIR),
|
Eq(TESTDATA_DIR),
|
||||||
Eq("-Wno-pragma-once-outside-header"))));
|
Eq("-Wno-pragma-once-outside-header"))));
|
||||||
@@ -212,14 +238,14 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsClearInCollector)
|
|||||||
|
|
||||||
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectPart)
|
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectPart)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockCollector, addFiles(_, _)).Times(2);
|
EXPECT_CALL(mockCollector, addFile(_, _)).Times(2);
|
||||||
|
|
||||||
indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved));
|
indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEveryProjectParts)
|
TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEveryProjectParts)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockCollector, addFiles(_, _))
|
EXPECT_CALL(mockCollector, addFile(_, _))
|
||||||
.Times(0);
|
.Times(0);
|
||||||
|
|
||||||
indexer.updateProjectParts({}, {});
|
indexer.updateProjectParts({}, {});
|
||||||
@@ -255,9 +281,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddUnsavedFilesInCollector)
|
|||||||
|
|
||||||
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddSymbolsAndSourceLocationsInStorage)
|
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddSymbolsAndSourceLocationsInStorage)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(2);
|
|
||||||
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(2);
|
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(2);
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(2);
|
|
||||||
|
|
||||||
indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved));
|
indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved));
|
||||||
}
|
}
|
||||||
@@ -320,14 +344,15 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, clear());
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
|
||||||
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId)));
|
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId)));
|
||||||
EXPECT_CALL(mockCollector, addFiles(_, _));
|
EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq(projectPart1.projectPartId), Eq(projectPart1.arguments), Eq(projectPart1.compilerMacros), Eq(projectPart1.includeSearchPaths)));
|
||||||
|
EXPECT_CALL(mockSqliteTransactionBackend, commit());
|
||||||
|
EXPECT_CALL(mockCollector, addFile(main1PathId, projectPart1.arguments));
|
||||||
EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved));
|
EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved));
|
||||||
EXPECT_CALL(mockCollector, collectSymbols());
|
EXPECT_CALL(mockCollector, collectSymbols());
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
|
||||||
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
|
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
|
||||||
EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq(projectPart1.projectPartId), Eq(projectPart1.arguments), Eq(projectPart1.compilerMacros), Eq(projectPart1.includeSearchPaths)));
|
|
||||||
EXPECT_CALL(mockStorage, updateProjectPartSources(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId), Eq(sourceFileIds)));
|
EXPECT_CALL(mockStorage, updateProjectPartSources(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId), Eq(sourceFileIds)));
|
||||||
EXPECT_CALL(mockStorage, insertOrUpdateUsedMacros(Eq(usedMacros)));
|
EXPECT_CALL(mockStorage, insertOrUpdateUsedMacros(Eq(usedMacros)));
|
||||||
EXPECT_CALL(mockStorage, insertFileStatuses(Eq(fileStatus)));
|
EXPECT_CALL(mockStorage, insertFileStatuses(Eq(fileStatus)));
|
||||||
@@ -341,7 +366,7 @@ TEST_F(SymbolIndexer, CallSetNotifier)
|
|||||||
{
|
{
|
||||||
EXPECT_CALL(mockPathWatcher, setNotifier(_));
|
EXPECT_CALL(mockPathWatcher, setNotifier(_));
|
||||||
|
|
||||||
ClangBackEnd::SymbolIndexer indexer{mockCollector, mockStorage, mockPathWatcher, filePathCache, fileStatusCache, mockSqliteTransactionBackend};
|
ClangBackEnd::SymbolIndexer indexer{indexerQueue, mockStorage, mockPathWatcher, filePathCache, fileStatusCache, mockSqliteTransactionBackend};
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
|
TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
|
||||||
@@ -356,9 +381,10 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, clear());
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
|
||||||
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(sourceFileIds[0]));
|
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(sourceFileIds[0])).WillOnce(Return(artefact));
|
||||||
EXPECT_CALL(mockCollector, addFiles(ElementsAre(sourceFileIds[0]), Eq(artefact.compilerArguments)));
|
EXPECT_CALL(mockSqliteTransactionBackend, commit());
|
||||||
|
EXPECT_CALL(mockCollector, addFile(Eq(sourceFileIds[0]), Eq(artefact.compilerArguments)));
|
||||||
EXPECT_CALL(mockCollector, collectSymbols());
|
EXPECT_CALL(mockCollector, collectSymbols());
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
|
||||||
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
|
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
|
||||||
@@ -368,17 +394,17 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
|
|||||||
EXPECT_CALL(mockStorage, insertOrUpdateSourceDependencies(Eq(sourceDependencies)));
|
EXPECT_CALL(mockStorage, insertOrUpdateSourceDependencies(Eq(sourceDependencies)));
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, commit());
|
EXPECT_CALL(mockSqliteTransactionBackend, commit());
|
||||||
|
|
||||||
indexer.updateChangedPath(sourceFileIds[0]);
|
indexer.pathsChanged({sourceFileIds[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
|
TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
|
||||||
{
|
{
|
||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
|
InSequence s;
|
||||||
.WillByDefault(Return(emptyArtefact));
|
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, clear());
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
|
||||||
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(sourceFileIds[0]));
|
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(sourceFileIds[0])).WillOnce(Return(emptyArtefact));
|
||||||
EXPECT_CALL(mockCollector, addFiles(_, _)).Times(0);
|
EXPECT_CALL(mockSqliteTransactionBackend, commit());
|
||||||
|
EXPECT_CALL(mockCollector, addFile(_, _)).Times(0);
|
||||||
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
|
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
|
||||||
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(_, _)).Times(0);
|
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(_, _)).Times(0);
|
||||||
@@ -388,7 +414,7 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
|
|||||||
EXPECT_CALL(mockStorage, insertOrUpdateSourceDependencies(_)).Times(0);
|
EXPECT_CALL(mockStorage, insertOrUpdateSourceDependencies(_)).Times(0);
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
|
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
|
||||||
|
|
||||||
indexer.updateChangedPath(sourceFileIds[0]);
|
indexer.pathsChanged({sourceFileIds[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
|
TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
|
||||||
@@ -397,26 +423,28 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
|
|||||||
.WillByDefault(Return(artefact));
|
.WillByDefault(Return(artefact));
|
||||||
ON_CALL(mockStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId)))
|
ON_CALL(mockStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId)))
|
||||||
.WillByDefault(Return(projectPartPch));
|
.WillByDefault(Return(projectPartPch));
|
||||||
|
std::vector<SymbolIndexerTask> symbolIndexerTask;
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds,
|
EXPECT_CALL(mockCollector, addFile(Eq(sourceFileIds[0]),
|
||||||
ElementsAre(Eq("-DFOO"),
|
ElementsAre(Eq("-DFOO"),
|
||||||
Eq("-Xclang"),
|
Eq("-Xclang"),
|
||||||
Eq("-include-pch"),
|
Eq("-include-pch"),
|
||||||
Eq("-Xclang"),
|
Eq("-Xclang"),
|
||||||
Eq("/path/to/pch"))));
|
Eq("/path/to/pch"))));
|
||||||
|
|
||||||
indexer.updateChangedPath(sourceFileIds[0]);
|
indexer.pathsChanged({sourceFileIds[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
|
TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
|
||||||
{
|
{
|
||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
|
ON_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
|
||||||
.WillByDefault(Return(artefact));
|
.WillByDefault(Return(artefact));
|
||||||
|
std::vector<SymbolIndexerTask> symbolIndexerTask;
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePathIds,
|
EXPECT_CALL(mockCollector, addFile(Eq(sourceFileIds[0]),
|
||||||
ElementsAre(Eq("-DFOO"))));
|
ElementsAre(Eq("-DFOO"))));
|
||||||
|
|
||||||
indexer.updateChangedPath(sourceFileIds[0]);
|
indexer.pathsChanged({sourceFileIds[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -458,11 +486,13 @@ TEST_F(SymbolIndexer, IncludeSearchPathsAreDifferent)
|
|||||||
|
|
||||||
TEST_F(SymbolIndexer, DontReparseInUpdateProjectPartsIfDefinesAreTheSame)
|
TEST_F(SymbolIndexer, DontReparseInUpdateProjectPartsIfDefinesAreTheSame)
|
||||||
{
|
{
|
||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, clear());
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
|
||||||
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId)));
|
EXPECT_CALL(mockStorage, fetchProjectPartArtefact(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId))).WillRepeatedly(Return(artefact));
|
||||||
EXPECT_CALL(mockCollector, addFiles(_, _)).Times(0);
|
EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq(projectPart1.projectPartId), Eq(projectPart1.arguments), Eq(projectPart1.compilerMacros), Eq(projectPart1.includeSearchPaths)));
|
||||||
|
EXPECT_CALL(mockSqliteTransactionBackend, commit());
|
||||||
|
EXPECT_CALL(mockCollector, addFile(_, _)).Times(0);
|
||||||
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
|
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
|
||||||
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
|
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
|
||||||
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(_, _)).Times(0);
|
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(_, _)).Times(0);
|
||||||
@@ -540,11 +570,12 @@ TEST_F(SymbolIndexer, UpToDateFilesDontPassFilteredUpdatableFilePathIds)
|
|||||||
TEST_F(SymbolIndexer, OutdatedFilesAreParsedInUpdateProjectParts)
|
TEST_F(SymbolIndexer, OutdatedFilesAreParsedInUpdateProjectParts)
|
||||||
{
|
{
|
||||||
indexer.pathsChanged({main1PathId});
|
indexer.pathsChanged({main1PathId});
|
||||||
|
indexerScheduler.syncTasks();
|
||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
|
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
|
||||||
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>()))
|
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>()))
|
||||||
.WillByDefault(Return(0));
|
.WillByDefault(Return(0));
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, addFiles(ElementsAre(main1PathId), _));
|
EXPECT_CALL(mockCollector, addFile(Eq(main1PathId), _));
|
||||||
|
|
||||||
indexer.updateProjectParts({projectPart1}, {});
|
indexer.updateProjectParts({projectPart1}, {});
|
||||||
}
|
}
|
||||||
@@ -552,11 +583,12 @@ TEST_F(SymbolIndexer, OutdatedFilesAreParsedInUpdateProjectParts)
|
|||||||
TEST_F(SymbolIndexer, UpToDateFilesAreNotParsedInUpdateProjectParts)
|
TEST_F(SymbolIndexer, UpToDateFilesAreNotParsedInUpdateProjectParts)
|
||||||
{
|
{
|
||||||
indexer.pathsChanged({main1PathId});
|
indexer.pathsChanged({main1PathId});
|
||||||
|
indexerScheduler.syncTasks();
|
||||||
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
|
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
|
||||||
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>()))
|
ON_CALL(mockStorage, fetchLowestLastModifiedTime(A<FilePathId>()))
|
||||||
.WillByDefault(Return(QDateTime::currentSecsSinceEpoch()));
|
.WillByDefault(Return(QDateTime::currentSecsSinceEpoch()));
|
||||||
|
|
||||||
EXPECT_CALL(mockCollector, addFiles(_, _)).Times(0);
|
EXPECT_CALL(mockCollector, addFile(_, _)).Times(0);
|
||||||
|
|
||||||
indexer.updateProjectParts({projectPart1}, {});
|
indexer.updateProjectParts({projectPart1}, {});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "googletest.h"
|
#include "googletest.h"
|
||||||
|
|
||||||
|
#include "mocksymbolindexertaskscheduler.h"
|
||||||
|
|
||||||
#include <symbolindexertaskqueue.h>
|
#include <symbolindexertaskqueue.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -48,12 +50,13 @@ MATCHER_P2(IsTask, filePathId, projectPartId,
|
|||||||
class SymbolIndexerTaskQueue : public testing::Test
|
class SymbolIndexerTaskQueue : public testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::size_t projectPartId(const Utils::SmallString &projectPartId)
|
int projectPartId(const Utils::SmallString &projectPartId)
|
||||||
{
|
{
|
||||||
return queue.projectPartNumberId(projectPartId);
|
return int(queue.projectPartNumberId(projectPartId));
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
ClangBackEnd::SymbolIndexerTaskQueue queue;
|
NiceMock<MockSymbolIndexerTaskScheduler> mockSymbolIndexerTaskScheduler;
|
||||||
|
ClangBackEnd::SymbolIndexerTaskQueue queue{mockSymbolIndexerTaskScheduler};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(SymbolIndexerTaskQueue, AddTasks)
|
TEST_F(SymbolIndexerTaskQueue, AddTasks)
|
||||||
@@ -162,4 +165,52 @@ TEST_F(SymbolIndexerTaskQueue, GetProjectPartIds)
|
|||||||
|
|
||||||
ASSERT_THAT(ids , ElementsAre(0, 2, 3));
|
ASSERT_THAT(ids , ElementsAre(0, 2, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolIndexerTaskQueue, ProcessTasksCallsFreeSlotsAndAddTasksInScheduler)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
queue.addOrUpdateTasks({{{1, 1}, projectPartId("yi"), Callable{}},
|
||||||
|
{{1, 3}, projectPartId("yi"), Callable{}},
|
||||||
|
{{1, 5}, projectPartId("yi"), Callable{}}});
|
||||||
|
|
||||||
|
EXPECT_CALL(mockSymbolIndexerTaskScheduler, freeSlots()).WillRepeatedly(Return(2));
|
||||||
|
EXPECT_CALL(mockSymbolIndexerTaskScheduler, addTasks(SizeIs(2)));
|
||||||
|
|
||||||
|
queue.processTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolIndexerTaskQueue, ProcessTasksCallsFreeSlotsAndAddTasksWithNoTaskInSchedulerIfTaskAreEmpty)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(mockSymbolIndexerTaskScheduler, freeSlots()).WillRepeatedly(Return(2));
|
||||||
|
EXPECT_CALL(mockSymbolIndexerTaskScheduler, addTasks(IsEmpty()));
|
||||||
|
|
||||||
|
queue.processTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolIndexerTaskQueue, ProcessTasksCallsFreeSlotsAndMoveAllTasksInSchedulerIfMoreSlotsAreFree)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
queue.addOrUpdateTasks({{{1, 1}, projectPartId("yi"), Callable{}},
|
||||||
|
{{1, 3}, projectPartId("yi"), Callable{}},
|
||||||
|
{{1, 5}, projectPartId("yi"), Callable{}}});
|
||||||
|
|
||||||
|
EXPECT_CALL(mockSymbolIndexerTaskScheduler, freeSlots()).WillRepeatedly(Return(4));
|
||||||
|
EXPECT_CALL(mockSymbolIndexerTaskScheduler, addTasks(SizeIs(3)));
|
||||||
|
|
||||||
|
queue.processTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolIndexerTaskQueue, ProcessTasksRemovesProcessedTasks)
|
||||||
|
{
|
||||||
|
queue.addOrUpdateTasks({{{1, 1}, projectPartId("yi"), Callable{}},
|
||||||
|
{{1, 3}, projectPartId("yi"), Callable{}},
|
||||||
|
{{1, 5}, projectPartId("yi"), Callable{}}});
|
||||||
|
ON_CALL(mockSymbolIndexerTaskScheduler, freeSlots()).WillByDefault(Return(2));
|
||||||
|
|
||||||
|
queue.processTasks();
|
||||||
|
|
||||||
|
ASSERT_THAT(queue.tasks(), SizeIs(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "mocksymbolscollectormanager.h"
|
#include "mocksymbolscollectormanager.h"
|
||||||
#include "mocksymbolscollector.h"
|
#include "mocksymbolscollector.h"
|
||||||
#include "mocksymbolstorage.h"
|
#include "mocksymbolstorage.h"
|
||||||
|
#include "mocksqlitetransactionbackend.h"
|
||||||
|
|
||||||
#include <symbolindexertaskscheduler.h>
|
#include <symbolindexertaskscheduler.h>
|
||||||
|
|
||||||
@@ -55,18 +56,27 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
MockFunction<void()> mock;
|
MockFunction<void()> mock;
|
||||||
ClangBackEnd::SymbolIndexerTaskScheduler::Task call{
|
ClangBackEnd::SymbolIndexerTaskScheduler::Task call{
|
||||||
[&] (SymbolsCollectorInterface &symbolsCollector,
|
[&] (SymbolsCollectorInterface &, SymbolStorageInterface &, Sqlite::TransactionInterface &) {
|
||||||
SymbolStorageInterface &symbolStorage) {
|
|
||||||
mock.Call(); }};
|
mock.Call(); }};
|
||||||
ClangBackEnd::SymbolIndexerTaskScheduler::Task nocall{
|
ClangBackEnd::SymbolIndexerTaskScheduler::Task nocall{
|
||||||
[&] (SymbolsCollectorInterface &symbolsCollector,
|
[&] (SymbolsCollectorInterface &, SymbolStorageInterface &, Sqlite::TransactionInterface &) {
|
||||||
SymbolStorageInterface &symbolStorage) {}};
|
}};
|
||||||
NiceMock<MockSymbolsCollectorManager> mockSymbolsCollectorManager;
|
NiceMock<MockSymbolsCollectorManager> mockSymbolsCollectorManager;
|
||||||
NiceMock<MockSymbolsCollector> mockSymbolsCollector;
|
NiceMock<MockSymbolsCollector> mockSymbolsCollector;
|
||||||
MockSymbolStorage mockSymbolStorage;
|
MockSymbolStorage mockSymbolStorage;
|
||||||
NiceMock<MockSymbolIndexerTaskQueue> mockSymbolIndexerTaskQueue;
|
NiceMock<MockSymbolIndexerTaskQueue> mockSymbolIndexerTaskQueue;
|
||||||
ClangBackEnd::SymbolIndexerTaskScheduler scheduler{mockSymbolsCollectorManager, mockSymbolStorage, mockSymbolIndexerTaskQueue, 4};
|
MockSqliteTransactionBackend mockSqliteTransactionBackend;
|
||||||
ClangBackEnd::SymbolIndexerTaskScheduler deferedScheduler{mockSymbolsCollectorManager, mockSymbolStorage, mockSymbolIndexerTaskQueue, 4, std::launch::deferred};
|
ClangBackEnd::SymbolIndexerTaskScheduler scheduler{mockSymbolsCollectorManager,
|
||||||
|
mockSymbolStorage,
|
||||||
|
mockSqliteTransactionBackend,
|
||||||
|
mockSymbolIndexerTaskQueue,
|
||||||
|
4};
|
||||||
|
ClangBackEnd::SymbolIndexerTaskScheduler deferedScheduler{mockSymbolsCollectorManager,
|
||||||
|
mockSymbolStorage,
|
||||||
|
mockSqliteTransactionBackend,
|
||||||
|
mockSymbolIndexerTaskQueue,
|
||||||
|
4,
|
||||||
|
std::launch::deferred};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(SymbolIndexerTaskScheduler, AddTasks)
|
TEST_F(SymbolIndexerTaskScheduler, AddTasks)
|
||||||
@@ -123,6 +133,7 @@ TEST_F(SymbolIndexerTaskScheduler, NoFuturesAfterFreeSlots)
|
|||||||
|
|
||||||
TEST_F(SymbolIndexerTaskScheduler, FreeSlotsCallSymbolsCollectorSetIsUnused)
|
TEST_F(SymbolIndexerTaskScheduler, FreeSlotsCallSymbolsCollectorSetIsUnused)
|
||||||
{
|
{
|
||||||
|
InSequence s;
|
||||||
scheduler.addTasks({nocall, nocall});
|
scheduler.addTasks({nocall, nocall});
|
||||||
scheduler.syncTasks();
|
scheduler.syncTasks();
|
||||||
|
|
||||||
@@ -131,6 +142,17 @@ TEST_F(SymbolIndexerTaskScheduler, FreeSlotsCallSymbolsCollectorSetIsUnused)
|
|||||||
scheduler.freeSlots();
|
scheduler.freeSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolIndexerTaskScheduler, FreeSlotsCallClearsSymbolsCollector)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
scheduler.addTasks({nocall, nocall});
|
||||||
|
scheduler.syncTasks();
|
||||||
|
|
||||||
|
EXPECT_CALL(mockSymbolsCollector, clear()).Times(2);
|
||||||
|
|
||||||
|
scheduler.freeSlots();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(SymbolIndexerTaskScheduler, AddTaskCallSymbolsCollectorManagerUnusedSymbolsCollector)
|
TEST_F(SymbolIndexerTaskScheduler, AddTaskCallSymbolsCollectorManagerUnusedSymbolsCollector)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockSymbolsCollectorManager, unusedSymbolsCollector()).Times(2);
|
EXPECT_CALL(mockSymbolsCollectorManager, unusedSymbolsCollector()).Times(2);
|
||||||
@@ -140,8 +162,12 @@ TEST_F(SymbolIndexerTaskScheduler, AddTaskCallSymbolsCollectorManagerUnusedSymbo
|
|||||||
|
|
||||||
TEST_F(SymbolIndexerTaskScheduler, CallProcessTasksInQueueAfterFinishedTasks)
|
TEST_F(SymbolIndexerTaskScheduler, CallProcessTasksInQueueAfterFinishedTasks)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockSymbolIndexerTaskQueue, processTasks()).Times(2);
|
InSequence s;
|
||||||
|
|
||||||
scheduler.addTasks({nocall, nocall});
|
EXPECT_CALL(mock, Call());
|
||||||
|
EXPECT_CALL(mockSymbolIndexerTaskQueue, processTasks());
|
||||||
|
|
||||||
|
scheduler.addTasks({call});
|
||||||
|
scheduler.syncTasks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ protected:
|
|||||||
TEST_F(SymbolIndexing, Locations)
|
TEST_F(SymbolIndexing, Locations)
|
||||||
{
|
{
|
||||||
indexing.indexer().updateProjectParts({projectPart1}, {});
|
indexing.indexer().updateProjectParts({projectPart1}, {});
|
||||||
|
indexing.syncTasks();
|
||||||
|
|
||||||
auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 1, 6);
|
auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 1, 6);
|
||||||
ASSERT_THAT(locations,
|
ASSERT_THAT(locations,
|
||||||
@@ -108,6 +109,7 @@ TEST_F(SymbolIndexing, Locations)
|
|||||||
TEST_F(SymbolIndexing, DISABLED_TemplateFunction)
|
TEST_F(SymbolIndexing, DISABLED_TemplateFunction)
|
||||||
{
|
{
|
||||||
indexing.indexer().updateProjectParts({projectPart1}, {});
|
indexing.indexer().updateProjectParts({projectPart1}, {});
|
||||||
|
indexing.syncTasks();
|
||||||
|
|
||||||
auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 21, 24);
|
auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 21, 24);
|
||||||
ASSERT_THAT(locations,
|
ASSERT_THAT(locations,
|
||||||
@@ -122,6 +124,8 @@ TEST_F(SymbolIndexing, PathsAreUpdated)
|
|||||||
|
|
||||||
indexing.indexer().pathsChanged({filePathId(main1Path)});
|
indexing.indexer().pathsChanged({filePathId(main1Path)});
|
||||||
indexing.indexer().pathsChanged({filePathId(main1Path)});
|
indexing.indexer().pathsChanged({filePathId(main1Path)});
|
||||||
|
indexing.syncTasks();
|
||||||
|
|
||||||
auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 1, 6);
|
auto locations = query.locationsAt(filePathId(TESTDATA_DIR "/symbolindexing_main1.cpp"), 1, 6);
|
||||||
ASSERT_THAT(locations,
|
ASSERT_THAT(locations,
|
||||||
ElementsAre(
|
ElementsAre(
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ protected:
|
|||||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
|
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
|
||||||
FilePathCaching filePathCache{database};
|
FilePathCaching filePathCache{database};
|
||||||
ClangBackEnd::SymbolsCollector collector{filePathCache};
|
ClangBackEnd::SymbolsCollector collector{database};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(SymbolsCollector, CollectSymbolName)
|
TEST_F(SymbolsCollector, CollectSymbolName)
|
||||||
|
|||||||
80
tests/unit/unittest/symbolscollectormanager-test.cpp
Normal file
80
tests/unit/unittest/symbolscollectormanager-test.cpp
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 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 "mocksymbolscollector.h"
|
||||||
|
|
||||||
|
#include <sqlitedatabase.h>
|
||||||
|
#include <refactoringdatabaseinitializer.h>
|
||||||
|
#include <symbolscollectormanager.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class SymbolsCollectorManager : public testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||||
|
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
|
||||||
|
ClangBackEnd::SymbolsCollectorManager<NiceMock<MockSymbolsCollector>> manager{database};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(SymbolsCollectorManager, CreateUnsedSystemCollector)
|
||||||
|
{
|
||||||
|
manager.unusedSymbolsCollector();
|
||||||
|
|
||||||
|
manager.unusedSymbolsCollector();
|
||||||
|
|
||||||
|
ASSERT_THAT(manager.collectors(), SizeIs(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolsCollectorManager, ReuseUnsedSystemCollector)
|
||||||
|
{
|
||||||
|
auto &collector = manager.unusedSymbolsCollector();
|
||||||
|
collector.setIsUsed(false);
|
||||||
|
|
||||||
|
manager.unusedSymbolsCollector();
|
||||||
|
|
||||||
|
ASSERT_THAT(manager.collectors(), SizeIs(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolsCollectorManager, AsGetNewUnusedSymbolsCollectorItIsSetUsed)
|
||||||
|
{
|
||||||
|
auto &collector = manager.unusedSymbolsCollector();
|
||||||
|
|
||||||
|
ASSERT_TRUE(collector.isUsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolsCollectorManager, AsGetReusedUnusedSymbolsCollectorItIsSetUsed)
|
||||||
|
{
|
||||||
|
auto &collector = manager.unusedSymbolsCollector();
|
||||||
|
collector.setIsUsed(false);
|
||||||
|
|
||||||
|
auto &collector2 = manager.unusedSymbolsCollector();
|
||||||
|
|
||||||
|
ASSERT_TRUE(collector2.isUsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -194,7 +194,7 @@ TEST_F(SymbolStorage, InsertProjectPart)
|
|||||||
TypedEq<Utils::SmallStringView>("[\"foo\"]"),
|
TypedEq<Utils::SmallStringView>("[\"foo\"]"),
|
||||||
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
|
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
|
||||||
TypedEq<Utils::SmallStringView>("[\"/includes\"]")));
|
TypedEq<Utils::SmallStringView>("[\"/includes\"]")));
|
||||||
EXPECT_CALL(mockDatabase, lastInsertedRowId());
|
EXPECT_CALL(mockDatabase, lastInsertedRowId()).Times(2);
|
||||||
|
|
||||||
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"});
|
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"});
|
||||||
}
|
}
|
||||||
@@ -216,6 +216,7 @@ TEST_F(SymbolStorage, UpdateProjectPart)
|
|||||||
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
|
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
|
||||||
TypedEq<Utils::SmallStringView>("[\"/includes\"]"),
|
TypedEq<Utils::SmallStringView>("[\"/includes\"]"),
|
||||||
TypedEq<Utils::SmallStringView>("project")));
|
TypedEq<Utils::SmallStringView>("project")));
|
||||||
|
EXPECT_CALL(mockDatabase, lastInsertedRowId());
|
||||||
|
|
||||||
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"});
|
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ SOURCES += \
|
|||||||
generatedfiles-test.cpp \
|
generatedfiles-test.cpp \
|
||||||
sourcesmanager-test.cpp \
|
sourcesmanager-test.cpp \
|
||||||
symbolindexertaskqueue-test.cpp \
|
symbolindexertaskqueue-test.cpp \
|
||||||
symbolindexertaskscheduler-test.cpp
|
symbolindexertaskscheduler-test.cpp \
|
||||||
|
symbolscollectormanager-test.cpp
|
||||||
|
|
||||||
!isEmpty(LIBCLANG_LIBS) {
|
!isEmpty(LIBCLANG_LIBS) {
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@@ -174,7 +175,7 @@ SOURCES += \
|
|||||||
symbolindexing-test.cpp \
|
symbolindexing-test.cpp \
|
||||||
symbolscollector-test.cpp \
|
symbolscollector-test.cpp \
|
||||||
symbolfinder-test.cpp \
|
symbolfinder-test.cpp \
|
||||||
testclangtool.cpp \
|
testclangtool.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
exists($$GOOGLEBENCHMARK_DIR) {
|
exists($$GOOGLEBENCHMARK_DIR) {
|
||||||
@@ -235,7 +236,9 @@ HEADERS += \
|
|||||||
mockprecompiledheaderstorage.h \
|
mockprecompiledheaderstorage.h \
|
||||||
mockeditormanager.h \
|
mockeditormanager.h \
|
||||||
mocksymbolscollectormanager.h \
|
mocksymbolscollectormanager.h \
|
||||||
mocksymbolindexertaskqueue.h
|
mocksymbolindexertaskqueue.h \
|
||||||
|
mocksymbolindexertaskscheduler.h
|
||||||
|
|
||||||
!isEmpty(LIBCLANG_LIBS) {
|
!isEmpty(LIBCLANG_LIBS) {
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
chunksreportedmonitor.h \
|
chunksreportedmonitor.h \
|
||||||
|
|||||||
Reference in New Issue
Block a user