ClangPchManager: Merge system pch tasks

The merging of the include search paths is quite heuristic but we could
provide an option to disable pch merging so users can decide themselves.
Maybe we could give user feedback why we cannot merge but this is quite
advanced.

Task-number: QTCREATORBUG-21381
Change-Id: Iac6af0c587b631d2151f63d6d97215ed6919819f
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2019-01-30 18:48:59 +01:00
parent 14a44948d8
commit 0082a82fc6
13 changed files with 544 additions and 121 deletions

View File

@@ -182,6 +182,13 @@ public:
{
CompilerMacros macros = compilerMacros;
macros.erase(std::remove_if(macros.begin(),
macros.end(),
[](const auto &macro) {
return macro.type == CompilerMacroType::NotDefined;
}),
macros.end());
std::sort(macros.begin(),
macros.end(),
[](const CompilerMacro &first, const CompilerMacro &second) {

View File

@@ -31,6 +31,8 @@
namespace ClangBackEnd {
enum class CompilerMacroType : unsigned char { Define, NotDefined };
class CompilerMacro
{
public:
@@ -40,39 +42,57 @@ public:
: key(std::move(key))
, value(std::move(value))
, index(index)
, type(CompilerMacroType::Define)
{}
CompilerMacro(Utils::SmallString &&key)
: key(std::move(key))
{}
CompilerMacro(const Utils::SmallString &key)
: key(key)
{}
friend QDataStream &operator<<(QDataStream &out, const CompilerMacro &compilerMacro)
{
out << compilerMacro.key;
out << compilerMacro.value;
out << compilerMacro.index;
out << static_cast<unsigned char>(compilerMacro.type);
return out;
}
friend QDataStream &operator>>(QDataStream &in, CompilerMacro &compilerMacro)
{
unsigned char type;
in >> compilerMacro.key;
in >> compilerMacro.value;
in >> compilerMacro.index;
in >> type;
compilerMacro.type = static_cast<CompilerMacroType>(type);
return in;
}
friend bool operator==(const CompilerMacro &first, const CompilerMacro &second)
{
return first.key == second.key
&& first.value == second.value;
return first.key == second.key && first.value == second.value && first.type == second.type;
}
friend bool operator<(const CompilerMacro &first, const CompilerMacro &second)
{
return std::tie(first.key, first.value) < std::tie(second.key, second.value);
return std::tie(first.key, first.type, first.value)
< std::tie(second.key, second.type, second.value);
}
public:
Utils::SmallString key;
Utils::SmallString value;
int index = 0;
int index = -1;
CompilerMacroType type = CompilerMacroType::NotDefined;
};
using CompilerMacros = std::vector<CompilerMacro>;

View File

@@ -43,7 +43,7 @@ public:
FilePathIds &&includes,
FilePathIds &&allIncludes,
CompilerMacros &&compilerMacros,
UsedMacros &&usedMacros,
Utils::SmallStringVector &&usedMacros,
Utils::SmallStringVector toolChainArguments,
IncludeSearchPaths systemIncludeSearchPaths,
IncludeSearchPaths projectIncludeSearchPaths,
@@ -54,7 +54,6 @@ public:
, includes(includes)
, allIncludes(allIncludes)
, compilerMacros(compilerMacros)
, usedMacros(usedMacros)
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
, toolChainArguments(std::move(toolChainArguments))
@@ -67,7 +66,7 @@ public:
FilePathIds &&includes,
FilePathIds &&allIncludes,
CompilerMacros &&compilerMacros,
UsedMacros &&usedMacros,
Utils::SmallStringVector &&usedMacros,
Utils::SmallStringVector toolChainArguments,
IncludeSearchPaths systemIncludeSearchPaths,
IncludeSearchPaths projectIncludeSearchPaths,
@@ -78,7 +77,6 @@ public:
, includes(includes)
, allIncludes(allIncludes)
, compilerMacros(compilerMacros)
, usedMacros(usedMacros)
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
, toolChainArguments(std::move(toolChainArguments))
@@ -92,7 +90,6 @@ public:
return first.systemPchPath == second.systemPchPath
&& first.projectPartIds == second.projectPartIds && first.includes == second.includes
&& first.compilerMacros == second.compilerMacros
&& first.usedMacros == second.usedMacros
&& first.systemIncludeSearchPaths == second.systemIncludeSearchPaths
&& first.projectIncludeSearchPaths == second.projectIncludeSearchPaths
&& first.toolChainArguments == second.toolChainArguments
@@ -109,13 +106,13 @@ public:
FilePathIds includes;
FilePathIds allIncludes;
CompilerMacros compilerMacros;
UsedMacros usedMacros;
IncludeSearchPaths systemIncludeSearchPaths;
IncludeSearchPaths projectIncludeSearchPaths;
Utils::SmallStringVector toolChainArguments;
Utils::Language language = Utils::Language::Cxx;
Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98;
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None;
bool isMerged = false;
};
class PchTaskSet

View File

@@ -42,9 +42,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
for (auto &projectPart : projectParts) {
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart);
UsedMacroFilter filter{buildDependency.includes, buildDependency.usedMacros};
filter.filter(projectPart.compilerMacros);
UsedMacroFilter filter{buildDependency.includes,
buildDependency.usedMacros,
projectPart.compilerMacros};
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId.clone(),
std::move(filter.topSystemIncludes),
@@ -53,7 +53,7 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
std::move(filter.systemUsedMacros),
projectPart.toolChainArguments,
projectPart.systemIncludeSearchPaths,
projectPart.projectIncludeSearchPaths,
{},
projectPart.language,
projectPart.languageVersion,
projectPart.languageExtension},

View File

@@ -30,20 +30,10 @@
namespace ClangBackEnd {
void PchTasksMerger::mergeTasks(PchTaskSets &&taskSets,
Utils::SmallStringVector &&/*toolChainArguments*/)
Utils::SmallStringVector && /*toolChainArguments*/)
{
PchTasks systemTasks;
systemTasks.reserve(taskSets.size());
PchTasks projectTasks;
projectTasks.reserve(taskSets.size());
for (PchTaskSet &taskSet : taskSets) {
projectTasks.push_back(std::move(taskSet.project));
systemTasks.push_back(std::move(taskSet.system));
}
m_pchTaskQueue.addSystemPchTasks(std::move(systemTasks));
m_pchTaskQueue.addProjectPchTasks(std::move(projectTasks));
mergeSystemTasks(taskSets);
addProjectTasksToQueue(taskSets);
m_pchTaskQueue.processEntries();
}
@@ -52,4 +42,117 @@ void PchTasksMerger::removePchTasks(const Utils::SmallStringVector &projectPartI
m_pchTaskQueue.removePchTasks(projectPartIds);
}
template<typename Container, typename Result = std::remove_const_t<std::remove_reference_t<Container>>>
Result merge(Container &&first, Container &&second)
{
Result result;
result.reserve(first.size() + second.size());
std::set_union(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()),
std::make_move_iterator(second.begin()),
std::make_move_iterator(second.end()),
std::back_inserter(result));
return result;
}
CompilerMacros PchTasksMerger::mergeMacros(const CompilerMacros &firstCompilerMacros,
const CompilerMacros &secondCompilerMacros)
{
return merge(firstCompilerMacros, secondCompilerMacros);
}
bool PchTasksMerger::hasDuplicates(const CompilerMacros &compilerMacros)
{
auto found = std::adjacent_find(compilerMacros.begin(),
compilerMacros.end(),
[](const CompilerMacro &first, const CompilerMacro &second) {
return first.key == second.key;
});
return found == compilerMacros.end();
}
IncludeSearchPaths mergeIncludeSearchPaths(IncludeSearchPaths &&first, IncludeSearchPaths &&second)
{
if (first.size() > second.size())
return merge(first, second);
return merge(first, second);
}
bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask)
{
if (firstTask.language != secondTask.language || firstTask.isMerged || secondTask.isMerged)
return false;
CompilerMacros macros = mergeMacros(firstTask.compilerMacros, secondTask.compilerMacros);
secondTask.isMerged = hasDuplicates(macros);
if (secondTask.isMerged && firstTask.language == secondTask.language) {
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
std::move(secondTask.projectPartIds));
firstTask.includes = merge(std::move(firstTask.includes), std::move(secondTask.includes));
firstTask.allIncludes = merge(std::move(firstTask.allIncludes),
std::move(secondTask.allIncludes));
firstTask.compilerMacros = std::move(macros);
firstTask.systemIncludeSearchPaths = mergeIncludeSearchPaths(
std::move(firstTask.systemIncludeSearchPaths),
std::move(secondTask.systemIncludeSearchPaths));
firstTask.languageVersion = std::max(firstTask.languageVersion, secondTask.languageVersion);
firstTask.languageExtension = firstTask.languageExtension | secondTask.languageExtension;
}
return secondTask.isMerged;
}
void PchTasksMerger::mergePchTasks(PchTasks &tasks)
{
auto begin = tasks.begin();
while (begin != tasks.end()) {
begin = std::find_if(begin, tasks.end(), [](const auto &task) { return !task.isMerged; });
if (begin != tasks.end()) {
PchTask &baseTask = *begin;
++begin;
std::for_each(begin, tasks.end(), [&](PchTask &currentTask) {
mergePchTasks(baseTask, currentTask);
});
}
}
}
void PchTasksMerger::addProjectTasksToQueue(PchTaskSets &taskSets)
{
PchTasks projectTasks;
projectTasks.reserve(taskSets.size());
for (PchTaskSet &taskSet : taskSets)
projectTasks.push_back(std::move(taskSet.project));
m_pchTaskQueue.addProjectPchTasks(std::move(projectTasks));
}
void PchTasksMerger::mergeSystemTasks(PchTaskSets &taskSets)
{
PchTasks systemTasks;
systemTasks.reserve(taskSets.size());
for (PchTaskSet &taskSet : taskSets)
systemTasks.push_back(std::move(taskSet.system));
mergePchTasks(systemTasks);
systemTasks.erase(std::remove_if(systemTasks.begin(),
systemTasks.end(),
[](const PchTask &task) { return task.isMerged; }),
systemTasks.end());
m_pchTaskQueue.addSystemPchTasks(std::move(systemTasks));
}
} // namespace ClangBackEnd

View File

@@ -32,7 +32,7 @@ namespace ClangBackEnd {
class PchTaskQueueInterface;
class PchTasksMerger : public PchTasksMergerInterface
class PchTasksMerger final : public PchTasksMergerInterface
{
public:
PchTasksMerger(PchTaskQueueInterface &pchTaskQueue)
@@ -42,6 +42,18 @@ public:
void mergeTasks(PchTaskSets &&taskSets, Utils::SmallStringVector &&toolChainArguments) override;
void removePchTasks(const Utils::SmallStringVector &projectPartIds) override;
static CompilerMacros mergeMacros(const CompilerMacros &firstCompilerMacros,
const CompilerMacros &secondCompilerMacros);
static bool hasDuplicates(const CompilerMacros &compilerMacros);
static bool mergePchTasks(PchTask &first, PchTask &second);
static void mergePchTasks(PchTasks &tasks);
private:
void addProjectTasksToQueue(PchTaskSets &taskSets);
void mergeSystemTasks(PchTaskSets &taskSets);
private:
PchTaskQueueInterface &m_pchTaskQueue;
};

View File

@@ -32,6 +32,27 @@
namespace ClangBackEnd {
template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
inline OutputIterator set_greedy_intersection(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
InputIterator2 last2,
OutputIterator result,
Compare comp)
{
while (first1 != last1 && first2 != last2)
if (comp(*first1, *first2))
++first1;
else if (comp(*first2, *first1))
++first2;
else {
*result = *first1;
++first1;
++result;
}
return result;
}
class UsedMacroFilter
{
public:
@@ -41,11 +62,14 @@ public:
FilePathIds system;
};
UsedMacroFilter(const SourceEntries &includes, const UsedMacros &usedMacros)
UsedMacroFilter(const SourceEntries &includes,
const UsedMacros &usedMacros,
const CompilerMacros &compilerMacros)
{
filterIncludes(includes);
systemUsedMacros = filterUsedMarcos(usedMacros, systemIncludes);
projectUsedMacros = filterUsedMarcos(usedMacros, projectIncludes);
filter(compilerMacros);
}
void filterIncludes(const SourceEntries &includes)
@@ -98,7 +122,8 @@ private:
allIncludes.emplace_back(include.sourceId);
}
static UsedMacros filterUsedMarcos(const UsedMacros &usedMacros, const FilePathIds &filePathId)
static Utils::SmallStringVector filterUsedMarcos(const UsedMacros &usedMacros,
const FilePathIds &filePathId)
{
struct Compare
{
@@ -113,52 +138,57 @@ private:
}
};
UsedMacros filtertedMacros;
Utils::SmallStringVector filtertedMacros;
filtertedMacros.reserve(usedMacros.size());
std::set_intersection(usedMacros.begin(),
usedMacros.end(),
filePathId.begin(),
filePathId.end(),
std::back_inserter(filtertedMacros),
Compare{});
set_greedy_intersection(usedMacros.begin(),
usedMacros.end(),
filePathId.begin(),
filePathId.end(),
std::back_inserter(filtertedMacros),
Compare{});
std::sort(filtertedMacros.begin(),
filtertedMacros.end(),
[](const UsedMacro &first, const UsedMacro &second) {
return first.macroName < second.macroName;
});
std::sort(filtertedMacros.begin(), filtertedMacros.end());
return filtertedMacros;
}
static CompilerMacros filtercompilerMacros(const CompilerMacros &indexedCompilerMacro,
const UsedMacros &usedMacros)
const Utils::SmallStringVector &usedMacros)
{
CompilerMacros filtertedCompilerMacros;
filtertedCompilerMacros.reserve(indexedCompilerMacro.size() + usedMacros.size());
struct Compare
{
bool operator()(const UsedMacro &usedMacro,
const CompilerMacro &compileMacro)
bool operator()(const CompilerMacro &compilerMacro, Utils::SmallStringView usedMacro)
{
return usedMacro.macroName < compileMacro.key;
return compilerMacro.key < usedMacro;
}
bool operator()(const CompilerMacro &compileMacro,
const UsedMacro &usedMacro)
bool operator()(Utils::SmallStringView usedMacro, const CompilerMacro &compilerMacro)
{
return compileMacro.key < usedMacro.macroName;
return usedMacro < compilerMacro.key;
}
};
CompilerMacros filtertedCompilerMacros;
filtertedCompilerMacros.reserve(indexedCompilerMacro.size());
set_greedy_intersection(indexedCompilerMacro.begin(),
indexedCompilerMacro.end(),
usedMacros.begin(),
usedMacros.end(),
std::back_inserter(filtertedCompilerMacros),
Compare{});
std::set_intersection(indexedCompilerMacro.begin(),
indexedCompilerMacro.end(),
usedMacros.begin(),
usedMacros.end(),
std::back_inserter(filtertedCompilerMacros),
Compare{});
auto split = filtertedCompilerMacros.end();
std::set_difference(usedMacros.begin(),
usedMacros.end(),
filtertedCompilerMacros.begin(),
filtertedCompilerMacros.end(),
std::back_inserter(filtertedCompilerMacros),
Compare{});
std::inplace_merge(filtertedCompilerMacros.begin(), split, filtertedCompilerMacros.end());
return filtertedCompilerMacros;
}
@@ -169,8 +199,8 @@ public:
FilePathIds systemIncludes;
FilePathIds topProjectIncludes;
FilePathIds topSystemIncludes;
UsedMacros projectUsedMacros;
UsedMacros systemUsedMacros;
Utils::SmallStringVector projectUsedMacros;
Utils::SmallStringVector systemUsedMacros;
CompilerMacros projectCompilerMacros;
CompilerMacros systemCompilerMacros;
};

View File

@@ -62,6 +62,10 @@ public:
{
return !(first == second);
}
operator Utils::SmallStringView() const { return macroName; }
operator const Utils::SmallString &() const { return macroName; }
public:
Utils::SmallString macroName;
FilePathId filePathId;

View File

@@ -511,7 +511,7 @@ TYPED_TEST(CommandLineBuilder, IncludePchPath)
TYPED_TEST(CommandLineBuilder, CompilerMacros)
{
this->emptyProjectInfo.compilerMacros = {{"YI", "1", 2}, {"ER", "2", 1}};
this->emptyProjectInfo.compilerMacros = {{"YI", "1", 2}, {"ER", "2", 1}, {"SAN"}};
Builder<TypeParam> builder{this->emptyProjectInfo};

View File

@@ -1157,10 +1157,9 @@ std::ostream &operator<<(std::ostream &out, const PchCreatorIncludes &includes)
std::ostream &operator<<(std::ostream &out, const PchTask &task)
{
return out << "(" << task.projectPartIds << ", " << task.includes << ", " << task.compilerMacros
<< ", " << task.usedMacros << ", " << toText(task.language) << ", "
<< task.systemIncludeSearchPaths << ", " << task.projectIncludeSearchPaths << ", "
<< task.toolChainArguments << ", " << toText(task.languageVersion) << ", "
<< toText(task.languageExtension) << ")";
<< toText(task.language) << ", " << task.systemIncludeSearchPaths << ", "
<< task.projectIncludeSearchPaths << ", " << task.toolChainArguments << ", "
<< toText(task.languageVersion) << ", " << toText(task.languageExtension) << ")";
}
std::ostream &operator<<(std::ostream &out, const PchTaskSet &taskSet)

View File

@@ -99,7 +99,6 @@ TEST_F(PchTaskGenerator, AddProjectParts)
Field(&PchTask::allIncludes, IsEmpty()),
Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})),
Field(&PchTask::usedMacros, ElementsAre(UsedMacro{"SE", 4}, UsedMacro{"WU", 5})),
Field(&PchTask::systemIncludeSearchPaths,
ElementsAre(
IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
@@ -120,7 +119,6 @@ TEST_F(PchTaskGenerator, AddProjectParts)
Field(&PchTask::allIncludes, ElementsAre(1, 2, 3, 4, 5)),
Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})),
Field(&PchTask::usedMacros, ElementsAre(UsedMacro{"YI", 1}, UsedMacro{"SAN", 3})),
Field(&PchTask::systemIncludeSearchPaths,
ElementsAre(
IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},

View File

@@ -31,11 +31,14 @@
namespace {
using ClangBackEnd::CompilerMacro;
using ClangBackEnd::CompilerMacros;
using ClangBackEnd::IncludeSearchPath;
using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::PchTask;
using ClangBackEnd::PchTaskSet;
using Merger = ClangBackEnd::PchTasksMerger;
using Id = ClangBackEnd::FilePathId;
class PchTasksMerger : public testing::Test
{
protected:
@@ -51,48 +54,58 @@ protected:
ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue};
PchTask systemTask1{"ProjectPart1",
{1, 2},
{1, 2},
{1, 2, 3},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}},
{"YI", "LIANG"},
{"--yi"},
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
{{"/system/path", 2, IncludeSearchPathType::System},
{"/builtin/path2", 3, IncludeSearchPathType::BuiltIn},
{"/framework/path", 1, IncludeSearchPathType::System}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask projectTask1{"ProjectPart1",
{11, 12},
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}},
{"ER", "SAN"},
{"--yi"},
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
{{"/system/path", 1, IncludeSearchPathType::System},
{"/builtin/path", 2, IncludeSearchPathType::BuiltIn}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask2{"ProjectPart2",
{1, 2},
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}},
{11, 12},
{11, 12, 13},
{{"SE", "4", 4}, {"WU", "5", 5}},
{"ER", "SAN"},
{"--yi"},
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
{{"/system/path", 2, IncludeSearchPathType::System},
{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
{"/framework/path", 1, IncludeSearchPathType::System}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask projectTask2{"ProjectPart2",
{11, 12},
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}},
{"ER", "SAN"},
{"--yi"},
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
{{"/system/path", 2, IncludeSearchPathType::System},
{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
{"/framework/path", 1, IncludeSearchPathType::System}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask3{"ProjectPart3",
{1, 2},
{1, 2},
{{"YI", "2", 1}, {"SAN", "3", 3}},
{"YI", "LIANG"},
{"--yi"},
{{"/system/path", 2, IncludeSearchPathType::System},
{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
{"/framework/path", 1, IncludeSearchPathType::System}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
Utils::SmallStringVector toolChainArguments = {"toolChainArguments"};
};
@@ -103,21 +116,33 @@ TEST_F(PchTasksMerger, AddProjectTasks)
EXPECT_CALL(mockPchTaskQueue, addProjectPchTasks(ElementsAre(projectTask1, projectTask2)));
EXPECT_CALL(mockPchTaskQueue, processEntries());
merger.mergeTasks(
{{clone(systemTask1), clone(projectTask1)}, {clone(systemTask1), clone(projectTask2)}},
std::move(toolChainArguments));
merger.mergeTasks({{clone(systemTask1), clone(projectTask1)},
{clone(systemTask1), clone(projectTask2)}},
std::move(toolChainArguments));
}
TEST_F(PchTasksMerger, AddSystemTasks)
{
InSequence s;
EXPECT_CALL(mockPchTaskQueue, addSystemPchTasks(ElementsAre(systemTask1, systemTask2)));
EXPECT_CALL(mockPchTaskQueue, addSystemPchTasks(ElementsAre(_, systemTask3)));
EXPECT_CALL(mockPchTaskQueue, processEntries());
merger.mergeTasks(
{{clone(systemTask1), clone(projectTask1)}, {clone(systemTask2), clone(projectTask2)}},
std::move(toolChainArguments));
merger.mergeTasks({{clone(systemTask1), clone(projectTask1)},
{clone(systemTask2), clone(projectTask2)},
{clone(systemTask3), clone(projectTask2)}},
std::move(toolChainArguments));
}
TEST_F(PchTasksMerger, AddSystemOnlyOneTask)
{
InSequence s;
EXPECT_CALL(mockPchTaskQueue, addSystemPchTasks(ElementsAre(systemTask1)));
EXPECT_CALL(mockPchTaskQueue, processEntries());
merger.mergeTasks({{clone(systemTask1), clone(projectTask1)}},
std::move(toolChainArguments));
}
TEST_F(PchTasksMerger, RemoveTasks)
@@ -126,4 +151,233 @@ TEST_F(PchTasksMerger, RemoveTasks)
merger.removePchTasks({"project1", "project2"});
}
TEST_F(PchTasksMerger, MergeMacros)
{
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"YI"}, {"SAN", "3", 3}};
CompilerMacros compilerMacros2{{"BA"}, {"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
auto macros = Merger::mergeMacros(compilerMacros1, compilerMacros2);
ASSERT_THAT(macros,
ElementsAre(CompilerMacro{"BA"},
CompilerMacro{"ER", "2", 2},
CompilerMacro{"SE", "4", 1},
CompilerMacro{"YI", "1", 1},
CompilerMacro{"YI"},
CompilerMacro{"SAN", "3", 3}));
}
TEST_F(PchTasksMerger, MacrosCanBeMerged)
{
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"QI"}, {"SE", "4", 1}, {"SAN", "3", 3}};
CompilerMacros compilerMacros2{{"BA"}, {"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
ASSERT_TRUE(canBeMerged);
}
TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseDifferentValue)
{
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"SAN", "3", 3}};
CompilerMacros compilerMacros2{{"ER", "1", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
ASSERT_FALSE(canBeMerged);
}
TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseUndefinedMacro)
{
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"YI"}, {"SAN", "3", 3}};
CompilerMacros compilerMacros2{{"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
ASSERT_FALSE(canBeMerged);
}
TEST_F(PchTasksMerger, CanMergePchTasks)
{
auto canBeMerged = Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_TRUE(canBeMerged);
}
TEST_F(PchTasksMerger, CannotMergePchTasks)
{
auto canBeMerged = Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_FALSE(canBeMerged);
}
TEST_F(PchTasksMerger, IsMergedIsSet)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_TRUE(systemTask2.isMerged);
}
TEST_F(PchTasksMerger, IsMergedIsNotSet)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_FALSE(systemTask3.isMerged);
}
TEST_F(PchTasksMerger, DontMergeLanguage)
{
systemTask2.language = Utils::Language::C;
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_FALSE(systemTask2.isMerged);
}
TEST_F(PchTasksMerger, MergeCompilerMacros)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.compilerMacros,
ElementsAre(CompilerMacro{"SE", "4", 4},
CompilerMacro{"WU", "5", 5},
CompilerMacro{"YI", "1", 1},
CompilerMacro{"SAN", "3", 3}));
}
TEST_F(PchTasksMerger, DontMergeCompilerMacros)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.compilerMacros,
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3}));
}
TEST_F(PchTasksMerger, MergeIncludes)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2, 11, 12));
}
TEST_F(PchTasksMerger, DontMergeIncludes)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2));
}
TEST_F(PchTasksMerger, MergeAllIncludes)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.allIncludes, ElementsAre(1, 2, 3, 11, 12, 13));
}
TEST_F(PchTasksMerger, DontAllMergeIncludes)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.allIncludes, ElementsAre(1, 2, 3));
}
TEST_F(PchTasksMerger, MergeProjectIds)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre("ProjectPart1", "ProjectPart2"));
}
TEST_F(PchTasksMerger, DontMergeProjectIds)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre("ProjectPart1"));
}
TEST_F(PchTasksMerger, MergeIncludeSearchPaths)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.systemIncludeSearchPaths,
ElementsAre(IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/builtin/path2", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}));
}
TEST_F(PchTasksMerger, DontMergeIncludeSearchPaths)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.systemIncludeSearchPaths,
ElementsAre(IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
IncludeSearchPath{"/builtin/path2", 3, IncludeSearchPathType::BuiltIn},
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}));
}
TEST_F(PchTasksMerger, ChooseLanguageVersionFromFirstTask)
{
systemTask2.languageVersion = Utils::LanguageVersion::CXX17;
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.languageVersion, Utils::LanguageVersion::CXX17);
}
TEST_F(PchTasksMerger, ChooseLanguageVersionFromSecondTask)
{
systemTask1.languageVersion = Utils::LanguageVersion::CXX17;
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.languageVersion, Utils::LanguageVersion::CXX17);
}
TEST_F(PchTasksMerger, DontChooseLanguageVersion)
{
systemTask3.languageVersion = Utils::LanguageVersion::CXX17;
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.languageVersion, Utils::LanguageVersion::CXX98);
}
TEST_F(PchTasksMerger, FirstTaskIsNotMergedAgain)
{
systemTask1.isMerged = true;
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_FALSE(systemTask2.isMerged);
}
TEST_F(PchTasksMerger, DontMergeAlreadyMergedFirstTask)
{
systemTask1.isMerged = true;
bool isMerged = Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_FALSE(isMerged);
}
TEST_F(PchTasksMerger, SecondTaskIsNotMergedAgain)
{
systemTask2.isMerged = true;
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2));
}
TEST_F(PchTasksMerger, DontMergeAlreadyMergedSecondTask)
{
systemTask2.isMerged = true;
bool isMerged = Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_FALSE(isMerged);
}
} // namespace

View File

@@ -46,7 +46,7 @@ protected:
{3, SourceType::ProjectInclude, 0},
{4, SourceType::TopSystemInclude, 0},
{5, SourceType::TopProjectInclude, 0}};
UsedMacros usedMacros{{"YI", 1}, {"ER", 2}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
UsedMacros usedMacros{{"YI", 1}, {"ER", 2}, {"LIU", 2}, {"QI", 3}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
CompilerMacros compileMacros{{"YI", "1", 1},
{"ER", "2", 2},
{"SAN", "3", 3},
@@ -57,36 +57,35 @@ protected:
TEST_F(UsedMacroFilter, SystemIncludes)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.systemIncludes, ElementsAre(FilePathId{2}, FilePathId{4}));
}
TEST_F(UsedMacroFilter, ProjectIncludes)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.projectIncludes, ElementsAre(FilePathId{3}, FilePathId{5}));
}
TEST_F(UsedMacroFilter, TopSystemIncludes)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.topSystemIncludes, ElementsAre(FilePathId{4}));
}
TEST_F(UsedMacroFilter, TopProjectIncludes)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.topProjectIncludes, ElementsAre(FilePathId{5}));
}
TEST_F(UsedMacroFilter, AllIncludes)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.allIncludes,
ElementsAre(FilePathId{1}, FilePathId{2}, FilePathId{3}, FilePathId{4}, FilePathId{5}));
@@ -94,36 +93,36 @@ TEST_F(UsedMacroFilter, AllIncludes)
TEST_F(UsedMacroFilter, SystemUsedMacros)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.systemUsedMacros, ElementsAre(UsedMacro{"ER", 2}, UsedMacro{"SE", 4}));
ASSERT_THAT(filter.systemUsedMacros, ElementsAre("ER", "SE", "LIU"));
}
TEST_F(UsedMacroFilter, ProjectUsedMacros)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.projectUsedMacros, ElementsAre(UsedMacro{"WU", 5}, UsedMacro{"SAN", 3}));
ASSERT_THAT(filter.projectUsedMacros, ElementsAre("QI", "WU", "SAN"));
}
TEST_F(UsedMacroFilter, SystemCompileMacros)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
filter.filter(compileMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.systemCompilerMacros,
ElementsAre(CompilerMacro{"ER", "2", 2}, CompilerMacro{"SE", "4", 4}));
ElementsAre(CompilerMacro{"ER", "2", 2},
CompilerMacro{"SE", "4", 4},
CompilerMacro{"LIU"}));
}
TEST_F(UsedMacroFilter, ProjectCompileMacros)
{
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
filter.filter(compileMacros);
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
ASSERT_THAT(filter.projectCompilerMacros,
ElementsAre(CompilerMacro{"WU", "5", 5}, CompilerMacro{"SAN", "3", 3}));
ElementsAre(CompilerMacro{"QI"},
CompilerMacro{"WU", "5", 5},
CompilerMacro{"SAN", "3", 3}));
}
} // namespace