Clang: Collect source dependencies

It is quite easy because we track the include directives in the
preprocessor callbacks.

Change-Id: I2d7bd67b31f50c0d8d4a46c57e83dffa0c558dc7
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2018-01-31 13:53:57 +01:00
parent b2d3951bde
commit 048224bef1
13 changed files with 93 additions and 16 deletions

View File

@@ -27,6 +27,7 @@
#include "fileinformation.h"
#include "symbolsvisitorbase.h"
#include "sourcedependency.h"
#include "sourcelocationsutils.h"
#include "sourcelocationentry.h"
#include "symbolentry.h"
@@ -50,6 +51,7 @@ public:
FilePathIds &sourceFiles,
UsedMacros &usedMacros,
FileInformations &fileInformations,
SourceDependencies &sourceDependencies,
FilePathCachingInterface &filePathCache,
const clang::SourceManager &sourceManager,
std::shared_ptr<clang::Preprocessor> &&preprocessor)
@@ -59,7 +61,8 @@ public:
m_sourceLocationEntries(sourceLocationEntries),
m_sourceFiles(sourceFiles),
m_usedMacros(usedMacros),
m_fileInformations(fileInformations)
m_fileInformations(fileInformations),
m_sourceDependencies(sourceDependencies)
{
}
@@ -73,14 +76,15 @@ public:
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(
m_sourceManager.getFileID(sourceLocation));
if (fileEntry) {
m_fileInformations.emplace_back(filePathId(sourceLocation),
m_fileInformations.emplace_back(filePathId(fileEntry),
fileEntry->getSize(),
fileEntry->getModificationTime());
addSourceFile(fileEntry);
}
}
}
void InclusionDirective(clang::SourceLocation /*hashLocation*/,
void InclusionDirective(clang::SourceLocation hashLocation,
const clang::Token &/*includeToken*/,
llvm::StringRef /*fileName*/,
bool /*isAngled*/,
@@ -91,7 +95,7 @@ public:
const clang::Module * /*imported*/) override
{
if (!m_skipInclude && file)
addSourceFile(file);
addSourceDependency(file, hashLocation);
m_skipInclude = false;
}
@@ -268,18 +272,26 @@ public:
void addSourceFile(const clang::FileEntry *file)
{
auto filePathId = m_filePathCache.filePathId(
FilePath::fromNativeFilePath(absolutePath(file->getName())));
auto id = filePathId(file);
auto found = std::find(m_sourceFiles.begin(), m_sourceFiles.end(), filePathId);
auto found = std::find(m_sourceFiles.begin(), m_sourceFiles.end(), id);
if (found == m_sourceFiles.end() || *found != filePathId)
m_sourceFiles.insert(found, filePathId);
if (found == m_sourceFiles.end() || *found != id)
m_sourceFiles.insert(found, id);
}
void addSourceDependency(const clang::FileEntry *file, clang::SourceLocation includeLocation)
{
auto includeFilePathId = filePathId(includeLocation);
auto includedFilePathId = filePathId(file);
m_sourceDependencies.emplace_back(includeFilePathId, includedFilePathId);
}
private:
UsedMacros m_maybeUsedMacros;
std::shared_ptr<clang::Preprocessor> m_preprocessor;
SourceDependencies &m_sourceDependencies;
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathIds &m_sourceFiles;

View File

@@ -39,6 +39,7 @@ bool CollectMacrosSourceFileCallbacks::handleBeginSource(clang::CompilerInstance
m_sourceFiles,
m_usedMacros,
m_fileInformations,
m_sourceDependencies,
m_filePathCache,
compilerInstance.getSourceManager(),
compilerInstance.getPreprocessorPtr());

View File

@@ -26,6 +26,7 @@
#pragma once
#include "fileinformation.h"
#include "sourcedependency.h"
#include "sourcelocationentry.h"
#include "symbolentry.h"
#include "usedmacro.h"
@@ -77,10 +78,16 @@ public:
return m_fileInformations;
}
const SourceDependencies &sourceDependencies() const
{
return m_sourceDependencies;
}
private:
FilePathIds m_sourceFiles;
UsedMacros m_usedMacros;
FileInformations m_fileInformations;
SourceDependencies m_sourceDependencies;
SymbolEntries &m_symbolEntries;
SourceLocationEntries &m_sourceLocationEntries;
FilePathCachingInterface &m_filePathCache;

View File

@@ -87,4 +87,9 @@ const FileInformations &SymbolsCollector::fileInformations() const
return m_collectMacrosSourceFileCallbacks.fileInformations();
}
const SourceDependencies &SymbolsCollector::sourceDependencies() const
{
return m_collectMacrosSourceFileCallbacks.sourceDependencies();
}
} // namespace ClangBackEnd

View File

@@ -53,6 +53,7 @@ public:
const FilePathIds &sourceFiles() const override;
const UsedMacros &usedMacros() const override;
const FileInformations &fileInformations() const override;
const SourceDependencies &sourceDependencies() const override;
private:
ClangTool m_clangTool;

View File

@@ -27,6 +27,7 @@
#include "fileinformation.h"
#include "symbolentry.h"
#include "sourcedependency.h"
#include "sourcelocationentry.h"
#include "usedmacro.h"
@@ -56,6 +57,7 @@ public:
virtual const FilePathIds &sourceFiles() const = 0;
virtual const UsedMacros &usedMacros() const = 0;
virtual const FileInformations &fileInformations() const = 0;
virtual const SourceDependencies &sourceDependencies() const = 0;
};
} // namespace ClangBackEnd

View File

@@ -50,22 +50,30 @@ public:
FilePathId filePathId(clang::SourceLocation sourceLocation)
{
uint clangFileId = m_sourceManager.getFileID(sourceLocation).getHashValue();
clang::FileID clangFileId = m_sourceManager.getFileID(sourceLocation);
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(clangFileId);
auto found = m_filePathIndices.find(clangFileId);
return filePathId(fileEntry);
}
FilePathId filePathId(const clang::FileEntry *fileEntry)
{
if (fileEntry) {
uint fileHash = fileEntry->getUID();
auto found = m_filePathIndices.find(fileHash);
if (found != m_filePathIndices.end())
return found->second;
auto filePath = m_sourceManager.getFilename(sourceLocation);
if (filePath.size() > 0) {
auto filePath = fileEntry->getName();
FilePathId filePathId = m_filePathCache.filePathId(FilePath::fromNativeFilePath(absolutePath(filePath)));
m_filePathIndices.emplace(clangFileId, filePathId);
m_filePathIndices.emplace(fileHash, filePathId);
return filePathId;
}
return {};
}

View File

@@ -0,0 +1,3 @@
#pragma once
#include "symbolscollector_header2.h"

View File

@@ -0,0 +1,5 @@
#include "symbolscollector_header1.h"
#include "symbolscollector_header3.h"
void function();

View File

@@ -39,6 +39,7 @@
#include <filepath.h>
#include <nativefilepath.h>
#include <precompiledheadersupdatedmessage.h>
#include <sourcedependency.h>
#include <sourcelocationentry.h>
#include <sourcelocationscontainer.h>
#include <tokeninfos.h>
@@ -838,6 +839,15 @@ std::ostream &operator<<(std::ostream &out, const FileInformation &fileInformati
<< ")";
}
std::ostream &operator<<(std::ostream &out, const SourceDependency &sourceDependency)
{
return out << "("
<< sourceDependency.filePathId
<< ", "
<< sourceDependency.dependencyFilePathId
<< ")";
}
void PrintTo(const FilePath &filePath, ::std::ostream *os)
{
*os << filePath;

View File

@@ -134,6 +134,7 @@ class ToolTipInfo;
class ProjectPartEntry;
class UsedMacro;
class FileInformation;
class SourceDependency;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -198,6 +199,7 @@ std::ostream &operator<<(std::ostream &out, const NativeFilePathView &nativeFile
std::ostream &operator<<(std::ostream &out, const ProjectPartEntry &projectPartEntry);
std::ostream &operator<<(std::ostream &out, const UsedMacro &usedMacro);
std::ostream &operator<<(std::ostream &out, const FileInformation &fileInformation);
std::ostream &operator<<(std::ostream &out, const SourceDependency &sourceDependency);
void PrintTo(const FilePath &filePath, ::std::ostream *os);
void PrintTo(const FilePathView &filePathView, ::std::ostream *os);

View File

@@ -59,4 +59,7 @@ public:
MOCK_CONST_METHOD0(fileInformations,
const ClangBackEnd::FileInformations &());
MOCK_CONST_METHOD0(sourceDependencies,
const ClangBackEnd::SourceDependencies &());
};

View File

@@ -50,6 +50,7 @@ using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathCaching;
using ClangBackEnd::V2::FileContainers;
using ClangBackEnd::SourceDependency;
using ClangBackEnd::SourceLocationEntry;
using ClangBackEnd::SymbolEntry;
using ClangBackEnd::SymbolType;
@@ -563,4 +564,21 @@ TEST_F(SymbolsCollector, CollectFileInformations)
fileInformation(TESTDATA_DIR "/symbolscollector_header2.h")));
}
TEST_F(SymbolsCollector, CollectSourceDependencies)
{
auto mainFileId = filePathId(TESTDATA_DIR "/symbolscollector_main2.cpp");
auto header1FileId = filePathId(TESTDATA_DIR "/symbolscollector_header1.h");
auto header2FileId = filePathId(TESTDATA_DIR "/symbolscollector_header2.h");
auto header3FileId = filePathId(TESTDATA_DIR "/symbolscollector_header3.h");
collector.addFiles({mainFileId}, {"cc", "-I" TESTDATA_DIR});
collector.collectSymbols();
ASSERT_THAT(collector.sourceDependencies(),
UnorderedElementsAre(SourceDependency(mainFileId, header1FileId),
SourceDependency(mainFileId, header3FileId),
SourceDependency(header3FileId, header2FileId),
SourceDependency(header1FileId, header2FileId)));
}
}