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:
Marco Bubke
2018-11-12 19:27:51 +01:00
parent e11ff791f0
commit 64a3a130ac
56 changed files with 1135 additions and 813 deletions

View File

@@ -32,6 +32,7 @@
#include <iterator> #include <iterator>
#include <ostream> #include <ostream>
#include <sstream>
namespace Utils { namespace Utils {
@@ -232,7 +233,19 @@ ostream &operator<<(ostream &out, const vector<T> &vector)
{ {
out << "["; 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 << "]"; out << "]";

View File

@@ -27,7 +27,7 @@
#include "builddependenciesstorageinterface.h" #include "builddependenciesstorageinterface.h"
#include "modifiedtimecheckerinterface.h" #include "modifiedtimecheckerinterface.h"
#include "builddependenciesgeneratorinterface.h" #include "builddependencygeneratorinterface.h"
#include <algorithm> #include <algorithm>

View File

@@ -31,14 +31,14 @@ namespace ClangBackEnd {
class BuildDependenciesStorageInterface; class BuildDependenciesStorageInterface;
class ModifiedTimeCheckerInterface; class ModifiedTimeCheckerInterface;
class BuildDependenciesGeneratorInterface; class BuildDependencyGeneratorInterface;
class BuildDependenciesProvider : public BuildDependenciesProviderInterface class BuildDependenciesProvider : public BuildDependenciesProviderInterface
{ {
public: public:
BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage, BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage,
ModifiedTimeCheckerInterface &modifiedTimeChecker, ModifiedTimeCheckerInterface &modifiedTimeChecker,
BuildDependenciesGeneratorInterface &buildDependenciesGenerator) BuildDependencyGeneratorInterface &buildDependenciesGenerator)
: m_buildDependenciesStorage(buildDependenciesStorage), : m_buildDependenciesStorage(buildDependenciesStorage),
m_modifiedTimeChecker(modifiedTimeChecker), m_modifiedTimeChecker(modifiedTimeChecker),
m_buildDependenciesGenerator(buildDependenciesGenerator) m_buildDependenciesGenerator(buildDependenciesGenerator)
@@ -56,7 +56,7 @@ private:
private: private:
BuildDependenciesStorageInterface &m_buildDependenciesStorage; BuildDependenciesStorageInterface &m_buildDependenciesStorage;
ModifiedTimeCheckerInterface &m_modifiedTimeChecker; ModifiedTimeCheckerInterface &m_modifiedTimeChecker;
BuildDependenciesGeneratorInterface &m_buildDependenciesGenerator; BuildDependencyGeneratorInterface &m_buildDependenciesGenerator;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include "filestatus.h"
#include "sourcedependency.h"
#include "sourceentry.h" #include "sourceentry.h"
#include "usedmacro.h" #include "usedmacro.h"
@@ -32,13 +34,24 @@ namespace ClangBackEnd {
class BuildDependency class BuildDependency
{ {
public:
void clear()
{
includes.clear();
usedMacros.clear();
sourceFiles.clear();
fileStatuses.clear();
sourceDependencies.clear();
}
public: public:
SourceEntries includes; SourceEntries includes;
FilePathIds topIncludeIds;
FilePathIds topsSystemIncludeIds;
UsedMacros usedMacros; UsedMacros usedMacros;
FilePathIds sourceFiles;
SourceDependencies sourceDependencies;
FileStatuses fileStatuses;
}; };
using BuildDependencies = std::vector<BuildDependency>; using BuildDependencies = std::vector<BuildDependency>;
} } // namespace ClangBackEnd

View File

@@ -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

View File

@@ -25,27 +25,28 @@
#pragma once #pragma once
#include "builddependencygeneratorinterface.h"
#include <clangtool.h> #include <clangtool.h>
#include <filestatus.h>
#include <sourcedependency.h>
#include <sourcesmanager.h> #include <sourcesmanager.h>
#include <usedmacro.h>
#include <filepathcachingfwd.h> #include <filepathcachingfwd.h>
namespace ClangBackEnd { namespace ClangBackEnd {
class IncludeCollector : public ClangTool class BuildDependencyCollector : public BuildDependencyGeneratorInterface
{ {
public: public:
IncludeCollector(const FilePathCachingInterface &filePathCache) BuildDependencyCollector(const FilePathCachingInterface &filePathCache)
: m_filePathCache(filePathCache) : m_filePathCache(filePathCache)
{ {
} }
BuildDependency create(const V2::ProjectPartContainer &projectPart) override;
void collect(); void collect();
void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes); void setExcludedFilePaths(ClangBackEnd::FilePaths &&excludedIncludes);
void addFiles(const FilePathIds &filePathIds, void addFiles(const FilePathIds &filePathIds,
const Utils::SmallStringVector &arguments); const Utils::SmallStringVector &arguments);
void addFile(FilePathId filePathId, void addFile(FilePathId filePathId,
@@ -53,62 +54,43 @@ public:
void addFile(FilePath filePath, void addFile(FilePath filePath,
const FilePathIds &sourceFileIds, const FilePathIds &sourceFileIds,
const Utils::SmallStringVector &arguments); const Utils::SmallStringVector &arguments);
void addUnsavedFiles(const V2::FileContainers &unsavedFiles);
void clear(); void clear();
const FileStatuses &fileStatuses() const const FileStatuses &fileStatuses() const
{ {
return m_fileStatuses; return m_buildDependency.fileStatuses;
} }
const FilePathIds &sourceFiles() const const FilePathIds &sourceFiles() const
{ {
return m_sourceFiles; return m_buildDependency.sourceFiles;
} }
const UsedMacros &usedMacros() const const UsedMacros &usedMacros() const
{ {
return m_usedMacros; return m_buildDependency.usedMacros;
} }
const SourceDependencies &sourceDependencies() const 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); return std::move(m_buildDependency.includes);
}
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);
} }
private: private:
ClangTool m_clangTool; ClangTool m_clangTool;
Utils::PathStringVector m_excludedIncludes; BuildDependency m_buildDependency;
FilePathIds m_includeIds; ClangBackEnd::FilePaths m_excludedFilePaths;
FilePathIds m_topIncludeIds;
FilePathIds m_topsSystemIncludeIds;
Utils::SmallStringVector m_directories; Utils::SmallStringVector m_directories;
SourcesManager m_sourcesManager; SourcesManager m_sourcesManager;
UsedMacros m_usedMacros;
FilePathIds m_sourceFiles;
SourceDependencies m_sourceDependencies;
FileStatuses m_fileStatuses;
const FilePathCachingInterface &m_filePathCache; const FilePathCachingInterface &m_filePathCache;
}; };

View File

@@ -31,13 +31,13 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class BuildDependenciesGeneratorInterface class BuildDependencyGeneratorInterface
{ {
public: public:
virtual BuildDependency create(const V2::ProjectPartContainer &projectPart) = 0; virtual BuildDependency create(const V2::ProjectPartContainer &projectPart) = 0;
protected: protected:
~BuildDependenciesGeneratorInterface() = default; ~BuildDependencyGeneratorInterface() = default;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -5,7 +5,8 @@ SOURCES += \
$$PWD/projectparts.cpp \ $$PWD/projectparts.cpp \
$$PWD/projectpartqueue.cpp \ $$PWD/projectpartqueue.cpp \
$$PWD/pchtaskgenerator.cpp \ $$PWD/pchtaskgenerator.cpp \
$$PWD/builddependenciesprovider.cpp $$PWD/builddependenciesprovider.cpp \
$$PWD/builddependencycollector.cpp
HEADERS += \ HEADERS += \
$$PWD/pchmanagerserver.h \ $$PWD/pchmanagerserver.h \
@@ -32,20 +33,19 @@ HEADERS += \
$$PWD/builddependency.h \ $$PWD/builddependency.h \
$$PWD/modifiedtimecheckerinterface.h \ $$PWD/modifiedtimecheckerinterface.h \
$$PWD/sourceentry.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) { !isEmpty(LIBTOOLING_LIBS) {
SOURCES += \ SOURCES += \
$$PWD/usedmacrosandsourcescollector.cpp \ $$PWD/usedmacrosandsourcescollector.cpp \
$$PWD/includecollector.cpp \
$$PWD/pchcreator.cpp $$PWD/pchcreator.cpp
HEADERS += \ HEADERS += \
$$PWD/includecollector.h \
$$PWD/collectincludestoolaction.h \
$$PWD/collectincludesaction.h \
$$PWD/collectincludespreprocessorcallbacks.h \
$$PWD/collectusedmacroactionfactory.h \ $$PWD/collectusedmacroactionfactory.h \
$$PWD/collectusedmacrosaction.h \ $$PWD/collectusedmacrosaction.h \
$$PWD/collectusedmacrosandsourcespreprocessorcallbacks.h \ $$PWD/collectusedmacrosandsourcespreprocessorcallbacks.h \

View File

@@ -25,7 +25,7 @@
#pragma once #pragma once
#include <collectincludespreprocessorcallbacks.h> #include <collectbuilddependencypreprocessorcallbacks.h>
#include <filepathcachingfwd.h> #include <filepathcachingfwd.h>
#include <filepathid.h> #include <filepathid.h>
@@ -36,31 +36,19 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class CollectIncludesAction final : public clang::PreprocessOnlyAction class CollectBuildDependencyAction final : public clang::PreprocessOnlyAction
{ {
public: public:
CollectIncludesAction(FilePathIds &includeIds, CollectBuildDependencyAction(BuildDependency &buildDependency,
FilePathIds &topIncludeIds,
FilePathIds &topsSystemIncludeIds,
const FilePathCachingInterface &filePathCache, const FilePathCachingInterface &filePathCache,
std::vector<uint> &excludedIncludeUID, std::vector<uint> &excludedIncludeUID,
std::vector<uint> &alreadyIncludedFileUIDs, std::vector<uint> &alreadyIncludedFileUIDs,
UsedMacros &usedMacros, SourcesManager &sourcesManager)
SourcesManager &sourcesManager, : m_buildDependency(buildDependency),
SourceDependencies &sourceDependencies,
FilePathIds &sourceFiles,
FileStatuses &fileStatuses)
: m_includeIds(includeIds),
m_topIncludeIds(topIncludeIds),
m_topsSystemIncludeIds(topsSystemIncludeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
m_excludedIncludeUID(excludedIncludeUID), m_excludedIncludeUID(excludedIncludeUID),
m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs), m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs),
m_usedMacros(usedMacros), m_sourcesManager(sourcesManager)
m_sourcesManager(sourcesManager),
m_sourceDependencies(sourceDependencies),
m_sourceFiles(sourceFiles),
m_fileStatuses(fileStatuses)
{ {
} }
@@ -71,20 +59,14 @@ public:
preprocessor.SetSuppressIncludeNotFoundError(true); preprocessor.SetSuppressIncludeNotFoundError(true);
auto macroPreprocessorCallbacks = new CollectIncludesPreprocessorCallbacks( auto macroPreprocessorCallbacks = new CollectBuildDependencyPreprocessorCallbacks(
m_includeIds, m_buildDependency,
m_topIncludeIds,
m_topsSystemIncludeIds,
m_filePathCache, m_filePathCache,
m_excludedIncludeUID, m_excludedIncludeUID,
m_alreadyIncludedFileUIDs, m_alreadyIncludedFileUIDs,
compilerInstance.getSourceManager(), compilerInstance.getSourceManager(),
m_usedMacros,
m_sourcesManager, m_sourcesManager,
compilerInstance.getPreprocessorPtr(), compilerInstance.getPreprocessorPtr());
m_sourceDependencies,
m_sourceFiles,
m_fileStatuses);
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks)); preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks));
@@ -100,17 +82,11 @@ public:
} }
private: private:
FilePathIds &m_includeIds; BuildDependency &m_buildDependency;
FilePathIds &m_topIncludeIds;
FilePathIds &m_topsSystemIncludeIds;
const FilePathCachingInterface &m_filePathCache; const FilePathCachingInterface &m_filePathCache;
std::vector<uint> &m_excludedIncludeUID; std::vector<uint> &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs; std::vector<uint> &m_alreadyIncludedFileUIDs;
UsedMacros &m_usedMacros;
SourcesManager &m_sourcesManager; SourcesManager &m_sourcesManager;
SourceDependencies &m_sourceDependencies;
FilePathIds &m_sourceFiles;
FileStatuses &m_fileStatuses;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include "builddependency.h"
#include "collectmacrospreprocessorcallbacks.h" #include "collectmacrospreprocessorcallbacks.h"
#include "sourcelocationsutils.h" #include "sourcelocationsutils.h"
@@ -33,6 +34,8 @@
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
#include <llvm/Support/MemoryBuffer.h>
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
#include <QTemporaryDir> #include <QTemporaryDir>
@@ -41,34 +44,26 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks, class CollectBuildDependencyPreprocessorCallbacks final : public clang::PPCallbacks,
public CollectUsedMacrosAndSourcesPreprocessorCallbacksBase public CollectUsedMacrosAndSourcesPreprocessorCallbacksBase
{ {
public: public:
CollectIncludesPreprocessorCallbacks(FilePathIds &includeIds, CollectBuildDependencyPreprocessorCallbacks(BuildDependency &buildDependency,
FilePathIds &topIncludeIds,
FilePathIds &topsSystemIncludeIds,
const FilePathCachingInterface &filePathCache, const FilePathCachingInterface &filePathCache,
const std::vector<uint> &excludedIncludeUID, const std::vector<uint> &excludedIncludeUID,
std::vector<uint> &alreadyIncludedFileUIDs, std::vector<uint> &alreadyIncludedFileUIDs,
const clang::SourceManager &sourceManager, clang::SourceManager &sourceManager,
UsedMacros &usedMacros,
SourcesManager &sourcesManager, SourcesManager &sourcesManager,
std::shared_ptr<clang::Preprocessor> preprocessor, std::shared_ptr<clang::Preprocessor> preprocessor)
SourceDependencies &sourceDependencies, : CollectUsedMacrosAndSourcesPreprocessorCallbacksBase(buildDependency.usedMacros,
FilePathIds &sourceFiles,
FileStatuses &fileStatuses)
: CollectUsedMacrosAndSourcesPreprocessorCallbacksBase(usedMacros,
filePathCache, filePathCache,
sourceManager, sourceManager,
sourcesManager, sourcesManager,
preprocessor, preprocessor,
sourceDependencies, buildDependency.sourceDependencies,
sourceFiles, buildDependency.sourceFiles,
fileStatuses), buildDependency.fileStatuses),
m_includeIds(includeIds), m_buildDependency(buildDependency),
m_topIncludeIds(topIncludeIds),
m_topsSystemIncludeIds(topsSystemIncludeIds),
m_excludedIncludeUID(excludedIncludeUID), m_excludedIncludeUID(excludedIncludeUID),
m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs) m_alreadyIncludedFileUIDs(alreadyIncludedFileUIDs)
{} {}
@@ -103,20 +98,30 @@ public:
if (!m_skipInclude && file) { if (!m_skipInclude && file) {
addSourceDependency(file, hashLocation); addSourceDependency(file, hashLocation);
auto fileUID = file->getUID(); auto fileUID = file->getUID();
auto sourceFileUID = m_sourceManager->getFileEntryForID(m_sourceManager->getFileID(hashLocation))->getUID(); auto sourceFileUID = m_sourceManager
if (isNotInExcludedIncludeUID(fileUID)) { ->getFileEntryForID(m_sourceManager->getFileID(hashLocation))
->getUID();
auto notAlreadyIncluded = isNotAlreadyIncluded(fileUID); auto notAlreadyIncluded = isNotAlreadyIncluded(fileUID);
if (notAlreadyIncluded.first) { if (notAlreadyIncluded.first) {
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID); m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
FilePath filePath = filePathFromFile(file); FilePath filePath = filePathFromFile(file);
if (!filePath.empty()) { if (!filePath.empty()) {
FilePathId includeId = m_filePathCache.filePathId(filePath); FilePathId includeId = m_filePathCache.filePathId(filePath);
m_includeIds.emplace_back(includeId);
if (isSystem(fileType) && !isInSystemHeader(hashLocation)) time_t lastModified = file->getModificationTime();
m_topsSystemIncludeIds.emplace_back(includeId);
if (isInExcludedIncludeUID(sourceFileUID)) SourceType sourceType = SourceType::UserInclude;
m_topIncludeIds.emplace_back(includeId); 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; 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; auto dummyPath = llvm::StringRef("/dummyPath");
temporaryDirectory.setAutoRemove(false);
const QByteArray temporaryDirUtf8 = temporaryDirectory.path().toUtf8();
const QString fileName = QString::fromUtf8(fileNameRef.data(), int(fileNameRef.size())); recoveryPath.append(std::cbegin(dummyPath), std::cend(dummyPath));
QString filePath = temporaryDirectory.path() + '/' + fileName;
ensureDirectory(temporaryDirectory.path(), fileName);
createFakeFile(filePath);
recoveryPath.append(temporaryDirUtf8.cbegin(), temporaryDirUtf8.cend());
m_skipInclude = true; m_skipInclude = true;
@@ -189,15 +187,6 @@ public:
QDir(directory).mkpath(directoryEntries.join('/')); 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 bool isNotInExcludedIncludeUID(uint uid) const
{ {
return !isInExcludedIncludeUID(uid); return !isInExcludedIncludeUID(uid);
@@ -224,10 +213,21 @@ public:
return FilePath::fromNativeFilePath(absolutePath(file->getName())); 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: private:
FilePathIds &m_includeIds; FilePathIds m_containsMissingIncludes;
FilePathIds &m_topIncludeIds; BuildDependency &m_buildDependency;
FilePathIds &m_topsSystemIncludeIds;
const std::vector<uint> &m_excludedIncludeUID; const std::vector<uint> &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs; std::vector<uint> &m_alreadyIncludedFileUIDs;
bool m_skipInclude = false; bool m_skipInclude = false;

View File

@@ -25,7 +25,7 @@
#pragma once #pragma once
#include "collectincludesaction.h" #include "collectbuilddependencyaction.h"
#include <filepathcachingfwd.h> #include <filepathcachingfwd.h>
#include <filepathid.h> #include <filepathid.h>
@@ -34,29 +34,17 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory class CollectBuildDependencyToolAction final : public clang::tooling::FrontendActionFactory
{ {
public: public:
CollectIncludesToolAction(FilePathIds &includeIds, CollectBuildDependencyToolAction(BuildDependency &buildDependency,
FilePathIds &topIncludeIds,
FilePathIds &topsSystemIncludeIds,
const FilePathCachingInterface &filePathCache, const FilePathCachingInterface &filePathCache,
const Utils::PathStringVector &excludedIncludes, const ClangBackEnd::FilePaths &excludedIncludes,
UsedMacros &usedMacros, SourcesManager &sourcesManager)
SourcesManager &sourcesManager, : m_buildDependency(buildDependency),
SourceDependencies &sourceDependencies,
FilePathIds &sourceFiles,
FileStatuses &fileStatuses)
: m_includeIds(includeIds),
m_topIncludeIds(topIncludeIds),
m_topsSystemIncludeIds(topsSystemIncludeIds),
m_filePathCache(filePathCache), m_filePathCache(filePathCache),
m_excludedIncludes(excludedIncludes), m_excludedFilePaths(excludedIncludes),
m_usedMacros(usedMacros), m_sourcesManager(sourcesManager)
m_sourcesManager(sourcesManager),
m_sourceDependencies(sourceDependencies),
m_sourceFiles(sourceFiles),
m_fileStatuses(fileStatuses)
{} {}
@@ -76,26 +64,21 @@ public:
clang::FrontendAction *create() override clang::FrontendAction *create() override
{ {
return new CollectIncludesAction(m_includeIds, return new CollectBuildDependencyAction(m_buildDependency,
m_topIncludeIds,
m_topsSystemIncludeIds,
m_filePathCache, m_filePathCache,
m_excludedIncludeUIDs, m_excludedIncludeUIDs,
m_alreadyIncludedFileUIDs, m_alreadyIncludedFileUIDs,
m_usedMacros, m_sourcesManager);
m_sourcesManager,
m_sourceDependencies,
m_sourceFiles,
m_fileStatuses);
} }
std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
{ {
std::vector<uint> fileUIDs; std::vector<uint> fileUIDs;
fileUIDs.reserve(m_excludedIncludes.size()); fileUIDs.reserve(m_excludedFilePaths.size());
for (const Utils::PathString &filePath : m_excludedIncludes) { for (const ClangBackEnd::FilePath &filePath : m_excludedFilePaths) {
const clang::FileEntry *file = fileManager.getFile({filePath.data(), filePath.size()}, true); const clang::FileEntry *file = fileManager.getFile({filePath.data(), filePath.size()},
true);
if (file) if (file)
fileUIDs.push_back(file->getUID()); fileUIDs.push_back(file->getUID());
@@ -109,16 +92,10 @@ public:
private: private:
std::vector<uint> m_alreadyIncludedFileUIDs; std::vector<uint> m_alreadyIncludedFileUIDs;
std::vector<uint> m_excludedIncludeUIDs; std::vector<uint> m_excludedIncludeUIDs;
FilePathIds &m_includeIds; BuildDependency &m_buildDependency;
FilePathIds &m_topIncludeIds;
FilePathIds &m_topsSystemIncludeIds;
const FilePathCachingInterface &m_filePathCache; const FilePathCachingInterface &m_filePathCache;
const Utils::PathStringVector &m_excludedIncludes; const ClangBackEnd::FilePaths &m_excludedFilePaths;
UsedMacros &m_usedMacros;
SourcesManager &m_sourcesManager; SourcesManager &m_sourcesManager;
SourceDependencies &m_sourceDependencies;
FilePathIds &m_sourceFiles;
FileStatuses &m_fileStatuses;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -102,7 +102,15 @@ public:
auto includeFilePathId = filePathId(includeLocation); auto includeFilePathId = filePathId(includeLocation);
auto includedFilePathId = filePathId(file); 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() void mergeUsedMacros()

View File

@@ -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

View File

@@ -26,7 +26,7 @@
#include "pchcreator.h" #include "pchcreator.h"
#include "environment.h" #include "environment.h"
#include "includecollector.h" #include "builddependencycollector.h"
#include "pchnotcreatederror.h" #include "pchnotcreatederror.h"
#include <clangpathwatcherinterface.h> #include <clangpathwatcherinterface.h>
@@ -58,12 +58,12 @@ void append(Target &target, const Source &source)
target.push_back(ValueType(std::move(entry))); target.push_back(ValueType(std::move(entry)));
} }
void appendFilePathId(Utils::PathStringVector &target, void appendFilePathId(ClangBackEnd::FilePaths &target,
const ClangBackEnd::FilePathIds &source, const ClangBackEnd::FilePathIds &source,
const ClangBackEnd::FilePathCachingInterface &filePathCache) const ClangBackEnd::FilePathCachingInterface &filePathCache)
{ {
for (FilePathId id : source) for (FilePathId id : source)
target.emplace_back(filePathCache.filePath(id).path()); target.emplace_back(filePathCache.filePath(id));
} }
Utils::PathStringVector generatedFilePaths(const V2::FileContainers &generaredFiles) Utils::PathStringVector generatedFilePaths(const V2::FileContainers &generaredFiles)
@@ -190,23 +190,23 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaders(
namespace { namespace {
std::size_t sizeOfContent(const Utils::PathStringVector &paths) std::size_t sizeOfContent(const ClangBackEnd::FilePaths &paths)
{ {
return std::accumulate(paths.begin(), return std::accumulate(paths.begin(),
paths.end(), paths.end(),
std::size_t(0), std::size_t(0),
[] (std::size_t size, const Utils::PathString &path) { [] (std::size_t size, const auto &path) {
const char includeTemplate[] = "#include \"\"\n"; const char includeTemplate[] = "#include \"\"\n";
return size + path.size() + sizeof(includeTemplate); 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; Utils::SmallString content;
content.reserve(size); content.reserve(size);
for (const Utils::PathString &path : paths) { for (const ClangBackEnd::FilePath &path : paths) {
content += "#include \""; content += "#include \"";
content += path; content += path;
content += "\"\n"; content += "\"\n";
@@ -220,15 +220,15 @@ Utils::SmallString concatContent(const Utils::PathStringVector &paths, std::size
Utils::SmallString PchCreator::generateProjectPartSourcesContent( Utils::SmallString PchCreator::generateProjectPartSourcesContent(
const V2::ProjectPartContainer &projectPart) const const V2::ProjectPartContainer &projectPart) const
{ {
Utils::PathStringVector paths = generateProjectPartSourcePaths(projectPart); ClangBackEnd::FilePaths paths = generateProjectPartSourcePaths(projectPart);
return concatContent(paths, sizeOfContent(paths)); return concatContent(paths, sizeOfContent(paths));
} }
Utils::PathStringVector PchCreator::generateProjectPartSourcePaths( ClangBackEnd::FilePaths PchCreator::generateProjectPartSourcePaths(
const V2::ProjectPartContainer &projectPart) const const V2::ProjectPartContainer &projectPart) const
{ {
Utils::PathStringVector includeAndSources; ClangBackEnd::FilePaths includeAndSources;
includeAndSources.reserve(projectPart.sourcePathIds.size()); includeAndSources.reserve(projectPart.sourcePathIds.size());
appendFilePathId(includeAndSources, projectPart.sourcePathIds, m_filePathCache); appendFilePathId(includeAndSources, projectPart.sourcePathIds, m_filePathCache);
@@ -236,7 +236,7 @@ Utils::PathStringVector PchCreator::generateProjectPartSourcePaths(
return includeAndSources; return includeAndSources;
} }
PchCreatorIncludes PchCreator::generateProjectPartPchIncludes( SourceEntries PchCreator::generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const const V2::ProjectPartContainer &projectPart) const
{ {
Utils::SmallString jointedFileContent = generateProjectPartSourcesContent(projectPart); Utils::SmallString jointedFileContent = generateProjectPartSourcesContent(projectPart);
@@ -245,9 +245,9 @@ PchCreatorIncludes PchCreator::generateProjectPartPchIncludes(
Utils::SmallStringVector arguments = generateProjectPartCommandLine(projectPart); Utils::SmallStringVector arguments = generateProjectPartCommandLine(projectPart);
FilePath filePath{Utils::PathString(jointedFilePath)}; 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); collector.addFile(filePath, projectPart.sourcePathIds, arguments);
@@ -257,7 +257,7 @@ PchCreatorIncludes PchCreator::generateProjectPartPchIncludes(
jointFile->remove(); jointFile->remove();
return {collector.takeIncludeIds(), collector.takeTopIncludeIds(), collector.takeTopsSystemIncludeIds()}; return collector.includeIds();
} }
Utils::SmallString PchCreator::generateProjectPathPchHeaderFilePath( Utils::SmallString PchCreator::generateProjectPathPchHeaderFilePath(
@@ -309,7 +309,7 @@ IdPaths PchCreator::generateProjectPartPch(const V2::ProjectPartContainer &proje
{ {
long long lastModified = QDateTime::currentSecsSinceEpoch(); long long lastModified = QDateTime::currentSecsSinceEpoch();
auto includes = generateProjectPartPchIncludes(projectPart); auto includes = generateProjectPartPchIncludes(projectPart);
auto content = generatePchIncludeFileContent(includes.topIncludeIds); auto content = generatePchIncludeFileContent(topIncludeIds(includes));
auto pchIncludeFilePath = generateProjectPathPchHeaderFilePath(projectPart); auto pchIncludeFilePath = generateProjectPathPchHeaderFilePath(projectPart);
auto pchFilePath = generateProjectPartPchFilePath(projectPart); auto pchFilePath = generateProjectPartPchFilePath(projectPart);
generateFileWithContent(pchIncludeFilePath, content); generateFileWithContent(pchIncludeFilePath, content);
@@ -323,7 +323,7 @@ IdPaths PchCreator::generateProjectPartPch(const V2::ProjectPartContainer &proje
m_projectPartPch.lastModified = lastModified; 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) void PchCreator::generatePch(const V2::ProjectPartContainer &projectPart)
@@ -392,6 +392,32 @@ std::unique_ptr<QFile> PchCreator::generateFileWithContent(
return precompiledIncludeFile; 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) QByteArray PchCreator::projectPartHash(const V2::ProjectPartContainer &projectPart)
{ {
QCryptographicHash hash(QCryptographicHash::Sha1); QCryptographicHash hash(QCryptographicHash::Sha1);

View File

@@ -28,6 +28,7 @@
#include "pchcreatorinterface.h" #include "pchcreatorinterface.h"
#include "idpaths.h" #include "idpaths.h"
#include "sourceentry.h"
#include <filepathcaching.h> #include <filepathcaching.h>
#include <projectpartpch.h> #include <projectpartpch.h>
@@ -93,9 +94,9 @@ public:
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPartSourcesContent( Utils::SmallString generateProjectPartSourcesContent(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
Utils::PathStringVector generateProjectPartSourcePaths( ClangBackEnd::FilePaths generateProjectPartSourcePaths(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
PchCreatorIncludes generateProjectPartPchIncludes( SourceEntries generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPathPchHeaderFilePath( Utils::SmallString generateProjectPathPchHeaderFilePath(
const V2::ProjectPartContainer &projectPart) const; const V2::ProjectPartContainer &projectPart) const;
@@ -113,6 +114,9 @@ public:
const Utils::SmallString &filePath, const Utils::SmallString &filePath,
const Utils::SmallString &content); const Utils::SmallString &content);
static FilePathIds topIncludeIds(const SourceEntries &includes);
static FilePathIds allIncludeIds(const SourceEntries &includes);
private: private:
static QByteArray projectPartHash(const V2::ProjectPartContainer &projectPart); static QByteArray projectPartHash(const V2::ProjectPartContainer &projectPart);

View File

@@ -33,9 +33,10 @@ namespace ClangBackEnd {
enum class SourceType : unsigned char enum class SourceType : unsigned char
{ {
Any,
TopInclude, TopInclude,
TopSystemInclude TopSystemInclude,
UserInclude,
SystemInclude
}; };
class TimeStamp class TimeStamp
@@ -62,7 +63,6 @@ public:
: lastModified(lastModified), : lastModified(lastModified),
sourceId(sourceId), sourceId(sourceId),
sourceType(static_cast<SourceType>(sourceType)) sourceType(static_cast<SourceType>(sourceType))
{} {}
SourceEntry(FilePathId sourceId, SourceType sourceType, TimeStamp lastModified) SourceEntry(FilePathId sourceId, SourceType sourceType, TimeStamp lastModified)
@@ -85,10 +85,12 @@ public:
&& first.lastModified == second.lastModified ; && first.lastModified == second.lastModified ;
} }
friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); }
public: public:
TimeStamp lastModified; TimeStamp lastModified;
FilePathId sourceId; FilePathId sourceId;
SourceType sourceType = SourceType::Any; SourceType sourceType = SourceType::UserInclude;
}; };
using SourceEntries = std::vector<SourceEntry>; using SourceEntries = std::vector<SourceEntry>;

View File

@@ -135,6 +135,8 @@ clang::tooling::ClangTool ClangTool::createTool() const
tool.mapVirtualFile(toStringRef(unsavedFileContent.filePath), tool.mapVirtualFile(toStringRef(unsavedFileContent.filePath),
toStringRef(unsavedFileContent.content)); toStringRef(unsavedFileContent.content));
tool.mapVirtualFile("/dummyFile", "#pragma once");
return tool; return tool;
} }

View File

@@ -54,6 +54,12 @@ public:
&& first.lastModified == second.lastModified; && first.lastModified == second.lastModified;
} }
friend
bool operator<(const FileStatus &first, const FileStatus &second)
{
return first.filePathId < second.filePathId;
}
public: public:
FilePathId filePathId; FilePathId filePathId;
off_t size; off_t size;

View File

@@ -34,23 +34,32 @@ namespace ClangBackEnd {
class SourceDependency class SourceDependency
{ {
public: public:
SourceDependency(FilePathId filePathId, SourceDependency(FilePathId filePathId, FilePathId dependencyFilePathId)
FilePathId dependencyFilePathId) : filePathId(filePathId)
: filePathId(filePathId), , dependencyFilePathId(dependencyFilePathId)
dependencyFilePathId(dependencyFilePathId)
{} {}
friend friend bool operator==(SourceDependency first, SourceDependency second)
bool operator==(SourceDependency first, SourceDependency second)
{ {
return first.filePathId == second.filePathId return first.filePathId == second.filePathId
&& first.dependencyFilePathId == second.dependencyFilePathId; && 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: public:
FilePathId filePathId; FilePathId filePathId;
FilePathId dependencyFilePathId; FilePathId dependencyFilePathId;
}; };
using SourceDependencies = std::vector<SourceDependency>; using SourceDependencies = std::vector<SourceDependency>;
} } // namespace ClangBackEnd

View File

@@ -145,7 +145,7 @@ public:
return SymbolIndex(reinterpret_cast<std::uintptr_t>(pointer)); return SymbolIndex(reinterpret_cast<std::uintptr_t>(pointer));
} }
void setSourceManager(const clang::SourceManager *sourceManager) void setSourceManager(clang::SourceManager *sourceManager)
{ {
m_sourceManager = sourceManager; m_sourceManager = sourceManager;
} }

View File

@@ -27,7 +27,7 @@
#include "mockbuilddependenciesstorage.h" #include "mockbuilddependenciesstorage.h"
#include "mockmodifiedtimechecker.h" #include "mockmodifiedtimechecker.h"
#include "mockbuilddependenciesgenerator.h" #include "mockbuilddependencygenerator.h"
#include <builddependenciesprovider.h> #include <builddependenciesprovider.h>
@@ -56,7 +56,7 @@ class BuildDependenciesProvider : public testing::Test
protected: protected:
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage; NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
NiceMock<MockModifiedTimeChecker> mockModifiedTimeChecker; NiceMock<MockModifiedTimeChecker> mockModifiedTimeChecker;
NiceMock<MockBuildDependenciesGenerator> mockBuildDependenciesGenerator; NiceMock<MockBuildDependencyGenerator> mockBuildDependenciesGenerator;
ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage, mockModifiedTimeChecker, mockBuildDependenciesGenerator}; ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage, mockModifiedTimeChecker, mockBuildDependenciesGenerator};
ClangBackEnd::V2::ProjectPartContainer projectPart1{"ProjectPart1", ClangBackEnd::V2::ProjectPartContainer projectPart1{"ProjectPart1",
{"--yi"}, {"--yi"},
@@ -70,13 +70,13 @@ protected:
{"/er"}, {"/er"},
{1}, {1},
{2, 3, 4}}; {2, 3, 4}};
SourceEntries firstSources{{1, SourceType::Any, 1}, {2, 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::Any, 1}, {3, SourceType::Any, 1}, {8, SourceType::Any, 1}}; SourceEntries secondSources{{1, SourceType::UserInclude, 1}, {3, SourceType::UserInclude, 1}, {8, SourceType::UserInclude, 1}};
SourceEntries thirdSources{{4, SourceType::Any, 1}, {8, SourceType::Any, 1}, {10, SourceType::Any, 1}}; SourceEntries thirdSources{{4, SourceType::UserInclude, 1}, {8, SourceType::UserInclude, 1}, {10, SourceType::UserInclude, 1}};
UsedMacros firstUsedMacros{{"YI", 1}}; UsedMacros firstUsedMacros{{"YI", 1}};
UsedMacros secondUsedMacros{{"LIANG", 2}, {"ER", 2}}; UsedMacros secondUsedMacros{{"LIANG", 2}, {"ER", 2}};
UsedMacros thirdUsedMacros{{"SAN", 10}}; UsedMacros thirdUsedMacros{{"SAN", 10}};
BuildDependency buildDependency{secondSources, {}, {}, {}}; BuildDependency buildDependency{secondSources, {}};
}; };
TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromStorageIfTimeStampsAreUpToDate) TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromStorageIfTimeStampsAreUpToDate)

View File

@@ -171,9 +171,9 @@ TEST_F(BuildDependenciesStorage, UpdateSources)
SourceEntries entries{{1, SourceType::TopInclude, 10}, {2, SourceType::TopSystemInclude, 20}}; SourceEntries entries{{1, SourceType::TopInclude, 10}, {2, SourceType::TopSystemInclude, 20}};
EXPECT_CALL(updateBuildDependencyTimeStampStatement, write(TypedEq<long long>(10), TypedEq<int>(1))); 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(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); storage.updateSources(entries);
} }

View 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

View File

@@ -0,0 +1,11 @@
#pragma once
#define DEFINE
#ifdef IFDEF
#endif
#if defined(DEFINED)
#endif
DEFINE

View File

@@ -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"

View File

@@ -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"

View File

@@ -66,6 +66,10 @@
#include <coreplugin/find/searchresultitem.h> #include <coreplugin/find/searchresultitem.h>
#include <coreplugin/locator/ilocatorfilter.h> #include <coreplugin/locator/ilocatorfilter.h>
namespace {
ClangBackEnd::FilePathCaching *filePathCache = nullptr;
}
void PrintTo(const Utf8String &text, ::std::ostream *os) void PrintTo(const Utf8String &text, ::std::ostream *os)
{ {
*os << text; *os << text;
@@ -171,7 +175,10 @@ namespace ClangBackEnd {
std::ostream &operator<<(std::ostream &out, const FilePathId &id) 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) 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) std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency)
{ {
return out << "(" return out << "(\n"
<< dependency.includes << ", " << "includes: " << dependency.includes << ",\n"
<< dependency.topsSystemIncludeIds << ", " << "usedMacros: " << dependency.usedMacros << ",\n"
<< dependency.topIncludeIds << ")"; << "fileStatuses: " << dependency.fileStatuses << ",\n"
<< "sourceFiles: " << dependency.sourceFiles << ",\n"
<< "sourceDependencies: " << dependency.sourceDependencies << ",\n"
<< ")";
} }
const char *sourceTypeString(SourceType sourceType) const char *sourceTypeString(SourceType sourceType)
@@ -1025,9 +1035,14 @@ const char *sourceTypeString(SourceType sourceType)
using ClangBackEnd::SymbolTag; using ClangBackEnd::SymbolTag;
switch (sourceType) { switch (sourceType) {
case SourceType::Any: return "Any"; case SourceType::TopInclude:
case SourceType::TopInclude: return "TopInclude"; return "TopInclude";
case SourceType::TopSystemInclude: return "TopSystemInclude"; case SourceType::TopSystemInclude:
return "TopSystemInclude";
case SourceType::SystemInclude:
return "SystemInclude";
case SourceType::UserInclude:
return "UserInclude";
} }
return ""; return "";
@@ -1131,3 +1146,8 @@ std::ostream &operator<<(std::ostream &out, const Usage &usage)
return out << "(" << usage.path << ", " << usage.line << ", " << usage.column <<")"; return out << "(" << usage.path << ", " << usage.line << ", " << usage.column <<")";
} }
} // namespace CppTools } // namespace CppTools
void setFilePathCache(ClangBackEnd::FilePathCaching *cache)
{
filePathCache = cache;
}

View File

@@ -173,6 +173,7 @@ class PchCreatorIncludes;
class PchTask; class PchTask;
class BuildDependency; class BuildDependency;
class SourceEntry; class SourceEntry;
class FilePathCaching;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry); std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths); std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -289,3 +290,5 @@ class Usage;
std::ostream &operator<<(std::ostream &out, const Usage &usage); std::ostream &operator<<(std::ostream &out, const Usage &usage);
} // namespace CppTools } // namespace CppTools
void setFilePathCache(ClangBackEnd::FilePathCaching *filePathCache);

View File

@@ -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)));
}
}

View File

@@ -27,9 +27,9 @@
#include "googletest.h" #include "googletest.h"
#include <builddependenciesgeneratorinterface.h> #include <builddependencygeneratorinterface.h>
class MockBuildDependenciesGenerator : public ClangBackEnd::BuildDependenciesGeneratorInterface class MockBuildDependencyGenerator : public ClangBackEnd::BuildDependencyGeneratorInterface
{ {
public: public:
MOCK_METHOD1(create, MOCK_METHOD1(create,

View File

@@ -43,21 +43,33 @@
namespace { namespace {
using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathId; using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathIds;
using ClangBackEnd::FilePathView;
using ClangBackEnd::GeneratedFiles; using ClangBackEnd::GeneratedFiles;
using ClangBackEnd::IdPaths; using ClangBackEnd::IdPaths;
using ClangBackEnd::ProjectPartPch; using ClangBackEnd::ProjectPartPch;
using ClangBackEnd::V2::ProjectPartContainer; using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry;
using ClangBackEnd::SourceType;
using ClangBackEnd::V2::FileContainer; using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::FilePath; using ClangBackEnd::V2::ProjectPartContainer;
using ClangBackEnd::FilePathIds;
using ClangBackEnd::FilePathView;
using Utils::PathString; using Utils::PathString;
using Utils::SmallString; using Utils::SmallString;
using UnitTests::EndsWith; 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 class PchCreator: public ::testing::Test
{ {
protected: protected:
@@ -74,27 +86,27 @@ protected:
protected: protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
FilePath main1Path = TESTDATA_DIR "/includecollector/project/main3.cpp"; FilePath main1Path = TESTDATA_DIR "/builddependencycollector/project/main3.cpp";
FilePath main2Path = TESTDATA_DIR "/includecollector/project/main2.cpp"; FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp";
FilePath header1Path = TESTDATA_DIR "/includecollector/project/header1.h"; FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h";
FilePath header2Path = TESTDATA_DIR "/includecollector/project/header2.h"; FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h";
Utils::SmallStringView generatedFileName = "includecollector/project/generated_file.h"; Utils::SmallStringView generatedFileName = "builddependencycollector/project/generated_file.h";
FilePath generatedFilePath = TESTDATA_DIR "/includecollector/project/generated_file.h"; FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h";
TestEnvironment environment; TestEnvironment environment;
FileContainer generatedFile{{TESTDATA_DIR, generatedFileName}, "#pragma once", {}}; FileContainer generatedFile{{TESTDATA_DIR, generatedFileName}, "#pragma once", {}};
NiceMock<MockPchManagerClient> mockPchManagerClient; NiceMock<MockPchManagerClient> mockPchManagerClient;
NiceMock<MockClangPathWatcher> mockClangPathWatcher; NiceMock<MockClangPathWatcher> mockClangPathWatcher;
ClangBackEnd::PchCreator creator{environment, database, mockPchManagerClient, mockClangPathWatcher}; ClangBackEnd::PchCreator creator{environment, database, mockPchManagerClient, mockClangPathWatcher};
ProjectPartContainer projectPart1{"project1", 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"}}, {{"DEFINE", "1"}},
{TESTDATA_DIR "/includecollector/external", TESTDATA_DIR "/includecollector/project"}, {TESTDATA_DIR "/builddependencycollector/external", TESTDATA_DIR "/builddependencycollector/project"},
{id(header1Path)}, {id(header1Path)},
{id(main1Path)}}; {id(main1Path)}};
ProjectPartContainer projectPart2{"project2", 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"}}, {{"DEFINE", "1"}},
{TESTDATA_DIR "/includecollector/external", TESTDATA_DIR "/includecollector/project"}, {TESTDATA_DIR "/builddependencycollector/external", TESTDATA_DIR "/builddependencycollector/project"},
{id(header2Path)}, {id(header2Path)},
{id(main2Path)}}; {id(main2Path)}};
}; };
@@ -112,7 +124,7 @@ TEST_F(PchCreator, CreateProjectPartCommandLine)
{ {
auto commandLine = creator.generateProjectPartCommandLine(projectPart1); 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) TEST_F(PchCreator, CreateProjectPartHeaders)
@@ -135,37 +147,45 @@ TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludes)
auto includeIds = creator.generateProjectPartPchIncludes(projectPart1); auto includeIds = creator.generateProjectPartPchIncludes(projectPart1);
ASSERT_THAT(includeIds, ASSERT_THAT(
includeIds,
AllOf( AllOf(
Field(&PchCreatorIncludes::includeIds, Contains(HasIdAndType(
AllOf(Contains(id(TESTDATA_DIR "/includecollector/external/external1.h")), id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
Contains(id(TESTDATA_DIR "/includecollector/external/external2.h")), SourceType::TopInclude)),
Contains(id(TESTDATA_DIR "/includecollector/project/header2.h")), Contains(HasIdAndType(
Contains(id(TESTDATA_DIR "/includecollector/system/system1.h")))), id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
Field(&PchCreatorIncludes::topSystemIncludeIds, SourceType::TopSystemInclude)),
AllOf(Contains(id(TESTDATA_DIR "/includecollector/system/system1.h")), Contains(HasIdAndType(
Not(Contains(id(TESTDATA_DIR "/includecollector/system/indirect_system.h"))))), id(TESTDATA_DIR
Field(&PchCreatorIncludes::topIncludeIds, "/builddependencycollector/system/indirect_system.h"),
AllOf(Contains(id(TESTDATA_DIR "/includecollector/external/external1.h")), SourceType::SystemInclude)),
Contains(id(TESTDATA_DIR "/includecollector/external/external2.h")))))); 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) TEST_F(PchCreatorSlowTest, CreateProjectPartPchFileContent)
{ {
auto includes = creator.generateProjectPartPchIncludes(projectPart1); auto includes = creator.generateProjectPartPchIncludes(projectPart1);
auto content = creator.generatePchIncludeFileContent(includes.topIncludeIds); auto content = creator.generatePchIncludeFileContent(creator.topIncludeIds(includes));
ASSERT_THAT(std::string(content), ASSERT_THAT(std::string(content),
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector/project/header2.h\"\n"), AllOf(HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/project/header2.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external1.h\"\n"), HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external1.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external2.h\"\n"))); HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external2.h\"\n")));
} }
TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludeFile) TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludeFile)
{ {
auto includes = creator.generateProjectPartPchIncludes(projectPart1); auto includes = creator.generateProjectPartPchIncludes(projectPart1);
auto content = creator.generatePchIncludeFileContent(includes.topIncludeIds); auto content = creator.generatePchIncludeFileContent(creator.topIncludeIds(includes));
auto pchIncludeFilePath = creator.generateProjectPathPchHeaderFilePath(projectPart1); auto pchIncludeFilePath = creator.generateProjectPathPchHeaderFilePath(projectPart1);
auto file = creator.generateFileWithContent(pchIncludeFilePath, content); auto file = creator.generateFileWithContent(pchIncludeFilePath, content);
file->open(QIODevice::ReadOnly); file->open(QIODevice::ReadOnly);
@@ -173,9 +193,9 @@ TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludeFile)
auto fileContent = file->readAll(); auto fileContent = file->readAll();
ASSERT_THAT(fileContent.toStdString(), ASSERT_THAT(fileContent.toStdString(),
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector/project/header2.h\"\n"), AllOf(HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/project/header2.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external1.h\"\n"), HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external1.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector/external/external2.h\"\n"))); HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external2.h\"\n")));
} }
TEST_F(PchCreator, CreateProjectPartPchCompilerArguments) TEST_F(PchCreator, CreateProjectPartPchCompilerArguments)
@@ -235,9 +255,9 @@ TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts)
ASSERT_THAT(creator.takeProjectIncludes(), ASSERT_THAT(creator.takeProjectIncludes(),
AllOf(Field(&IdPaths::id, "project1"), AllOf(Field(&IdPaths::id, "project1"),
Field(&IdPaths::filePathIds, AllOf(Contains(id(TESTDATA_DIR "/includecollector/project/header2.h")), Field(&IdPaths::filePathIds, AllOf(Contains(id(TESTDATA_DIR "/builddependencycollector/project/header2.h")),
Contains(id(TESTDATA_DIR "/includecollector/external/external1.h")), Contains(id(TESTDATA_DIR "/builddependencycollector/external/external1.h")),
Contains(id(TESTDATA_DIR "/includecollector/external/external2.h")))))); Contains(id(TESTDATA_DIR "/builddependencycollector/external/external2.h"))))));
} }
TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForProjectPart) TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForProjectPart)
@@ -276,7 +296,7 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesNoPchForProjectPart
{{"DEFINE", "1"}}, {{"DEFINE", "1"}},
{"/includes"}, {"/includes"},
{}, {},
{id(TESTDATA_DIR "/includecollector/project/faulty.cpp")}}; {id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")}};
creator.generatePch(faultyProjectPart); creator.generatePch(faultyProjectPart);
@@ -290,15 +310,14 @@ TEST_F(PchCreator, CreateProjectPartSourcesContent)
{ {
auto content = creator.generateProjectPartSourcesContent(projectPart1); 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) TEST_F(PchCreator, Call)
{ {
auto content = creator.generateProjectPartSourcesContent(projectPart1); 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"));
} }
} }

View File

@@ -74,10 +74,10 @@ protected:
NiceMock<MockPchManagerClient> mockPchManagerClient; NiceMock<MockPchManagerClient> mockPchManagerClient;
SmallString projectPartId1 = "project1"; SmallString projectPartId1 = "project1";
SmallString projectPartId2 = "project2"; SmallString projectPartId2 = "project2";
PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp"; PathString main1Path = TESTDATA_DIR "/BuildDependencyCollector_main3.cpp";
PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString main2Path = TESTDATA_DIR "/BuildDependencyCollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; PathString header1Path = TESTDATA_DIR "/BuildDependencyCollector_header1.h";
PathString header2Path = TESTDATA_DIR "/includecollector_header2.h"; PathString header2Path = TESTDATA_DIR "/BuildDependencyCollector_header2.h";
ClangBackEnd::IdPaths idPath{projectPartId1, {1, 2}}; ClangBackEnd::IdPaths idPath{projectPartId1, {1, 2}};
ProjectPartContainer projectPart1{projectPartId1.clone(), ProjectPartContainer projectPart1{projectPartId1.clone(),
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},

View File

@@ -49,8 +49,8 @@ protected:
{"/yi"}, {"/yi"},
{{1, 1}}, {{1, 1}},
{{1, 2}}}; {{1, 2}}};
SourceEntries firstSources{{1, SourceType::Any, 1}, {2, SourceType::Any, 1}, {10, SourceType::Any, 1}}; SourceEntries firstSources{{1, SourceType::UserInclude, 1}, {2, SourceType::UserInclude, 1}, {10, SourceType::UserInclude, 1}};
BuildDependency buildDependency{firstSources, {}, {}, {}}; BuildDependency buildDependency{firstSources, {}};
}; };
TEST_F(PchTaskGenerator, Create) TEST_F(PchTaskGenerator, Create)

View File

@@ -162,7 +162,7 @@ protected:
ClangBackEnd::FilePathId main2PathId{filePathId(TESTDATA_DIR "/symbolindexer_main2.cpp")}; ClangBackEnd::FilePathId main2PathId{filePathId(TESTDATA_DIR "/symbolindexer_main2.cpp")};
ClangBackEnd::FilePathId header2PathId{filePathId(TESTDATA_DIR "/symbolindexer_header1.h")}; ClangBackEnd::FilePathId header2PathId{filePathId(TESTDATA_DIR "/symbolindexer_header1.h")};
ClangBackEnd::FilePathId header1PathId{filePathId(TESTDATA_DIR "/symbolindexer_header2.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; ClangBackEnd::FilePathId generatedFilePathId21;
ProjectPartContainer projectPart1{"project1", ProjectPartContainer projectPart1{"project1",
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},

View File

@@ -106,7 +106,8 @@ SOURCES += \
pchtaskgenerator-test.cpp \ pchtaskgenerator-test.cpp \
compilationdatabaseutils-test.cpp \ compilationdatabaseutils-test.cpp \
builddependenciesprovider-test.cpp \ builddependenciesprovider-test.cpp \
builddependenciesstorage-test.cpp builddependenciesstorage-test.cpp \
builddependencycollector-test.cpp
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
SOURCES += \ SOURCES += \
@@ -172,7 +173,6 @@ SOURCES += \
clangqueryprojectfindfilter-test.cpp \ clangqueryprojectfindfilter-test.cpp \
clangquery-test.cpp \ clangquery-test.cpp \
gtest-clang-printing.cpp \ gtest-clang-printing.cpp \
includecollector-test.cpp \
pchcreator-test.cpp \ pchcreator-test.cpp \
refactoringclientserverinprocess-test.cpp \ refactoringclientserverinprocess-test.cpp \
refactoringclient-test.cpp \ refactoringclient-test.cpp \
@@ -252,8 +252,8 @@ HEADERS += \
mocktaskscheduler.h \ mocktaskscheduler.h \
mockbuilddependenciesprovider.h \ mockbuilddependenciesprovider.h \
mockmodifiedtimechecker.h \ mockmodifiedtimechecker.h \
mockbuilddependenciesgenerator.h \ mockbuilddependenciesstorage.h \
mockbuilddependenciesstorage.h mockbuilddependencygenerator.h
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
HEADERS += \ HEADERS += \