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

@@ -9,7 +9,9 @@ HEADERS += \
$$PWD/symbolscollectorinterface.h \
$$PWD/symbolstorageinterface.h \
$$PWD/symbolstorage.h \
$$PWD/storagesqlitestatementfactory.h
$$PWD/storagesqlitestatementfactory.h \
$$PWD/symbolindexing.h \
$$PWD/symbolindexinginterface.h
!isEmpty(LIBTOOLING_LIBS) {
SOURCES += \
@@ -55,4 +57,5 @@ SOURCES += \
$$PWD/symbolindexer.cpp \
$$PWD/symbolentry.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;
};
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

View File

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

View File

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

View File

@@ -40,13 +40,14 @@ class CollectSymbolsConsumer : public clang::ASTConsumer
public:
CollectSymbolsConsumer(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
FilePathCache<> &filePathCache)
FilePathCache<std::mutex> &filePathCache)
: m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries),
m_filePathCache(filePathCache)
{}
void HandleTranslationUnit(clang::ASTContext &astContext) override {
void HandleTranslationUnit(clang::ASTContext &astContext) override
{
CollectSymbolsASTVisitor visitor{m_symbolEntries,
m_sourceLocationEntries,
m_filePathCache,
@@ -54,9 +55,20 @@ public:
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:
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathCache<> &m_filePathCache;
FilePathCache<std::mutex> &m_filePathCache;
};
}

View File

@@ -27,6 +27,7 @@
#include "symbolfinder.h"
#include "clangquery.h"
#include "symbolindexing.h"
#include <refactoringclientinterface.h>
#include <clangrefactoringmessages.h>
@@ -38,7 +39,10 @@
namespace ClangBackEnd {
RefactoringServer::RefactoringServer()
RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing,
FilePathCache<std::mutex> &filePathCache)
: m_symbolIndexing(symbolIndexing),
m_filePathCache(filePathCache)
{
m_pollTimer.setInterval(100);
@@ -88,7 +92,17 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo
{
gatherSourceRangesForQueryMessages(message.takeSources(),
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()

View File

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

View File

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

View File

@@ -29,6 +29,7 @@
#include "symbolstorageinterface.h"
#include <projectpartcontainerv2.h>
#include <filecontainerv2.h>
namespace ClangBackEnd {
@@ -38,7 +39,8 @@ public:
SymbolIndexer(SymbolsCollectorInterface &symbolsCollector,
SymbolStorageInterface &symbolStorage);
void updateProjectParts(V2::ProjectPartContainers &&projectParts);
void updateProjectParts(V2::ProjectPartContainers &&projectParts,
V2::FileContainers &&generatedFiles);
private:
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 {
SymbolsCollector::SymbolsCollector(FilePathCache<> &filePathCache)
SymbolsCollector::SymbolsCollector(FilePathCache<std::mutex> &filePathCache)
: m_collectSymbolsAction(filePathCache)
{
}
@@ -37,6 +37,11 @@ void SymbolsCollector::addFiles(const Utils::PathStringVector &filePaths, const
ClangTool::addFiles(filePaths, arguments);
}
void SymbolsCollector::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
{
ClangTool::addUnsavedFiles(unsavedFiles);
}
void SymbolsCollector::collectSymbols()
{
auto tool = createTool();

View File

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

View File

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

View File

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