Clang: Add Symbol Indexing

It is a first step and now a database is generated if you start QtCreator.
Some code is now shared with the PchManager which can be improved in the
future.

Change-Id: Ic267fe7960f6c455d91832859a673ce98f269aa2
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-08-17 12:44:52 +02:00
parent 8488ce627b
commit 3adb71d45e
65 changed files with 1195 additions and 175 deletions

View File

@@ -30,3 +30,5 @@
#include "requestsourcelocationforrenamingmessage.h" #include "requestsourcelocationforrenamingmessage.h"
#include "requestsourcerangesanddiagnosticsforquerymessage.h" #include "requestsourcerangesanddiagnosticsforquerymessage.h"
#include "requestsourcerangesforquerymessage.h" #include "requestsourcerangesforquerymessage.h"
#include "updatepchprojectpartsmessage.h"
#include "removepchprojectpartsmessage.h"

View File

@@ -174,6 +174,7 @@ HEADERS += \
$$PWD/ipcclientprovider.h \ $$PWD/ipcclientprovider.h \
$$PWD/requestsourcerangesforquerymessage.h \ $$PWD/requestsourcerangesforquerymessage.h \
$$PWD/stringcachefwd.h \ $$PWD/stringcachefwd.h \
$$PWD/stringcachealgorithms.h $$PWD/stringcachealgorithms.h \
$$PWD/projectmanagementserverinterface.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -25,7 +25,7 @@
#pragma once #pragma once
#include "ipcserverinterface.h" #include "projectmanagementserverinterface.h"
#include <memory> #include <memory>
@@ -35,15 +35,12 @@ class PchManagerClientInterface;
class RemovePchProjectPartsMessage; class RemovePchProjectPartsMessage;
class UpdatePchProjectPartsMessage; class UpdatePchProjectPartsMessage;
class CMBIPC_EXPORT PchManagerServerInterface : public ProjectManagementServerInterface
class CMBIPC_EXPORT PchManagerServerInterface : public IpcServerInterface
{ {
public: public:
void dispatch(const MessageEnvelop &messageEnvelop) override; void dispatch(const MessageEnvelop &messageEnvelop) override;
virtual void end() = 0; virtual void end() = 0;
virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0;
virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** 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 "ipcserverinterface.h"
namespace ClangBackEnd {
class RemovePchProjectPartsMessage;
class UpdatePchProjectPartsMessage;
class CMBIPC_EXPORT ProjectManagementServerInterface : public IpcInterface
{
public:
virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0;
virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0;
};
} // namespace ClangBackEnd

View File

@@ -47,6 +47,12 @@ void RefactoringServerInterface::dispatch(const MessageEnvelop &messageEnvelop)
case MessageType::RequestSourceRangesForQueryMessage: case MessageType::RequestSourceRangesForQueryMessage:
requestSourceRangesForQueryMessage(messageEnvelop.message<RequestSourceRangesForQueryMessage>()); requestSourceRangesForQueryMessage(messageEnvelop.message<RequestSourceRangesForQueryMessage>());
break; break;
case MessageType::UpdatePchProjectPartsMessage:
updatePchProjectParts(messageEnvelop.message<UpdatePchProjectPartsMessage>());
break;
case MessageType::RemovePchProjectPartsMessage:
removePchProjectParts(messageEnvelop.message<RemovePchProjectPartsMessage>());
break;
case MessageType::CancelMessage: case MessageType::CancelMessage:
cancel(); cancel();
break; break;

View File

@@ -25,7 +25,7 @@
#pragma once #pragma once
#include "ipcserverinterface.h" #include "projectmanagementserverinterface.h"
#include <memory> #include <memory>
@@ -36,8 +36,10 @@ class RequestSourceLocationsForRenamingMessage;
class RequestSourceRangesAndDiagnosticsForQueryMessage; class RequestSourceRangesAndDiagnosticsForQueryMessage;
class RequestSourceRangesForQueryMessage; class RequestSourceRangesForQueryMessage;
class CancelMessage; class CancelMessage;
class UpdatePchProjectPartsMessage;
class RemovePchProjectPartsMessage;
class CMBIPC_EXPORT RefactoringServerInterface : public IpcServerInterface class CMBIPC_EXPORT RefactoringServerInterface : public ProjectManagementServerInterface
{ {
public: public:

View File

@@ -62,6 +62,16 @@ void RefactoringServerProxy::requestSourceRangesForQueryMessage(RequestSourceRan
writeMessageBlock.write(message); writeMessageBlock.write(message);
} }
void RefactoringServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
{
writeMessageBlock.write(message);
}
void RefactoringServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message)
{
writeMessageBlock.write(message);
}
void RefactoringServerProxy::cancel() void RefactoringServerProxy::cancel()
{ {
writeMessageBlock.write(CancelMessage()); writeMessageBlock.write(CancelMessage());

View File

@@ -53,6 +53,8 @@ public:
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override; void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override;
void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override; void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
void cancel() override; void cancel() override;
void readMessages(); void readMessages();

View File

@@ -125,12 +125,7 @@ public:
{ {
std::lock_guard<Mutex> lock(m_mutex); std::lock_guard<Mutex> lock(m_mutex);
Found found = find(stringView); return ungardedStringId(stringView);
if (!found.wasFound)
return insertString(found.iterator, stringView);
return found.iterator->id;
} }
template <typename Container> template <typename Container>
@@ -144,7 +139,7 @@ public:
std::transform(strings.begin(), std::transform(strings.begin(),
strings.end(), strings.end(),
std::back_inserter(ids), std::back_inserter(ids),
[&] (const auto &string) { return this->stringId(string); }); [&] (const auto &string) { return this->ungardedStringId(string); });
return ids; return ids;
} }
@@ -182,6 +177,16 @@ public:
} }
private: private:
IndexType ungardedStringId(Utils::SmallStringView stringView)
{
Found found = find(stringView);
if (!found.wasFound)
return insertString(found.iterator, stringView);
return found.iterator->id;
}
Found find(Utils::SmallStringView stringView) Found find(Utils::SmallStringView stringView)
{ {
return findInSorted(m_strings.cbegin(), m_strings.cend(), stringView, compare); return findInSorted(m_strings.cbegin(), m_strings.cend(), stringView, compare);

View File

@@ -43,7 +43,8 @@ HEADERS += \
$$PWD/utf8stringvector.h \ $$PWD/utf8stringvector.h \
$$PWD/sqlitedatabase.h \ $$PWD/sqlitedatabase.h \
$$PWD/sqlitetable.h \ $$PWD/sqlitetable.h \
$$PWD/sqlitecolumn.h $$PWD/sqlitecolumn.h \
$$PWD/sqliteindex.h
DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA

View File

@@ -29,6 +29,8 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <functional>
namespace Sqlite { namespace Sqlite {
class SqliteColumn class SqliteColumn
@@ -108,5 +110,7 @@ private:
}; };
using SqliteColumns = std::vector<SqliteColumn>; using SqliteColumns = std::vector<SqliteColumn>;
using SqliteColumnConstReference = std::reference_wrapper<const SqliteColumn>;
using SqliteColumnConstReferences = std::vector<SqliteColumnConstReference>;
} // namespace Sqlite } // namespace Sqlite

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** 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 "sqliteglobal.h"
#include "sqliteexception.h"
#include <utils/smallstringvector.h>
namespace Sqlite {
class SqliteIndex
{
public:
SqliteIndex(Utils::SmallString &&tableName, Utils::SmallStringVector &&columnNames)
: m_tableName(std::move(tableName)),
m_columnNames(std::move(columnNames))
{
}
Utils::SmallString sqlStatement() const
{
checkTableName();
checkColumns();
return {"CREATE INDEX IF NOT EXISTS index_",
m_tableName,
"_",
m_columnNames.join("_"),
" ON ",
m_tableName,
"(",
m_columnNames.join(", "),
")"
};
}
void checkTableName() const
{
if (m_tableName.isEmpty())
throw SqliteException("SqliteIndex has not table name!");
}
void checkColumns() const
{
if (m_columnNames.empty())
throw SqliteException("SqliteIndex has no columns!");
}
private:
Utils::SmallString m_tableName;
Utils::SmallStringVector m_columnNames;
};
using SqliteIndices = std::vector<SqliteIndex>;
} //

View File

@@ -28,6 +28,7 @@
#include "createtablesqlstatementbuilder.h" #include "createtablesqlstatementbuilder.h"
#include "sqliteglobal.h" #include "sqliteglobal.h"
#include "sqlitecolumn.h" #include "sqlitecolumn.h"
#include "sqliteindex.h"
#include "sqliteexception.h" #include "sqliteexception.h"
namespace Sqlite { namespace Sqlite {
@@ -37,6 +38,12 @@ class SqliteDatabase;
class SqliteTable class SqliteTable
{ {
public: public:
SqliteTable(std::size_t reserve = 10)
{
m_sqliteColumns.reserve(reserve);
m_sqliteIndices.reserve(reserve);
}
void setName(Utils::SmallString &&name) void setName(Utils::SmallString &&name)
{ {
m_tableName = std::move(name); m_tableName = std::move(name);
@@ -76,6 +83,13 @@ public:
return m_sqliteColumns.back(); return m_sqliteColumns.back();
} }
SqliteIndex &addIndex(const SqliteColumnConstReferences &columns)
{
m_sqliteIndices.emplace_back(m_tableName.clone(), sqliteColumnNames(columns));
return m_sqliteIndices.back();
}
const SqliteColumns &columns() const const SqliteColumns &columns() const
{ {
return m_sqliteColumns; return m_sqliteColumns;
@@ -89,22 +103,25 @@ public:
template <typename Database> template <typename Database>
void initialize(Database &database) void initialize(Database &database)
{ {
try { CreateTableSqlStatementBuilder builder;
CreateTableSqlStatementBuilder builder;
builder.setTableName(m_tableName.clone()); builder.setTableName(m_tableName.clone());
builder.setUseWithoutRowId(m_withoutRowId); builder.setUseWithoutRowId(m_withoutRowId);
builder.setUseIfNotExists(m_useIfNotExists); builder.setUseIfNotExists(m_useIfNotExists);
builder.setUseTemporaryTable(m_useTemporaryTable); builder.setUseTemporaryTable(m_useTemporaryTable);
builder.setColumns(m_sqliteColumns); builder.setColumns(m_sqliteColumns);
database.execute(builder.sqlStatement()); database.execute(builder.sqlStatement());
m_isReady = true; initializeIndices(database);
} catch (const SqliteException &exception) { m_isReady = true;
exception.printWarning(); }
} template <typename Database>
void initializeIndices(Database &database)
{
for (const SqliteIndex &index : m_sqliteIndices)
database.execute(index.sqlStatement());
} }
friend bool operator==(const SqliteTable &first, const SqliteTable &second) friend bool operator==(const SqliteTable &first, const SqliteTable &second)
@@ -116,9 +133,21 @@ public:
&& first.m_sqliteColumns == second.m_sqliteColumns; && first.m_sqliteColumns == second.m_sqliteColumns;
} }
private:
Utils::SmallStringVector sqliteColumnNames(const SqliteColumnConstReferences &columns)
{
Utils::SmallStringVector columnNames;
for (const SqliteColumn &column : columns)
columnNames.push_back(column.name());
return columnNames;
}
private: private:
Utils::SmallString m_tableName; Utils::SmallString m_tableName;
SqliteColumns m_sqliteColumns; SqliteColumns m_sqliteColumns;
SqliteIndices m_sqliteIndices;
bool m_withoutRowId = false; bool m_withoutRowId = false;
bool m_useIfNotExists = false; bool m_useIfNotExists = false;
bool m_useTemporaryTable = false; bool m_useTemporaryTable = false;

View File

@@ -36,7 +36,7 @@ template <typename Database>
class SqliteAbstractTransaction class SqliteAbstractTransaction
{ {
public: public:
virtual ~SqliteAbstractTransaction() ~SqliteAbstractTransaction()
{ {
if (!m_isAlreadyCommited) if (!m_isAlreadyCommited)
m_database.execute("ROLLBACK"); m_database.execute("ROLLBACK");
@@ -68,7 +68,6 @@ public:
{ {
database.execute("BEGIN"); database.execute("BEGIN");
} }
}; };
template <typename Database> template <typename Database>
@@ -80,7 +79,6 @@ public:
{ {
database.execute("BEGIN IMMEDIATE"); database.execute("BEGIN IMMEDIATE");
} }
}; };
template <typename Database> template <typename Database>
@@ -92,7 +90,6 @@ public:
{ {
database.execute("BEGIN EXCLUSIVE"); database.execute("BEGIN EXCLUSIVE");
} }
}; };
} // namespace Sqlite } // namespace Sqlite

View File

@@ -11,12 +11,14 @@ HEADERS += \
$$PWD/pchmanagernotifierinterface.h \ $$PWD/pchmanagernotifierinterface.h \
$$PWD/pchmanagerconnectionclient.h \ $$PWD/pchmanagerconnectionclient.h \
$$PWD/clangpchmanager_global.h \ $$PWD/clangpchmanager_global.h \
$$PWD/projectupdater.h $$PWD/projectupdater.h \
$$PWD/pchmanagerprojectupdater.h
SOURCES += \ SOURCES += \
$$PWD/pchmanagerclient.cpp \ $$PWD/pchmanagerclient.cpp \
$$PWD/pchmanagernotifierinterface.cpp \ $$PWD/pchmanagernotifierinterface.cpp \
$$PWD/pchmanagerconnectionclient.cpp \ $$PWD/pchmanagerconnectionclient.cpp \
$$PWD/projectupdater.cpp $$PWD/projectupdater.cpp \
$$PWD/pchmanagerprojectupdater.cpp

View File

@@ -52,7 +52,7 @@ class ClangPchManagerPluginData
public: public:
PchManagerClient pchManagerClient; PchManagerClient pchManagerClient;
PchManagerConnectionClient connectionClient{&pchManagerClient}; PchManagerConnectionClient connectionClient{&pchManagerClient};
QtCreatorProjectUpdater projectUpdate{connectionClient.serverProxy(), pchManagerClient}; QtCreatorProjectUpdater<PchManagerProjectUpdater> projectUpdate{connectionClient.serverProxy(), pchManagerClient};
}; };
std::unique_ptr<ClangPchManagerPluginData> ClangPchManagerPlugin::d; std::unique_ptr<ClangPchManagerPluginData> ClangPchManagerPlugin::d;

View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** 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 "pchmanagerprojectupdater.h"
#include "pchmanagerclient.h"
namespace ClangPchManager {
PchManagerProjectUpdater::PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
PchManagerClient &client)
: ProjectUpdater(server),
m_client(client)
{
}
void PchManagerProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
{
ProjectUpdater::removeProjectParts(projectPartIds);
for (const QString &projectPartiId : projectPartIds)
m_client.precompiledHeaderRemoved(projectPartiId);
}
} // namespace ClangPchManager

View File

@@ -0,0 +1,44 @@
/****************************************************************************
**
** 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 "projectupdater.h"
namespace ClangPchManager {
class PchManagerProjectUpdater : public ProjectUpdater
{
public:
PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
PchManagerClient &client);
void removeProjectParts(const QStringList &projectPartIds);
private:
PchManagerClient &m_client;
};
} // namespace ClangPchManager

View File

@@ -52,10 +52,8 @@ public:
Utils::PathStringVector sources; Utils::PathStringVector sources;
}; };
ProjectUpdater::ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server, ProjectUpdater::ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server)
PchManagerClient &client) : m_server(server)
: m_server(server),
m_client(client)
{ {
} }
@@ -75,9 +73,6 @@ void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
ClangBackEnd::RemovePchProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)}; ClangBackEnd::RemovePchProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)};
m_server.removePchProjectParts(std::move(message)); m_server.removePchProjectParts(std::move(message));
for (const QString &projectPartiId : projectPartIds)
m_client.precompiledHeaderRemoved(projectPartiId);
} }
void ProjectUpdater::setExcludedPaths(Utils::PathStringVector &&excludedPaths) void ProjectUpdater::setExcludedPaths(Utils::PathStringVector &&excludedPaths)

View File

@@ -35,7 +35,7 @@ class ProjectFile;
} }
namespace ClangBackEnd { namespace ClangBackEnd {
class PchManagerServerInterface; class ProjectManagementServerInterface;
namespace V2 { namespace V2 {
class ProjectPartContainer; class ProjectPartContainer;
@@ -51,11 +51,10 @@ namespace ClangPchManager {
class HeaderAndSources; class HeaderAndSources;
class PchManagerClient; class PchManagerClient;
class ProjectUpdater class CLANGPCHMANAGER_EXPORT ProjectUpdater
{ {
public: public:
ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server, ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server);
PchManagerClient &client);
void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts, void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts,
ClangBackEnd::V2::FileContainers &&generatedFiles); ClangBackEnd::V2::FileContainers &&generatedFiles);
@@ -77,8 +76,7 @@ unittest_public:
private: private:
Utils::PathStringVector m_excludedPaths; Utils::PathStringVector m_excludedPaths;
ClangBackEnd::PchManagerServerInterface &m_server; ClangBackEnd::ProjectManagementServerInterface &m_server;
PchManagerClient &m_client;
}; };
} // namespace ClangPchManager } // namespace ClangPchManager

View File

@@ -26,26 +26,18 @@
#include "qtcreatorprojectupdater.h" #include "qtcreatorprojectupdater.h"
#include <cpptools/abstracteditorsupport.h> #include <cpptools/abstracteditorsupport.h>
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
namespace ClangPchManager { namespace ClangPchManager {
static CppTools::CppModelManager *cppModelManager() namespace Internal {
CppTools::CppModelManager *cppModelManager()
{ {
return CppTools::CppModelManager::instance(); return CppTools::CppModelManager::instance();
} }
QtCreatorProjectUpdater::QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
PchManagerClient &client)
: ProjectUpdater(server, client)
{
connectToCppModelManager();
}
namespace {
std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles() std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles()
{ {
auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports(); auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports();
@@ -85,30 +77,7 @@ std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project
convertToRawPointer); convertToRawPointer);
return projectParts; return projectParts;
}
} }
} // namespace Internal
void QtCreatorProjectUpdater::projectPartsUpdated(ProjectExplorer::Project *project)
{
updateProjectParts(createProjectParts(project), createGeneratedFiles());
}
void QtCreatorProjectUpdater::projectPartsRemoved(const QStringList &projectPartIds)
{
removeProjectParts(projectPartIds);
}
void QtCreatorProjectUpdater::connectToCppModelManager()
{
connect(cppModelManager(),
&CppTools::CppModelManager::projectPartsUpdated,
this,
&QtCreatorProjectUpdater::projectPartsUpdated);
connect(cppModelManager(),
&CppTools::CppModelManager::projectPartsRemoved,
this,
&QtCreatorProjectUpdater::projectPartsRemoved);
}
} // namespace ClangPchManager } // namespace ClangPchManager

View File

@@ -25,7 +25,11 @@
#pragma once #pragma once
#include "projectupdater.h" #include "pchmanagerprojectupdater.h"
#include <cpptools/cppmodelmanager.h>
#include <filecontainerv2.h>
#include <QObject> #include <QObject>
@@ -33,19 +37,57 @@ namespace ProjectExplorer {
class Project; class Project;
} }
namespace CppTools {
class CppModelManager;
}
namespace ClangPchManager { namespace ClangPchManager {
class QtCreatorProjectUpdater : public QObject, public ProjectUpdater namespace Internal {
CLANGPCHMANAGER_EXPORT CppTools::CppModelManager *cppModelManager();
CLANGPCHMANAGER_EXPORT std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles();
CLANGPCHMANAGER_EXPORT std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project *project);
}
template <typename ProjectUpdaterType>
class QtCreatorProjectUpdater : public ProjectUpdaterType
{ {
public: public:
QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server, template <typename ClientType>
PchManagerClient &client); QtCreatorProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
ClientType &client)
: ProjectUpdaterType(server, client)
{
connectToCppModelManager();
}
void projectPartsUpdated(ProjectExplorer::Project *project); QtCreatorProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server)
void projectPartsRemoved(const QStringList &projectPartIds); : ProjectUpdaterType(server)
{
connectToCppModelManager();
}
void projectPartsUpdated(ProjectExplorer::Project *project)
{
ProjectUpdaterType::updateProjectParts(Internal::createProjectParts(project),
Internal::createGeneratedFiles());
}
void projectPartsRemoved(const QStringList &projectPartIds)
{
ProjectUpdaterType::removeProjectParts(projectPartIds);
}
private: private:
void connectToCppModelManager(); void connectToCppModelManager()
{
QObject::connect(Internal::cppModelManager(),
&CppTools::CppModelManager::projectPartsUpdated,
[&] (ProjectExplorer::Project *project) { projectPartsUpdated(project); });
QObject::connect(Internal::cppModelManager(),
&CppTools::CppModelManager::projectPartsRemoved,
[&] (const QStringList &projectPartIds) { projectPartsRemoved(projectPartIds); });
}
}; };
} // namespace ClangPchManager } // namespace ClangPchManager

View File

@@ -11,7 +11,8 @@ HEADERS += \
$$PWD/clangqueryexamplehighlightmarker.h \ $$PWD/clangqueryexamplehighlightmarker.h \
$$PWD/clangqueryhighlightmarker.h \ $$PWD/clangqueryhighlightmarker.h \
$$PWD/clangqueryexamplehighlighter.h \ $$PWD/clangqueryexamplehighlighter.h \
$$PWD/clangqueryhighlighter.h $$PWD/clangqueryhighlighter.h \
$$PWD/refactoringprojectupdater.h
SOURCES += \ SOURCES += \
$$PWD/refactoringengine.cpp \ $$PWD/refactoringengine.cpp \
@@ -22,4 +23,5 @@ SOURCES += \
$$PWD/projectpartutilities.cpp \ $$PWD/projectpartutilities.cpp \
$$PWD/clangqueryprojectsfindfilter.cpp \ $$PWD/clangqueryprojectsfindfilter.cpp \
$$PWD/clangqueryexamplehighlighter.cpp \ $$PWD/clangqueryexamplehighlighter.cpp \
$$PWD/clangqueryhighlighter.cpp $$PWD/clangqueryhighlighter.cpp \
$$PWD/refactoringprojectupdater.cpp

View File

@@ -5,4 +5,5 @@ QTC_LIB_DEPENDS += \
QTC_PLUGIN_DEPENDS += \ QTC_PLUGIN_DEPENDS += \
coreplugin \ coreplugin \
cpptools \ cpptools \
texteditor texteditor \
clangpchmanager

View File

@@ -25,6 +25,8 @@
#include "clangrefactoringplugin.h" #include "clangrefactoringplugin.h"
#include <clangpchmanager/qtcreatorprojectupdater.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -50,6 +52,7 @@ std::unique_ptr<ClangRefactoringPluginData> ClangRefactoringPlugin::d;
class ClangRefactoringPluginData class ClangRefactoringPluginData
{ {
using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater<ClangPchManager::ProjectUpdater>;
public: public:
RefactoringClient refactoringClient; RefactoringClient refactoringClient;
ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient}; ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient};
@@ -58,6 +61,9 @@ public:
QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(), QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(),
qtCreatorSearch, qtCreatorSearch,
refactoringClient}; refactoringClient};
ProjectUpdater projectUpdate{connectionClient.serverProxy()};
}; };
ClangRefactoringPlugin::ClangRefactoringPlugin() ClangRefactoringPlugin::ClangRefactoringPlugin()

View File

@@ -0,0 +1,37 @@
/****************************************************************************
**
** 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 "refactoringprojectupdater.h"
namespace ClangRefactoring {
RefactoringProjectUpdater::RefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
RefactoringClient &)
: ClangPchManager::ProjectUpdater(server)
{
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,41 @@
/****************************************************************************
**
** 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 <clangpchmanager/projectupdater.h>
namespace ClangRefactoring {
class RefactoringClient;
class RefactoringProjectUpdater : public ClangPchManager::ProjectUpdater
{
public:
RefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
RefactoringClient &client);
};
} // namespace ClangRefactoring

View File

@@ -50,6 +50,13 @@ public:
Utils::PathString sourcePath; Utils::PathString sourcePath;
}; };
enum LocationGetter
{
SourceId = 0,
Line,
Column
};
std::vector<Location> locations; std::vector<Location> locations;
std::unordered_map<qint64, Utils::PathString> sources; std::unordered_map<qint64, Utils::PathString> sources;
}; };

View File

@@ -26,14 +26,19 @@
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCoreApplication> #include <QCoreApplication>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QDir>
#include <connectionserver.h> #include <connectionserver.h>
#include <stringcache.h>
#include <refactoringserver.h> #include <refactoringserver.h>
#include <refactoringclientproxy.h> #include <refactoringclientproxy.h>
#include <symbolindexing.h>
using ClangBackEnd::FilePathCache;
using ClangBackEnd::RefactoringClientProxy; using ClangBackEnd::RefactoringClientProxy;
using ClangBackEnd::RefactoringServer; using ClangBackEnd::RefactoringServer;
using ClangBackEnd::ConnectionServer; using ClangBackEnd::ConnectionServer;
using ClangBackEnd::SymbolIndexing;
QString processArguments(QCoreApplication &application) QString processArguments(QCoreApplication &application)
{ {
@@ -52,7 +57,7 @@ QString processArguments(QCoreApplication &application)
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ try {
//QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false")); //QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false"));
QCoreApplication::setOrganizationName(QStringLiteral("QtProject")); QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
@@ -64,13 +69,17 @@ int main(int argc, char *argv[])
const QString connection = processArguments(application); const QString connection = processArguments(application);
RefactoringServer clangCodeModelServer; FilePathCache<std::mutex> filePathCache;
SymbolIndexing symbolIndexing{filePathCache, Utils::PathString{QDir::tempPath() + "/symbol.db"}};
RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache};
ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection); ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection);
connectionServer.start(); connectionServer.start();
connectionServer.setServer(&clangCodeModelServer); connectionServer.setServer(&clangCodeModelServer);
return application.exec(); return application.exec();
} catch (const Sqlite::SqliteException &exception) {
exception.printWarning();
} }

View File

@@ -9,7 +9,9 @@ HEADERS += \
$$PWD/symbolscollectorinterface.h \ $$PWD/symbolscollectorinterface.h \
$$PWD/symbolstorageinterface.h \ $$PWD/symbolstorageinterface.h \
$$PWD/symbolstorage.h \ $$PWD/symbolstorage.h \
$$PWD/storagesqlitestatementfactory.h $$PWD/storagesqlitestatementfactory.h \
$$PWD/symbolindexing.h \
$$PWD/symbolindexinginterface.h
!isEmpty(LIBTOOLING_LIBS) { !isEmpty(LIBTOOLING_LIBS) {
SOURCES += \ SOURCES += \
@@ -55,4 +57,5 @@ SOURCES += \
$$PWD/symbolindexer.cpp \ $$PWD/symbolindexer.cpp \
$$PWD/symbolentry.cpp \ $$PWD/symbolentry.cpp \
$$PWD/sourcelocationentry.cpp \ $$PWD/sourcelocationentry.cpp \
$$PWD/symbolstorage.cpp $$PWD/symbolstorage.cpp \
$$PWD/symbolindexing.cpp

View File

@@ -110,4 +110,11 @@ private:
std::vector<UnsavedFileContent> m_unsavedFileContents; std::vector<UnsavedFileContent> m_unsavedFileContents;
}; };
extern template
void ClangTool::addFiles<Utils::SmallStringVector>(const Utils::SmallStringVector &filePaths,
const Utils::SmallStringVector &arguments);
extern template
void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths,
const Utils::SmallStringVector &arguments);
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -35,12 +35,14 @@
#include <clang/Frontend/FrontendAction.h> #include <clang/Frontend/FrontendAction.h>
#include <mutex>
namespace ClangBackEnd { namespace ClangBackEnd {
class CollectSymbolsAction class CollectSymbolsAction
{ {
public: public:
CollectSymbolsAction(FilePathCache<> &filePathCache) CollectSymbolsAction(FilePathCache<std::mutex> &filePathCache)
: m_filePathCache(filePathCache) : m_filePathCache(filePathCache)
{} {}
@@ -64,7 +66,7 @@ public:
private: private:
SymbolEntries m_symbolEntries; SymbolEntries m_symbolEntries;
SourceLocationEntries m_sourceLocationEntries; SourceLocationEntries m_sourceLocationEntries;
FilePathCache<> &m_filePathCache; FilePathCache<std::mutex> &m_filePathCache;
}; };

View File

@@ -50,7 +50,7 @@ class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor<CollectSymbol
public: public:
CollectSymbolsASTVisitor(SymbolEntries &symbolEntries, CollectSymbolsASTVisitor(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries, SourceLocationEntries &sourceLocationEntries,
FilePathCache<> &filePathCache, FilePathCache<std::mutex> &filePathCache,
const clang::SourceManager &sourceManager) const clang::SourceManager &sourceManager)
: m_symbolEntries(symbolEntries), : m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries), m_sourceLocationEntries(sourceLocationEntries),
@@ -58,8 +58,16 @@ public:
m_sourceManager(sourceManager) m_sourceManager(sourceManager)
{} {}
bool shouldVisitTemplateInstantiations() const
{
return true;
}
bool VisitNamedDecl(const clang::NamedDecl *declaration) bool VisitNamedDecl(const clang::NamedDecl *declaration)
{ {
if (!declaration->getIdentifier())
return true;
SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl()); SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
auto sourceLocation = declaration->getLocation(); auto sourceLocation = declaration->getLocation();
@@ -141,7 +149,7 @@ private:
SymbolEntries &m_symbolEntries; SymbolEntries &m_symbolEntries;
std::unordered_map<uint, FilePathIndex> m_filePathIndices; std::unordered_map<uint, FilePathIndex> m_filePathIndices;
SourceLocationEntries &m_sourceLocationEntries; SourceLocationEntries &m_sourceLocationEntries;
FilePathCache<> &m_filePathCache; FilePathCache<std::mutex> &m_filePathCache;
const clang::SourceManager &m_sourceManager; const clang::SourceManager &m_sourceManager;
}; };

View File

@@ -40,13 +40,14 @@ class CollectSymbolsConsumer : public clang::ASTConsumer
public: public:
CollectSymbolsConsumer(SymbolEntries &symbolEntries, CollectSymbolsConsumer(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries, SourceLocationEntries &sourceLocationEntries,
FilePathCache<> &filePathCache) FilePathCache<std::mutex> &filePathCache)
: m_symbolEntries(symbolEntries), : m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries), m_sourceLocationEntries(sourceLocationEntries),
m_filePathCache(filePathCache) m_filePathCache(filePathCache)
{} {}
void HandleTranslationUnit(clang::ASTContext &astContext) override { void HandleTranslationUnit(clang::ASTContext &astContext) override
{
CollectSymbolsASTVisitor visitor{m_symbolEntries, CollectSymbolsASTVisitor visitor{m_symbolEntries,
m_sourceLocationEntries, m_sourceLocationEntries,
m_filePathCache, m_filePathCache,
@@ -54,9 +55,20 @@ public:
visitor.TraverseDecl(astContext.getTranslationUnitDecl()); visitor.TraverseDecl(astContext.getTranslationUnitDecl());
} }
bool shouldSkipFunctionBody(clang::Decl *declation) override
{
const clang::SourceManager &sourceManager = declation->getASTContext().getSourceManager();
const clang::SourceLocation location = declation->getLocation();
if (sourceManager.isInSystemHeader(location))
return true;
return false;
}
private: private:
SymbolEntries &m_symbolEntries; SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries; SourceLocationEntries &m_sourceLocationEntries;
FilePathCache<> &m_filePathCache; FilePathCache<std::mutex> &m_filePathCache;
}; };
} }

View File

@@ -27,6 +27,7 @@
#include "symbolfinder.h" #include "symbolfinder.h"
#include "clangquery.h" #include "clangquery.h"
#include "symbolindexing.h"
#include <refactoringclientinterface.h> #include <refactoringclientinterface.h>
#include <clangrefactoringmessages.h> #include <clangrefactoringmessages.h>
@@ -38,7 +39,10 @@
namespace ClangBackEnd { namespace ClangBackEnd {
RefactoringServer::RefactoringServer() RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing,
FilePathCache<std::mutex> &filePathCache)
: m_symbolIndexing(symbolIndexing),
m_filePathCache(filePathCache)
{ {
m_pollTimer.setInterval(100); m_pollTimer.setInterval(100);
@@ -88,7 +92,17 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo
{ {
gatherSourceRangesForQueryMessages(message.takeSources(), gatherSourceRangesForQueryMessages(message.takeSources(),
message.takeUnsavedContent(), message.takeUnsavedContent(),
message.takeQuery()); message.takeQuery());
}
void RefactoringServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
{
m_symbolIndexing.updateProjectParts(message.takeProjectsParts(), message.takeGeneratedFiles());
}
void RefactoringServer::removePchProjectParts(RemovePchProjectPartsMessage &&)
{
} }
void RefactoringServer::cancel() void RefactoringServer::cancel()

View File

@@ -42,6 +42,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class SourceRangesForQueryMessage; class SourceRangesForQueryMessage;
class SymbolIndexingInterface;
namespace V2 { namespace V2 {
class FileContainer; class FileContainer;
@@ -52,12 +53,15 @@ class RefactoringServer : public RefactoringServerInterface,
{ {
using Future = std::future<SourceRangesForQueryMessage>; using Future = std::future<SourceRangesForQueryMessage>;
public: public:
RefactoringServer(); RefactoringServer(SymbolIndexingInterface &symbolIndexing,
FilePathCache<std::mutex> &filePathCache);
void end() override; void end() override;
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override; void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override;
void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override; void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override;
void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
void cancel() override; void cancel() override;
bool isCancelingJobs() const; bool isCancelingJobs() const;
@@ -75,9 +79,10 @@ private:
Utils::SmallString &&query); Utils::SmallString &&query);
private: private:
FilePathCache<std::mutex> m_filePathCache;
ClangQueryGatherer m_gatherer; ClangQueryGatherer m_gatherer;
QTimer m_pollTimer; QTimer m_pollTimer;
SymbolIndexingInterface &m_symbolIndexing;
FilePathCache<std::mutex> &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -53,8 +53,9 @@ public:
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("symbols"); table.setName("symbols");
table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("usr", Sqlite::ColumnType::Text); const Sqlite::SqliteColumn &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
table.addColumn("symbolName", Sqlite::ColumnType::Text); table.addColumn("symbolName", Sqlite::ColumnType::Text);
table.addIndex({usrColumn});
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database); table.initialize(database);
@@ -71,7 +72,8 @@ public:
table.addColumn("symbolId", Sqlite::ColumnType::Integer); table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer); table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer); table.addColumn("column", Sqlite::ColumnType::Integer);
table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::SqliteColumn &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn});
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database); table.initialize(database);
@@ -101,9 +103,11 @@ public:
table.setName("newSymbols"); table.setName("newSymbols");
table.setUseTemporaryTable(true); table.setUseTemporaryTable(true);
table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("symbolId", Sqlite::ColumnType::Integer); const Sqlite::SqliteColumn &symbolIdColumn = table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("usr", Sqlite::ColumnType::Text); const Sqlite::SqliteColumn &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
table.addColumn("symbolName", Sqlite::ColumnType::Text); const Sqlite::SqliteColumn &symbolNameColumn = table.addColumn("symbolName", Sqlite::ColumnType::Text);
table.addIndex({usrColumn, symbolNameColumn});
table.addIndex({symbolIdColumn});
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database); table.initialize(database);
@@ -121,7 +125,8 @@ public:
table.addColumn("symbolId", Sqlite::ColumnType::Integer); table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer); table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer); table.addColumn("column", Sqlite::ColumnType::Integer);
table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::SqliteColumn &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn});
Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database); Sqlite::SqliteImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database); table.initialize(database);
@@ -142,39 +147,49 @@ public:
database}; database};
WriteStatement insertLocationsToNewLocationsStatement{ WriteStatement insertLocationsToNewLocationsStatement{
"INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)", "INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)",
database}; database
};
// WriteStatement syncNewLocationsToLocationsStatement{ // WriteStatement syncNewLocationsToLocationsStatement{
// "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations", // "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
// database}; // database};
ReadStatement selectNewSourceIdsStatement{ ReadStatement selectNewSourceIdsStatement{
"SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)", "SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)",
database}; database
};
WriteStatement addNewSymbolsToSymbolsStatement{ WriteStatement addNewSymbolsToSymbolsStatement{
"INSERT INTO symbols(usr, symbolname) " "INSERT INTO symbols(usr, symbolName) "
"SELECT usr, symbolname FROM newsymbols WHERE NOT EXISTS " "SELECT usr, symbolName FROM newSymbols WHERE NOT EXISTS "
"(SELECT usr FROM symbols WHERE usr == newsymbols.usr)", "(SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)",
database}; database
};
WriteStatement insertSourcesStatement{ WriteStatement insertSourcesStatement{
"INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)", "INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)",
database}; database
};
WriteStatement syncNewSymbolsFromSymbolsStatement{ WriteStatement syncNewSymbolsFromSymbolsStatement{
"UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)", "UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)",
database}; database
};
WriteStatement syncSymbolsIntoNewLocationsStatement{ WriteStatement syncSymbolsIntoNewLocationsStatement{
"UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)", "UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)",
database}; database
};
WriteStatement deleteAllLocationsFromUpdatedFilesStatement{ WriteStatement deleteAllLocationsFromUpdatedFilesStatement{
"DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)", "DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)",
database}; database
};
WriteStatement insertNewLocationsInLocationsStatement{ WriteStatement insertNewLocationsInLocationsStatement{
"INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations", "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
database}; database
};
WriteStatement deleteNewSymbolsTableStatement{ WriteStatement deleteNewSymbolsTableStatement{
"DELETE FROM newSymbols", "DELETE FROM newSymbols",
database}; database
};
WriteStatement deleteNewLocationsTableStatement{ WriteStatement deleteNewLocationsTableStatement{
"DELETE FROM newLocations", "DELETE FROM newLocations",
database}; database
};
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -33,11 +33,14 @@ SymbolIndexer::SymbolIndexer(SymbolsCollectorInterface &symbolsCollector, Symbol
{ {
} }
void SymbolIndexer::updateProjectParts(V2::ProjectPartContainers &&projectParts) void SymbolIndexer::updateProjectParts(V2::ProjectPartContainers &&projectParts,
V2::FileContainers &&generatedFiles)
{ {
for (const V2::ProjectPartContainer &projectPart : projectParts) for (const V2::ProjectPartContainer &projectPart : projectParts)
m_symbolsCollector.addFiles(projectPart.sourcePaths(), projectPart.arguments()); m_symbolsCollector.addFiles(projectPart.sourcePaths(), projectPart.arguments());
m_symbolsCollector.addUnsavedFiles(generatedFiles);
m_symbolsCollector.collectSymbols(); m_symbolsCollector.collectSymbols();
m_symbolStorage.addSymbolsAndSourceLocations(m_symbolsCollector.symbols(), m_symbolStorage.addSymbolsAndSourceLocations(m_symbolsCollector.symbols(),

View File

@@ -29,6 +29,7 @@
#include "symbolstorageinterface.h" #include "symbolstorageinterface.h"
#include <projectpartcontainerv2.h> #include <projectpartcontainerv2.h>
#include <filecontainerv2.h>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -38,7 +39,8 @@ public:
SymbolIndexer(SymbolsCollectorInterface &symbolsCollector, SymbolIndexer(SymbolsCollectorInterface &symbolsCollector,
SymbolStorageInterface &symbolStorage); SymbolStorageInterface &symbolStorage);
void updateProjectParts(V2::ProjectPartContainers &&projectParts); void updateProjectParts(V2::ProjectPartContainers &&projectParts,
V2::FileContainers &&generatedFiles);
private: private:
SymbolsCollectorInterface &m_symbolsCollector; SymbolsCollectorInterface &m_symbolsCollector;

View File

@@ -0,0 +1,30 @@
/****************************************************************************
**
** 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 "symbolindexing.h"
namespace ClangBackEnd {
} // namespace ClangBackEnd

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** 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 "symbolindexinginterface.h"
#include "storagesqlitestatementfactory.h"
#include "symbolindexer.h"
#include "symbolscollector.h"
#include "symbolstorage.h"
#include <stringcache.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
namespace ClangBackEnd {
class SymbolIndexing final : public SymbolIndexingInterface
{
public:
using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<Sqlite::SqliteDatabase,
Sqlite::SqliteReadStatement,
Sqlite::SqliteWriteStatement>;
using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
SymbolIndexing(FilePathCache<std::mutex> &filePathCache,
Utils::PathString &&databaseFilePath)
: m_filePathCache(filePathCache),
m_database(std::move(databaseFilePath))
{
}
SymbolIndexer &indexer()
{
return m_indexer;
}
Sqlite::SqliteDatabase &database()
{
return m_database;
}
void updateProjectParts(V2::ProjectPartContainers &&projectParts,
V2::FileContainers &&generatedFiles)
{
m_indexer.updateProjectParts(std::move(projectParts), std::move(generatedFiles));
}
private:
FilePathCache<std::mutex> &m_filePathCache;
Sqlite::SqliteDatabase m_database;
SymbolsCollector m_collector{m_filePathCache};
StatementFactory m_statementFactory{m_database};
Storage m_symbolStorage{m_statementFactory, m_filePathCache};
SymbolIndexer m_indexer{m_collector, m_symbolStorage};
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,40 @@
/****************************************************************************
**
** 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 <projectpartcontainerv2.h>
#include <filecontainerv2.h>
namespace ClangBackEnd {
class SymbolIndexingInterface
{
public:
virtual void updateProjectParts(V2::ProjectPartContainers &&projectParts,
V2::FileContainers &&generatedFiles) = 0;
};
} // namespace ClangBackEnd

View File

@@ -27,7 +27,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
SymbolsCollector::SymbolsCollector(FilePathCache<> &filePathCache) SymbolsCollector::SymbolsCollector(FilePathCache<std::mutex> &filePathCache)
: m_collectSymbolsAction(filePathCache) : m_collectSymbolsAction(filePathCache)
{ {
} }
@@ -37,6 +37,11 @@ void SymbolsCollector::addFiles(const Utils::PathStringVector &filePaths, const
ClangTool::addFiles(filePaths, arguments); ClangTool::addFiles(filePaths, arguments);
} }
void SymbolsCollector::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
{
ClangTool::addUnsavedFiles(unsavedFiles);
}
void SymbolsCollector::collectSymbols() void SymbolsCollector::collectSymbols()
{ {
auto tool = createTool(); auto tool = createTool();

View File

@@ -37,11 +37,13 @@ namespace ClangBackEnd {
class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface
{ {
public: public:
SymbolsCollector(FilePathCache<> &filePathCache); SymbolsCollector(FilePathCache<std::mutex> &filePathCache);
void addFiles(const Utils::PathStringVector &filePaths, void addFiles(const Utils::PathStringVector &filePaths,
const Utils::SmallStringVector &arguments) override; const Utils::SmallStringVector &arguments) override;
void addUnsavedFiles(const V2::FileContainers &unsavedFiles) override;
void collectSymbols() override; void collectSymbols() override;
const SymbolEntries &symbols() const override; const SymbolEntries &symbols() const override;

View File

@@ -28,6 +28,8 @@
#include "symbolentry.h" #include "symbolentry.h"
#include "sourcelocationentry.h" #include "sourcelocationentry.h"
#include <filecontainerv2.h>
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
#include <string> #include <string>
@@ -41,6 +43,8 @@ public:
virtual void addFiles(const Utils::PathStringVector &filePaths, virtual void addFiles(const Utils::PathStringVector &filePaths,
const Utils::SmallStringVector &arguments) = 0; const Utils::SmallStringVector &arguments) = 0;
virtual void addUnsavedFiles(const V2::FileContainers &unsavedFiles) = 0;
virtual void collectSymbols() = 0; virtual void collectSymbols() = 0;
virtual const SymbolEntries &symbols() const = 0; virtual const SymbolEntries &symbols() const = 0;

View File

@@ -27,9 +27,12 @@
#include "symbolstorageinterface.h" #include "symbolstorageinterface.h"
#include <sqliteexception.h>
#include <sqlitetransaction.h> #include <sqlitetransaction.h>
#include <stringcache.h> #include <stringcache.h>
#include <mutex>
namespace ClangBackEnd { namespace ClangBackEnd {
template <typename StatementFactory> template <typename StatementFactory>
@@ -42,7 +45,7 @@ class SymbolStorage : public SymbolStorageInterface
public: public:
SymbolStorage(StatementFactory &statementFactory, SymbolStorage(StatementFactory &statementFactory,
FilePathCache<> &filePathCache) FilePathCache<std::mutex> &filePathCache)
: m_statementFactory(statementFactory), : m_statementFactory(statementFactory),
m_filePathCache(filePathCache) m_filePathCache(filePathCache)
{ {
@@ -149,7 +152,7 @@ public:
private: private:
StatementFactory &m_statementFactory; StatementFactory &m_statementFactory;
FilePathCache<> &m_filePathCache; FilePathCache<std::mutex> &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,36 @@
void function();
void function()
{
int x;
x = 20;
}
template <typename T>
T templateFunction(T t)
{
return t;
}
template <>
int templateFunction(int t)
{
return t;
}
extern template double templateFunction<double>(double);
template double templateFunction<double>(double);
template<typename T>
using TemplateFunctionType = T(&)(T);
TemplateFunctionType<int> aliasToTemplateFunction = templateFunction<int>;
void f()
{
aliasToTemplateFunction(1);
}
void f(int);
void f(double);

View File

@@ -0,0 +1 @@
#include "symbolscollector_generated_file.h"

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include <utils/smallstringio.h>
#include <QtGlobal> #include <QtGlobal>
#include <iosfwd> #include <iosfwd>

View File

@@ -44,6 +44,12 @@ public:
MOCK_METHOD1(requestSourceRangesForQueryMessage, MOCK_METHOD1(requestSourceRangesForQueryMessage,
void (const ClangBackEnd::RequestSourceRangesForQueryMessage&)); void (const ClangBackEnd::RequestSourceRangesForQueryMessage&));
MOCK_METHOD1(updatePchProjectParts,
void (const ClangBackEnd::UpdatePchProjectPartsMessage&));
MOCK_METHOD1(removePchProjectParts,
void (const ClangBackEnd::RemovePchProjectPartsMessage&));
MOCK_METHOD0(cancel, MOCK_METHOD0(cancel,
void()); void());
@@ -61,4 +67,14 @@ public:
{ {
requestSourceRangesForQueryMessage(message); requestSourceRangesForQueryMessage(message);
} }
void updatePchProjectParts(ClangBackEnd::UpdatePchProjectPartsMessage &&message) override
{
updatePchProjectParts(message);
}
void removePchProjectParts(ClangBackEnd::RemovePchProjectPartsMessage &&message) override
{
removePchProjectParts(message);
}
}; };

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** 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 "googletest.h"
#include <symbolindexinginterface.h>
class MockSymbolIndexing : public ClangBackEnd::SymbolIndexingInterface
{
public:
MOCK_METHOD2(updateProjectParts,
void(const ClangBackEnd::V2::ProjectPartContainers &projectParts,
const ClangBackEnd::V2::FileContainers &generatedFiles));
void updateProjectParts(ClangBackEnd::V2::ProjectPartContainers &&projectParts,
ClangBackEnd::V2::FileContainers &&generatedFiles) override
{
updateProjectParts(projectParts, generatedFiles);
}
};

View File

@@ -39,6 +39,9 @@ public:
void(const Utils::PathStringVector &filePaths, void(const Utils::PathStringVector &filePaths,
const Utils::SmallStringVector &arguments)); const Utils::SmallStringVector &arguments));
MOCK_METHOD1(addUnsavedFiles,
void(const ClangBackEnd::V2::FileContainers &unsavedFiles));
MOCK_CONST_METHOD0(symbols, MOCK_CONST_METHOD0(symbols,
const ClangBackEnd::SymbolEntries &()); const ClangBackEnd::SymbolEntries &());

View File

@@ -29,7 +29,7 @@
#include "mockpchmanagerserver.h" #include "mockpchmanagerserver.h"
#include <pchmanagerclient.h> #include <pchmanagerclient.h>
#include <projectupdater.h> #include <pchmanagerprojectupdater.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h> #include <removepchprojectpartsmessage.h>
@@ -49,7 +49,7 @@ protected:
MockPchManagerServer mockPchManagerServer; MockPchManagerServer mockPchManagerServer;
ClangPchManager::PchManagerClient client; ClangPchManager::PchManagerClient client;
MockPchManagerNotifier mockPchManagerNotifier{client}; MockPchManagerNotifier mockPchManagerNotifier{client};
ClangPchManager::ProjectUpdater projectUpdater{mockPchManagerServer, client}; ClangPchManager::PchManagerProjectUpdater projectUpdater{mockPchManagerServer, client};
Utils::SmallString projectPartId{"projectPartId"}; Utils::SmallString projectPartId{"projectPartId"};
Utils::SmallString pchFilePath{"/path/to/pch"}; Utils::SmallString pchFilePath{"/path/to/pch"};
PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone()}}}; PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone()}}};

View File

@@ -29,7 +29,7 @@
#include "mockpchmanagernotifier.h" #include "mockpchmanagernotifier.h"
#include "mockpchmanagerserver.h" #include "mockpchmanagerserver.h"
#include <projectupdater.h> #include <pchmanagerprojectupdater.h>
#include <pchmanagerclient.h> #include <pchmanagerclient.h>
#include <precompiledheadersupdatedmessage.h> #include <precompiledheadersupdatedmessage.h>
@@ -60,7 +60,7 @@ protected:
ClangPchManager::PchManagerClient pchManagerClient; ClangPchManager::PchManagerClient pchManagerClient;
MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient}; MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient};
NiceMock<MockPchManagerServer> mockPchManagerServer; NiceMock<MockPchManagerServer> mockPchManagerServer;
ClangPchManager::ProjectUpdater updater{mockPchManagerServer, pchManagerClient}; ClangPchManager::ProjectUpdater updater{mockPchManagerServer};
Utils::SmallString projectPartId{"project1"}; Utils::SmallString projectPartId{"project1"};
Utils::SmallString projectPartId2{"project2"}; Utils::SmallString projectPartId2{"project2"};
Utils::PathStringVector headerPaths = {"/path/to/header1.h", "/path/to/header2.h"}; Utils::PathStringVector headerPaths = {"/path/to/header1.h", "/path/to/header2.h"};
@@ -87,7 +87,7 @@ TEST_F(ProjectUpdater, CallUpdatePchProjectParts)
TEST_F(ProjectUpdater, CallRemovePchProjectParts) TEST_F(ProjectUpdater, CallRemovePchProjectParts)
{ {
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(_)).Times(AnyNumber());
ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}};
EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message)); EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message));
@@ -95,14 +95,15 @@ TEST_F(ProjectUpdater, CallRemovePchProjectParts)
updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)}); updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)});
} }
TEST_F(ProjectUpdater, CallPrecompiledHeaderRemoved) TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater)
{ {
ClangPchManager::PchManagerProjectUpdater pchUpdater{mockPchManagerServer, pchManagerClient};
ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}};
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString())); EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString()));
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString())); EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString()));
updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)}); pchUpdater.removeProjectParts({QString(projectPartId), QString(projectPartId2)});
} }
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer) TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)

View File

@@ -47,6 +47,11 @@ using ::testing::Args;
using ::testing::Property; using ::testing::Property;
using ::testing::Eq; using ::testing::Eq;
using ClangBackEnd::UpdatePchProjectPartsMessage;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::RemovePchProjectPartsMessage;
class RefactoringClientServerInProcess : public ::testing::Test class RefactoringClientServerInProcess : public ::testing::Test
{ {
protected: protected:
@@ -169,6 +174,31 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesForQueryMessage)
scheduleServerMessages(); scheduleServerMessages();
} }
TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage)
{
ProjectPartContainer projectPart2{"projectPartId",
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{TESTDATA_DIR "/includecollector_header.h"},
{TESTDATA_DIR "/includecollector_main.cpp"}};
FileContainer fileContainer{{"/path/to/", "file"}, "content", {}};
UpdatePchProjectPartsMessage message{{projectPart2}, {fileContainer}};
EXPECT_CALL(mockRefactoringServer, updatePchProjectParts(message));
serverProxy.updatePchProjectParts(message.clone());
scheduleServerMessages();
}
TEST_F(RefactoringClientServerInProcess, SendRemovePchProjectPartsMessage)
{
RemovePchProjectPartsMessage message{{"projectPartId1", "projectPartId2"}};
EXPECT_CALL(mockRefactoringServer, removePchProjectParts(message));
serverProxy.removePchProjectParts(message.clone());
scheduleServerMessages();
}
TEST_F(RefactoringClientServerInProcess, CancelMessage) TEST_F(RefactoringClientServerInProcess, CancelMessage)
{ {
EXPECT_CALL(mockRefactoringServer, cancel()); EXPECT_CALL(mockRefactoringServer, cancel());

View File

@@ -27,6 +27,7 @@
#include "filesystem-utilities.h" #include "filesystem-utilities.h"
#include "mockrefactoringclient.h" #include "mockrefactoringclient.h"
#include "mocksymbolindexing.h"
#include "sourcerangecontainer-matcher.h" #include "sourcerangecontainer-matcher.h"
#include <refactoringserver.h> #include <refactoringserver.h>
@@ -57,6 +58,9 @@ using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage;
using ClangBackEnd::SourceRangesForQueryMessage; using ClangBackEnd::SourceRangesForQueryMessage;
using ClangBackEnd::SourceRangesContainer; using ClangBackEnd::SourceRangesContainer;
using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::FileContainers;
using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::V2::ProjectPartContainers;
MATCHER_P2(IsSourceLocation, line, column, MATCHER_P2(IsSourceLocation, line, column,
std::string(negation ? "isn't " : "is ") std::string(negation ? "isn't " : "is ")
@@ -76,8 +80,10 @@ protected:
void TearDown() override; void TearDown() override;
protected: protected:
ClangBackEnd::RefactoringServer refactoringServer;
NiceMock<MockRefactoringClient> mockRefactoringClient; NiceMock<MockRefactoringClient> mockRefactoringClient;
NiceMock<MockSymbolIndexing> mockSymbolIndexing;
ClangBackEnd::FilePathCache<std::mutex> filePathCache;
ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, filePathCache};
Utils::SmallString sourceContent{"void f()\n {}"}; Utils::SmallString sourceContent{"void f()\n {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(), sourceContent.clone(),
@@ -283,6 +289,23 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message));
} }
TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectParts)
{
ProjectPartContainers projectParts{{{"projectPartId",
{"-I", TESTDATA_DIR},
{"header1.h"},
{"main.cpp"}}}};
FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
"void f();",
{}}};
EXPECT_CALL(mockSymbolIndexing,
updateProjectParts(projectParts, unsaved));
refactoringServer.updatePchProjectParts({Utils::clone(projectParts), Utils::clone(unsaved)});
}
void RefactoringServer::SetUp() void RefactoringServer::SetUp()
{ {
temporaryFile.open(); temporaryFile.open();

View File

@@ -96,6 +96,18 @@ TEST_F(SqliteDatabase, AddTable)
ASSERT_THAT(database.tables(), Contains(sqliteTable)); ASSERT_THAT(database.tables(), Contains(sqliteTable));
} }
TEST_F(SqliteDatabase, TableIsReadyAfterOpenDatabase)
{
database.close();
auto &table = database.addTable();
table.setName("foo");
table.addColumn("name");
database.open();
ASSERT_TRUE(table.isReady());
}
void SqliteDatabase::SetUp() void SqliteDatabase::SetUp()
{ {
database.setJournalMode(JournalMode::Memory); database.setJournalMode(JournalMode::Memory);

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** 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 <sqliteindex.h>
namespace {
using Sqlite::SqliteException;
using Sqlite::SqliteIndex;
TEST(SqliteIndex, OneColumn)
{
SqliteIndex index{"tableName", {"column1"}};
auto sqlStatement = index.sqlStatement();
ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1 ON tableName(column1)"));
}
TEST(SqliteIndex, TwoColumn)
{
SqliteIndex index{"tableName", {"column1", "column2"}};
auto sqlStatement = index.sqlStatement();
ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1_column2 ON tableName(column1, column2)"));
}
TEST(SqliteIndex, EmptyTableName)
{
SqliteIndex index{"", {"column1", "column2"}};
ASSERT_THROW(index.sqlStatement(), SqliteException);
}
TEST(SqliteIndex, EmptyColumns)
{
SqliteIndex index{"tableName", {}};
ASSERT_THROW(index.sqlStatement(), SqliteException);
}
}

View File

@@ -27,7 +27,7 @@
#include "spydummy.h" #include "spydummy.h"
#include <sqlitecolumn.h> #include <sqlitecolumn.h>
#include <sqlitedatabase.h> #include <mocksqlitedatabase.h>
#include <sqlitetable.h> #include <sqlitetable.h>
namespace { namespace {
@@ -41,13 +41,8 @@ using Sqlite::SqliteDatabase;
class SqliteTable : public ::testing::Test class SqliteTable : public ::testing::Test
{ {
protected: protected:
void SetUp() override; NiceMock<MockSqliteDatabase> mockDatabase;
void TearDown() override; Sqlite::SqliteTable table;
protected:
SpyDummy spyDummy;
SqliteDatabase database;
Sqlite::SqliteTable &table = database.addTable();
Utils::SmallString tableName = "testTable"; Utils::SmallString tableName = "testTable";
}; };
@@ -73,26 +68,46 @@ TEST_F(SqliteTable, SetUseWithoutRowid)
ASSERT_TRUE(table.useWithoutRowId()); ASSERT_TRUE(table.useWithoutRowId());
} }
TEST_F(SqliteTable, TableIsReadyAfterOpenDatabase) TEST_F(SqliteTable, AddIndex)
{ {
table.setName(tableName.clone()); table.setName(tableName.clone());
auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value");
auto index = table.addIndex({column, column2});
ASSERT_THAT(Utils::SmallStringView(index.sqlStatement()),
Eq("CREATE INDEX IF NOT EXISTS index_testTable_name_value ON testTable(name, value)"));
}
TEST_F(SqliteTable, InitializeTable)
{
table.setName(tableName.clone());
table.setUseIfNotExists(true);
table.setUseTemporaryTable(true);
table.setUseWithoutRowId(true);
table.addColumn("name"); table.addColumn("name");
table.addColumn("value");
database.open(); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name NUMERIC, value NUMERIC) WITHOUT ROWID")));
ASSERT_TRUE(table.isReady()); table.initialize(mockDatabase);
} }
void SqliteTable::SetUp() TEST_F(SqliteTable, InitializeTableWithIndex)
{ {
database.setJournalMode(JournalMode::Memory); InSequence sequence;
database.setDatabaseFilePath( QStringLiteral(":memory:")); table.setName(tableName.clone());
} auto &column = table.addColumn("name");
auto &column2 = table.addColumn("value");
table.addIndex({column});
table.addIndex({column2});
void SqliteTable::TearDown() EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE testTable(name NUMERIC, value NUMERIC)")));
{ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_name ON testTable(name)")));
if (database.isOpen()) EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_value ON testTable(value)")));
database.close();
table.initialize(mockDatabase);
} }
} }

View File

@@ -52,6 +52,7 @@ TEST_F(StorageSqliteStatementFactory, AddSymbolsTable)
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createSymbolsTable(); factory.createSymbolsTable();
@@ -63,6 +64,7 @@ TEST_F(StorageSqliteStatementFactory, AddLocationsTable)
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createLocationsTable(); factory.createLocationsTable();
@@ -85,6 +87,8 @@ TEST_F(StorageSqliteStatementFactory, AddNewSymbolsTable)
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createNewSymbolsTable(); factory.createNewSymbolsTable();
@@ -97,6 +101,7 @@ TEST_F(StorageSqliteStatementFactory, AddNewLocationsTable)
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))); EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newLocations_sourceId ON newLocations(sourceId)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
factory.createNewLocationsTable(); factory.createNewLocationsTable();
@@ -108,10 +113,15 @@ TEST_F(StorageSqliteStatementFactory, AddTablesInConstructor)
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(5); EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(5);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)"))); EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newLocations_sourceId ON newLocations(sourceId)")));
StatementFactory factory{mockDatabase}; StatementFactory factory{mockDatabase};
} }
@@ -137,7 +147,7 @@ TEST_F(StorageSqliteStatementFactory, SelectNewSourceIdsStatement)
TEST_F(StorageSqliteStatementFactory, AddNewSymbolsToSymbolsStatement) TEST_F(StorageSqliteStatementFactory, AddNewSymbolsToSymbolsStatement)
{ {
ASSERT_THAT(factory.addNewSymbolsToSymbolsStatement.sqlStatement, ASSERT_THAT(factory.addNewSymbolsToSymbolsStatement.sqlStatement,
Eq("INSERT INTO symbols(usr, symbolname) SELECT usr, symbolname FROM newsymbols WHERE NOT EXISTS (SELECT usr FROM symbols WHERE usr == newsymbols.usr)")); Eq("INSERT INTO symbols(usr, symbolName) SELECT usr, symbolName FROM newSymbols WHERE NOT EXISTS (SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)"));
} }
TEST_F(StorageSqliteStatementFactory, InsertSourcesStatement) TEST_F(StorageSqliteStatementFactory, InsertSourcesStatement)

View File

@@ -46,6 +46,7 @@ using testing::Sequence;
using Utils::PathString; using Utils::PathString;
using ClangBackEnd::V2::ProjectPartContainer; using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::V2::ProjectPartContainers; using ClangBackEnd::V2::ProjectPartContainers;
using ClangBackEnd::V2::FileContainers;
using ClangBackEnd::SymbolEntries; using ClangBackEnd::SymbolEntries;
using ClangBackEnd::SymbolEntry; using ClangBackEnd::SymbolEntry;
using ClangBackEnd::SourceLocationEntries; using ClangBackEnd::SourceLocationEntries;
@@ -72,6 +73,9 @@ protected:
{"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"}, {"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"},
{header2Path.clone()}, {header2Path.clone()},
{main2Path.clone()}}; {main2Path.clone()}};
FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
"void f();",
{}}};
SymbolEntries symbolEntries{{1, {"function", "function"}}}; SymbolEntries symbolEntries{{1, {"function", "function"}}};
SourceLocationEntries sourceLocations{{1, 1, {42, 23}, SymbolType::Declaration}}; SourceLocationEntries sourceLocations{{1, 1, {42, 23}, SymbolType::Declaration}};
NiceMock<MockSymbolsCollector> mockCollector; NiceMock<MockSymbolsCollector> mockCollector;
@@ -83,7 +87,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
{ {
EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePaths(), projectPart1.arguments())); EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePaths(), projectPart1.arguments()));
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
} }
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectPart) TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectPart)
@@ -91,7 +95,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectP
EXPECT_CALL(mockCollector, addFiles(_, _)) EXPECT_CALL(mockCollector, addFiles(_, _))
.Times(2); .Times(2);
indexer.updateProjectParts({projectPart1, projectPart2}); indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved));
} }
TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEveryProjectParts) TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEveryProjectParts)
@@ -99,48 +103,54 @@ TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEv
EXPECT_CALL(mockCollector, addFiles(_, _)) EXPECT_CALL(mockCollector, addFiles(_, _))
.Times(0); .Times(0);
indexer.updateProjectParts({}); indexer.updateProjectParts({}, {});
} }
TEST_F(SymbolIndexer, UpdateProjectPartsCallscollectSymbolsInCollector) TEST_F(SymbolIndexer, UpdateProjectPartsCallscollectSymbolsInCollector)
{ {
EXPECT_CALL(mockCollector, collectSymbols()); EXPECT_CALL(mockCollector, collectSymbols());
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
} }
TEST_F(SymbolIndexer, UpdateProjectPartsCallsSymbolsInCollector) TEST_F(SymbolIndexer, UpdateProjectPartsCallsSymbolsInCollector)
{ {
EXPECT_CALL(mockCollector, symbols()); EXPECT_CALL(mockCollector, symbols());
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
} }
TEST_F(SymbolIndexer, UpdateProjectPartsCallsSourceLocationsInCollector) TEST_F(SymbolIndexer, UpdateProjectPartsCallsSourceLocationsInCollector)
{ {
EXPECT_CALL(mockCollector, sourceLocations()); EXPECT_CALL(mockCollector, sourceLocations());
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
}
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddUnsavedFilesInCollector)
{
EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved));
indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
} }
TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddSymbolsAndSourceLocationsInStorage) TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddSymbolsAndSourceLocationsInStorage)
{ {
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
} }
TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder) TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder)
{ {
Sequence sequence;
EXPECT_CALL(mockCollector, addFiles(_, _)); EXPECT_CALL(mockCollector, addFiles(_, _));
EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved));
EXPECT_CALL(mockCollector, collectSymbols()); EXPECT_CALL(mockCollector, collectSymbols());
EXPECT_CALL(mockCollector, symbols()); EXPECT_CALL(mockCollector, symbols());
EXPECT_CALL(mockCollector, sourceLocations()); EXPECT_CALL(mockCollector, sourceLocations());
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
indexer.updateProjectParts({projectPart1}); indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
} }
void SymbolIndexer::SetUp() void SymbolIndexer::SetUp()

View File

@@ -0,0 +1,112 @@
/****************************************************************************
**
** 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 <projectpartcontainerv2.h>
#include <symbolindexing.h>
#include <symbolquery.h>
#include <querysqlitestatementfactory.h>
#include <QDir>
namespace {
using Sqlite::SqliteDatabase;
using Sqlite::SqliteReadStatement;
using ClangBackEnd::SymbolIndexer;
using ClangBackEnd::SymbolsCollector;
using ClangBackEnd::SymbolStorage;
using ClangBackEnd::FilePathCache;
using ClangBackEnd::FilePathCache;
using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::V2::ProjectPartContainer;
using ClangRefactoring::SymbolQuery;
using ClangRefactoring::QuerySqliteStatementFactory;
using Utils::PathString;
using SL = ClangRefactoring::SourceLocations;
using StatementFactory = QuerySqliteStatementFactory<SqliteDatabase, SqliteReadStatement>;
using Query = SymbolQuery<StatementFactory>;
MATCHER_P3(IsLocation, sourceId, line, column,
std::string(negation ? "isn't" : "is")
+ " source id " + PrintToString(sourceId)
+ " line " + PrintToString(line)
+ " and column " + PrintToString(column)
)
{
const SL::Location &location = arg;
return location.sourceId == sourceId
&& location.line == line
&& location.column == column;
};
class SymbolIndexing : public testing::Test
{
protected:
FilePathCache<std::mutex> filePathCache;
ClangBackEnd::SymbolIndexing indexing{filePathCache, QDir::tempPath() + "/symbol.db"};
StatementFactory queryFactory{indexing.database()};
Query query{queryFactory};
PathString main1Path = TESTDATA_DIR "/symbolindexing_main1.cpp";
ProjectPartContainer projectPart1{"project1",
{"cc", "-I", TESTDATA_DIR, "-std=c++1z"},
{},
{main1Path.clone()}};
};
TEST_F(SymbolIndexing, Locations)
{
indexing.indexer().updateProjectParts({projectPart1}, {});
auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 6, 5);
ASSERT_THAT(locations.locations,
ElementsAre(
IsLocation(0, 5, 9),
IsLocation(0, 6, 5)));
}
TEST_F(SymbolIndexing, Sources)
{
indexing.indexer().updateProjectParts({projectPart1}, {});
auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 6, 5);
ASSERT_THAT(locations.sources, ElementsAre(Pair(0, Eq(TESTDATA_DIR "/symbolindexing_main1.cpp"))));
}
TEST_F(SymbolIndexing, DISABLED_TemplateFunction)
{
indexing.indexer().updateProjectParts({projectPart1}, {});
auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 21, 24);
ASSERT_THAT(locations.locations,
ElementsAre(
IsLocation(0, 5, 9),
IsLocation(0, 6, 5)));
}
}

View File

@@ -39,6 +39,7 @@ using testing::Pair;
using testing::Value; using testing::Value;
using testing::_; using testing::_;
using ClangBackEnd::V2::FileContainers;
using ClangBackEnd::SourceLocationEntry; using ClangBackEnd::SourceLocationEntry;
using ClangBackEnd::SymbolEntry; using ClangBackEnd::SymbolEntry;
using ClangBackEnd::SymbolType; using ClangBackEnd::SymbolType;
@@ -57,7 +58,7 @@ protected:
SymbolIndex symbolIdForSymbolName(const Utils::SmallString &symbolName); SymbolIndex symbolIdForSymbolName(const Utils::SmallString &symbolName);
protected: protected:
ClangBackEnd::FilePathCache<> filePathCache; ClangBackEnd::FilePathCache<std::mutex> filePathCache;
ClangBackEnd::SymbolsCollector collector{filePathCache}; ClangBackEnd::SymbolsCollector collector{filePathCache};
}; };
@@ -150,6 +151,21 @@ TEST_F(SymbolsCollector, ReferencedSymboldMatchesLocation)
Field(&SourceLocationEntry::column, 5)))); Field(&SourceLocationEntry::column, 5))));
} }
TEST_F(SymbolsCollector, DISABLED_ON_WINDOWS(CollectInUnsavedFile))
{
FileContainers unsaved{{{TESTDATA_DIR, "symbolscollector_generated_file.h"},
"void function();",
{}}};
collector.addFile(TESTDATA_DIR, "symbolscollector_unsaved.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_unsaved.cpp"});
collector.addUnsavedFiles(std::move(unsaved));
collector.collectSymbols();
ASSERT_THAT(collector.symbols(),
Contains(
Pair(_, Field(&SymbolEntry::symbolName, "function"))));
}
SymbolIndex SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName) SymbolIndex SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName)
{ {
for (const auto &entry : collector.symbols()) { for (const auto &entry : collector.symbols()) {

View File

@@ -58,7 +58,7 @@ protected:
void SetUp(); void SetUp();
protected: protected:
FilePathCache<> filePathCache; FilePathCache<std::mutex> filePathCache;
NiceMock<MockSqliteDatabase> mockDatabase; NiceMock<MockSqliteDatabase> mockDatabase;
StatementFactory statementFactory{mockDatabase}; StatementFactory statementFactory{mockDatabase};

View File

@@ -74,7 +74,9 @@ SOURCES += \
mocksqlitereadstatement.cpp \ mocksqlitereadstatement.cpp \
symbolquery-test.cpp \ symbolquery-test.cpp \
storagesqlitestatementfactory-test.cpp \ storagesqlitestatementfactory-test.cpp \
querysqlitestatementfactory-test.cpp querysqlitestatementfactory-test.cpp \
symbolindexing-test.cpp \
sqliteindex-test.cpp
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
SOURCES += \ SOURCES += \
@@ -197,7 +199,8 @@ HEADERS += \
mocksqlitewritestatement.h \ mocksqlitewritestatement.h \
mocksqlitedatabase.h \ mocksqlitedatabase.h \
mocksqlitereadstatement.h \ mocksqlitereadstatement.h \
google-using-declarations.h google-using-declarations.h \
mocksymbolindexing.h
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
HEADERS += \ HEADERS += \