Commit f0e00a8c authored by Marco Bubke's avatar Marco Bubke

Clang: Add symbols collector

Change-Id: I64c25eef8eaa6cc6c3ff09d41866972b6c7248d0
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent 8640ef19
......@@ -172,6 +172,7 @@ HEADERS += \
$$PWD/updatevisibletranslationunitsmessage.h \
$$PWD/writemessageblock.h \
$$PWD/ipcclientprovider.h \
$$PWD/requestsourcerangesforquerymessage.h \
$$PWD/stringcachefwd.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
......@@ -2,7 +2,14 @@ INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/clangrefactoringbackend_global.h \
$$PWD/sourcerangefilter.h
$$PWD/sourcerangefilter.h \
$$PWD/symbolscollector.h \
$$PWD/symbolentry.h \
$$PWD/collectsymbolsconsumer.h \
$$PWD/collectsymbolsaction.h \
$$PWD/collectmacrossourcefilecallbacks.h \
$$PWD/collectsymbolsastvisitor.h \
$$PWD/sourcelocationentry.h
!isEmpty(LIBTOOLING_LIBS) {
SOURCES += \
......@@ -36,4 +43,9 @@ HEADERS += \
}
SOURCES += \
$$PWD/sourcerangefilter.cpp
$$PWD/sourcerangefilter.cpp \
$$PWD/symbolscollector.cpp \
$$PWD/collectsymbolsaction.cpp \
$$PWD/collectmacrossourcefilecallbacks.cpp \
$$PWD/symbolentry.cpp \
$$PWD/sourcelocationentry.cpp
......@@ -47,15 +47,15 @@ void ClangTool::addFile(std::string &&directory,
std::string &&content,
std::vector<std::string> &&commandLine)
{
fileContents.emplace_back(toNativePath(std::move(directory)),
m_fileContents.emplace_back(toNativePath(std::move(directory)),
std::move(fileName),
std::move(content),
std::move(commandLine));
const auto &fileContent = fileContents.back();
const auto &fileContent = m_fileContents.back();
compilationDatabase.addFile(fileContent.directory, fileContent.fileName, fileContent.commandLine);
sourceFilePaths.push_back(fileContent.filePath);
m_compilationDatabase.addFile(fileContent.directory, fileContent.fileName, fileContent.commandLine);
m_sourceFilePaths.push_back(fileContent.filePath);
}
template <typename Container>
......@@ -86,7 +86,7 @@ void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector
void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
{
unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size());
m_unsavedFileContents.reserve(m_unsavedFileContents.size() + unsavedFiles.size());
auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) {
return UnsavedFileContent{toNativePath(unsavedFile.filePath().path().clone()),
......@@ -95,7 +95,7 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
std::transform(unsavedFiles.begin(),
unsavedFiles.end(),
std::back_inserter(unsavedFileContents),
std::back_inserter(m_unsavedFileContents),
convertToUnsavedFileContent);
}
......@@ -109,14 +109,14 @@ llvm::StringRef toStringRef(const String &string)
clang::tooling::ClangTool ClangTool::createTool() const
{
clang::tooling::ClangTool tool(compilationDatabase, sourceFilePaths);
clang::tooling::ClangTool tool(m_compilationDatabase, m_sourceFilePaths);
for (const auto &fileContent : fileContents) {
for (const auto &fileContent : m_fileContents) {
if (!fileContent.content.empty())
tool.mapVirtualFile(fileContent.filePath, fileContent.content);
}
for (const auto &unsavedFileContent : unsavedFileContents)
for (const auto &unsavedFileContent : m_unsavedFileContents)
tool.mapVirtualFile(toStringRef(unsavedFileContent.filePath),
toStringRef(unsavedFileContent.content));
......
......@@ -104,10 +104,10 @@ public:
clang::tooling::ClangTool createTool() const;
private:
RefactoringCompilationDatabase compilationDatabase;
std::vector<FileContent> fileContents;
std::vector<std::string> sourceFilePaths;
std::vector<UnsavedFileContent> unsavedFileContents;
RefactoringCompilationDatabase m_compilationDatabase;
std::vector<FileContent> m_fileContents;
std::vector<std::string> m_sourceFilePaths;
std::vector<UnsavedFileContent> m_unsavedFileContents;
};
} // namespace ClangBackEnd
/****************************************************************************
**
** 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 "collectmacrossourcefilecallbacks.h"
namespace ClangBackEnd {
CollectMacrosSourceFileCallbacks::CollectMacrosSourceFileCallbacks()
{
}
} // namespace ClangBackEnd
/****************************************************************************
**
** 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 <clang/Tooling/Tooling.h>
namespace ClangBackEnd {
class CollectMacrosSourceFileCallbacks : public clang::tooling::SourceFileCallbacks
{
public:
CollectMacrosSourceFileCallbacks();
};
} // namespace ClangBackEnd
/****************************************************************************
**
** 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 "collectsymbolsaction.h"
#include "collectsymbolsconsumer.h"
namespace ClangBackEnd {
std::unique_ptr<clang::ASTConsumer> CollectSymbolsAction::newASTConsumer()
{
return std::make_unique<CollectSymbolsConsumer>(m_symbolEntries,
m_sourceLocationEntries,
m_filePathCache);
}
} // namespace ClangBackEnd
/****************************************************************************
**
** 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 "clangrefactoringbackend_global.h"
#include "sourcelocationentry.h"
#include "symbolentry.h"
#include <utils/smallstring.h>
#include <stringcachefwd.h>
#include <clang/Frontend/FrontendAction.h>
namespace ClangBackEnd {
class CollectSymbolsAction
{
public:
CollectSymbolsAction(FilePathCache<> &filePathCache)
: m_filePathCache(filePathCache)
{}
std::unique_ptr<clang::ASTConsumer> newASTConsumer();
SymbolEntries takeSymbols()
{
return std::move(m_symbolEntries);
}
const SymbolEntries &symbols() const
{
return m_symbolEntries;
}
const SourceLocationEntries &sourceLocations() const
{
return m_sourceLocationEntries;
}
private:
SymbolEntries m_symbolEntries;
SourceLocationEntries m_sourceLocationEntries;
FilePathCache<> &m_filePathCache;
};
} // namespace ClangBackEnd
/****************************************************************************
**
** 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 "symbolentry.h"
#include "sourcelocationentry.h"
#include <stringcache.h>
#include <clang/AST/AST.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Index/USRGeneration.h>
#include <llvm/ADT/SmallVector.h>
#include <vector>
namespace ClangBackEnd {
Utils::SmallStringView toStringView(clang::StringRef stringReference)
{
return Utils::SmallStringView(stringReference.data(), stringReference.size());
}
class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor<CollectSymbolsASTVisitor>
{
public:
CollectSymbolsASTVisitor(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
FilePathCache<> &filePathCache,
const clang::SourceManager &sourceManager)
: m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries),
m_filePathCache(filePathCache),
m_sourceManager(sourceManager)
{}
bool VisitNamedDecl(const clang::NamedDecl *declaration)
{
auto globalId = declaration->getCanonicalDecl()->getLocation().getRawEncoding();
auto sourceLocation = declaration->getLocation();
auto found = m_symbolEntries.find(globalId);
if (found == m_symbolEntries.end()) {
m_symbolEntries.emplace(std::piecewise_construct,
std::forward_as_tuple(globalId),
std::forward_as_tuple(generateUSR(declaration), declaration->getName()));
}
m_sourceLocationEntries.emplace_back(globalId,
filePathId(sourceLocation),
lineColum(sourceLocation),
SymbolType::Declaration);
return true;
}
bool VisitDeclRefExpr(const clang::DeclRefExpr *expression)
{
auto declaration = expression->getFoundDecl();
auto globalId = declaration->getCanonicalDecl()->getLocation().getRawEncoding();
auto sourceLocation = expression->getLocation();
m_sourceLocationEntries.emplace_back(globalId,
filePathId(sourceLocation),
lineColum(sourceLocation),
SymbolType::DeclarationReference);
return true;
}
uint filePathId(clang::SourceLocation sourceLocation)
{
auto filePath = m_sourceManager.getFilename(sourceLocation);
return m_filePathCache.stringId(toStringView(filePath));
}
LineColumn lineColum(clang::SourceLocation sourceLocation)
{
return {m_sourceManager.getSpellingLineNumber(sourceLocation),
m_sourceManager.getSpellingColumnNumber(sourceLocation)};
}
llvm::SmallVector<char, 128> generateUSR(const clang::Decl *declaration)
{
llvm::SmallVector<char, 128> usr;
clang::index::generateUSRForDecl(declaration, usr);
return usr;
}
private:
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathCache<> &m_filePathCache;
const clang::SourceManager &m_sourceManager;
};
} // namespace ClangBackend
/****************************************************************************
**
** 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 "collectsymbolsastvisitor.h"
#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h>
#include <stringcachefwd.h>
namespace ClangBackEnd {
class CollectSymbolsConsumer : public clang::ASTConsumer
{
public:
CollectSymbolsConsumer(SymbolEntries &symbolEntries,
SourceLocationEntries &sourceLocationEntries,
FilePathCache<> &filePathCache)
: m_symbolEntries(symbolEntries),
m_sourceLocationEntries(sourceLocationEntries),
m_filePathCache(filePathCache)
{}
void HandleTranslationUnit(clang::ASTContext &astContext) override {
CollectSymbolsASTVisitor visitor{m_symbolEntries,
m_sourceLocationEntries,
m_filePathCache,
astContext.getSourceManager()};
visitor.TraverseDecl(astContext.getTranslationUnitDecl());
}
private:
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathCache<> &m_filePathCache;
};
}
......@@ -25,26 +25,12 @@
#pragma once
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning( disable : 4100 )
#endif
#include <clang/AST/AST.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Index/USRGeneration.h>
#include <llvm/ADT/SmallVector.h>
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
#include <vector>
namespace ClangBackEnd {
......@@ -54,8 +40,8 @@ class FindNamedDeclarationASTVisitor : public clang::RecursiveASTVisitor<FindNam
public:
explicit FindNamedDeclarationASTVisitor(const clang::SourceManager &sourceManager,
const clang::SourceLocation cursorSourceLocation)
: sourceManager(sourceManager),
cursorSourceLocation(cursorSourceLocation)
: m_sourceManager(sourceManager),
m_cursorSourceLocation(cursorSourceLocation)
{
}
......@@ -96,7 +82,7 @@ public:
std::vector<const clang::NamedDecl*> takeNamedDecl()
{
return std::move(namedDeclarations);
return std::move(m_namedDeclarations);
}
private:
......@@ -138,7 +124,7 @@ private:
bool isValid = isValidLocationWithCursorInside(startLocation, endLocation);
if (isValid)
namedDeclarations.push_back(declaration);
m_namedDeclarations.push_back(declaration);
return !isValid;
}
......@@ -153,20 +139,20 @@ private:
bool isCursorLocationBetween(const clang::SourceLocation startLocation,
const clang::SourceLocation endLocation)
{
return cursorSourceLocation == startLocation
|| cursorSourceLocation == endLocation
|| (sourceManager.isBeforeInTranslationUnit(startLocation, cursorSourceLocation)
&& sourceManager.isBeforeInTranslationUnit(cursorSourceLocation, endLocation));
return m_cursorSourceLocation == startLocation
|| m_cursorSourceLocation == endLocation
|| (m_sourceManager.isBeforeInTranslationUnit(startLocation, m_cursorSourceLocation)
&& m_sourceManager.isBeforeInTranslationUnit(m_cursorSourceLocation, endLocation));
}
std::vector<const clang::NamedDecl*> namedDeclarations;
const clang::SourceManager &sourceManager;
const clang::SourceLocation cursorSourceLocation;
std::vector<const clang::NamedDecl*> m_namedDeclarations;
const clang::SourceManager &m_sourceManager;
const clang::SourceLocation m_cursorSourceLocation;
};
inline
std::vector<const clang::NamedDecl *> namedDeclarationsAt(const clang::ASTContext &Context,
const clang::SourceLocation cursorSourceLocation)
const clang::SourceLocation cursorSourceLocation)
{
const auto &sourceManager = Context.getSourceManager();
const auto currentFile = sourceManager.getFilename(cursorSourceLocation);
......
......@@ -27,24 +27,10 @@
#include "findcursorusr.h"
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning( disable : 4100 )
#endif
#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h>
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
#include <algorithm>
#include <vector>
......@@ -54,16 +40,16 @@ namespace {
std::vector<USRName> collectConstructorUnifiedSymbolResolutions(const clang::CXXRecordDecl *declarations)
{
std::vector<USRName> unifiedSymbolResolutions;
std::vector<USRName> unifiedSymbolResolutions;
const auto constructorDeclarations = declarations->getDefinition()->ctors();
const auto constructorDeclarations = declarations->getDefinition()->ctors();
std::transform(constructorDeclarations.begin(),
constructorDeclarations.end(),
std::back_inserter(unifiedSymbolResolutions),
USROfDeclaration);
std::transform(constructorDeclarations.begin(),
constructorDeclarations.end(),
std::back_inserter(unifiedSymbolResolutions),
USROfDeclaration);
return unifiedSymbolResolutions;
return unifiedSymbolResolutions;
}