forked from qt-creator/qt-creator
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:
@@ -67,7 +67,6 @@ SOURCES += \
|
||||
$$PWD/requestsourcelocationforrenamingmessage.cpp \
|
||||
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \
|
||||
$$PWD/requestsourcerangesforquerymessage.cpp \
|
||||
$$PWD/sourcefilepathcontainerbase.cpp \
|
||||
$$PWD/sourcelocationcontainer.cpp \
|
||||
$$PWD/sourcelocationcontainerv2.cpp \
|
||||
$$PWD/sourcelocationscontainer.cpp \
|
||||
@@ -82,7 +81,9 @@ SOURCES += \
|
||||
$$PWD/updatepchprojectpartsmessage.cpp \
|
||||
$$PWD/updatetranslationunitsforeditormessage.cpp \
|
||||
$$PWD/updatevisibletranslationunitsmessage.cpp \
|
||||
$$PWD/writemessageblock.cpp
|
||||
$$PWD/writemessageblock.cpp \
|
||||
$$PWD/filepathcaching.cpp \
|
||||
$$PWD/filepathid.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/cancelmessage.h \
|
||||
@@ -150,7 +151,6 @@ HEADERS += \
|
||||
$$PWD/requestsourcelocationforrenamingmessage.h \
|
||||
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \
|
||||
$$PWD/requestsourcerangesforquerymessage.h \
|
||||
$$PWD/sourcefilepathcontainerbase.h \
|
||||
$$PWD/sourcelocationcontainer.h \
|
||||
$$PWD/sourcelocationcontainerv2.h \
|
||||
$$PWD/sourcelocationscontainer.h \
|
||||
@@ -172,6 +172,15 @@ HEADERS += \
|
||||
$$PWD/stringcachefwd.h \
|
||||
$$PWD/stringcachealgorithms.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
|
||||
|
@@ -94,9 +94,7 @@ public:
|
||||
|
||||
DynamicASTMatcherDiagnosticMessageContainer clone() const
|
||||
{
|
||||
return DynamicASTMatcherDiagnosticMessageContainer(m_sourceRange.clone(),
|
||||
m_errorType,
|
||||
m_arguments.clone());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -63,22 +63,27 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
FilePath(const Utils::PathString &directory, const Utils::PathString &name)
|
||||
: m_path({std::move(directory), "/", std::move(name)}),
|
||||
FilePath(Utils::SmallStringView directory, Utils::SmallStringView name)
|
||||
: m_path({directory, "/", name}),
|
||||
m_slashIndex(directory.size())
|
||||
{}
|
||||
|
||||
Utils::SmallStringView directory() const
|
||||
Utils::SmallStringView directory() const noexcept
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
const Utils::PathString &path() const
|
||||
const Utils::PathString &path() const noexcept
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
operator Utils::PathString() const noexcept
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
@@ -105,9 +110,7 @@ public:
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, const FilePath &filePath)
|
||||
{
|
||||
out << filePath.directory() << "/" << filePath.name();
|
||||
|
||||
return out;
|
||||
return out << "(" << filePath.path() << ", " << filePath.slashIndex() << ")";
|
||||
}
|
||||
|
||||
friend bool operator==(const FilePath &first, const FilePath &second)
|
||||
@@ -115,6 +118,16 @@ public:
|
||||
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)
|
||||
{
|
||||
return first.m_path < second.m_path;
|
||||
@@ -125,11 +138,18 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::size_t slashIndex() const
|
||||
{
|
||||
return m_slashIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
Utils::PathString m_path = "/";
|
||||
std::size_t m_slashIndex = 0;
|
||||
};
|
||||
|
||||
using FilePaths = std::vector<FilePath>;
|
||||
|
||||
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath);
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
128
src/libs/clangsupport/filepathcache.h
Normal file
128
src/libs/clangsupport/filepathcache.h
Normal 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
|
@@ -23,20 +23,18 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "sourcelocationentry.h"
|
||||
|
||||
#include <utils/smallstringio.h>
|
||||
#include "filepathcaching.h"
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry)
|
||||
FilePathId FilePathCaching::filePathId(Utils::SmallStringView filePath) const
|
||||
{
|
||||
out << "("
|
||||
<< entry.fileId << ", "
|
||||
<< entry.line << ", "
|
||||
<< entry.column << ")";
|
||||
return m_cache.filePathId(filePath);
|
||||
}
|
||||
|
||||
return out;
|
||||
FilePath FilePathCaching::filePath(FilePathId filePathId) const
|
||||
{
|
||||
return m_cache.filePath(filePathId);
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
62
src/libs/clangsupport/filepathcaching.h
Normal file
62
src/libs/clangsupport/filepathcaching.h
Normal 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
|
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
@@ -23,10 +23,10 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "sourcefilepathcontainerbase.h"
|
||||
#pragma once
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
|
||||
class FilePathCachingInterface;
|
||||
|
||||
} // namespace ClangBackEnd
|
73
src/libs/clangsupport/filepathcachinginterface.h
Normal file
73
src/libs/clangsupport/filepathcachinginterface.h
Normal 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
|
59
src/libs/clangsupport/filepathexceptions.h
Normal file
59
src/libs/clangsupport/filepathexceptions.h
Normal 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
|
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 {
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths)
|
||||
QDebug operator<<(QDebug debug, const FilePathId &filePathId)
|
||||
{
|
||||
out << "("
|
||||
<< idPaths.id << ", "
|
||||
<< idPaths.paths << ")";
|
||||
debug.nospace() << "(" << filePathId.directoryId << ", " << filePathId.fileNameId << ")";
|
||||
|
||||
return out;
|
||||
return debug;
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
113
src/libs/clangsupport/filepathid.h
Normal file
113
src/libs/clangsupport/filepathid.h
Normal 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
|
187
src/libs/clangsupport/filepathstorage.h
Normal file
187
src/libs/clangsupport/filepathstorage.h
Normal 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
|
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
@@ -25,41 +25,50 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "filepath.h"
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
using FilePathDict = std::unordered_map<uint, FilePath>;
|
||||
|
||||
class SourceFilePathContainerBase
|
||||
namespace Sources {
|
||||
class Directory
|
||||
{
|
||||
public:
|
||||
SourceFilePathContainerBase() = default;
|
||||
SourceFilePathContainerBase(std::unordered_map<uint, FilePath> &&filePathHash)
|
||||
: m_filePathHash(std::move(filePathHash))
|
||||
Directory(int directoryId, Utils::PathString &&directoryPath)
|
||||
: directoryId(directoryId), directoryPath(std::move(directoryPath))
|
||||
{}
|
||||
|
||||
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)
|
||||
{
|
||||
if (m_filePathHash.find(fileId) == m_filePathHash.end())
|
||||
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;
|
||||
public:
|
||||
int directoryId;
|
||||
Utils::PathString directoryPath;
|
||||
};
|
||||
|
||||
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
|
@@ -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
|
||||
|
@@ -44,6 +44,7 @@ public:
|
||||
createSymbolsTable();
|
||||
createLocationsTable();
|
||||
createSourcesTable();
|
||||
createDirectoriesTable();
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
@@ -67,10 +68,10 @@ public:
|
||||
table.setUseIfNotExists(true);
|
||||
table.setName("locations");
|
||||
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
|
||||
table.addColumn("line", Sqlite::ColumnType::Integer);
|
||||
table.addColumn("column", Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &lineColumn = table.addColumn("line", Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &columnColumn = table.addColumn("column", Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
|
||||
table.addIndex({sourceIdColumn});
|
||||
table.addIndex({sourceIdColumn, lineColumn, columnColumn});
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
@@ -81,7 +82,22 @@ public:
|
||||
table.setUseIfNotExists(true);
|
||||
table.setName("sources");
|
||||
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);
|
||||
}
|
||||
|
@@ -38,15 +38,15 @@ QDebug operator<<(QDebug debug, const SourceLocationContainer &container)
|
||||
<< container.line() << ", "
|
||||
<< container.column() << ", "
|
||||
<< container.offset() << ", "
|
||||
<< container.fileHash()
|
||||
<< container.filePathId().fileNameId
|
||||
<< ")";
|
||||
return debug;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container)
|
||||
{
|
||||
os << "("
|
||||
<< container.fileHash() << ", "
|
||||
os << "(("
|
||||
<< container.filePathId().directoryId << ", " << container.filePathId().fileNameId << "), "
|
||||
<< container.line() << ", "
|
||||
<< container.column() << ", "
|
||||
<< container.offset()
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "clangsupport_global.h"
|
||||
#include "filepathid.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
@@ -37,20 +38,20 @@ class SourceLocationContainer
|
||||
{
|
||||
public:
|
||||
SourceLocationContainer() = default;
|
||||
SourceLocationContainer(uint fileHash,
|
||||
SourceLocationContainer(FilePathId filePathId,
|
||||
uint line,
|
||||
uint column,
|
||||
uint offset)
|
||||
: m_fileHash(fileHash),
|
||||
: m_filePathId(filePathId),
|
||||
m_line(line),
|
||||
m_column(column),
|
||||
m_offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
uint fileHash() const
|
||||
FilePathId filePathId() const
|
||||
{
|
||||
return m_fileHash;
|
||||
return m_filePathId;
|
||||
}
|
||||
|
||||
uint line() const
|
||||
@@ -70,7 +71,7 @@ public:
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container)
|
||||
{
|
||||
out << container.m_fileHash;
|
||||
out << container.m_filePathId;
|
||||
out << container.m_line;
|
||||
out << container.m_column;
|
||||
out << container.m_offset;
|
||||
@@ -80,7 +81,7 @@ public:
|
||||
|
||||
friend QDataStream &operator>>(QDataStream &in, SourceLocationContainer &container)
|
||||
{
|
||||
in >> container.m_fileHash;
|
||||
in >> container.m_filePathId;
|
||||
in >> container.m_line;
|
||||
in >> container.m_column;
|
||||
in >> container.m_offset;
|
||||
@@ -97,23 +98,23 @@ public:
|
||||
{
|
||||
return first.m_line != second.m_line
|
||||
|| first.m_column != second.m_column
|
||||
|| first.m_fileHash != second.m_fileHash;
|
||||
|| first.m_filePathId != second.m_filePathId;
|
||||
}
|
||||
|
||||
friend bool operator<(const SourceLocationContainer &first,
|
||||
const SourceLocationContainer &second)
|
||||
{
|
||||
return std::tie(first.m_fileHash, first.m_line, first.m_column)
|
||||
< std::tie(second.m_fileHash, second.m_line, second.m_column);
|
||||
return std::tie(first.m_filePathId, first.m_line, first.m_column)
|
||||
< std::tie(second.m_filePathId, second.m_line, second.m_column);
|
||||
}
|
||||
|
||||
SourceLocationContainer clone() const
|
||||
{
|
||||
return SourceLocationContainer(m_fileHash, m_line, m_column, m_offset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
uint m_fileHash = 0;
|
||||
FilePathId m_filePathId;
|
||||
uint m_line = 1;
|
||||
uint m_column = 1;
|
||||
uint m_offset = 0;
|
||||
|
@@ -33,10 +33,10 @@ QDebug operator<<(QDebug debug, const SourceLocationsContainer &container)
|
||||
{
|
||||
debug.nospace() << "SourceLocationsContainer([";
|
||||
for (const auto &sourceLocation: container.sourceLocationContainers()) {
|
||||
debug.nospace() << "["
|
||||
<< container.filePathForSourceLocation(sourceLocation).name() << ","
|
||||
debug.nospace() << "("
|
||||
<< sourceLocation.filePathId() << ","
|
||||
<< sourceLocation.line() << ","
|
||||
<< sourceLocation.column() << "], ";
|
||||
<< sourceLocation.column() << "), ";
|
||||
}
|
||||
|
||||
debug.nospace() << "])";
|
||||
|
@@ -25,30 +25,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sourcefilepathcontainerbase.h"
|
||||
#include "sourcelocationcontainerv2.h"
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
#include <utils/smallstringio.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class SourceLocationsContainer : public SourceFilePathContainerBase
|
||||
class SourceLocationsContainer
|
||||
{
|
||||
public:
|
||||
SourceLocationsContainer() = default;
|
||||
SourceLocationsContainer(std::unordered_map<uint, FilePath> &&filePathHash,
|
||||
std::vector<V2::SourceLocationContainer> &&sourceLocationContainers)
|
||||
: SourceFilePathContainerBase(std::move(filePathHash)),
|
||||
m_sourceLocationContainers(std::move(sourceLocationContainers))
|
||||
SourceLocationsContainer(std::vector<V2::SourceLocationContainer> &&sourceLocationContainers)
|
||||
: 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
|
||||
{
|
||||
return m_sourceLocationContainers;
|
||||
@@ -59,20 +49,18 @@ public:
|
||||
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)
|
||||
{
|
||||
SourceFilePathContainerBase::reserve(size);
|
||||
m_sourceLocationContainers.reserve(size);
|
||||
}
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &out, const SourceLocationsContainer &container)
|
||||
{
|
||||
out << container.m_filePathHash;
|
||||
out << container.m_sourceLocationContainers;
|
||||
|
||||
return out;
|
||||
@@ -80,7 +68,6 @@ public:
|
||||
|
||||
friend QDataStream &operator>>(QDataStream &in, SourceLocationsContainer &container)
|
||||
{
|
||||
in >> container.m_filePathHash;
|
||||
in >> container.m_sourceLocationContainers;
|
||||
|
||||
return in;
|
||||
@@ -93,7 +80,7 @@ public:
|
||||
|
||||
SourceLocationsContainer clone() const
|
||||
{
|
||||
return SourceLocationsContainer(Utils::clone(m_filePathHash), Utils::clone(m_sourceLocationContainers));
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<V2::SourceLocationContainer> m_sourceLocationContainers;
|
||||
|
@@ -43,15 +43,15 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
SourceRangeContainer(uint fileHash,
|
||||
SourceRangeContainer(FilePathId filePathId,
|
||||
uint startLine,
|
||||
uint startColumn,
|
||||
uint startOffset,
|
||||
uint endLine,
|
||||
uint endColumn,
|
||||
uint endOffset)
|
||||
: m_start(fileHash, startLine, startColumn, startOffset),
|
||||
m_end(fileHash, endLine, endColumn, endOffset)
|
||||
: m_start(filePathId, startLine, startColumn, startOffset),
|
||||
m_end(filePathId, endLine, endColumn, endOffset)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,9 +65,9 @@ public:
|
||||
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)
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
|
||||
SourceRangeContainer clone() const
|
||||
{
|
||||
return SourceRangeContainer(m_start.clone(), m_end.clone());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -31,12 +31,11 @@ QDebug operator<<(QDebug debug, const SourceRangesContainer &container)
|
||||
{
|
||||
debug.nospace() << "SourceRangesContainer([";
|
||||
for (const auto &sourceRangeWithText: container.sourceRangeWithTextContainers()) {
|
||||
debug.nospace() << "["
|
||||
<< container.filePathForSourceRange(sourceRangeWithText).name() << ", ("
|
||||
debug.nospace() << "("
|
||||
<< sourceRangeWithText.start().line() << ","
|
||||
<< sourceRangeWithText.start().column() << "), ("
|
||||
<< sourceRangeWithText.end().line() << ","
|
||||
<< sourceRangeWithText.end().column() << ")], ";
|
||||
<< sourceRangeWithText.end().column() << "), ";
|
||||
}
|
||||
|
||||
debug.nospace() << "])";
|
||||
|
@@ -25,30 +25,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sourcefilepathcontainerbase.h"
|
||||
#include "sourcerangewithtextcontainer.h"
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class SourceRangesContainer : public SourceFilePathContainerBase
|
||||
class SourceRangesContainer
|
||||
{
|
||||
public:
|
||||
SourceRangesContainer() = default;
|
||||
SourceRangesContainer(std::unordered_map<uint, FilePath> &&filePathHash,
|
||||
SourceRangeWithTextContainers &&sourceRangeWithTextContainers)
|
||||
: SourceFilePathContainerBase(std::move(filePathHash)),
|
||||
m_sourceRangeWithTextContainers(std::move(sourceRangeWithTextContainers))
|
||||
SourceRangesContainer(SourceRangeWithTextContainers &&sourceRangeWithTextContainers)
|
||||
: 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
|
||||
{
|
||||
return m_sourceRangeWithTextContainers;
|
||||
@@ -69,7 +59,7 @@ public:
|
||||
return !m_sourceRangeWithTextContainers.empty();
|
||||
}
|
||||
|
||||
void insertSourceRange(uint fileId,
|
||||
void insertSourceRange(FilePathId filePathId,
|
||||
uint startLine,
|
||||
uint startColumn,
|
||||
uint startOffset,
|
||||
@@ -78,7 +68,7 @@ public:
|
||||
uint endOffset,
|
||||
Utils::SmallString &&text)
|
||||
{
|
||||
m_sourceRangeWithTextContainers.emplace_back(fileId,
|
||||
m_sourceRangeWithTextContainers.emplace_back(filePathId,
|
||||
startLine,
|
||||
startColumn,
|
||||
startOffset,
|
||||
@@ -90,13 +80,11 @@ public:
|
||||
|
||||
void reserve(std::size_t size)
|
||||
{
|
||||
SourceFilePathContainerBase::reserve(size);
|
||||
m_sourceRangeWithTextContainers.reserve(size);
|
||||
}
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &out, const SourceRangesContainer &container)
|
||||
{
|
||||
out << container.m_filePathHash;
|
||||
out << container.m_sourceRangeWithTextContainers;
|
||||
|
||||
return out;
|
||||
@@ -104,7 +92,6 @@ public:
|
||||
|
||||
friend QDataStream &operator>>(QDataStream &in, SourceRangesContainer &container)
|
||||
{
|
||||
in >> container.m_filePathHash;
|
||||
in >> container.m_sourceRangeWithTextContainers;
|
||||
|
||||
return in;
|
||||
|
@@ -35,7 +35,7 @@ class SourceRangeWithTextContainer : public V2::SourceRangeContainer
|
||||
{
|
||||
public:
|
||||
SourceRangeWithTextContainer() = default;
|
||||
SourceRangeWithTextContainer(uint fileHash,
|
||||
SourceRangeWithTextContainer(FilePathId filePathId,
|
||||
uint startLine,
|
||||
uint startColumn,
|
||||
uint startOffset,
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
uint endColumn,
|
||||
uint endOffset,
|
||||
Utils::SmallString &&text)
|
||||
: V2::SourceRangeContainer(fileHash,
|
||||
: V2::SourceRangeContainer(filePathId,
|
||||
startLine,
|
||||
startColumn,
|
||||
startOffset,
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
|
||||
using V2::SourceRangeContainer::start;
|
||||
using V2::SourceRangeContainer::end;
|
||||
using V2::SourceRangeContainer::fileHash;
|
||||
using V2::SourceRangeContainer::filePathId;
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &out, const SourceRangeWithTextContainer &container)
|
||||
{
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "stringcachealgorithms.h"
|
||||
#include "stringcachefwd.h"
|
||||
|
||||
#include <utils/optional.h>
|
||||
#include <utils/smallstringview.h>
|
||||
#include <utils/smallstringfwd.h>
|
||||
|
||||
@@ -70,15 +71,12 @@ public:
|
||||
}
|
||||
|
||||
StringType string;
|
||||
uint id;
|
||||
IndexType id;
|
||||
};
|
||||
|
||||
template <typename StringType, typename IndexType>
|
||||
using StringCacheEntries = std::vector<StringCacheEntry<StringType, IndexType>>;
|
||||
|
||||
using FileCacheCacheEntry = StringCacheEntry<Utils::PathString, FilePathIndex>;
|
||||
using FileCacheCacheEntries = std::vector<FileCacheCacheEntry>;
|
||||
|
||||
template <typename StringType,
|
||||
typename IndexType,
|
||||
typename Mutex,
|
||||
@@ -86,25 +84,26 @@ template <typename StringType,
|
||||
Compare compare = Utils::compare>
|
||||
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:
|
||||
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_indices.reserve(1024);
|
||||
m_strings.reserve(reserveSize);
|
||||
m_indices.reserve(reserveSize);
|
||||
}
|
||||
|
||||
void populate(CacheEnties &&entries)
|
||||
void populate(CacheEntries &&entries)
|
||||
{
|
||||
uncheckedPopulate(std::move(entries));
|
||||
|
||||
checkEntries();
|
||||
}
|
||||
|
||||
void uncheckedPopulate(CacheEnties &&entries)
|
||||
void uncheckedPopulate(CacheEntries &&entries)
|
||||
{
|
||||
std::sort(entries.begin(),
|
||||
entries.end(),
|
||||
@@ -149,13 +148,35 @@ public:
|
||||
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);
|
||||
|
||||
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::lock_guard<Mutex> lock(m_mutex);
|
||||
@@ -176,13 +197,31 @@ public:
|
||||
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:
|
||||
IndexType ungardedStringId(Utils::SmallStringView stringView)
|
||||
{
|
||||
Found found = find(stringView);
|
||||
|
||||
if (!found.wasFound)
|
||||
return insertString(found.iterator, stringView);
|
||||
insertString(found.iterator, stringView, IndexType(m_indices.size()));
|
||||
|
||||
return found.iterator->id;
|
||||
}
|
||||
@@ -202,20 +241,26 @@ private:
|
||||
});
|
||||
}
|
||||
|
||||
IndexType insertString(const_iterator beforeIterator,
|
||||
Utils::SmallStringView stringView)
|
||||
void ensureSize(IndexType id)
|
||||
{
|
||||
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 newIndex = IndexType(std::distance(m_strings.begin(), inserted));
|
||||
|
||||
incrementLargerOrEqualIndicesByOne(newIndex);
|
||||
|
||||
m_indices.push_back(newIndex);
|
||||
ensureSize(id);
|
||||
m_indices.at(id) = newIndex;
|
||||
|
||||
return id;
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
void checkEntries()
|
||||
@@ -227,11 +272,9 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
CacheEnties m_strings;
|
||||
CacheEntries m_strings;
|
||||
std::vector<IndexType> m_indices;
|
||||
mutable Mutex m_mutex;
|
||||
};
|
||||
|
||||
using FilePathIndices = std::vector<FilePathIndex>;
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -29,8 +29,6 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
using FilePathIndex = long long int;
|
||||
|
||||
class NonLockingMutex;
|
||||
|
||||
template <typename StringType,
|
||||
@@ -39,13 +37,5 @@ template <typename StringType,
|
||||
typename Compare,
|
||||
Compare compare>
|
||||
class StringCache;
|
||||
|
||||
template <typename Mutex = NonLockingMutex>
|
||||
using FilePathCache = StringCache<Utils::PathString,
|
||||
FilePathIndex,
|
||||
Mutex,
|
||||
decltype(&Utils::reverseCompare),
|
||||
Utils::reverseCompare>;
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
|
@@ -17,7 +17,6 @@ SOURCES += \
|
||||
$$PWD/sqliteglobal.cpp \
|
||||
$$PWD/sqlitereadstatement.cpp \
|
||||
$$PWD/sqlitereadwritestatement.cpp \
|
||||
$$PWD/sqlitestatement.cpp \
|
||||
$$PWD/sqlitetransaction.cpp \
|
||||
$$PWD/sqlitewritestatement.cpp \
|
||||
$$PWD/sqlstatementbuilder.cpp \
|
||||
@@ -26,7 +25,8 @@ SOURCES += \
|
||||
$$PWD/utf8stringvector.cpp \
|
||||
$$PWD/sqlitedatabase.cpp \
|
||||
$$PWD/sqlitetable.cpp \
|
||||
$$PWD/sqlitecolumn.cpp
|
||||
$$PWD/sqlitecolumn.cpp \
|
||||
$$PWD/sqlitebasestatement.cpp
|
||||
HEADERS += \
|
||||
$$PWD/createtablesqlstatementbuilder.h \
|
||||
$$PWD/sqlitedatabasebackend.h \
|
||||
@@ -34,7 +34,6 @@ HEADERS += \
|
||||
$$PWD/sqliteglobal.h \
|
||||
$$PWD/sqlitereadstatement.h \
|
||||
$$PWD/sqlitereadwritestatement.h \
|
||||
$$PWD/sqlitestatement.h \
|
||||
$$PWD/sqlitetransaction.h \
|
||||
$$PWD/sqlitewritestatement.h \
|
||||
$$PWD/sqlstatementbuilder.h \
|
||||
@@ -44,7 +43,8 @@ HEADERS += \
|
||||
$$PWD/sqlitedatabase.h \
|
||||
$$PWD/sqlitetable.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
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "sqlitestatement.h"
|
||||
#include "sqlitebasestatement.h"
|
||||
|
||||
#include "sqlitedatabase.h"
|
||||
#include "sqlitedatabasebackend.h"
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
Statement::Statement(Utils::SmallStringView sqlStatement, Database &database)
|
||||
BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database)
|
||||
: m_compiledStatement(nullptr, deleteCompiledStatement),
|
||||
m_database(database),
|
||||
m_bindingParameterCount(0),
|
||||
@@ -49,11 +49,10 @@ Statement::Statement(Utils::SmallStringView sqlStatement, Database &database)
|
||||
{
|
||||
prepare(sqlStatement);
|
||||
setBindingParameterCount();
|
||||
setBindingColumnNamesFromStatement();
|
||||
setColumnCount();
|
||||
}
|
||||
|
||||
void Statement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
|
||||
void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
|
||||
{
|
||||
if (compiledStatement)
|
||||
sqlite3_finalize(compiledStatement);
|
||||
@@ -92,7 +91,7 @@ private:
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
void Statement::waitForUnlockNotify() const
|
||||
void BaseStatement::waitForUnlockNotify() const
|
||||
{
|
||||
UnlockNotification unlockNotification;
|
||||
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
|
||||
@@ -105,7 +104,7 @@ void Statement::waitForUnlockNotify() const
|
||||
unlockNotification.wait();
|
||||
}
|
||||
|
||||
void Statement::reset() const
|
||||
void BaseStatement::reset() const
|
||||
{
|
||||
int resultCode = sqlite3_reset(m_compiledStatement.get());
|
||||
switch (resultCode) {
|
||||
@@ -119,7 +118,7 @@ void Statement::reset() const
|
||||
m_isReadyToFetchValues = false;
|
||||
}
|
||||
|
||||
bool Statement::next() const
|
||||
bool BaseStatement::next() const
|
||||
{
|
||||
int resultCode;
|
||||
|
||||
@@ -137,26 +136,26 @@ bool Statement::next() const
|
||||
return checkForStepError(resultCode);
|
||||
}
|
||||
|
||||
void Statement::step() const
|
||||
void BaseStatement::step() const
|
||||
{
|
||||
next();
|
||||
}
|
||||
|
||||
void Statement::execute() const
|
||||
void BaseStatement::execute() const
|
||||
{
|
||||
next();
|
||||
reset();
|
||||
}
|
||||
|
||||
int Statement::columnCount() const
|
||||
int BaseStatement::columnCount() const
|
||||
{
|
||||
return m_columnCount;
|
||||
}
|
||||
|
||||
Utils::SmallStringVector Statement::columnNames() const
|
||||
Utils::SmallStringVector BaseStatement::columnNames() const
|
||||
{
|
||||
Utils::SmallStringVector columnNames;
|
||||
int columnCount = Statement::columnCount();
|
||||
int columnCount = BaseStatement::columnCount();
|
||||
columnNames.reserve(std::size_t(columnCount));
|
||||
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++)
|
||||
columnNames.emplace_back(sqlite3_column_origin_name(m_compiledStatement.get(), columnIndex));
|
||||
@@ -164,25 +163,25 @@ Utils::SmallStringVector Statement::columnNames() const
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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(),
|
||||
index,
|
||||
@@ -193,35 +192,25 @@ void Statement::bind(int index, Utils::SmallStringView text)
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Statement::bind(Utils::SmallStringView name, Type value)
|
||||
void BaseStatement::bind(Utils::SmallStringView name, Type value)
|
||||
{
|
||||
int index = bindingIndexForName(name);
|
||||
checkBindingName(index);
|
||||
bind(index, value);
|
||||
}
|
||||
|
||||
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value);
|
||||
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value);
|
||||
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value);
|
||||
template SQLITE_EXPORT void Statement::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, int value);
|
||||
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long value);
|
||||
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long long value);
|
||||
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, double value);
|
||||
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());
|
||||
}
|
||||
|
||||
void Statement::setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames)
|
||||
{
|
||||
m_bindingColumnNames = bindingColumnNames;
|
||||
}
|
||||
|
||||
const Utils::SmallStringVector &Statement::bindingColumnNames() const
|
||||
{
|
||||
return m_bindingColumnNames;
|
||||
}
|
||||
|
||||
void Statement::prepare(Utils::SmallStringView sqlStatement)
|
||||
void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
|
||||
{
|
||||
int resultCode;
|
||||
|
||||
@@ -242,17 +231,17 @@ void Statement::prepare(Utils::SmallStringView sqlStatement)
|
||||
checkForPrepareError(resultCode);
|
||||
}
|
||||
|
||||
sqlite3 *Statement::sqliteDatabaseHandle() const
|
||||
sqlite3 *BaseStatement::sqliteDatabaseHandle() const
|
||||
{
|
||||
return m_database.backend().sqliteDatabaseHandle();
|
||||
}
|
||||
|
||||
TextEncoding Statement::databaseTextEncoding()
|
||||
TextEncoding BaseStatement::databaseTextEncoding()
|
||||
{
|
||||
return m_database.backend().textEncoding();
|
||||
}
|
||||
|
||||
bool Statement::checkForStepError(int resultCode) const
|
||||
bool BaseStatement::checkForStepError(int resultCode) const
|
||||
{
|
||||
switch (resultCode) {
|
||||
case SQLITE_ROW: return true;
|
||||
@@ -268,7 +257,7 @@ bool Statement::checkForStepError(int resultCode) const
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
void Statement::checkForPrepareError(int resultCode) const
|
||||
void BaseStatement::checkForPrepareError(int resultCode) const
|
||||
{
|
||||
switch (resultCode) {
|
||||
case SQLITE_OK: return;
|
||||
@@ -280,7 +269,7 @@ void Statement::checkForPrepareError(int resultCode) const
|
||||
throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened");
|
||||
}
|
||||
|
||||
void Statement::checkForBindingError(int resultCode) const
|
||||
void BaseStatement::checkForBindingError(int resultCode) const
|
||||
{
|
||||
switch (resultCode) {
|
||||
case SQLITE_OK: return;
|
||||
@@ -292,7 +281,7 @@ void Statement::checkForBindingError(int resultCode) const
|
||||
throwUnknowError("SqliteStatement::bind: unknown error has happened");
|
||||
}
|
||||
|
||||
void Statement::setIfIsReadyToFetchValues(int resultCode) const
|
||||
void BaseStatement::setIfIsReadyToFetchValues(int resultCode) const
|
||||
{
|
||||
if (resultCode == SQLITE_ROW)
|
||||
m_isReadyToFetchValues = true;
|
||||
@@ -301,13 +290,13 @@ void Statement::setIfIsReadyToFetchValues(int resultCode) const
|
||||
|
||||
}
|
||||
|
||||
void Statement::checkIfIsReadyToFetchValues() const
|
||||
void BaseStatement::checkIfIsReadyToFetchValues() const
|
||||
{
|
||||
if (!m_isReadyToFetchValues)
|
||||
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) {
|
||||
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)
|
||||
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)
|
||||
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());
|
||||
}
|
||||
@@ -340,65 +329,57 @@ Utils::SmallStringView chopFirstLetter(const char *rawBindingName)
|
||||
return Utils::SmallStringView("");
|
||||
}
|
||||
|
||||
void Statement::setBindingColumnNamesFromStatement()
|
||||
{
|
||||
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()
|
||||
void BaseStatement::setColumnCount()
|
||||
{
|
||||
m_columnCount = sqlite3_column_count(m_compiledStatement.get());
|
||||
}
|
||||
|
||||
bool Statement::isReadOnlyStatement() const
|
||||
bool BaseStatement::isReadOnlyStatement() const
|
||||
{
|
||||
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()));
|
||||
}
|
||||
|
||||
void Statement::throwStatementHasError(const char *whatHasHappened) const
|
||||
void BaseStatement::throwStatementHasError(const char *whatHasHappened) const
|
||||
{
|
||||
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()));
|
||||
}
|
||||
|
||||
void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const
|
||||
void BaseStatement::throwConstraintPreventsModification(const char *whatHasHappened) const
|
||||
{
|
||||
throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
}
|
||||
|
||||
void Statement::throwNoValuesToFetch(const char *whatHasHappened) const
|
||||
void BaseStatement::throwNoValuesToFetch(const char *whatHasHappened) const
|
||||
{
|
||||
throw NoValuesToFetch(whatHasHappened);
|
||||
}
|
||||
|
||||
void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const
|
||||
void BaseStatement::throwInvalidColumnFetched(const char *whatHasHappened) const
|
||||
{
|
||||
throw InvalidColumnFetched(whatHasHappened);
|
||||
}
|
||||
|
||||
void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
|
||||
void BaseStatement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
|
||||
{
|
||||
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())
|
||||
throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
@@ -406,17 +387,17 @@ void Statement::throwUnknowError(const char *whatHasHappened) const
|
||||
throw UnknowError(whatHasHappened);
|
||||
}
|
||||
|
||||
void Statement::throwBingingTooBig(const char *whatHasHappened) const
|
||||
void BaseStatement::throwBingingTooBig(const char *whatHasHappened) const
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
Database &Statement::database() const
|
||||
Database &BaseStatement::database() const
|
||||
{
|
||||
return m_database;
|
||||
}
|
||||
@@ -445,7 +426,7 @@ static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
int Statement::fetchIntValue(int column) const
|
||||
int BaseStatement::fetchIntValue(int column) const
|
||||
{
|
||||
checkIfIsReadyToFetchValues();
|
||||
checkColumnIsValid(column);
|
||||
@@ -453,23 +434,23 @@ int Statement::fetchIntValue(int column) const
|
||||
}
|
||||
|
||||
template<>
|
||||
int Statement::fetchValue<int>(int column) const
|
||||
int BaseStatement::fetchValue<int>(int column) const
|
||||
{
|
||||
return fetchIntValue(column);
|
||||
}
|
||||
|
||||
long Statement::fetchLongValue(int column) const
|
||||
long BaseStatement::fetchLongValue(int column) const
|
||||
{
|
||||
return long(fetchValue<long long>(column));
|
||||
}
|
||||
|
||||
template<>
|
||||
long Statement::fetchValue<long>(int column) const
|
||||
long BaseStatement::fetchValue<long>(int column) const
|
||||
{
|
||||
return fetchLongValue(column);
|
||||
}
|
||||
|
||||
long long Statement::fetchLongLongValue(int column) const
|
||||
long long BaseStatement::fetchLongLongValue(int column) const
|
||||
{
|
||||
checkIfIsReadyToFetchValues();
|
||||
checkColumnIsValid(column);
|
||||
@@ -477,12 +458,12 @@ long long Statement::fetchLongLongValue(int column) const
|
||||
}
|
||||
|
||||
template<>
|
||||
long long Statement::fetchValue<long long>(int column) const
|
||||
long long BaseStatement::fetchValue<long long>(int column) const
|
||||
{
|
||||
return fetchLongLongValue(column);
|
||||
}
|
||||
|
||||
double Statement::fetchDoubleValue(int column) const
|
||||
double BaseStatement::fetchDoubleValue(int column) const
|
||||
{
|
||||
checkIfIsReadyToFetchValues();
|
||||
checkColumnIsValid(column);
|
||||
@@ -490,62 +471,30 @@ double Statement::fetchDoubleValue(int column) const
|
||||
}
|
||||
|
||||
template<>
|
||||
double Statement::fetchValue<double>(int column) const
|
||||
double BaseStatement::fetchValue<double>(int column) const
|
||||
{
|
||||
return fetchDoubleValue(column);
|
||||
}
|
||||
|
||||
template<typename StringType>
|
||||
StringType Statement::fetchValue(int column) const
|
||||
StringType BaseStatement::fetchValue(int column) const
|
||||
{
|
||||
checkIfIsReadyToFetchValues();
|
||||
checkColumnIsValid(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);
|
||||
}
|
||||
|
||||
Utils::PathString Statement::fetchPathStringValue(int column) const
|
||||
Utils::PathString BaseStatement::fetchPathStringValue(int column) const
|
||||
{
|
||||
return fetchValue<Utils::PathString>(column);
|
||||
}
|
||||
|
||||
template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
|
||||
template SQLITE_EXPORT Utils::PathString Statement::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);
|
||||
template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue<Utils::SmallString>(int column) const;
|
||||
template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathString>(int column) const;
|
||||
|
||||
} // namespace Sqlite
|
@@ -48,10 +48,10 @@ namespace Sqlite {
|
||||
class Database;
|
||||
class DatabaseBackend;
|
||||
|
||||
class SQLITE_EXPORT Statement
|
||||
class SQLITE_EXPORT BaseStatement
|
||||
{
|
||||
protected:
|
||||
explicit Statement(Utils::SmallStringView sqlStatement, Database &database);
|
||||
public:
|
||||
explicit BaseStatement(Utils::SmallStringView sqlStatement, Database &database);
|
||||
|
||||
static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement);
|
||||
|
||||
@@ -68,7 +68,6 @@ protected:
|
||||
Utils::PathString fetchPathStringValue(int column) const;
|
||||
template<typename Type>
|
||||
Type fetchValue(int column) const;
|
||||
Utils::SmallString text(int column) const;
|
||||
int columnCount() const;
|
||||
Utils::SmallStringVector columnNames() const;
|
||||
|
||||
@@ -87,140 +86,11 @@ protected:
|
||||
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>
|
||||
void bind(Utils::SmallStringView name, Type fetchValue);
|
||||
|
||||
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 waitForUnlockNotify() const;
|
||||
|
||||
@@ -236,7 +106,6 @@ protected:
|
||||
void checkColumnIsValid(int column) const;
|
||||
void checkBindingName(int index) const;
|
||||
void setBindingParameterCount();
|
||||
void setBindingColumnNamesFromStatement();
|
||||
void setColumnCount();
|
||||
bool isReadOnlyStatement() const;
|
||||
[[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const;
|
||||
@@ -250,22 +119,185 @@ protected:
|
||||
[[noreturn]] void throwUnknowError(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;
|
||||
|
||||
Database &database() const;
|
||||
|
||||
protected:
|
||||
explicit Statement(Utils::SmallStringView sqlStatement,
|
||||
DatabaseBackend &databaseBackend);
|
||||
private:
|
||||
std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
|
||||
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:
|
||||
class ValueGetter
|
||||
struct Resetter
|
||||
{
|
||||
public:
|
||||
ValueGetter(Statement &statement, int column)
|
||||
Resetter(StatementImplementation &statement)
|
||||
: statement(statement)
|
||||
{}
|
||||
|
||||
~Resetter()
|
||||
{
|
||||
statement.reset();
|
||||
}
|
||||
|
||||
StatementImplementation &statement;
|
||||
};
|
||||
|
||||
struct ValueGetter
|
||||
{
|
||||
ValueGetter(StatementImplementation &statement, int column)
|
||||
: statement(statement),
|
||||
column(column)
|
||||
{}
|
||||
@@ -300,7 +332,7 @@ private:
|
||||
return statement.fetchPathStringValue(column);
|
||||
}
|
||||
|
||||
Statement &statement;
|
||||
StatementImplementation &statement;
|
||||
int column;
|
||||
};
|
||||
|
||||
@@ -335,26 +367,26 @@ private:
|
||||
template<typename ValueType>
|
||||
void bindValuesByIndex(int index, const ValueType &value)
|
||||
{
|
||||
bind(index, value);
|
||||
BaseStatement::bind(index, value);
|
||||
}
|
||||
|
||||
template<typename ValueType, typename... ValueTypes>
|
||||
void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values)
|
||||
{
|
||||
bind(index, value);
|
||||
BaseStatement::bind(index, value);
|
||||
bindValuesByIndex(index + 1, values...);
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
void bindValuesByName(Utils::SmallStringView name, const ValueType &value)
|
||||
{
|
||||
bind(bindingIndexForName(name), value);
|
||||
BaseStatement::bind(BaseStatement::bindingIndexForName(name), value);
|
||||
}
|
||||
|
||||
template<typename ValueType, typename... ValueTypes>
|
||||
void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values)
|
||||
{
|
||||
bind(bindingIndexForName(name), value);
|
||||
BaseStatement::bind(BaseStatement::bindingIndexForName(name), value);
|
||||
bindValuesByName(values...);
|
||||
}
|
||||
|
||||
@@ -371,30 +403,6 @@ private:
|
||||
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
|
@@ -28,7 +28,7 @@
|
||||
#include "sqliteexception.h"
|
||||
#include "sqlitereadstatement.h"
|
||||
#include "sqlitereadwritestatement.h"
|
||||
#include "sqlitestatement.h"
|
||||
#include "sqlitebasestatement.h"
|
||||
#include "sqlitewritestatement.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
@@ -125,10 +125,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class WrongBingingName : public Exception
|
||||
class WrongBindingName : public Exception
|
||||
{
|
||||
public:
|
||||
WrongBingingName(const char *whatErrorHasHappen)
|
||||
WrongBindingName(const char *whatErrorHasHappen)
|
||||
: Exception(whatErrorHasHappen)
|
||||
{
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ namespace Sqlite {
|
||||
|
||||
ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement,
|
||||
Database &database)
|
||||
: Statement(sqlStatement, database)
|
||||
: StatementImplementation(sqlStatement, database)
|
||||
{
|
||||
checkIsReadOnlyStatement();
|
||||
}
|
||||
|
@@ -25,19 +25,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sqlitestatement.h"
|
||||
#include "sqlitebasestatement.h"
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
class SQLITE_EXPORT ReadStatement final : private Statement
|
||||
class SQLITE_EXPORT ReadStatement final : protected StatementImplementation<BaseStatement>
|
||||
{
|
||||
public:
|
||||
explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database);
|
||||
|
||||
using Statement::value;
|
||||
using Statement::values;
|
||||
using Statement::toValue;
|
||||
using Statement::database;
|
||||
using StatementImplementation::value;
|
||||
using StatementImplementation::values;
|
||||
using StatementImplementation::toValue;
|
||||
|
||||
protected:
|
||||
void checkIsReadOnlyStatement();
|
||||
|
@@ -29,7 +29,7 @@ namespace Sqlite {
|
||||
|
||||
ReadWriteStatement::ReadWriteStatement(Utils::SmallStringView sqlStatement,
|
||||
Database &database)
|
||||
: Statement(sqlStatement, database)
|
||||
: StatementImplementation(sqlStatement, database)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -25,24 +25,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sqlitestatement.h"
|
||||
#include "sqlitebasestatement.h"
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
class SQLITE_EXPORT ReadWriteStatement final : private Statement
|
||||
class SQLITE_EXPORT ReadWriteStatement final : protected StatementImplementation<BaseStatement>
|
||||
{
|
||||
friend class DatabaseBackend;
|
||||
|
||||
public:
|
||||
ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database);
|
||||
|
||||
using Statement::execute;
|
||||
using Statement::value;
|
||||
using Statement::values;
|
||||
using Statement::toValue;
|
||||
using Statement::database;
|
||||
using Statement::write;
|
||||
using Statement::writeNamed;
|
||||
using StatementImplementation::execute;
|
||||
using StatementImplementation::value;
|
||||
using StatementImplementation::values;
|
||||
using StatementImplementation::toValue;
|
||||
using StatementImplementation::write;
|
||||
using StatementImplementation::writeNamed;
|
||||
};
|
||||
|
||||
} // namespace Sqlite
|
||||
|
@@ -29,7 +29,7 @@ namespace Sqlite {
|
||||
|
||||
WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement,
|
||||
Database &database)
|
||||
: Statement(sqlStatement, database)
|
||||
: StatementImplementation(sqlStatement, database)
|
||||
{
|
||||
checkIsWritableStatement();
|
||||
}
|
||||
|
@@ -25,19 +25,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sqlitestatement.h"
|
||||
#include "sqlitebasestatement.h"
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
class SQLITE_EXPORT WriteStatement : private Statement
|
||||
class SQLITE_EXPORT WriteStatement : protected StatementImplementation<BaseStatement>
|
||||
{
|
||||
public:
|
||||
explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database);
|
||||
|
||||
using Statement::execute;
|
||||
using Statement::database;
|
||||
using Statement::write;
|
||||
using Statement::writeNamed;
|
||||
using StatementImplementation::execute;
|
||||
using StatementImplementation::database;
|
||||
using StatementImplementation::write;
|
||||
using StatementImplementation::writeNamed;
|
||||
|
||||
protected:
|
||||
void checkIsWritableStatement();
|
||||
|
@@ -145,25 +145,7 @@ public:
|
||||
BasicSmallString(std::initializer_list<Utils::SmallStringView> list)
|
||||
: m_data(Internal::StringDataLayout<Size>())
|
||||
{
|
||||
std::size_t size = std::accumulate(list.begin(),
|
||||
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;
|
||||
appendInitializerList(list, 0);
|
||||
}
|
||||
|
||||
~BasicSmallString() noexcept
|
||||
@@ -478,6 +460,13 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicSmallString &operator+=(std::initializer_list<SmallStringView> list)
|
||||
{
|
||||
appendInitializerList(list, size());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void replace(SmallStringView fromText, SmallStringView toText)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_data.allocated.data.pointer[size] = 0;
|
||||
|
@@ -193,15 +193,16 @@ inline
|
||||
int reverse_memcmp(const char *first, const char *second, size_t n)
|
||||
{
|
||||
|
||||
const char *currentFirst = first + n;
|
||||
const char *currentSecond = second + n;
|
||||
const char *currentFirst = first + n - 1;
|
||||
const char *currentSecond = second + n - 1;
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
// If the current characters differ, return an appropriately signed
|
||||
// value; otherwise, keep searching backwards
|
||||
if (*currentFirst != *currentSecond)
|
||||
return *currentFirst - *currentSecond;
|
||||
int difference = *currentFirst - *currentSecond;
|
||||
if (difference != 0)
|
||||
return difference;
|
||||
|
||||
--currentFirst;
|
||||
--currentSecond;
|
||||
|
@@ -33,8 +33,15 @@
|
||||
#include <coreplugin/find/searchresultwindow.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <filepathcaching.h>
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
namespace ClangRefactoring {
|
||||
|
||||
namespace {
|
||||
@@ -54,9 +61,12 @@ class ClangRefactoringPluginData
|
||||
{
|
||||
using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater<ClangPchManager::ProjectUpdater>;
|
||||
public:
|
||||
Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
ClangBackEnd::FilePathCaching filePathCache{database};
|
||||
RefactoringClient refactoringClient;
|
||||
ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient};
|
||||
RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient};
|
||||
RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient, filePathCache};
|
||||
QtCreatorSearch qtCreatorSearch{*Core::SearchResultWindow::instance()};
|
||||
QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(),
|
||||
qtCreatorSearch,
|
||||
|
@@ -40,14 +40,9 @@ public:
|
||||
{}
|
||||
Database &database;
|
||||
ReadStatement selectLocationsForSymbolLocation{
|
||||
"SELECT sourceId, line, column FROM locations WHERE symbolId = "
|
||||
" (SELECT symbolId FROM locations WHERE sourceId="
|
||||
" (SELECT sourceId FROM sources WHERE sourcePath =?)"
|
||||
" AND line=? AND column=?) "
|
||||
"SELECT directoryId, sourceId, line, column FROM locations JOIN sources USING(sourceId) WHERE symbolId = "
|
||||
" (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND 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};
|
||||
};
|
||||
|
||||
|
@@ -28,8 +28,9 @@
|
||||
#include "clangqueryhighlighter.h"
|
||||
#include "clangqueryexamplehighlighter.h"
|
||||
|
||||
#include <refactoringconnectionclient.h>
|
||||
#include <clangrefactoringmessages.h>
|
||||
#include <filepathcachinginterface.h>
|
||||
#include <refactoringconnectionclient.h>
|
||||
|
||||
namespace ClangRefactoring {
|
||||
|
||||
@@ -122,38 +123,17 @@ void RefactoringClient::setRefactoringConnectionClient(
|
||||
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)
|
||||
{
|
||||
auto filePaths = convertFilePaths(sourceRanges.filePaths());
|
||||
|
||||
for (const auto &sourceRangeWithText : sourceRanges.sourceRangeWithTextContainers())
|
||||
addSearchResult(sourceRangeWithText, filePaths);
|
||||
addSearchResult(sourceRangeWithText);
|
||||
}
|
||||
|
||||
void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText,
|
||||
std::unordered_map<uint, QString> &filePaths)
|
||||
void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText)
|
||||
{
|
||||
m_searchHandle->addResult(filePaths[sourceRangeWithText.fileHash()],
|
||||
auto &filePathCache = m_refactoringEngine->filePathCache();
|
||||
|
||||
m_searchHandle->addResult(QString(filePathCache.filePath(sourceRangeWithText.filePathId()).path()),
|
||||
QString(sourceRangeWithText.text()),
|
||||
{{int(sourceRangeWithText.start().line()),
|
||||
int(sourceRangeWithText.start().column() - 1),
|
||||
|
@@ -66,9 +66,6 @@ public:
|
||||
|
||||
bool hasValidLocalRenamingCallback() const;
|
||||
|
||||
static std::unordered_map<uint, QString> convertFilePaths(
|
||||
const std::unordered_map<uint, ClangBackEnd::FilePath> &filePaths);
|
||||
|
||||
void setExpectedResultCount(uint count);
|
||||
uint expectedResultCount() const;
|
||||
uint resultCounter() const;
|
||||
@@ -76,8 +73,7 @@ public:
|
||||
void setRefactoringConnectionClient(ClangBackEnd::RefactoringConnectionClient *connectionClient);
|
||||
|
||||
unittest_public:
|
||||
void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange,
|
||||
std::unordered_map<uint, QString> &filePaths);
|
||||
void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange);
|
||||
|
||||
private:
|
||||
void addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges);
|
||||
|
@@ -46,9 +46,11 @@ namespace ClangRefactoring {
|
||||
using ClangBackEnd::RequestSourceLocationsForRenamingMessage;
|
||||
|
||||
RefactoringEngine::RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server,
|
||||
ClangBackEnd::RefactoringClientInterface &client)
|
||||
: server(server),
|
||||
client(client)
|
||||
ClangBackEnd::RefactoringClientInterface &client,
|
||||
ClangBackEnd::FilePathCachingInterface &filePathCache)
|
||||
: m_server(server),
|
||||
m_client(client),
|
||||
m_filePathCache(filePathCache)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -60,7 +62,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
|
||||
|
||||
setUsable(false);
|
||||
|
||||
client.setLocalRenamingCallback(std::move(renameSymbolsCallback));
|
||||
m_client.setLocalRenamingCallback(std::move(renameSymbolsCallback));
|
||||
|
||||
QString filePath = data.filePath().toString();
|
||||
QTextCursor textCursor = data.cursor();
|
||||
@@ -79,7 +81,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
|
||||
textCursor.document()->revision());
|
||||
|
||||
|
||||
server.requestSourceLocationsForRenamingMessage(std::move(message));
|
||||
m_server.requestSourceLocationsForRenamingMessage(std::move(message));
|
||||
}
|
||||
|
||||
void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
|
||||
@@ -89,12 +91,12 @@ void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
|
||||
|
||||
bool RefactoringEngine::isUsable() const
|
||||
{
|
||||
return server.isUsable();
|
||||
return m_server.isUsable();
|
||||
}
|
||||
|
||||
void RefactoringEngine::setUsable(bool isUsable)
|
||||
{
|
||||
server.setUsable(isUsable);
|
||||
m_server.setUsable(isUsable);
|
||||
}
|
||||
|
||||
} // namespace ClangRefactoring
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
#include <cpptools/refactoringengineinterface.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
@@ -37,8 +39,10 @@ namespace ClangRefactoring {
|
||||
class RefactoringEngine : public CppTools::RefactoringEngineInterface
|
||||
{
|
||||
public:
|
||||
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server,
|
||||
ClangBackEnd::RefactoringClientInterface &client);
|
||||
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &m_server,
|
||||
ClangBackEnd::RefactoringClientInterface &m_client,
|
||||
ClangBackEnd::FilePathCachingInterface &filePathCache);
|
||||
|
||||
void startLocalRenaming(const CppTools::CursorInEditor &data,
|
||||
CppTools::ProjectPart *projectPart,
|
||||
RenameCallback &&renameSymbolsCallback) override;
|
||||
@@ -47,9 +51,15 @@ public:
|
||||
bool isUsable() const override;
|
||||
void setUsable(bool isUsable);
|
||||
|
||||
ClangBackEnd::FilePathCachingInterface &filePathCache()
|
||||
{
|
||||
return m_filePathCache;
|
||||
}
|
||||
|
||||
private:
|
||||
ClangBackEnd::RefactoringServerInterface &server;
|
||||
ClangBackEnd::RefactoringClientInterface &client;
|
||||
ClangBackEnd::RefactoringServerInterface &m_server;
|
||||
ClangBackEnd::RefactoringClientInterface &m_client;
|
||||
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
} // namespace ClangRefactoring
|
||||
|
@@ -27,39 +27,26 @@
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <filepathid.h>
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ClangRefactoring {
|
||||
|
||||
class SourceLocations
|
||||
struct SourceLocation
|
||||
{
|
||||
public:
|
||||
struct Location
|
||||
{
|
||||
Location(qint64 sourceId, qint64 line, qint64 column)
|
||||
: sourceId(sourceId), line(line), column(column)
|
||||
SourceLocation(ClangBackEnd::FilePathId filePathId, int line, int column)
|
||||
: filePathId(filePathId), line(line), column(column)
|
||||
{}
|
||||
SourceLocation(int directoryId, int sourceId, int line, int column)
|
||||
: filePathId{directoryId, sourceId}, line(line), column(column)
|
||||
{}
|
||||
|
||||
qint64 sourceId;
|
||||
qint64 line;
|
||||
qint64 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;
|
||||
ClangBackEnd::FilePathId filePathId;
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
using SourceLocations = std::vector<SourceLocation>;
|
||||
|
||||
} // namespace ClangRefactoring
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <filepathid.h>
|
||||
#include <sourcelocations.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -39,68 +40,20 @@ class SymbolQuery
|
||||
using ReadStatement = typename StatementFactory::ReadStatementType;
|
||||
|
||||
public:
|
||||
using Location = SourceLocations::Location;
|
||||
using Source = SourceLocations::Source;
|
||||
|
||||
SymbolQuery(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;
|
||||
|
||||
const std::size_t reserveSize = 128;
|
||||
|
||||
auto locations = locationsStatement.template values<Location, 3>(
|
||||
reserveSize,
|
||||
filePath,
|
||||
return locationsStatement.template values<SourceLocation, 4>(reserveSize,
|
||||
filePathId.fileNameId,
|
||||
line,
|
||||
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:
|
||||
|
@@ -31,7 +31,9 @@
|
||||
#include <pchmanagerserver.h>
|
||||
#include <pchmanagerclientproxy.h>
|
||||
#include <projectparts.h>
|
||||
#include <stringcache.h>
|
||||
#include <filepathcaching.h>
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QCoreApplication>
|
||||
@@ -103,15 +105,16 @@ int main(int argc, char *argv[])
|
||||
|
||||
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);
|
||||
ApplicationEnvironment environment;
|
||||
PchGenerator<QProcess> pchGenerator(environment);
|
||||
PchCreator pchCreator(environment, filePathCache);
|
||||
pchCreator.setGenerator(&pchGenerator);
|
||||
ProjectParts projectParts;
|
||||
PchManagerServer clangPchManagerServer(filePathCache,
|
||||
includeWatcher,
|
||||
PchManagerServer clangPchManagerServer(includeWatcher,
|
||||
pchCreator,
|
||||
projectParts);
|
||||
includeWatcher.setNotifier(&clangPchManagerServer);
|
||||
|
@@ -28,7 +28,9 @@
|
||||
#include "clangpathwatcherinterface.h"
|
||||
#include "clangpathwatchernotifier.h"
|
||||
#include "changedfilepathcompressor.h"
|
||||
#include "stringcache.h"
|
||||
|
||||
#include <filepathcachinginterface.h>
|
||||
#include <stringcache.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
@@ -37,34 +39,34 @@ namespace ClangBackEnd {
|
||||
class WatcherEntry
|
||||
{
|
||||
public:
|
||||
FilePathIndex id;
|
||||
FilePathIndex path;
|
||||
int id;
|
||||
FilePathId pathId;
|
||||
|
||||
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)
|
||||
{
|
||||
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 IdCache = StringCache<Utils::SmallString,
|
||||
FilePathIndex,
|
||||
int,
|
||||
NonLockingMutex,
|
||||
decltype(&Utils::compare),
|
||||
Utils::compare>;
|
||||
@@ -74,7 +76,7 @@ template <typename FileSystemWatcher,
|
||||
class ClangPathWatcher : public ClangPathWatcherInterface
|
||||
{
|
||||
public:
|
||||
ClangPathWatcher(FilePathCache<> &pathCache,
|
||||
ClangPathWatcher(FilePathCachingInterface &pathCache,
|
||||
ClangPathWatcherNotifier *notifier=nullptr)
|
||||
: m_pathCache(pathCache),
|
||||
m_notifier(notifier)
|
||||
@@ -136,9 +138,9 @@ unittest_public:
|
||||
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());
|
||||
|
||||
@@ -148,33 +150,33 @@ unittest_public:
|
||||
std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
std::pair<WatcherEntries,std::vector<FilePathIndex>>
|
||||
std::pair<WatcherEntries, std::vector<int>>
|
||||
convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
|
||||
{
|
||||
WatcherEntries entries;
|
||||
entries.reserve(sizeOfIdPaths(idPaths));
|
||||
std::vector<FilePathIndex> ids;
|
||||
std::vector<int> ids;
|
||||
ids.reserve(ids.size());
|
||||
|
||||
auto outputIterator = std::back_inserter(entries);
|
||||
|
||||
for (const IdPaths &idPath : idPaths)
|
||||
{
|
||||
FilePathIndex id = m_idCache.stringId(idPath.id);
|
||||
int id = m_idCache.stringId(idPath.id);
|
||||
|
||||
ids.push_back(id);
|
||||
|
||||
outputIterator = std::transform(idPath.paths.begin(),
|
||||
idPath.paths.end(),
|
||||
outputIterator = std::transform(idPath.filePathIds.begin(),
|
||||
idPath.filePathIds.end(),
|
||||
outputIterator,
|
||||
[&] (uint path) { return WatcherEntry{id, path}; });
|
||||
[&] (FilePathId pathId) { return WatcherEntry{id, pathId}; });
|
||||
}
|
||||
|
||||
std::sort(entries.begin(), entries.end());
|
||||
@@ -196,7 +198,7 @@ unittest_public:
|
||||
}
|
||||
|
||||
void removeUnusedEntries(const WatcherEntries &entries,
|
||||
const std::vector<FilePathIndex> &ids)
|
||||
const std::vector<int> &ids)
|
||||
{
|
||||
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
|
||||
|
||||
@@ -222,7 +224,9 @@ unittest_public:
|
||||
std::transform(watcherEntries.begin(),
|
||||
watcherEntries.end(),
|
||||
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;
|
||||
}
|
||||
@@ -252,7 +256,7 @@ unittest_public:
|
||||
WatcherEntries notWatchedPaths(const WatcherEntries &entries) const
|
||||
{
|
||||
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
|
||||
return first.path < second.path;
|
||||
return first.pathId < second.pathId;
|
||||
};
|
||||
|
||||
return notWatchedEntries(entries, compare);
|
||||
@@ -278,7 +282,7 @@ unittest_public:
|
||||
|
||||
WatcherEntries notAnymoreWatchedEntriesWithIds(
|
||||
const WatcherEntries &newEntries,
|
||||
const std::vector<FilePathIndex> &ids) const
|
||||
const std::vector<int> &ids) const
|
||||
{
|
||||
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
|
||||
|
||||
@@ -313,7 +317,7 @@ unittest_public:
|
||||
WatcherEntries uniqueEntries;
|
||||
|
||||
auto compare = [] (const WatcherEntry &first, const WatcherEntry &second) {
|
||||
return first.path == second.path;
|
||||
return first.pathId == second.pathId;
|
||||
};
|
||||
|
||||
std::unique_copy(pathEntries.begin(),
|
||||
@@ -334,7 +338,7 @@ unittest_public:
|
||||
return m_watchedEntries;
|
||||
}
|
||||
|
||||
WatcherEntries removeIdsFromWatchedEntries(const std::vector<FilePathIndex> &ids)
|
||||
WatcherEntries removeIdsFromWatchedEntries(const std::vector<int> &ids)
|
||||
{
|
||||
|
||||
auto keep = [&] (const WatcherEntry &entry) {
|
||||
@@ -374,11 +378,11 @@ unittest_public:
|
||||
|
||||
WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths)
|
||||
{
|
||||
std::vector<FilePathIndex> pathIds = m_pathCache.stringIds(filePaths);
|
||||
FilePathIds pathIds = m_pathCache.filePathIds(filePaths);
|
||||
|
||||
WatcherEntries foundEntries;
|
||||
|
||||
for (uint pathId : pathIds) {
|
||||
for (FilePathId pathId : pathIds) {
|
||||
auto range = std::equal_range(m_watchedEntries.begin(), m_watchedEntries.end(), pathId);
|
||||
foundEntries.insert(foundEntries.end(), range.first, range.second);
|
||||
}
|
||||
@@ -420,7 +424,7 @@ unittest_public:
|
||||
}
|
||||
}
|
||||
|
||||
FilePathCache<> &pathCache()
|
||||
FilePathCachingInterface &pathCache()
|
||||
{
|
||||
return m_pathCache;
|
||||
}
|
||||
@@ -435,10 +439,8 @@ private:
|
||||
WatcherEntries m_watchedEntries;
|
||||
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor;
|
||||
FileSystemWatcher m_fileSystemWatcher;
|
||||
FilePathCache<> &m_pathCache;
|
||||
FilePathCachingInterface &m_pathCache;
|
||||
ClangPathWatcherNotifier *m_notifier;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry);
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -2,9 +2,7 @@ INCLUDEPATH += $$PWD
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/pchmanagerserver.cpp \
|
||||
$$PWD/clangpathwatcher.cpp \
|
||||
$$PWD/projectparts.cpp \
|
||||
$$PWD/idpaths.cpp \
|
||||
$$PWD/pchcreatorinterface.cpp \
|
||||
$$PWD/clangpathwatcherinterface.cpp \
|
||||
$$PWD/projectpartsinterface.cpp \
|
||||
|
@@ -25,10 +25,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stringcache.h"
|
||||
|
||||
#include <collectincludespreprocessorcallbacks.h>
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <filepathid.h>
|
||||
|
||||
#include <clang/Frontend/FrontendActions.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
@@ -38,10 +39,10 @@ namespace ClangBackEnd {
|
||||
class CollectIncludesAction final : public clang::PreprocessOnlyAction
|
||||
{
|
||||
public:
|
||||
CollectIncludesAction(FilePathIndices &includeIds,
|
||||
FilePathCache<> &filePathCache,
|
||||
FilePathIndices &excludedIncludeUID,
|
||||
FilePathIndices &alreadyIncludedFileUIDs)
|
||||
CollectIncludesAction(FilePathIds &includeIds,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
std::vector<uint> &excludedIncludeUID,
|
||||
std::vector<uint> &alreadyIncludedFileUIDs)
|
||||
: m_includeIds(includeIds),
|
||||
m_filePathCache(filePathCache),
|
||||
m_excludedIncludeUID(excludedIncludeUID),
|
||||
@@ -78,10 +79,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
FilePathIndices &m_includeIds;
|
||||
FilePathCache<> &m_filePathCache;
|
||||
FilePathIndices &m_excludedIncludeUID;
|
||||
FilePathIndices &m_alreadyIncludedFileUIDs;
|
||||
FilePathIds &m_includeIds;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
std::vector<uint> &m_excludedIncludeUID;
|
||||
std::vector<uint> &m_alreadyIncludedFileUIDs;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -25,7 +25,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stringcache.h"
|
||||
#include <filepathcachinginterface.h>
|
||||
#include <filepathid.h>
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
#include <clang/Lex/MacroInfo.h>
|
||||
@@ -33,8 +36,6 @@
|
||||
#include <clang/Lex/PPCallbacks.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QTemporaryDir>
|
||||
@@ -47,10 +48,10 @@ class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks
|
||||
{
|
||||
public:
|
||||
CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch,
|
||||
std::vector<FilePathIndex> &includeIds,
|
||||
FilePathCache<> &filePathCache,
|
||||
const std::vector<FilePathIndex> &excludedIncludeUID,
|
||||
std::vector<FilePathIndex> &alreadyIncludedFileUIDs)
|
||||
FilePathIds &includeIds,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
const std::vector<uint> &excludedIncludeUID,
|
||||
std::vector<uint> &alreadyIncludedFileUIDs)
|
||||
: m_headerSearch(headerSearch),
|
||||
m_includeIds(includeIds),
|
||||
m_filePathCache(filePathCache),
|
||||
@@ -78,7 +79,7 @@ public:
|
||||
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
|
||||
Utils::PathString filePath = filePathFromFile(file);
|
||||
if (!filePath.isEmpty()) {
|
||||
FilePathIndex includeId = m_filePathCache.stringId(filePath);
|
||||
FilePathId includeId = m_filePathCache.filePathId(filePath);
|
||||
m_includeIds.emplace_back(includeId);
|
||||
}
|
||||
}
|
||||
@@ -132,7 +133,7 @@ public:
|
||||
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(),
|
||||
m_alreadyIncludedFileUIDs.end(),
|
||||
@@ -174,10 +175,10 @@ public:
|
||||
|
||||
private:
|
||||
clang::HeaderSearch &m_headerSearch;
|
||||
std::vector<FilePathIndex> &m_includeIds;
|
||||
FilePathCache<> &m_filePathCache;
|
||||
const std::vector<FilePathIndex> &m_excludedIncludeUID;
|
||||
std::vector<FilePathIndex> &m_alreadyIncludedFileUIDs;
|
||||
FilePathIds &m_includeIds;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
const std::vector<uint> &m_excludedIncludeUID;
|
||||
std::vector<uint> &m_alreadyIncludedFileUIDs;
|
||||
bool m_skipInclude = false;
|
||||
};
|
||||
|
||||
|
@@ -25,10 +25,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stringcache.h"
|
||||
|
||||
#include "collectincludesaction.h"
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <filepathid.h>
|
||||
|
||||
#include <clang/Tooling/Tooling.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
@@ -36,8 +37,8 @@ namespace ClangBackEnd {
|
||||
class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory
|
||||
{
|
||||
public:
|
||||
CollectIncludesToolAction(std::vector<FilePathIndex> &includeIds,
|
||||
FilePathCache<> &filePathCache,
|
||||
CollectIncludesToolAction(FilePathIds &includeIds,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
const Utils::PathStringVector &excludedIncludes)
|
||||
: m_includeIds(includeIds),
|
||||
m_filePathCache(filePathCache),
|
||||
@@ -72,9 +73,9 @@ public:
|
||||
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());
|
||||
|
||||
for (const Utils::PathString &filePath : m_excludedIncludes) {
|
||||
@@ -90,10 +91,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<FilePathIndex> m_alreadyIncludedFileUIDs;
|
||||
std::vector<FilePathIndex> m_excludedIncludeUIDs;
|
||||
std::vector<FilePathIndex> &m_includeIds;
|
||||
FilePathCache<> &m_filePathCache;
|
||||
std::vector<uint> m_alreadyIncludedFileUIDs;
|
||||
std::vector<uint> m_excludedIncludeUIDs;
|
||||
FilePathIds &m_includeIds;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
const Utils::PathStringVector &m_excludedIncludes;
|
||||
};
|
||||
|
||||
|
@@ -27,9 +27,7 @@
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include <stringcachefwd.h>
|
||||
#include <filepathid.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
@@ -37,14 +35,12 @@ class IdPaths
|
||||
{
|
||||
public:
|
||||
Utils::SmallString id;
|
||||
std::vector<FilePathIndex> paths;
|
||||
FilePathIds filePathIds;
|
||||
|
||||
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
|
||||
|
@@ -33,7 +33,7 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
IncludeCollector::IncludeCollector(FilePathCache<> &filePathCache)
|
||||
IncludeCollector::IncludeCollector(FilePathCachingInterface &filePathCache)
|
||||
: m_filePathCache(filePathCache)
|
||||
{
|
||||
}
|
||||
@@ -69,7 +69,7 @@ void IncludeCollector::setExcludedIncludes(Utils::PathStringVector &&excludedInc
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<FilePathIndex> IncludeCollector::takeIncludeIds()
|
||||
FilePathIds IncludeCollector::takeIncludeIds()
|
||||
{
|
||||
std::sort(m_includeIds.begin(), m_includeIds.end());
|
||||
|
||||
|
@@ -25,28 +25,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stringcache.h"
|
||||
|
||||
#include <clangtool.h>
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class IncludeCollector : public ClangTool
|
||||
{
|
||||
public:
|
||||
IncludeCollector(FilePathCache<> &filePathCache);
|
||||
IncludeCollector(FilePathCachingInterface &filePathCache);
|
||||
|
||||
void collectIncludes();
|
||||
|
||||
void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes);
|
||||
|
||||
std::vector<FilePathIndex> takeIncludeIds();
|
||||
FilePathIds takeIncludeIds();
|
||||
|
||||
private:
|
||||
Utils::PathStringVector m_excludedIncludes;
|
||||
std::vector<FilePathIndex> m_includeIds;
|
||||
FilePathIds m_includeIds;
|
||||
Utils::SmallStringVector m_directories;
|
||||
FilePathCache<> &m_filePathCache;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "includecollector.h"
|
||||
#include "pchnotcreatederror.h"
|
||||
|
||||
#include <filepathcachinginterface.h>
|
||||
#include <projectpartpch.h>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
@@ -37,7 +38,7 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache)
|
||||
PchCreator::PchCreator(Environment &environment, FilePathCachingInterface &filePathCache)
|
||||
: m_environment(environment),
|
||||
m_filePathCache(filePathCache)
|
||||
{
|
||||
@@ -45,7 +46,7 @@ PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache)
|
||||
|
||||
PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts,
|
||||
Environment &environment,
|
||||
FilePathCache<> &filePathCache,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
PchGeneratorInterface *pchGenerator,
|
||||
V2::FileContainers &&generatedFiles)
|
||||
: m_projectParts(std::move(projectsParts)),
|
||||
@@ -239,7 +240,7 @@ Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() cons
|
||||
return compilerArguments;
|
||||
}
|
||||
|
||||
std::vector<FilePathIndex> PchCreator::generateGlobalPchIncludeIds() const
|
||||
FilePathIds PchCreator::generateGlobalPchIncludeIds() const
|
||||
{
|
||||
IncludeCollector collector(m_filePathCache);
|
||||
|
||||
@@ -256,7 +257,7 @@ std::vector<FilePathIndex> PchCreator::generateGlobalPchIncludeIds() const
|
||||
|
||||
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) {
|
||||
return size + include.size();
|
||||
@@ -266,20 +267,16 @@ std::size_t contentSize(const std::vector<Utils::PathString> &includes)
|
||||
}
|
||||
}
|
||||
|
||||
Utils::SmallString PchCreator::generatePchIncludeFileContent(
|
||||
const std::vector<FilePathIndex> &includeIds) const
|
||||
Utils::SmallString PchCreator::generatePchIncludeFileContent(const FilePathIds &includeIds) const
|
||||
{
|
||||
Utils::SmallString fileContent;
|
||||
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));
|
||||
|
||||
for (const Utils::PathString &include : includes) {
|
||||
fileContent += "#include \"";
|
||||
fileContent += include;
|
||||
fileContent += "\"\n";
|
||||
}
|
||||
for (const Utils::PathString &include : includes)
|
||||
fileContent += {"#include \"", include, "\"\n"};
|
||||
|
||||
return fileContent;
|
||||
}
|
||||
@@ -461,7 +458,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaderAndSourcePaths(
|
||||
return includeAndSources;
|
||||
}
|
||||
|
||||
std::vector<FilePathIndex> PchCreator::generateProjectPartPchIncludes(
|
||||
FilePathIds PchCreator::generateProjectPartPchIncludes(
|
||||
const V2::ProjectPartContainer &projectPart) const
|
||||
{
|
||||
Utils::SmallString jointedFileContent = generateProjectPartHeaderAndSourcesContent(projectPart);
|
||||
|
@@ -28,9 +28,9 @@
|
||||
#include "pchcreatorinterface.h"
|
||||
|
||||
#include "pchgeneratorinterface.h"
|
||||
#include "stringcache.h"
|
||||
#include "idpaths.h"
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <projectpartpch.h>
|
||||
#include <projectpartcontainerv2.h>
|
||||
|
||||
@@ -48,10 +48,10 @@ class PchCreator final : public PchCreatorInterface
|
||||
{
|
||||
public:
|
||||
PchCreator(Environment &environment,
|
||||
FilePathCache<> &filePathCache);
|
||||
FilePathCachingInterface &filePathCache);
|
||||
PchCreator(V2::ProjectPartContainers &&projectsParts,
|
||||
Environment &environment,
|
||||
FilePathCache<> &filePathCache,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
PchGeneratorInterface *pchGenerator,
|
||||
V2::FileContainers &&generatedFiles);
|
||||
|
||||
@@ -70,9 +70,9 @@ unittest_public:
|
||||
Utils::SmallStringVector generateGlobalPchCompilerArguments() 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;
|
||||
std::unique_ptr<QFile> generateGlobalPchHeaderFile();
|
||||
void generatePch(Utils::SmallStringVector &&commandLineArguments,
|
||||
@@ -97,7 +97,7 @@ unittest_public:
|
||||
const V2::ProjectPartContainer &projectPart);
|
||||
static Utils::PathStringVector generateProjectPartHeaderAndSourcePaths(
|
||||
const V2::ProjectPartContainer &projectPart);
|
||||
std::vector<FilePathIndex> generateProjectPartPchIncludes(
|
||||
FilePathIds generateProjectPartPchIncludes(
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
Utils::SmallString generateProjectPathPchHeaderFilePath(
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
@@ -127,7 +127,7 @@ private:
|
||||
std::vector<ProjectPartPch> m_projectPartPchs;
|
||||
std::vector<IdPaths> m_projectsIncludeIds;
|
||||
Environment &m_environment;
|
||||
FilePathCache<> &m_filePathCache;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
PchGeneratorInterface *m_pchGenerator = nullptr;
|
||||
};
|
||||
|
||||
|
@@ -36,12 +36,10 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
PchManagerServer::PchManagerServer(FilePathCache<> &filePathCache,
|
||||
ClangPathWatcherInterface &fileSystemWatcher,
|
||||
PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
|
||||
PchCreatorInterface &pchCreator,
|
||||
ProjectPartsInterface &projectParts)
|
||||
: m_filePathCache(filePathCache),
|
||||
m_fileSystemWatcher(fileSystemWatcher),
|
||||
: m_fileSystemWatcher(fileSystemWatcher),
|
||||
m_pchCreator(pchCreator),
|
||||
m_projectParts(projectParts)
|
||||
{
|
||||
|
@@ -31,7 +31,6 @@
|
||||
#include "pchgeneratornotifierinterface.h"
|
||||
#include "pchmanagerserverinterface.h"
|
||||
#include "projectpartsinterface.h"
|
||||
#include "stringcache.h"
|
||||
|
||||
#include <ipcclientprovider.h>
|
||||
|
||||
@@ -46,8 +45,7 @@ class PchManagerServer : public PchManagerServerInterface,
|
||||
|
||||
{
|
||||
public:
|
||||
PchManagerServer(FilePathCache<> &filePathCache,
|
||||
ClangPathWatcherInterface &fileSystemWatcher,
|
||||
PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
|
||||
PchCreatorInterface &pchCreator,
|
||||
ProjectPartsInterface &projectParts);
|
||||
|
||||
@@ -60,7 +58,6 @@ public:
|
||||
void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override;
|
||||
|
||||
private:
|
||||
FilePathCache<> &m_filePathCache;
|
||||
ClangPathWatcherInterface &m_fileSystemWatcher;
|
||||
PchCreatorInterface &m_pchCreator;
|
||||
ProjectPartsInterface &m_projectParts;
|
||||
|
@@ -29,14 +29,15 @@
|
||||
#include <QDir>
|
||||
|
||||
#include <connectionserver.h>
|
||||
#include <stringcache.h>
|
||||
#include <filepathcaching.h>
|
||||
#include <refactoringserver.h>
|
||||
#include <refactoringclientproxy.h>
|
||||
#include <symbolindexing.h>
|
||||
|
||||
using ClangBackEnd::FilePathCache;
|
||||
using ClangBackEnd::FilePathCaching;
|
||||
using ClangBackEnd::RefactoringClientProxy;
|
||||
using ClangBackEnd::RefactoringServer;
|
||||
using ClangBackEnd::RefactoringDatabaseInitializer;
|
||||
using ClangBackEnd::ConnectionServer;
|
||||
using ClangBackEnd::SymbolIndexing;
|
||||
|
||||
@@ -69,8 +70,10 @@ try {
|
||||
|
||||
const QString connection = processArguments(application);
|
||||
|
||||
FilePathCache<std::mutex> filePathCache;
|
||||
SymbolIndexing symbolIndexing{filePathCache, Utils::PathString{QDir::tempPath() + "/symbol.db"}};
|
||||
Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}};
|
||||
RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
FilePathCaching filePathCache{database};
|
||||
SymbolIndexing symbolIndexing{database, filePathCache};
|
||||
RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache};
|
||||
ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection);
|
||||
connectionServer.start();
|
||||
|
@@ -54,16 +54,16 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
|
||||
}
|
||||
};
|
||||
|
||||
ClangQuery::ClangQuery(FilePathCache<std::mutex> &filePathCache,
|
||||
ClangQuery::ClangQuery(FilePathCachingInterface &filePathCache,
|
||||
Utils::SmallString &&query)
|
||||
: query(std::move(query)),
|
||||
filePathCache(filePathCache)
|
||||
: m_query(std::move(query)),
|
||||
m_filePathCache(filePathCache)
|
||||
{
|
||||
}
|
||||
|
||||
void ClangQuery::setQuery(Utils::SmallString &&query)
|
||||
{
|
||||
this->query = std::move(query);
|
||||
this->m_query = std::move(query);
|
||||
}
|
||||
|
||||
void ClangQuery::findLocations()
|
||||
@@ -78,7 +78,7 @@ void ClangQuery::findLocations()
|
||||
std::make_move_iterator(asts.end()),
|
||||
[&] (std::unique_ptr<clang::ASTUnit> &&ast) {
|
||||
Diagnostics diagnostics;
|
||||
auto optionalMatcher = Parser::parseMatcherExpression({query.data(), query.size()},
|
||||
auto optionalMatcher = Parser::parseMatcherExpression({m_query.data(), m_query.size()},
|
||||
nullptr,
|
||||
&diagnostics);
|
||||
parseDiagnostics(diagnostics);
|
||||
@@ -89,19 +89,19 @@ void ClangQuery::findLocations()
|
||||
|
||||
SourceRangesContainer ClangQuery::takeSourceRanges()
|
||||
{
|
||||
return std::move(sourceRangesContainer);
|
||||
return std::move(m_sourceRangesContainer);
|
||||
}
|
||||
|
||||
DynamicASTMatcherDiagnosticContainers ClangQuery::takeDiagnosticContainers()
|
||||
{
|
||||
return std::move(diagnosticContainers_);
|
||||
return std::move(m_diagnosticContainers_);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
V2::SourceRangeContainer convertToContainer(const clang::ast_matchers::dynamic::SourceRange sourceRange)
|
||||
{
|
||||
return V2::SourceRangeContainer(0,
|
||||
return V2::SourceRangeContainer({1, 0},
|
||||
sourceRange.Start.Line,
|
||||
sourceRange.Start.Column,
|
||||
0,
|
||||
@@ -159,8 +159,8 @@ void ClangQuery::parseDiagnostics(const clang::ast_matchers::dynamic::Diagnostic
|
||||
auto errors = diagnostics.errors();
|
||||
|
||||
for (const auto &errorContent : errors) {
|
||||
diagnosticContainers_.emplace_back();
|
||||
DynamicASTMatcherDiagnosticContainer &diagnosticContainer = diagnosticContainers_.back();
|
||||
m_diagnosticContainers_.emplace_back();
|
||||
DynamicASTMatcherDiagnosticContainer &diagnosticContainer = m_diagnosticContainers_.back();
|
||||
|
||||
for (const auto &message : errorContent.Messages) {
|
||||
diagnosticContainer.insertMessage(convertToContainer(message.Range),
|
||||
@@ -216,8 +216,8 @@ void ClangQuery::matchLocation(
|
||||
|
||||
SourceRangeExtractor extractor(ast->getSourceManager(),
|
||||
ast->getLangOpts(),
|
||||
filePathCache,
|
||||
sourceRangesContainer);
|
||||
m_filePathCache,
|
||||
m_sourceRangesContainer);
|
||||
extractor.addSourceRanges(sourceRanges);
|
||||
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include <sourcerangescontainer.h>
|
||||
#include <dynamicastmatcherdiagnosticcontainer.h>
|
||||
|
||||
#include <stringcache.h>
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
namespace clang {
|
||||
namespace ast_matchers {
|
||||
@@ -51,9 +51,9 @@ namespace ClangBackEnd {
|
||||
class ClangQuery : public ClangTool
|
||||
{
|
||||
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();
|
||||
|
||||
@@ -66,10 +66,10 @@ private:
|
||||
std::unique_ptr<clang::ASTUnit> ast);
|
||||
|
||||
private:
|
||||
SourceRangesContainer sourceRangesContainer;
|
||||
Utils::SmallString query;
|
||||
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_;
|
||||
FilePathCache<std::mutex> &filePathCache;
|
||||
SourceRangesContainer m_sourceRangesContainer;
|
||||
Utils::SmallString m_query;
|
||||
std::vector<DynamicASTMatcherDiagnosticContainer> m_diagnosticContainers_;
|
||||
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
ClangQueryGatherer::ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
|
||||
ClangQueryGatherer::ClangQueryGatherer(FilePathCachingInterface *filePathCache,
|
||||
std::vector<V2::FileContainer> &&sources,
|
||||
std::vector<V2::FileContainer> &&unsaved,
|
||||
Utils::SmallString &&query)
|
||||
@@ -43,7 +43,7 @@ ClangQueryGatherer::ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
|
||||
|
||||
SourceRangesForQueryMessage
|
||||
ClangQueryGatherer::createSourceRangesForSource(
|
||||
FilePathCache<std::mutex> *filePathCache,
|
||||
FilePathCachingInterface *filePathCache,
|
||||
V2::FileContainer &&source,
|
||||
const std::vector<V2::FileContainer> &unsaved,
|
||||
Utils::SmallString &&query)
|
||||
|
@@ -29,7 +29,7 @@
|
||||
|
||||
#include <sourcerangesforquerymessage.h>
|
||||
#include <filecontainerv2.h>
|
||||
#include <stringcache.h>
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
#include <future>
|
||||
|
||||
@@ -41,13 +41,13 @@ public:
|
||||
using Future = std::future<SourceRangesForQueryMessage>;
|
||||
|
||||
ClangQueryGatherer() = default;
|
||||
ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
|
||||
ClangQueryGatherer(FilePathCachingInterface *filePathCache,
|
||||
std::vector<V2::FileContainer> &&sources,
|
||||
std::vector<V2::FileContainer> &&unsaved,
|
||||
Utils::SmallString &&query);
|
||||
|
||||
static SourceRangesForQueryMessage createSourceRangesForSource(
|
||||
FilePathCache<std::mutex> *filePathCache,
|
||||
FilePathCachingInterface *filePathCache,
|
||||
V2::FileContainer &&source,
|
||||
const std::vector<V2::FileContainer> &unsaved,
|
||||
Utils::SmallString &&query);
|
||||
@@ -69,7 +69,7 @@ protected:
|
||||
std::vector<Future> finishedFutures();
|
||||
|
||||
private:
|
||||
FilePathCache<std::mutex> *m_filePathCache = nullptr;
|
||||
FilePathCachingInterface *m_filePathCache = nullptr;
|
||||
SourceRangeFilter m_sourceRangeFilter;
|
||||
std::vector<V2::FileContainer> m_sources;
|
||||
std::vector<V2::FileContainer> m_unsaved;
|
||||
|
@@ -57,5 +57,4 @@ HEADERS += \
|
||||
SOURCES += \
|
||||
$$PWD/sourcerangefilter.cpp \
|
||||
$$PWD/symbolindexer.cpp \
|
||||
$$PWD/symbolentry.cpp \
|
||||
$$PWD/sourcelocationentry.cpp
|
||||
$$PWD/symbolentry.cpp
|
||||
|
@@ -31,7 +31,7 @@
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <stringcachefwd.h>
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
#include <clang/Frontend/FrontendAction.h>
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace ClangBackEnd {
|
||||
class CollectSymbolsAction
|
||||
{
|
||||
public:
|
||||
CollectSymbolsAction(FilePathCache<std::mutex> &filePathCache)
|
||||
CollectSymbolsAction(FilePathCachingInterface &filePathCache)
|
||||
: m_filePathCache(filePathCache)
|
||||
{}
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
private:
|
||||
SymbolEntries m_symbolEntries;
|
||||
SourceLocationEntries m_sourceLocationEntries;
|
||||
FilePathCache<std::mutex> &m_filePathCache;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
|
||||
};
|
||||
|
||||
|
@@ -28,7 +28,7 @@
|
||||
#include "symbolentry.h"
|
||||
#include "sourcelocationentry.h"
|
||||
|
||||
#include <stringcache.h>
|
||||
#include <filepathcachinginterface.h>
|
||||
|
||||
#include <clang/AST/AST.h>
|
||||
#include <clang/AST/ASTContext.h>
|
||||
@@ -50,7 +50,7 @@ class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor<CollectSymbol
|
||||
public:
|
||||
CollectSymbolsASTVisitor(SymbolEntries &symbolEntries,
|
||||
SourceLocationEntries &sourceLocationEntries,
|
||||
FilePathCache<std::mutex> &filePathCache,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
const clang::SourceManager &sourceManager)
|
||||
: m_symbolEntries(symbolEntries),
|
||||
m_sourceLocationEntries(sourceLocationEntries),
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
FilePathIndex filePathId(clang::SourceLocation sourceLocation)
|
||||
FilePathId filePathId(clang::SourceLocation sourceLocation)
|
||||
{
|
||||
uint clangFileId = m_sourceManager.getFileID(sourceLocation).getHashValue();
|
||||
|
||||
@@ -111,11 +111,11 @@ public:
|
||||
|
||||
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)
|
||||
@@ -147,9 +147,9 @@ public:
|
||||
|
||||
private:
|
||||
SymbolEntries &m_symbolEntries;
|
||||
std::unordered_map<uint, FilePathIndex> m_filePathIndices;
|
||||
std::unordered_map<uint, FilePathId> m_filePathIndices;
|
||||
SourceLocationEntries &m_sourceLocationEntries;
|
||||
FilePathCache<std::mutex> &m_filePathCache;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
const clang::SourceManager &m_sourceManager;
|
||||
};
|
||||
|
||||
|
@@ -31,7 +31,7 @@
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/AST/ASTContext.h>
|
||||
|
||||
#include <stringcachefwd.h>
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
@@ -40,7 +40,7 @@ class CollectSymbolsConsumer : public clang::ASTConsumer
|
||||
public:
|
||||
CollectSymbolsConsumer(SymbolEntries &symbolEntries,
|
||||
SourceLocationEntries &sourceLocationEntries,
|
||||
FilePathCache<std::mutex> &filePathCache)
|
||||
FilePathCachingInterface &filePathCache)
|
||||
: m_symbolEntries(symbolEntries),
|
||||
m_sourceLocationEntries(sourceLocationEntries),
|
||||
m_filePathCache(filePathCache)
|
||||
@@ -69,6 +69,6 @@ public:
|
||||
private:
|
||||
SymbolEntries &m_symbolEntries;
|
||||
SourceLocationEntries &m_sourceLocationEntries;
|
||||
FilePathCache<std::mutex> &m_filePathCache;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
}
|
||||
|
@@ -48,9 +48,12 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
LocationSourceFileCallbacks::LocationSourceFileCallbacks(uint line, uint column)
|
||||
: line(line),
|
||||
column(column)
|
||||
LocationSourceFileCallbacks::LocationSourceFileCallbacks(uint line,
|
||||
uint 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();
|
||||
|
||||
macroPreprocessorCallbacks = new MacroPreprocessorCallbacks(sourceLocationsContainer,
|
||||
symbolName,
|
||||
m_macroPreprocessorCallbacks = new MacroPreprocessorCallbacks(m_sourceLocationsContainer,
|
||||
m_symbolName,
|
||||
preprocessor,
|
||||
line,
|
||||
column);
|
||||
m_filePathCache,
|
||||
m_line,
|
||||
m_column);
|
||||
|
||||
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks));
|
||||
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(m_macroPreprocessorCallbacks));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SourceLocationsContainer LocationSourceFileCallbacks::takeSourceLocations()
|
||||
{
|
||||
return std::move(sourceLocationsContainer);
|
||||
return std::move(m_sourceLocationsContainer);
|
||||
}
|
||||
|
||||
Utils::SmallString LocationSourceFileCallbacks::takeSymbolName()
|
||||
{
|
||||
return std::move(symbolName);
|
||||
return std::move(m_symbolName);
|
||||
}
|
||||
|
||||
bool LocationSourceFileCallbacks::hasSourceLocations() const
|
||||
{
|
||||
return sourceLocationsContainer.hasContent();
|
||||
return m_sourceLocationsContainer.hasContent();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <sourcelocationscontainer.h>
|
||||
|
||||
#include <clang/Tooling/Tooling.h>
|
||||
@@ -45,7 +46,7 @@ class SourceLocationsContainer;
|
||||
class LocationSourceFileCallbacks : public clang::tooling::SourceFileCallbacks
|
||||
{
|
||||
public:
|
||||
LocationSourceFileCallbacks(uint line, uint column);
|
||||
LocationSourceFileCallbacks(uint line, uint column, FilePathCachingInterface &filePathCache);
|
||||
|
||||
bool handleBeginSource(clang::CompilerInstance &compilerInstance,
|
||||
llvm::StringRef fileName) override;
|
||||
@@ -56,11 +57,12 @@ public:
|
||||
bool hasSourceLocations() const;
|
||||
|
||||
private:
|
||||
SourceLocationsContainer sourceLocationsContainer;
|
||||
Utils::SmallString symbolName;
|
||||
MacroPreprocessorCallbacks *macroPreprocessorCallbacks;
|
||||
uint line;
|
||||
uint column;
|
||||
SourceLocationsContainer m_sourceLocationsContainer;
|
||||
Utils::SmallString m_symbolName;
|
||||
MacroPreprocessorCallbacks *m_macroPreprocessorCallbacks;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
uint m_line;
|
||||
uint m_column;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -30,13 +30,15 @@ namespace ClangBackEnd {
|
||||
MacroPreprocessorCallbacks::MacroPreprocessorCallbacks(SourceLocationsContainer &sourceLocationsContainer,
|
||||
Utils::SmallString &symbolName,
|
||||
clang::Preprocessor &preprocessor,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
uint line,
|
||||
uint column)
|
||||
: sourceLocationsContainer(sourceLocationsContainer),
|
||||
symbolName(symbolName),
|
||||
preprocessor(preprocessor),
|
||||
line(line),
|
||||
column(column)
|
||||
: m_sourceLocationsContainer(sourceLocationsContainer),
|
||||
m_symbolName(symbolName),
|
||||
m_preprocessor(preprocessor),
|
||||
m_filePathCache(filePathCache),
|
||||
m_line(line),
|
||||
m_column(column)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -27,27 +27,14 @@
|
||||
|
||||
#include "sourcelocationsutils.h"
|
||||
|
||||
#include <filepathcachingfwd.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/Lex/PPCallbacks.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
#include <clang/Lex/MacroInfo.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
@@ -67,18 +54,19 @@ struct MacroDirectiveToken
|
||||
class MacroPreprocessorCallbacks : public clang::PPCallbacks
|
||||
{
|
||||
public:
|
||||
MacroPreprocessorCallbacks(SourceLocationsContainer &sourceLocationsContainer,
|
||||
Utils::SmallString &symbolName,
|
||||
clang::Preprocessor &preprocessor,
|
||||
uint line,
|
||||
uint column);
|
||||
MacroPreprocessorCallbacks(SourceLocationsContainer &m_sourceLocationsContainer,
|
||||
Utils::SmallString &m_symbolName,
|
||||
clang::Preprocessor &m_preprocessor,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
uint m_line,
|
||||
uint m_column);
|
||||
|
||||
void FileChanged(clang::SourceLocation location,
|
||||
FileChangeReason reason,
|
||||
clang::SrcMgr::CharacteristicKind /*fileType*/,
|
||||
clang::FileID /*previousFileIdentifier*/) final
|
||||
{
|
||||
if (!isMainFileEntered) {
|
||||
if (!m_isMainFileEntered) {
|
||||
updateLocations();
|
||||
updateIsMainFileEntered(location, reason);
|
||||
}
|
||||
@@ -88,9 +76,9 @@ public:
|
||||
{
|
||||
if (isInMainFile(token)) {
|
||||
if (includesCursorPosition(token)) {
|
||||
sourceLocations.push_back(token.getLocation());
|
||||
cursorMacroDirective = macroDirective;
|
||||
symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(),
|
||||
m_sourceLocations.push_back(token.getLocation());
|
||||
m_cursorMacroDirective = macroDirective;
|
||||
m_symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(),
|
||||
token.getIdentifierInfo()->getLength());
|
||||
}
|
||||
}
|
||||
@@ -103,59 +91,60 @@ public:
|
||||
{
|
||||
if (includesCursorPosition(token)) {
|
||||
appendSourceLocations(token, macroDefinition);
|
||||
cursorMacroDirective = macroDefinition.getLocalDirective();
|
||||
symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(),
|
||||
m_cursorMacroDirective = macroDefinition.getLocalDirective();
|
||||
m_symbolName = Utils::SmallString(token.getIdentifierInfo()->getNameStart(),
|
||||
token.getIdentifierInfo()->getLength());
|
||||
} else if (isCurrentTokenExpansion(macroDefinition)) {
|
||||
sourceLocations.push_back(token.getLocation());
|
||||
m_sourceLocations.push_back(token.getLocation());
|
||||
} else if (isBeforeCursorSourceLocation()) {
|
||||
preCursorMacroDirectiveTokens.emplace_back(macroDefinition.getLocalDirective(), token);
|
||||
m_preCursorMacroDirectiveTokens.emplace_back(macroDefinition.getLocalDirective(), token);
|
||||
}
|
||||
}
|
||||
|
||||
void EndOfMainFile() final
|
||||
{
|
||||
appendSourceLocationsToSourceLocationsContainer(sourceLocationsContainer,
|
||||
sourceLocations,
|
||||
sourceManager());
|
||||
appendSourceLocationsToSourceLocationsContainer(m_sourceLocationsContainer,
|
||||
m_sourceLocations,
|
||||
sourceManager(),
|
||||
m_filePathCache);
|
||||
}
|
||||
|
||||
private:
|
||||
void appendSourceLocations(const clang::Token &token,
|
||||
const clang::MacroDefinition ¯oDefinition)
|
||||
{
|
||||
sourceLocations.push_back(macroDefinition.getLocalDirective()->getLocation());
|
||||
for (const auto ¯oDirectiveToken : preCursorMacroDirectiveTokens) {
|
||||
m_sourceLocations.push_back(macroDefinition.getLocalDirective()->getLocation());
|
||||
for (const auto ¯oDirectiveToken : m_preCursorMacroDirectiveTokens) {
|
||||
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()
|
||||
{
|
||||
if (mainFileSourceLocation.isInvalid()) {
|
||||
mainFileSourceLocation = sourceManager().getLocForStartOfFile(sourceManager().getMainFileID());
|
||||
cursorSourceLocation = sourceManager().translateLineCol(sourceManager().getMainFileID(),
|
||||
line,
|
||||
column);
|
||||
if (m_mainFileSourceLocation.isInvalid()) {
|
||||
m_mainFileSourceLocation = sourceManager().getLocForStartOfFile(sourceManager().getMainFileID());
|
||||
m_cursorSourceLocation = sourceManager().translateLineCol(sourceManager().getMainFileID(),
|
||||
m_line,
|
||||
m_column);
|
||||
}
|
||||
}
|
||||
|
||||
void updateIsMainFileEntered(clang::SourceLocation location, FileChangeReason reason)
|
||||
{
|
||||
if (location == mainFileSourceLocation && reason == PPCallbacks::EnterFile)
|
||||
isMainFileEntered = true;
|
||||
if (location == m_mainFileSourceLocation && reason == PPCallbacks::EnterFile)
|
||||
m_isMainFileEntered = true;
|
||||
}
|
||||
|
||||
const clang::SourceManager &sourceManager() const
|
||||
{
|
||||
return preprocessor.getSourceManager();
|
||||
return m_preprocessor.getSourceManager();
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -163,35 +152,36 @@ private:
|
||||
auto start = token.getLocation();
|
||||
auto end = token.getEndLoc();
|
||||
|
||||
return cursorSourceLocation == start
|
||||
|| cursorSourceLocation == end
|
||||
|| (sourceManager().isBeforeInTranslationUnit(start, cursorSourceLocation) &&
|
||||
sourceManager().isBeforeInTranslationUnit(cursorSourceLocation, end));
|
||||
return m_cursorSourceLocation == start
|
||||
|| m_cursorSourceLocation == end
|
||||
|| (sourceManager().isBeforeInTranslationUnit(start, m_cursorSourceLocation) &&
|
||||
sourceManager().isBeforeInTranslationUnit(m_cursorSourceLocation, end));
|
||||
}
|
||||
|
||||
bool isCurrentTokenExpansion(const clang::MacroDefinition ¯oDefinition)
|
||||
{
|
||||
return cursorMacroDirective
|
||||
&& cursorMacroDirective == macroDefinition.getLocalDirective();
|
||||
return m_cursorMacroDirective
|
||||
&& m_cursorMacroDirective == macroDefinition.getLocalDirective();
|
||||
}
|
||||
|
||||
bool isBeforeCursorSourceLocation() const
|
||||
{
|
||||
return !cursorMacroDirective;
|
||||
return !m_cursorMacroDirective;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<clang::SourceLocation> sourceLocations;
|
||||
std::vector<MacroDirectiveToken> preCursorMacroDirectiveTokens;
|
||||
SourceLocationsContainer &sourceLocationsContainer;
|
||||
Utils::SmallString &symbolName;
|
||||
clang::Preprocessor &preprocessor;
|
||||
const clang::MacroDirective *cursorMacroDirective = nullptr;
|
||||
clang::SourceLocation mainFileSourceLocation;
|
||||
clang::SourceLocation cursorSourceLocation;
|
||||
uint line;
|
||||
uint column;
|
||||
bool isMainFileEntered = false;
|
||||
std::vector<clang::SourceLocation> m_sourceLocations;
|
||||
std::vector<MacroDirectiveToken> m_preCursorMacroDirectiveTokens;
|
||||
SourceLocationsContainer &m_sourceLocationsContainer;
|
||||
Utils::SmallString &m_symbolName;
|
||||
clang::Preprocessor &m_preprocessor;
|
||||
const clang::MacroDirective *m_cursorMacroDirective = nullptr;
|
||||
clang::SourceLocation m_mainFileSourceLocation;
|
||||
clang::SourceLocation m_cursorSourceLocation;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
uint m_line;
|
||||
uint m_column;
|
||||
bool m_isMainFileEntered = false;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -40,7 +40,7 @@
|
||||
namespace ClangBackEnd {
|
||||
|
||||
RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing,
|
||||
FilePathCache<std::mutex> &filePathCache)
|
||||
FilePathCachingInterface &filePathCache)
|
||||
: m_symbolIndexing(symbolIndexing),
|
||||
m_filePathCache(filePathCache)
|
||||
{
|
||||
@@ -58,7 +58,7 @@ void RefactoringServer::end()
|
||||
|
||||
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()),
|
||||
std::string(message.filePath().name()),
|
||||
|
@@ -29,12 +29,13 @@
|
||||
|
||||
#include <refactoringserverinterface.h>
|
||||
|
||||
#include <QTimer>
|
||||
#include <ipcclientprovider.h>
|
||||
#include <stringcache.h>
|
||||
#include <filepathcachinginterface.h>
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
@@ -54,7 +55,7 @@ class RefactoringServer : public RefactoringServerInterface,
|
||||
using Future = std::future<SourceRangesForQueryMessage>;
|
||||
public:
|
||||
RefactoringServer(SymbolIndexingInterface &symbolIndexing,
|
||||
FilePathCache<std::mutex> &filePathCache);
|
||||
FilePathCachingInterface &filePathCache);
|
||||
|
||||
void end() override;
|
||||
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
|
||||
@@ -82,7 +83,7 @@ private:
|
||||
ClangQueryGatherer m_gatherer;
|
||||
QTimer m_pollTimer;
|
||||
SymbolIndexingInterface &m_symbolIndexing;
|
||||
FilePathCache<std::mutex> &m_filePathCache;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -25,11 +25,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stringcachefwd.h>
|
||||
#include <filepathid.h>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <iosfwd>
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
@@ -59,18 +58,18 @@ class SourceLocationEntry
|
||||
{
|
||||
public:
|
||||
SourceLocationEntry(SymbolIndex symbolId,
|
||||
FilePathIndex fileId,
|
||||
FilePathId filePathId,
|
||||
LineColumn lineColumn,
|
||||
SymbolType symbolType)
|
||||
: symbolId(symbolId),
|
||||
fileId(fileId),
|
||||
filePathId(filePathId),
|
||||
line(lineColumn.line),
|
||||
column(lineColumn.column),
|
||||
symbolType(symbolType)
|
||||
{}
|
||||
|
||||
SymbolIndex symbolId = 0;
|
||||
FilePathIndex fileId = std::numeric_limits<uint>::max();
|
||||
FilePathId filePathId;
|
||||
uint line = 0;
|
||||
uint column = 0;
|
||||
SymbolType symbolType;
|
||||
@@ -78,7 +77,7 @@ public:
|
||||
friend bool operator==(const SourceLocationEntry &first, const SourceLocationEntry &second)
|
||||
{
|
||||
return first.symbolId == second.symbolId
|
||||
&& first.fileId == second.fileId
|
||||
&& first.filePathId == second.filePathId
|
||||
&& first.line == second.line
|
||||
&& first.column == second.column
|
||||
&& first.symbolType == second.symbolType;
|
||||
@@ -87,6 +86,4 @@ public:
|
||||
|
||||
using SourceLocationEntries = std::vector<SourceLocationEntry>;
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -25,28 +25,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filepathcachinginterface.h>
|
||||
#include <sourcelocationscontainer.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/Lex/Lexer.h>
|
||||
#include <llvm/Support/FileSystem.h>
|
||||
#include <llvm/Support/FileUtilities.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <iterator>
|
||||
#include <cctype>
|
||||
|
||||
@@ -79,7 +66,8 @@ inline
|
||||
void appendSourceLocationsToSourceLocationsContainer(
|
||||
ClangBackEnd::SourceLocationsContainer &sourceLocationsContainer,
|
||||
const std::vector<clang::SourceLocation> &sourceLocations,
|
||||
const clang::SourceManager &sourceManager)
|
||||
const clang::SourceManager &sourceManager,
|
||||
FilePathCachingInterface &filePathCache)
|
||||
{
|
||||
sourceLocationsContainer.reserve(sourceLocations.size());
|
||||
|
||||
@@ -89,10 +77,9 @@ void appendSourceLocationsToSourceLocationsContainer(
|
||||
const auto fileId = decomposedLoction.first;
|
||||
const auto offset = decomposedLoction.second;
|
||||
const auto fileEntry = sourceManager.getFileEntryForID(fileId);
|
||||
auto filePath = fromNativePath(absolutePath(fileEntry->getName()));
|
||||
|
||||
sourceLocationsContainer.insertFilePath(fileId.getHashValue(),
|
||||
fromNativePath(absolutePath(fileEntry->getName())));
|
||||
sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(),
|
||||
sourceLocationsContainer.insertSourceLocation(filePathCache.filePathId(filePath),
|
||||
fullSourceLocation.getSpellingLineNumber(),
|
||||
fullSourceLocation.getSpellingColumnNumber(),
|
||||
offset);
|
||||
|
@@ -28,14 +28,7 @@
|
||||
#include "sourcelocationsutils.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 <filepathcachinginterface.h>
|
||||
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
#include <clang/Lex/Lexer.h>
|
||||
@@ -43,18 +36,12 @@
|
||||
#include <llvm/Support/FileUtilities.h>
|
||||
#include <llvm/ADT/SmallVector.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
SourceRangeExtractor::SourceRangeExtractor(
|
||||
const clang::SourceManager &sourceManager,
|
||||
const clang::LangOptions &languageOptions,
|
||||
ClangBackEnd::FilePathCache<std::mutex> &filePathCache,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
SourceRangesContainer &sourceRangesContainer)
|
||||
: sourceManager(sourceManager),
|
||||
languageOptions(languageOptions),
|
||||
@@ -127,16 +114,14 @@ const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(c
|
||||
return {sourceRange.getBegin(), endLocation};
|
||||
}
|
||||
|
||||
void SourceRangeExtractor::insertSourceRange(uint fileId,
|
||||
Utils::PathString &&filePath,
|
||||
void SourceRangeExtractor::insertSourceRange(FilePathId filePathId,
|
||||
const clang::FullSourceLoc &startLocation,
|
||||
uint startOffset,
|
||||
const clang::FullSourceLoc &endLocation,
|
||||
uint endOffset,
|
||||
Utils::SmallString &&lineSnippet)
|
||||
{
|
||||
sourceRangesContainer.insertFilePath(fileId, std::move(filePath));
|
||||
sourceRangesContainer.insertSourceRange(fileId,
|
||||
sourceRangesContainer.insertSourceRange(filePathId,
|
||||
startLocation.getSpellingLineNumber(),
|
||||
startLocation.getSpellingColumnNumber(),
|
||||
startOffset,
|
||||
@@ -146,7 +131,7 @@ void SourceRangeExtractor::insertSourceRange(uint fileId,
|
||||
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());
|
||||
if (found != m_fileIdMapping.end()) {
|
||||
@@ -154,7 +139,7 @@ FilePathIndex SourceRangeExtractor::findFileId(clang::FileID fileId, const clang
|
||||
}
|
||||
|
||||
auto filePath = absolutePath(fileEntry->getName());
|
||||
return filePathCache.stringId(fromNativePath(filePath));
|
||||
return filePathCache.filePathId(fromNativePath(filePath));
|
||||
}
|
||||
|
||||
void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
|
||||
@@ -176,13 +161,11 @@ void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
|
||||
endOffset);
|
||||
|
||||
insertSourceRange(findFileId(fileId, fileEntry),
|
||||
fromNativePath(absolutePath(fileEntry->getName())),
|
||||
startSourceLocation,
|
||||
startOffset,
|
||||
endSourceLocation,
|
||||
endOffset,
|
||||
std::move(lineSnippet));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -25,9 +25,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stringcache.h>
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
#include <filepath.h>
|
||||
#include <filepathid.h>
|
||||
|
||||
#include <utils/smallstringfwd.h>
|
||||
|
||||
@@ -59,7 +60,7 @@ class SourceRangeExtractor
|
||||
public:
|
||||
SourceRangeExtractor(const clang::SourceManager &sourceManager,
|
||||
const clang::LangOptions &languageOptions,
|
||||
ClangBackEnd::FilePathCache<std::mutex> &filePathCache,
|
||||
FilePathCachingInterface &filePathCache,
|
||||
SourceRangesContainer &sourceRangesContainer);
|
||||
|
||||
void addSourceRange(const clang::SourceRange &sourceRange);
|
||||
@@ -74,21 +75,20 @@ public:
|
||||
const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange);
|
||||
|
||||
private:
|
||||
void insertSourceRange(uint fileId,
|
||||
Utils::PathString &&filePath,
|
||||
void insertSourceRange(FilePathId filePathId,
|
||||
const clang::FullSourceLoc &startLocation,
|
||||
uint startOffset,
|
||||
const clang::FullSourceLoc &endLocation,
|
||||
uint endOffset,
|
||||
Utils::SmallString &&lineSnippet);
|
||||
|
||||
FilePathIndex findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
|
||||
FilePathId findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
|
||||
|
||||
private:
|
||||
mutable std::unordered_map<uint, uint> m_fileIdMapping;
|
||||
mutable std::unordered_map<uint, FilePathId> m_fileIdMapping;
|
||||
const clang::SourceManager &sourceManager;
|
||||
const clang::LangOptions &languageOptions;
|
||||
ClangBackEnd::FilePathCache<std::mutex> &filePathCache;
|
||||
FilePathCachingInterface &filePathCache;
|
||||
SourceRangesContainer &sourceRangesContainer;
|
||||
};
|
||||
|
||||
|
@@ -25,8 +25,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <createtablesqlstatementbuilder.h>
|
||||
|
||||
#include <sqlitetransaction.h>
|
||||
#include <sqlitetable.h>
|
||||
|
||||
@@ -96,9 +94,6 @@ public:
|
||||
"INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)",
|
||||
database
|
||||
};
|
||||
// WriteStatement syncNewLocationsToLocationsStatement{
|
||||
// "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
|
||||
// database};
|
||||
ReadStatement selectNewSourceIdsStatement{
|
||||
"SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)",
|
||||
database
|
||||
@@ -109,10 +104,6 @@ public:
|
||||
"(SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)",
|
||||
database
|
||||
};
|
||||
WriteStatement insertSourcesStatement{
|
||||
"INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)",
|
||||
database
|
||||
};
|
||||
WriteStatement syncNewSymbolsFromSymbolsStatement{
|
||||
"UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)",
|
||||
database
|
||||
|
@@ -30,9 +30,10 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
SymbolFinder::SymbolFinder(uint line, uint column)
|
||||
: usrFindingAction(line, column),
|
||||
sourceFileCallbacks(line, column)
|
||||
SymbolFinder::SymbolFinder(uint line, uint column, FilePathCachingInterface &filePathCache)
|
||||
: m_usrFindingAction(line, column),
|
||||
m_symbolLocationFinderAction(filePathCache),
|
||||
m_sourceFileCallbacks(line, column, filePathCache)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,39 +41,39 @@ void SymbolFinder::findSymbol()
|
||||
{
|
||||
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()) {
|
||||
sourceLocations_ = sourceFileCallbacks.takeSourceLocations();
|
||||
symbolName = sourceFileCallbacks.takeSymbolName();
|
||||
if (m_sourceFileCallbacks.hasSourceLocations()) {
|
||||
m_sourceLocations_ = m_sourceFileCallbacks.takeSourceLocations();
|
||||
m_symbolName = m_sourceFileCallbacks.takeSymbolName();
|
||||
} 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();
|
||||
symbolName = usrFindingAction.takeSymbolName();
|
||||
m_sourceLocations_ = m_symbolLocationFinderAction.takeSourceLocations();
|
||||
m_symbolName = m_usrFindingAction.takeSymbolName();
|
||||
}
|
||||
}
|
||||
|
||||
Utils::SmallString SymbolFinder::takeSymbolName()
|
||||
{
|
||||
return std::move(symbolName);
|
||||
return std::move(m_symbolName);
|
||||
}
|
||||
|
||||
const std::vector<USRName> &SymbolFinder::unifiedSymbolResolutions()
|
||||
{
|
||||
return symbolLocationFinderAction.unifiedSymbolResolutions();
|
||||
return m_symbolLocationFinderAction.unifiedSymbolResolutions();
|
||||
}
|
||||
|
||||
const SourceLocationsContainer &SymbolFinder::sourceLocations() const
|
||||
{
|
||||
return sourceLocations_;
|
||||
return m_sourceLocations_;
|
||||
}
|
||||
|
||||
SourceLocationsContainer SymbolFinder::takeSourceLocations()
|
||||
{
|
||||
return std::move(sourceLocations_);
|
||||
return std::move(m_sourceLocations_);
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "symbollocationfinderaction.h"
|
||||
#include "locationsourcefilecallbacks.h"
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <sourcelocationscontainer.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
@@ -37,7 +38,7 @@ namespace ClangBackEnd {
|
||||
class SymbolFinder : public ClangTool
|
||||
{
|
||||
public:
|
||||
SymbolFinder(uint line, uint column);
|
||||
SymbolFinder(uint line, uint column, FilePathCachingInterface &filePathCache);
|
||||
|
||||
void findSymbol();
|
||||
|
||||
@@ -47,12 +48,11 @@ public:
|
||||
SourceLocationsContainer takeSourceLocations();
|
||||
|
||||
private:
|
||||
Utils::SmallString symbolName;
|
||||
USRFindingAction usrFindingAction;
|
||||
SymbolLocationFinderAction symbolLocationFinderAction;
|
||||
LocationSourceFileCallbacks sourceFileCallbacks;
|
||||
|
||||
ClangBackEnd::SourceLocationsContainer sourceLocations_;
|
||||
Utils::SmallString m_symbolName;
|
||||
USRFindingAction m_usrFindingAction;
|
||||
SymbolLocationFinderAction m_symbolLocationFinderAction;
|
||||
LocationSourceFileCallbacks m_sourceFileCallbacks;
|
||||
ClangBackEnd::SourceLocationsContainer m_sourceLocations_;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -33,7 +33,7 @@
|
||||
#include "symbolstorage.h"
|
||||
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <stringcache.h>
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
#include <sqlitereadstatement.h>
|
||||
@@ -48,13 +48,11 @@ public:
|
||||
Sqlite::ReadStatement,
|
||||
Sqlite::WriteStatement>;
|
||||
using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
|
||||
using DatabaseInitializer = RefactoringDatabaseInitializer<Sqlite::Database>;
|
||||
|
||||
SymbolIndexing(FilePathCache<std::mutex> &filePathCache,
|
||||
Utils::PathString &&databaseFilePath)
|
||||
SymbolIndexing(Sqlite::Database &database,
|
||||
FilePathCachingInterface &filePathCache)
|
||||
: m_filePathCache(filePathCache),
|
||||
m_database(std::move(databaseFilePath)),
|
||||
m_databaseInitializer(m_database)
|
||||
m_statementFactory(database)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -63,11 +61,6 @@ public:
|
||||
return m_indexer;
|
||||
}
|
||||
|
||||
Sqlite::Database &database()
|
||||
{
|
||||
return m_database;
|
||||
}
|
||||
|
||||
void updateProjectParts(V2::ProjectPartContainers &&projectParts,
|
||||
V2::FileContainers &&generatedFiles)
|
||||
{
|
||||
@@ -75,11 +68,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
FilePathCache<std::mutex> &m_filePathCache;
|
||||
Sqlite::Database m_database;
|
||||
DatabaseInitializer m_databaseInitializer;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
SymbolsCollector m_collector{m_filePathCache};
|
||||
StatementFactory m_statementFactory{m_database};
|
||||
StatementFactory m_statementFactory;
|
||||
Storage m_symbolStorage{m_statementFactory, m_filePathCache};
|
||||
SymbolIndexer m_indexer{m_collector, m_symbolStorage};
|
||||
};
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include "sourcelocationsutils.h"
|
||||
#include "findlocationsofusrs.h"
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/AST/ASTContext.h>
|
||||
|
||||
@@ -38,8 +40,10 @@ namespace ClangBackEnd {
|
||||
class FindingSymbolsASTConsumer : public clang::ASTConsumer
|
||||
{
|
||||
public:
|
||||
FindingSymbolsASTConsumer(std::vector<USRName> &unifiedSymbolResolutions)
|
||||
: m_unifiedSymbolResolutions(unifiedSymbolResolutions)
|
||||
FindingSymbolsASTConsumer(std::vector<USRName> &unifiedSymbolResolutions,
|
||||
FilePathCachingInterface &filePathCache)
|
||||
: m_unifiedSymbolResolutions(unifiedSymbolResolutions),
|
||||
m_filePathCache(filePathCache)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,7 +69,10 @@ public:
|
||||
void updateSourceLocations(const std::vector<clang::SourceLocation> &sourceLocations,
|
||||
const clang::SourceManager &sourceManager)
|
||||
{
|
||||
appendSourceLocationsToSourceLocationsContainer(*m_sourceLocationsContainer, sourceLocations, sourceManager);
|
||||
appendSourceLocationsToSourceLocationsContainer(*m_sourceLocationsContainer,
|
||||
sourceLocations,
|
||||
sourceManager,
|
||||
m_filePathCache);
|
||||
}
|
||||
|
||||
void setSourceLocations(ClangBackEnd::SourceLocationsContainer *sourceLocations)
|
||||
@@ -76,11 +83,13 @@ public:
|
||||
private:
|
||||
ClangBackEnd::SourceLocationsContainer *m_sourceLocationsContainer = nullptr;
|
||||
std::vector<USRName> &m_unifiedSymbolResolutions;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "clangrefactoringbackend_global.h"
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <sourcelocationscontainer.h>
|
||||
|
||||
#include <clang/Tooling/Refactoring.h>
|
||||
@@ -40,6 +41,9 @@ namespace ClangBackEnd {
|
||||
class SymbolLocationFinderAction
|
||||
{
|
||||
public:
|
||||
SymbolLocationFinderAction(FilePathCachingInterface &filePathCache)
|
||||
: m_filePathCache(filePathCache)
|
||||
{}
|
||||
|
||||
std::unique_ptr<clang::ASTConsumer> newASTConsumer();
|
||||
|
||||
@@ -61,6 +65,7 @@ public:
|
||||
private:
|
||||
ClangBackEnd::SourceLocationsContainer m_sourceLocations;
|
||||
std::vector<USRName> m_unifiedSymbolResolutions_;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
SymbolsCollector::SymbolsCollector(FilePathCache<std::mutex> &filePathCache)
|
||||
SymbolsCollector::SymbolsCollector(FilePathCachingInterface &filePathCache)
|
||||
: m_collectSymbolsAction(filePathCache)
|
||||
{
|
||||
}
|
||||
|
@@ -30,14 +30,15 @@
|
||||
#include "collectsymbolsaction.h"
|
||||
#include "symbolscollectorinterface.h"
|
||||
#include "symbolentry.h"
|
||||
#include "stringcache.h"
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface
|
||||
{
|
||||
public:
|
||||
SymbolsCollector(FilePathCache<std::mutex> &filePathCache);
|
||||
SymbolsCollector(FilePathCachingInterface &filePathCache);
|
||||
|
||||
void addFiles(const Utils::PathStringVector &filePaths,
|
||||
const Utils::SmallStringVector &arguments) override;
|
||||
|
@@ -29,9 +29,7 @@
|
||||
|
||||
#include <sqliteexception.h>
|
||||
#include <sqlitetransaction.h>
|
||||
#include <stringcache.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
@@ -45,7 +43,7 @@ class SymbolStorage : public SymbolStorageInterface
|
||||
|
||||
public:
|
||||
SymbolStorage(StatementFactory &statementFactory,
|
||||
FilePathCache<std::mutex> &filePathCache)
|
||||
FilePathCachingInterface &filePathCache)
|
||||
: m_statementFactory(statementFactory),
|
||||
m_filePathCache(filePathCache)
|
||||
{
|
||||
@@ -61,7 +59,6 @@ public:
|
||||
addNewSymbolsToSymbols();
|
||||
syncNewSymbolsFromSymbols();
|
||||
syncSymbolsIntoNewLocations();
|
||||
insertNewSources();
|
||||
deleteAllLocationsFromUpdatedFiles();
|
||||
insertNewLocationsInLocations();
|
||||
deleteNewSymbolsTable();
|
||||
@@ -89,7 +86,7 @@ public:
|
||||
statement.write(locationsEntry.symbolId,
|
||||
locationsEntry.line,
|
||||
locationsEntry.column,
|
||||
locationsEntry.fileId);
|
||||
locationsEntry.filePathId.fileNameId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,23 +115,6 @@ public:
|
||||
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()
|
||||
{
|
||||
m_statementFactory.deleteNewSymbolsTableStatement.execute();
|
||||
@@ -152,7 +132,7 @@ public:
|
||||
|
||||
private:
|
||||
StatementFactory &m_statementFactory;
|
||||
FilePathCache<std::mutex> &m_filePathCache;
|
||||
FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -23,6 +23,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include "clangiasyncjob.h"
|
||||
#include "dummyclangipcclient.h"
|
||||
#include "processevents-utilities.h"
|
||||
@@ -35,11 +37,6 @@
|
||||
#include <projects.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;
|
||||
|
||||
namespace {
|
||||
|
@@ -23,6 +23,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include "clangiasyncjob.h"
|
||||
#include "dummyclangipcclient.h"
|
||||
#include "processevents-utilities.h"
|
||||
@@ -37,11 +39,6 @@
|
||||
#include <projects.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 namespace ClangBackEnd;
|
||||
|
@@ -26,11 +26,13 @@
|
||||
#include "googletest.h"
|
||||
|
||||
#include "faketimer.h"
|
||||
#include "mockfilepathcaching.h"
|
||||
#include "mockqfilesystemwatcher.h"
|
||||
#include "mockclangpathwatchernotifier.h"
|
||||
|
||||
#include <clangpathwatcher.h>
|
||||
#include <stringcache.h>
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -42,34 +44,41 @@ using testing::NiceMock;
|
||||
|
||||
using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>;
|
||||
using ClangBackEnd::WatcherEntry;
|
||||
using ClangBackEnd::FilePathIndices;
|
||||
using ClangBackEnd::FilePath;
|
||||
using ClangBackEnd::FilePathId;
|
||||
using ClangBackEnd::FilePathIds;
|
||||
|
||||
class ClangPathWatcher : public testing::Test
|
||||
{
|
||||
protected:
|
||||
ClangBackEnd::FilePathCache<> pathCache;
|
||||
void SetUp();
|
||||
|
||||
protected:
|
||||
NiceMock<MockFilePathCaching> filePathCache;
|
||||
NiceMock<MockClangPathWatcherNotifier> notifier;
|
||||
Watcher watcher{pathCache, ¬ifier};
|
||||
Watcher watcher{filePathCache, ¬ifier};
|
||||
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
|
||||
Utils::SmallString id1{"id4"};
|
||||
Utils::SmallString id2{"id2"};
|
||||
Utils::SmallString id3{"id3"};
|
||||
Utils::PathString path1{"/path/path1"};
|
||||
Utils::PathString path2{"/path/path2"};
|
||||
FilePathIndices paths{watcher.pathCache().stringIds({path1, path2})};
|
||||
FilePathIndices ids{watcher.idCache().stringIds({id1, id2, id3})};
|
||||
WatcherEntry watcherEntry1{ids[0], paths[0]};
|
||||
WatcherEntry watcherEntry2{ids[1], paths[0]};
|
||||
WatcherEntry watcherEntry3{ids[0], paths[1]};
|
||||
WatcherEntry watcherEntry4{ids[1], paths[1]};
|
||||
WatcherEntry watcherEntry5{ids[2], paths[1]};
|
||||
FilePath path1{Utils::PathString{"/path/path1"}};
|
||||
FilePath path2{Utils::PathString{"/path/path2"}};
|
||||
QString path1QString = QString(path1.path());
|
||||
QString path2QString = QString(path2.path());
|
||||
FilePathIds pathIds = {{1, 1}, {1, 2}};
|
||||
std::vector<int> ids{watcher.idCache().stringIds({id1, id2, id3})};
|
||||
WatcherEntry watcherEntry1{ids[0], pathIds[0]};
|
||||
WatcherEntry watcherEntry2{ids[1], pathIds[0]};
|
||||
WatcherEntry watcherEntry3{ids[0], pathIds[1]};
|
||||
WatcherEntry watcherEntry4{ids[1], pathIds[1]};
|
||||
WatcherEntry watcherEntry5{ids[2], pathIds[1]};
|
||||
};
|
||||
|
||||
TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList)
|
||||
{
|
||||
auto convertedList = watcher.convertWatcherEntriesToQStringList({watcherEntry1, watcherEntry3});
|
||||
|
||||
ASSERT_THAT(convertedList, ElementsAre(QString(path1), QString(path2)));
|
||||
ASSERT_THAT(convertedList, ElementsAre(path1QString, path2QString));
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, UniquePaths)
|
||||
@@ -90,51 +99,51 @@ TEST_F(ClangPathWatcher, NotWatchedEntries)
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
watcher.updateIdPaths({{id1, {paths[1]}}, {id2, {paths[0]}}});
|
||||
watcher.updateIdPaths({{id1, {pathIds[1]}}, {id2, {pathIds[0]}}});
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -190,14 +199,14 @@ TEST_F(ClangPathWatcher, AddEmptyEntries)
|
||||
|
||||
TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths)
|
||||
{
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1), QString(path2)}));
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString, path2QString}));
|
||||
|
||||
watcher.addEntries({watcherEntry1, watcherEntry3});
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths)
|
||||
{
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)}));
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString}));
|
||||
|
||||
watcher.addEntries({watcherEntry1, watcherEntry2});
|
||||
}
|
||||
@@ -206,7 +215,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithSameIdAndSamePaths)
|
||||
{
|
||||
watcher.addEntries({watcherEntry1});
|
||||
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)}))
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString}))
|
||||
.Times(0);
|
||||
|
||||
watcher.addEntries({watcherEntry1});
|
||||
@@ -216,7 +225,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths)
|
||||
{
|
||||
watcher.addEntries({watcherEntry1});
|
||||
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)}))
|
||||
EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString}))
|
||||
.Times(0);
|
||||
|
||||
watcher.addEntries({watcherEntry2});
|
||||
@@ -253,7 +262,7 @@ TEST_F(ClangPathWatcher, RemovePathForOneId)
|
||||
{
|
||||
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3});
|
||||
|
||||
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)}));
|
||||
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString}));
|
||||
|
||||
watcher.removeIds({id1});
|
||||
}
|
||||
@@ -262,7 +271,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
|
||||
{
|
||||
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});
|
||||
}
|
||||
@@ -271,7 +280,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
|
||||
{
|
||||
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
|
||||
|
||||
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path1)}));
|
||||
EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1QString}));
|
||||
|
||||
watcher.removeIds({id1, id2});
|
||||
}
|
||||
@@ -298,9 +307,9 @@ TEST_F(ClangPathWatcher, EmptyVectorNotifyFileChange)
|
||||
{
|
||||
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)
|
||||
@@ -309,7 +318,7 @@ TEST_F(ClangPathWatcher, NotifyFileChange)
|
||||
|
||||
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id1)));
|
||||
|
||||
mockQFileSytemWatcher.fileChanged(path1.toQString());
|
||||
mockQFileSytemWatcher.fileChanged(path1QString);
|
||||
}
|
||||
|
||||
TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
|
||||
@@ -318,8 +327,19 @@ TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
|
||||
|
||||
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id3, id1)));
|
||||
|
||||
mockQFileSytemWatcher.fileChanged(path2.toQString());
|
||||
mockQFileSytemWatcher.fileChanged(path1.toQString());
|
||||
mockQFileSytemWatcher.fileChanged(path2QString);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@@ -29,11 +29,19 @@
|
||||
#include "filesystem-utilities.h"
|
||||
|
||||
#include <clangquery.h>
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#include <filepathcaching.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
using ClangBackEnd::ClangQuery;
|
||||
using ClangBackEnd::FilePathCache;
|
||||
using ClangBackEnd::FilePathCaching;
|
||||
using ClangBackEnd::RefactoringDatabaseInitializer;
|
||||
|
||||
using testing::AllOf;
|
||||
using testing::Contains;
|
||||
@@ -48,7 +56,9 @@ protected:
|
||||
void SetUp() override;
|
||||
|
||||
protected:
|
||||
FilePathCache<std::mutex> filePathCache;
|
||||
Sqlite::Database database{QDir::tempPath() + "/symbol.db"};
|
||||
RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
|
||||
FilePathCaching filePathCache{database};
|
||||
::ClangQuery simpleFunctionQuery{filePathCache};
|
||||
::ClangQuery simpleClassQuery{filePathCache};
|
||||
};
|
||||
|
@@ -66,7 +66,7 @@ TEST_F(ClangQueryExampleHighlightMarker, NoCallForNotSourceRanges)
|
||||
|
||||
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);
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(2, 7, textFormats[0]));
|
||||
@@ -76,7 +76,7 @@ TEST_F(ClangQueryExampleHighlightMarker, SingleLineSourceRange)
|
||||
|
||||
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.highlightBlock(1, "foo");
|
||||
|
||||
@@ -88,9 +88,9 @@ TEST_F(ClangQueryExampleHighlightMarker, OtherSingleLineSourceRange)
|
||||
TEST_F(ClangQueryExampleHighlightMarker, CascadedSingleLineSourceRanges)
|
||||
{
|
||||
InSequence sequence;
|
||||
SourceRanges sourceRanges{{1, 1, 2, 2, 1, 15, 15, "void function"},
|
||||
{1, 1, 2, 2, 1, 6, 6, "void"},
|
||||
{1, 1, 7, 7, 1, 15, 15, "function"}};
|
||||
SourceRanges sourceRanges{{{1, 1}, 1, 2, 2, 1, 15, 15, "void function"},
|
||||
{{1, 1}, 1, 2, 2, 1, 6, 6, "void"},
|
||||
{{1, 1}, 1, 7, 7, 1, 15, 15, "function"}};
|
||||
Marker marker(std::move(sourceRanges), highlighter, textFormats);
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(1, 13, textFormats[0]));
|
||||
@@ -103,7 +103,7 @@ TEST_F(ClangQueryExampleHighlightMarker, CascadedSingleLineSourceRanges)
|
||||
TEST_F(ClangQueryExampleHighlightMarker, DualLineSourceRanges)
|
||||
{
|
||||
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);
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0]));
|
||||
@@ -116,7 +116,7 @@ TEST_F(ClangQueryExampleHighlightMarker, DualLineSourceRanges)
|
||||
TEST_F(ClangQueryExampleHighlightMarker, MultipleLineSourceRanges)
|
||||
{
|
||||
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);
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(1, 7, textFormats[0]));
|
||||
@@ -131,9 +131,9 @@ TEST_F(ClangQueryExampleHighlightMarker, MultipleLineSourceRanges)
|
||||
TEST_F(ClangQueryExampleHighlightMarker, MoreMultipleLineSourceRanges)
|
||||
{
|
||||
InSequence sequence;
|
||||
SourceRanges sourceRanges{{1, 1, 1, 0, 4, 2, 0, ""},
|
||||
{1, 2, 2, 0, 2, 7, 0, ""},
|
||||
{1, 3, 2, 0, 3, 7, 0, ""}};
|
||||
SourceRanges sourceRanges{{{1, 1}, 1, 1, 0, 4, 2, 0, ""},
|
||||
{{1, 1}, 2, 2, 0, 2, 7, 0, ""},
|
||||
{{1, 1}, 3, 2, 0, 3, 7, 0, ""}};
|
||||
Marker marker(std::move(sourceRanges), highlighter, textFormats);
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(0, 10, textFormats[0]));
|
||||
@@ -152,9 +152,9 @@ TEST_F(ClangQueryExampleHighlightMarker, MoreMultipleLineSourceRanges)
|
||||
TEST_F(ClangQueryExampleHighlightMarker, CascadedMultipleLineSourceRanges)
|
||||
{
|
||||
InSequence sequence;
|
||||
SourceRanges sourceRanges{{1, 1, 1, 0, 4, 2, 0, ""},
|
||||
{1, 2, 2, 0, 3, 4, 0, ""},
|
||||
{1, 2, 11, 0, 2, 16, 0, ""}};
|
||||
SourceRanges sourceRanges{{{1, 1}, 1, 1, 0, 4, 2, 0, ""},
|
||||
{{1, 1}, 2, 2, 0, 3, 4, 0, ""},
|
||||
{{1, 1}, 2, 11, 0, 2, 16, 0, ""}};
|
||||
Marker marker(std::move(sourceRanges), highlighter, textFormats);
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(0, 9, textFormats[0]));
|
||||
@@ -173,7 +173,7 @@ TEST_F(ClangQueryExampleHighlightMarker, CascadedMultipleLineSourceRanges)
|
||||
|
||||
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]));
|
||||
|
||||
@@ -182,7 +182,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatSingle)
|
||||
|
||||
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]));
|
||||
|
||||
@@ -191,7 +191,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleStart)
|
||||
|
||||
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]));
|
||||
|
||||
@@ -200,7 +200,7 @@ TEST_F(ClangQueryExampleHighlightMarker, FormatMultipleEnd)
|
||||
|
||||
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]));
|
||||
|
||||
|
@@ -30,9 +30,15 @@
|
||||
#include "sourcerangecontainer-matcher.h"
|
||||
|
||||
#include <filecontainerv2.h>
|
||||
#include <filepathcaching.h>
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#include <clangquerygatherer.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
namespace {
|
||||
|
||||
using testing::AllOf;
|
||||
@@ -75,7 +81,9 @@ protected:
|
||||
void SetUp() override;
|
||||
|
||||
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() {}"};
|
||||
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
|
||||
sourceContent.clone(),
|
||||
|
@@ -74,10 +74,10 @@ TEST_F(ClangQueryHighlightMarker, NoCallForNoMessagesAndContexts)
|
||||
TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextsForASingleLine)
|
||||
{
|
||||
InSequence sequence;
|
||||
Messages messages{{{1, 1, 5, 0, 1, 10, 0}, ErrorType::RegistryMatcherNotFound, {}},
|
||||
{{1, 1, 30, 0, 1, 40, 0}, ErrorType::RegistryMatcherNotFound, {}}};
|
||||
Contexts contexts{{{1, 1, 2, 0, 1, 15, 0}, ContextType::MatcherArg, {}},
|
||||
{{1, 1, 20, 0, 1, 50, 0}, ContextType::MatcherArg, {}}};
|
||||
Messages messages{{{{0, 1}, 1, 5, 0, 1, 10, 0}, ErrorType::RegistryMatcherNotFound, {}},
|
||||
{{{0, 1}, 1, 30, 0, 1, 40, 0}, ErrorType::RegistryMatcherNotFound, {}}};
|
||||
Contexts contexts{{{{0, 1}, 1, 2, 0, 1, 15, 0}, ContextType::MatcherArg, {}},
|
||||
{{{0, 1}, 1, 20, 0, 1, 50, 0}, ContextType::MatcherArg, {}}};
|
||||
marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(1, 13, contextTextFormat));
|
||||
@@ -91,7 +91,7 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextsForASingleLine)
|
||||
TEST_F(ClangQueryHighlightMarker, CallForMessagesForAMultiLine)
|
||||
{
|
||||
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;
|
||||
marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
|
||||
|
||||
@@ -107,8 +107,8 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesForAMultiLine)
|
||||
TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextForAMultiLine)
|
||||
{
|
||||
InSequence sequence;
|
||||
Messages messages{{{1, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}};
|
||||
Contexts contexts{{{1, 1, 2, 0, 3, 4, 0}, ContextType::MatcherArg, {}}};
|
||||
Messages messages{{{{1, 1}, 1, 5, 0, 3, 3, 0}, ErrorType::RegistryMatcherNotFound, {}}};
|
||||
Contexts contexts{{{{1, 1}, 1, 2, 0, 3, 4, 0}, ContextType::MatcherArg, {}}};
|
||||
marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
|
||||
|
||||
EXPECT_CALL(highlighter, setFormat(1, 11, contextTextFormat));
|
||||
@@ -136,7 +136,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesIfEmpty)
|
||||
|
||||
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,
|
||||
{"foo"}}};
|
||||
Contexts contexts;
|
||||
@@ -149,7 +149,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition)
|
||||
|
||||
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,
|
||||
{"foo"}}};
|
||||
Contexts contexts;
|
||||
@@ -162,7 +162,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition)
|
||||
|
||||
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,
|
||||
{"foo"}};
|
||||
Messages messages{message.clone()};
|
||||
@@ -176,7 +176,7 @@ TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition)
|
||||
|
||||
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,
|
||||
{"foo"}};
|
||||
Messages messages{message.clone()};
|
||||
@@ -190,7 +190,7 @@ TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition)
|
||||
|
||||
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);
|
||||
|
||||
@@ -199,7 +199,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine)
|
||||
|
||||
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);
|
||||
|
||||
@@ -208,7 +208,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn)
|
||||
|
||||
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);
|
||||
|
||||
@@ -217,7 +217,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn)
|
||||
|
||||
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);
|
||||
|
||||
@@ -226,7 +226,7 @@ TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn)
|
||||
|
||||
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);
|
||||
|
||||
@@ -235,7 +235,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine)
|
||||
|
||||
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);
|
||||
|
||||
@@ -244,7 +244,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn)
|
||||
|
||||
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);
|
||||
|
||||
@@ -253,7 +253,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn)
|
||||
|
||||
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);
|
||||
|
||||
@@ -262,7 +262,7 @@ TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn)
|
||||
|
||||
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);
|
||||
|
||||
@@ -271,7 +271,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine)
|
||||
|
||||
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);
|
||||
|
||||
@@ -280,7 +280,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine)
|
||||
|
||||
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);
|
||||
|
||||
@@ -289,7 +289,7 @@ TEST_F(ClangQueryHighlightMarker, InBetweenLine)
|
||||
|
||||
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);
|
||||
|
||||
@@ -298,7 +298,7 @@ TEST_F(ClangQueryHighlightMarker, SingleLineBefore)
|
||||
|
||||
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);
|
||||
|
||||
@@ -307,7 +307,7 @@ TEST_F(ClangQueryHighlightMarker, SingleLineAfter)
|
||||
|
||||
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);
|
||||
|
||||
@@ -328,7 +328,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsIfEmpty)
|
||||
TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition)
|
||||
{
|
||||
Messages messages;
|
||||
Contexts contexts{{{1, 1, 5, 0, 3, 3, 0},
|
||||
Contexts contexts{{{{0, 1}, 1, 5, 0, 3, 3, 0},
|
||||
ContextType::MatcherArg,
|
||||
{"foo"}}};
|
||||
marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
|
||||
@@ -341,7 +341,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition)
|
||||
TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition)
|
||||
{
|
||||
Messages messages;
|
||||
Contexts contexts{{{1, 1, 5, 0, 3, 3, 0},
|
||||
Contexts contexts{{{{0, 1}, 1, 5, 0, 3, 3, 0},
|
||||
ContextType::MatcherArg,
|
||||
{"foo"}}};
|
||||
marker.setMessagesAndContexts(std::move(messages), std::move(contexts));
|
||||
@@ -353,7 +353,7 @@ TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition)
|
||||
|
||||
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,
|
||||
{"foo"}};
|
||||
Messages messages;
|
||||
@@ -367,7 +367,7 @@ TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition)
|
||||
|
||||
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,
|
||||
{"foo"}};
|
||||
Messages messages;
|
||||
|
@@ -23,6 +23,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include "dummyclangipcclient.h"
|
||||
#include "processevents-utilities.h"
|
||||
|
||||
@@ -39,11 +41,6 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gmock/gmock-matchers.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "gtest-qt-printing.h"
|
||||
|
||||
using namespace ClangBackEnd;
|
||||
|
||||
using testing::Eq;
|
||||
|
@@ -23,6 +23,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include <clangtranslationunit.h>
|
||||
#include <clangtranslationunitupdater.h>
|
||||
#include <diagnosticcontainer.h>
|
||||
@@ -30,11 +32,6 @@
|
||||
|
||||
#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::TranslationUnit;
|
||||
using ClangBackEnd::TranslationUnitUpdateInput;
|
||||
|
@@ -23,6 +23,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include <clangbackend_global.h>
|
||||
#include <clangexceptions.h>
|
||||
#include <clangtranslationunit.h>
|
||||
@@ -31,11 +33,6 @@
|
||||
|
||||
#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::TranslationUnit;
|
||||
using ClangBackEnd::TranslationUnits;
|
||||
|
286
tests/unit/unittest/filepathcache-test.cpp
Normal file
286
tests/unit/unittest/filepathcache-test.cpp
Normal 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")));
|
||||
}
|
||||
|
||||
}
|
||||
|
409
tests/unit/unittest/filepathstorage-test.cpp
Normal file
409
tests/unit/unittest/filepathstorage-test.cpp
Normal 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());
|
||||
}
|
||||
}
|
@@ -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
Reference in New Issue
Block a user