Clang: Add file cache

The database is using file path integer ids to handle file paths because
otherwise we would save many redundant data. This patch is improving it
further with the introduction of a database based file path cache. The
entries are now divided in a directory path and file name. This is quite
handy for directory based file watching.

Change-Id: I03f2e388e43f3d521d6bf8e39dfb95eb2309dc73
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-09-21 11:43:59 +02:00
committed by Tim Jenssen
parent 0be8240002
commit d2e15e5f1e
135 changed files with 3458 additions and 1517 deletions

View File

@@ -67,7 +67,6 @@ SOURCES += \
$$PWD/requestsourcelocationforrenamingmessage.cpp \ $$PWD/requestsourcelocationforrenamingmessage.cpp \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \ $$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \
$$PWD/requestsourcerangesforquerymessage.cpp \ $$PWD/requestsourcerangesforquerymessage.cpp \
$$PWD/sourcefilepathcontainerbase.cpp \
$$PWD/sourcelocationcontainer.cpp \ $$PWD/sourcelocationcontainer.cpp \
$$PWD/sourcelocationcontainerv2.cpp \ $$PWD/sourcelocationcontainerv2.cpp \
$$PWD/sourcelocationscontainer.cpp \ $$PWD/sourcelocationscontainer.cpp \
@@ -82,7 +81,9 @@ SOURCES += \
$$PWD/updatepchprojectpartsmessage.cpp \ $$PWD/updatepchprojectpartsmessage.cpp \
$$PWD/updatetranslationunitsforeditormessage.cpp \ $$PWD/updatetranslationunitsforeditormessage.cpp \
$$PWD/updatevisibletranslationunitsmessage.cpp \ $$PWD/updatevisibletranslationunitsmessage.cpp \
$$PWD/writemessageblock.cpp $$PWD/writemessageblock.cpp \
$$PWD/filepathcaching.cpp \
$$PWD/filepathid.cpp
HEADERS += \ HEADERS += \
$$PWD/cancelmessage.h \ $$PWD/cancelmessage.h \
@@ -150,7 +151,6 @@ HEADERS += \
$$PWD/requestsourcelocationforrenamingmessage.h \ $$PWD/requestsourcelocationforrenamingmessage.h \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \ $$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \
$$PWD/requestsourcerangesforquerymessage.h \ $$PWD/requestsourcerangesforquerymessage.h \
$$PWD/sourcefilepathcontainerbase.h \
$$PWD/sourcelocationcontainer.h \ $$PWD/sourcelocationcontainer.h \
$$PWD/sourcelocationcontainerv2.h \ $$PWD/sourcelocationcontainerv2.h \
$$PWD/sourcelocationscontainer.h \ $$PWD/sourcelocationscontainer.h \
@@ -172,6 +172,15 @@ HEADERS += \
$$PWD/stringcachefwd.h \ $$PWD/stringcachefwd.h \
$$PWD/stringcachealgorithms.h \ $$PWD/stringcachealgorithms.h \
$$PWD/projectmanagementserverinterface.h \ $$PWD/projectmanagementserverinterface.h \
$$PWD/refactoringdatabaseinitializer.h $$PWD/refactoringdatabaseinitializer.h \
$$PWD/filepathcache.h \
$$PWD/filepathid.h \
$$PWD/filepathstorage.h \
$$PWD/filepathstoragesqlitestatementfactory.h \
$$PWD/filepathstoragesources.h \
$$PWD/filepathexceptions.h \
$$PWD/filepathcachinginterface.h \
$$PWD/filepathcaching.h \
$$PWD/filepathcachingfwd.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -94,9 +94,7 @@ public:
DynamicASTMatcherDiagnosticMessageContainer clone() const DynamicASTMatcherDiagnosticMessageContainer clone() const
{ {
return DynamicASTMatcherDiagnosticMessageContainer(m_sourceRange.clone(), return *this;
m_errorType,
m_arguments.clone());
} }
private: private:

View File

@@ -63,22 +63,27 @@ public:
{ {
} }
FilePath(const Utils::PathString &directory, const Utils::PathString &name) FilePath(Utils::SmallStringView directory, Utils::SmallStringView name)
: m_path({std::move(directory), "/", std::move(name)}), : m_path({directory, "/", name}),
m_slashIndex(directory.size()) m_slashIndex(directory.size())
{} {}
Utils::SmallStringView directory() const Utils::SmallStringView directory() const noexcept
{ {
return m_path.mid(0, m_slashIndex); return m_path.mid(0, m_slashIndex);
} }
Utils::SmallStringView name() const Utils::SmallStringView name() const noexcept
{ {
return m_path.mid(m_slashIndex + 1, m_path.size() - m_slashIndex - 1); return m_path.mid(m_slashIndex + 1, m_path.size() - m_slashIndex - 1);
} }
const Utils::PathString &path() const const Utils::PathString &path() const noexcept
{
return m_path;
}
operator Utils::PathString() const noexcept
{ {
return m_path; return m_path;
} }
@@ -105,9 +110,7 @@ public:
friend std::ostream &operator<<(std::ostream &out, const FilePath &filePath) friend std::ostream &operator<<(std::ostream &out, const FilePath &filePath)
{ {
out << filePath.directory() << "/" << filePath.name(); return out << "(" << filePath.path() << ", " << filePath.slashIndex() << ")";
return out;
} }
friend bool operator==(const FilePath &first, const FilePath &second) friend bool operator==(const FilePath &first, const FilePath &second)
@@ -115,6 +118,16 @@ public:
return first.m_path == second.m_path; return first.m_path == second.m_path;
} }
friend bool operator==(const FilePath &first, const Utils::SmallStringView &second)
{
return first.path() == second;
}
friend bool operator==(const Utils::SmallStringView &first, const FilePath&second)
{
return second == first;
}
friend bool operator<(const FilePath &first, const FilePath &second) friend bool operator<(const FilePath &first, const FilePath &second)
{ {
return first.m_path < second.m_path; return first.m_path < second.m_path;
@@ -125,11 +138,18 @@ public:
return *this; return *this;
} }
std::size_t slashIndex() const
{
return m_slashIndex;
}
private: private:
Utils::PathString m_path = "/"; Utils::PathString m_path = "/";
std::size_t m_slashIndex = 0; std::size_t m_slashIndex = 0;
}; };
using FilePaths = std::vector<FilePath>;
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath); CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath);
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,128 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "filepathexceptions.h"
#include "filepathid.h"
#include "filepath.h"
#include "stringcache.h"
#include <utils/smallstringview.h>
#include <algorithm>
namespace ClangBackEnd {
class FilePathCacheBase
{
public:
static
std::ptrdiff_t lastSlashIndex(Utils::SmallStringView filePath)
{
auto foundReverse = std::find(filePath.rbegin(), filePath.rend(), '/');
auto found = foundReverse.base();
--found;
return std::distance(filePath.begin(), found);
}
static
Utils::SmallStringView directoryPath(Utils::SmallStringView filePath, std::ptrdiff_t slashIndex)
{
return {filePath.data(), std::size_t(std::max(std::ptrdiff_t(0), slashIndex))};
}
static
Utils::SmallStringView fileName(Utils::SmallStringView filePath, std::ptrdiff_t slashIndex)
{
return {filePath.data() + slashIndex + 1, filePath.size() - std::size_t(slashIndex) - 1};
}
};
template <typename FilePathStorage>
class FilePathCache final : private FilePathCacheBase
{
using DirectoryPathCache = StringCache<Utils::PathString,
int,
std::mutex,
decltype(&Utils::reverseCompare),
Utils::reverseCompare>;
using FileNameCache = StringCache<Utils::SmallString,
int,
std::mutex,
decltype(&Utils::compare),
Utils::compare>;
public:
FilePathCache(FilePathStorage &filePathStorage)
: m_filePathStorage(filePathStorage)
{}
FilePathId filePathId(Utils::SmallStringView filePath) const
{
std::ptrdiff_t slashIndex = lastSlashIndex(filePath);
Utils::SmallStringView directoryPath = this->directoryPath(filePath, slashIndex);
int directoryId = m_directyPathCache.stringId(directoryPath,
[&] (const Utils::SmallStringView) {
return m_filePathStorage.fetchDirectoryId(directoryPath);
});
Utils::SmallStringView fileName = this->fileName(filePath, slashIndex);
int fileNameId = m_fileNameCache.stringId(fileName,
[&] (const Utils::SmallStringView) {
return m_filePathStorage.fetchSourceId(directoryId, fileName);
});
return {directoryId, fileNameId};
}
FilePath filePath(FilePathId filePathId) const
{
if (Q_UNLIKELY(!filePathId.isValid()))
throw NoFilePathForInvalidFilePathId();
auto fetchFilePath = [&] (int id) { return m_filePathStorage.fetchDirectoryPath(id); };
Utils::PathString directoryPath = m_directyPathCache.string(filePathId.directoryId,
fetchFilePath);
auto fetchSoureName = [&] (int id) { return m_filePathStorage.fetchSourceName(id); };
Utils::SmallString fileName = m_fileNameCache.string(filePathId.fileNameId,
fetchSoureName);
return {directoryPath, fileName};
}
private:
mutable DirectoryPathCache m_directyPathCache;
mutable FileNameCache m_fileNameCache;
FilePathStorage &m_filePathStorage;
};
} // namespace ClangBackEnd

View File

@@ -23,20 +23,18 @@
** **
****************************************************************************/ ****************************************************************************/
#include "sourcelocationentry.h" #include "filepathcaching.h"
#include <utils/smallstringio.h>
namespace ClangBackEnd { namespace ClangBackEnd {
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry) FilePathId FilePathCaching::filePathId(Utils::SmallStringView filePath) const
{ {
out << "(" return m_cache.filePathId(filePath);
<< entry.fileId << ", " }
<< entry.line << ", "
<< entry.column << ")";
return out; FilePath FilePathCaching::filePath(FilePathId filePathId) const
{
return m_cache.filePath(filePathId);
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "clangsupport_global.h"
#include "filepathcachinginterface.h"
#include "filepathcache.h"
#include "filepathstoragesqlitestatementfactory.h"
#include "filepathstorage.h"
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
namespace ClangBackEnd {
class CMBIPC_EXPORT FilePathCaching final : public FilePathCachingInterface
{
using Factory = FilePathStorageSqliteStatementFactory<Sqlite::Database,
Sqlite::ReadStatement,
Sqlite::WriteStatement>;
using Storage = FilePathStorage<Factory>;
using Cache = FilePathCache<Storage>;
public:
FilePathCaching(Sqlite::Database &database)
: m_factory(database)
{}
FilePathId filePathId(Utils::SmallStringView filePath) const override;
FilePath filePath(FilePathId filePathId) const override;
private:
Factory m_factory;
Storage m_storage{m_factory};
Cache m_cache{m_storage};
};
} // namespace ClangBackEnd

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -23,10 +23,10 @@
** **
****************************************************************************/ ****************************************************************************/
#include "sourcefilepathcontainerbase.h" #pragma once
namespace ClangBackEnd { namespace ClangBackEnd {
class FilePathCachingInterface;
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "filepath.h"
#include "filepathid.h"
namespace ClangBackEnd {
class FilePathCachingInterface
{
public:
virtual FilePathId filePathId(Utils::SmallStringView filePath) const = 0;
virtual FilePath filePath(FilePathId filePathId) const = 0;
template <typename Container>
FilePathIds filePathIds(Container &&filePaths) const
{
FilePathIds filePathIds;
filePathIds.reserve(filePaths.size());
std::transform(filePaths.begin(),
filePaths.end(),
std::back_inserter(filePathIds),
[&] (const auto &filePath) { return this->filePathId(filePath); });
return filePathIds;
}
template <typename Element>
FilePathIds filePathIds(std::initializer_list<Element> filePaths) const
{
return filePathIds(std::vector<Element>(filePaths));
}
FilePaths filePaths(const FilePathIds &filePathIds) const
{
FilePaths filePaths;
filePaths.reserve(filePathIds.size());
std::transform(filePathIds.begin(),
filePathIds.end(),
std::back_inserter(filePaths),
[&] (auto filePathId) { return this->filePath(filePathId); });
return filePaths;
}
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <exception>
namespace ClangBackEnd {
class NoFilePathForInvalidFilePathId : std::exception
{
public:
const char *what() const noexcept override
{
return "You cannot get a file path for an invalid file path id!";
}
};
class SourceNameIdDoesNotExists : std::exception
{
public:
const char *what() const noexcept override
{
return "The source name id does not exists in the database!";
}
};
class DirectoryPathIdDoesNotExists : std::exception
{
public:
const char *what() const noexcept override
{
return "The directory path id does not exists in the database!";
}
};
} // namespace ClangBackEnd

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -23,19 +23,17 @@
** **
****************************************************************************/ ****************************************************************************/
#include "idpaths.h" #include "filepathid.h"
#include <utils/smallstringio.h> #include <QDebug>
namespace ClangBackEnd { namespace ClangBackEnd {
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths) QDebug operator<<(QDebug debug, const FilePathId &filePathId)
{ {
out << "(" debug.nospace() << "(" << filePathId.directoryId << ", " << filePathId.fileNameId << ")";
<< idPaths.id << ", "
<< idPaths.paths << ")";
return out; return debug;
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,113 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "clangsupport_global.h"
#include <QDataStream>
#include <cstdint>
#include <tuple>
#include <vector>
namespace ClangBackEnd {
class FilePathId
{
public:
FilePathId() = default;
FilePathId(int directoryId, int fileNameId)
: directoryId(directoryId),
fileNameId(fileNameId)
{}
bool isValid() const
{
return directoryId >= 0 && fileNameId >= 0;
}
friend bool operator==(FilePathId first, FilePathId second)
{
return first.isValid()
&& second.isValid()
&& first.directoryId == second.directoryId
&& first.fileNameId == second.fileNameId;
}
friend bool operator!=(FilePathId first, FilePathId second)
{
return !(first==second);
}
friend bool operator<(FilePathId first, FilePathId second)
{
return std::tie(first.directoryId, first.fileNameId)
< std::tie(second.directoryId, second.fileNameId);
}
friend QDataStream &operator<<(QDataStream &out, const FilePathId &filePathId)
{
out << filePathId.directoryId;
out << filePathId.fileNameId;
return out;
}
friend QDataStream &operator>>(QDataStream &in, FilePathId &filePathId)
{
in >> filePathId.directoryId;
in >> filePathId.fileNameId;
return in;
}
public:
int directoryId = -1;
int fileNameId = -1;
};
using FilePathIds = std::vector<FilePathId>;
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePathId &filePathId);
} // namespace ClangBackEnd
namespace std {
template<> struct hash<ClangBackEnd::FilePathId>
{
using argument_type = ClangBackEnd::FilePathId;
using result_type = std::size_t;
result_type operator()(const argument_type& filePathId) const
{
long long hash = filePathId.directoryId;
hash = hash << 32;
hash += filePathId.fileNameId;
return std::hash<long long>{}(hash);
}
};
} // namespace std

View File

@@ -0,0 +1,187 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "filepathexceptions.h"
#include "filepathid.h"
#include "filepathstoragesources.h"
#include <sqliteexception.h>
#include <sqlitetransaction.h>
#include <utils/optional.h>
namespace ClangBackEnd {
template <typename StatementFactory>
class FilePathStorage
{
using DeferredTransaction = Sqlite::DeferredTransaction<typename StatementFactory::DatabaseType>;
using ImmediateTransaction = Sqlite::ImmediateTransaction<typename StatementFactory::DatabaseType>;
using ReadStatement = typename StatementFactory::ReadStatementType;
using WriteStatement = typename StatementFactory::WriteStatementType;
using Database = typename StatementFactory::DatabaseType;
public:
FilePathStorage(StatementFactory &statementFactory)
: m_statementFactory(statementFactory)
{}
int fetchDirectoryId(Utils::SmallStringView directoryPath)
try {
DeferredTransaction transaction{m_statementFactory.database};
Utils::optional<int> optionalDirectoryId = readDirectoryId(directoryPath);
int directoryId = -1;
if (optionalDirectoryId)
directoryId = optionalDirectoryId.value();
else
directoryId = writeDirectoryId(directoryPath);
transaction.commit();
return directoryId;
} catch (Sqlite::StatementIsBusy &) {
return fetchDirectoryId(directoryPath);
}
Utils::optional<int> readDirectoryId(Utils::SmallStringView directoryPath)
{
ReadStatement &statement = m_statementFactory.selectDirectoryIdFromDirectoriesByDirectoryPath;
return statement.template value<int>(directoryPath);
}
int writeDirectoryId(Utils::SmallStringView directoryPath)
{
WriteStatement &statement = m_statementFactory.insertIntoDirectories;
statement.write(directoryPath);
return int(m_statementFactory.database.lastInsertedRowId());
}
Utils::PathString fetchDirectoryPath(int directoryPathId)
{
DeferredTransaction transaction{m_statementFactory.database};
ReadStatement &statement = m_statementFactory.selectDirectoryPathFromDirectoriesByDirectoryId;
auto optionalDirectoryPath = statement.template value<Utils::PathString>(directoryPathId);
if (!optionalDirectoryPath)
throw DirectoryPathIdDoesNotExists();
transaction.commit();
return optionalDirectoryPath.value();
}
std::vector<Sources::Directory> fetchAllDirectories()
{
DeferredTransaction transaction{m_statementFactory.database};
ReadStatement &statement = m_statementFactory.selectAllDirectories;
auto directories = statement.template values<Sources::Directory, 2>(256);
transaction.commit();
return directories;
}
int fetchSourceId(int directoryId, Utils::SmallStringView sourceName)
try {
DeferredTransaction transaction{m_statementFactory.database};
Utils::optional<int> optionalSourceId = readSourceId(directoryId, sourceName);
int sourceId = -1;
if (optionalSourceId)
sourceId = optionalSourceId.value();
else
sourceId = writeSourceId(directoryId, sourceName);
transaction.commit();
return sourceId;
} catch (Sqlite::StatementIsBusy &) {
return fetchSourceId(directoryId, sourceName);
}
int writeSourceId(int directoryId, Utils::SmallStringView sourceName)
{
WriteStatement &statement = m_statementFactory.insertIntoSources;
statement.write(directoryId, sourceName);
return int(m_statementFactory.database.lastInsertedRowId());
}
Utils::optional<int> readSourceId(int directoryId, Utils::SmallStringView sourceName)
{
ReadStatement &statement = m_statementFactory.selectSourceIdFromSourcesByDirectoryIdAndSourceName;
return statement.template value<int>(directoryId, sourceName);
}
Utils::SmallString fetchSourceName(int sourceId)
{
DeferredTransaction transaction{m_statementFactory.database};
ReadStatement &statement = m_statementFactory.selectSourceNameFromSourcesBySourceId;
auto optionalSourceName = statement.template value<Utils::SmallString>(sourceId);
if (!optionalSourceName)
throw SourceNameIdDoesNotExists();
transaction.commit();
return optionalSourceName.value();
}
std::vector<Sources::Source> fetchAllSources()
{
DeferredTransaction transaction{m_statementFactory.database};
ReadStatement &statement = m_statementFactory.selectAllSources;
auto sources = statement.template values<Sources::Source, 2>(8192);
transaction.commit();
return sources;
}
private:
StatementFactory &m_statementFactory;
};
} // namespace ClangBackEnd

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -25,41 +25,50 @@
#pragma once #pragma once
#include "filepath.h" #include <utils/smallstring.h>
#include <cstdint>
#include <vector>
#include <tuple>
#include <unordered_map> #include <unordered_map>
namespace ClangBackEnd { namespace ClangBackEnd {
namespace Sources {
using FilePathDict = std::unordered_map<uint, FilePath>; class Directory
class SourceFilePathContainerBase
{ {
public: public:
SourceFilePathContainerBase() = default; Directory(int directoryId, Utils::PathString &&directoryPath)
SourceFilePathContainerBase(std::unordered_map<uint, FilePath> &&filePathHash) : directoryId(directoryId), directoryPath(std::move(directoryPath))
: m_filePathHash(std::move(filePathHash)) {}
friend
bool operator==(const Directory &first, const Directory &second)
{ {
return first.directoryId == second.directoryId && first.directoryPath == second.directoryPath;
} }
void insertFilePath(uint fileId, Utils::PathString &&filePath) public:
{ int directoryId;
if (m_filePathHash.find(fileId) == m_filePathHash.end()) Utils::PathString directoryPath;
m_filePathHash.emplace(fileId, FilePath(std::move(filePath)));
}
void reserve(std::size_t size)
{
m_filePathHash.reserve(size / 3);
}
const FilePathDict &filePaths() const
{
return m_filePathHash;
}
protected:
FilePathDict m_filePathHash;
}; };
class Source
{
public:
Source(int sourceId, Utils::PathString &&sourceName)
: sourceId(sourceId), sourceName(std::move(sourceName))
{}
friend
bool operator==(const Source &first, const Source &second)
{
return first.sourceId == second.sourceId && first.sourceName == second.sourceName;
}
public:
int sourceId;
Utils::PathString sourceName;
};
} // namespace ClangBackEnd
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <sqlitetransaction.h>
#include <sqlitetable.h>
namespace ClangBackEnd {
template<typename Database,
typename ReadStatement,
typename WriteStatement>
class FilePathStorageSqliteStatementFactory
{
public:
using DatabaseType = Database;
using ReadStatementType = ReadStatement;
using WriteStatementType = WriteStatement;
FilePathStorageSqliteStatementFactory(Database &database)
: database(database)
{
}
public:
Database &database;
ReadStatement selectDirectoryIdFromDirectoriesByDirectoryPath{
"SELECT directoryId FROM directories WHERE directoryPath = ?",
database
};
ReadStatement selectDirectoryPathFromDirectoriesByDirectoryId{
"SELECT directoryPath FROM directories WHERE directoryId = ?",
database
};
ReadStatement selectAllDirectories{
"SELECT directoryId, directoryPath FROM directories",
database
};
WriteStatement insertIntoDirectories{
"INSERT INTO directories(directoryPath) VALUES (?)",
database
};
ReadStatement selectSourceIdFromSourcesByDirectoryIdAndSourceName{
"SELECT sourceId FROM sources WHERE directoryId = ? AND sourceName = ?",
database
};
ReadStatement selectSourceNameFromSourcesBySourceId{
"SELECT sourceName FROM sources WHERE sourceId = ?",
database
};
WriteStatement insertIntoSources{
"INSERT INTO sources(directoryId, sourceName) VALUES (?,?)",
database
};
ReadStatement selectAllSources{
"SELECT sourceId, sourceName FROM sources",
database
};
};
} // namespace ClangBackEnd

View File

@@ -44,6 +44,7 @@ public:
createSymbolsTable(); createSymbolsTable();
createLocationsTable(); createLocationsTable();
createSourcesTable(); createSourcesTable();
createDirectoriesTable();
transaction.commit(); transaction.commit();
} }
@@ -67,10 +68,10 @@ public:
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("locations"); table.setName("locations");
table.addColumn("symbolId", Sqlite::ColumnType::Integer); table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer); const Sqlite::Column &lineColumn = table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer); const Sqlite::Column &columnColumn = table.addColumn("column", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn}); table.addIndex({sourceIdColumn, lineColumn, columnColumn});
table.initialize(database); table.initialize(database);
} }
@@ -81,7 +82,22 @@ public:
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("sources"); table.setName("sources");
table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("sourcePath", Sqlite::ColumnType::Text); table.addColumn("directoryId", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceNameColumn = table.addColumn("sourceName", Sqlite::ColumnType::Text);
table.addColumn("sourceType", Sqlite::ColumnType::Integer);
table.addIndex({sourceNameColumn});
table.initialize(database);
}
void createDirectoriesTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("directories");
table.addColumn("directoryId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
const Sqlite::Column &directoryPathColumn = table.addColumn("directoryPath", Sqlite::ColumnType::Text);
table.addIndex({directoryPathColumn});
table.initialize(database); table.initialize(database);
} }

View File

@@ -38,15 +38,15 @@ QDebug operator<<(QDebug debug, const SourceLocationContainer &container)
<< container.line() << ", " << container.line() << ", "
<< container.column() << ", " << container.column() << ", "
<< container.offset() << ", " << container.offset() << ", "
<< container.fileHash() << container.filePathId().fileNameId
<< ")"; << ")";
return debug; return debug;
} }
std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container) std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container)
{ {
os << "(" os << "(("
<< container.fileHash() << ", " << container.filePathId().directoryId << ", " << container.filePathId().fileNameId << "), "
<< container.line() << ", " << container.line() << ", "
<< container.column() << ", " << container.column() << ", "
<< container.offset() << container.offset()

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include "clangsupport_global.h" #include "clangsupport_global.h"
#include "filepathid.h"
#include <QDataStream> #include <QDataStream>
@@ -37,20 +38,20 @@ class SourceLocationContainer
{ {
public: public:
SourceLocationContainer() = default; SourceLocationContainer() = default;
SourceLocationContainer(uint fileHash, SourceLocationContainer(FilePathId filePathId,
uint line, uint line,
uint column, uint column,
uint offset) uint offset)
: m_fileHash(fileHash), : m_filePathId(filePathId),
m_line(line), m_line(line),
m_column(column), m_column(column),
m_offset(offset) m_offset(offset)
{ {
} }
uint fileHash() const FilePathId filePathId() const
{ {
return m_fileHash; return m_filePathId;
} }
uint line() const uint line() const
@@ -70,7 +71,7 @@ public:
friend QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container) friend QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container)
{ {
out << container.m_fileHash; out << container.m_filePathId;
out << container.m_line; out << container.m_line;
out << container.m_column; out << container.m_column;
out << container.m_offset; out << container.m_offset;
@@ -80,7 +81,7 @@ public:
friend QDataStream &operator>>(QDataStream &in, SourceLocationContainer &container) friend QDataStream &operator>>(QDataStream &in, SourceLocationContainer &container)
{ {
in >> container.m_fileHash; in >> container.m_filePathId;
in >> container.m_line; in >> container.m_line;
in >> container.m_column; in >> container.m_column;
in >> container.m_offset; in >> container.m_offset;
@@ -97,23 +98,23 @@ public:
{ {
return first.m_line != second.m_line return first.m_line != second.m_line
|| first.m_column != second.m_column || first.m_column != second.m_column
|| first.m_fileHash != second.m_fileHash; || first.m_filePathId != second.m_filePathId;
} }
friend bool operator<(const SourceLocationContainer &first, friend bool operator<(const SourceLocationContainer &first,
const SourceLocationContainer &second) const SourceLocationContainer &second)
{ {
return std::tie(first.m_fileHash, first.m_line, first.m_column) return std::tie(first.m_filePathId, first.m_line, first.m_column)
< std::tie(second.m_fileHash, second.m_line, second.m_column); < std::tie(second.m_filePathId, second.m_line, second.m_column);
} }
SourceLocationContainer clone() const SourceLocationContainer clone() const
{ {
return SourceLocationContainer(m_fileHash, m_line, m_column, m_offset); return *this;
} }
private: private:
uint m_fileHash = 0; FilePathId m_filePathId;
uint m_line = 1; uint m_line = 1;
uint m_column = 1; uint m_column = 1;
uint m_offset = 0; uint m_offset = 0;

View File

@@ -33,10 +33,10 @@ QDebug operator<<(QDebug debug, const SourceLocationsContainer &container)
{ {
debug.nospace() << "SourceLocationsContainer(["; debug.nospace() << "SourceLocationsContainer([";
for (const auto &sourceLocation: container.sourceLocationContainers()) { for (const auto &sourceLocation: container.sourceLocationContainers()) {
debug.nospace() << "[" debug.nospace() << "("
<< container.filePathForSourceLocation(sourceLocation).name() << "," << sourceLocation.filePathId() << ","
<< sourceLocation.line() << "," << sourceLocation.line() << ","
<< sourceLocation.column() << "], "; << sourceLocation.column() << "), ";
} }
debug.nospace() << "])"; debug.nospace() << "])";

View File

@@ -25,30 +25,20 @@
#pragma once #pragma once
#include "sourcefilepathcontainerbase.h"
#include "sourcelocationcontainerv2.h" #include "sourcelocationcontainerv2.h"
#include <utils/smallstringvector.h> #include <utils/smallstringio.h>
namespace ClangBackEnd { namespace ClangBackEnd {
class SourceLocationsContainer : public SourceFilePathContainerBase class SourceLocationsContainer
{ {
public: public:
SourceLocationsContainer() = default; SourceLocationsContainer() = default;
SourceLocationsContainer(std::unordered_map<uint, FilePath> &&filePathHash, SourceLocationsContainer(std::vector<V2::SourceLocationContainer> &&sourceLocationContainers)
std::vector<V2::SourceLocationContainer> &&sourceLocationContainers) : m_sourceLocationContainers(std::move(sourceLocationContainers))
: SourceFilePathContainerBase(std::move(filePathHash)),
m_sourceLocationContainers(std::move(sourceLocationContainers))
{} {}
const FilePath &filePathForSourceLocation(const V2::SourceLocationContainer &sourceLocation) const
{
auto found = m_filePathHash.find(sourceLocation.fileHash());
return found->second;
}
const std::vector<V2::SourceLocationContainer> &sourceLocationContainers() const const std::vector<V2::SourceLocationContainer> &sourceLocationContainers() const
{ {
return m_sourceLocationContainers; return m_sourceLocationContainers;
@@ -59,20 +49,18 @@ public:
return !m_sourceLocationContainers.empty(); return !m_sourceLocationContainers.empty();
} }
void insertSourceLocation(uint fileId, uint line, uint column, uint offset) void insertSourceLocation(FilePathId filePathId, uint line, uint column, uint offset)
{ {
m_sourceLocationContainers.emplace_back(fileId, line, column, offset); m_sourceLocationContainers.emplace_back(filePathId, line, column, offset);
} }
void reserve(std::size_t size) void reserve(std::size_t size)
{ {
SourceFilePathContainerBase::reserve(size);
m_sourceLocationContainers.reserve(size); m_sourceLocationContainers.reserve(size);
} }
friend QDataStream &operator<<(QDataStream &out, const SourceLocationsContainer &container) friend QDataStream &operator<<(QDataStream &out, const SourceLocationsContainer &container)
{ {
out << container.m_filePathHash;
out << container.m_sourceLocationContainers; out << container.m_sourceLocationContainers;
return out; return out;
@@ -80,7 +68,6 @@ public:
friend QDataStream &operator>>(QDataStream &in, SourceLocationsContainer &container) friend QDataStream &operator>>(QDataStream &in, SourceLocationsContainer &container)
{ {
in >> container.m_filePathHash;
in >> container.m_sourceLocationContainers; in >> container.m_sourceLocationContainers;
return in; return in;
@@ -93,7 +80,7 @@ public:
SourceLocationsContainer clone() const SourceLocationsContainer clone() const
{ {
return SourceLocationsContainer(Utils::clone(m_filePathHash), Utils::clone(m_sourceLocationContainers)); return *this;
} }
std::vector<V2::SourceLocationContainer> m_sourceLocationContainers; std::vector<V2::SourceLocationContainer> m_sourceLocationContainers;

View File

@@ -43,15 +43,15 @@ public:
{ {
} }
SourceRangeContainer(uint fileHash, SourceRangeContainer(FilePathId filePathId,
uint startLine, uint startLine,
uint startColumn, uint startColumn,
uint startOffset, uint startOffset,
uint endLine, uint endLine,
uint endColumn, uint endColumn,
uint endOffset) uint endOffset)
: m_start(fileHash, startLine, startColumn, startOffset), : m_start(filePathId, startLine, startColumn, startOffset),
m_end(fileHash, endLine, endColumn, endOffset) m_end(filePathId, endLine, endColumn, endOffset)
{ {
} }
@@ -65,9 +65,9 @@ public:
return m_end; return m_end;
} }
uint fileHash() const FilePathId filePathId() const
{ {
return m_start.fileHash(); return m_start.filePathId();
} }
friend QDataStream &operator<<(QDataStream &out, const SourceRangeContainer &container) friend QDataStream &operator<<(QDataStream &out, const SourceRangeContainer &container)
@@ -99,7 +99,7 @@ public:
SourceRangeContainer clone() const SourceRangeContainer clone() const
{ {
return SourceRangeContainer(m_start.clone(), m_end.clone()); return *this;
} }
private: private:

View File

@@ -31,12 +31,11 @@ QDebug operator<<(QDebug debug, const SourceRangesContainer &container)
{ {
debug.nospace() << "SourceRangesContainer(["; debug.nospace() << "SourceRangesContainer([";
for (const auto &sourceRangeWithText: container.sourceRangeWithTextContainers()) { for (const auto &sourceRangeWithText: container.sourceRangeWithTextContainers()) {
debug.nospace() << "[" debug.nospace() << "("
<< container.filePathForSourceRange(sourceRangeWithText).name() << ", ("
<< sourceRangeWithText.start().line() << "," << sourceRangeWithText.start().line() << ","
<< sourceRangeWithText.start().column() << "), (" << sourceRangeWithText.start().column() << "), ("
<< sourceRangeWithText.end().line() << "," << sourceRangeWithText.end().line() << ","
<< sourceRangeWithText.end().column() << ")], "; << sourceRangeWithText.end().column() << "), ";
} }
debug.nospace() << "])"; debug.nospace() << "])";

View File

@@ -25,30 +25,20 @@
#pragma once #pragma once
#include "sourcefilepathcontainerbase.h"
#include "sourcerangewithtextcontainer.h" #include "sourcerangewithtextcontainer.h"
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
namespace ClangBackEnd { namespace ClangBackEnd {
class SourceRangesContainer : public SourceFilePathContainerBase class SourceRangesContainer
{ {
public: public:
SourceRangesContainer() = default; SourceRangesContainer() = default;
SourceRangesContainer(std::unordered_map<uint, FilePath> &&filePathHash, SourceRangesContainer(SourceRangeWithTextContainers &&sourceRangeWithTextContainers)
SourceRangeWithTextContainers &&sourceRangeWithTextContainers) : m_sourceRangeWithTextContainers(std::move(sourceRangeWithTextContainers))
: SourceFilePathContainerBase(std::move(filePathHash)),
m_sourceRangeWithTextContainers(std::move(sourceRangeWithTextContainers))
{} {}
const FilePath &filePathForSourceRange(const SourceRangeWithTextContainer &sourceRange) const
{
auto found = m_filePathHash.find(sourceRange.fileHash());
return found->second;
}
const SourceRangeWithTextContainers &sourceRangeWithTextContainers() const const SourceRangeWithTextContainers &sourceRangeWithTextContainers() const
{ {
return m_sourceRangeWithTextContainers; return m_sourceRangeWithTextContainers;
@@ -69,7 +59,7 @@ public:
return !m_sourceRangeWithTextContainers.empty(); return !m_sourceRangeWithTextContainers.empty();
} }
void insertSourceRange(uint fileId, void insertSourceRange(FilePathId filePathId,
uint startLine, uint startLine,
uint startColumn, uint startColumn,
uint startOffset, uint startOffset,
@@ -78,7 +68,7 @@ public:
uint endOffset, uint endOffset,
Utils::SmallString &&text) Utils::SmallString &&text)
{ {
m_sourceRangeWithTextContainers.emplace_back(fileId, m_sourceRangeWithTextContainers.emplace_back(filePathId,
startLine, startLine,
startColumn, startColumn,
startOffset, startOffset,
@@ -90,13 +80,11 @@ public:
void reserve(std::size_t size) void reserve(std::size_t size)
{ {
SourceFilePathContainerBase::reserve(size);
m_sourceRangeWithTextContainers.reserve(size); m_sourceRangeWithTextContainers.reserve(size);
} }
friend QDataStream &operator<<(QDataStream &out, const SourceRangesContainer &container) friend QDataStream &operator<<(QDataStream &out, const SourceRangesContainer &container)
{ {
out << container.m_filePathHash;
out << container.m_sourceRangeWithTextContainers; out << container.m_sourceRangeWithTextContainers;
return out; return out;
@@ -104,7 +92,6 @@ public:
friend QDataStream &operator>>(QDataStream &in, SourceRangesContainer &container) friend QDataStream &operator>>(QDataStream &in, SourceRangesContainer &container)
{ {
in >> container.m_filePathHash;
in >> container.m_sourceRangeWithTextContainers; in >> container.m_sourceRangeWithTextContainers;
return in; return in;

View File

@@ -35,7 +35,7 @@ class SourceRangeWithTextContainer : public V2::SourceRangeContainer
{ {
public: public:
SourceRangeWithTextContainer() = default; SourceRangeWithTextContainer() = default;
SourceRangeWithTextContainer(uint fileHash, SourceRangeWithTextContainer(FilePathId filePathId,
uint startLine, uint startLine,
uint startColumn, uint startColumn,
uint startOffset, uint startOffset,
@@ -43,7 +43,7 @@ public:
uint endColumn, uint endColumn,
uint endOffset, uint endOffset,
Utils::SmallString &&text) Utils::SmallString &&text)
: V2::SourceRangeContainer(fileHash, : V2::SourceRangeContainer(filePathId,
startLine, startLine,
startColumn, startColumn,
startOffset, startOffset,
@@ -67,7 +67,7 @@ public:
using V2::SourceRangeContainer::start; using V2::SourceRangeContainer::start;
using V2::SourceRangeContainer::end; using V2::SourceRangeContainer::end;
using V2::SourceRangeContainer::fileHash; using V2::SourceRangeContainer::filePathId;
friend QDataStream &operator<<(QDataStream &out, const SourceRangeWithTextContainer &container) friend QDataStream &operator<<(QDataStream &out, const SourceRangeWithTextContainer &container)
{ {

View File

@@ -28,6 +28,7 @@
#include "stringcachealgorithms.h" #include "stringcachealgorithms.h"
#include "stringcachefwd.h" #include "stringcachefwd.h"
#include <utils/optional.h>
#include <utils/smallstringview.h> #include <utils/smallstringview.h>
#include <utils/smallstringfwd.h> #include <utils/smallstringfwd.h>
@@ -70,15 +71,12 @@ public:
} }
StringType string; StringType string;
uint id; IndexType id;
}; };
template <typename StringType, typename IndexType> template <typename StringType, typename IndexType>
using StringCacheEntries = std::vector<StringCacheEntry<StringType, IndexType>>; using StringCacheEntries = std::vector<StringCacheEntry<StringType, IndexType>>;
using FileCacheCacheEntry = StringCacheEntry<Utils::PathString, FilePathIndex>;
using FileCacheCacheEntries = std::vector<FileCacheCacheEntry>;
template <typename StringType, template <typename StringType,
typename IndexType, typename IndexType,
typename Mutex, typename Mutex,
@@ -86,25 +84,26 @@ template <typename StringType,
Compare compare = Utils::compare> Compare compare = Utils::compare>
class StringCache class StringCache
{ {
using CacheEntry = StringCacheEntry<StringType, IndexType>;
using CacheEnties = StringCacheEntries<StringType, IndexType>;
using const_iterator = typename CacheEnties::const_iterator;
using Found = ClangBackEnd::Found<const_iterator>;
public: public:
StringCache() using CacheEntry = StringCacheEntry<StringType, IndexType>;
using CacheEntries = StringCacheEntries<StringType, IndexType>;
using const_iterator = typename CacheEntries::const_iterator;
using Found = ClangBackEnd::Found<const_iterator>;
StringCache(std::size_t reserveSize = 1024)
{ {
m_strings.reserve(1024); m_strings.reserve(reserveSize);
m_indices.reserve(1024); m_indices.reserve(reserveSize);
} }
void populate(CacheEnties &&entries) void populate(CacheEntries &&entries)
{ {
uncheckedPopulate(std::move(entries)); uncheckedPopulate(std::move(entries));
checkEntries(); checkEntries();
} }
void uncheckedPopulate(CacheEnties &&entries) void uncheckedPopulate(CacheEntries &&entries)
{ {
std::sort(entries.begin(), std::sort(entries.begin(),
entries.end(), entries.end(),
@@ -149,13 +148,35 @@ public:
return stringIds<std::initializer_list<StringType>>(strings); return stringIds<std::initializer_list<StringType>>(strings);
} }
Utils::SmallStringView string(IndexType id) const StringType string(IndexType id) const
{ {
std::lock_guard<Mutex> lock(m_mutex); std::lock_guard<Mutex> lock(m_mutex);
return m_strings.at(m_indices.at(id)).string; return m_strings.at(m_indices.at(id)).string;
} }
template<typename Function>
StringType string(IndexType id, Function storageFunction)
{
std::lock_guard<Mutex> lock(m_mutex);
IndexType index;
if (IndexType(m_indices.size()) <= id) {
StringType string{storageFunction(id)};
index = insertString(find(string).iterator, string, id);
} else {
index = m_indices.at(id);
if (index < 0) {
StringType string{storageFunction(id)};
index = insertString(find(string).iterator, string, id);
}
}
return m_strings.at(index).string;
}
std::vector<StringType> strings(const std::vector<IndexType> &ids) const std::vector<StringType> strings(const std::vector<IndexType> &ids) const
{ {
std::lock_guard<Mutex> lock(m_mutex); std::lock_guard<Mutex> lock(m_mutex);
@@ -176,13 +197,31 @@ public:
return m_strings.empty() && m_indices.empty(); return m_strings.empty() && m_indices.empty();
} }
template<typename Function>
IndexType stringId(Utils::SmallStringView stringView, Function storageFunction)
{
std::lock_guard<Mutex> lock(m_mutex);
Found found = find(stringView);
if (!found.wasFound)
insertString(found.iterator, stringView, storageFunction(stringView));
return found.iterator->id;
}
Mutex &mutex() const
{
return m_mutex;
}
private: private:
IndexType ungardedStringId(Utils::SmallStringView stringView) IndexType ungardedStringId(Utils::SmallStringView stringView)
{ {
Found found = find(stringView); Found found = find(stringView);
if (!found.wasFound) if (!found.wasFound)
return insertString(found.iterator, stringView); insertString(found.iterator, stringView, IndexType(m_indices.size()));
return found.iterator->id; return found.iterator->id;
} }
@@ -202,20 +241,26 @@ private:
}); });
} }
IndexType insertString(const_iterator beforeIterator, void ensureSize(IndexType id)
Utils::SmallStringView stringView)
{ {
auto id = IndexType(m_indices.size()); if (m_indices.size() <= std::size_t(id))
m_indices.resize(id + 1, -1);
}
IndexType insertString(const_iterator beforeIterator,
Utils::SmallStringView stringView,
IndexType id)
{
auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id); auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id);
auto newIndex = IndexType(std::distance(m_strings.begin(), inserted)); auto newIndex = IndexType(std::distance(m_strings.begin(), inserted));
incrementLargerOrEqualIndicesByOne(newIndex); incrementLargerOrEqualIndicesByOne(newIndex);
m_indices.push_back(newIndex); ensureSize(id);
m_indices.at(id) = newIndex;
return id; return newIndex;
} }
void checkEntries() void checkEntries()
@@ -227,11 +272,9 @@ private:
} }
private: private:
CacheEnties m_strings; CacheEntries m_strings;
std::vector<IndexType> m_indices; std::vector<IndexType> m_indices;
mutable Mutex m_mutex; mutable Mutex m_mutex;
}; };
using FilePathIndices = std::vector<FilePathIndex>;
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,8 +29,6 @@
namespace ClangBackEnd { namespace ClangBackEnd {
using FilePathIndex = long long int;
class NonLockingMutex; class NonLockingMutex;
template <typename StringType, template <typename StringType,
@@ -39,13 +37,5 @@ template <typename StringType,
typename Compare, typename Compare,
Compare compare> Compare compare>
class StringCache; class StringCache;
template <typename Mutex = NonLockingMutex>
using FilePathCache = StringCache<Utils::PathString,
FilePathIndex,
Mutex,
decltype(&Utils::reverseCompare),
Utils::reverseCompare>;
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -17,7 +17,6 @@ SOURCES += \
$$PWD/sqliteglobal.cpp \ $$PWD/sqliteglobal.cpp \
$$PWD/sqlitereadstatement.cpp \ $$PWD/sqlitereadstatement.cpp \
$$PWD/sqlitereadwritestatement.cpp \ $$PWD/sqlitereadwritestatement.cpp \
$$PWD/sqlitestatement.cpp \
$$PWD/sqlitetransaction.cpp \ $$PWD/sqlitetransaction.cpp \
$$PWD/sqlitewritestatement.cpp \ $$PWD/sqlitewritestatement.cpp \
$$PWD/sqlstatementbuilder.cpp \ $$PWD/sqlstatementbuilder.cpp \
@@ -26,7 +25,8 @@ SOURCES += \
$$PWD/utf8stringvector.cpp \ $$PWD/utf8stringvector.cpp \
$$PWD/sqlitedatabase.cpp \ $$PWD/sqlitedatabase.cpp \
$$PWD/sqlitetable.cpp \ $$PWD/sqlitetable.cpp \
$$PWD/sqlitecolumn.cpp $$PWD/sqlitecolumn.cpp \
$$PWD/sqlitebasestatement.cpp
HEADERS += \ HEADERS += \
$$PWD/createtablesqlstatementbuilder.h \ $$PWD/createtablesqlstatementbuilder.h \
$$PWD/sqlitedatabasebackend.h \ $$PWD/sqlitedatabasebackend.h \
@@ -34,7 +34,6 @@ HEADERS += \
$$PWD/sqliteglobal.h \ $$PWD/sqliteglobal.h \
$$PWD/sqlitereadstatement.h \ $$PWD/sqlitereadstatement.h \
$$PWD/sqlitereadwritestatement.h \ $$PWD/sqlitereadwritestatement.h \
$$PWD/sqlitestatement.h \
$$PWD/sqlitetransaction.h \ $$PWD/sqlitetransaction.h \
$$PWD/sqlitewritestatement.h \ $$PWD/sqlitewritestatement.h \
$$PWD/sqlstatementbuilder.h \ $$PWD/sqlstatementbuilder.h \
@@ -44,7 +43,8 @@ HEADERS += \
$$PWD/sqlitedatabase.h \ $$PWD/sqlitedatabase.h \
$$PWD/sqlitetable.h \ $$PWD/sqlitetable.h \
$$PWD/sqlitecolumn.h \ $$PWD/sqlitecolumn.h \
$$PWD/sqliteindex.h $$PWD/sqliteindex.h \
$$PWD/sqlitebasestatement.h
DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA

View File

@@ -23,7 +23,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include "sqlitestatement.h" #include "sqlitebasestatement.h"
#include "sqlitedatabase.h" #include "sqlitedatabase.h"
#include "sqlitedatabasebackend.h" #include "sqlitedatabasebackend.h"
@@ -40,7 +40,7 @@
namespace Sqlite { namespace Sqlite {
Statement::Statement(Utils::SmallStringView sqlStatement, Database &database) BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database)
: m_compiledStatement(nullptr, deleteCompiledStatement), : m_compiledStatement(nullptr, deleteCompiledStatement),
m_database(database), m_database(database),
m_bindingParameterCount(0), m_bindingParameterCount(0),
@@ -49,11 +49,10 @@ Statement::Statement(Utils::SmallStringView sqlStatement, Database &database)
{ {
prepare(sqlStatement); prepare(sqlStatement);
setBindingParameterCount(); setBindingParameterCount();
setBindingColumnNamesFromStatement();
setColumnCount(); setColumnCount();
} }
void Statement::deleteCompiledStatement(sqlite3_stmt *compiledStatement) void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
{ {
if (compiledStatement) if (compiledStatement)
sqlite3_finalize(compiledStatement); sqlite3_finalize(compiledStatement);
@@ -92,7 +91,7 @@ private:
std::mutex m_mutex; std::mutex m_mutex;
}; };
void Statement::waitForUnlockNotify() const void BaseStatement::waitForUnlockNotify() const
{ {
UnlockNotification unlockNotification; UnlockNotification unlockNotification;
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
@@ -105,7 +104,7 @@ void Statement::waitForUnlockNotify() const
unlockNotification.wait(); unlockNotification.wait();
} }
void Statement::reset() const void BaseStatement::reset() const
{ {
int resultCode = sqlite3_reset(m_compiledStatement.get()); int resultCode = sqlite3_reset(m_compiledStatement.get());
switch (resultCode) { switch (resultCode) {
@@ -119,7 +118,7 @@ void Statement::reset() const
m_isReadyToFetchValues = false; m_isReadyToFetchValues = false;
} }
bool Statement::next() const bool BaseStatement::next() const
{ {
int resultCode; int resultCode;
@@ -137,26 +136,26 @@ bool Statement::next() const
return checkForStepError(resultCode); return checkForStepError(resultCode);
} }
void Statement::step() const void BaseStatement::step() const
{ {
next(); next();
} }
void Statement::execute() const void BaseStatement::execute() const
{ {
next(); next();
reset(); reset();
} }
int Statement::columnCount() const int BaseStatement::columnCount() const
{ {
return m_columnCount; return m_columnCount;
} }
Utils::SmallStringVector Statement::columnNames() const Utils::SmallStringVector BaseStatement::columnNames() const
{ {
Utils::SmallStringVector columnNames; Utils::SmallStringVector columnNames;
int columnCount = Statement::columnCount(); int columnCount = BaseStatement::columnCount();
columnNames.reserve(std::size_t(columnCount)); columnNames.reserve(std::size_t(columnCount));
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) for (int columnIndex = 0; columnIndex < columnCount; columnIndex++)
columnNames.emplace_back(sqlite3_column_origin_name(m_compiledStatement.get(), columnIndex)); columnNames.emplace_back(sqlite3_column_origin_name(m_compiledStatement.get(), columnIndex));
@@ -164,25 +163,25 @@ Utils::SmallStringVector Statement::columnNames() const
return columnNames; return columnNames;
} }
void Statement::bind(int index, int value) void BaseStatement::bind(int index, int value)
{ {
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
checkForBindingError(resultCode); checkForBindingError(resultCode);
} }
void Statement::bind(int index, long long value) void BaseStatement::bind(int index, long long value)
{ {
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
checkForBindingError(resultCode); checkForBindingError(resultCode);
} }
void Statement::bind(int index, double value) void BaseStatement::bind(int index, double value)
{ {
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
checkForBindingError(resultCode); checkForBindingError(resultCode);
} }
void Statement::bind(int index, Utils::SmallStringView text) void BaseStatement::bind(int index, Utils::SmallStringView text)
{ {
int resultCode = sqlite3_bind_text(m_compiledStatement.get(), int resultCode = sqlite3_bind_text(m_compiledStatement.get(),
index, index,
@@ -193,35 +192,25 @@ void Statement::bind(int index, Utils::SmallStringView text)
} }
template <typename Type> template <typename Type>
void Statement::bind(Utils::SmallStringView name, Type value) void BaseStatement::bind(Utils::SmallStringView name, Type value)
{ {
int index = bindingIndexForName(name); int index = bindingIndexForName(name);
checkBindingName(index); checkBindingName(index);
bind(index, value); bind(index, value);
} }
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value); template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, int value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value); template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value); template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long long value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value); template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, double value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text); template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
int Statement::bindingIndexForName(Utils::SmallStringView name) const int BaseStatement::bindingIndexForName(Utils::SmallStringView name) const
{ {
return sqlite3_bind_parameter_index(m_compiledStatement.get(), name.data()); return sqlite3_bind_parameter_index(m_compiledStatement.get(), name.data());
} }
void Statement::setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames) void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
{
m_bindingColumnNames = bindingColumnNames;
}
const Utils::SmallStringVector &Statement::bindingColumnNames() const
{
return m_bindingColumnNames;
}
void Statement::prepare(Utils::SmallStringView sqlStatement)
{ {
int resultCode; int resultCode;
@@ -242,17 +231,17 @@ void Statement::prepare(Utils::SmallStringView sqlStatement)
checkForPrepareError(resultCode); checkForPrepareError(resultCode);
} }
sqlite3 *Statement::sqliteDatabaseHandle() const sqlite3 *BaseStatement::sqliteDatabaseHandle() const
{ {
return m_database.backend().sqliteDatabaseHandle(); return m_database.backend().sqliteDatabaseHandle();
} }
TextEncoding Statement::databaseTextEncoding() TextEncoding BaseStatement::databaseTextEncoding()
{ {
return m_database.backend().textEncoding(); return m_database.backend().textEncoding();
} }
bool Statement::checkForStepError(int resultCode) const bool BaseStatement::checkForStepError(int resultCode) const
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_ROW: return true; case SQLITE_ROW: return true;
@@ -268,7 +257,7 @@ bool Statement::checkForStepError(int resultCode) const
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
void Statement::checkForPrepareError(int resultCode) const void BaseStatement::checkForPrepareError(int resultCode) const
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_OK: return; case SQLITE_OK: return;
@@ -280,7 +269,7 @@ void Statement::checkForPrepareError(int resultCode) const
throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened"); throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened");
} }
void Statement::checkForBindingError(int resultCode) const void BaseStatement::checkForBindingError(int resultCode) const
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_OK: return; case SQLITE_OK: return;
@@ -292,7 +281,7 @@ void Statement::checkForBindingError(int resultCode) const
throwUnknowError("SqliteStatement::bind: unknown error has happened"); throwUnknowError("SqliteStatement::bind: unknown error has happened");
} }
void Statement::setIfIsReadyToFetchValues(int resultCode) const void BaseStatement::setIfIsReadyToFetchValues(int resultCode) const
{ {
if (resultCode == SQLITE_ROW) if (resultCode == SQLITE_ROW)
m_isReadyToFetchValues = true; m_isReadyToFetchValues = true;
@@ -301,13 +290,13 @@ void Statement::setIfIsReadyToFetchValues(int resultCode) const
} }
void Statement::checkIfIsReadyToFetchValues() const void BaseStatement::checkIfIsReadyToFetchValues() const
{ {
if (!m_isReadyToFetchValues) if (!m_isReadyToFetchValues)
throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!"); throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!");
} }
void Statement::checkColumnsAreValid(const std::vector<int> &columns) const void BaseStatement::checkColumnsAreValid(const std::vector<int> &columns) const
{ {
for (int column : columns) { for (int column : columns) {
if (column < 0 || column >= m_columnCount) if (column < 0 || column >= m_columnCount)
@@ -315,19 +304,19 @@ void Statement::checkColumnsAreValid(const std::vector<int> &columns) const
} }
} }
void Statement::checkColumnIsValid(int column) const void BaseStatement::checkColumnIsValid(int column) const
{ {
if (column < 0 || column >= m_columnCount) if (column < 0 || column >= m_columnCount)
throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!"); throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
} }
void Statement::checkBindingName(int index) const void BaseStatement::checkBindingName(int index) const
{ {
if (index <= 0 || index > m_bindingParameterCount) if (index <= 0 || index > m_bindingParameterCount)
throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!"); throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!");
} }
void Statement::setBindingParameterCount() void BaseStatement::setBindingParameterCount()
{ {
m_bindingParameterCount = sqlite3_bind_parameter_count(m_compiledStatement.get()); m_bindingParameterCount = sqlite3_bind_parameter_count(m_compiledStatement.get());
} }
@@ -340,65 +329,57 @@ Utils::SmallStringView chopFirstLetter(const char *rawBindingName)
return Utils::SmallStringView(""); return Utils::SmallStringView("");
} }
void Statement::setBindingColumnNamesFromStatement() void BaseStatement::setColumnCount()
{
for (int index = 1; index <= m_bindingParameterCount; index++) {
Utils::SmallStringView bindingName = chopFirstLetter(sqlite3_bind_parameter_name(m_compiledStatement.get(), index));
m_bindingColumnNames.push_back(Utils::SmallString(bindingName));
}
}
void Statement::setColumnCount()
{ {
m_columnCount = sqlite3_column_count(m_compiledStatement.get()); m_columnCount = sqlite3_column_count(m_compiledStatement.get());
} }
bool Statement::isReadOnlyStatement() const bool BaseStatement::isReadOnlyStatement() const
{ {
return sqlite3_stmt_readonly(m_compiledStatement.get()); return sqlite3_stmt_readonly(m_compiledStatement.get());
} }
void Statement::throwStatementIsBusy(const char *whatHasHappened) const void BaseStatement::throwStatementIsBusy(const char *whatHasHappened) const
{ {
throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
void Statement::throwStatementHasError(const char *whatHasHappened) const void BaseStatement::throwStatementHasError(const char *whatHasHappened) const
{ {
throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
void Statement::throwStatementIsMisused(const char *whatHasHappened) const void BaseStatement::throwStatementIsMisused(const char *whatHasHappened) const
{ {
throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const void BaseStatement::throwConstraintPreventsModification(const char *whatHasHappened) const
{ {
throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
void Statement::throwNoValuesToFetch(const char *whatHasHappened) const void BaseStatement::throwNoValuesToFetch(const char *whatHasHappened) const
{ {
throw NoValuesToFetch(whatHasHappened); throw NoValuesToFetch(whatHasHappened);
} }
void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const void BaseStatement::throwInvalidColumnFetched(const char *whatHasHappened) const
{ {
throw InvalidColumnFetched(whatHasHappened); throw InvalidColumnFetched(whatHasHappened);
} }
void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const void BaseStatement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
{ {
throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
void Statement::throwWrongBingingName(const char *whatHasHappened) const void BaseStatement::throwWrongBingingName(const char *whatHasHappened) const
{ {
throw WrongBingingName(whatHasHappened); throw WrongBindingName(whatHasHappened);
} }
void Statement::throwUnknowError(const char *whatHasHappened) const void BaseStatement::throwUnknowError(const char *whatHasHappened) const
{ {
if (sqliteDatabaseHandle()) if (sqliteDatabaseHandle())
throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
@@ -406,17 +387,17 @@ void Statement::throwUnknowError(const char *whatHasHappened) const
throw UnknowError(whatHasHappened); throw UnknowError(whatHasHappened);
} }
void Statement::throwBingingTooBig(const char *whatHasHappened) const void BaseStatement::throwBingingTooBig(const char *whatHasHappened) const
{ {
throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
QString Statement::columnName(int column) const QString BaseStatement::columnName(int column) const
{ {
return QString::fromUtf8(sqlite3_column_name(m_compiledStatement.get(), column)); return QString::fromUtf8(sqlite3_column_name(m_compiledStatement.get(), column));
} }
Database &Statement::database() const Database &BaseStatement::database() const
{ {
return m_database; return m_database;
} }
@@ -445,7 +426,7 @@ static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
int Statement::fetchIntValue(int column) const int BaseStatement::fetchIntValue(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
@@ -453,23 +434,23 @@ int Statement::fetchIntValue(int column) const
} }
template<> template<>
int Statement::fetchValue<int>(int column) const int BaseStatement::fetchValue<int>(int column) const
{ {
return fetchIntValue(column); return fetchIntValue(column);
} }
long Statement::fetchLongValue(int column) const long BaseStatement::fetchLongValue(int column) const
{ {
return long(fetchValue<long long>(column)); return long(fetchValue<long long>(column));
} }
template<> template<>
long Statement::fetchValue<long>(int column) const long BaseStatement::fetchValue<long>(int column) const
{ {
return fetchLongValue(column); return fetchLongValue(column);
} }
long long Statement::fetchLongLongValue(int column) const long long BaseStatement::fetchLongLongValue(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
@@ -477,12 +458,12 @@ long long Statement::fetchLongLongValue(int column) const
} }
template<> template<>
long long Statement::fetchValue<long long>(int column) const long long BaseStatement::fetchValue<long long>(int column) const
{ {
return fetchLongLongValue(column); return fetchLongLongValue(column);
} }
double Statement::fetchDoubleValue(int column) const double BaseStatement::fetchDoubleValue(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
@@ -490,62 +471,30 @@ double Statement::fetchDoubleValue(int column) const
} }
template<> template<>
double Statement::fetchValue<double>(int column) const double BaseStatement::fetchValue<double>(int column) const
{ {
return fetchDoubleValue(column); return fetchDoubleValue(column);
} }
template<typename StringType> template<typename StringType>
StringType Statement::fetchValue(int column) const StringType BaseStatement::fetchValue(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
return convertToTextForColumn<StringType>(m_compiledStatement.get(), column); return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
} }
Utils::SmallString Statement::fetchSmallStringValue(int column) const Utils::SmallString BaseStatement::fetchSmallStringValue(int column) const
{ {
return fetchValue<Utils::SmallString>(column); return fetchValue<Utils::SmallString>(column);
} }
Utils::PathString Statement::fetchPathStringValue(int column) const Utils::PathString BaseStatement::fetchPathStringValue(int column) const
{ {
return fetchValue<Utils::PathString>(column); return fetchValue<Utils::PathString>(column);
} }
template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const; template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue<Utils::SmallString>(int column) const;
template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const; template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathString>(int column) const;
Utils::SmallString Statement::text(int column) const
{
return fetchValue<Utils::SmallString>(column);
}
template <typename ContainerType>
ContainerType Statement::columnValues(const std::vector<int> &columnIndices) const
{
using ElementType = typename ContainerType::value_type;
ContainerType valueContainer;
valueContainer.reserve(columnIndices.size());
for (int columnIndex : columnIndices)
valueContainer.push_back(fetchValue<ElementType>(columnIndex));
return valueContainer;
}
template <typename Type>
Type Statement::toValue(Utils::SmallStringView sqlStatement, Database &database)
{
Statement statement(sqlStatement, database);
statement.next();
return statement.fetchValue<Type>(0);
}
template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);
template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::SmallStringView sqlStatement, Database &database);
template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database);
template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database);
} // namespace Sqlite } // namespace Sqlite

View File

@@ -48,10 +48,10 @@ namespace Sqlite {
class Database; class Database;
class DatabaseBackend; class DatabaseBackend;
class SQLITE_EXPORT Statement class SQLITE_EXPORT BaseStatement
{ {
protected: public:
explicit Statement(Utils::SmallStringView sqlStatement, Database &database); explicit BaseStatement(Utils::SmallStringView sqlStatement, Database &database);
static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement); static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement);
@@ -68,7 +68,6 @@ protected:
Utils::PathString fetchPathStringValue(int column) const; Utils::PathString fetchPathStringValue(int column) const;
template<typename Type> template<typename Type>
Type fetchValue(int column) const; Type fetchValue(int column) const;
Utils::SmallString text(int column) const;
int columnCount() const; int columnCount() const;
Utils::SmallStringVector columnNames() const; Utils::SmallStringVector columnNames() const;
@@ -87,140 +86,11 @@ protected:
bind(index, static_cast<long long>(value)); bind(index, static_cast<long long>(value));
} }
void bindValues()
{
}
template<typename... ValueType>
void bindValues(const ValueType&... values)
{
bindValuesByIndex(1, values...);
}
template<typename... ValueType>
void write(const ValueType&... values)
{
bindValuesByIndex(1, values...);
execute();
}
template<typename... ValueType>
void bindNameValues(const ValueType&... values)
{
bindValuesByName(values...);
}
template<typename... ValueType>
void writeNamed(const ValueType&... values)
{
bindValuesByName(values...);
execute();
}
template <typename Type> template <typename Type>
void bind(Utils::SmallStringView name, Type fetchValue); void bind(Utils::SmallStringView name, Type fetchValue);
int bindingIndexForName(Utils::SmallStringView name) const; int bindingIndexForName(Utils::SmallStringView name) const;
void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames);
const Utils::SmallStringVector &bindingColumnNames() const;
template <typename ResultType,
int ResultTypeCount = 1>
std::vector<ResultType> values(std::size_t reserveSize)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
bindValues(queryValues...);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename QueryElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) {
bindValues(queryValue);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryElementTypes>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
bindTupleValues(queryTuple);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
Utils::optional<ResultType> value( const QueryTypes&... queryValues)
{
Utils::optional<ResultType> resultValue;
bindValues(queryValues...);
if (next())
resultValue = assignValue<Utils::optional<ResultType>, ResultTypeCount>();
reset();
return resultValue;
}
template <typename Type>
static Type toValue(Utils::SmallStringView sqlStatement, Database &database);
void prepare(Utils::SmallStringView sqlStatement); void prepare(Utils::SmallStringView sqlStatement);
void waitForUnlockNotify() const; void waitForUnlockNotify() const;
@@ -236,7 +106,6 @@ protected:
void checkColumnIsValid(int column) const; void checkColumnIsValid(int column) const;
void checkBindingName(int index) const; void checkBindingName(int index) const;
void setBindingParameterCount(); void setBindingParameterCount();
void setBindingColumnNamesFromStatement();
void setColumnCount(); void setColumnCount();
bool isReadOnlyStatement() const; bool isReadOnlyStatement() const;
[[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const; [[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const;
@@ -250,22 +119,185 @@ protected:
[[noreturn]] void throwUnknowError(const char *whatHasHappened) const; [[noreturn]] void throwUnknowError(const char *whatHasHappened) const;
[[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const; [[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const;
template <typename ContainerType>
ContainerType columnValues(const std::vector<int> &columnIndices) const;
QString columnName(int column) const; QString columnName(int column) const;
Database &database() const; Database &database() const;
protected: private:
explicit Statement(Utils::SmallStringView sqlStatement, std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
DatabaseBackend &databaseBackend); Database &m_database;
int m_bindingParameterCount;
int m_columnCount;
mutable bool m_isReadyToFetchValues;
};
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, int value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long long value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, double value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
template <> SQLITE_EXPORT int BaseStatement::fetchValue<int>(int column) const;
template <> SQLITE_EXPORT long BaseStatement::fetchValue<long>(int column) const;
template <> SQLITE_EXPORT long long BaseStatement::fetchValue<long long>(int column) const;
template <> SQLITE_EXPORT double BaseStatement::fetchValue<double>(int column) const;
extern template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue<Utils::SmallString>(int column) const;
extern template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathString>(int column) const;
template <typename BaseStatement>
class SQLITE_EXPORT StatementImplementation : public BaseStatement
{
public:
using BaseStatement::BaseStatement;
void bindValues()
{
}
template<typename... ValueType>
void bindValues(const ValueType&... values)
{
bindValuesByIndex(1, values...);
}
template<typename... ValueType>
void write(const ValueType&... values)
{
bindValuesByIndex(1, values...);
BaseStatement::execute();
}
template<typename... ValueType>
void bindNameValues(const ValueType&... values)
{
bindValuesByName(values...);
}
template<typename... ValueType>
void writeNamed(const ValueType&... values)
{
bindValuesByName(values...);
BaseStatement::execute();
}
template <typename ResultType,
int ResultTypeCount = 1>
std::vector<ResultType> values(std::size_t reserveSize)
{
Resetter resetter{*this};
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{
Resetter resetter{*this};
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
bindValues(queryValues...);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename QueryElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) {
Resetter resetter{*this};
bindValues(queryValue);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryElementTypes>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
Resetter resetter{*this};
bindTupleValues(queryTuple);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
Utils::optional<ResultType> value(const QueryTypes&... queryValues)
{
Resetter resetter{*this};
Utils::optional<ResultType> resultValue;
bindValues(queryValues...);
if (BaseStatement::next())
resultValue = assignValue<Utils::optional<ResultType>, ResultTypeCount>();
return resultValue;
}
template <typename Type>
static Type toValue(Utils::SmallStringView sqlStatement, Database &database)
{
StatementImplementation statement(sqlStatement, database);
statement.next();
return statement.template fetchValue<Type>(0);
}
private: private:
class ValueGetter struct Resetter
{ {
public: Resetter(StatementImplementation &statement)
ValueGetter(Statement &statement, int column) : statement(statement)
{}
~Resetter()
{
statement.reset();
}
StatementImplementation &statement;
};
struct ValueGetter
{
ValueGetter(StatementImplementation &statement, int column)
: statement(statement), : statement(statement),
column(column) column(column)
{} {}
@@ -300,7 +332,7 @@ private:
return statement.fetchPathStringValue(column); return statement.fetchPathStringValue(column);
} }
Statement &statement; StatementImplementation &statement;
int column; int column;
}; };
@@ -335,26 +367,26 @@ private:
template<typename ValueType> template<typename ValueType>
void bindValuesByIndex(int index, const ValueType &value) void bindValuesByIndex(int index, const ValueType &value)
{ {
bind(index, value); BaseStatement::bind(index, value);
} }
template<typename ValueType, typename... ValueTypes> template<typename ValueType, typename... ValueTypes>
void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values) void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values)
{ {
bind(index, value); BaseStatement::bind(index, value);
bindValuesByIndex(index + 1, values...); bindValuesByIndex(index + 1, values...);
} }
template<typename ValueType> template<typename ValueType>
void bindValuesByName(Utils::SmallStringView name, const ValueType &value) void bindValuesByName(Utils::SmallStringView name, const ValueType &value)
{ {
bind(bindingIndexForName(name), value); BaseStatement::bind(BaseStatement::bindingIndexForName(name), value);
} }
template<typename ValueType, typename... ValueTypes> template<typename ValueType, typename... ValueTypes>
void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values) void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values)
{ {
bind(bindingIndexForName(name), value); BaseStatement::bind(BaseStatement::bindingIndexForName(name), value);
bindValuesByName(values...); bindValuesByName(values...);
} }
@@ -371,30 +403,6 @@ private:
bindTupleValuesElement(element, ColumnIndices()); bindTupleValuesElement(element, ColumnIndices());
} }
private:
std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
Utils::SmallStringVector m_bindingColumnNames;
Database &m_database;
int m_bindingParameterCount;
int m_columnCount;
mutable bool m_isReadyToFetchValues;
}; };
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
extern template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);
extern template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::SmallStringView sqlStatement, Database &database);
extern template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database);
extern template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database);
template <> SQLITE_EXPORT int Statement::fetchValue<int>(int column) const;
template <> SQLITE_EXPORT long Statement::fetchValue<long>(int column) const;
template <> SQLITE_EXPORT long long Statement::fetchValue<long long>(int column) const;
template <> SQLITE_EXPORT double Statement::fetchValue<double>(int column) const;
extern template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
extern template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const;
} // namespace Sqlite } // namespace Sqlite

View File

@@ -28,7 +28,7 @@
#include "sqliteexception.h" #include "sqliteexception.h"
#include "sqlitereadstatement.h" #include "sqlitereadstatement.h"
#include "sqlitereadwritestatement.h" #include "sqlitereadwritestatement.h"
#include "sqlitestatement.h" #include "sqlitebasestatement.h"
#include "sqlitewritestatement.h" #include "sqlitewritestatement.h"
#include <QFileInfo> #include <QFileInfo>

View File

@@ -125,10 +125,10 @@ public:
} }
}; };
class WrongBingingName : public Exception class WrongBindingName : public Exception
{ {
public: public:
WrongBingingName(const char *whatErrorHasHappen) WrongBindingName(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen) : Exception(whatErrorHasHappen)
{ {
} }

View File

@@ -31,7 +31,7 @@ namespace Sqlite {
ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement, ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement,
Database &database) Database &database)
: Statement(sqlStatement, database) : StatementImplementation(sqlStatement, database)
{ {
checkIsReadOnlyStatement(); checkIsReadOnlyStatement();
} }

View File

@@ -25,19 +25,18 @@
#pragma once #pragma once
#include "sqlitestatement.h" #include "sqlitebasestatement.h"
namespace Sqlite { namespace Sqlite {
class SQLITE_EXPORT ReadStatement final : private Statement class SQLITE_EXPORT ReadStatement final : protected StatementImplementation<BaseStatement>
{ {
public: public:
explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database); explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::value; using StatementImplementation::value;
using Statement::values; using StatementImplementation::values;
using Statement::toValue; using StatementImplementation::toValue;
using Statement::database;
protected: protected:
void checkIsReadOnlyStatement(); void checkIsReadOnlyStatement();

View File

@@ -29,7 +29,7 @@ namespace Sqlite {
ReadWriteStatement::ReadWriteStatement(Utils::SmallStringView sqlStatement, ReadWriteStatement::ReadWriteStatement(Utils::SmallStringView sqlStatement,
Database &database) Database &database)
: Statement(sqlStatement, database) : StatementImplementation(sqlStatement, database)
{ {
} }

View File

@@ -25,24 +25,23 @@
#pragma once #pragma once
#include "sqlitestatement.h" #include "sqlitebasestatement.h"
namespace Sqlite { namespace Sqlite {
class SQLITE_EXPORT ReadWriteStatement final : private Statement class SQLITE_EXPORT ReadWriteStatement final : protected StatementImplementation<BaseStatement>
{ {
friend class DatabaseBackend; friend class DatabaseBackend;
public: public:
ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database); ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::execute; using StatementImplementation::execute;
using Statement::value; using StatementImplementation::value;
using Statement::values; using StatementImplementation::values;
using Statement::toValue; using StatementImplementation::toValue;
using Statement::database; using StatementImplementation::write;
using Statement::write; using StatementImplementation::writeNamed;
using Statement::writeNamed;
}; };
} // namespace Sqlite } // namespace Sqlite

View File

@@ -29,7 +29,7 @@ namespace Sqlite {
WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement, WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement,
Database &database) Database &database)
: Statement(sqlStatement, database) : StatementImplementation(sqlStatement, database)
{ {
checkIsWritableStatement(); checkIsWritableStatement();
} }

View File

@@ -25,19 +25,19 @@
#pragma once #pragma once
#include "sqlitestatement.h" #include "sqlitebasestatement.h"
namespace Sqlite { namespace Sqlite {
class SQLITE_EXPORT WriteStatement : private Statement class SQLITE_EXPORT WriteStatement : protected StatementImplementation<BaseStatement>
{ {
public: public:
explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database); explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::execute; using StatementImplementation::execute;
using Statement::database; using StatementImplementation::database;
using Statement::write; using StatementImplementation::write;
using Statement::writeNamed; using StatementImplementation::writeNamed;
protected: protected:
void checkIsWritableStatement(); void checkIsWritableStatement();

View File

@@ -145,25 +145,7 @@ public:
BasicSmallString(std::initializer_list<Utils::SmallStringView> list) BasicSmallString(std::initializer_list<Utils::SmallStringView> list)
: m_data(Internal::StringDataLayout<Size>()) : m_data(Internal::StringDataLayout<Size>())
{ {
std::size_t size = std::accumulate(list.begin(), appendInitializerList(list, 0);
list.end(),
std::size_t(0),
[] (std::size_t size, Utils::SmallStringView string) {
return size + string.size();
});
reserve(size);
setSize(size);
char *currentData = data();
for (Utils::SmallStringView string : list) {
std::memcpy(currentData, string.data(), string.size());
currentData += string.size();
}
at(size) = 0;
} }
~BasicSmallString() noexcept ~BasicSmallString() noexcept
@@ -478,6 +460,13 @@ public:
return *this; return *this;
} }
BasicSmallString &operator+=(std::initializer_list<SmallStringView> list)
{
appendInitializerList(list, size());
return *this;
}
void replace(SmallStringView fromText, SmallStringView toText) void replace(SmallStringView fromText, SmallStringView toText)
{ {
if (toText.size() == fromText.size()) if (toText.size() == fromText.size())
@@ -690,6 +679,27 @@ private:
{ {
} }
void appendInitializerList(std::initializer_list<SmallStringView> list, std::size_t initialSize)
{
auto addSize = [] (std::size_t size, Utils::SmallStringView string) {
return size + string.size();
};
std::size_t size = std::accumulate(list.begin(), list.end(), initialSize, addSize);
reserve(size);
setSize(size);
char *currentData = data() + initialSize;
for (Utils::SmallStringView string : list) {
std::memcpy(currentData, string.data(), string.size());
currentData += string.size();
}
at(size) = 0;
}
void initializeLongString(size_type size, size_type capacity) void initializeLongString(size_type size, size_type capacity)
{ {
m_data.allocated.data.pointer[size] = 0; m_data.allocated.data.pointer[size] = 0;

View File

@@ -193,15 +193,16 @@ inline
int reverse_memcmp(const char *first, const char *second, size_t n) int reverse_memcmp(const char *first, const char *second, size_t n)
{ {
const char *currentFirst = first + n; const char *currentFirst = first + n - 1;
const char *currentSecond = second + n; const char *currentSecond = second + n - 1;
while (n > 0) while (n > 0)
{ {
// If the current characters differ, return an appropriately signed // If the current characters differ, return an appropriately signed
// value; otherwise, keep searching backwards // value; otherwise, keep searching backwards
if (*currentFirst != *currentSecond) int difference = *currentFirst - *currentSecond;
return *currentFirst - *currentSecond; if (difference != 0)
return difference;
--currentFirst; --currentFirst;
--currentSecond; --currentSecond;

View File

@@ -33,8 +33,15 @@
#include <coreplugin/find/searchresultwindow.h> #include <coreplugin/find/searchresultwindow.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <refactoringdatabaseinitializer.h>
#include <filepathcaching.h>
#include <sqlitedatabase.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <QDir>
namespace ClangRefactoring { namespace ClangRefactoring {
namespace { namespace {
@@ -54,9 +61,12 @@ class ClangRefactoringPluginData
{ {
using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater<ClangPchManager::ProjectUpdater>; using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater<ClangPchManager::ProjectUpdater>;
public: public:
Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
RefactoringClient refactoringClient; RefactoringClient refactoringClient;
ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient}; ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient};
RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient}; RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient, filePathCache};
QtCreatorSearch qtCreatorSearch{*Core::SearchResultWindow::instance()}; QtCreatorSearch qtCreatorSearch{*Core::SearchResultWindow::instance()};
QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(), QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(),
qtCreatorSearch, qtCreatorSearch,

View File

@@ -40,14 +40,9 @@ public:
{} {}
Database &database; Database &database;
ReadStatement selectLocationsForSymbolLocation{ ReadStatement selectLocationsForSymbolLocation{
"SELECT sourceId, line, column FROM locations WHERE symbolId = " "SELECT directoryId, sourceId, line, column FROM locations JOIN sources USING(sourceId) WHERE symbolId = "
" (SELECT symbolId FROM locations WHERE sourceId=" " (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) "
" (SELECT sourceId FROM sources WHERE sourcePath =?)"
" AND line=? AND column=?) "
"ORDER BY sourceId, line, column", "ORDER BY sourceId, line, column",
database}; // alternatively SELECT l2.symbolid, l2.sourceId, l2.line, l2.column FROM locations AS l2, sources, locations AS l1 ON sources.sourceId = l1.sourceId AND l2.symbolId=l1.symbolId WHERE sourcePath = ? AND l1.line=? AND l1.column=? ORDER BY l2.sourceId, l2.line, l2.column
ReadStatement selectSourcePathForId{
"SELECT sourceId, sourcePath FROM sources WHERE sourceId = ?",
database}; database};
}; };

View File

@@ -28,8 +28,9 @@
#include "clangqueryhighlighter.h" #include "clangqueryhighlighter.h"
#include "clangqueryexamplehighlighter.h" #include "clangqueryexamplehighlighter.h"
#include <refactoringconnectionclient.h>
#include <clangrefactoringmessages.h> #include <clangrefactoringmessages.h>
#include <filepathcachinginterface.h>
#include <refactoringconnectionclient.h>
namespace ClangRefactoring { namespace ClangRefactoring {
@@ -122,38 +123,17 @@ void RefactoringClient::setRefactoringConnectionClient(
m_connectionClient = connectionClient; m_connectionClient = connectionClient;
} }
std::unordered_map<uint, QString> RefactoringClient::convertFilePaths(
const ClangBackEnd::FilePathDict &filePaths)
{
using Dict = std::unordered_map<uint, QString>;
Dict qstringFilePaths;
qstringFilePaths.reserve(filePaths.size());
auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) {
return std::make_pair(dictonaryEntry.first,
dictonaryEntry.second.path().toQString());
};
std::transform(filePaths.begin(),
filePaths.end(),
std::inserter(qstringFilePaths, qstringFilePaths.begin()),
convertFilePath);
return qstringFilePaths;
}
void RefactoringClient::addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges) void RefactoringClient::addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges)
{ {
auto filePaths = convertFilePaths(sourceRanges.filePaths());
for (const auto &sourceRangeWithText : sourceRanges.sourceRangeWithTextContainers()) for (const auto &sourceRangeWithText : sourceRanges.sourceRangeWithTextContainers())
addSearchResult(sourceRangeWithText, filePaths); addSearchResult(sourceRangeWithText);
} }
void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText, void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText)
std::unordered_map<uint, QString> &filePaths)
{ {
m_searchHandle->addResult(filePaths[sourceRangeWithText.fileHash()], auto &filePathCache = m_refactoringEngine->filePathCache();
m_searchHandle->addResult(QString(filePathCache.filePath(sourceRangeWithText.filePathId()).path()),
QString(sourceRangeWithText.text()), QString(sourceRangeWithText.text()),
{{int(sourceRangeWithText.start().line()), {{int(sourceRangeWithText.start().line()),
int(sourceRangeWithText.start().column() - 1), int(sourceRangeWithText.start().column() - 1),

View File

@@ -66,9 +66,6 @@ public:
bool hasValidLocalRenamingCallback() const; bool hasValidLocalRenamingCallback() const;
static std::unordered_map<uint, QString> convertFilePaths(
const std::unordered_map<uint, ClangBackEnd::FilePath> &filePaths);
void setExpectedResultCount(uint count); void setExpectedResultCount(uint count);
uint expectedResultCount() const; uint expectedResultCount() const;
uint resultCounter() const; uint resultCounter() const;
@@ -76,8 +73,7 @@ public:
void setRefactoringConnectionClient(ClangBackEnd::RefactoringConnectionClient *connectionClient); void setRefactoringConnectionClient(ClangBackEnd::RefactoringConnectionClient *connectionClient);
unittest_public: unittest_public:
void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange, void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange);
std::unordered_map<uint, QString> &filePaths);
private: private:
void addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges); void addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges);

View File

@@ -46,9 +46,11 @@ namespace ClangRefactoring {
using ClangBackEnd::RequestSourceLocationsForRenamingMessage; using ClangBackEnd::RequestSourceLocationsForRenamingMessage;
RefactoringEngine::RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server, RefactoringEngine::RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server,
ClangBackEnd::RefactoringClientInterface &client) ClangBackEnd::RefactoringClientInterface &client,
: server(server), ClangBackEnd::FilePathCachingInterface &filePathCache)
client(client) : m_server(server),
m_client(client),
m_filePathCache(filePathCache)
{ {
} }
@@ -60,7 +62,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
setUsable(false); setUsable(false);
client.setLocalRenamingCallback(std::move(renameSymbolsCallback)); m_client.setLocalRenamingCallback(std::move(renameSymbolsCallback));
QString filePath = data.filePath().toString(); QString filePath = data.filePath().toString();
QTextCursor textCursor = data.cursor(); QTextCursor textCursor = data.cursor();
@@ -79,7 +81,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
textCursor.document()->revision()); textCursor.document()->revision());
server.requestSourceLocationsForRenamingMessage(std::move(message)); m_server.requestSourceLocationsForRenamingMessage(std::move(message));
} }
void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &) void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
@@ -89,12 +91,12 @@ void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
bool RefactoringEngine::isUsable() const bool RefactoringEngine::isUsable() const
{ {
return server.isUsable(); return m_server.isUsable();
} }
void RefactoringEngine::setUsable(bool isUsable) void RefactoringEngine::setUsable(bool isUsable)
{ {
server.setUsable(isUsable); m_server.setUsable(isUsable);
} }
} // namespace ClangRefactoring } // namespace ClangRefactoring

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include <filepathcachingfwd.h>
#include <cpptools/refactoringengineinterface.h> #include <cpptools/refactoringengineinterface.h>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -37,8 +39,10 @@ namespace ClangRefactoring {
class RefactoringEngine : public CppTools::RefactoringEngineInterface class RefactoringEngine : public CppTools::RefactoringEngineInterface
{ {
public: public:
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server, RefactoringEngine(ClangBackEnd::RefactoringServerInterface &m_server,
ClangBackEnd::RefactoringClientInterface &client); ClangBackEnd::RefactoringClientInterface &m_client,
ClangBackEnd::FilePathCachingInterface &filePathCache);
void startLocalRenaming(const CppTools::CursorInEditor &data, void startLocalRenaming(const CppTools::CursorInEditor &data,
CppTools::ProjectPart *projectPart, CppTools::ProjectPart *projectPart,
RenameCallback &&renameSymbolsCallback) override; RenameCallback &&renameSymbolsCallback) override;
@@ -47,9 +51,15 @@ public:
bool isUsable() const override; bool isUsable() const override;
void setUsable(bool isUsable); void setUsable(bool isUsable);
ClangBackEnd::FilePathCachingInterface &filePathCache()
{
return m_filePathCache;
}
private: private:
ClangBackEnd::RefactoringServerInterface &server; ClangBackEnd::RefactoringServerInterface &m_server;
ClangBackEnd::RefactoringClientInterface &client; ClangBackEnd::RefactoringClientInterface &m_client;
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangRefactoring } // namespace ClangRefactoring

View File

@@ -27,39 +27,26 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <cstdint> #include <filepathid.h>
#include <vector> #include <vector>
#include <tuple>
#include <unordered_map>
namespace ClangRefactoring { namespace ClangRefactoring {
class SourceLocations struct SourceLocation
{ {
public: SourceLocation(ClangBackEnd::FilePathId filePathId, int line, int column)
struct Location : filePathId(filePathId), line(line), column(column)
{ {}
Location(qint64 sourceId, qint64 line, qint64 column) SourceLocation(int directoryId, int sourceId, int line, int column)
: sourceId(sourceId), line(line), column(column) : filePathId{directoryId, sourceId}, line(line), column(column)
{} {}
qint64 sourceId; ClangBackEnd::FilePathId filePathId;
qint64 line; int line;
qint64 column; int column;
};
struct Source
{
Source(qint64 sourceId, Utils::PathString &&sourcePath)
: sourceId(sourceId), sourcePath(std::move(sourcePath))
{}
qint64 sourceId;
Utils::PathString sourcePath;
};
std::vector<Location> locations;
std::unordered_map<qint64, Utils::PathString> sources;
}; };
using SourceLocations = std::vector<SourceLocation>;
} // namespace ClangRefactoring } // namespace ClangRefactoring

View File

@@ -27,6 +27,7 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <filepathid.h>
#include <sourcelocations.h> #include <sourcelocations.h>
#include <algorithm> #include <algorithm>
@@ -39,68 +40,20 @@ class SymbolQuery
using ReadStatement = typename StatementFactory::ReadStatementType; using ReadStatement = typename StatementFactory::ReadStatementType;
public: public:
using Location = SourceLocations::Location;
using Source = SourceLocations::Source;
SymbolQuery(StatementFactory &statementFactory) SymbolQuery(StatementFactory &statementFactory)
: m_statementFactory(statementFactory) : m_statementFactory(statementFactory)
{} {}
SourceLocations locationsAt(const Utils::PathString &filePath, uint line, uint utf8Column) SourceLocations locationsAt(ClangBackEnd::FilePathId filePathId, int line, int utf8Column)
{ {
ReadStatement &locationsStatement = m_statementFactory.selectLocationsForSymbolLocation; ReadStatement &locationsStatement = m_statementFactory.selectLocationsForSymbolLocation;
const std::size_t reserveSize = 128; const std::size_t reserveSize = 128;
auto locations = locationsStatement.template values<Location, 3>( return locationsStatement.template values<SourceLocation, 4>(reserveSize,
reserveSize, filePathId.fileNameId,
filePath,
line, line,
utf8Column); utf8Column);
const std::vector<qint64> sourceIds = uniqueSourceIds(locations);
ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId;
auto sources = sourcesStatement.template values<Source, 2>(
reserveSize,
sourceIds);
return {locations, sourcesToHashMap(sources)};
}
static
qint64 sourceId(const Location &location)
{
return location.sourceId;
}
static
std::vector<qint64> uniqueSourceIds(const std::vector<Location> &locations)
{
std::vector<qint64> ids;
ids.reserve(locations.size());
std::transform(locations.begin(),
locations.end(),
std::back_inserter(ids),
sourceId);
auto newEnd = std::unique(ids.begin(), ids.end());
ids.erase(newEnd, ids.end());
return ids;
}
static
std::unordered_map<qint64, Utils::PathString> sourcesToHashMap(const std::vector<Source> &sources)
{
std::unordered_map<qint64, Utils::PathString> dictonary;
for (const Source &source : sources)
dictonary.emplace(source.sourceId, std::move(source.sourcePath));
return dictonary;
} }
private: private:

View File

@@ -31,7 +31,9 @@
#include <pchmanagerserver.h> #include <pchmanagerserver.h>
#include <pchmanagerclientproxy.h> #include <pchmanagerclientproxy.h>
#include <projectparts.h> #include <projectparts.h>
#include <stringcache.h> #include <filepathcaching.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCoreApplication> #include <QCoreApplication>
@@ -103,15 +105,16 @@ int main(int argc, char *argv[])
const QString connection = processArguments(application); const QString connection = processArguments(application);
FilePathCache<> filePathCache; Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache); ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache);
ApplicationEnvironment environment; ApplicationEnvironment environment;
PchGenerator<QProcess> pchGenerator(environment); PchGenerator<QProcess> pchGenerator(environment);
PchCreator pchCreator(environment, filePathCache); PchCreator pchCreator(environment, filePathCache);
pchCreator.setGenerator(&pchGenerator); pchCreator.setGenerator(&pchGenerator);
ProjectParts projectParts; ProjectParts projectParts;
PchManagerServer clangPchManagerServer(filePathCache, PchManagerServer clangPchManagerServer(includeWatcher,
includeWatcher,
pchCreator, pchCreator,
projectParts); projectParts);
includeWatcher.setNotifier(&clangPchManagerServer); includeWatcher.setNotifier(&clangPchManagerServer);

View File

@@ -28,7 +28,9 @@
#include "clangpathwatcherinterface.h" #include "clangpathwatcherinterface.h"
#include "clangpathwatchernotifier.h" #include "clangpathwatchernotifier.h"
#include "changedfilepathcompressor.h" #include "changedfilepathcompressor.h"
#include "stringcache.h"
#include <filepathcachinginterface.h>
#include <stringcache.h>
#include <QTimer> #include <QTimer>
@@ -37,34 +39,34 @@ namespace ClangBackEnd {
class WatcherEntry class WatcherEntry
{ {
public: public:
FilePathIndex id; int id;
FilePathIndex path; FilePathId pathId;
friend bool operator==(const WatcherEntry &first, const WatcherEntry &second) friend bool operator==(const WatcherEntry &first, const WatcherEntry &second)
{ {
return first.id == second.id && first.path == second.path; return first.id == second.id && first.pathId == second.pathId;
} }
friend bool operator<(const WatcherEntry &first, const WatcherEntry &second) friend bool operator<(const WatcherEntry &first, const WatcherEntry &second)
{ {
return std::tie(first.path, first.id) < std::tie(second.path, second.id); return std::tie(first.pathId, first.id) < std::tie(second.pathId, second.id);
} }
friend bool operator<(const WatcherEntry &entry, FilePathIndex path) friend bool operator<(const WatcherEntry &entry, FilePathId pathId)
{ {
return entry.path < path; return entry.pathId < pathId;
} }
friend bool operator<(FilePathIndex path, const WatcherEntry &entry) friend bool operator<(FilePathId pathId, const WatcherEntry &entry)
{ {
return path < entry.path; return pathId < entry.pathId;
} }
}; };
using WatcherEntries = std::vector<WatcherEntry>; using WatcherEntries = std::vector<WatcherEntry>;
using IdCache = StringCache<Utils::SmallString, using IdCache = StringCache<Utils::SmallString,
FilePathIndex, int,
NonLockingMutex, NonLockingMutex,
decltype(&Utils::compare), decltype(&Utils::compare),
Utils::compare>; Utils::compare>;
@@ -74,7 +76,7 @@ template <typename FileSystemWatcher,
class ClangPathWatcher : public ClangPathWatcherInterface class ClangPathWatcher : public ClangPathWatcherInterface
{ {
public: public:
ClangPathWatcher(FilePathCache<> &pathCache, ClangPathWatcher(FilePathCachingInterface &pathCache,
ClangPathWatcherNotifier *notifier=nullptr) ClangPathWatcherNotifier *notifier=nullptr)
: m_pathCache(pathCache), : m_pathCache(pathCache),
m_notifier(notifier) m_notifier(notifier)
@@ -136,9 +138,9 @@ unittest_public:
return ids; return ids;
} }
std::vector<FilePathIndex> convertToIdNumbers(const Utils::SmallStringVector &ids) std::vector<int> convertToIdNumbers(const Utils::SmallStringVector &ids)
{ {
std::vector<FilePathIndex> idNumbers = m_idCache.stringIds(ids); std::vector<int> idNumbers = m_idCache.stringIds(ids);
std::sort(idNumbers.begin(), idNumbers.end()); std::sort(idNumbers.begin(), idNumbers.end());
@@ -148,33 +150,33 @@ unittest_public:
std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths) std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
{ {
auto sumSize = [] (std::size_t size, const IdPaths &idPath) { auto sumSize = [] (std::size_t size, const IdPaths &idPath) {
return size + idPath.paths.size(); return size + idPath.filePathIds.size();
}; };
return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize); return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize);
} }
std::pair<WatcherEntries,std::vector<FilePathIndex>> std::pair<WatcherEntries, std::vector<int>>
convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths) convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
{ {
WatcherEntries entries; WatcherEntries entries;
entries.reserve(sizeOfIdPaths(idPaths)); entries.reserve(sizeOfIdPaths(idPaths));
std::vector<FilePathIndex> ids; std::vector<int> ids;
ids.reserve(ids.size()); ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries); auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths) for (const IdPaths &idPath : idPaths)
{ {
FilePathIndex id = m_idCache.stringId(idPath.id); int id = m_idCache.stringId(idPath.id);
ids.push_back(id); ids.push_back(id);
outputIterator = std::transform(idPath.paths.begin(), outputIterator = std::transform(idPath.filePathIds.begin(),
idPath.paths.end(), idPath.filePathIds.end(),
outputIterator, outputIterator,
[&] (uint path) { return WatcherEntry{id, path}; }); [&] (FilePathId pathId) { return WatcherEntry{id, pathId}; });
} }
std::sort(entries.begin(), entries.end()); std::sort(entries.begin(), entries.end());
@@ -196,7 +198,7 @@ unittest_public:
} }
void removeUnusedEntries(const WatcherEntries &entries, void removeUnusedEntries(const WatcherEntries &entries,
const std::vector<FilePathIndex> &ids) const std::vector<int> &ids)
{ {
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids); auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
@@ -222,7 +224,9 @@ unittest_public:
std::transform(watcherEntries.begin(), std::transform(watcherEntries.begin(),
watcherEntries.end(), watcherEntries.end(),
std::back_inserter(paths), std::back_inserter(paths),
[&] (const WatcherEntry &entry) { return QString(m_pathCache.string(entry.path)); }); [&] (const WatcherEntry &entry) {
return QString(m_pathCache.filePath(entry.pathId).path());
});
return paths; return paths;
} }
@@ -252,7 +256,7 @@ unittest_public:
WatcherEntries notWatchedPaths(const WatcherEntries &entries) const WatcherEntries notWatchedPaths(const WatcherEntries &entries) const
{ {
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) { auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
return first.path < second.path; return first.pathId < second.pathId;
}; };
return notWatchedEntries(entries, compare); return notWatchedEntries(entries, compare);
@@ -278,7 +282,7 @@ unittest_public:
WatcherEntries notAnymoreWatchedEntriesWithIds( WatcherEntries notAnymoreWatchedEntriesWithIds(
const WatcherEntries &newEntries, const WatcherEntries &newEntries,
const std::vector<FilePathIndex> &ids) const const std::vector<int> &ids) const
{ {
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>()); auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
@@ -313,7 +317,7 @@ unittest_public:
WatcherEntries uniqueEntries; WatcherEntries uniqueEntries;
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) { auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
return first.path == second.path; return first.pathId == second.pathId;
}; };
std::unique_copy(pathEntries.begin(), std::unique_copy(pathEntries.begin(),
@@ -334,7 +338,7 @@ unittest_public:
return m_watchedEntries; return m_watchedEntries;
} }
WatcherEntries removeIdsFromWatchedEntries(const std::vector<FilePathIndex> &ids) WatcherEntries removeIdsFromWatchedEntries(const std::vector<int> &ids)
{ {
auto keep = [&] (const WatcherEntry &entry) { auto keep = [&] (const WatcherEntry &entry) {
@@ -374,11 +378,11 @@ unittest_public:
WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths) WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths)
{ {
std::vector<FilePathIndex> pathIds = m_pathCache.stringIds(filePaths); FilePathIds pathIds = m_pathCache.filePathIds(filePaths);
WatcherEntries foundEntries; WatcherEntries foundEntries;
for (uint pathId : pathIds) { for (FilePathId pathId : pathIds) {
auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId); auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId);
foundEntries.insert(foundEntries.end(), range.first, range.second); foundEntries.insert(foundEntries.end(), range.first, range.second);
} }
@@ -420,7 +424,7 @@ unittest_public:
} }
} }
FilePathCache<> &pathCache() FilePathCachingInterface &pathCache()
{ {
return m_pathCache; return m_pathCache;
} }
@@ -435,10 +439,8 @@ private:
WatcherEntries m_watchedEntries; WatcherEntries m_watchedEntries;
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor; ChangedFilePathCompressor<Timer> m_changedFilePathCompressor;
FileSystemWatcher m_fileSystemWatcher; FileSystemWatcher m_fileSystemWatcher;
FilePathCache<> &m_pathCache; FilePathCachingInterface &m_pathCache;
ClangPathWatcherNotifier *m_notifier; ClangPathWatcherNotifier *m_notifier;
}; };
std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry);
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -2,9 +2,7 @@ INCLUDEPATH += $$PWD
SOURCES += \ SOURCES += \
$$PWD/pchmanagerserver.cpp \ $$PWD/pchmanagerserver.cpp \
$$PWD/clangpathwatcher.cpp \
$$PWD/projectparts.cpp \ $$PWD/projectparts.cpp \
$$PWD/idpaths.cpp \
$$PWD/pchcreatorinterface.cpp \ $$PWD/pchcreatorinterface.cpp \
$$PWD/clangpathwatcherinterface.cpp \ $$PWD/clangpathwatcherinterface.cpp \
$$PWD/projectpartsinterface.cpp \ $$PWD/projectpartsinterface.cpp \

View File

@@ -25,10 +25,11 @@
#pragma once #pragma once
#include "stringcache.h"
#include <collectincludespreprocessorcallbacks.h> #include <collectincludespreprocessorcallbacks.h>
#include <filepathcachingfwd.h>
#include <filepathid.h>
#include <clang/Frontend/FrontendActions.h> #include <clang/Frontend/FrontendActions.h>
#include <clang/Frontend/CompilerInstance.h> #include <clang/Frontend/CompilerInstance.h>
#include <clang/Lex/Preprocessor.h> #include <clang/Lex/Preprocessor.h>
@@ -38,10 +39,10 @@ namespace ClangBackEnd {
class CollectIncludesAction final : public clang::PreprocessOnlyAction class CollectIncludesAction final : public clang::PreprocessOnlyAction
{ {
public: public:
CollectIncludesAction(FilePathIndices &includeIds, CollectIncludesAction(FilePathIds &includeIds,
FilePathCache<> &filePathCache, FilePathCachingInterface &filePathCache,
FilePathIndices &excludedIncludeUID, std::vector<uint> &excludedIncludeUID,
FilePathIndices &alreadyIncludedFileUIDs) std::vector<uint> &alreadyIncludedFileUIDs)
: m_includeIds(includeIds), : m_includeIds(includeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
m_excludedIncludeUID(excludedIncludeUID), m_excludedIncludeUID(excludedIncludeUID),
@@ -78,10 +79,10 @@ public:
} }
private: private:
FilePathIndices &m_includeIds; FilePathIds &m_includeIds;
FilePathCache<> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
FilePathIndices &m_excludedIncludeUID; std::vector<uint> &m_excludedIncludeUID;
FilePathIndices &m_alreadyIncludedFileUIDs; std::vector<uint> &m_alreadyIncludedFileUIDs;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,7 +25,10 @@
#pragma once #pragma once
#include "stringcache.h" #include <filepathcachinginterface.h>
#include <filepathid.h>
#include <utils/smallstringvector.h>
#include <clang/Basic/SourceManager.h> #include <clang/Basic/SourceManager.h>
#include <clang/Lex/MacroInfo.h> #include <clang/Lex/MacroInfo.h>
@@ -33,8 +36,6 @@
#include <clang/Lex/PPCallbacks.h> #include <clang/Lex/PPCallbacks.h>
#include <clang/Lex/Preprocessor.h> #include <clang/Lex/Preprocessor.h>
#include <utils/smallstringvector.h>
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
#include <QTemporaryDir> #include <QTemporaryDir>
@@ -47,10 +48,10 @@ class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks
{ {
public: public:
CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch, CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch,
std::vector<FilePathIndex> &includeIds, FilePathIds &includeIds,
FilePathCache<> &filePathCache, FilePathCachingInterface &filePathCache,
const std::vector<FilePathIndex> &excludedIncludeUID, const std::vector<uint> &excludedIncludeUID,
std::vector<FilePathIndex> &alreadyIncludedFileUIDs) std::vector<uint> &alreadyIncludedFileUIDs)
: m_headerSearch(headerSearch), : m_headerSearch(headerSearch),
m_includeIds(includeIds), m_includeIds(includeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
@@ -78,7 +79,7 @@ public:
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID); m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
Utils::PathString filePath = filePathFromFile(file); Utils::PathString filePath = filePathFromFile(file);
if (!filePath.isEmpty()) { if (!filePath.isEmpty()) {
FilePathIndex includeId = m_filePathCache.stringId(filePath); FilePathId includeId = m_filePathCache.filePathId(filePath);
m_includeIds.emplace_back(includeId); m_includeIds.emplace_back(includeId);
} }
} }
@@ -132,7 +133,7 @@ public:
uid); uid);
} }
std::pair<bool, std::vector<FilePathIndex>::iterator> isNotAlreadyIncluded(FilePathIndex uid) const std::pair<bool, std::vector<uint>::iterator> isNotAlreadyIncluded(uint uid) const
{ {
auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(), auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(),
m_alreadyIncludedFileUIDs.end(), m_alreadyIncludedFileUIDs.end(),
@@ -174,10 +175,10 @@ public:
private: private:
clang::HeaderSearch &m_headerSearch; clang::HeaderSearch &m_headerSearch;
std::vector<FilePathIndex> &m_includeIds; FilePathIds &m_includeIds;
FilePathCache<> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
const std::vector<FilePathIndex> &m_excludedIncludeUID; const std::vector<uint> &m_excludedIncludeUID;
std::vector<FilePathIndex> &m_alreadyIncludedFileUIDs; std::vector<uint> &m_alreadyIncludedFileUIDs;
bool m_skipInclude = false; bool m_skipInclude = false;
}; };

View File

@@ -25,10 +25,11 @@
#pragma once #pragma once
#include "stringcache.h"
#include "collectincludesaction.h" #include "collectincludesaction.h"
#include <filepathcachingfwd.h>
#include <filepathid.h>
#include <clang/Tooling/Tooling.h> #include <clang/Tooling/Tooling.h>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -36,8 +37,8 @@ namespace ClangBackEnd {
class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory
{ {
public: public:
CollectIncludesToolAction(std::vector<FilePathIndex> &includeIds, CollectIncludesToolAction(FilePathIds &includeIds,
FilePathCache<> &filePathCache, FilePathCachingInterface &filePathCache,
const Utils::PathStringVector &excludedIncludes) const Utils::PathStringVector &excludedIncludes)
: m_includeIds(includeIds), : m_includeIds(includeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
@@ -72,9 +73,9 @@ public:
m_alreadyIncludedFileUIDs); m_alreadyIncludedFileUIDs);
} }
std::vector<FilePathIndex> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
{ {
std::vector<FilePathIndex> fileUIDs; std::vector<uint> fileUIDs;
fileUIDs.reserve(m_excludedIncludes.size()); fileUIDs.reserve(m_excludedIncludes.size());
for (const Utils::PathString &filePath : m_excludedIncludes) { for (const Utils::PathString &filePath : m_excludedIncludes) {
@@ -90,10 +91,10 @@ public:
} }
private: private:
std::vector<FilePathIndex> m_alreadyIncludedFileUIDs; std::vector<uint> m_alreadyIncludedFileUIDs;
std::vector<FilePathIndex> m_excludedIncludeUIDs; std::vector<uint> m_excludedIncludeUIDs;
std::vector<FilePathIndex> &m_includeIds; FilePathIds &m_includeIds;
FilePathCache<> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
const Utils::PathStringVector &m_excludedIncludes; const Utils::PathStringVector &m_excludedIncludes;
}; };

View File

@@ -27,9 +27,7 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <iosfwd> #include <filepathid.h>
#include <stringcachefwd.h>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -37,14 +35,12 @@ class IdPaths
{ {
public: public:
Utils::SmallString id; Utils::SmallString id;
std::vector<FilePathIndex> paths; FilePathIds filePathIds;
friend bool operator==(const IdPaths &first, const IdPaths &second) friend bool operator==(const IdPaths &first, const IdPaths &second)
{ {
return first.id == second.id && first.paths == second.paths; return first.id == second.id && first.filePathIds == second.filePathIds;
} }
}; };
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -33,7 +33,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
IncludeCollector::IncludeCollector(FilePathCache<> &filePathCache) IncludeCollector::IncludeCollector(FilePathCachingInterface &filePathCache)
: m_filePathCache(filePathCache) : m_filePathCache(filePathCache)
{ {
} }
@@ -69,7 +69,7 @@ void IncludeCollector::setExcludedIncludes(Utils::PathStringVector &&excludedInc
#endif #endif
} }
std::vector<FilePathIndex> IncludeCollector::takeIncludeIds() FilePathIds IncludeCollector::takeIncludeIds()
{ {
std::sort(m_includeIds.begin(), m_includeIds.end()); std::sort(m_includeIds.begin(), m_includeIds.end());

View File

@@ -25,28 +25,28 @@
#pragma once #pragma once
#include "stringcache.h"
#include <clangtool.h> #include <clangtool.h>
#include <filepathcachingfwd.h>
namespace ClangBackEnd { namespace ClangBackEnd {
class IncludeCollector : public ClangTool class IncludeCollector : public ClangTool
{ {
public: public:
IncludeCollector(FilePathCache<> &filePathCache); IncludeCollector(FilePathCachingInterface &filePathCache);
void collectIncludes(); void collectIncludes();
void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes); void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes);
std::vector<FilePathIndex> takeIncludeIds(); FilePathIds takeIncludeIds();
private: private:
Utils::PathStringVector m_excludedIncludes; Utils::PathStringVector m_excludedIncludes;
std::vector<FilePathIndex> m_includeIds; FilePathIds m_includeIds;
Utils::SmallStringVector m_directories; Utils::SmallStringVector m_directories;
FilePathCache<> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,6 +29,7 @@
#include "includecollector.h" #include "includecollector.h"
#include "pchnotcreatederror.h" #include "pchnotcreatederror.h"
#include <filepathcachinginterface.h>
#include <projectpartpch.h> #include <projectpartpch.h>
#include <QCryptographicHash> #include <QCryptographicHash>
@@ -37,7 +38,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache) PchCreator::PchCreator(Environment &environment, FilePathCachingInterface &filePathCache)
: m_environment(environment), : m_environment(environment),
m_filePathCache(filePathCache) m_filePathCache(filePathCache)
{ {
@@ -45,7 +46,7 @@ PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache)
PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts, PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment, Environment &environment,
FilePathCache<> &filePathCache, FilePathCachingInterface &filePathCache,
PchGeneratorInterface *pchGenerator, PchGeneratorInterface *pchGenerator,
V2::FileContainers &&generatedFiles) V2::FileContainers &&generatedFiles)
: m_projectParts(std::move(projectsParts)), : m_projectParts(std::move(projectsParts)),
@@ -239,7 +240,7 @@ Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() cons
return compilerArguments; return compilerArguments;
} }
std::vector<FilePathIndex> PchCreator::generateGlobalPchIncludeIds() const FilePathIds PchCreator::generateGlobalPchIncludeIds() const
{ {
IncludeCollector collector(m_filePathCache); IncludeCollector collector(m_filePathCache);
@@ -256,7 +257,7 @@ std::vector<FilePathIndex> PchCreator::generateGlobalPchIncludeIds() const
namespace { namespace {
std::size_t contentSize(const std::vector<Utils::PathString> &includes) std::size_t contentSize(const FilePaths &includes)
{ {
auto countIncludeSize = [] (std::size_t size, const Utils::PathString &include) { auto countIncludeSize = [] (std::size_t size, const Utils::PathString &include) {
return size + include.size(); return size + include.size();
@@ -266,20 +267,16 @@ std::size_t contentSize(const std::vector<Utils::PathString> &includes)
} }
} }
Utils::SmallString PchCreator::generatePchIncludeFileContent( Utils::SmallString PchCreator::generatePchIncludeFileContent(const FilePathIds &includeIds) const
const std::vector<FilePathIndex> &includeIds) const
{ {
Utils::SmallString fileContent; Utils::SmallString fileContent;
const std::size_t lineTemplateSize = 12; const std::size_t lineTemplateSize = 12;
auto includes = m_filePathCache.strings(includeIds); auto includes = m_filePathCache.filePaths(includeIds);
fileContent.reserve(includes.size() * lineTemplateSize + contentSize(includes)); fileContent.reserve(includes.size() * lineTemplateSize + contentSize(includes));
for (const Utils::PathString &include : includes) { for (const Utils::PathString &include : includes)
fileContent += "#include \""; fileContent += {"#include \"", include, "\"\n"};
fileContent += include;
fileContent += "\"\n";
}
return fileContent; return fileContent;
} }
@@ -461,7 +458,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaderAndSourcePaths(
return includeAndSources; return includeAndSources;
} }
std::vector<FilePathIndex> PchCreator::generateProjectPartPchIncludes( FilePathIds PchCreator::generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const const V2::ProjectPartContainer &projectPart) const
{ {
Utils::SmallString jointedFileContent = generateProjectPartHeaderAndSourcesContent(projectPart); Utils::SmallString jointedFileContent = generateProjectPartHeaderAndSourcesContent(projectPart);

View File

@@ -28,9 +28,9 @@
#include "pchcreatorinterface.h" #include "pchcreatorinterface.h"
#include "pchgeneratorinterface.h" #include "pchgeneratorinterface.h"
#include "stringcache.h"
#include "idpaths.h" #include "idpaths.h"
#include <filepathcachingfwd.h>
#include <projectpartpch.h> #include <projectpartpch.h>
#include <projectpartcontainerv2.h> #include <projectpartcontainerv2.h>
@@ -48,10 +48,10 @@ class PchCreator final : public PchCreatorInterface
{ {
public: public:
PchCreator(Environment &environment, PchCreator(Environment &environment,
FilePathCache<> &filePathCache); FilePathCachingInterface &filePathCache);
PchCreator(V2::ProjectPartContainers &&projectsParts, PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment, Environment &environment,
FilePathCache<> &filePathCache, FilePathCachingInterface &filePathCache,
PchGeneratorInterface *pchGenerator, PchGeneratorInterface *pchGenerator,
V2::FileContainers &&generatedFiles); V2::FileContainers &&generatedFiles);
@@ -70,9 +70,9 @@ unittest_public:
Utils::SmallStringVector generateGlobalPchCompilerArguments() const; Utils::SmallStringVector generateGlobalPchCompilerArguments() const;
Utils::SmallStringVector generateGlobalClangCompilerArguments() const; Utils::SmallStringVector generateGlobalClangCompilerArguments() const;
std::vector<FilePathIndex> generateGlobalPchIncludeIds() const; FilePathIds generateGlobalPchIncludeIds() const;
Utils::SmallString generatePchIncludeFileContent(const std::vector<FilePathIndex> &includeIds) const; Utils::SmallString generatePchIncludeFileContent(const FilePathIds &includeIds) const;
Utils::SmallString generateGlobalPchHeaderFileContent() const; Utils::SmallString generateGlobalPchHeaderFileContent() const;
std::unique_ptr<QFile> generateGlobalPchHeaderFile(); std::unique_ptr<QFile> generateGlobalPchHeaderFile();
void generatePch(Utils::SmallStringVector &&commandLineArguments, void generatePch(Utils::SmallStringVector &&commandLineArguments,
@@ -97,7 +97,7 @@ unittest_public:
const V2::ProjectPartContainer &projectPart); const V2::ProjectPartContainer &projectPart);
static Utils::PathStringVector generateProjectPartHeaderAndSourcePaths( static Utils::PathStringVector generateProjectPartHeaderAndSourcePaths(
const V2::ProjectPartContainer &projectPart); const V2::ProjectPartContainer &projectPart);
std::vector<FilePathIndex> generateProjectPartPchIncludes( FilePathIds generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPathPchHeaderFilePath( Utils::SmallString generateProjectPathPchHeaderFilePath(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
@@ -127,7 +127,7 @@ private:
std::vector<ProjectPartPch> m_projectPartPchs; std::vector<ProjectPartPch> m_projectPartPchs;
std::vector<IdPaths> m_projectsIncludeIds; std::vector<IdPaths> m_projectsIncludeIds;
Environment &m_environment; Environment &m_environment;
FilePathCache<> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
PchGeneratorInterface *m_pchGenerator = nullptr; PchGeneratorInterface *m_pchGenerator = nullptr;
}; };

View File

@@ -36,12 +36,10 @@
namespace ClangBackEnd { namespace ClangBackEnd {
PchManagerServer::PchManagerServer(FilePathCache<> &filePathCache, PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator, PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts) ProjectPartsInterface &projectParts)
: m_filePathCache(filePathCache), : m_fileSystemWatcher(fileSystemWatcher),
m_fileSystemWatcher(fileSystemWatcher),
m_pchCreator(pchCreator), m_pchCreator(pchCreator),
m_projectParts(projectParts) m_projectParts(projectParts)
{ {

View File

@@ -31,7 +31,6 @@
#include "pchgeneratornotifierinterface.h" #include "pchgeneratornotifierinterface.h"
#include "pchmanagerserverinterface.h" #include "pchmanagerserverinterface.h"
#include "projectpartsinterface.h" #include "projectpartsinterface.h"
#include "stringcache.h"
#include <ipcclientprovider.h> #include <ipcclientprovider.h>
@@ -46,8 +45,7 @@ class PchManagerServer : public PchManagerServerInterface,
{ {
public: public:
PchManagerServer(FilePathCache<> &filePathCache, PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator, PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts); ProjectPartsInterface &projectParts);
@@ -60,7 +58,6 @@ public:
void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override; void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override;
private: private:
FilePathCache<> &m_filePathCache;
ClangPathWatcherInterface &m_fileSystemWatcher; ClangPathWatcherInterface &m_fileSystemWatcher;
PchCreatorInterface &m_pchCreator; PchCreatorInterface &m_pchCreator;
ProjectPartsInterface &m_projectParts; ProjectPartsInterface &m_projectParts;

View File

@@ -29,14 +29,15 @@
#include <QDir> #include <QDir>
#include <connectionserver.h> #include <connectionserver.h>
#include <stringcache.h> #include <filepathcaching.h>
#include <refactoringserver.h> #include <refactoringserver.h>
#include <refactoringclientproxy.h> #include <refactoringclientproxy.h>
#include <symbolindexing.h> #include <symbolindexing.h>
using ClangBackEnd::FilePathCache; using ClangBackEnd::FilePathCaching;
using ClangBackEnd::RefactoringClientProxy; using ClangBackEnd::RefactoringClientProxy;
using ClangBackEnd::RefactoringServer; using ClangBackEnd::RefactoringServer;
using ClangBackEnd::RefactoringDatabaseInitializer;
using ClangBackEnd::ConnectionServer; using ClangBackEnd::ConnectionServer;
using ClangBackEnd::SymbolIndexing; using ClangBackEnd::SymbolIndexing;
@@ -69,8 +70,10 @@ try {
const QString connection = processArguments(application); const QString connection = processArguments(application);
FilePathCache<std::mutex> filePathCache; Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}};
SymbolIndexing symbolIndexing{filePathCache, Utils::PathString{QDir::tempPath() + "/symbol.db"}}; RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
FilePathCaching filePathCache{database};
SymbolIndexing symbolIndexing{database, filePathCache};
RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache}; RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache};
ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection); ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection);
connectionServer.start(); connectionServer.start();

View File

@@ -54,16 +54,16 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
} }
}; };
ClangQuery::ClangQuery(FilePathCache<std::mutex> &filePathCache, ClangQuery::ClangQuery(FilePathCachingInterface &filePathCache,
Utils::SmallString &&query) Utils::SmallString &&query)
: query(std::move(query)), : m_query(std::move(query)),
filePathCache(filePathCache) m_filePathCache(filePathCache)
{ {
} }
void ClangQuery::setQuery(Utils::SmallString &&query) void ClangQuery::setQuery(Utils::SmallString &&query)
{ {
this->query = std::move(query); this->m_query = std::move(query);
} }
void ClangQuery::findLocations() void ClangQuery::findLocations()
@@ -78,7 +78,7 @@ void ClangQuery::findLocations()
std::make_move_iterator(asts.end()), std::make_move_iterator(asts.end()),
[&] (std::unique_ptr<clang::ASTUnit> &&ast) { [&] (std::unique_ptr<clang::ASTUnit> &&ast) {
Diagnostics diagnostics; Diagnostics diagnostics;
auto optionalMatcher = Parser::parseMatcherExpression({query.data(), query.size()}, auto optionalMatcher = Parser::parseMatcherExpression({m_query.data(), m_query.size()},
nullptr, nullptr,
&diagnostics); &diagnostics);
parseDiagnostics(diagnostics); parseDiagnostics(diagnostics);
@@ -89,19 +89,19 @@ void ClangQuery::findLocations()
SourceRangesContainer ClangQuery::takeSourceRanges() SourceRangesContainer ClangQuery::takeSourceRanges()
{ {
return std::move(sourceRangesContainer); return std::move(m_sourceRangesContainer);
} }
DynamicASTMatcherDiagnosticContainers ClangQuery::takeDiagnosticContainers() DynamicASTMatcherDiagnosticContainers ClangQuery::takeDiagnosticContainers()
{ {
return std::move(diagnosticContainers_); return std::move(m_diagnosticContainers_);
} }
namespace { namespace {
V2::SourceRangeContainer convertToContainer(const clang::ast_matchers::dynamic::SourceRange sourceRange) V2::SourceRangeContainer convertToContainer(const clang::ast_matchers::dynamic::SourceRange sourceRange)
{ {
return V2::SourceRangeContainer(0, return V2::SourceRangeContainer({1, 0},
sourceRange.Start.Line, sourceRange.Start.Line,
sourceRange.Start.Column, sourceRange.Start.Column,
0, 0,
@@ -159,8 +159,8 @@ void ClangQuery::parseDiagnostics(const clang::ast_matchers::dynamic::Diagnostic
auto errors = diagnostics.errors(); auto errors = diagnostics.errors();
for (const auto &errorContent : errors) { for (const auto &errorContent : errors) {
diagnosticContainers_.emplace_back(); m_diagnosticContainers_.emplace_back();
DynamicASTMatcherDiagnosticContainer &diagnosticContainer = diagnosticContainers_.back(); DynamicASTMatcherDiagnosticContainer &diagnosticContainer = m_diagnosticContainers_.back();
for (const auto &message : errorContent.Messages) { for (const auto &message : errorContent.Messages) {
diagnosticContainer.insertMessage(convertToContainer(message.Range), diagnosticContainer.insertMessage(convertToContainer(message.Range),
@@ -216,8 +216,8 @@ void ClangQuery::matchLocation(
SourceRangeExtractor extractor(ast->getSourceManager(), SourceRangeExtractor extractor(ast->getSourceManager(),
ast->getLangOpts(), ast->getLangOpts(),
filePathCache, m_filePathCache,
sourceRangesContainer); m_sourceRangesContainer);
extractor.addSourceRanges(sourceRanges); extractor.addSourceRanges(sourceRanges);
} }

View File

@@ -30,7 +30,7 @@
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#include <dynamicastmatcherdiagnosticcontainer.h> #include <dynamicastmatcherdiagnosticcontainer.h>
#include <stringcache.h> #include <filepathcachingfwd.h>
namespace clang { namespace clang {
namespace ast_matchers { namespace ast_matchers {
@@ -51,9 +51,9 @@ namespace ClangBackEnd {
class ClangQuery : public ClangTool class ClangQuery : public ClangTool
{ {
public: public:
ClangQuery(FilePathCache<std::mutex> &filePathCache, Utils::SmallString &&query={}); ClangQuery(FilePathCachingInterface &m_filePathCache, Utils::SmallString &&m_query={});
void setQuery(Utils::SmallString &&query); void setQuery(Utils::SmallString &&m_query);
void findLocations(); void findLocations();
@@ -66,10 +66,10 @@ private:
std::unique_ptr<clang::ASTUnit> ast); std::unique_ptr<clang::ASTUnit> ast);
private: private:
SourceRangesContainer sourceRangesContainer; SourceRangesContainer m_sourceRangesContainer;
Utils::SmallString query; Utils::SmallString m_query;
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_; std::vector<DynamicASTMatcherDiagnosticContainer> m_diagnosticContainers_;
FilePathCache<std::mutex> &filePathCache; ClangBackEnd::FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,7 +29,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
ClangQueryGatherer::ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache, ClangQueryGatherer::ClangQueryGatherer(FilePathCachingInterface *filePathCache,
std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query) Utils::SmallString &&query)
@@ -43,7 +43,7 @@ ClangQueryGatherer::ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
SourceRangesForQueryMessage SourceRangesForQueryMessage
ClangQueryGatherer::createSourceRangesForSource( ClangQueryGatherer::createSourceRangesForSource(
FilePathCache<std::mutex> *filePathCache, FilePathCachingInterface *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query) Utils::SmallString &&query)

View File

@@ -29,7 +29,7 @@
#include <sourcerangesforquerymessage.h> #include <sourcerangesforquerymessage.h>
#include <filecontainerv2.h> #include <filecontainerv2.h>
#include <stringcache.h> #include <filepathcachingfwd.h>
#include <future> #include <future>
@@ -41,13 +41,13 @@ public:
using Future = std::future<SourceRangesForQueryMessage>; using Future = std::future<SourceRangesForQueryMessage>;
ClangQueryGatherer() = default; ClangQueryGatherer() = default;
ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache, ClangQueryGatherer(FilePathCachingInterface *filePathCache,
std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
static SourceRangesForQueryMessage createSourceRangesForSource( static SourceRangesForQueryMessage createSourceRangesForSource(
FilePathCache<std::mutex> *filePathCache, FilePathCachingInterface *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
@@ -69,7 +69,7 @@ protected:
std::vector<Future> finishedFutures(); std::vector<Future> finishedFutures();
private: private:
FilePathCache<std::mutex> *m_filePathCache = nullptr; FilePathCachingInterface *m_filePathCache = nullptr;
SourceRangeFilter m_sourceRangeFilter; SourceRangeFilter m_sourceRangeFilter;
std::vector<V2::FileContainer> m_sources; std::vector<V2::FileContainer> m_sources;
std::vector<V2::FileContainer> m_unsaved; std::vector<V2::FileContainer> m_unsaved;

View File

@@ -57,5 +57,4 @@ HEADERS += \
SOURCES += \ SOURCES += \
$$PWD/sourcerangefilter.cpp \ $$PWD/sourcerangefilter.cpp \
$$PWD/symbolindexer.cpp \ $$PWD/symbolindexer.cpp \
$$PWD/symbolentry.cpp \ $$PWD/symbolentry.cpp
$$PWD/sourcelocationentry.cpp

View File

@@ -31,7 +31,7 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <stringcachefwd.h> #include <filepathcachingfwd.h>
#include <clang/Frontend/FrontendAction.h> #include <clang/Frontend/FrontendAction.h>
@@ -42,7 +42,7 @@ namespace ClangBackEnd {
class CollectSymbolsAction class CollectSymbolsAction
{ {
public: public:
CollectSymbolsAction(FilePathCache<std::mutex> &filePathCache) CollectSymbolsAction(FilePathCachingInterface &filePathCache)
: m_filePathCache(filePathCache) : m_filePathCache(filePathCache)
{} {}
@@ -66,7 +66,7 @@ public:
private: private:
SymbolEntries m_symbolEntries; SymbolEntries m_symbolEntries;
SourceLocationEntries m_sourceLocationEntries; SourceLocationEntries m_sourceLocationEntries;
FilePathCache<std::mutex> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
}; };

View File

@@ -28,7 +28,7 @@
#include "symbolentry.h" #include "symbolentry.h"
#include "sourcelocationentry.h" #include "sourcelocationentry.h"
#include <stringcache.h> #include <filepathcachinginterface.h>
#include <clang/AST/AST.h> #include <clang/AST/AST.h>
#include <clang/AST/ASTContext.h> #include <clang/AST/ASTContext.h>
@@ -50,7 +50,7 @@ class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor<CollectSymbol
public: public:
CollectSymbolsASTVisitor(SymbolEntries &symbolEntries, CollectSymbolsASTVisitor(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries, SourceLocationEntries &sourceLocationEntries,
FilePathCache<std::mutex> &filePathCache, FilePathCachingInterface &filePathCache,
const clang::SourceManager &sourceManager) const clang::SourceManager &sourceManager)
: m_symbolEntries(symbolEntries), : m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries), m_sourceLocationEntries(sourceLocationEntries),
@@ -100,7 +100,7 @@ public:
return true; return true;
} }
FilePathIndex filePathId(clang::SourceLocation sourceLocation) FilePathId filePathId(clang::SourceLocation sourceLocation)
{ {
uint clangFileId = m_sourceManager.getFileID(sourceLocation).getHashValue(); uint clangFileId = m_sourceManager.getFileID(sourceLocation).getHashValue();
@@ -111,11 +111,11 @@ public:
auto filePath = m_sourceManager.getFilename(sourceLocation); auto filePath = m_sourceManager.getFilename(sourceLocation);
FilePathIndex index = m_filePathCache.stringId(toStringView(filePath)); FilePathId filePathId = m_filePathCache.filePathId(toStringView(filePath));
m_filePathIndices.emplace(clangFileId, index); m_filePathIndices.emplace(clangFileId, filePathId);
return index; return filePathId;
} }
LineColumn lineColum(clang::SourceLocation sourceLocation) LineColumn lineColum(clang::SourceLocation sourceLocation)
@@ -147,9 +147,9 @@ public:
private: private:
SymbolEntries &m_symbolEntries; SymbolEntries &m_symbolEntries;
std::unordered_map<uint, FilePathIndex> m_filePathIndices; std::unordered_map<uint, FilePathId> m_filePathIndices;
SourceLocationEntries &m_sourceLocationEntries; SourceLocationEntries &m_sourceLocationEntries;
FilePathCache<std::mutex> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
const clang::SourceManager &m_sourceManager; const clang::SourceManager &m_sourceManager;
}; };

View File

@@ -31,7 +31,7 @@
#include <clang/AST/ASTConsumer.h> #include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h> #include <clang/AST/ASTContext.h>
#include <stringcachefwd.h> #include <filepathcachingfwd.h>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -40,7 +40,7 @@ class CollectSymbolsConsumer : public clang::ASTConsumer
public: public:
CollectSymbolsConsumer(SymbolEntries &symbolEntries, CollectSymbolsConsumer(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries, SourceLocationEntries &sourceLocationEntries,
FilePathCache<std::mutex> &filePathCache) FilePathCachingInterface &filePathCache)
: m_symbolEntries(symbolEntries), : m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries), m_sourceLocationEntries(sourceLocationEntries),
m_filePathCache(filePathCache) m_filePathCache(filePathCache)
@@ -69,6 +69,6 @@ public:
private: private:
SymbolEntries &m_symbolEntries; SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries; SourceLocationEntries &m_sourceLocationEntries;
FilePathCache<std::mutex> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
}; };
} }

View File

@@ -48,9 +48,12 @@
namespace ClangBackEnd { namespace ClangBackEnd {
LocationSourceFileCallbacks::LocationSourceFileCallbacks(uint line, uint column) LocationSourceFileCallbacks::LocationSourceFileCallbacks(uint line,
: line(line), uint column,
column(column) FilePathCachingInterface &filePathCache)
: m_filePathCache(filePathCache),
m_line(line),
m_column(column)
{ {
} }
@@ -58,30 +61,31 @@ bool LocationSourceFileCallbacks::handleBeginSource(clang::CompilerInstance &com
{ {
auto &preprocessor = compilerInstance.getPreprocessor(); auto &preprocessor = compilerInstance.getPreprocessor();
macroPreprocessorCallbacks = new MacroPreprocessorCallbacks(sourceLocationsContainer, m_macroPreprocessorCallbacks = new MacroPreprocessorCallbacks(m_sourceLocationsContainer,
symbolName, m_symbolName,
preprocessor, preprocessor,
line, m_filePathCache,
column); m_line,
m_column);
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks)); preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(m_macroPreprocessorCallbacks));
return true; return true;
} }
SourceLocationsContainer LocationSourceFileCallbacks::takeSourceLocations() SourceLocationsContainer LocationSourceFileCallbacks::takeSourceLocations()
{ {
return std::move(sourceLocationsContainer); return std::move(m_sourceLocationsContainer);
} }
Utils::SmallString LocationSourceFileCallbacks::takeSymbolName() Utils::SmallString LocationSourceFileCallbacks::takeSymbolName()
{ {
return std::move(symbolName); return std::move(m_symbolName);
} }
bool LocationSourceFileCallbacks::hasSourceLocations() const bool LocationSourceFileCallbacks::hasSourceLocations() const
{ {
return sourceLocationsContainer.hasContent(); return m_sourceLocationsContainer.hasContent();
} }

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include <filepathcachingfwd.h>
#include <sourcelocationscontainer.h> #include <sourcelocationscontainer.h>
#include <clang/Tooling/Tooling.h> #include <clang/Tooling/Tooling.h>
@@ -45,7 +46,7 @@ class SourceLocationsContainer;
class LocationSourceFileCallbacks : public clang::tooling::SourceFileCallbacks class LocationSourceFileCallbacks : public clang::tooling::SourceFileCallbacks
{ {
public: public:
LocationSourceFileCallbacks(uint line, uint column); LocationSourceFileCallbacks(uint line, uint column, FilePathCachingInterface &filePathCache);
bool handleBeginSource(clang::CompilerInstance &compilerInstance, bool handleBeginSource(clang::CompilerInstance &compilerInstance,
llvm::StringRef fileName) override; llvm::StringRef fileName) override;
@@ -56,11 +57,12 @@ public:
bool hasSourceLocations() const; bool hasSourceLocations() const;
private: private:
SourceLocationsContainer sourceLocationsContainer; SourceLocationsContainer m_sourceLocationsContainer;
Utils::SmallString symbolName; Utils::SmallString m_symbolName;
MacroPreprocessorCallbacks *macroPreprocessorCallbacks; MacroPreprocessorCallbacks *m_macroPreprocessorCallbacks;
uint line; FilePathCachingInterface &m_filePathCache;
uint column; uint m_line;
uint m_column;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -30,13 +30,15 @@ namespace ClangBackEnd {
MacroPreprocessorCallbacks::MacroPreprocessorCallbacks(SourceLocationsContainer &sourceLocationsContainer, MacroPreprocessorCallbacks::MacroPreprocessorCallbacks(SourceLocationsContainer &sourceLocationsContainer,
Utils::SmallString &symbolName, Utils::SmallString &symbolName,
clang::Preprocessor &preprocessor, clang::Preprocessor &preprocessor,
FilePathCachingInterface &filePathCache,
uint line, uint line,
uint column) uint column)
: sourceLocationsContainer(sourceLocationsContainer), : m_sourceLocationsContainer(sourceLocationsContainer),
symbolName(symbolName), m_symbolName(symbolName),
preprocessor(preprocessor), m_preprocessor(preprocessor),
line(line), m_filePathCache(filePathCache),
column(column) m_line(line),
m_column(column)
{ {
} }

View File

@@ -27,27 +27,14 @@
#include "sourcelocationsutils.h" #include "sourcelocationsutils.h"
#include <filepathcachingfwd.h>
#include <sourcelocationscontainer.h> #include <sourcelocationscontainer.h>
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning( disable : 4100 )
#endif
#include <clang/Basic/SourceManager.h> #include <clang/Basic/SourceManager.h>
#include <clang/Lex/PPCallbacks.h> #include <clang/Lex/PPCallbacks.h>
#include <clang/Lex/Preprocessor.h> #include <clang/Lex/Preprocessor.h>
#include <clang/Lex/MacroInfo.h> #include <clang/Lex/MacroInfo.h>
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
#include <QDebug> #include <QDebug>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -67,18 +54,19 @@ struct MacroDirectiveToken
class MacroPreprocessorCallbacks : public clang::PPCallbacks class MacroPreprocessorCallbacks : public clang::PPCallbacks
{ {
public: public:
MacroPreprocessorCallbacks(SourceLocationsContainer &sourceLocationsContainer, MacroPreprocessorCallbacks(SourceLocationsContainer &m_sourceLocationsContainer,
Utils::SmallString &symbolName, Utils::SmallString &m_symbolName,
clang::Preprocessor &preprocessor, clang::Preprocessor &m_preprocessor,
uint line, FilePathCachingInterface &filePathCache,
uint column); uint m_line,
uint m_column);
void FileChanged(clang::SourceLocation location, void FileChanged(clang::SourceLocation location,
FileChangeReason reason, FileChangeReason reason,
clang::SrcMgr::CharacteristicKind /*fileType*/, clang::SrcMgr::CharacteristicKind /*fileType*/,
clang::FileID /*previousFileIdentifier*/) final clang::FileID /*previousFileIdentifier*/) final
{ {
if (!isMainFileEntered) { if (!m_isMainFileEntered) {
updateLocations(); updateLocations();
updateIsMainFileEntered(location, reason); updateIsMainFileEntered(location, reason);
} }
@@ -88,9 +76,9 @@ public:
{ {
if (isInMainFile(token)) { if (isInMainFile(token)) {
if (includesCursorPosition(token)) { if (includesCursorPosition(token)) {
sourceLocations.push_back(token.getLocation()); m_sourceLocations.push_back(token.getLocation());
cursorMacroDirective = macroDirective; m_cursorMacroDirective = macroDirective;
symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(), m_symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(),
token.getIdentifierInfo()->getLength()); token.getIdentifierInfo()->getLength());
} }
} }
@@ -103,59 +91,60 @@ public:
{ {
if (includesCursorPosition(token)) { if (includesCursorPosition(token)) {
appendSourceLocations(token, macroDefinition); appendSourceLocations(token, macroDefinition);
cursorMacroDirective = macroDefinition.getLocalDirective(); m_cursorMacroDirective = macroDefinition.getLocalDirective();
symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(), m_symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(),
token.getIdentifierInfo()->getLength()); token.getIdentifierInfo()->getLength());
} else if (isCurrentTokenExpansion(macroDefinition)) { } else if (isCurrentTokenExpansion(macroDefinition)) {
sourceLocations.push_back(token.getLocation()); m_sourceLocations.push_back(token.getLocation());
} else if (isBeforeCursorSourceLocation()) { } else if (isBeforeCursorSourceLocation()) {
preCursorMacroDirectiveTokens.emplace_back(macroDefinition.getLocalDirective(), token); m_preCursorMacroDirectiveTokens.emplace_back(macroDefinition.getLocalDirective(), token);
} }
} }
void EndOfMainFile() final void EndOfMainFile() final
{ {
appendSourceLocationsToSourceLocationsContainer(sourceLocationsContainer, appendSourceLocationsToSourceLocationsContainer(m_sourceLocationsContainer,
sourceLocations, m_sourceLocations,
sourceManager()); sourceManager(),
m_filePathCache);
} }
private: private:
void appendSourceLocations(const clang::Token &token, void appendSourceLocations(const clang::Token &token,
const clang::MacroDefinition &macroDefinition) const clang::MacroDefinition &macroDefinition)
{ {
sourceLocations.push_back(macroDefinition.getLocalDirective()->getLocation()); m_sourceLocations.push_back(macroDefinition.getLocalDirective()->getLocation());
for (const auto &macroDirectiveToken : preCursorMacroDirectiveTokens) { for (const auto &macroDirectiveToken : m_preCursorMacroDirectiveTokens) {
if (macroDirectiveToken.macroDirective == macroDefinition.getLocalDirective()) if (macroDirectiveToken.macroDirective == macroDefinition.getLocalDirective())
sourceLocations.push_back(macroDirectiveToken.token.getLocation()); m_sourceLocations.push_back(macroDirectiveToken.token.getLocation());
} }
sourceLocations.push_back(token.getLocation()); m_sourceLocations.push_back(token.getLocation());
} }
void updateLocations() void updateLocations()
{ {
if (mainFileSourceLocation.isInvalid()) { if (m_mainFileSourceLocation.isInvalid()) {
mainFileSourceLocation = sourceManager().getLocForStartOfFile(sourceManager().getMainFileID()); m_mainFileSourceLocation = sourceManager().getLocForStartOfFile(sourceManager().getMainFileID());
cursorSourceLocation = sourceManager().translateLineCol(sourceManager().getMainFileID(), m_cursorSourceLocation = sourceManager().translateLineCol(sourceManager().getMainFileID(),
line, m_line,
column); m_column);
} }
} }
void updateIsMainFileEntered(clang::SourceLocation location, FileChangeReason reason) void updateIsMainFileEntered(clang::SourceLocation location, FileChangeReason reason)
{ {
if (location == mainFileSourceLocation && reason == PPCallbacks::EnterFile) if (location == m_mainFileSourceLocation && reason == PPCallbacks::EnterFile)
isMainFileEntered = true; m_isMainFileEntered = true;
} }
const clang::SourceManager &sourceManager() const const clang::SourceManager &sourceManager() const
{ {
return preprocessor.getSourceManager(); return m_preprocessor.getSourceManager();
} }
bool isInMainFile(const clang::Token &token) bool isInMainFile(const clang::Token &token)
{ {
return isMainFileEntered && sourceManager().isWrittenInMainFile(token.getLocation()); return m_isMainFileEntered && sourceManager().isWrittenInMainFile(token.getLocation());
} }
bool includesCursorPosition(const clang::Token &token) bool includesCursorPosition(const clang::Token &token)
@@ -163,35 +152,36 @@ private:
auto start = token.getLocation(); auto start = token.getLocation();
auto end = token.getEndLoc(); auto end = token.getEndLoc();
return cursorSourceLocation == start return m_cursorSourceLocation == start
|| cursorSourceLocation == end || m_cursorSourceLocation == end
|| (sourceManager().isBeforeInTranslationUnit(start, cursorSourceLocation) && || (sourceManager().isBeforeInTranslationUnit(start, m_cursorSourceLocation) &&
sourceManager().isBeforeInTranslationUnit(cursorSourceLocation, end)); sourceManager().isBeforeInTranslationUnit(m_cursorSourceLocation, end));
} }
bool isCurrentTokenExpansion(const clang::MacroDefinition &macroDefinition) bool isCurrentTokenExpansion(const clang::MacroDefinition &macroDefinition)
{ {
return cursorMacroDirective return m_cursorMacroDirective
&& cursorMacroDirective == macroDefinition.getLocalDirective(); && m_cursorMacroDirective == macroDefinition.getLocalDirective();
} }
bool isBeforeCursorSourceLocation() const bool isBeforeCursorSourceLocation() const
{ {
return !cursorMacroDirective; return !m_cursorMacroDirective;
} }
private: private:
std::vector<clang::SourceLocation> sourceLocations; std::vector<clang::SourceLocation> m_sourceLocations;
std::vector<MacroDirectiveToken> preCursorMacroDirectiveTokens; std::vector<MacroDirectiveToken> m_preCursorMacroDirectiveTokens;
SourceLocationsContainer &sourceLocationsContainer; SourceLocationsContainer &m_sourceLocationsContainer;
Utils::SmallString &symbolName; Utils::SmallString &m_symbolName;
clang::Preprocessor &preprocessor; clang::Preprocessor &m_preprocessor;
const clang::MacroDirective *cursorMacroDirective = nullptr; const clang::MacroDirective *m_cursorMacroDirective = nullptr;
clang::SourceLocation mainFileSourceLocation; clang::SourceLocation m_mainFileSourceLocation;
clang::SourceLocation cursorSourceLocation; clang::SourceLocation m_cursorSourceLocation;
uint line; FilePathCachingInterface &m_filePathCache;
uint column; uint m_line;
bool isMainFileEntered = false; uint m_column;
bool m_isMainFileEntered = false;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -40,7 +40,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing, RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing,
FilePathCache<std::mutex> &filePathCache) FilePathCachingInterface &filePathCache)
: m_symbolIndexing(symbolIndexing), : m_symbolIndexing(symbolIndexing),
m_filePathCache(filePathCache) m_filePathCache(filePathCache)
{ {
@@ -58,7 +58,7 @@ void RefactoringServer::end()
void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message)
{ {
SymbolFinder symbolFinder(message.line(), message.column()); SymbolFinder symbolFinder(message.line(), message.column(), m_filePathCache);
symbolFinder.addFile(std::string(message.filePath().directory()), symbolFinder.addFile(std::string(message.filePath().directory()),
std::string(message.filePath().name()), std::string(message.filePath().name()),

View File

@@ -29,12 +29,13 @@
#include <refactoringserverinterface.h> #include <refactoringserverinterface.h>
#include <QTimer>
#include <ipcclientprovider.h> #include <ipcclientprovider.h>
#include <stringcache.h> #include <filepathcachinginterface.h>
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <QTimer>
#include <future> #include <future>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
@@ -54,7 +55,7 @@ class RefactoringServer : public RefactoringServerInterface,
using Future = std::future<SourceRangesForQueryMessage>; using Future = std::future<SourceRangesForQueryMessage>;
public: public:
RefactoringServer(SymbolIndexingInterface &symbolIndexing, RefactoringServer(SymbolIndexingInterface &symbolIndexing,
FilePathCache<std::mutex> &filePathCache); FilePathCachingInterface &filePathCache);
void end() override; void end() override;
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
@@ -82,7 +83,7 @@ private:
ClangQueryGatherer m_gatherer; ClangQueryGatherer m_gatherer;
QTimer m_pollTimer; QTimer m_pollTimer;
SymbolIndexingInterface &m_symbolIndexing; SymbolIndexingInterface &m_symbolIndexing;
FilePathCache<std::mutex> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,11 +25,10 @@
#pragma once #pragma once
#include <stringcachefwd.h> #include <filepathid.h>
#include <limits> #include <limits>
#include <vector> #include <vector>
#include <iosfwd>
using uint = unsigned int; using uint = unsigned int;
@@ -59,18 +58,18 @@ class SourceLocationEntry
{ {
public: public:
SourceLocationEntry(SymbolIndex symbolId, SourceLocationEntry(SymbolIndex symbolId,
FilePathIndex fileId, FilePathId filePathId,
LineColumn lineColumn, LineColumn lineColumn,
SymbolType symbolType) SymbolType symbolType)
: symbolId(symbolId), : symbolId(symbolId),
fileId(fileId), filePathId(filePathId),
line(lineColumn.line), line(lineColumn.line),
column(lineColumn.column), column(lineColumn.column),
symbolType(symbolType) symbolType(symbolType)
{} {}
SymbolIndex symbolId = 0; SymbolIndex symbolId = 0;
FilePathIndex fileId = std::numeric_limits<uint>::max(); FilePathId filePathId;
uint line = 0; uint line = 0;
uint column = 0; uint column = 0;
SymbolType symbolType; SymbolType symbolType;
@@ -78,7 +77,7 @@ public:
friend bool operator==(const SourceLocationEntry &first, const SourceLocationEntry &second) friend bool operator==(const SourceLocationEntry &first, const SourceLocationEntry &second)
{ {
return first.symbolId == second.symbolId return first.symbolId == second.symbolId
&& first.fileId == second.fileId && first.filePathId == second.filePathId
&& first.line == second.line && first.line == second.line
&& first.column == second.column && first.column == second.column
&& first.symbolType == second.symbolType; && first.symbolType == second.symbolType;
@@ -87,6 +86,4 @@ public:
using SourceLocationEntries = std::vector<SourceLocationEntry>; using SourceLocationEntries = std::vector<SourceLocationEntry>;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,28 +25,15 @@
#pragma once #pragma once
#include <filepathcachinginterface.h>
#include <sourcelocationscontainer.h> #include <sourcelocationscontainer.h>
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning( disable : 4100 )
#endif
#include <clang/Basic/SourceManager.h> #include <clang/Basic/SourceManager.h>
#include <clang/Lex/Lexer.h> #include <clang/Lex/Lexer.h>
#include <llvm/Support/FileSystem.h> #include <llvm/Support/FileSystem.h>
#include <llvm/Support/FileUtilities.h> #include <llvm/Support/FileUtilities.h>
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
#include <iterator> #include <iterator>
#include <cctype> #include <cctype>
@@ -79,7 +66,8 @@ inline
void appendSourceLocationsToSourceLocationsContainer( void appendSourceLocationsToSourceLocationsContainer(
ClangBackEnd::SourceLocationsContainer &sourceLocationsContainer, ClangBackEnd::SourceLocationsContainer &sourceLocationsContainer,
const std::vector<clang::SourceLocation> &sourceLocations, const std::vector<clang::SourceLocation> &sourceLocations,
const clang::SourceManager &sourceManager) const clang::SourceManager &sourceManager,
FilePathCachingInterface &filePathCache)
{ {
sourceLocationsContainer.reserve(sourceLocations.size()); sourceLocationsContainer.reserve(sourceLocations.size());
@@ -89,10 +77,9 @@ void appendSourceLocationsToSourceLocationsContainer(
const auto fileId = decomposedLoction.first; const auto fileId = decomposedLoction.first;
const auto offset = decomposedLoction.second; const auto offset = decomposedLoction.second;
const auto fileEntry = sourceManager.getFileEntryForID(fileId); const auto fileEntry = sourceManager.getFileEntryForID(fileId);
auto filePath = fromNativePath(absolutePath(fileEntry->getName()));
sourceLocationsContainer.insertFilePath(fileId.getHashValue(), sourceLocationsContainer.insertSourceLocation(filePathCache.filePathId(filePath),
fromNativePath(absolutePath(fileEntry->getName())));
sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(),
fullSourceLocation.getSpellingLineNumber(), fullSourceLocation.getSpellingLineNumber(),
fullSourceLocation.getSpellingColumnNumber(), fullSourceLocation.getSpellingColumnNumber(),
offset); offset);

View File

@@ -28,14 +28,7 @@
#include "sourcelocationsutils.h" #include "sourcelocationsutils.h"
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#include <filepathcachinginterface.h>
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning( disable : 4100 )
#endif
#include <clang/Basic/SourceManager.h> #include <clang/Basic/SourceManager.h>
#include <clang/Lex/Lexer.h> #include <clang/Lex/Lexer.h>
@@ -43,18 +36,12 @@
#include <llvm/Support/FileUtilities.h> #include <llvm/Support/FileUtilities.h>
#include <llvm/ADT/SmallVector.h> #include <llvm/ADT/SmallVector.h>
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
namespace ClangBackEnd { namespace ClangBackEnd {
SourceRangeExtractor::SourceRangeExtractor( SourceRangeExtractor::SourceRangeExtractor(
const clang::SourceManager &sourceManager, const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::FilePathCache<std::mutex> &filePathCache, FilePathCachingInterface &filePathCache,
SourceRangesContainer &sourceRangesContainer) SourceRangesContainer &sourceRangesContainer)
: sourceManager(sourceManager), : sourceManager(sourceManager),
languageOptions(languageOptions), languageOptions(languageOptions),
@@ -127,16 +114,14 @@ const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(c
return {sourceRange.getBegin(), endLocation}; return {sourceRange.getBegin(), endLocation};
} }
void SourceRangeExtractor::insertSourceRange(uint fileId, void SourceRangeExtractor::insertSourceRange(FilePathId filePathId,
Utils::PathString &&filePath,
const clang::FullSourceLoc &startLocation, const clang::FullSourceLoc &startLocation,
uint startOffset, uint startOffset,
const clang::FullSourceLoc &endLocation, const clang::FullSourceLoc &endLocation,
uint endOffset, uint endOffset,
Utils::SmallString &&lineSnippet) Utils::SmallString &&lineSnippet)
{ {
sourceRangesContainer.insertFilePath(fileId, std::move(filePath)); sourceRangesContainer.insertSourceRange(filePathId,
sourceRangesContainer.insertSourceRange(fileId,
startLocation.getSpellingLineNumber(), startLocation.getSpellingLineNumber(),
startLocation.getSpellingColumnNumber(), startLocation.getSpellingColumnNumber(),
startOffset, startOffset,
@@ -146,7 +131,7 @@ void SourceRangeExtractor::insertSourceRange(uint fileId,
std::move(lineSnippet)); std::move(lineSnippet));
} }
FilePathIndex SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const FilePathId SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const
{ {
auto found = m_fileIdMapping.find(fileId.getHashValue()); auto found = m_fileIdMapping.find(fileId.getHashValue());
if (found != m_fileIdMapping.end()) { if (found != m_fileIdMapping.end()) {
@@ -154,7 +139,7 @@ FilePathIndex SourceRangeExtractor::findFileId(clang::FileID fileId, const clang
} }
auto filePath = absolutePath(fileEntry->getName()); auto filePath = absolutePath(fileEntry->getName());
return filePathCache.stringId(fromNativePath(filePath)); return filePathCache.filePathId(fromNativePath(filePath));
} }
void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange) void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
@@ -176,13 +161,11 @@ void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
endOffset); endOffset);
insertSourceRange(findFileId(fileId, fileEntry), insertSourceRange(findFileId(fileId, fileEntry),
fromNativePath(absolutePath(fileEntry->getName())),
startSourceLocation, startSourceLocation,
startOffset, startOffset,
endSourceLocation, endSourceLocation,
endOffset, endOffset,
std::move(lineSnippet)); std::move(lineSnippet));
} }
} }

View File

@@ -25,9 +25,10 @@
#pragma once #pragma once
#include <stringcache.h> #include <filepathcachingfwd.h>
#include <filepath.h> #include <filepath.h>
#include <filepathid.h>
#include <utils/smallstringfwd.h> #include <utils/smallstringfwd.h>
@@ -59,7 +60,7 @@ class SourceRangeExtractor
public: public:
SourceRangeExtractor(const clang::SourceManager &sourceManager, SourceRangeExtractor(const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::FilePathCache<std::mutex> &filePathCache, FilePathCachingInterface &filePathCache,
SourceRangesContainer &sourceRangesContainer); SourceRangesContainer &sourceRangesContainer);
void addSourceRange(const clang::SourceRange &sourceRange); void addSourceRange(const clang::SourceRange &sourceRange);
@@ -74,21 +75,20 @@ public:
const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange); const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange);
private: private:
void insertSourceRange(uint fileId, void insertSourceRange(FilePathId filePathId,
Utils::PathString &&filePath,
const clang::FullSourceLoc &startLocation, const clang::FullSourceLoc &startLocation,
uint startOffset, uint startOffset,
const clang::FullSourceLoc &endLocation, const clang::FullSourceLoc &endLocation,
uint endOffset, uint endOffset,
Utils::SmallString &&lineSnippet); Utils::SmallString &&lineSnippet);
FilePathIndex findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; FilePathId findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
private: private:
mutable std::unordered_map<uint, uint> m_fileIdMapping; mutable std::unordered_map<uint, FilePathId> m_fileIdMapping;
const clang::SourceManager &sourceManager; const clang::SourceManager &sourceManager;
const clang::LangOptions &languageOptions; const clang::LangOptions &languageOptions;
ClangBackEnd::FilePathCache<std::mutex> &filePathCache; FilePathCachingInterface &filePathCache;
SourceRangesContainer &sourceRangesContainer; SourceRangesContainer &sourceRangesContainer;
}; };

View File

@@ -25,8 +25,6 @@
#pragma once #pragma once
#include <createtablesqlstatementbuilder.h>
#include <sqlitetransaction.h> #include <sqlitetransaction.h>
#include <sqlitetable.h> #include <sqlitetable.h>
@@ -96,9 +94,6 @@ public:
"INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)", "INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)",
database database
}; };
// WriteStatement syncNewLocationsToLocationsStatement{
// "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
// database};
ReadStatement selectNewSourceIdsStatement{ ReadStatement selectNewSourceIdsStatement{
"SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)", "SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)",
database database
@@ -109,10 +104,6 @@ public:
"(SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)", "(SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)",
database database
}; };
WriteStatement insertSourcesStatement{
"INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)",
database
};
WriteStatement syncNewSymbolsFromSymbolsStatement{ WriteStatement syncNewSymbolsFromSymbolsStatement{
"UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)", "UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)",
database database

View File

@@ -30,9 +30,10 @@
namespace ClangBackEnd { namespace ClangBackEnd {
SymbolFinder::SymbolFinder(uint line, uint column) SymbolFinder::SymbolFinder(uint line, uint column, FilePathCachingInterface &filePathCache)
: usrFindingAction(line, column), : m_usrFindingAction(line, column),
sourceFileCallbacks(line, column) m_symbolLocationFinderAction(filePathCache),
m_sourceFileCallbacks(line, column, filePathCache)
{ {
} }
@@ -40,39 +41,39 @@ void SymbolFinder::findSymbol()
{ {
clang::tooling::ClangTool tool = createTool(); clang::tooling::ClangTool tool = createTool();
tool.run(clang::tooling::newFrontendActionFactory(&usrFindingAction, &sourceFileCallbacks).get()); tool.run(clang::tooling::newFrontendActionFactory(&m_usrFindingAction, &m_sourceFileCallbacks).get());
if (sourceFileCallbacks.hasSourceLocations()) { if (m_sourceFileCallbacks.hasSourceLocations()) {
sourceLocations_ = sourceFileCallbacks.takeSourceLocations(); m_sourceLocations_ = m_sourceFileCallbacks.takeSourceLocations();
symbolName = sourceFileCallbacks.takeSymbolName(); m_symbolName = m_sourceFileCallbacks.takeSymbolName();
} else { } else {
symbolLocationFinderAction.setUnifiedSymbolResolutions(usrFindingAction.takeUnifiedSymbolResolutions()); m_symbolLocationFinderAction.setUnifiedSymbolResolutions(m_usrFindingAction.takeUnifiedSymbolResolutions());
tool.run(clang::tooling::newFrontendActionFactory(&symbolLocationFinderAction).get()); tool.run(clang::tooling::newFrontendActionFactory(&m_symbolLocationFinderAction).get());
sourceLocations_ = symbolLocationFinderAction.takeSourceLocations(); m_sourceLocations_ = m_symbolLocationFinderAction.takeSourceLocations();
symbolName = usrFindingAction.takeSymbolName(); m_symbolName = m_usrFindingAction.takeSymbolName();
} }
} }
Utils::SmallString SymbolFinder::takeSymbolName() Utils::SmallString SymbolFinder::takeSymbolName()
{ {
return std::move(symbolName); return std::move(m_symbolName);
} }
const std::vector<USRName> &SymbolFinder::unifiedSymbolResolutions() const std::vector<USRName> &SymbolFinder::unifiedSymbolResolutions()
{ {
return symbolLocationFinderAction.unifiedSymbolResolutions(); return m_symbolLocationFinderAction.unifiedSymbolResolutions();
} }
const SourceLocationsContainer &SymbolFinder::sourceLocations() const const SourceLocationsContainer &SymbolFinder::sourceLocations() const
{ {
return sourceLocations_; return m_sourceLocations_;
} }
SourceLocationsContainer SymbolFinder::takeSourceLocations() SourceLocationsContainer SymbolFinder::takeSourceLocations()
{ {
return std::move(sourceLocations_); return std::move(m_sourceLocations_);
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -30,6 +30,7 @@
#include "symbollocationfinderaction.h" #include "symbollocationfinderaction.h"
#include "locationsourcefilecallbacks.h" #include "locationsourcefilecallbacks.h"
#include <filepathcachingfwd.h>
#include <sourcelocationscontainer.h> #include <sourcelocationscontainer.h>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -37,7 +38,7 @@ namespace ClangBackEnd {
class SymbolFinder : public ClangTool class SymbolFinder : public ClangTool
{ {
public: public:
SymbolFinder(uint line, uint column); SymbolFinder(uint line, uint column, FilePathCachingInterface &filePathCache);
void findSymbol(); void findSymbol();
@@ -47,12 +48,11 @@ public:
SourceLocationsContainer takeSourceLocations(); SourceLocationsContainer takeSourceLocations();
private: private:
Utils::SmallString symbolName; Utils::SmallString m_symbolName;
USRFindingAction usrFindingAction; USRFindingAction m_usrFindingAction;
SymbolLocationFinderAction symbolLocationFinderAction; SymbolLocationFinderAction m_symbolLocationFinderAction;
LocationSourceFileCallbacks sourceFileCallbacks; LocationSourceFileCallbacks m_sourceFileCallbacks;
ClangBackEnd::SourceLocationsContainer m_sourceLocations_;
ClangBackEnd::SourceLocationsContainer sourceLocations_;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -33,7 +33,7 @@
#include "symbolstorage.h" #include "symbolstorage.h"
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <stringcache.h> #include <filepathcachingfwd.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
#include <sqlitereadstatement.h> #include <sqlitereadstatement.h>
@@ -48,13 +48,11 @@ public:
Sqlite::ReadStatement, Sqlite::ReadStatement,
Sqlite::WriteStatement>; Sqlite::WriteStatement>;
using Storage = ClangBackEnd::SymbolStorage<StatementFactory>; using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
using DatabaseInitializer = RefactoringDatabaseInitializer<Sqlite::Database>;
SymbolIndexing(FilePathCache<std::mutex> &filePathCache, SymbolIndexing(Sqlite::Database &database,
Utils::PathString &&databaseFilePath) FilePathCachingInterface &filePathCache)
: m_filePathCache(filePathCache), : m_filePathCache(filePathCache),
m_database(std::move(databaseFilePath)), m_statementFactory(database)
m_databaseInitializer(m_database)
{ {
} }
@@ -63,11 +61,6 @@ public:
return m_indexer; return m_indexer;
} }
Sqlite::Database &database()
{
return m_database;
}
void updateProjectParts(V2::ProjectPartContainers &&projectParts, void updateProjectParts(V2::ProjectPartContainers &&projectParts,
V2::FileContainers &&generatedFiles) V2::FileContainers &&generatedFiles)
{ {
@@ -75,11 +68,9 @@ public:
} }
private: private:
FilePathCache<std::mutex> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
Sqlite::Database m_database;
DatabaseInitializer m_databaseInitializer;
SymbolsCollector m_collector{m_filePathCache}; SymbolsCollector m_collector{m_filePathCache};
StatementFactory m_statementFactory{m_database}; StatementFactory m_statementFactory;
Storage m_symbolStorage{m_statementFactory, m_filePathCache}; Storage m_symbolStorage{m_statementFactory, m_filePathCache};
SymbolIndexer m_indexer{m_collector, m_symbolStorage}; SymbolIndexer m_indexer{m_collector, m_symbolStorage};
}; };

View File

@@ -28,6 +28,8 @@
#include "sourcelocationsutils.h" #include "sourcelocationsutils.h"
#include "findlocationsofusrs.h" #include "findlocationsofusrs.h"
#include <filepathcachingfwd.h>
#include <clang/AST/ASTConsumer.h> #include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h> #include <clang/AST/ASTContext.h>
@@ -38,8 +40,10 @@ namespace ClangBackEnd {
class FindingSymbolsASTConsumer : public clang::ASTConsumer class FindingSymbolsASTConsumer : public clang::ASTConsumer
{ {
public: public:
FindingSymbolsASTConsumer(std::vector<USRName> &unifiedSymbolResolutions) FindingSymbolsASTConsumer(std::vector<USRName> &unifiedSymbolResolutions,
: m_unifiedSymbolResolutions(unifiedSymbolResolutions) FilePathCachingInterface &filePathCache)
: m_unifiedSymbolResolutions(unifiedSymbolResolutions),
m_filePathCache(filePathCache)
{ {
} }
@@ -65,7 +69,10 @@ public:
void updateSourceLocations(const std::vector<clang::SourceLocation> &sourceLocations, void updateSourceLocations(const std::vector<clang::SourceLocation> &sourceLocations,
const clang::SourceManager &sourceManager) const clang::SourceManager &sourceManager)
{ {
appendSourceLocationsToSourceLocationsContainer(*m_sourceLocationsContainer, sourceLocations, sourceManager); appendSourceLocationsToSourceLocationsContainer(*m_sourceLocationsContainer,
sourceLocations,
sourceManager,
m_filePathCache);
} }
void setSourceLocations(ClangBackEnd::SourceLocationsContainer *sourceLocations) void setSourceLocations(ClangBackEnd::SourceLocationsContainer *sourceLocations)
@@ -76,11 +83,13 @@ public:
private: private:
ClangBackEnd::SourceLocationsContainer *m_sourceLocationsContainer = nullptr; ClangBackEnd::SourceLocationsContainer *m_sourceLocationsContainer = nullptr;
std::vector<USRName> &m_unifiedSymbolResolutions; std::vector<USRName> &m_unifiedSymbolResolutions;
FilePathCachingInterface &m_filePathCache;
}; };
std::unique_ptr<clang::ASTConsumer> SymbolLocationFinderAction::newASTConsumer() std::unique_ptr<clang::ASTConsumer> SymbolLocationFinderAction::newASTConsumer()
{ {
auto consumer = std::unique_ptr<FindingSymbolsASTConsumer>(new FindingSymbolsASTConsumer(m_unifiedSymbolResolutions_)); auto consumer = std::make_unique<FindingSymbolsASTConsumer>(m_unifiedSymbolResolutions_,
m_filePathCache);
consumer->setSourceLocations(&m_sourceLocations); consumer->setSourceLocations(&m_sourceLocations);

View File

@@ -27,6 +27,7 @@
#include "clangrefactoringbackend_global.h" #include "clangrefactoringbackend_global.h"
#include <filepathcachingfwd.h>
#include <sourcelocationscontainer.h> #include <sourcelocationscontainer.h>
#include <clang/Tooling/Refactoring.h> #include <clang/Tooling/Refactoring.h>
@@ -40,6 +41,9 @@ namespace ClangBackEnd {
class SymbolLocationFinderAction class SymbolLocationFinderAction
{ {
public: public:
SymbolLocationFinderAction(FilePathCachingInterface &filePathCache)
: m_filePathCache(filePathCache)
{}
std::unique_ptr<clang::ASTConsumer> newASTConsumer(); std::unique_ptr<clang::ASTConsumer> newASTConsumer();
@@ -61,6 +65,7 @@ public:
private: private:
ClangBackEnd::SourceLocationsContainer m_sourceLocations; ClangBackEnd::SourceLocationsContainer m_sourceLocations;
std::vector<USRName> m_unifiedSymbolResolutions_; std::vector<USRName> m_unifiedSymbolResolutions_;
FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -27,7 +27,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
SymbolsCollector::SymbolsCollector(FilePathCache<std::mutex> &filePathCache) SymbolsCollector::SymbolsCollector(FilePathCachingInterface &filePathCache)
: m_collectSymbolsAction(filePathCache) : m_collectSymbolsAction(filePathCache)
{ {
} }

View File

@@ -30,14 +30,15 @@
#include "collectsymbolsaction.h" #include "collectsymbolsaction.h"
#include "symbolscollectorinterface.h" #include "symbolscollectorinterface.h"
#include "symbolentry.h" #include "symbolentry.h"
#include "stringcache.h"
#include <filepathcachingfwd.h>
namespace ClangBackEnd { namespace ClangBackEnd {
class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface
{ {
public: public:
SymbolsCollector(FilePathCache<std::mutex> &filePathCache); SymbolsCollector(FilePathCachingInterface &filePathCache);
void addFiles(const Utils::PathStringVector &filePaths, void addFiles(const Utils::PathStringVector &filePaths,
const Utils::SmallStringVector &arguments) override; const Utils::SmallStringVector &arguments) override;

View File

@@ -29,9 +29,7 @@
#include <sqliteexception.h> #include <sqliteexception.h>
#include <sqlitetransaction.h> #include <sqlitetransaction.h>
#include <stringcache.h> #include <filepathcachingfwd.h>
#include <mutex>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -45,7 +43,7 @@ class SymbolStorage : public SymbolStorageInterface
public: public:
SymbolStorage(StatementFactory &statementFactory, SymbolStorage(StatementFactory &statementFactory,
FilePathCache<std::mutex> &filePathCache) FilePathCachingInterface &filePathCache)
: m_statementFactory(statementFactory), : m_statementFactory(statementFactory),
m_filePathCache(filePathCache) m_filePathCache(filePathCache)
{ {
@@ -61,7 +59,6 @@ public:
addNewSymbolsToSymbols(); addNewSymbolsToSymbols();
syncNewSymbolsFromSymbols(); syncNewSymbolsFromSymbols();
syncSymbolsIntoNewLocations(); syncSymbolsIntoNewLocations();
insertNewSources();
deleteAllLocationsFromUpdatedFiles(); deleteAllLocationsFromUpdatedFiles();
insertNewLocationsInLocations(); insertNewLocationsInLocations();
deleteNewSymbolsTable(); deleteNewSymbolsTable();
@@ -89,7 +86,7 @@ public:
statement.write(locationsEntry.symbolId, statement.write(locationsEntry.symbolId,
locationsEntry.line, locationsEntry.line,
locationsEntry.column, locationsEntry.column,
locationsEntry.fileId); locationsEntry.filePathId.fileNameId);
} }
} }
@@ -118,23 +115,6 @@ public:
m_statementFactory.insertNewLocationsInLocationsStatement.execute(); m_statementFactory.insertNewLocationsInLocationsStatement.execute();
} }
FilePathIndices selectNewSourceIds() const
{
ReadStatement &statement = m_statementFactory.selectNewSourceIdsStatement;
return statement.template values<FilePathIndex>(16);
}
void insertNewSources()
{
WriteStatement &statement = m_statementFactory.insertSourcesStatement;
FilePathIndices newSourceIds = selectNewSourceIds();
for (FilePathIndex sourceId : newSourceIds)
statement.write(sourceId, m_filePathCache.string(sourceId));
}
void deleteNewSymbolsTable() void deleteNewSymbolsTable()
{ {
m_statementFactory.deleteNewSymbolsTableStatement.execute(); m_statementFactory.deleteNewSymbolsTableStatement.execute();
@@ -152,7 +132,7 @@ public:
private: private:
StatementFactory &m_statementFactory; StatementFactory &m_statementFactory;
FilePathCache<std::mutex> &m_filePathCache; FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -23,6 +23,8 @@
** **
****************************************************************************/ ****************************************************************************/
#include "googletest.h"
#include "clangiasyncjob.h" #include "clangiasyncjob.h"
#include "dummyclangipcclient.h" #include "dummyclangipcclient.h"
#include "processevents-utilities.h" #include "processevents-utilities.h"
@@ -35,11 +37,6 @@
#include <projects.h> #include <projects.h>
#include <unsavedfiles.h> #include <unsavedfiles.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using namespace ClangBackEnd; using namespace ClangBackEnd;
namespace { namespace {

View File

@@ -23,6 +23,8 @@
** **
****************************************************************************/ ****************************************************************************/
#include "googletest.h"
#include "clangiasyncjob.h" #include "clangiasyncjob.h"
#include "dummyclangipcclient.h" #include "dummyclangipcclient.h"
#include "processevents-utilities.h" #include "processevents-utilities.h"
@@ -37,11 +39,6 @@
#include <projects.h> #include <projects.h>
#include <unsavedfiles.h> #include <unsavedfiles.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using testing::Eq; using testing::Eq;
using namespace ClangBackEnd; using namespace ClangBackEnd;

View File

@@ -26,11 +26,13 @@
#include "googletest.h" #include "googletest.h"
#include "faketimer.h" #include "faketimer.h"
#include "mockfilepathcaching.h"
#include "mockqfilesystemwatcher.h" #include "mockqfilesystemwatcher.h"
#include "mockclangpathwatchernotifier.h" #include "mockclangpathwatchernotifier.h"
#include <clangpathwatcher.h> #include <clangpathwatcher.h>
#include <stringcache.h>
#include <utils/smallstring.h>
namespace { namespace {
@@ -42,34 +44,41 @@ using testing::NiceMock;
using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>; using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>;
using ClangBackEnd::WatcherEntry; using ClangBackEnd::WatcherEntry;
using ClangBackEnd::FilePathIndices; using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathIds;
class ClangPathWatcher : public testing::Test class ClangPathWatcher : public testing::Test
{ {
protected: protected:
ClangBackEnd::FilePathCache<> pathCache; void SetUp();
protected:
NiceMock<MockFilePathCaching> filePathCache;
NiceMock<MockClangPathWatcherNotifier> notifier; NiceMock<MockClangPathWatcherNotifier> notifier;
Watcher watcher{pathCache, &notifier}; Watcher watcher{filePathCache, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher(); NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
Utils::SmallString id1{"id4"}; Utils::SmallString id1{"id4"};
Utils::SmallString id2{"id2"}; Utils::SmallString id2{"id2"};
Utils::SmallString id3{"id3"}; Utils::SmallString id3{"id3"};
Utils::PathString path1{"/path/path1"}; FilePath path1{Utils::PathString{"/path/path1"}};
Utils::PathString path2{"/path/path2"}; FilePath path2{Utils::PathString{"/path/path2"}};
FilePathIndices paths{watcher.pathCache().stringIds({path1, path2})}; QString path1QString = QString(path1.path());
FilePathIndices ids{watcher.idCache().stringIds({id1, id2, id3})}; QString path2QString = QString(path2.path());
WatcherEntry watcherEntry1{ids[0], paths[0]}; FilePathIds pathIds = {{1, 1}, {1, 2}};
WatcherEntry watcherEntry2{ids[1], paths[0]}; std::vector<int> ids{watcher.idCache().stringIds({id1, id2, id3})};
WatcherEntry watcherEntry3{ids[0], paths[1]}; WatcherEntry watcherEntry1{ids[0], pathIds[0]};
WatcherEntry watcherEntry4{ids[1], paths[1]}; WatcherEntry watcherEntry2{ids[1], pathIds[0]};
WatcherEntry watcherEntry5{ids[2], paths[1]}; WatcherEntry watcherEntry3{ids[0], pathIds[1]};
WatcherEntry watcherEntry4{ids[1], pathIds[1]};
WatcherEntry watcherEntry5{ids[2], pathIds[1]};
}; };
TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList) TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList)
{ {
auto convertedList = watcher.convertWatcherEntriesToQStringList({watcherEntry1, watcherEntry3}); auto convertedList = watcher.convertWatcherEntriesToQStringList({watcherEntry1, watcherEntry3});
ASSERT_THAT(convertedList, ElementsAre(QString(path1), QString(path2))); ASSERT_THAT(convertedList, ElementsAre(path1QString, path2QString));
} }
TEST_F(ClangPathWatcher, UniquePaths) TEST_F(ClangPathWatcher, UniquePaths)
@@ -90,51 +99,51 @@ TEST_F(ClangPathWatcher, NotWatchedEntries)
TEST_F(ClangPathWatcher, AddIdPaths) TEST_F(ClangPathWatcher, AddIdPaths)
{ {
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1), QString(path2)})); EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString, path2QString}));
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}}); watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}});
} }
TEST_F(ClangPathWatcher, UpdateIdPathsCallsAddPathInFileWatcher) TEST_F(ClangPathWatcher, UpdateIdPathsCallsAddPathInFileWatcher)
{ {
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}}); watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[0]}}});
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path2)})); EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path2QString}));
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}}); watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}});
} }
TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsCallsRemovePathInFileWatcher) TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsCallsRemovePathInFileWatcher)
{ {
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}}); watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0]}}});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)})); EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString}));
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}}); watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[0]}}});
} }
TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsDoNotCallsRemovePathInFileWatcher) TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsDoNotCallsRemovePathInFileWatcher)
{ {
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}}); watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0]}}});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)})) EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString}))
.Times(0); .Times(0);
watcher.updateIdPaths({{id1, {paths[1]}}, {id2, {paths[0]}}}); watcher.updateIdPaths({{id1, {pathIds[1]}}, {id2, {pathIds[0]}}});
} }
TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPaths) TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPaths)
{ {
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[1]}}}); watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[1]}}});
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[1]}}}); watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[1]}}});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5)); ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5));
} }
TEST_F(ClangPathWatcher, ExtractSortedEntriesFromConvertIdPaths) TEST_F(ClangPathWatcher, ExtractSortedEntriesFromConvertIdPaths)
{ {
auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {paths[0], paths[1]}}, {id1, {paths[0], paths[1]}}}); auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {pathIds[0], pathIds[1]}}, {id1, {pathIds[0], pathIds[1]}}});
ASSERT_THAT(entriesAndIds.first, ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4)); ASSERT_THAT(entriesAndIds.first, ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4));
} }
@@ -190,14 +199,14 @@ TEST_F(ClangPathWatcher, AddEmptyEntries)
TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths) TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths)
{ {
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1), QString(path2)})); EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString, path2QString}));
watcher.addEntries({watcherEntry1, watcherEntry3}); watcher.addEntries({watcherEntry1, watcherEntry3});
} }
TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths) TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths)
{ {
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)})); EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString}));
watcher.addEntries({watcherEntry1, watcherEntry2}); watcher.addEntries({watcherEntry1, watcherEntry2});
} }
@@ -206,7 +215,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithSameIdAndSamePaths)
{ {
watcher.addEntries({watcherEntry1}); watcher.addEntries({watcherEntry1});
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)})) EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString}))
.Times(0); .Times(0);
watcher.addEntries({watcherEntry1}); watcher.addEntries({watcherEntry1});
@@ -216,7 +225,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths)
{ {
watcher.addEntries({watcherEntry1}); watcher.addEntries({watcherEntry1});
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)})) EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString}))
.Times(0); .Times(0);
watcher.addEntries({watcherEntry2}); watcher.addEntries({watcherEntry2});
@@ -253,7 +262,7 @@ TEST_F(ClangPathWatcher, RemovePathForOneId)
{ {
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3}); watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)})); EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString}));
watcher.removeIds({id1}); watcher.removeIds({id1});
} }
@@ -262,7 +271,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
{ {
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path1), QString(path2)})); EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1QString, path2QString}));
watcher.removeIds({id1, id2, id3}); watcher.removeIds({id1, id2, id3});
} }
@@ -271,7 +280,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
{ {
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path1)})); EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1QString}));
watcher.removeIds({id1, id2}); watcher.removeIds({id1, id2});
} }
@@ -298,9 +307,9 @@ TEST_F(ClangPathWatcher, EmptyVectorNotifyFileChange)
{ {
watcher.addEntries({watcherEntry3}); watcher.addEntries({watcherEntry3});
EXPECT_CALL(notifier, pathsWithIdsChanged(IsEmpty())).Times(1); EXPECT_CALL(notifier, pathsWithIdsChanged(IsEmpty()));
mockQFileSytemWatcher.fileChanged(path1.toQString()); mockQFileSytemWatcher.fileChanged(path1QString);
} }
TEST_F(ClangPathWatcher, NotifyFileChange) TEST_F(ClangPathWatcher, NotifyFileChange)
@@ -309,7 +318,7 @@ TEST_F(ClangPathWatcher, NotifyFileChange)
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id1))); EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id1)));
mockQFileSytemWatcher.fileChanged(path1.toQString()); mockQFileSytemWatcher.fileChanged(path1QString);
} }
TEST_F(ClangPathWatcher, TwoNotifyFileChanges) TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
@@ -318,8 +327,19 @@ TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id3, id1))); EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id3, id1)));
mockQFileSytemWatcher.fileChanged(path2.toQString()); mockQFileSytemWatcher.fileChanged(path2QString);
mockQFileSytemWatcher.fileChanged(path1.toQString()); mockQFileSytemWatcher.fileChanged(path1QString);
} }
void ClangPathWatcher::SetUp()
{
ON_CALL(filePathCache, filePathId(Eq(path1)))
.WillByDefault(Return(pathIds[0]));
ON_CALL(filePathCache, filePathId(Eq(path2)))
.WillByDefault(Return(pathIds[1]));
ON_CALL(filePathCache, filePath(pathIds[0]))
.WillByDefault(Return(path1));
ON_CALL(filePathCache, filePath(Eq(pathIds[1])))
.WillByDefault(Return(path2));
}
} }

View File

@@ -29,11 +29,19 @@
#include "filesystem-utilities.h" #include "filesystem-utilities.h"
#include <clangquery.h> #include <clangquery.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <filepathcaching.h>
#include <QDir>
#include <mutex> #include <mutex>
using ClangBackEnd::ClangQuery; using ClangBackEnd::ClangQuery;
using ClangBackEnd::FilePathCache; using ClangBackEnd::FilePathCaching;
using ClangBackEnd::RefactoringDatabaseInitializer;
using testing::AllOf; using testing::AllOf;
using testing::Contains; using testing::Contains;
@@ -48,7 +56,9 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
FilePathCache<std::mutex> filePathCache; Sqlite::Database database{QDir::tempPath() + "/symbol.db"};
RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
FilePathCaching filePathCache{database};
::ClangQuery simpleFunctionQuery{filePathCache}; ::ClangQuery simpleFunctionQuery{filePathCache};
::ClangQuery simpleClassQuery{filePathCache}; ::ClangQuery simpleClassQuery{filePathCache};
}; };

View File

@@ -66,7 +66,7 @@ TEST_F(ClangQueryExampleHighlightMarker, NoCallForNotSourceRanges)
TEST_F(ClangQueryExampleHighlightMarker, SingleLineSourceRange) TEST_F(ClangQueryExampleHighlightMarker, SingleLineSourceRange)
{ {
SourceRanges sourceRanges{{1, 1, 3, 3, 1, 10, 10, "function"}}; SourceRanges sourceRanges{{{1, 1}, 1, 3, 3, 1, 10, 10, "function"}};
Marker marker(std::move(sourceRanges), highlighter, textFormats); Marker marker(std::move(sourceRanges), highlighter, textFormats);
EXPECT_CALL(highlighter, setFormat(2, 7, textFormats[0])); EXPECT_CALL(highlighter, setFormat(2, 7, textFormats[0]));
@@ -76,7 +76,7 @@ TEST_F(ClangQueryExampleHighlightMarker, SingleLineSourceRange)
TEST_F(ClangQueryExampleHighlightMarker, OtherSingleLineSourceRange) TEST_F(ClangQueryExampleHighlightMarker, OtherSingleLineSourceRange)
{ {
SourceRanges sourceRanges{{1, 2, 5, 5, 2, 11, 11, "function"}}; SourceRanges sourceRanges{{{1, 1}, 2, 5, 5, 2, 11, 11, "function"}};
Marker marker(std::move(sourceRanges), highlighter, textFormats); Marker marker(std::move(sourceRanges), highlighter, textFormats);
marker.highlightBlock(1, "foo"); marker.highlightBlock(1, "foo");
@@ -88,9 +88,9 @@ TEST_F(ClangQueryExampleHighlightMarker, OtherSingleLineSourceRange)
TEST_F(ClangQueryExampleHighlightMarker, CascadedSingleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, CascadedSingleLineSourceRanges)
{ {
InSequence sequence; InSequence sequence;
SourceRanges sourceRanges{{1, 1, 2, 2, 1, 15, 15, "void function"}, SourceRanges sourceRanges{{{1, 1}, 1, 2, 2, 1, 15, 15, "void function"},
{1, 1, 2, 2, 1, 6, 6, "void"}, {{1, 1}, 1, 2, 2, 1, 6, 6, "void"},
{1, 1, 7, 7, 1, 15, 15, "function"}}; {{1, 1}, 1, 7, 7, 1, 15, 15, "function"}};
Marker marker(std::move(sourceRanges), highlighter, textFormats); Marker marker(std::move(sourceRanges), highlighter, textFormats);
EXPECT_CALL(highlighter, setFormat(1, 13, textFormats[0])); EXPECT_CALL(highlighter, setFormat(1, 13, textFormats[0]));
@@ -103,7 +103,7 @@ TEST_F(ClangQueryExampleHighlightMarker, CascadedSingleLineSourceRanges)
TEST_F(ClangQueryExampleHighlightMarker, DualLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, DualLineSourceRanges)
{ {
InSequence sequence; InSequence sequence;
SourceRanges sourceRanges{{1, 1, 2, 2, 2, 4, 20, "void f()\n {}"}}; SourceRanges sourceRanges{{{1, 1}, 1, 2, 2, 2, 4, 20, "void f()\n {}"}};
Marker marker(std::move(sourceRanges), highlighter, textFormats); Marker marker(std::move(sourceRanges), highlighter, textFormats);
EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0])); EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0]));
@@ -116,7 +116,7 @@ TEST_F(ClangQueryExampleHighlightMarker, DualLineSourceRanges)
TEST_F(ClangQueryExampleHighlightMarker, MultipleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, MultipleLineSourceRanges)
{ {
InSequence sequence; InSequence sequence;
SourceRanges sourceRanges{{1, 1, 2, 2, 3, 3, 20, "void f()\n {\n }"}}; SourceRanges sourceRanges{{{1, 1}, 1, 2, 2, 3, 3, 20, "void f()\n {\n }"}};
Marker marker(std::move(sourceRanges), highlighter, textFormats); Marker marker(std::move(sourceRanges), highlighter, textFormats);
EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0])); EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0]));
@@ -131,9 +131,9 @@ TEST_F(ClangQueryExampleHighlightMarker, MultipleLineSourceRanges)
TEST_F(ClangQueryExampleHighlightMarker, MoreMultipleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, MoreMultipleLineSourceRanges)
{ {
InSequence sequence; InSequence sequence;
SourceRanges sourceRanges{{1, 1, 1, 0, 4, 2, 0, ""}, SourceRanges sourceRanges{{{1, 1}, 1, 1, 0, 4, 2, 0, ""},
{1, 2, 2, 0, 2, 7, 0, ""}, {{1, 1}, 2, 2, 0, 2, 7, 0, ""},
{1, 3, 2, 0, 3, 7, 0, ""}}; {{1, 1}, 3, 2, 0, 3, 7, 0, ""}};
Marker marker(std::move(sourceRanges), highlighter, textFormats); Marker marker(std::move(sourceRanges), highlighter, textFormats);
EXPECT_CALL(highlighter, setFormat(0, 10, textFormats[0])); EXPECT_CALL(highlighter, setFormat(0, 10, textFormats[0]));
@@ -152,9 +152,9 @@ TEST_F(ClangQueryExampleHighlightMarker, MoreMultipleLineSourceRanges)
TEST_F(ClangQueryExampleHighlightMarker, CascadedMultipleLineSourceRanges) TEST_F(ClangQueryExampleHighlightMarker, CascadedMultipleLineSourceRanges)
{ {
InSequence sequence; InSequence sequence;
SourceRanges sourceRanges{{1, 1, 1, 0, 4, 2, 0, ""}, SourceRanges sourceRanges{{{1, 1}, 1, 1, 0, 4, 2, 0, ""},
{1, 2, 2, 0, 3, 4, 0, ""}, {{1, 1}, 2, 2, 0, 3, 4, 0, ""},
{1, 2, 11, 0, 2, 16, 0, ""}}; {{1, 1}, 2, 11, 0, 2, 16, 0, ""}};
Marker marker(std::move(sourceRanges), highlighter, textFormats); Marker marker(std::move(sourceRanges), highlighter, textFormats);
EXPECT_CALL(highlighter, setFormat(0, 9, textFormats[0])); EXPECT_CALL(highlighter, setFormat(0, 9, textFormats[0]));
@@ -173,7 +173,7 @@ TEST_F(ClangQueryExampleHighlightMarker, CascadedMultipleLineSourceRanges)
TEST_F(ClangQueryExampleHighlightMarker, FormatSingle) TEST_F(ClangQueryExampleHighlightMarker, FormatSingle)
{ {
SourceRange sourceRange{1, 1, 3, 3, 1, 10, 10}; SourceRange sourceRange{{1, 1}, 1, 3, 3, 1, 10, 10};
EXPECT_CALL(highlighter, setFormat(2, 7, textFormats[0])); EXPECT_CALL(highlighter, setFormat(2, 7, textFormats[0]));
@@ -182,7 +182,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatSingle)
TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleStart) TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleStart)
{ {
SourceRange sourceRange{1, 1, 3, 3, 2, 9, 20}; SourceRange sourceRange{{1, 1}, 1, 3, 3, 2, 9, 20};
EXPECT_CALL(highlighter, setFormat(2, 8, textFormats[0])); EXPECT_CALL(highlighter, setFormat(2, 8, textFormats[0]));
@@ -191,7 +191,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleStart)
TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleEnd) TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleEnd)
{ {
SourceRange sourceRange{1, 1, 3, 3, 2, 8, 20}; SourceRange sourceRange{{1, 1}, 1, 3, 3, 2, 8, 20};
EXPECT_CALL(highlighter, setFormat(0, 7, textFormats[1])); EXPECT_CALL(highlighter, setFormat(0, 7, textFormats[1]));
@@ -200,7 +200,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleEnd)
TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleMiddle) TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleMiddle)
{ {
SourceRange sourceRange{1, 1, 3, 3, 3, 8, 20}; SourceRange sourceRange{{1, 1}, 1, 3, 3, 3, 8, 20};
EXPECT_CALL(highlighter, setFormat(0, 10, textFormats[2])); EXPECT_CALL(highlighter, setFormat(0, 10, textFormats[2]));

View File

@@ -30,9 +30,15 @@
#include "sourcerangecontainer-matcher.h" #include "sourcerangecontainer-matcher.h"
#include <filecontainerv2.h> #include <filecontainerv2.h>
#include <filepathcaching.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <clangquerygatherer.h> #include <clangquerygatherer.h>
#include <QDir>
namespace { namespace {
using testing::AllOf; using testing::AllOf;
@@ -75,7 +81,9 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
ClangBackEnd::FilePathCache<std::mutex> filePathCache; Sqlite::Database database{QDir::tempPath() + "/symbol.db"};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"}; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(), sourceContent.clone(),

View File

@@ -74,10 +74,10 @@ TEST_F(ClangQueryHighlightMarker, NoCallForNoMessagesAndContexts)
TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextsForASingleLine) TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextsForASingleLine)
{ {
InSequence sequence; InSequence sequence;
Messages messages{{{1, 1, 5, 0, 1, 10, 0}, ErrorType::RegistryMatcherNotFound, {}}, Messages messages{{{{0, 1}, 1, 5, 0, 1, 10, 0}, ErrorType::RegistryMatcherNotFound, {}},
{{1, 1, 30, 0, 1, 40, 0}, ErrorType::RegistryMatcherNotFound, {}}}; {{{0, 1}, 1, 30, 0, 1, 40, 0}, ErrorType::RegistryMatcherNotFound, {}}};
Contexts contexts{{{1, 1, 2, 0, 1, 15, 0}, ContextType::MatcherArg, {}}, Contexts contexts{{{{0, 1}, 1, 2, 0, 1, 15, 0}, ContextType::MatcherArg, {}},
{{1, 1, 20, 0, 1, 50, 0}, ContextType::MatcherArg, {}}}; {{{0, 1}, 1, 20, 0, 1, 50, 0}, ContextType::MatcherArg, {}}};
marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
EXPECT_CALL(highlighter, setFormat(1, 13, contextTextFormat)); EXPECT_CALL(highlighter, setFormat(1, 13, contextTextFormat));
@@ -91,7 +91,7 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextsForASingleLine)
TEST_F(ClangQueryHighlightMarker, CallForMessagesForAMultiLine) TEST_F(ClangQueryHighlightMarker, CallForMessagesForAMultiLine)
{ {
InSequence sequence; InSequence sequence;
Messages messages{{{1, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}}; Messages messages{{{{0, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}};
Contexts contexts; Contexts contexts;
marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
@@ -107,8 +107,8 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesForAMultiLine)
TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextForAMultiLine) TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextForAMultiLine)
{ {
InSequence sequence; InSequence sequence;
Messages messages{{{1, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}}; Messages messages{{{{1, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}};
Contexts contexts{{{1, 1, 2, 0, 3, 4, 0}, ContextType::MatcherArg, {}}}; Contexts contexts{{{{1, 1}, 1, 2, 0, 3, 4, 0}, ContextType::MatcherArg, {}}};
marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
EXPECT_CALL(highlighter, setFormat(1, 11, contextTextFormat)); EXPECT_CALL(highlighter, setFormat(1, 11, contextTextFormat));
@@ -136,7 +136,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesIfEmpty)
TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition) TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition)
{ {
Messages messages{{{1, 1, 5, 0, 3, 3, 0}, Messages messages{{{{0, 1}, 1, 5, 0, 3, 3, 0},
ErrorType::RegistryMatcherNotFound, ErrorType::RegistryMatcherNotFound,
{"foo"}}}; {"foo"}}};
Contexts contexts; Contexts contexts;
@@ -149,7 +149,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition)
TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition) TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition)
{ {
Messages messages{{{1, 1, 5, 0, 3, 3, 0}, Messages messages{{{{0, 1}, 1, 5, 0, 3, 3, 0},
ErrorType::RegistryMatcherNotFound, ErrorType::RegistryMatcherNotFound,
{"foo"}}}; {"foo"}}};
Contexts contexts; Contexts contexts;
@@ -162,7 +162,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition)
TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition) TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition)
{ {
Message message{{1, 1, 5, 0, 3, 3, 0}, Message message{{{0, 1}, 1, 5, 0, 3, 3, 0},
ErrorType::RegistryMatcherNotFound, ErrorType::RegistryMatcherNotFound,
{"foo"}}; {"foo"}};
Messages messages{message.clone()}; Messages messages{message.clone()};
@@ -176,7 +176,7 @@ TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition)
TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition) TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition)
{ {
Message message{{1, 1, 5, 0, 3, 3, 0}, Message message{{{0, 1}, 1, 5, 0, 3, 3, 0},
ErrorType::RegistryMatcherNotFound, ErrorType::RegistryMatcherNotFound,
{"foo"}}; {"foo"}};
Messages messages{message.clone()}; Messages messages{message.clone()};
@@ -190,7 +190,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition)
TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine) TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isAfterStartColumn = marker.isInsideRange(sourceRange, 1, 6); bool isAfterStartColumn = marker.isInsideRange(sourceRange, 1, 6);
@@ -199,7 +199,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine)
TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn) TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 4); bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 4);
@@ -208,7 +208,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn)
TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn) TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 5); bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 5);
@@ -217,7 +217,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn)
TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn) TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 6); bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 6);
@@ -226,7 +226,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn)
TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 4, 1); bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 4, 1);
@@ -235,7 +235,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine)
TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 4); bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 4);
@@ -244,7 +244,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn)
TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 3); bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 3);
@@ -253,7 +253,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn)
TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn) TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 2); bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 2);
@@ -262,7 +262,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn)
TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine) TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine)
{ {
SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 3, 3, 0};
bool isInBetween = marker.isInsideRange(sourceRange, 1, 6); bool isInBetween = marker.isInsideRange(sourceRange, 1, 6);
@@ -271,7 +271,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine)
TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine) TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine)
{ {
SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 4, 3, 0};
bool isInBetween = marker.isInsideRange(sourceRange, 5, 1); bool isInBetween = marker.isInsideRange(sourceRange, 5, 1);
@@ -280,7 +280,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine)
TEST_F(ClangQueryHighlightMarker, InBetweenLine) TEST_F(ClangQueryHighlightMarker, InBetweenLine)
{ {
SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 4, 3, 0};
bool isInBetween = marker.isInsideRange(sourceRange, 3, 1); bool isInBetween = marker.isInsideRange(sourceRange, 3, 1);
@@ -289,7 +289,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLine)
TEST_F(ClangQueryHighlightMarker, SingleLineBefore) TEST_F(ClangQueryHighlightMarker, SingleLineBefore)
{ {
SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 2, 10, 0};
bool isInRange = marker.isInsideRange(sourceRange, 2, 4); bool isInRange = marker.isInsideRange(sourceRange, 2, 4);
@@ -298,7 +298,7 @@ TEST_F(ClangQueryHighlightMarker, SingleLineBefore)
TEST_F(ClangQueryHighlightMarker, SingleLineAfter) TEST_F(ClangQueryHighlightMarker, SingleLineAfter)
{ {
SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 2, 10, 0};
bool isInRange = marker.isInsideRange(sourceRange, 2, 11); bool isInRange = marker.isInsideRange(sourceRange, 2, 11);
@@ -307,7 +307,7 @@ TEST_F(ClangQueryHighlightMarker, SingleLineAfter)
TEST_F(ClangQueryHighlightMarker, SingleLineInRange) TEST_F(ClangQueryHighlightMarker, SingleLineInRange)
{ {
SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; SourceRange sourceRange{{0, 1}, 2, 5, 0, 2, 10, 0};
bool isInRange = marker.isInsideRange(sourceRange, 2, 6); bool isInRange = marker.isInsideRange(sourceRange, 2, 6);
@@ -328,7 +328,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsIfEmpty)
TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition) TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition)
{ {
Messages messages; Messages messages;
Contexts contexts{{{1, 1, 5, 0, 3, 3, 0}, Contexts contexts{{{{0, 1}, 1, 5, 0, 3, 3, 0},
ContextType::MatcherArg, ContextType::MatcherArg,
{"foo"}}}; {"foo"}}};
marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
@@ -341,7 +341,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition)
TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition) TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition)
{ {
Messages messages; Messages messages;
Contexts contexts{{{1, 1, 5, 0, 3, 3, 0}, Contexts contexts{{{{0, 1}, 1, 5, 0, 3, 3, 0},
ContextType::MatcherArg, ContextType::MatcherArg,
{"foo"}}}; {"foo"}}};
marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
@@ -353,7 +353,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition)
TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition) TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition)
{ {
Context context{{1, 1, 5, 0, 3, 3, 0}, Context context{{{0, 1}, 1, 5, 0, 3, 3, 0},
ContextType::MatcherArg, ContextType::MatcherArg,
{"foo"}}; {"foo"}};
Messages messages; Messages messages;
@@ -367,7 +367,7 @@ TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition)
TEST_F(ClangQueryHighlightMarker, NoContextsForOutsidePosition) TEST_F(ClangQueryHighlightMarker, NoContextsForOutsidePosition)
{ {
Context context{{1, 1, 5, 0, 3, 3, 0}, Context context{{{0, 1}, 1, 5, 0, 3, 3, 0},
ContextType::MatcherArg, ContextType::MatcherArg,
{"foo"}}; {"foo"}};
Messages messages; Messages messages;

View File

@@ -23,6 +23,8 @@
** **
****************************************************************************/ ****************************************************************************/
#include "googletest.h"
#include "dummyclangipcclient.h" #include "dummyclangipcclient.h"
#include "processevents-utilities.h" #include "processevents-utilities.h"
@@ -39,11 +41,6 @@
#include <memory> #include <memory>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using namespace ClangBackEnd; using namespace ClangBackEnd;
using testing::Eq; using testing::Eq;

View File

@@ -23,6 +23,8 @@
** **
****************************************************************************/ ****************************************************************************/
#include "googletest.h"
#include <clangtranslationunit.h> #include <clangtranslationunit.h>
#include <clangtranslationunitupdater.h> #include <clangtranslationunitupdater.h>
#include <diagnosticcontainer.h> #include <diagnosticcontainer.h>
@@ -30,11 +32,6 @@
#include <clang-c/Index.h> #include <clang-c/Index.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using ClangBackEnd::DiagnosticContainer; using ClangBackEnd::DiagnosticContainer;
using ClangBackEnd::TranslationUnit; using ClangBackEnd::TranslationUnit;
using ClangBackEnd::TranslationUnitUpdateInput; using ClangBackEnd::TranslationUnitUpdateInput;

View File

@@ -23,6 +23,8 @@
** **
****************************************************************************/ ****************************************************************************/
#include "googletest.h"
#include <clangbackend_global.h> #include <clangbackend_global.h>
#include <clangexceptions.h> #include <clangexceptions.h>
#include <clangtranslationunit.h> #include <clangtranslationunit.h>
@@ -31,11 +33,6 @@
#include <clang-c/Index.h> #include <clang-c/Index.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using ClangBackEnd::Clock; using ClangBackEnd::Clock;
using ClangBackEnd::TranslationUnit; using ClangBackEnd::TranslationUnit;
using ClangBackEnd::TranslationUnits; using ClangBackEnd::TranslationUnits;

View File

@@ -0,0 +1,286 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mockfilepathstorage.h"
#include <filepathcache.h>
namespace {
using ClangBackEnd::FilePathId;
using FPCB = ClangBackEnd::FilePathCacheBase;
using Cache = ClangBackEnd::FilePathCache<NiceMock<MockFilePathStorage>>;
using ClangBackEnd::FilePathId;
class FilePathCache : public testing::Test
{
protected:
void SetUp();
protected:
NiceMock<MockFilePathStorage> mockStorage;
Cache cache{mockStorage};
};
TEST_F(FilePathCache, FilePathSlashForEmptyPath)
{
auto slashIndex = FPCB::lastSlashIndex("");
ASSERT_THAT(slashIndex, -1);
}
TEST_F(FilePathCache, FilePathSlashForSingleSlash)
{
auto slashIndex = FPCB::lastSlashIndex("/");
ASSERT_THAT(slashIndex, 0);
}
TEST_F(FilePathCache, FilePathSlashForFileInRoot)
{
auto slashIndex = FPCB::lastSlashIndex("/file.h");
ASSERT_THAT(slashIndex, 0);
}
TEST_F(FilePathCache, FilePathSlashForSomeLongerPath)
{
auto slashIndex = FPCB::lastSlashIndex("/path/to/some/file.h");
ASSERT_THAT(slashIndex, 13);
}
TEST_F(FilePathCache, FilePathSlashForFileNameOnly)
{
auto slashIndex = FPCB::lastSlashIndex("file.h");
ASSERT_THAT(slashIndex, -1);
}
TEST_F(FilePathCache, DirectoryPathForEmptyPath)
{
auto slashIndex = FPCB::lastSlashIndex("");
auto directoryPath = FPCB::directoryPath("", slashIndex);
ASSERT_THAT(directoryPath, "");
}
TEST_F(FilePathCache, DirectoryPathForSingleSlashPath)
{
Utils::SmallStringView singleSlashPath{"/"};
auto slashIndex = FPCB::lastSlashIndex(singleSlashPath);
auto directoryPath = FPCB::directoryPath(singleSlashPath, slashIndex);
ASSERT_THAT(directoryPath, "");
}
TEST_F(FilePathCache, DirectoryPathForLongerPath)
{
Utils::SmallStringView longerPath{"/path/to/some/file.h"};
auto slashIndex = FPCB::lastSlashIndex(longerPath);
auto directoryPath = FPCB::directoryPath(longerPath, slashIndex);
ASSERT_THAT(directoryPath, "/path/to/some");
}
TEST_F(FilePathCache, DirectoryPathForFileNameOnly)
{
Utils::SmallStringView longerPath{"file.h"};
auto slashIndex = FPCB::lastSlashIndex(longerPath);
auto directoryPath = FPCB::directoryPath(longerPath, slashIndex);
ASSERT_THAT(directoryPath, IsEmpty());
}
TEST_F(FilePathCache, FileNameForEmptyPath)
{
auto slashIndex = FPCB::lastSlashIndex("");
auto fileName = FPCB::fileName("", slashIndex);
ASSERT_THAT(fileName, "");
}
TEST_F(FilePathCache, FileNameForSingleSlashPath)
{
Utils::SmallStringView singleSlashPath{"/"};
auto slashIndex = FPCB::lastSlashIndex(singleSlashPath);
auto fileName = FPCB::fileName(singleSlashPath, slashIndex);
ASSERT_THAT(fileName, "");
}
TEST_F(FilePathCache, FileNameForLongerPath)
{
Utils::SmallStringView longerPath{"/path/to/some/file.h"};
auto slashIndex = FPCB::lastSlashIndex(longerPath);
auto fileName = FPCB::fileName(longerPath, slashIndex);
ASSERT_THAT(fileName, "file.h");
}
TEST_F(FilePathCache, FileNameForFileNameOnly)
{
Utils::SmallStringView longerPath{"file.h"};
auto slashIndex = FPCB::lastSlashIndex(longerPath);
auto fileName = FPCB::fileName(longerPath, slashIndex);
ASSERT_THAT(fileName, "file.h");
}
TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId)
{
EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to")));
cache.filePathId("/path/to/file.cpp");
}
TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCalls)
{
EXPECT_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp")));
cache.filePathId("/path/to/file.cpp");
}
TEST_F(FilePathCache, DirectoryIdOfFilePathIdWithOutAnyEntry)
{
auto filePathId = cache.filePathId("/path/to/file.cpp");
ASSERT_THAT(filePathId.directoryId, 5);
}
TEST_F(FilePathCache, FileNameIdOfFilePathIdWithOutAnyEntry)
{
auto filePathId = cache.filePathId("/path/to/file.cpp");
ASSERT_THAT(filePathId.fileNameId, 42);
}
TEST_F(FilePathCache, IfEntryExistsDontCallInStrorage)
{
cache.filePathId("/path/to/file.cpp");
EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))).Times(0);
EXPECT_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp"))).Times(0);
cache.filePathId("/path/to/file.cpp");
}
TEST_F(FilePathCache, IfDirectoryEntryExistsDontCallFetchDirectoryIdButStillCallFetchSourceId)
{
cache.filePathId("/path/to/file2.cpp");
EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))).Times(0);
EXPECT_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp")));
cache.filePathId("/path/to/file.cpp");
}
TEST_F(FilePathCache, GetFileNameIdWithCachedValue)
{
cache.filePathId("/path/to/file.cpp");
auto filePathId = cache.filePathId("/path/to/file.cpp");
ASSERT_THAT(filePathId.fileNameId, 42);
}
TEST_F(FilePathCache, GetFileNameIdWithDirectoryIdCached)
{
cache.filePathId("/path/to/file.cpp");
auto filePathId = cache.filePathId("/path/to/file2.cpp");
ASSERT_THAT(filePathId.fileNameId, 63);
}
TEST_F(FilePathCache, GetDirectyIdWithCachedValue)
{
cache.filePathId("/path/to/file.cpp");
auto filePathId = cache.filePathId("/path/to/file2.cpp");
ASSERT_THAT(filePathId.directoryId, 5);
}
TEST_F(FilePathCache, GetDirectyIdWithDirectoryIdCached)
{
cache.filePathId("/path/to/file.cpp");
auto filePathId = cache.filePathId("/path/to/file2.cpp");
ASSERT_THAT(filePathId.directoryId, 5);
}
TEST_F(FilePathCache, ThrowForGettingAFilePathWithAnInvalidId)
{
FilePathId filePathId;
ASSERT_THROW(cache.filePath(filePathId), ClangBackEnd::NoFilePathForInvalidFilePathId);
}
TEST_F(FilePathCache, GetAFilePath)
{
FilePathId filePathId = cache.filePathId("/path/to/file.cpp");
auto filePath = cache.filePath(filePathId);
ASSERT_THAT(filePath, Eq("/path/to/file.cpp"));
}
TEST_F(FilePathCache, GetAFilePathWithCachedFilePathId)
{
FilePathId filePathId{5, 42};
auto filePath = cache.filePath(filePathId);
ASSERT_THAT(filePath, Eq("/path/to/file.cpp"));
}
void FilePathCache::SetUp()
{
ON_CALL(mockStorage, fetchDirectoryId(Eq("/path/to")))
.WillByDefault(Return(5));
ON_CALL(mockStorage, fetchSourceId(5, Eq("file.cpp")))
.WillByDefault(Return(42));
ON_CALL(mockStorage, fetchSourceId(5, Eq("file2.cpp")))
.WillByDefault(Return(63));
ON_CALL(mockStorage, fetchDirectoryPath(5))
.WillByDefault(Return(Utils::PathString("/path/to")));
ON_CALL(mockStorage, fetchSourceName(42))
.WillByDefault(Return(Utils::SmallString("file.cpp")));
}
}

View File

@@ -0,0 +1,409 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mockmutex.h"
#include "mocksqlitedatabase.h"
#include "mocksqlitereadstatement.h"
#include "mocksqlitewritestatement.h"
#include <filepathstorage.h>
#include <filepathstoragesqlitestatementfactory.h>
namespace {
using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>,
MockSqliteReadStatement,
MockSqliteWriteStatement>;
using Storage = ClangBackEnd::FilePathStorage<StatementFactory>;
using ClangBackEnd::Sources::Directory;
using ClangBackEnd::Sources::Source;
class FilePathStorage : public testing::Test
{
protected:
void SetUp();
protected:
NiceMock<MockMutex> mockMutex;
NiceMock<MockSqliteDatabase> mockDatabase{mockMutex};
StatementFactory factory{mockDatabase};
MockSqliteReadStatement &selectDirectoryIdFromDirectoriesByDirectoryPath = factory.selectDirectoryIdFromDirectoriesByDirectoryPath;
MockSqliteReadStatement &selectSourceIdFromSourcesByDirectoryIdAndSourceName = factory.selectSourceIdFromSourcesByDirectoryIdAndSourceName;
MockSqliteReadStatement &selectDirectoryPathFromDirectoriesByDirectoryId = factory.selectDirectoryPathFromDirectoriesByDirectoryId;
MockSqliteReadStatement &selectSourceNameFromSourcesBySourceId = factory.selectSourceNameFromSourcesBySourceId;
MockSqliteReadStatement &selectAllDirectories = factory.selectAllDirectories;
MockSqliteWriteStatement &insertIntoDirectories = factory.insertIntoDirectories;
MockSqliteWriteStatement &insertIntoSources = factory.insertIntoSources;
MockSqliteReadStatement &selectAllSources = factory.selectAllSources;
Storage storage{factory};
};
TEST_F(FilePathStorage, ReadDirectoryIdForNotContainedPath)
{
auto directoryId = storage.readDirectoryId("/some/not/known/path");
ASSERT_FALSE(directoryId);
}
TEST_F(FilePathStorage, ReadSourceIdForNotContainedPathAndDirectoryId)
{
auto sourceId = storage.readSourceId(23, "/some/not/known/path");
ASSERT_FALSE(sourceId);
}
TEST_F(FilePathStorage, ReadDirectoryIdForEmptyPath)
{
auto directoryId = storage.readDirectoryId("");
ASSERT_THAT(directoryId.value(), 0);
}
TEST_F(FilePathStorage, ReadSourceIdForEmptyNameAndZeroDirectoryId)
{
auto sourceId = storage.readSourceId(0, "");
ASSERT_THAT(sourceId.value(), 0);
}
TEST_F(FilePathStorage, ReadDirectoryIdForPath)
{
auto directoryId = storage.readDirectoryId("/path/to");
ASSERT_THAT(directoryId.value(), 5);
}
TEST_F(FilePathStorage, ReadSourceIdForPathAndDirectoryId)
{
auto sourceId = storage.readSourceId(5, "file.h");
ASSERT_THAT(sourceId.value(), 42);
}
TEST_F(FilePathStorage, FetchDirectoryIdForEmptyPath)
{
auto directoryId = storage.fetchDirectoryId("");
ASSERT_THAT(directoryId, 0);
}
TEST_F(FilePathStorage, FetchSourceIdForEmptyNameAndZeroDirectoryId)
{
auto sourceId = storage.fetchSourceId(0, "");
ASSERT_THAT(sourceId, 0);
}
TEST_F(FilePathStorage, FetchDirectoryIdForPath)
{
auto directoryId = storage.fetchDirectoryId("/path/to");
ASSERT_THAT(directoryId, 5);
}
TEST_F(FilePathStorage, FetchSourceIdForPathAndDirectoryId)
{
auto sourceId = storage.fetchSourceId(5, "file.h");
ASSERT_THAT(sourceId, 42);
}
TEST_F(FilePathStorage, CallWriteForWriteDirectory)
{
EXPECT_CALL(insertIntoDirectories, write(Eq("/some/not/known/path")));
storage.writeDirectoryId("/some/not/known/path");
}
TEST_F(FilePathStorage, CallWriteForWriteSource)
{
EXPECT_CALL(insertIntoSources, write(5, Eq("unknownfile.h")));
storage.writeSourceId(5, "unknownfile.h");
}
TEST_F(FilePathStorage, GetTheDirectoryIdBackAfterWritingANewEntryInDirectories)
{
auto directoryId = storage.writeDirectoryId("/some/not/known/path");
ASSERT_THAT(directoryId, 12);
}
TEST_F(FilePathStorage, GetTheSourceIdBackAfterWritingANewEntryInSources)
{
auto sourceId = storage.writeSourceId(5, "unknownfile.h");
ASSERT_THAT(sourceId, 12);
}
TEST_F(FilePathStorage, GetTheDirectoryIdBackAfterFetchingANewEntryFromDirectories)
{
auto directoryId = storage.fetchDirectoryId("/some/not/known/path");
ASSERT_THAT(directoryId, 12);
}
TEST_F(FilePathStorage, GetTheSourceIdBackAfterFetchingANewEntryFromSources)
{
auto sourceId = storage.fetchSourceId(5, "unknownfile.h");
ASSERT_THAT(sourceId, 12);
}
TEST_F(FilePathStorage, CallSelectForFetchingDirectoryIdForKnownPath)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath,
valueReturnInt32(Eq("/path/to")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchDirectoryId("/path/to");
}
TEST_F(FilePathStorage, CallSelectForFetchingSourceIdForKnownPath)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(5, Eq("file.h")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchSourceId(5, "file.h");
}
TEST_F(FilePathStorage, CallNotWriteForFetchingDirectoryIdForKnownPath)
{
EXPECT_CALL(insertIntoDirectories, write(_)).Times(0);
storage.fetchDirectoryId("/path/to");
}
TEST_F(FilePathStorage, CallNotWriteForFetchingSoureIdForKnownEntry)
{
EXPECT_CALL(insertIntoSources, write(_, _)).Times(0);
storage.fetchSourceId(5, "file.h");
}
TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdForUnknownPath)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath,
valueReturnInt32(Eq("/some/not/known/path")));
EXPECT_CALL(insertIntoDirectories, write(Eq("/some/not/known/path")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchDirectoryId("/some/not/known/path");
}
TEST_F(FilePathStorage, CallSelectAndWriteForFetchingSourceIdForUnknownEntry)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(5, Eq("unknownfile.h")));
EXPECT_CALL(insertIntoSources, write(5, Eq("unknownfile.h")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchSourceId(5, "unknownfile.h");
}
TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdTwoTimesIfTheDatabaseIsBusyBecauseTheTableAlreadyChanged)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath,
valueReturnInt32(Eq("/other/unknow/path")));
EXPECT_CALL(insertIntoDirectories, write(Eq("/other/unknow/path")))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK")));
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath,
valueReturnInt32(Eq("/other/unknow/path")));
EXPECT_CALL(insertIntoDirectories, write(Eq("/other/unknow/path")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchDirectoryId("/other/unknow/path");
}
TEST_F(FilePathStorage, CallSelectAndWriteForFetchingSourceTwoTimesIfTheDatabaseIsBusyBecauseTheTableAlreadyChanged)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(5, Eq("otherunknownfile.h")));
EXPECT_CALL(insertIntoSources, write(5, Eq("otherunknownfile.h")))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));;
EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK")));
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(5, Eq("otherunknownfile.h")));
EXPECT_CALL(insertIntoSources, write(5, Eq("otherunknownfile.h")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchSourceId(5, "otherunknownfile.h");
}
TEST_F(FilePathStorage, SelectAllDirectories)
{
auto directories = storage.fetchAllDirectories();
ASSERT_THAT(directories,
ElementsAre(Directory{1, "/path/to"}, Directory{2, "/other/path"}));
}
TEST_F(FilePathStorage, SelectAllSources)
{
auto sources = storage.fetchAllSources();
ASSERT_THAT(sources,
ElementsAre(Source{1, "file.h"}, Source{4, "file.cpp"}));
}
TEST_F(FilePathStorage, CallSelectAllDirectories)
{
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectAllDirectories, valuesReturnStdVectorDirectory(256));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchAllDirectories();
}
TEST_F(FilePathStorage, CallSelectAllSources)
{
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectAllSources, valuesReturnStdVectorSource(8192));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchAllSources();
}
TEST_F(FilePathStorage, CallValueForFetchDirectoryPathForId)
{
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, valueReturnPathString(5));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchDirectoryPath(5);
}
TEST_F(FilePathStorage, FetchDirectoryPathForId)
{
auto path = storage.fetchDirectoryPath(5);
ASSERT_THAT(path, Eq("/path/to"));
}
TEST_F(FilePathStorage, ThrowAsFetchingDirectoryPathForNonExistingId)
{
ASSERT_THROW(storage.fetchDirectoryPath(12), ClangBackEnd::DirectoryPathIdDoesNotExists);
}
TEST_F(FilePathStorage, CallValueForFetchSoureNameForId)
{
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
EXPECT_CALL(selectSourceNameFromSourcesBySourceId, valueReturnSmallString(42));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
storage.fetchSourceName(42);
}
TEST_F(FilePathStorage, FetchSoureNameForId)
{
auto path = storage.fetchSourceName(42);
ASSERT_THAT(path, Eq("file.cpp"));
}
TEST_F(FilePathStorage, ThrowAsFetchingSourceNameForNonExistingId)
{
ASSERT_THROW(storage.fetchSourceName(12), ClangBackEnd::SourceNameIdDoesNotExists);
}
void FilePathStorage::SetUp()
{
ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath,
valueReturnInt32(_))
.WillByDefault(Return(Utils::optional<int>()));
ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath,
valueReturnInt32(Utils::SmallStringView("")))
.WillByDefault(Return(Utils::optional<int>(0)));
ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath,
valueReturnInt32(Utils::SmallStringView("/path/to")))
.WillByDefault(Return(Utils::optional<int>(5)));
ON_CALL(mockDatabase, lastInsertedRowId())
.WillByDefault(Return(12));
ON_CALL(selectAllDirectories,
valuesReturnStdVectorDirectory(_))
.WillByDefault(Return(std::vector<Directory>{{1, "/path/to"}, {2, "/other/path"}}));
ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(_, _))
.WillByDefault(Return(Utils::optional<int>()));
ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(0, Utils::SmallStringView("")))
.WillByDefault(Return(Utils::optional<int>(0)));
ON_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName,
valueReturnInt32(5, Utils::SmallStringView("file.h")))
.WillByDefault(Return(Utils::optional<int>(42)));
ON_CALL(selectAllSources,
valuesReturnStdVectorSource(_))
.WillByDefault(Return(std::vector<Source>{{1, "file.h"}, {4, "file.cpp"}}));
ON_CALL(selectDirectoryPathFromDirectoriesByDirectoryId,
valueReturnPathString(5))
.WillByDefault(Return(Utils::optional<Utils::PathString>("/path/to")));
ON_CALL(selectSourceNameFromSourcesBySourceId,
valueReturnSmallString(42))
.WillByDefault(Return(Utils::optional<Utils::SmallString>("file.cpp")));
EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, valueReturnInt32(_))
.Times(AnyNumber());
EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, valueReturnInt32(_, _))
.Times(AnyNumber());
EXPECT_CALL(insertIntoDirectories,write(_))
.Times(AnyNumber());
EXPECT_CALL(insertIntoSources,write(_, _))
.Times(AnyNumber());
EXPECT_CALL(selectAllDirectories, valuesReturnStdVectorDirectory(_))
.Times(AnyNumber());
EXPECT_CALL(selectAllSources, valuesReturnStdVectorSource(_))
.Times(AnyNumber());
EXPECT_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, valueReturnPathString(_))
.Times(AnyNumber());
EXPECT_CALL(selectSourceNameFromSourcesBySourceId, valueReturnSmallString(_))
.Times(AnyNumber());
}
}

View File

@@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mockmutex.h"
#include "mocksqlitedatabase.h"
#include "mocksqlitereadstatement.h"
#include "mocksqlitewritestatement.h"
#include <filepathstoragesqlitestatementfactory.h>
namespace {
using StatementFactory = ClangBackEnd::FilePathStorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>,
MockSqliteReadStatement,
MockSqliteWriteStatement>;
class FilePathStorageSqliteStatementFactory : public testing::Test
{
protected:
NiceMock<MockMutex> mockMutex;
NiceMock<MockSqliteDatabase> mockDatabase{mockMutex};
StatementFactory factory{mockDatabase};
};
TEST_F(FilePathStorageSqliteStatementFactory, SelectDirectoryIdFromDirectoriesByDirectoryPath)
{
ASSERT_THAT(factory.selectDirectoryIdFromDirectoriesByDirectoryPath.sqlStatement,
Eq("SELECT directoryId FROM directories WHERE directoryPath = ?"));
}
TEST_F(FilePathStorageSqliteStatementFactory, SelectDirectoryPathFromDirectoriesByDirectoryId)
{
ASSERT_THAT(factory.selectDirectoryPathFromDirectoriesByDirectoryId.sqlStatement,
Eq("SELECT directoryPath FROM directories WHERE directoryId = ?"));
}
TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceIdFromSourcesByDirectoryIdAndSourceName)
{
ASSERT_THAT(factory.selectSourceIdFromSourcesByDirectoryIdAndSourceName.sqlStatement,
Eq("SELECT sourceId FROM sources WHERE directoryId = ? AND sourceName = ?"));
}
TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceNameFromSourcesByDirectoryIdAndSourceId)
{
ASSERT_THAT(factory.selectSourceNameFromSourcesBySourceId.sqlStatement,
Eq("SELECT sourceName FROM sources WHERE sourceId = ?"));
}
TEST_F(FilePathStorageSqliteStatementFactory, SelectAllDirectories)
{
ASSERT_THAT(factory.selectAllDirectories.sqlStatement,
Eq("SELECT directoryId, directoryPath FROM directories"));
}
TEST_F(FilePathStorageSqliteStatementFactory, InsertIntoDirectories)
{
ASSERT_THAT(factory.insertIntoDirectories.sqlStatement,
Eq("INSERT INTO directories(directoryPath) VALUES (?)"));
}
TEST_F(FilePathStorageSqliteStatementFactory, InsertIntoSources)
{
ASSERT_THAT(factory.insertIntoSources.sqlStatement,
Eq("INSERT INTO sources(directoryId, sourceName) VALUES (?,?)"));
}
TEST_F(FilePathStorageSqliteStatementFactory, SelectAllSources)
{
ASSERT_THAT(factory.selectAllSources.sqlStatement,
Eq("SELECT sourceId, sourceName FROM sources"));
}
}

Some files were not shown because too many files have changed in this diff Show More