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 "fileinformation.h"
|
||||||
#include "symbolsvisitorbase.h"
|
#include "symbolsvisitorbase.h"
|
||||||
|
#include "sourcedependency.h"
|
||||||
#include "sourcelocationsutils.h"
|
#include "sourcelocationsutils.h"
|
||||||
#include "sourcelocationentry.h"
|
#include "sourcelocationentry.h"
|
||||||
#include "symbolentry.h"
|
#include "symbolentry.h"
|
||||||
@@ -50,6 +51,7 @@ public:
|
|||||||
FilePathIds &sourceFiles,
|
FilePathIds &sourceFiles,
|
||||||
UsedMacros &usedMacros,
|
UsedMacros &usedMacros,
|
||||||
FileInformations &fileInformations,
|
FileInformations &fileInformations,
|
||||||
|
SourceDependencies &sourceDependencies,
|
||||||
FilePathCachingInterface &filePathCache,
|
FilePathCachingInterface &filePathCache,
|
||||||
const clang::SourceManager &sourceManager,
|
const clang::SourceManager &sourceManager,
|
||||||
std::shared_ptr<clang::Preprocessor> &&preprocessor)
|
std::shared_ptr<clang::Preprocessor> &&preprocessor)
|
||||||
@@ -59,7 +61,8 @@ public:
|
|||||||
m_sourceLocationEntries(sourceLocationEntries),
|
m_sourceLocationEntries(sourceLocationEntries),
|
||||||
m_sourceFiles(sourceFiles),
|
m_sourceFiles(sourceFiles),
|
||||||
m_usedMacros(usedMacros),
|
m_usedMacros(usedMacros),
|
||||||
m_fileInformations(fileInformations)
|
m_fileInformations(fileInformations),
|
||||||
|
m_sourceDependencies(sourceDependencies)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,14 +76,15 @@ public:
|
|||||||
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(
|
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(
|
||||||
m_sourceManager.getFileID(sourceLocation));
|
m_sourceManager.getFileID(sourceLocation));
|
||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
m_fileInformations.emplace_back(filePathId(sourceLocation),
|
m_fileInformations.emplace_back(filePathId(fileEntry),
|
||||||
fileEntry->getSize(),
|
fileEntry->getSize(),
|
||||||
fileEntry->getModificationTime());
|
fileEntry->getModificationTime());
|
||||||
|
addSourceFile(fileEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InclusionDirective(clang::SourceLocation /*hashLocation*/,
|
void InclusionDirective(clang::SourceLocation hashLocation,
|
||||||
const clang::Token &/*includeToken*/,
|
const clang::Token &/*includeToken*/,
|
||||||
llvm::StringRef /*fileName*/,
|
llvm::StringRef /*fileName*/,
|
||||||
bool /*isAngled*/,
|
bool /*isAngled*/,
|
||||||
@@ -91,7 +95,7 @@ public:
|
|||||||
const clang::Module * /*imported*/) override
|
const clang::Module * /*imported*/) override
|
||||||
{
|
{
|
||||||
if (!m_skipInclude && file)
|
if (!m_skipInclude && file)
|
||||||
addSourceFile(file);
|
addSourceDependency(file, hashLocation);
|
||||||
|
|
||||||
m_skipInclude = false;
|
m_skipInclude = false;
|
||||||
}
|
}
|
||||||
@@ -268,18 +272,26 @@ public:
|
|||||||
|
|
||||||
void addSourceFile(const clang::FileEntry *file)
|
void addSourceFile(const clang::FileEntry *file)
|
||||||
{
|
{
|
||||||
auto filePathId = m_filePathCache.filePathId(
|
auto id = filePathId(file);
|
||||||
FilePath::fromNativeFilePath(absolutePath(file->getName())));
|
|
||||||
|
|
||||||
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)
|
if (found == m_sourceFiles.end() || *found != id)
|
||||||
m_sourceFiles.insert(found, filePathId);
|
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:
|
private:
|
||||||
UsedMacros m_maybeUsedMacros;
|
UsedMacros m_maybeUsedMacros;
|
||||||
std::shared_ptr<clang::Preprocessor> m_preprocessor;
|
std::shared_ptr<clang::Preprocessor> m_preprocessor;
|
||||||
|
SourceDependencies &m_sourceDependencies;
|
||||||
SymbolEntries &m_symbolEntries;
|
SymbolEntries &m_symbolEntries;
|
||||||
SourceLocationEntries &m_sourceLocationEntries;
|
SourceLocationEntries &m_sourceLocationEntries;
|
||||||
FilePathIds &m_sourceFiles;
|
FilePathIds &m_sourceFiles;
|
||||||
|
@@ -39,6 +39,7 @@ bool CollectMacrosSourceFileCallbacks::handleBeginSource(clang::CompilerInstance
|
|||||||
m_sourceFiles,
|
m_sourceFiles,
|
||||||
m_usedMacros,
|
m_usedMacros,
|
||||||
m_fileInformations,
|
m_fileInformations,
|
||||||
|
m_sourceDependencies,
|
||||||
m_filePathCache,
|
m_filePathCache,
|
||||||
compilerInstance.getSourceManager(),
|
compilerInstance.getSourceManager(),
|
||||||
compilerInstance.getPreprocessorPtr());
|
compilerInstance.getPreprocessorPtr());
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fileinformation.h"
|
#include "fileinformation.h"
|
||||||
|
#include "sourcedependency.h"
|
||||||
#include "sourcelocationentry.h"
|
#include "sourcelocationentry.h"
|
||||||
#include "symbolentry.h"
|
#include "symbolentry.h"
|
||||||
#include "usedmacro.h"
|
#include "usedmacro.h"
|
||||||
@@ -77,10 +78,16 @@ public:
|
|||||||
return m_fileInformations;
|
return m_fileInformations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SourceDependencies &sourceDependencies() const
|
||||||
|
{
|
||||||
|
return m_sourceDependencies;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FilePathIds m_sourceFiles;
|
FilePathIds m_sourceFiles;
|
||||||
UsedMacros m_usedMacros;
|
UsedMacros m_usedMacros;
|
||||||
FileInformations m_fileInformations;
|
FileInformations m_fileInformations;
|
||||||
|
SourceDependencies m_sourceDependencies;
|
||||||
SymbolEntries &m_symbolEntries;
|
SymbolEntries &m_symbolEntries;
|
||||||
SourceLocationEntries &m_sourceLocationEntries;
|
SourceLocationEntries &m_sourceLocationEntries;
|
||||||
FilePathCachingInterface &m_filePathCache;
|
FilePathCachingInterface &m_filePathCache;
|
||||||
|
@@ -87,4 +87,9 @@ const FileInformations &SymbolsCollector::fileInformations() const
|
|||||||
return m_collectMacrosSourceFileCallbacks.fileInformations();
|
return m_collectMacrosSourceFileCallbacks.fileInformations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SourceDependencies &SymbolsCollector::sourceDependencies() const
|
||||||
|
{
|
||||||
|
return m_collectMacrosSourceFileCallbacks.sourceDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -53,6 +53,7 @@ public:
|
|||||||
const FilePathIds &sourceFiles() const override;
|
const FilePathIds &sourceFiles() const override;
|
||||||
const UsedMacros &usedMacros() const override;
|
const UsedMacros &usedMacros() const override;
|
||||||
const FileInformations &fileInformations() const override;
|
const FileInformations &fileInformations() const override;
|
||||||
|
const SourceDependencies &sourceDependencies() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClangTool m_clangTool;
|
ClangTool m_clangTool;
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "fileinformation.h"
|
#include "fileinformation.h"
|
||||||
#include "symbolentry.h"
|
#include "symbolentry.h"
|
||||||
|
#include "sourcedependency.h"
|
||||||
#include "sourcelocationentry.h"
|
#include "sourcelocationentry.h"
|
||||||
#include "usedmacro.h"
|
#include "usedmacro.h"
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ public:
|
|||||||
virtual const FilePathIds &sourceFiles() const = 0;
|
virtual const FilePathIds &sourceFiles() const = 0;
|
||||||
virtual const UsedMacros &usedMacros() const = 0;
|
virtual const UsedMacros &usedMacros() const = 0;
|
||||||
virtual const FileInformations &fileInformations() const = 0;
|
virtual const FileInformations &fileInformations() const = 0;
|
||||||
|
virtual const SourceDependencies &sourceDependencies() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -50,22 +50,30 @@ public:
|
|||||||
|
|
||||||
FilePathId filePathId(clang::SourceLocation sourceLocation)
|
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())
|
if (found != m_filePathIndices.end())
|
||||||
return found->second;
|
return found->second;
|
||||||
|
|
||||||
auto filePath = m_sourceManager.getFilename(sourceLocation);
|
auto filePath = fileEntry->getName();
|
||||||
|
|
||||||
if (filePath.size() > 0) {
|
|
||||||
FilePathId filePathId = m_filePathCache.filePathId(FilePath::fromNativeFilePath(absolutePath(filePath)));
|
FilePathId filePathId = m_filePathCache.filePathId(FilePath::fromNativeFilePath(absolutePath(filePath)));
|
||||||
|
|
||||||
m_filePathIndices.emplace(clangFileId, filePathId);
|
m_filePathIndices.emplace(fileHash, filePathId);
|
||||||
|
|
||||||
return filePathId;
|
return filePathId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
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 <filepath.h>
|
||||||
#include <nativefilepath.h>
|
#include <nativefilepath.h>
|
||||||
#include <precompiledheadersupdatedmessage.h>
|
#include <precompiledheadersupdatedmessage.h>
|
||||||
|
#include <sourcedependency.h>
|
||||||
#include <sourcelocationentry.h>
|
#include <sourcelocationentry.h>
|
||||||
#include <sourcelocationscontainer.h>
|
#include <sourcelocationscontainer.h>
|
||||||
#include <tokeninfos.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)
|
void PrintTo(const FilePath &filePath, ::std::ostream *os)
|
||||||
{
|
{
|
||||||
*os << filePath;
|
*os << filePath;
|
||||||
|
@@ -134,6 +134,7 @@ class ToolTipInfo;
|
|||||||
class ProjectPartEntry;
|
class ProjectPartEntry;
|
||||||
class UsedMacro;
|
class UsedMacro;
|
||||||
class FileInformation;
|
class FileInformation;
|
||||||
|
class SourceDependency;
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
|
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
|
||||||
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
|
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 ProjectPartEntry &projectPartEntry);
|
||||||
std::ostream &operator<<(std::ostream &out, const UsedMacro &usedMacro);
|
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 FileInformation &fileInformation);
|
||||||
|
std::ostream &operator<<(std::ostream &out, const SourceDependency &sourceDependency);
|
||||||
|
|
||||||
void PrintTo(const FilePath &filePath, ::std::ostream *os);
|
void PrintTo(const FilePath &filePath, ::std::ostream *os);
|
||||||
void PrintTo(const FilePathView &filePathView, ::std::ostream *os);
|
void PrintTo(const FilePathView &filePathView, ::std::ostream *os);
|
||||||
|
@@ -59,4 +59,7 @@ public:
|
|||||||
|
|
||||||
MOCK_CONST_METHOD0(fileInformations,
|
MOCK_CONST_METHOD0(fileInformations,
|
||||||
const ClangBackEnd::FileInformations &());
|
const ClangBackEnd::FileInformations &());
|
||||||
|
|
||||||
|
MOCK_CONST_METHOD0(sourceDependencies,
|
||||||
|
const ClangBackEnd::SourceDependencies &());
|
||||||
};
|
};
|
||||||
|
@@ -50,6 +50,7 @@ using ClangBackEnd::FilePath;
|
|||||||
using ClangBackEnd::FilePathId;
|
using ClangBackEnd::FilePathId;
|
||||||
using ClangBackEnd::FilePathCaching;
|
using ClangBackEnd::FilePathCaching;
|
||||||
using ClangBackEnd::V2::FileContainers;
|
using ClangBackEnd::V2::FileContainers;
|
||||||
|
using ClangBackEnd::SourceDependency;
|
||||||
using ClangBackEnd::SourceLocationEntry;
|
using ClangBackEnd::SourceLocationEntry;
|
||||||
using ClangBackEnd::SymbolEntry;
|
using ClangBackEnd::SymbolEntry;
|
||||||
using ClangBackEnd::SymbolType;
|
using ClangBackEnd::SymbolType;
|
||||||
@@ -563,4 +564,21 @@ TEST_F(SymbolsCollector, CollectFileInformations)
|
|||||||
fileInformation(TESTDATA_DIR "/symbolscollector_header2.h")));
|
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