forked from qt-creator/qt-creator
Clang: Add BuildDependencyCollector
IncludeCollector is renamed to BuildDependencyCollector. It is now returning a BuildDependency instead of individual getter. The test coverage is improved too. Task-number: QTCREATORBUG-21379 Change-Id: Ifc2d1c40c85772cf498c21968de526f4408b6023 Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
@@ -232,7 +233,19 @@ ostream &operator<<(ostream &out, const vector<T> &vector)
|
||||
{
|
||||
out << "[";
|
||||
|
||||
copy(vector.cbegin(), vector.cend(), ostream_iterator<T>(out, ", "));
|
||||
for (auto current = vector.begin(); current != vector.end(); ++current) {
|
||||
std::ostringstream entryStream;
|
||||
entryStream << *current;
|
||||
std::string entryString = entryStream.str();
|
||||
|
||||
if (entryString.size() > 4)
|
||||
out << "\n\t";
|
||||
|
||||
out << entryString;
|
||||
|
||||
if (std::next(current) != vector.end())
|
||||
out << ", ";
|
||||
}
|
||||
|
||||
out << "]";
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "builddependenciesstorageinterface.h"
|
||||
#include "modifiedtimecheckerinterface.h"
|
||||
#include "builddependenciesgeneratorinterface.h"
|
||||
#include "builddependencygeneratorinterface.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
@@ -31,14 +31,14 @@ namespace ClangBackEnd {
|
||||
|
||||
class BuildDependenciesStorageInterface;
|
||||
class ModifiedTimeCheckerInterface;
|
||||
class BuildDependenciesGeneratorInterface;
|
||||
class BuildDependencyGeneratorInterface;
|
||||
|
||||
class BuildDependenciesProvider : public BuildDependenciesProviderInterface
|
||||
{
|
||||
public:
|
||||
BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage,
|
||||
ModifiedTimeCheckerInterface &modifiedTimeChecker,
|
||||
BuildDependenciesGeneratorInterface &buildDependenciesGenerator)
|
||||
BuildDependencyGeneratorInterface &buildDependenciesGenerator)
|
||||
: m_buildDependenciesStorage(buildDependenciesStorage),
|
||||
m_modifiedTimeChecker(modifiedTimeChecker),
|
||||
m_buildDependenciesGenerator(buildDependenciesGenerator)
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
private:
|
||||
BuildDependenciesStorageInterface &m_buildDependenciesStorage;
|
||||
ModifiedTimeCheckerInterface &m_modifiedTimeChecker;
|
||||
BuildDependenciesGeneratorInterface &m_buildDependenciesGenerator;
|
||||
BuildDependencyGeneratorInterface &m_buildDependenciesGenerator;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "filestatus.h"
|
||||
#include "sourcedependency.h"
|
||||
#include "sourceentry.h"
|
||||
#include "usedmacro.h"
|
||||
|
||||
@@ -32,13 +34,24 @@ namespace ClangBackEnd {
|
||||
|
||||
class BuildDependency
|
||||
{
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
includes.clear();
|
||||
usedMacros.clear();
|
||||
sourceFiles.clear();
|
||||
fileStatuses.clear();
|
||||
sourceDependencies.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
SourceEntries includes;
|
||||
FilePathIds topIncludeIds;
|
||||
FilePathIds topsSystemIncludeIds;
|
||||
UsedMacros usedMacros;
|
||||
FilePathIds sourceFiles;
|
||||
SourceDependencies sourceDependencies;
|
||||
FileStatuses fileStatuses;
|
||||
};
|
||||
|
||||
using BuildDependencies = std::vector<BuildDependency>;
|
||||
|
||||
}
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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 "builddependencycollector.h"
|
||||
|
||||
#include "collectbuilddependencytoolaction.h"
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
namespace {
|
||||
FilePathIds operator+(const FilePathIds &first, const FilePathIds &second)
|
||||
{
|
||||
FilePathIds result = first;
|
||||
|
||||
std::copy(second.begin(), second.end(), std::back_inserter(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
BuildDependency BuildDependencyCollector::create(const V2::ProjectPartContainer &projectPart)
|
||||
{
|
||||
addFiles(projectPart.sourcePathIds, projectPart.arguments);
|
||||
|
||||
setExcludedFilePaths(
|
||||
m_filePathCache.filePaths(projectPart.headerPathIds + projectPart.sourcePathIds));
|
||||
|
||||
collect();
|
||||
|
||||
return std::move(m_buildDependency);
|
||||
}
|
||||
|
||||
void BuildDependencyCollector::collect()
|
||||
{
|
||||
clang::tooling::ClangTool tool = m_clangTool.createTool();
|
||||
|
||||
auto action = std::make_unique<CollectBuildDependencyToolAction>(m_buildDependency,
|
||||
m_filePathCache,
|
||||
m_excludedFilePaths,
|
||||
m_sourcesManager);
|
||||
|
||||
tool.run(action.get());
|
||||
}
|
||||
|
||||
void BuildDependencyCollector::setExcludedFilePaths(ClangBackEnd::FilePaths &&excludedFilePaths)
|
||||
{
|
||||
if (Utils::HostOsInfo::isWindowsHost()) {
|
||||
m_excludedFilePaths.clear();
|
||||
m_excludedFilePaths.reserve(excludedFilePaths.size());
|
||||
std::transform(std::make_move_iterator(excludedFilePaths.begin()),
|
||||
std::make_move_iterator(excludedFilePaths.end()),
|
||||
std::back_inserter(m_excludedFilePaths),
|
||||
[](auto &&path) {
|
||||
path.replace("/", "\\");
|
||||
return std::move(path);
|
||||
});
|
||||
} else {
|
||||
m_excludedFilePaths = std::move(excludedFilePaths);
|
||||
}
|
||||
}
|
||||
|
||||
void BuildDependencyCollector::addFiles(const FilePathIds &filePathIds,
|
||||
const Utils::SmallStringVector &arguments)
|
||||
{
|
||||
m_clangTool.addFiles(m_filePathCache.filePaths(filePathIds), arguments);
|
||||
m_buildDependency.sourceFiles.insert(m_buildDependency.sourceFiles.end(),
|
||||
filePathIds.begin(),
|
||||
filePathIds.end());
|
||||
}
|
||||
|
||||
void BuildDependencyCollector::addFile(FilePathId filePathId,
|
||||
const Utils::SmallStringVector &arguments)
|
||||
{
|
||||
addFiles({filePathId}, arguments);
|
||||
}
|
||||
|
||||
void BuildDependencyCollector::addFile(FilePath filePath,
|
||||
const FilePathIds &sourceFileIds,
|
||||
const Utils::SmallStringVector &arguments)
|
||||
{
|
||||
m_clangTool.addFiles({filePath}, arguments);
|
||||
m_buildDependency.sourceFiles.insert(m_buildDependency.sourceFiles.end(),
|
||||
sourceFileIds.begin(),
|
||||
sourceFileIds.end());
|
||||
}
|
||||
|
||||
void BuildDependencyCollector::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
|
||||
{
|
||||
m_clangTool.addUnsavedFiles(unsavedFiles);
|
||||
}
|
||||
|
||||
void BuildDependencyCollector::clear()
|
||||
{
|
||||
m_clangTool = ClangTool();
|
||||
m_buildDependency.clear();
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -25,27 +25,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "builddependencygeneratorinterface.h"
|
||||
|
||||
#include <clangtool.h>
|
||||
#include <filestatus.h>
|
||||
#include <sourcedependency.h>
|
||||
#include <sourcesmanager.h>
|
||||
#include <usedmacro.h>
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class IncludeCollector : public ClangTool
|
||||
class BuildDependencyCollector : public BuildDependencyGeneratorInterface
|
||||
{
|
||||
public:
|
||||
IncludeCollector(const FilePathCachingInterface &filePathCache)
|
||||
BuildDependencyCollector(const FilePathCachingInterface &filePathCache)
|
||||
: m_filePathCache(filePathCache)
|
||||
{
|
||||
}
|
||||
|
||||
BuildDependency create(const V2::ProjectPartContainer &projectPart) override;
|
||||
|
||||
void collect();
|
||||
|
||||
void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes);
|
||||
void setExcludedFilePaths(ClangBackEnd::FilePaths &&excludedIncludes);
|
||||
void addFiles(const FilePathIds &filePathIds,
|
||||
const Utils::SmallStringVector &arguments);
|
||||
void addFile(FilePathId filePathId,
|
||||
@@ -53,62 +54,43 @@ public:
|
||||
void addFile(FilePath filePath,
|
||||
const FilePathIds &sourceFileIds,
|
||||
const Utils::SmallStringVector &arguments);
|
||||
void addUnsavedFiles(const V2::FileContainers &unsavedFiles);
|
||||
|
||||
void clear();
|
||||
|
||||
const FileStatuses &fileStatuses() const
|
||||
{
|
||||
return m_fileStatuses;
|
||||
return m_buildDependency.fileStatuses;
|
||||
}
|
||||
|
||||
const FilePathIds &sourceFiles() const
|
||||
{
|
||||
return m_sourceFiles;
|
||||
return m_buildDependency.sourceFiles;
|
||||
}
|
||||
|
||||
const UsedMacros &usedMacros() const
|
||||
{
|
||||
return m_usedMacros;
|
||||
return m_buildDependency.usedMacros;
|
||||
}
|
||||
|
||||
const SourceDependencies &sourceDependencies() const
|
||||
{
|
||||
return m_sourceDependencies;
|
||||
return m_buildDependency.sourceDependencies;
|
||||
}
|
||||
|
||||
FilePathIds takeIncludeIds()
|
||||
const SourceEntries &includeIds()
|
||||
{
|
||||
std::sort(m_includeIds.begin(), m_includeIds.end());
|
||||
std::sort(m_buildDependency.includes.begin(), m_buildDependency.includes.end());
|
||||
|
||||
return std::move(m_includeIds);
|
||||
}
|
||||
|
||||
FilePathIds takeTopIncludeIds()
|
||||
{
|
||||
std::sort(m_topIncludeIds.begin(), m_topIncludeIds.end());
|
||||
|
||||
return std::move(m_topIncludeIds);
|
||||
}
|
||||
|
||||
FilePathIds takeTopsSystemIncludeIds()
|
||||
{
|
||||
std::sort(m_topsSystemIncludeIds.begin(), m_topsSystemIncludeIds.end());
|
||||
|
||||
return std::move(m_topsSystemIncludeIds);
|
||||
return std::move(m_buildDependency.includes);
|
||||
}
|
||||
|
||||
private:
|
||||
ClangTool m_clangTool;
|
||||
Utils::PathStringVector m_excludedIncludes;
|
||||
FilePathIds m_includeIds;
|
||||
FilePathIds m_topIncludeIds;
|
||||
FilePathIds m_topsSystemIncludeIds;
|
||||
BuildDependency m_buildDependency;
|
||||
ClangBackEnd::FilePaths m_excludedFilePaths;
|
||||
Utils::SmallStringVector m_directories;
|
||||
SourcesManager m_sourcesManager;
|
||||
UsedMacros m_usedMacros;
|
||||
FilePathIds m_sourceFiles;
|
||||
SourceDependencies m_sourceDependencies;
|
||||
FileStatuses m_fileStatuses;
|
||||
const FilePathCachingInterface &m_filePathCache;
|
||||
};
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class BuildDependenciesGeneratorInterface
|
||||
class BuildDependencyGeneratorInterface
|
||||
{
|
||||
public:
|
||||
virtual BuildDependency create(const V2::ProjectPartContainer &projectPart) = 0;
|
||||
|
||||
protected:
|
||||
~BuildDependenciesGeneratorInterface() = default;
|
||||
~BuildDependencyGeneratorInterface() = default;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -5,7 +5,8 @@ SOURCES += \
|
||||
$$PWD/projectparts.cpp \
|
||||
$$PWD/projectpartqueue.cpp \
|
||||
$$PWD/pchtaskgenerator.cpp \
|
||||
$$PWD/builddependenciesprovider.cpp
|
||||
$$PWD/builddependenciesprovider.cpp \
|
||||
$$PWD/builddependencycollector.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/pchmanagerserver.h \
|
||||
@@ -32,20 +33,19 @@ HEADERS += \
|
||||
$$PWD/builddependency.h \
|
||||
$$PWD/modifiedtimecheckerinterface.h \
|
||||
$$PWD/sourceentry.h \
|
||||
$$PWD/builddependenciesgeneratorinterface.h \
|
||||
$$PWD/builddependenciesstorage.h
|
||||
$$PWD/builddependenciesstorage.h \
|
||||
$$PWD/builddependencycollector.h \
|
||||
$$PWD/builddependencygeneratorinterface.h \
|
||||
$$PWD/collectbuilddependencytoolaction.h \
|
||||
$$PWD/collectbuilddependencyaction.h \
|
||||
$$PWD/collectbuilddependencypreprocessorcallbacks.h
|
||||
|
||||
!isEmpty(LIBTOOLING_LIBS) {
|
||||
SOURCES += \
|
||||
$$PWD/usedmacrosandsourcescollector.cpp \
|
||||
$$PWD/includecollector.cpp \
|
||||
$$PWD/pchcreator.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/includecollector.h \
|
||||
$$PWD/collectincludestoolaction.h \
|
||||
$$PWD/collectincludesaction.h \
|
||||
$$PWD/collectincludespreprocessorcallbacks.h \
|
||||
$$PWD/collectusedmacroactionfactory.h \
|
||||
$$PWD/collectusedmacrosaction.h \
|
||||
$$PWD/collectusedmacrosandsourcespreprocessorcallbacks.h \
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <collectincludespreprocessorcallbacks.h>
|
||||
#include <collectbuilddependencypreprocessorcallbacks.h>
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <filepathid.h>
|
||||
@@ -36,31 +36,19 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class CollectIncludesAction final : public clang::PreprocessOnlyAction
|
||||
class CollectBuildDependencyAction final : public clang::PreprocessOnlyAction
|
||||
{
|
||||
public:
|
||||
CollectIncludesAction(FilePathIds &includeIds,
|
||||
FilePathIds &topIncludeIds,
|
||||
FilePathIds &topsSystemIncludeIds,
|
||||
CollectBuildDependencyAction(BuildDependency &buildDependency,
|
||||
const FilePathCachingInterface &filePathCache,
|
||||
std::vector<uint> &excludedIncludeUID,
|
||||
std::vector<uint> &alreadyIncludedFileUIDs,
|
||||
UsedMacros &usedMacros,
|
||||
SourcesManager &sourcesManager,
|
||||
SourceDependencies &sourceDependencies,
|
||||
FilePathIds &sourceFiles,
|
||||
FileStatuses &fileStatuses)
|
||||
: m_includeIds(includeIds),
|
||||
m_topIncludeIds(topIncludeIds),
|
||||
m_topsSystemIncludeIds(topsSystemIncludeIds),
|
||||
SourcesManager &sourcesManager)
|
||||
: m_buildDependency(buildDependency),
|
||||
m_filePathCache(filePathCache),
|
||||
m_excludedIncludeUID(excludedIncludeUID),
|
||||
m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs),
|
||||
m_usedMacros(usedMacros),
|
||||
m_sourcesManager(sourcesManager),
|
||||
m_sourceDependencies(sourceDependencies),
|
||||
m_sourceFiles(sourceFiles),
|
||||
m_fileStatuses(fileStatuses)
|
||||
m_sourcesManager(sourcesManager)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -71,20 +59,14 @@ public:
|
||||
|
||||
preprocessor.SetSuppressIncludeNotFoundError(true);
|
||||
|
||||
auto macroPreprocessorCallbacks = new CollectIncludesPreprocessorCallbacks(
|
||||
m_includeIds,
|
||||
m_topIncludeIds,
|
||||
m_topsSystemIncludeIds,
|
||||
auto macroPreprocessorCallbacks = new CollectBuildDependencyPreprocessorCallbacks(
|
||||
m_buildDependency,
|
||||
m_filePathCache,
|
||||
m_excludedIncludeUID,
|
||||
m_alreadyIncludedFileUIDs,
|
||||
compilerInstance.getSourceManager(),
|
||||
m_usedMacros,
|
||||
m_sourcesManager,
|
||||
compilerInstance.getPreprocessorPtr(),
|
||||
m_sourceDependencies,
|
||||
m_sourceFiles,
|
||||
m_fileStatuses);
|
||||
compilerInstance.getPreprocessorPtr());
|
||||
|
||||
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks));
|
||||
|
||||
@@ -100,17 +82,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
FilePathIds &m_includeIds;
|
||||
FilePathIds &m_topIncludeIds;
|
||||
FilePathIds &m_topsSystemIncludeIds;
|
||||
BuildDependency &m_buildDependency;
|
||||
const FilePathCachingInterface &m_filePathCache;
|
||||
std::vector<uint> &m_excludedIncludeUID;
|
||||
std::vector<uint> &m_alreadyIncludedFileUIDs;
|
||||
UsedMacros &m_usedMacros;
|
||||
SourcesManager &m_sourcesManager;
|
||||
SourceDependencies &m_sourceDependencies;
|
||||
FilePathIds &m_sourceFiles;
|
||||
FileStatuses &m_fileStatuses;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "builddependency.h"
|
||||
#include "collectmacrospreprocessorcallbacks.h"
|
||||
#include "sourcelocationsutils.h"
|
||||
|
||||
@@ -33,6 +34,8 @@
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
#include <llvm/Support/MemoryBuffer.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QTemporaryDir>
|
||||
@@ -41,34 +44,26 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks,
|
||||
class CollectBuildDependencyPreprocessorCallbacks final : public clang::PPCallbacks,
|
||||
public CollectUsedMacrosAndSourcesPreprocessorCallbacksBase
|
||||
{
|
||||
public:
|
||||
CollectIncludesPreprocessorCallbacks(FilePathIds &includeIds,
|
||||
FilePathIds &topIncludeIds,
|
||||
FilePathIds &topsSystemIncludeIds,
|
||||
CollectBuildDependencyPreprocessorCallbacks(BuildDependency &buildDependency,
|
||||
const FilePathCachingInterface &filePathCache,
|
||||
const std::vector<uint> &excludedIncludeUID,
|
||||
std::vector<uint> &alreadyIncludedFileUIDs,
|
||||
const clang::SourceManager &sourceManager,
|
||||
UsedMacros &usedMacros,
|
||||
clang::SourceManager &sourceManager,
|
||||
SourcesManager &sourcesManager,
|
||||
std::shared_ptr<clang::Preprocessor> preprocessor,
|
||||
SourceDependencies &sourceDependencies,
|
||||
FilePathIds &sourceFiles,
|
||||
FileStatuses &fileStatuses)
|
||||
: CollectUsedMacrosAndSourcesPreprocessorCallbacksBase(usedMacros,
|
||||
std::shared_ptr<clang::Preprocessor> preprocessor)
|
||||
: CollectUsedMacrosAndSourcesPreprocessorCallbacksBase(buildDependency.usedMacros,
|
||||
filePathCache,
|
||||
sourceManager,
|
||||
sourcesManager,
|
||||
preprocessor,
|
||||
sourceDependencies,
|
||||
sourceFiles,
|
||||
fileStatuses),
|
||||
m_includeIds(includeIds),
|
||||
m_topIncludeIds(topIncludeIds),
|
||||
m_topsSystemIncludeIds(topsSystemIncludeIds),
|
||||
buildDependency.sourceDependencies,
|
||||
buildDependency.sourceFiles,
|
||||
buildDependency.fileStatuses),
|
||||
m_buildDependency(buildDependency),
|
||||
m_excludedIncludeUID(excludedIncludeUID),
|
||||
m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs)
|
||||
{}
|
||||
@@ -90,7 +85,7 @@ public:
|
||||
}
|
||||
|
||||
void InclusionDirective(clang::SourceLocation hashLocation,
|
||||
const clang::Token &/*includeToken*/,
|
||||
const clang::Token & /*includeToken*/,
|
||||
llvm::StringRef /*fileName*/,
|
||||
bool /*isAngled*/,
|
||||
clang::CharSourceRange /*fileNameRange*/,
|
||||
@@ -103,20 +98,30 @@ public:
|
||||
if (!m_skipInclude && file) {
|
||||
addSourceDependency(file, hashLocation);
|
||||
auto fileUID = file->getUID();
|
||||
auto sourceFileUID = m_sourceManager->getFileEntryForID(m_sourceManager->getFileID(hashLocation))->getUID();
|
||||
if (isNotInExcludedIncludeUID(fileUID)) {
|
||||
auto sourceFileUID = m_sourceManager
|
||||
->getFileEntryForID(m_sourceManager->getFileID(hashLocation))
|
||||
->getUID();
|
||||
auto notAlreadyIncluded = isNotAlreadyIncluded(fileUID);
|
||||
if (notAlreadyIncluded.first) {
|
||||
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
|
||||
FilePath filePath = filePathFromFile(file);
|
||||
if (!filePath.empty()) {
|
||||
FilePathId includeId = m_filePathCache.filePathId(filePath);
|
||||
m_includeIds.emplace_back(includeId);
|
||||
if (isSystem(fileType) && !isInSystemHeader(hashLocation))
|
||||
m_topsSystemIncludeIds.emplace_back(includeId);
|
||||
if (isInExcludedIncludeUID(sourceFileUID))
|
||||
m_topIncludeIds.emplace_back(includeId);
|
||||
|
||||
time_t lastModified = file->getModificationTime();
|
||||
|
||||
SourceType sourceType = SourceType::UserInclude;
|
||||
if (isSystem(fileType)) {
|
||||
if (isInSystemHeader(hashLocation))
|
||||
sourceType = SourceType::SystemInclude;
|
||||
else
|
||||
sourceType = SourceType::TopSystemInclude;
|
||||
} else if (isNotInExcludedIncludeUID(fileUID)
|
||||
&& isInExcludedIncludeUID(sourceFileUID)) {
|
||||
sourceType = SourceType::TopInclude;
|
||||
}
|
||||
|
||||
addInclude({includeId, sourceType, lastModified});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,19 +129,12 @@ public:
|
||||
m_skipInclude = false;
|
||||
}
|
||||
|
||||
bool FileNotFound(clang::StringRef fileNameRef, clang::SmallVectorImpl<char> &recoveryPath) override
|
||||
bool FileNotFound(clang::StringRef /*fileNameRef*/,
|
||||
clang::SmallVectorImpl<char> &recoveryPath) override
|
||||
{
|
||||
QTemporaryDir temporaryDirectory;
|
||||
temporaryDirectory.setAutoRemove(false);
|
||||
const QByteArray temporaryDirUtf8 = temporaryDirectory.path().toUtf8();
|
||||
auto dummyPath = llvm::StringRef("/dummyPath");
|
||||
|
||||
const QString fileName = QString::fromUtf8(fileNameRef.data(), int(fileNameRef.size()));
|
||||
QString filePath = temporaryDirectory.path() + '/' + fileName;
|
||||
|
||||
ensureDirectory(temporaryDirectory.path(), fileName);
|
||||
createFakeFile(filePath);
|
||||
|
||||
recoveryPath.append(temporaryDirUtf8.cbegin(), temporaryDirUtf8.cend());
|
||||
recoveryPath.append(std::cbegin(dummyPath), std::cend(dummyPath));
|
||||
|
||||
m_skipInclude = true;
|
||||
|
||||
@@ -189,15 +187,6 @@ public:
|
||||
QDir(directory).mkpath(directoryEntries.join('/'));
|
||||
}
|
||||
|
||||
void createFakeFile(const QString &filePath)
|
||||
{
|
||||
QFile fakeFile;
|
||||
fakeFile.setFileName(filePath);
|
||||
|
||||
fakeFile.open(QIODevice::ReadWrite);
|
||||
fakeFile.close();
|
||||
}
|
||||
|
||||
bool isNotInExcludedIncludeUID(uint uid) const
|
||||
{
|
||||
return !isInExcludedIncludeUID(uid);
|
||||
@@ -224,10 +213,21 @@ public:
|
||||
return FilePath::fromNativeFilePath(absolutePath(file->getName()));
|
||||
}
|
||||
|
||||
void addInclude(SourceEntry sourceEntry)
|
||||
{
|
||||
auto &includes = m_buildDependency.includes;
|
||||
auto found = std::lower_bound(includes.begin(),
|
||||
includes.end(),
|
||||
sourceEntry,
|
||||
[](auto first, auto second) { return first < second; });
|
||||
|
||||
if (found == includes.end() || *found != sourceEntry)
|
||||
includes.emplace(found, sourceEntry);
|
||||
}
|
||||
|
||||
private:
|
||||
FilePathIds &m_includeIds;
|
||||
FilePathIds &m_topIncludeIds;
|
||||
FilePathIds &m_topsSystemIncludeIds;
|
||||
FilePathIds m_containsMissingIncludes;
|
||||
BuildDependency &m_buildDependency;
|
||||
const std::vector<uint> &m_excludedIncludeUID;
|
||||
std::vector<uint> &m_alreadyIncludedFileUIDs;
|
||||
bool m_skipInclude = false;
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "collectincludesaction.h"
|
||||
#include "collectbuilddependencyaction.h"
|
||||
|
||||
#include <filepathcachingfwd.h>
|
||||
#include <filepathid.h>
|
||||
@@ -34,29 +34,17 @@
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory
|
||||
class CollectBuildDependencyToolAction final : public clang::tooling::FrontendActionFactory
|
||||
{
|
||||
public:
|
||||
CollectIncludesToolAction(FilePathIds &includeIds,
|
||||
FilePathIds &topIncludeIds,
|
||||
FilePathIds &topsSystemIncludeIds,
|
||||
CollectBuildDependencyToolAction(BuildDependency &buildDependency,
|
||||
const FilePathCachingInterface &filePathCache,
|
||||
const Utils::PathStringVector &excludedIncludes,
|
||||
UsedMacros &usedMacros,
|
||||
SourcesManager &sourcesManager,
|
||||
SourceDependencies &sourceDependencies,
|
||||
FilePathIds &sourceFiles,
|
||||
FileStatuses &fileStatuses)
|
||||
: m_includeIds(includeIds),
|
||||
m_topIncludeIds(topIncludeIds),
|
||||
m_topsSystemIncludeIds(topsSystemIncludeIds),
|
||||
const ClangBackEnd::FilePaths &excludedIncludes,
|
||||
SourcesManager &sourcesManager)
|
||||
: m_buildDependency(buildDependency),
|
||||
m_filePathCache(filePathCache),
|
||||
m_excludedIncludes(excludedIncludes),
|
||||
m_usedMacros(usedMacros),
|
||||
m_sourcesManager(sourcesManager),
|
||||
m_sourceDependencies(sourceDependencies),
|
||||
m_sourceFiles(sourceFiles),
|
||||
m_fileStatuses(fileStatuses)
|
||||
m_excludedFilePaths(excludedIncludes),
|
||||
m_sourcesManager(sourcesManager)
|
||||
{}
|
||||
|
||||
|
||||
@@ -76,26 +64,21 @@ public:
|
||||
|
||||
clang::FrontendAction *create() override
|
||||
{
|
||||
return new CollectIncludesAction(m_includeIds,
|
||||
m_topIncludeIds,
|
||||
m_topsSystemIncludeIds,
|
||||
return new CollectBuildDependencyAction(m_buildDependency,
|
||||
m_filePathCache,
|
||||
m_excludedIncludeUIDs,
|
||||
m_alreadyIncludedFileUIDs,
|
||||
m_usedMacros,
|
||||
m_sourcesManager,
|
||||
m_sourceDependencies,
|
||||
m_sourceFiles,
|
||||
m_fileStatuses);
|
||||
m_sourcesManager);
|
||||
}
|
||||
|
||||
std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
|
||||
{
|
||||
std::vector<uint> fileUIDs;
|
||||
fileUIDs.reserve(m_excludedIncludes.size());
|
||||
fileUIDs.reserve(m_excludedFilePaths.size());
|
||||
|
||||
for (const Utils::PathString &filePath : m_excludedIncludes) {
|
||||
const clang::FileEntry *file = fileManager.getFile({filePath.data(), filePath.size()}, true);
|
||||
for (const ClangBackEnd::FilePath &filePath : m_excludedFilePaths) {
|
||||
const clang::FileEntry *file = fileManager.getFile({filePath.data(), filePath.size()},
|
||||
true);
|
||||
|
||||
if (file)
|
||||
fileUIDs.push_back(file->getUID());
|
||||
@@ -109,16 +92,10 @@ public:
|
||||
private:
|
||||
std::vector<uint> m_alreadyIncludedFileUIDs;
|
||||
std::vector<uint> m_excludedIncludeUIDs;
|
||||
FilePathIds &m_includeIds;
|
||||
FilePathIds &m_topIncludeIds;
|
||||
FilePathIds &m_topsSystemIncludeIds;
|
||||
BuildDependency &m_buildDependency;
|
||||
const FilePathCachingInterface &m_filePathCache;
|
||||
const Utils::PathStringVector &m_excludedIncludes;
|
||||
UsedMacros &m_usedMacros;
|
||||
const ClangBackEnd::FilePaths &m_excludedFilePaths;
|
||||
SourcesManager &m_sourcesManager;
|
||||
SourceDependencies &m_sourceDependencies;
|
||||
FilePathIds &m_sourceFiles;
|
||||
FileStatuses &m_fileStatuses;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -102,7 +102,15 @@ public:
|
||||
auto includeFilePathId = filePathId(includeLocation);
|
||||
auto includedFilePathId = filePathId(file);
|
||||
|
||||
m_sourceDependencies.emplace_back(includeFilePathId, includedFilePathId);
|
||||
SourceDependency sourceDependency{includeFilePathId, includedFilePathId};
|
||||
|
||||
auto found = std::lower_bound(m_sourceDependencies.begin(),
|
||||
m_sourceDependencies.end(),
|
||||
sourceDependency,
|
||||
[](auto first, auto second) { return first < second; });
|
||||
|
||||
if (found == m_sourceDependencies.end() || *found != sourceDependency)
|
||||
m_sourceDependencies.emplace(found, sourceDependency);
|
||||
}
|
||||
|
||||
void mergeUsedMacros()
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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 "includecollector.h"
|
||||
|
||||
#include "collectincludestoolaction.h"
|
||||
|
||||
#include <utils/smallstring.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
void IncludeCollector::collect()
|
||||
{
|
||||
clang::tooling::ClangTool tool = m_clangTool.createTool();
|
||||
|
||||
auto action = std::unique_ptr<CollectIncludesToolAction>(
|
||||
new CollectIncludesToolAction(m_includeIds,
|
||||
m_topIncludeIds,
|
||||
m_topsSystemIncludeIds,
|
||||
m_filePathCache,
|
||||
m_excludedIncludes,
|
||||
m_usedMacros,
|
||||
m_sourcesManager,
|
||||
m_sourceDependencies,
|
||||
m_sourceFiles,
|
||||
m_fileStatuses));
|
||||
|
||||
tool.run(action.get());
|
||||
}
|
||||
|
||||
void IncludeCollector::setExcludedIncludes(Utils::PathStringVector &&excludedIncludes)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_excludedIncludes.clear();
|
||||
m_excludedIncludes.reserve(excludedIncludes.size());
|
||||
std::transform(std::make_move_iterator(excludedIncludes.begin()),
|
||||
std::make_move_iterator(excludedIncludes.end()),
|
||||
std::back_inserter(m_excludedIncludes),
|
||||
[] (Utils::PathString &&path) {
|
||||
path.replace("/", "\\");
|
||||
return std::move(path);
|
||||
});
|
||||
|
||||
|
||||
#else
|
||||
m_excludedIncludes = std::move(excludedIncludes);
|
||||
#endif
|
||||
}
|
||||
|
||||
void IncludeCollector::addFiles(const FilePathIds &filePathIds,
|
||||
const Utils::SmallStringVector &arguments)
|
||||
{
|
||||
m_clangTool.addFiles(m_filePathCache.filePaths(filePathIds), arguments);
|
||||
m_sourceFiles.insert(m_sourceFiles.end(), filePathIds.begin(), filePathIds.end());
|
||||
}
|
||||
|
||||
void IncludeCollector::addFile(FilePathId filePathId, const Utils::SmallStringVector &arguments)
|
||||
{
|
||||
addFiles({filePathId}, arguments);
|
||||
}
|
||||
|
||||
void IncludeCollector::addFile(FilePath filePath,
|
||||
const FilePathIds &sourceFileIds,
|
||||
const Utils::SmallStringVector &arguments)
|
||||
{
|
||||
m_clangTool.addFiles({filePath}, arguments);
|
||||
m_sourceFiles.insert(m_sourceFiles.end(), sourceFileIds.begin(), sourceFileIds.end());
|
||||
}
|
||||
|
||||
void IncludeCollector::clear()
|
||||
{
|
||||
m_clangTool = ClangTool();
|
||||
m_usedMacros.clear();
|
||||
m_sourceFiles.clear();
|
||||
m_fileStatuses.clear();
|
||||
m_sourceDependencies.clear();
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "pchcreator.h"
|
||||
|
||||
#include "environment.h"
|
||||
#include "includecollector.h"
|
||||
#include "builddependencycollector.h"
|
||||
#include "pchnotcreatederror.h"
|
||||
|
||||
#include <clangpathwatcherinterface.h>
|
||||
@@ -58,12 +58,12 @@ void append(Target &target, const Source &source)
|
||||
target.push_back(ValueType(std::move(entry)));
|
||||
}
|
||||
|
||||
void appendFilePathId(Utils::PathStringVector &target,
|
||||
void appendFilePathId(ClangBackEnd::FilePaths &target,
|
||||
const ClangBackEnd::FilePathIds &source,
|
||||
const ClangBackEnd::FilePathCachingInterface &filePathCache)
|
||||
{
|
||||
for (FilePathId id : source)
|
||||
target.emplace_back(filePathCache.filePath(id).path());
|
||||
target.emplace_back(filePathCache.filePath(id));
|
||||
}
|
||||
|
||||
Utils::PathStringVector generatedFilePaths(const V2::FileContainers &generaredFiles)
|
||||
@@ -190,23 +190,23 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaders(
|
||||
|
||||
namespace {
|
||||
|
||||
std::size_t sizeOfContent(const Utils::PathStringVector &paths)
|
||||
std::size_t sizeOfContent(const ClangBackEnd::FilePaths &paths)
|
||||
{
|
||||
return std::accumulate(paths.begin(),
|
||||
paths.end(),
|
||||
std::size_t(0),
|
||||
[] (std::size_t size, const Utils::PathString &path) {
|
||||
[] (std::size_t size, const auto &path) {
|
||||
const char includeTemplate[] = "#include \"\"\n";
|
||||
return size + path.size() + sizeof(includeTemplate);
|
||||
});
|
||||
}
|
||||
|
||||
Utils::SmallString concatContent(const Utils::PathStringVector &paths, std::size_t size)
|
||||
Utils::SmallString concatContent(const ClangBackEnd::FilePaths &paths, std::size_t size)
|
||||
{
|
||||
Utils::SmallString content;
|
||||
content.reserve(size);
|
||||
|
||||
for (const Utils::PathString &path : paths) {
|
||||
for (const ClangBackEnd::FilePath &path : paths) {
|
||||
content += "#include \"";
|
||||
content += path;
|
||||
content += "\"\n";
|
||||
@@ -220,15 +220,15 @@ Utils::SmallString concatContent(const Utils::PathStringVector &paths, std::size
|
||||
Utils::SmallString PchCreator::generateProjectPartSourcesContent(
|
||||
const V2::ProjectPartContainer &projectPart) const
|
||||
{
|
||||
Utils::PathStringVector paths = generateProjectPartSourcePaths(projectPart);
|
||||
ClangBackEnd::FilePaths paths = generateProjectPartSourcePaths(projectPart);
|
||||
|
||||
return concatContent(paths, sizeOfContent(paths));
|
||||
}
|
||||
|
||||
Utils::PathStringVector PchCreator::generateProjectPartSourcePaths(
|
||||
ClangBackEnd::FilePaths PchCreator::generateProjectPartSourcePaths(
|
||||
const V2::ProjectPartContainer &projectPart) const
|
||||
{
|
||||
Utils::PathStringVector includeAndSources;
|
||||
ClangBackEnd::FilePaths includeAndSources;
|
||||
includeAndSources.reserve(projectPart.sourcePathIds.size());
|
||||
|
||||
appendFilePathId(includeAndSources, projectPart.sourcePathIds, m_filePathCache);
|
||||
@@ -236,7 +236,7 @@ Utils::PathStringVector PchCreator::generateProjectPartSourcePaths(
|
||||
return includeAndSources;
|
||||
}
|
||||
|
||||
PchCreatorIncludes PchCreator::generateProjectPartPchIncludes(
|
||||
SourceEntries PchCreator::generateProjectPartPchIncludes(
|
||||
const V2::ProjectPartContainer &projectPart) const
|
||||
{
|
||||
Utils::SmallString jointedFileContent = generateProjectPartSourcesContent(projectPart);
|
||||
@@ -245,9 +245,9 @@ PchCreatorIncludes PchCreator::generateProjectPartPchIncludes(
|
||||
Utils::SmallStringVector arguments = generateProjectPartCommandLine(projectPart);
|
||||
FilePath filePath{Utils::PathString(jointedFilePath)};
|
||||
|
||||
IncludeCollector collector(m_filePathCache);
|
||||
BuildDependencyCollector collector(m_filePathCache);
|
||||
|
||||
collector.setExcludedIncludes(generateProjectPartSourcePaths(projectPart));
|
||||
collector.setExcludedFilePaths(generateProjectPartSourcePaths(projectPart));
|
||||
|
||||
collector.addFile(filePath, projectPart.sourcePathIds, arguments);
|
||||
|
||||
@@ -257,7 +257,7 @@ PchCreatorIncludes PchCreator::generateProjectPartPchIncludes(
|
||||
|
||||
jointFile->remove();
|
||||
|
||||
return {collector.takeIncludeIds(), collector.takeTopIncludeIds(), collector.takeTopsSystemIncludeIds()};
|
||||
return collector.includeIds();
|
||||
}
|
||||
|
||||
Utils::SmallString PchCreator::generateProjectPathPchHeaderFilePath(
|
||||
@@ -309,7 +309,7 @@ IdPaths PchCreator::generateProjectPartPch(const V2::ProjectPartContainer &proje
|
||||
{
|
||||
long long lastModified = QDateTime::currentSecsSinceEpoch();
|
||||
auto includes = generateProjectPartPchIncludes(projectPart);
|
||||
auto content = generatePchIncludeFileContent(includes.topIncludeIds);
|
||||
auto content = generatePchIncludeFileContent(topIncludeIds(includes));
|
||||
auto pchIncludeFilePath = generateProjectPathPchHeaderFilePath(projectPart);
|
||||
auto pchFilePath = generateProjectPartPchFilePath(projectPart);
|
||||
generateFileWithContent(pchIncludeFilePath, content);
|
||||
@@ -323,7 +323,7 @@ IdPaths PchCreator::generateProjectPartPch(const V2::ProjectPartContainer &proje
|
||||
m_projectPartPch.lastModified = lastModified;
|
||||
}
|
||||
|
||||
return {projectPart.projectPartId.clone(), std::move(includes.includeIds)};
|
||||
return {projectPart.projectPartId.clone(), allIncludeIds(includes)};
|
||||
}
|
||||
|
||||
void PchCreator::generatePch(const V2::ProjectPartContainer &projectPart)
|
||||
@@ -392,6 +392,32 @@ std::unique_ptr<QFile> PchCreator::generateFileWithContent(
|
||||
return precompiledIncludeFile;
|
||||
}
|
||||
|
||||
FilePathIds PchCreator::topIncludeIds(const SourceEntries &includes)
|
||||
{
|
||||
FilePathIds topIncludes;
|
||||
topIncludes.reserve(includes.size());
|
||||
|
||||
for (SourceEntry include : includes) {
|
||||
if (include.sourceType == SourceType::TopInclude)
|
||||
topIncludes.push_back(include.sourceId);
|
||||
}
|
||||
|
||||
return topIncludes;
|
||||
}
|
||||
|
||||
FilePathIds PchCreator::allIncludeIds(const SourceEntries &includes)
|
||||
{
|
||||
FilePathIds allIncludes;
|
||||
allIncludes.reserve(includes.size());
|
||||
|
||||
std::transform(includes.begin(),
|
||||
includes.end(),
|
||||
std::back_inserter(allIncludes),
|
||||
[](auto &&entry) { return entry.sourceId; });
|
||||
|
||||
return allIncludes;
|
||||
}
|
||||
|
||||
QByteArray PchCreator::projectPartHash(const V2::ProjectPartContainer &projectPart)
|
||||
{
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "pchcreatorinterface.h"
|
||||
|
||||
#include "idpaths.h"
|
||||
#include "sourceentry.h"
|
||||
|
||||
#include <filepathcaching.h>
|
||||
#include <projectpartpch.h>
|
||||
@@ -93,9 +94,9 @@ public:
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
Utils::SmallString generateProjectPartSourcesContent(
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
Utils::PathStringVector generateProjectPartSourcePaths(
|
||||
ClangBackEnd::FilePaths generateProjectPartSourcePaths(
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
PchCreatorIncludes generateProjectPartPchIncludes(
|
||||
SourceEntries generateProjectPartPchIncludes(
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
Utils::SmallString generateProjectPathPchHeaderFilePath(
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
@@ -113,6 +114,9 @@ public:
|
||||
const Utils::SmallString &filePath,
|
||||
const Utils::SmallString &content);
|
||||
|
||||
static FilePathIds topIncludeIds(const SourceEntries &includes);
|
||||
static FilePathIds allIncludeIds(const SourceEntries &includes);
|
||||
|
||||
private:
|
||||
static QByteArray projectPartHash(const V2::ProjectPartContainer &projectPart);
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ namespace ClangBackEnd {
|
||||
|
||||
enum class SourceType : unsigned char
|
||||
{
|
||||
Any,
|
||||
TopInclude,
|
||||
TopSystemInclude
|
||||
TopSystemInclude,
|
||||
UserInclude,
|
||||
SystemInclude
|
||||
};
|
||||
|
||||
class TimeStamp
|
||||
@@ -62,7 +63,6 @@ public:
|
||||
: lastModified(lastModified),
|
||||
sourceId(sourceId),
|
||||
sourceType(static_cast<SourceType>(sourceType))
|
||||
|
||||
{}
|
||||
|
||||
SourceEntry(FilePathId sourceId, SourceType sourceType, TimeStamp lastModified)
|
||||
@@ -85,10 +85,12 @@ public:
|
||||
&& first.lastModified == second.lastModified ;
|
||||
}
|
||||
|
||||
friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); }
|
||||
|
||||
public:
|
||||
TimeStamp lastModified;
|
||||
FilePathId sourceId;
|
||||
SourceType sourceType = SourceType::Any;
|
||||
SourceType sourceType = SourceType::UserInclude;
|
||||
};
|
||||
|
||||
using SourceEntries = std::vector<SourceEntry>;
|
||||
|
||||
@@ -135,6 +135,8 @@ clang::tooling::ClangTool ClangTool::createTool() const
|
||||
tool.mapVirtualFile(toStringRef(unsavedFileContent.filePath),
|
||||
toStringRef(unsavedFileContent.content));
|
||||
|
||||
tool.mapVirtualFile("/dummyFile", "#pragma once");
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,12 @@ public:
|
||||
&& first.lastModified == second.lastModified;
|
||||
}
|
||||
|
||||
friend
|
||||
bool operator<(const FileStatus &first, const FileStatus &second)
|
||||
{
|
||||
return first.filePathId < second.filePathId;
|
||||
}
|
||||
|
||||
public:
|
||||
FilePathId filePathId;
|
||||
off_t size;
|
||||
|
||||
@@ -34,23 +34,32 @@ namespace ClangBackEnd {
|
||||
class SourceDependency
|
||||
{
|
||||
public:
|
||||
SourceDependency(FilePathId filePathId,
|
||||
FilePathId dependencyFilePathId)
|
||||
: filePathId(filePathId),
|
||||
dependencyFilePathId(dependencyFilePathId)
|
||||
SourceDependency(FilePathId filePathId, FilePathId dependencyFilePathId)
|
||||
: filePathId(filePathId)
|
||||
, dependencyFilePathId(dependencyFilePathId)
|
||||
{}
|
||||
|
||||
friend
|
||||
bool operator==(SourceDependency first, SourceDependency second)
|
||||
friend bool operator==(SourceDependency first, SourceDependency second)
|
||||
{
|
||||
return first.filePathId == second.filePathId
|
||||
&& first.dependencyFilePathId == second.dependencyFilePathId;
|
||||
}
|
||||
|
||||
friend bool operator!=(SourceDependency first, SourceDependency second)
|
||||
{
|
||||
return !(first == second);
|
||||
}
|
||||
|
||||
friend bool operator<(SourceDependency first, SourceDependency second)
|
||||
{
|
||||
return std::tie(first.filePathId, first.dependencyFilePathId)
|
||||
< std::tie(second.filePathId, second.dependencyFilePathId);
|
||||
}
|
||||
|
||||
public:
|
||||
FilePathId filePathId;
|
||||
FilePathId dependencyFilePathId;
|
||||
};
|
||||
|
||||
using SourceDependencies = std::vector<SourceDependency>;
|
||||
}
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
return SymbolIndex(reinterpret_cast<std::uintptr_t>(pointer));
|
||||
}
|
||||
|
||||
void setSourceManager(const clang::SourceManager *sourceManager)
|
||||
void setSourceManager(clang::SourceManager *sourceManager)
|
||||
{
|
||||
m_sourceManager = sourceManager;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "mockbuilddependenciesstorage.h"
|
||||
#include "mockmodifiedtimechecker.h"
|
||||
#include "mockbuilddependenciesgenerator.h"
|
||||
#include "mockbuilddependencygenerator.h"
|
||||
|
||||
#include <builddependenciesprovider.h>
|
||||
|
||||
@@ -56,7 +56,7 @@ class BuildDependenciesProvider : public testing::Test
|
||||
protected:
|
||||
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
|
||||
NiceMock<MockModifiedTimeChecker> mockModifiedTimeChecker;
|
||||
NiceMock<MockBuildDependenciesGenerator> mockBuildDependenciesGenerator;
|
||||
NiceMock<MockBuildDependencyGenerator> mockBuildDependenciesGenerator;
|
||||
ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage, mockModifiedTimeChecker, mockBuildDependenciesGenerator};
|
||||
ClangBackEnd::V2::ProjectPartContainer projectPart1{"ProjectPart1",
|
||||
{"--yi"},
|
||||
@@ -70,13 +70,13 @@ protected:
|
||||
{"/er"},
|
||||
{1},
|
||||
{2, 3, 4}};
|
||||
SourceEntries firstSources{{1, SourceType::Any, 1}, {2, SourceType::Any, 1}, {10, SourceType::Any, 1}};
|
||||
SourceEntries secondSources{{1, SourceType::Any, 1}, {3, SourceType::Any, 1}, {8, SourceType::Any, 1}};
|
||||
SourceEntries thirdSources{{4, SourceType::Any, 1}, {8, SourceType::Any, 1}, {10, SourceType::Any, 1}};
|
||||
SourceEntries firstSources{{1, SourceType::UserInclude, 1}, {2, SourceType::UserInclude, 1}, {10, SourceType::UserInclude, 1}};
|
||||
SourceEntries secondSources{{1, SourceType::UserInclude, 1}, {3, SourceType::UserInclude, 1}, {8, SourceType::UserInclude, 1}};
|
||||
SourceEntries thirdSources{{4, SourceType::UserInclude, 1}, {8, SourceType::UserInclude, 1}, {10, SourceType::UserInclude, 1}};
|
||||
UsedMacros firstUsedMacros{{"YI", 1}};
|
||||
UsedMacros secondUsedMacros{{"LIANG", 2}, {"ER", 2}};
|
||||
UsedMacros thirdUsedMacros{{"SAN", 10}};
|
||||
BuildDependency buildDependency{secondSources, {}, {}, {}};
|
||||
BuildDependency buildDependency{secondSources, {}};
|
||||
};
|
||||
|
||||
TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromStorageIfTimeStampsAreUpToDate)
|
||||
|
||||
@@ -171,9 +171,9 @@ TEST_F(BuildDependenciesStorage, UpdateSources)
|
||||
SourceEntries entries{{1, SourceType::TopInclude, 10}, {2, SourceType::TopSystemInclude, 20}};
|
||||
|
||||
EXPECT_CALL(updateBuildDependencyTimeStampStatement, write(TypedEq<long long>(10), TypedEq<int>(1)));
|
||||
EXPECT_CALL(updateSourceTypeStatement, write(TypedEq<uchar>(1), TypedEq<int>(1)));
|
||||
EXPECT_CALL(updateSourceTypeStatement, write(TypedEq<uchar>(0), TypedEq<int>(1)));
|
||||
EXPECT_CALL(updateBuildDependencyTimeStampStatement, write(TypedEq<long long>(20), TypedEq<int>(2)));
|
||||
EXPECT_CALL(updateSourceTypeStatement, write(TypedEq<uchar>(2), TypedEq<int>(2)));
|
||||
EXPECT_CALL(updateSourceTypeStatement, write(TypedEq<uchar>(1), TypedEq<int>(2)));
|
||||
|
||||
storage.updateSources(entries);
|
||||
}
|
||||
|
||||
635
tests/unit/unittest/builddependencycollector-test.cpp
Normal file
635
tests/unit/unittest/builddependencycollector-test.cpp
Normal file
@@ -0,0 +1,635 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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 "googletest.h"
|
||||
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <filepathcaching.h>
|
||||
#include <builddependencycollector.h>
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
|
||||
using testing::AllOf;
|
||||
using testing::Contains;
|
||||
using testing::Not;
|
||||
using testing::ElementsAre;
|
||||
using testing::UnorderedElementsAre;
|
||||
|
||||
using ClangBackEnd::BuildDependency;
|
||||
using ClangBackEnd::FilePathId;
|
||||
using ClangBackEnd::FilePathIds;
|
||||
using ClangBackEnd::FilePathView;
|
||||
using ClangBackEnd::SourceDependency;
|
||||
using ClangBackEnd::SourceType;
|
||||
using ClangBackEnd::UsedMacro;
|
||||
|
||||
namespace {
|
||||
|
||||
MATCHER_P2(HasInclude, sourceId, sourceType,
|
||||
std::string(negation ? "hasn't " : "has ")
|
||||
+ PrintToString(ClangBackEnd::SourceEntry(sourceId, sourceType, -1)))
|
||||
{
|
||||
const ClangBackEnd::SourceEntry &entry = arg;
|
||||
|
||||
return entry.sourceId == sourceId && entry.sourceType == sourceType;
|
||||
}
|
||||
|
||||
class BuildDependencyCollector : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
BuildDependencyCollector()
|
||||
{
|
||||
setFilePathCache(&filePathCache);
|
||||
|
||||
collector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
collector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
collector.addUnsavedFiles({{{TESTDATA_DIR, "BuildDependencyCollector/project/generated_file.h"}, "#pragma once", {}}});
|
||||
|
||||
collector.setExcludedFilePaths(Utils::clone(excludePaths));
|
||||
emptyCollector.setExcludedFilePaths(Utils::clone(excludePaths));
|
||||
}
|
||||
|
||||
~BuildDependencyCollector()
|
||||
{
|
||||
setFilePathCache(nullptr);
|
||||
}
|
||||
|
||||
FilePathId id(const Utils::SmallStringView &path) const
|
||||
{
|
||||
return filePathCache.filePathId(FilePathView{path});
|
||||
}
|
||||
|
||||
static off_t fileSize(Utils::SmallStringView filePath)
|
||||
{
|
||||
return QFileInfo(QString(filePath)).size();
|
||||
}
|
||||
|
||||
static std::time_t lastModified(Utils::SmallStringView filePath)
|
||||
{
|
||||
return QFileInfo(QString(filePath)).lastModified().toTime_t();
|
||||
}
|
||||
|
||||
ClangBackEnd::FileStatus fileStatus(Utils::SmallStringView filePath) const
|
||||
{
|
||||
return {id(filePath), fileSize(filePath), lastModified(filePath), false};
|
||||
}
|
||||
|
||||
static
|
||||
FilePathIds filteredIncludes(const ClangBackEnd::SourceEntries &includes,
|
||||
ClangBackEnd::SourceType includeType)
|
||||
{
|
||||
FilePathIds filteredIncludes;
|
||||
|
||||
for (const ClangBackEnd::SourceEntry &include : includes) {
|
||||
if (include.sourceType == includeType)
|
||||
filteredIncludes.push_back(include.sourceId);
|
||||
}
|
||||
|
||||
return filteredIncludes;
|
||||
}
|
||||
|
||||
static
|
||||
FilePathIds topIncludes(const ClangBackEnd::SourceEntries &includes)
|
||||
{
|
||||
return filteredIncludes(includes, ClangBackEnd::SourceType::TopInclude);
|
||||
}
|
||||
|
||||
static
|
||||
FilePathIds systemTopIncludes(const ClangBackEnd::SourceEntries &includes)
|
||||
{
|
||||
return filteredIncludes(includes, ClangBackEnd::SourceType::TopSystemInclude);
|
||||
}
|
||||
|
||||
static
|
||||
FilePathIds userIncludes(const ClangBackEnd::SourceEntries &includes)
|
||||
{
|
||||
return filteredIncludes(includes, ClangBackEnd::SourceType::UserInclude);
|
||||
}
|
||||
|
||||
static
|
||||
FilePathIds allIncludes(const ClangBackEnd::SourceEntries &includes)
|
||||
{
|
||||
FilePathIds filteredIncludes;
|
||||
|
||||
for (const ClangBackEnd::SourceEntry &include : includes)
|
||||
filteredIncludes.push_back(include.sourceId);
|
||||
|
||||
return filteredIncludes;
|
||||
}
|
||||
|
||||
protected:
|
||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
ClangBackEnd::FilePathCaching filePathCache{database};
|
||||
ClangBackEnd::BuildDependencyCollector collector{filePathCache};
|
||||
ClangBackEnd::BuildDependencyCollector emptyCollector{filePathCache};
|
||||
ClangBackEnd::FilePaths excludePaths = {TESTDATA_DIR "/builddependencycollector/project/main.cpp",
|
||||
TESTDATA_DIR "/builddependencycollector/project/main2.cpp",
|
||||
TESTDATA_DIR "/builddependencycollector/project/header1.h",
|
||||
TESTDATA_DIR "/builddependencycollector/project/header2.h",
|
||||
TESTDATA_DIR "/builddependencycollector/project/generated_file.h"};
|
||||
};
|
||||
|
||||
TEST_F(BuildDependencyCollector, IncludesExternalHeader)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(allIncludes(collector.includeIds()),
|
||||
AllOf(Contains(id(TESTDATA_DIR "/builddependencycollector/external/external1.h")),
|
||||
Contains(id(TESTDATA_DIR "/builddependencycollector/external/external2.h")),
|
||||
Contains(id(TESTDATA_DIR "/builddependencycollector/external/indirect_external.h")),
|
||||
Contains(id(TESTDATA_DIR "/builddependencycollector/external/indirect_external2.h"))));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, InternalHeaderAreUserIncludes)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(userIncludes(collector.includeIds()), Contains(id(TESTDATA_DIR "/builddependencycollector/project/header1.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, NoDuplicate)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(allIncludes(collector.includeIds()),
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external3.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external2.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, IncludesAreSorted)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(allIncludes(collector.includeIds()),
|
||||
ElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external3.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, If)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/if.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(allIncludes(emptyCollector.includeIds()),
|
||||
ElementsAre(id(TESTDATA_DIR "/builddependencycollector/project/true.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, LocalPath)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(allIncludes(emptyCollector.includeIds()),
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external3.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external2.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, IgnoreMissingFile)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/missingfile.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(allIncludes(emptyCollector.includeIds()),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external2.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, IncludesOnlyTopExternalHeader)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(topIncludes(collector.includeIds()),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external3.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, TopIncludeInIfMacro)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/if.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
emptyCollector.setExcludedFilePaths({TESTDATA_DIR "/builddependencycollector/project/if.cpp"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(topIncludes(emptyCollector.includeIds()),
|
||||
ElementsAre(id(TESTDATA_DIR "/builddependencycollector/project/true.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, TopIncludeWithLocalPath)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(topIncludes(emptyCollector.includeIds()),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external3.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, TopIncludesIgnoreMissingFile)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/missingfile.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
emptyCollector.setExcludedFilePaths({TESTDATA_DIR "/builddependencycollector/project/missingfile.cpp"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(topIncludes(emptyCollector.includeIds()),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/builddependencycollector/external/external1.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, SourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header1.h"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header2.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, MainFileInSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
ElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, ResetMainFileInSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
ElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, DontDuplicateSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header1.h"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header2.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, ClearSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, ClearFileStatus)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.fileStatuses(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, ClearUsedMacros)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_defines.h"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, ClearSourceDependencies)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main2.cpp"), {"cc", "-I" TESTDATA_DIR});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceDependencies(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, DontCollectSourceFilesAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, DontCollectFileStatusAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.fileStatuses(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, DontCollectUsedMacrosAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(), IsEmpty());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(BuildDependencyCollector, DontCollectSourceDependenciesAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceDependencies(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, CollectUsedMacrosWithExternalDefine)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
||||
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"__clang__", fileId}),
|
||||
Eq(UsedMacro{"CLASS_EXPORT", fileId}),
|
||||
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
|
||||
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, CollectUsedMacrosWithoutExternalDefine)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
||||
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"__clang__", fileId}),
|
||||
Eq(UsedMacro{"CLASS_EXPORT", fileId}),
|
||||
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
|
||||
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, DontCollectHeaderGuards)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
Not(Contains(Eq(UsedMacro{"SYMBOLSCOLLECTOR_DEFINES_H", fileId}))));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, DISABLED_DontCollectDynamicLibraryExports)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
Not(Contains(Eq(UsedMacro{"CLASS_EXPORT", fileId}))));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, CollectFileStatuses)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.fileStatuses(),
|
||||
ElementsAre(
|
||||
fileStatus(TESTDATA_DIR "/symbolscollector_main.cpp"),
|
||||
fileStatus(TESTDATA_DIR "/symbolscollector_header1.h"),
|
||||
fileStatus(TESTDATA_DIR "/symbolscollector_header2.h")));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, CollectSourceDependencies)
|
||||
{
|
||||
auto mainFileId = id(TESTDATA_DIR "/symbolscollector_main2.cpp");
|
||||
auto header1FileId = id(TESTDATA_DIR "/symbolscollector_header1.h");
|
||||
auto header2FileId = id(TESTDATA_DIR "/symbolscollector_header2.h");
|
||||
auto header3FileId = id(TESTDATA_DIR "/symbolscollector_header3.h");
|
||||
emptyCollector.addFile(mainFileId, {"cc", "-I" TESTDATA_DIR});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceDependencies(),
|
||||
UnorderedElementsAre(SourceDependency(mainFileId, header1FileId),
|
||||
SourceDependency(mainFileId, header3FileId),
|
||||
SourceDependency(header3FileId, header2FileId),
|
||||
SourceDependency(header1FileId, header2FileId)));
|
||||
}
|
||||
|
||||
TEST_F(BuildDependencyCollector, Create)
|
||||
{
|
||||
ClangBackEnd::BuildDependencyCollector collector{filePathCache};
|
||||
ClangBackEnd::V2::ProjectPartContainer
|
||||
projectPart{"project1",
|
||||
{"cc",
|
||||
"-I",
|
||||
TESTDATA_DIR "/builddependencycollector/external",
|
||||
"-I",
|
||||
TESTDATA_DIR "/builddependencycollector/project",
|
||||
"-isystem",
|
||||
TESTDATA_DIR "/builddependencycollector/system"},
|
||||
{},
|
||||
{},
|
||||
{id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/macros.h"),},
|
||||
{id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp")}};
|
||||
|
||||
auto buildDependency = collector.create(projectPart);
|
||||
|
||||
ASSERT_THAT(
|
||||
buildDependency,
|
||||
AllOf(
|
||||
Field(&BuildDependency::fileStatuses,
|
||||
UnorderedElementsAre(
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/external/external3.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
fileStatus(TESTDATA_DIR
|
||||
"/builddependencycollector/external/indirect_external.h"),
|
||||
fileStatus(TESTDATA_DIR
|
||||
"/builddependencycollector/external/indirect_external2.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/system/indirect_system.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/system/indirect_system2.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
|
||||
fileStatus(TESTDATA_DIR "/builddependencycollector/project/macros.h"))),
|
||||
Field(&BuildDependency::includes,
|
||||
UnorderedElementsAre(
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
SourceType::UserInclude),
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
SourceType::UserInclude),
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/external/external3.h"),
|
||||
SourceType::TopInclude),
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
SourceType::TopInclude),
|
||||
HasInclude(id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/indirect_external.h"),
|
||||
SourceType::UserInclude),
|
||||
HasInclude(id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/indirect_external2.h"),
|
||||
SourceType::UserInclude),
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
SourceType::TopInclude),
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||
SourceType::TopSystemInclude),
|
||||
HasInclude(id(TESTDATA_DIR
|
||||
"/builddependencycollector/system/indirect_system.h"),
|
||||
SourceType::SystemInclude),
|
||||
HasInclude(id(TESTDATA_DIR
|
||||
"/builddependencycollector/system/indirect_system2.h"),
|
||||
SourceType::SystemInclude),
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
|
||||
SourceType::UserInclude),
|
||||
HasInclude(id(TESTDATA_DIR "/builddependencycollector/project/macros.h"),
|
||||
SourceType::UserInclude))),
|
||||
Field(&BuildDependency::usedMacros,
|
||||
UnorderedElementsAre(
|
||||
UsedMacro{"DEFINE",
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/macros.h")},
|
||||
UsedMacro{"IFDEF",
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/macros.h")},
|
||||
UsedMacro{"DEFINED",
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/macros.h")})),
|
||||
Field(&BuildDependency::sourceFiles,
|
||||
UnorderedElementsAre(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external3.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/indirect_external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/system/indirect_system.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/system/indirect_system2.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/missingfile.h"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/macros.h"))),
|
||||
Field(
|
||||
&BuildDependency::sourceDependencies,
|
||||
UnorderedElementsAre(
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header1.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/project/missingfile.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/external1.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/external2.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/system/system1.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/main4.cpp"),
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/macros.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/external3.h")),
|
||||
SourceDependency(id(TESTDATA_DIR
|
||||
"/builddependencycollector/project/missingfile.h"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/external1.h")),
|
||||
SourceDependency(id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/external1.h"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/indirect_external.h")),
|
||||
SourceDependency(id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/indirect_external2.h")),
|
||||
SourceDependency(id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/system/indirect_system.h")),
|
||||
SourceDependency(id(TESTDATA_DIR
|
||||
"/builddependencycollector/system/indirect_system.h"),
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/system/indirect_system2.h"))))));
|
||||
}
|
||||
} // namespace
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#define DEFINE
|
||||
|
||||
#ifdef IFDEF
|
||||
#endif
|
||||
|
||||
#if defined(DEFINED)
|
||||
#endif
|
||||
DEFINE
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <header1.h>
|
||||
#include <header2.h>
|
||||
#include "missingfile.h"
|
||||
#include "missingfile.h"
|
||||
#include <external1.h>
|
||||
#include <../external/external1.h>
|
||||
#include <../external/external2.h>
|
||||
#include <system1.h>
|
||||
#include "macros.h"
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "missing_file.moc"
|
||||
#include "foo/missing_file.moc"
|
||||
#include <missing_file2.moc>
|
||||
#include <foo2/missing_file2.moc>
|
||||
|
||||
#include "external1.h"
|
||||
@@ -66,6 +66,10 @@
|
||||
#include <coreplugin/find/searchresultitem.h>
|
||||
#include <coreplugin/locator/ilocatorfilter.h>
|
||||
|
||||
namespace {
|
||||
ClangBackEnd::FilePathCaching *filePathCache = nullptr;
|
||||
}
|
||||
|
||||
void PrintTo(const Utf8String &text, ::std::ostream *os)
|
||||
{
|
||||
*os << text;
|
||||
@@ -171,7 +175,10 @@ namespace ClangBackEnd {
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const FilePathId &id)
|
||||
{
|
||||
return out << "(" << id.filePathId << ")";
|
||||
if (filePathCache)
|
||||
return out << "(" << id.filePathId << ", " << filePathCache->filePath(id) << ")";
|
||||
|
||||
return out << id.filePathId;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const FilePathView &filePathView)
|
||||
@@ -1014,10 +1021,13 @@ std::ostream &operator<<(std::ostream &out, const PchTask &task)
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency)
|
||||
{
|
||||
return out << "("
|
||||
<< dependency.includes << ", "
|
||||
<< dependency.topsSystemIncludeIds << ", "
|
||||
<< dependency.topIncludeIds << ")";
|
||||
return out << "(\n"
|
||||
<< "includes: " << dependency.includes << ",\n"
|
||||
<< "usedMacros: " << dependency.usedMacros << ",\n"
|
||||
<< "fileStatuses: " << dependency.fileStatuses << ",\n"
|
||||
<< "sourceFiles: " << dependency.sourceFiles << ",\n"
|
||||
<< "sourceDependencies: " << dependency.sourceDependencies << ",\n"
|
||||
<< ")";
|
||||
}
|
||||
|
||||
const char *sourceTypeString(SourceType sourceType)
|
||||
@@ -1025,9 +1035,14 @@ const char *sourceTypeString(SourceType sourceType)
|
||||
using ClangBackEnd::SymbolTag;
|
||||
|
||||
switch (sourceType) {
|
||||
case SourceType::Any: return "Any";
|
||||
case SourceType::TopInclude: return "TopInclude";
|
||||
case SourceType::TopSystemInclude: return "TopSystemInclude";
|
||||
case SourceType::TopInclude:
|
||||
return "TopInclude";
|
||||
case SourceType::TopSystemInclude:
|
||||
return "TopSystemInclude";
|
||||
case SourceType::SystemInclude:
|
||||
return "SystemInclude";
|
||||
case SourceType::UserInclude:
|
||||
return "UserInclude";
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -1131,3 +1146,8 @@ std::ostream &operator<<(std::ostream &out, const Usage &usage)
|
||||
return out << "(" << usage.path << ", " << usage.line << ", " << usage.column <<")";
|
||||
}
|
||||
} // namespace CppTools
|
||||
|
||||
void setFilePathCache(ClangBackEnd::FilePathCaching *cache)
|
||||
{
|
||||
filePathCache = cache;
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ class PchCreatorIncludes;
|
||||
class PchTask;
|
||||
class BuildDependency;
|
||||
class SourceEntry;
|
||||
class FilePathCaching;
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
|
||||
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
|
||||
@@ -289,3 +290,5 @@ class Usage;
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Usage &usage);
|
||||
} // namespace CppTools
|
||||
|
||||
void setFilePathCache(ClangBackEnd::FilePathCaching *filePathCache);
|
||||
|
||||
@@ -1,422 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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 "googletest.h"
|
||||
|
||||
#include <refactoringdatabaseinitializer.h>
|
||||
#include <filepathcaching.h>
|
||||
#include <includecollector.h>
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
|
||||
using testing::AllOf;
|
||||
using testing::Contains;
|
||||
using testing::Not;
|
||||
using testing::ElementsAre;
|
||||
using testing::UnorderedElementsAre;
|
||||
|
||||
using ClangBackEnd::FilePathId;
|
||||
using ClangBackEnd::FilePathIds;
|
||||
using ClangBackEnd::FilePathView;
|
||||
using ClangBackEnd::SourceDependency;
|
||||
using ClangBackEnd::UsedMacro;
|
||||
|
||||
namespace {
|
||||
|
||||
class IncludeCollector : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp()
|
||||
{
|
||||
collector.addFile(id(TESTDATA_DIR "/includecollector/project/main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
collector.addFile(id(TESTDATA_DIR "/includecollector/project/main2.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
collector.addUnsavedFiles({{{TESTDATA_DIR, "includecollector/project/generated_file.h"}, "#pragma once", {}}});
|
||||
|
||||
collector.setExcludedIncludes(excludePaths.clone());
|
||||
emptyCollector.setExcludedIncludes(excludePaths.clone());
|
||||
}
|
||||
|
||||
FilePathId id(const Utils::SmallStringView &path) const
|
||||
{
|
||||
return filePathCache.filePathId(FilePathView{path});
|
||||
}
|
||||
|
||||
static off_t fileSize(Utils::SmallStringView filePath)
|
||||
{
|
||||
return QFileInfo(QString(filePath)).size();
|
||||
}
|
||||
|
||||
static std::time_t lastModified(Utils::SmallStringView filePath)
|
||||
{
|
||||
return QFileInfo(QString(filePath)).lastModified().toTime_t();
|
||||
}
|
||||
|
||||
ClangBackEnd::FileStatus fileStatus(Utils::SmallStringView filePath) const
|
||||
{
|
||||
return {id(filePath), fileSize(filePath), lastModified(filePath), false};
|
||||
}
|
||||
protected:
|
||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
ClangBackEnd::FilePathCaching filePathCache{database};
|
||||
ClangBackEnd::IncludeCollector collector{filePathCache};
|
||||
ClangBackEnd::IncludeCollector emptyCollector{filePathCache};
|
||||
Utils::PathStringVector excludePaths = {TESTDATA_DIR "/includecollector/project/main.cpp",
|
||||
TESTDATA_DIR "/includecollector/project/main2.cpp",
|
||||
TESTDATA_DIR "/includecollector/project/header1.h",
|
||||
TESTDATA_DIR "/includecollector/project/header2.h",
|
||||
TESTDATA_DIR "/includecollector/project/generated_file.h"};
|
||||
};
|
||||
|
||||
TEST_F(IncludeCollector, IncludesExternalHeader)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(collector.takeIncludeIds(),
|
||||
AllOf(Contains(id(TESTDATA_DIR "/includecollector/external/external1.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/external/external2.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/external/indirect_external.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/external/indirect_external2.h"))));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, DoesNotIncludesInternalHeader)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(collector.takeIncludeIds(), Not(Contains(id(TESTDATA_DIR "/includecollector/project/header1.h"))));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, NoDuplicate)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(collector.takeIncludeIds(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/includecollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external3.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/indirect_external2.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, IncludesAreSorted)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(collector.takeIncludeIds(),
|
||||
SizeIs(5));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, If)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/includecollector/project/if.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.takeIncludeIds(),
|
||||
ElementsAre(id(TESTDATA_DIR "/includecollector/project/true.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, LocalPath)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/includecollector/project/main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.takeIncludeIds(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/includecollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external3.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/indirect_external2.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, IgnoreMissingFile)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/includecollector/project/missingfile.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.takeIncludeIds(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/includecollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/indirect_external.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/indirect_external2.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, IncludesOnlyTopExternalHeader)
|
||||
{
|
||||
collector.collect();
|
||||
|
||||
ASSERT_THAT(collector.takeTopIncludeIds(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/includecollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external3.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, TopIncludeInIfMacro)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/includecollector/project/if.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
emptyCollector.setExcludedIncludes({TESTDATA_DIR "/includecollector/project/if.cpp"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.takeTopIncludeIds(),
|
||||
ElementsAre(id(TESTDATA_DIR "/includecollector/project/true.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, TopIncludeWithLocalPath)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/includecollector/project/main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.takeTopIncludeIds(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/includecollector/external/external1.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external2.h"),
|
||||
id(TESTDATA_DIR "/includecollector/external/external3.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, TopIncludesIgnoreMissingFile)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/includecollector/project/missingfile.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
emptyCollector.setExcludedIncludes({TESTDATA_DIR "/includecollector/project/missingfile.cpp"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.takeTopIncludeIds(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/includecollector/external/external1.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, SourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header1.h"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header2.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, MainFileInSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
ElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, ResetMainFileInSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
ElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, DontDuplicateSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(),
|
||||
UnorderedElementsAre(id(TESTDATA_DIR "/symbolscollector_main.cpp"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header1.h"),
|
||||
id(TESTDATA_DIR "/symbolscollector_header2.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, ClearSourceFiles)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, ClearFileStatus)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.fileStatuses(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, ClearUsedMacros)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_defines.h"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, ClearSourceDependencies)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main2.cpp"), {"cc", "-I" TESTDATA_DIR});
|
||||
emptyCollector.collect();
|
||||
|
||||
emptyCollector.clear();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceDependencies(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, DontCollectSourceFilesAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceFiles(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, DontCollectFileStatusAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.fileStatuses(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, DontCollectUsedMacrosAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(), IsEmpty());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(IncludeCollector, DontCollectSourceDependenciesAfterFilesAreCleared)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.clear();
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceDependencies(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, CollectUsedMacrosWithExternalDefine)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-DCOMPILER_ARGUMENT"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
||||
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"__clang__", fileId}),
|
||||
Eq(UsedMacro{"CLASS_EXPORT", fileId}),
|
||||
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
|
||||
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, CollectUsedMacrosWithoutExternalDefine)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
||||
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"__clang__", fileId}),
|
||||
Eq(UsedMacro{"CLASS_EXPORT", fileId}),
|
||||
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
||||
Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
|
||||
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, DontCollectHeaderGuards)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
Not(Contains(Eq(UsedMacro{"SYMBOLSCOLLECTOR_DEFINES_H", fileId}))));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, DISABLED_DontCollectDynamicLibraryExports)
|
||||
{
|
||||
auto fileId = id(TESTDATA_DIR "/symbolscollector_defines.h");
|
||||
emptyCollector.addFile(fileId, {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.usedMacros(),
|
||||
Not(Contains(Eq(UsedMacro{"CLASS_EXPORT", fileId}))));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, CollectFileStatuses)
|
||||
{
|
||||
emptyCollector.addFile(id(TESTDATA_DIR "/symbolscollector_main.cpp"), {"cc", "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system"});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.fileStatuses(),
|
||||
ElementsAre(
|
||||
fileStatus(TESTDATA_DIR "/symbolscollector_main.cpp"),
|
||||
fileStatus(TESTDATA_DIR "/symbolscollector_header1.h"),
|
||||
fileStatus(TESTDATA_DIR "/symbolscollector_header2.h")));
|
||||
}
|
||||
|
||||
TEST_F(IncludeCollector, CollectSourceDependencies)
|
||||
{
|
||||
auto mainFileId = id(TESTDATA_DIR "/symbolscollector_main2.cpp");
|
||||
auto header1FileId = id(TESTDATA_DIR "/symbolscollector_header1.h");
|
||||
auto header2FileId = id(TESTDATA_DIR "/symbolscollector_header2.h");
|
||||
auto header3FileId = id(TESTDATA_DIR "/symbolscollector_header3.h");
|
||||
emptyCollector.addFile(mainFileId, {"cc", "-I" TESTDATA_DIR});
|
||||
|
||||
emptyCollector.collect();
|
||||
|
||||
ASSERT_THAT(emptyCollector.sourceDependencies(),
|
||||
UnorderedElementsAre(SourceDependency(mainFileId, header1FileId),
|
||||
SourceDependency(mainFileId, header3FileId),
|
||||
SourceDependency(header3FileId, header2FileId),
|
||||
SourceDependency(header1FileId, header2FileId)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,9 +27,9 @@
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include <builddependenciesgeneratorinterface.h>
|
||||
#include <builddependencygeneratorinterface.h>
|
||||
|
||||
class MockBuildDependenciesGenerator : public ClangBackEnd::BuildDependenciesGeneratorInterface
|
||||
class MockBuildDependencyGenerator : public ClangBackEnd::BuildDependencyGeneratorInterface
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD1(create,
|
||||
@@ -43,21 +43,33 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using ClangBackEnd::FilePath;
|
||||
using ClangBackEnd::FilePathId;
|
||||
using ClangBackEnd::FilePathIds;
|
||||
using ClangBackEnd::FilePathView;
|
||||
using ClangBackEnd::GeneratedFiles;
|
||||
using ClangBackEnd::IdPaths;
|
||||
using ClangBackEnd::ProjectPartPch;
|
||||
using ClangBackEnd::V2::ProjectPartContainer;
|
||||
using ClangBackEnd::SourceEntries;
|
||||
using ClangBackEnd::SourceEntry;
|
||||
using ClangBackEnd::SourceType;
|
||||
using ClangBackEnd::V2::FileContainer;
|
||||
using ClangBackEnd::FilePath;
|
||||
using ClangBackEnd::FilePathIds;
|
||||
using ClangBackEnd::FilePathView;
|
||||
using ClangBackEnd::V2::ProjectPartContainer;
|
||||
|
||||
using Utils::PathString;
|
||||
using Utils::SmallString;
|
||||
|
||||
using UnitTests::EndsWith;
|
||||
|
||||
MATCHER_P2(HasIdAndType, sourceId, sourceType,
|
||||
std::string(negation ? "hasn't" : "has") +
|
||||
PrintToString(ClangBackEnd::SourceEntry(sourceId, sourceType,
|
||||
-1)))
|
||||
{
|
||||
const ClangBackEnd::SourceEntry &entry = arg;
|
||||
return entry.sourceId == sourceId && entry.sourceType == sourceType;
|
||||
}
|
||||
|
||||
class PchCreator: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
@@ -74,27 +86,27 @@ protected:
|
||||
protected:
|
||||
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||
FilePath main1Path = TESTDATA_DIR "/includecollector/project/main3.cpp";
|
||||
FilePath main2Path = TESTDATA_DIR "/includecollector/project/main2.cpp";
|
||||
FilePath header1Path = TESTDATA_DIR "/includecollector/project/header1.h";
|
||||
FilePath header2Path = TESTDATA_DIR "/includecollector/project/header2.h";
|
||||
Utils::SmallStringView generatedFileName = "includecollector/project/generated_file.h";
|
||||
FilePath generatedFilePath = TESTDATA_DIR "/includecollector/project/generated_file.h";
|
||||
FilePath main1Path = TESTDATA_DIR "/builddependencycollector/project/main3.cpp";
|
||||
FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp";
|
||||
FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h";
|
||||
FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h";
|
||||
Utils::SmallStringView generatedFileName = "builddependencycollector/project/generated_file.h";
|
||||
FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h";
|
||||
TestEnvironment environment;
|
||||
FileContainer generatedFile{{TESTDATA_DIR, generatedFileName}, "#pragma once", {}};
|
||||
NiceMock<MockPchManagerClient> mockPchManagerClient;
|
||||
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
|
||||
ClangBackEnd::PchCreator creator{environment, database, mockPchManagerClient, mockClangPathWatcher};
|
||||
ProjectPartContainer projectPart1{"project1",
|
||||
{"-I", TESTDATA_DIR, "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system", "-Wno-pragma-once-outside-header"},
|
||||
{"-I", TESTDATA_DIR, "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system", "-Wno-pragma-once-outside-header"},
|
||||
{{"DEFINE", "1"}},
|
||||
{TESTDATA_DIR "/includecollector/external", TESTDATA_DIR "/includecollector/project"},
|
||||
{TESTDATA_DIR "/builddependencycollector/external", TESTDATA_DIR "/builddependencycollector/project"},
|
||||
{id(header1Path)},
|
||||
{id(main1Path)}};
|
||||
ProjectPartContainer projectPart2{"project2",
|
||||
{"-I", TESTDATA_DIR, "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-x", "c++-header", "-Wno-pragma-once-outside-header"},
|
||||
{"-I", TESTDATA_DIR, "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-x", "c++-header", "-Wno-pragma-once-outside-header"},
|
||||
{{"DEFINE", "1"}},
|
||||
{TESTDATA_DIR "/includecollector/external", TESTDATA_DIR "/includecollector/project"},
|
||||
{TESTDATA_DIR "/builddependencycollector/external", TESTDATA_DIR "/builddependencycollector/project"},
|
||||
{id(header2Path)},
|
||||
{id(main2Path)}};
|
||||
};
|
||||
@@ -112,7 +124,7 @@ TEST_F(PchCreator, CreateProjectPartCommandLine)
|
||||
{
|
||||
auto commandLine = creator.generateProjectPartCommandLine(projectPart1);
|
||||
|
||||
ASSERT_THAT(commandLine, ElementsAre(environment.clangCompilerPath(), "-I", TESTDATA_DIR, "-I", TESTDATA_DIR "/includecollector/external", "-I", TESTDATA_DIR "/includecollector/project", "-isystem", TESTDATA_DIR "/includecollector/system", "-Wno-pragma-once-outside-header"));
|
||||
ASSERT_THAT(commandLine, ElementsAre(environment.clangCompilerPath(), "-I", TESTDATA_DIR, "-I", TESTDATA_DIR "/builddependencycollector/external", "-I", TESTDATA_DIR "/builddependencycollector/project", "-isystem", TESTDATA_DIR "/builddependencycollector/system", "-Wno-pragma-once-outside-header"));
|
||||
}
|
||||
|
||||
TEST_F(PchCreator, CreateProjectPartHeaders)
|
||||
@@ -135,37 +147,45 @@ TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludes)
|
||||
|
||||
auto includeIds = creator.generateProjectPartPchIncludes(projectPart1);
|
||||
|
||||
ASSERT_THAT(includeIds,
|
||||
ASSERT_THAT(
|
||||
includeIds,
|
||||
AllOf(
|
||||
Field(&PchCreatorIncludes::includeIds,
|
||||
AllOf(Contains(id(TESTDATA_DIR "/includecollector/external/external1.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/external/external2.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/project/header2.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/system/system1.h")))),
|
||||
Field(&PchCreatorIncludes::topSystemIncludeIds,
|
||||
AllOf(Contains(id(TESTDATA_DIR "/includecollector/system/system1.h")),
|
||||
Not(Contains(id(TESTDATA_DIR "/includecollector/system/indirect_system.h"))))),
|
||||
Field(&PchCreatorIncludes::topIncludeIds,
|
||||
AllOf(Contains(id(TESTDATA_DIR "/includecollector/external/external1.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/external/external2.h"))))));
|
||||
Contains(HasIdAndType(
|
||||
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||
SourceType::TopInclude)),
|
||||
Contains(HasIdAndType(
|
||||
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
|
||||
SourceType::TopSystemInclude)),
|
||||
Contains(HasIdAndType(
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/system/indirect_system.h"),
|
||||
SourceType::SystemInclude)),
|
||||
Contains(HasIdAndType(
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/external1.h"),
|
||||
SourceType::TopInclude)),
|
||||
Contains(HasIdAndType(
|
||||
id(TESTDATA_DIR
|
||||
"/builddependencycollector/external/external2.h"),
|
||||
SourceType::TopInclude))));
|
||||
}
|
||||
|
||||
TEST_F(PchCreatorSlowTest, CreateProjectPartPchFileContent)
|
||||
{
|
||||
auto includes = creator.generateProjectPartPchIncludes(projectPart1);
|
||||
|
||||
auto content = creator.generatePchIncludeFileContent(includes.topIncludeIds);
|
||||
auto content = creator.generatePchIncludeFileContent(creator.topIncludeIds(includes));
|
||||
|
||||
ASSERT_THAT(std::string(content),
|
||||
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector/project/header2.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external1.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external2.h\"\n")));
|
||||
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/project/header2.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external1.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external2.h\"\n")));
|
||||
}
|
||||
|
||||
TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludeFile)
|
||||
{
|
||||
auto includes = creator.generateProjectPartPchIncludes(projectPart1);
|
||||
auto content = creator.generatePchIncludeFileContent(includes.topIncludeIds);
|
||||
auto content = creator.generatePchIncludeFileContent(creator.topIncludeIds(includes));
|
||||
auto pchIncludeFilePath = creator.generateProjectPathPchHeaderFilePath(projectPart1);
|
||||
auto file = creator.generateFileWithContent(pchIncludeFilePath, content);
|
||||
file->open(QIODevice::ReadOnly);
|
||||
@@ -173,9 +193,9 @@ TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludeFile)
|
||||
auto fileContent = file->readAll();
|
||||
|
||||
ASSERT_THAT(fileContent.toStdString(),
|
||||
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector/project/header2.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external1.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external2.h\"\n")));
|
||||
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/project/header2.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external1.h\"\n"),
|
||||
HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external2.h\"\n")));
|
||||
}
|
||||
|
||||
TEST_F(PchCreator, CreateProjectPartPchCompilerArguments)
|
||||
@@ -235,9 +255,9 @@ TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts)
|
||||
|
||||
ASSERT_THAT(creator.takeProjectIncludes(),
|
||||
AllOf(Field(&IdPaths::id, "project1"),
|
||||
Field(&IdPaths::filePathIds, AllOf(Contains(id(TESTDATA_DIR "/includecollector/project/header2.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/external/external1.h")),
|
||||
Contains(id(TESTDATA_DIR "/includecollector/external/external2.h"))))));
|
||||
Field(&IdPaths::filePathIds, AllOf(Contains(id(TESTDATA_DIR "/builddependencycollector/project/header2.h")),
|
||||
Contains(id(TESTDATA_DIR "/builddependencycollector/external/external1.h")),
|
||||
Contains(id(TESTDATA_DIR "/builddependencycollector/external/external2.h"))))));
|
||||
}
|
||||
|
||||
TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForProjectPart)
|
||||
@@ -276,7 +296,7 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesNoPchForProjectPart
|
||||
{{"DEFINE", "1"}},
|
||||
{"/includes"},
|
||||
{},
|
||||
{id(TESTDATA_DIR "/includecollector/project/faulty.cpp")}};
|
||||
{id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")}};
|
||||
|
||||
creator.generatePch(faultyProjectPart);
|
||||
|
||||
@@ -290,15 +310,14 @@ TEST_F(PchCreator, CreateProjectPartSourcesContent)
|
||||
{
|
||||
auto content = creator.generateProjectPartSourcesContent(projectPart1);
|
||||
|
||||
ASSERT_THAT(content, Eq("#include \"" TESTDATA_DIR "/includecollector/project/main3.cpp\"\n"));
|
||||
ASSERT_THAT(content, Eq("#include \"" TESTDATA_DIR "/builddependencycollector/project/main3.cpp\"\n"));
|
||||
}
|
||||
|
||||
TEST_F(PchCreator, Call)
|
||||
{
|
||||
auto content = creator.generateProjectPartSourcesContent(projectPart1);
|
||||
|
||||
ASSERT_THAT(content, Eq("#include \"" TESTDATA_DIR "/includecollector/project/main3.cpp\"\n"));
|
||||
ASSERT_THAT(content, Eq("#include \"" TESTDATA_DIR "/builddependencycollector/project/main3.cpp\"\n"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -74,10 +74,10 @@ protected:
|
||||
NiceMock<MockPchManagerClient> mockPchManagerClient;
|
||||
SmallString projectPartId1 = "project1";
|
||||
SmallString projectPartId2 = "project2";
|
||||
PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp";
|
||||
PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
|
||||
PathString header1Path = TESTDATA_DIR "/includecollector_header1.h";
|
||||
PathString header2Path = TESTDATA_DIR "/includecollector_header2.h";
|
||||
PathString main1Path = TESTDATA_DIR "/BuildDependencyCollector_main3.cpp";
|
||||
PathString main2Path = TESTDATA_DIR "/BuildDependencyCollector_main2.cpp";
|
||||
PathString header1Path = TESTDATA_DIR "/BuildDependencyCollector_header1.h";
|
||||
PathString header2Path = TESTDATA_DIR "/BuildDependencyCollector_header2.h";
|
||||
ClangBackEnd::IdPaths idPath{projectPartId1, {1, 2}};
|
||||
ProjectPartContainer projectPart1{projectPartId1.clone(),
|
||||
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
|
||||
|
||||
@@ -49,8 +49,8 @@ protected:
|
||||
{"/yi"},
|
||||
{{1, 1}},
|
||||
{{1, 2}}};
|
||||
SourceEntries firstSources{{1, SourceType::Any, 1}, {2, SourceType::Any, 1}, {10, SourceType::Any, 1}};
|
||||
BuildDependency buildDependency{firstSources, {}, {}, {}};
|
||||
SourceEntries firstSources{{1, SourceType::UserInclude, 1}, {2, SourceType::UserInclude, 1}, {10, SourceType::UserInclude, 1}};
|
||||
BuildDependency buildDependency{firstSources, {}};
|
||||
};
|
||||
|
||||
TEST_F(PchTaskGenerator, Create)
|
||||
|
||||
@@ -162,7 +162,7 @@ protected:
|
||||
ClangBackEnd::FilePathId main2PathId{filePathId(TESTDATA_DIR "/symbolindexer_main2.cpp")};
|
||||
ClangBackEnd::FilePathId header2PathId{filePathId(TESTDATA_DIR "/symbolindexer_header1.h")};
|
||||
ClangBackEnd::FilePathId header1PathId{filePathId(TESTDATA_DIR "/symbolindexer_header2.h")};
|
||||
PathString generatedFileName = "includecollector_generated_file.h";
|
||||
PathString generatedFileName = "BuildDependencyCollector_generated_file.h";
|
||||
ClangBackEnd::FilePathId generatedFilePathId21;
|
||||
ProjectPartContainer projectPart1{"project1",
|
||||
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
|
||||
|
||||
@@ -106,7 +106,8 @@ SOURCES += \
|
||||
pchtaskgenerator-test.cpp \
|
||||
compilationdatabaseutils-test.cpp \
|
||||
builddependenciesprovider-test.cpp \
|
||||
builddependenciesstorage-test.cpp
|
||||
builddependenciesstorage-test.cpp \
|
||||
builddependencycollector-test.cpp
|
||||
|
||||
!isEmpty(LIBCLANG_LIBS) {
|
||||
SOURCES += \
|
||||
@@ -172,7 +173,6 @@ SOURCES += \
|
||||
clangqueryprojectfindfilter-test.cpp \
|
||||
clangquery-test.cpp \
|
||||
gtest-clang-printing.cpp \
|
||||
includecollector-test.cpp \
|
||||
pchcreator-test.cpp \
|
||||
refactoringclientserverinprocess-test.cpp \
|
||||
refactoringclient-test.cpp \
|
||||
@@ -252,8 +252,8 @@ HEADERS += \
|
||||
mocktaskscheduler.h \
|
||||
mockbuilddependenciesprovider.h \
|
||||
mockmodifiedtimechecker.h \
|
||||
mockbuilddependenciesgenerator.h \
|
||||
mockbuilddependenciesstorage.h
|
||||
mockbuilddependenciesstorage.h \
|
||||
mockbuilddependencygenerator.h
|
||||
|
||||
!isEmpty(LIBCLANG_LIBS) {
|
||||
HEADERS += \
|
||||
|
||||
Reference in New Issue
Block a user