forked from qt-creator/qt-creator
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:
@@ -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;
|
||||
|
@@ -39,6 +39,7 @@ bool CollectMacrosSourceFileCallbacks::handleBeginSource(clang::CompilerInstance
|
||||
m_sourceFiles,
|
||||
m_usedMacros,
|
||||
m_fileInformations,
|
||||
m_sourceDependencies,
|
||||
m_filePathCache,
|
||||
compilerInstance.getSourceManager(),
|
||||
compilerInstance.getPreprocessorPtr());
|
||||
|
@@ -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;
|
||||
|
@@ -87,4 +87,9 @@ const FileInformations &SymbolsCollector::fileInformations() const
|
||||
return m_collectMacrosSourceFileCallbacks.fileInformations();
|
||||
}
|
||||
|
||||
const SourceDependencies &SymbolsCollector::sourceDependencies() const
|
||||
{
|
||||
return m_collectMacrosSourceFileCallbacks.sourceDependencies();
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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 {};
|
||||
}
|
||||
|
||||
|
3
tests/unit/unittest/data/symbolscollector_header3.h
Normal file
3
tests/unit/unittest/data/symbolscollector_header3.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "symbolscollector_header2.h"
|
5
tests/unit/unittest/data/symbolscollector_main2.cpp
Normal file
5
tests/unit/unittest/data/symbolscollector_main2.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "symbolscollector_header1.h"
|
||||
#include "symbolscollector_header3.h"
|
||||
|
||||
void function();
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -59,4 +59,7 @@ public:
|
||||
|
||||
MOCK_CONST_METHOD0(fileInformations,
|
||||
const ClangBackEnd::FileInformations &());
|
||||
|
||||
MOCK_CONST_METHOD0(sourceDependencies,
|
||||
const ClangBackEnd::SourceDependencies &());
|
||||
};
|
||||
|
@@ -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)));
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user