Clang: Use the clang indexer for indexing

It is not removing so much code but will makes somethings easier in the
future. We added the SymbolType::Definition too.

Change-Id: I4e106b8518e6bfed0c6a4aa6be61c4a5fe5f8bef
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2018-03-22 13:57:03 +01:00
parent 41a12410e6
commit 576eb3370c
11 changed files with 247 additions and 190 deletions

View File

@@ -20,7 +20,8 @@ HEADERS += \
$$PWD/filestatus.h \
$$PWD/projectpartartefactexception.h \
$$PWD/projectpartartefact.h \
$$PWD/filestatuscache.h
$$PWD/filestatuscache.h \
$$PWD/indexdataconsumer.h
!isEmpty(LIBTOOLING_LIBS) {
SOURCES += \
@@ -55,9 +56,7 @@ HEADERS += \
$$PWD/clangtool.h \
$$PWD/sourcerangeextractor.h \
$$PWD/locationsourcefilecallbacks.h \
$$PWD/collectsymbolsconsumer.h \
$$PWD/collectsymbolsaction.h \
$$PWD/collectsymbolsastvisitor.h \
$$PWD/collectmacrossourcefilecallbacks.h \
$$PWD/symbolscollector.h \
$$PWD/clangquerygatherer.h
@@ -68,4 +67,5 @@ SOURCES += \
$$PWD/symbolindexer.cpp \
$$PWD/symbolentry.cpp \
$$PWD/projectpartartefact.cpp \
$$PWD/filestatuscache.cpp
$$PWD/filestatuscache.cpp \
$$PWD/indexdataconsumer.cpp

View File

@@ -55,7 +55,7 @@ public:
FilePathCachingInterface &filePathCache,
const clang::SourceManager &sourceManager,
std::shared_ptr<clang::Preprocessor> &&preprocessor)
: SymbolsVisitorBase(filePathCache, sourceManager),
: SymbolsVisitorBase(filePathCache, &sourceManager),
m_preprocessor(std::move(preprocessor)),
m_sourceDependencies(sourceDependencies),
m_symbolEntries(symbolEntries),
@@ -73,8 +73,8 @@ public:
{
if (reason == clang::PPCallbacks::EnterFile)
{
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(
m_sourceManager.getFileID(sourceLocation));
const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(
m_sourceManager->getFileID(sourceLocation));
if (fileEntry) {
addFileStatus(fileEntry);
addSourceFile(fileEntry);

View File

@@ -25,15 +25,16 @@
#include "collectsymbolsaction.h"
#include "collectsymbolsconsumer.h"
#include <clang/Frontend/CompilerInstance.h>
namespace ClangBackEnd {
std::unique_ptr<clang::ASTConsumer> CollectSymbolsAction::newASTConsumer()
std::unique_ptr<clang::ASTConsumer> CollectSymbolsAction::newASTConsumer(
clang::CompilerInstance &compilerInstance,
llvm::StringRef inFile)
{
return std::make_unique<CollectSymbolsConsumer>(m_symbolEntries,
m_sourceLocationEntries,
m_filePathCache);
m_indexDataConsumer->setSourceManager(&compilerInstance.getSourceManager());
return m_action.CreateASTConsumer(compilerInstance, inFile);
}
} // namespace ClangBackEnd

View File

@@ -27,6 +27,7 @@
#include "clangrefactoringbackend_global.h"
#include "sourcelocationentry.h"
#include "indexdataconsumer.h"
#include "symbolentry.h"
#include <utils/smallstring.h>
@@ -34,6 +35,7 @@
#include <filepathcachingfwd.h>
#include <clang/Frontend/FrontendAction.h>
#include <clang/Index/IndexingAction.h>
#include <mutex>
@@ -42,36 +44,45 @@ namespace ClangBackEnd {
class CollectSymbolsAction
{
public:
CollectSymbolsAction(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
FilePathCachingInterface &filePathCache)
: m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries),
m_filePathCache(filePathCache)
CollectSymbolsAction(std::shared_ptr<IndexDataConsumer> indexDataConsumer)
: m_action(indexDataConsumer, createIndexingOptions()),
m_indexDataConsumer(indexDataConsumer.get())
{}
std::unique_ptr<clang::ASTConsumer> newASTConsumer();
SymbolEntries takeSymbols()
std::unique_ptr<clang::ASTConsumer> newASTConsumer(clang::CompilerInstance &compilerInstance,
llvm::StringRef inFile);
private:
class WrappedIndexAction : public clang::WrapperFrontendAction
{
return std::move(m_symbolEntries);
}
public:
WrappedIndexAction(std::shared_ptr<clang::index::IndexDataConsumer> m_indexDataConsumer,
clang::index::IndexingOptions indexingOptions)
: clang::WrapperFrontendAction(
clang::index::createIndexingAction(m_indexDataConsumer, indexingOptions, nullptr))
{}
const SymbolEntries &symbols() const
{
return m_symbolEntries;
}
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &compilerInstance,
llvm::StringRef inFile) override
{
return WrapperFrontendAction::CreateASTConsumer(compilerInstance, inFile);
}
};
const SourceLocationEntries &sourceLocations() const
static
clang::index::IndexingOptions createIndexingOptions()
{
return m_sourceLocationEntries;
clang::index::IndexingOptions options;
options.SystemSymbolFilter = clang::index::IndexingOptions::SystemSymbolFilterKind::All;
options.IndexFunctionLocals = true;
return options;
}
private:
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathCachingInterface &m_filePathCache;
WrappedIndexAction m_action;
IndexDataConsumer *m_indexDataConsumer;
};
} // namespace ClangBackEnd

View File

@@ -1,112 +0,0 @@
/****************************************************************************
**
** 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 "sourcelocationentry.h"
#include "sourcelocationsutils.h"
#include "symbolentry.h"
#include "symbolsvisitorbase.h"
#include <clang/AST/AST.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <vector>
namespace ClangBackEnd {
class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor<CollectSymbolsASTVisitor>,
public SymbolsVisitorBase
{
public:
CollectSymbolsASTVisitor(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
FilePathCachingInterface &filePathCache,
const clang::SourceManager &sourceManager)
: SymbolsVisitorBase(filePathCache, sourceManager),
m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries)
{}
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();
auto found = m_symbolEntries.find(globalId);
if (found == m_symbolEntries.end()) {
Utils::optional<Utils::PathString> usr = generateUSR(declaration);
if (usr) {
m_symbolEntries.emplace(std::piecewise_construct,
std::forward_as_tuple(globalId),
std::forward_as_tuple(std::move(usr.value()), symbolName(declaration)));
}
}
m_sourceLocationEntries.emplace_back(globalId,
filePathId(sourceLocation),
lineColum(sourceLocation),
SymbolType::Declaration);
return true;
}
bool VisitDeclRefExpr(const clang::DeclRefExpr *expression)
{
auto declaration = expression->getFoundDecl();
SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
auto sourceLocation = expression->getLocation();
m_sourceLocationEntries.emplace_back(globalId,
filePathId(sourceLocation),
lineColum(sourceLocation),
SymbolType::DeclarationReference);
return true;
}
Utils::SmallString symbolName(const clang::NamedDecl *declaration)
{
return declaration->getName();
}
private:
SymbolEntries &m_symbolEntries;
std::unordered_map<uint, FilePathId> m_filePathIndices;
SourceLocationEntries &m_sourceLocationEntries;
};
} // namespace ClangBackend

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "indexdataconsumer.h"
#include <clang/Basic/SourceLocation.h>
#include <clang/Index/IndexSymbol.h>
#include <clang/AST/Decl.h>
#include <llvm/ADT/ArrayRef.h>
namespace ClangBackEnd {
namespace {
bool hasSymbolRole(clang::index::SymbolRole role, clang::index::SymbolRoleSet roleSet)
{
return roleSet & static_cast<clang::index::SymbolRoleSet>(role);
}
Utils::SmallString symbolName(const clang::NamedDecl *declaration)
{
return declaration->getName();
}
SymbolType symbolType(clang::index::SymbolRoleSet roles)
{
if (hasSymbolRole(clang::index::SymbolRole::Reference, roles))
return SymbolType::DeclarationReference;
else if (hasSymbolRole(clang::index::SymbolRole::Declaration, roles))
return SymbolType::Declaration;
else if (hasSymbolRole(clang::index::SymbolRole::Definition, roles))
return SymbolType::Definition;
return SymbolType::None;
}
}
bool IndexDataConsumer::handleDeclOccurence(const clang::Decl *declaration,
clang::index::SymbolRoleSet symbolRoles,
llvm::ArrayRef<clang::index::SymbolRelation> symbolRelations,
clang::FileID fileId,
unsigned offset,
IndexDataConsumer::ASTNodeInfo astNodeInfo)
{
const auto *namedDeclaration = clang::dyn_cast<clang::NamedDecl>(declaration);
if (namedDeclaration) {
if (!namedDeclaration->getIdentifier())
return true;
SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
clang::SourceLocation sourceLocation = m_sourceManager->getLocForStartOfFile(fileId).getLocWithOffset(offset);
auto found = m_symbolEntries.find(globalId);
if (found == m_symbolEntries.end()) {
Utils::optional<Utils::PathString> usr = generateUSR(namedDeclaration);
if (usr) {
m_symbolEntries.emplace(std::piecewise_construct,
std::forward_as_tuple(globalId),
std::forward_as_tuple(std::move(usr.value()), symbolName(namedDeclaration)));
}
}
m_sourceLocationEntries.emplace_back(globalId,
filePathId(sourceLocation),
lineColum(sourceLocation),
symbolType(symbolRoles));
}
return true;
}
} // namespace ClangBackEnd

View File

@@ -25,50 +25,42 @@
#pragma once
#include "collectsymbolsastvisitor.h"
#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h>
#include "clangrefactoringbackend_global.h"
#include "sourcelocationentry.h"
#include "symbolentry.h"
#include "symbolsvisitorbase.h"
#include <filepathcachingfwd.h>
#include <clang/Index/IndexDataConsumer.h>
namespace ClangBackEnd {
class CollectSymbolsConsumer : public clang::ASTConsumer
class IndexDataConsumer : public clang::index::IndexDataConsumer,
public SymbolsVisitorBase
{
public:
CollectSymbolsConsumer(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
FilePathCachingInterface &filePathCache)
: m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries),
m_filePathCache(filePathCache)
IndexDataConsumer(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
FilePathCachingInterface &filePathCache)
: SymbolsVisitorBase(filePathCache, nullptr),
m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries)
{}
void HandleTranslationUnit(clang::ASTContext &astContext) override
{
CollectSymbolsASTVisitor visitor{m_symbolEntries,
m_sourceLocationEntries,
m_filePathCache,
astContext.getSourceManager()};
visitor.TraverseDecl(astContext.getTranslationUnitDecl());
}
IndexDataConsumer(const IndexDataConsumer &) = delete;
IndexDataConsumer &operator=(const IndexDataConsumer &) = delete;
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;
}
bool handleDeclOccurence(const clang::Decl *declaration,
clang::index::SymbolRoleSet symbolRoles,
llvm::ArrayRef<clang::index::SymbolRelation> symbolRelations,
clang::FileID fileId,
unsigned offset,
ASTNodeInfo astNodeInfo) override;
private:
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathCachingInterface &m_filePathCache;
};
}
} // namespace ClangBackEnd

View File

@@ -38,9 +38,11 @@ namespace ClangBackEnd {
enum class SymbolType
{
None = 0,
Declaration,
DeclarationReference,
MacroDefinition,
Definition,
MacroDefinition = 1024,
MacroUsage,
MacroUndefinition
};

View File

@@ -25,10 +25,13 @@
#include "symbolscollector.h"
#include <clang/Frontend/FrontendActions.h>
namespace ClangBackEnd {
SymbolsCollector::SymbolsCollector(FilePathCachingInterface &filePathCache)
: m_collectSymbolsAction(m_symbolEntries, m_sourceLocationEntries, filePathCache),
: m_indexDataConsumer(std::make_shared<IndexDataConsumer>(m_symbolEntries, m_sourceLocationEntries, filePathCache)),
m_collectSymbolsAction(m_indexDataConsumer),
m_collectMacrosSourceFileCallbacks(m_symbolEntries, m_sourceLocationEntries, filePathCache),
m_filePathCache(filePathCache)
{
@@ -54,22 +57,80 @@ void SymbolsCollector::clear()
m_clangTool = ClangTool();
}
template <typename Factory>
std::unique_ptr<clang::tooling::FrontendActionFactory>
newFrontendActionFactory(Factory *consumerFactory,
clang::tooling::SourceFileCallbacks *sourceFileCallbacks)
{
class FrontendActionFactoryAdapter : public clang::tooling::FrontendActionFactory
{
public:
explicit FrontendActionFactoryAdapter(Factory *consumerFactory,
clang::tooling::SourceFileCallbacks *sourceFileCallbacks)
: m_consumerFactory(consumerFactory),
m_sourceFileCallbacks(sourceFileCallbacks)
{}
clang::FrontendAction *create() override {
return new ConsumerFactoryAdaptor(m_consumerFactory, m_sourceFileCallbacks);
}
private:
class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
public:
ConsumerFactoryAdaptor(Factory *consumerFactory,
clang::tooling::SourceFileCallbacks *sourceFileCallbacks)
: m_consumerFactory(consumerFactory),
m_sourceFileCallbacks(sourceFileCallbacks)
{}
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &instance, StringRef inFile) override {
return m_consumerFactory->newASTConsumer(instance, inFile);
}
protected:
bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
if (!clang::ASTFrontendAction::BeginSourceFileAction(CI))
return false;
if (m_sourceFileCallbacks)
return m_sourceFileCallbacks->handleBeginSource(CI);
return true;
}
void EndSourceFileAction() override {
if (m_sourceFileCallbacks)
m_sourceFileCallbacks->handleEndSource();
clang::ASTFrontendAction::EndSourceFileAction();
}
private:
Factory *m_consumerFactory;
clang::tooling::SourceFileCallbacks *m_sourceFileCallbacks;
};
Factory *m_consumerFactory;
clang::tooling::SourceFileCallbacks *m_sourceFileCallbacks;
};
return std::unique_ptr<clang::tooling::FrontendActionFactory>(
new FrontendActionFactoryAdapter(consumerFactory, sourceFileCallbacks));
}
void SymbolsCollector::collectSymbols()
{
auto tool = m_clangTool.createTool();
tool.run(clang::tooling::newFrontendActionFactory(&m_collectSymbolsAction,
&m_collectMacrosSourceFileCallbacks).get());
tool.run(ClangBackEnd::newFrontendActionFactory(&m_collectSymbolsAction,
&m_collectMacrosSourceFileCallbacks).get());
}
const SymbolEntries &SymbolsCollector::symbols() const
{
return m_collectSymbolsAction.symbols();
return m_symbolEntries;
}
const SourceLocationEntries &SymbolsCollector::sourceLocations() const
{
return m_collectSymbolsAction.sourceLocations();
return m_sourceLocationEntries;
}
const FilePathIds &SymbolsCollector::sourceFiles() const

View File

@@ -59,6 +59,7 @@ private:
ClangTool m_clangTool;
SymbolEntries m_symbolEntries;
SourceLocationEntries m_sourceLocationEntries;
std::shared_ptr<IndexDataConsumer> m_indexDataConsumer;
CollectSymbolsAction m_collectSymbolsAction;
CollectMacrosSourceFileCallbacks m_collectMacrosSourceFileCallbacks;
FilePathCachingInterface &m_filePathCache;

View File

@@ -43,15 +43,15 @@ class SymbolsVisitorBase
{
public:
SymbolsVisitorBase(FilePathCachingInterface &filePathCache,
const clang::SourceManager &sourceManager)
const clang::SourceManager *sourceManager)
: m_filePathCache(filePathCache),
m_sourceManager(sourceManager)
{}
FilePathId filePathId(clang::SourceLocation sourceLocation)
{
clang::FileID clangFileId = m_sourceManager.getFileID(sourceLocation);
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(clangFileId);
clang::FileID clangFileId = m_sourceManager->getFileID(sourceLocation);
const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(clangFileId);
return filePathId(fileEntry);
}
@@ -79,8 +79,8 @@ public:
Utils::LineColumn lineColum(clang::SourceLocation sourceLocation)
{
return {int(m_sourceManager.getSpellingLineNumber(sourceLocation)),
int(m_sourceManager.getSpellingColumnNumber(sourceLocation))};
return {int(m_sourceManager->getSpellingLineNumber(sourceLocation)),
int(m_sourceManager->getSpellingColumnNumber(sourceLocation))};
}
static Utils::optional<Utils::PathString> generateUSR(const clang::Decl *declaration)
@@ -106,7 +106,7 @@ public:
bool wasNotWorking = clang::index::generateUSRForMacro(macroName,
sourceLocation,
m_sourceManager,
*m_sourceManager,
usr);
if (!wasNotWorking)
@@ -120,10 +120,15 @@ public:
return SymbolIndex(reinterpret_cast<std::uintptr_t>(pointer));
}
void setSourceManager(const clang::SourceManager *sourceManager)
{
m_sourceManager = sourceManager;
}
protected:
std::unordered_map<uint, FilePathId> m_filePathIndices;
FilePathCachingInterface &m_filePathCache;
const clang::SourceManager &m_sourceManager;
const clang::SourceManager *m_sourceManager = nullptr;
};
} // namespace ClangBackend