diff --git a/src/libs/clangsupport/commandlinebuilder.h b/src/libs/clangsupport/commandlinebuilder.h index 6a9975a3ac9..df116197ab1 100644 --- a/src/libs/clangsupport/commandlinebuilder.h +++ b/src/libs/clangsupport/commandlinebuilder.h @@ -182,6 +182,13 @@ public: { CompilerMacros macros = compilerMacros; + macros.erase(std::remove_if(macros.begin(), + macros.end(), + [](const auto ¯o) { + return macro.type == CompilerMacroType::NotDefined; + }), + macros.end()); + std::sort(macros.begin(), macros.end(), [](const CompilerMacro &first, const CompilerMacro &second) { diff --git a/src/libs/clangsupport/compilermacro.h b/src/libs/clangsupport/compilermacro.h index ddba1a40762..798bab2ebd7 100644 --- a/src/libs/clangsupport/compilermacro.h +++ b/src/libs/clangsupport/compilermacro.h @@ -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(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(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; diff --git a/src/tools/clangpchmanagerbackend/source/pchtask.h b/src/tools/clangpchmanagerbackend/source/pchtask.h index 46c3bf2503f..c94d7ac8164 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtask.h +++ b/src/tools/clangpchmanagerbackend/source/pchtask.h @@ -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 diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp index 569e4a1d8a3..82584ad1dd8 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp @@ -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}, diff --git a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp index 9ace04e09de..636d9a32364 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp @@ -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>> +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 ¤tTask) { + 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 diff --git a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.h b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.h index 9c777b8a7cb..26df2022b4d 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.h +++ b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.h @@ -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; }; diff --git a/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h b/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h index e7969c4ea1b..0b39ae1f4f2 100644 --- a/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h +++ b/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h @@ -32,6 +32,27 @@ namespace ClangBackEnd { +template +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; }; diff --git a/src/tools/clangrefactoringbackend/source/usedmacro.h b/src/tools/clangrefactoringbackend/source/usedmacro.h index a7312b63761..8fc992e39b1 100644 --- a/src/tools/clangrefactoringbackend/source/usedmacro.h +++ b/src/tools/clangrefactoringbackend/source/usedmacro.h @@ -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; diff --git a/tests/unit/unittest/commandlinebuilder-test.cpp b/tests/unit/unittest/commandlinebuilder-test.cpp index f51a4f6a714..c3b60df3694 100644 --- a/tests/unit/unittest/commandlinebuilder-test.cpp +++ b/tests/unit/unittest/commandlinebuilder-test.cpp @@ -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 builder{this->emptyProjectInfo}; diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 682d28740b0..3901cb0d305 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -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) diff --git a/tests/unit/unittest/pchtaskgenerator-test.cpp b/tests/unit/unittest/pchtaskgenerator-test.cpp index 0b2ec3968e3..a3ebb3c17be 100644 --- a/tests/unit/unittest/pchtaskgenerator-test.cpp +++ b/tests/unit/unittest/pchtaskgenerator-test.cpp @@ -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}, diff --git a/tests/unit/unittest/pchtasksmerger-test.cpp b/tests/unit/unittest/pchtasksmerger-test.cpp index f54e7aca582..e878438f339 100644 --- a/tests/unit/unittest/pchtasksmerger-test.cpp +++ b/tests/unit/unittest/pchtasksmerger-test.cpp @@ -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 diff --git a/tests/unit/unittest/usedmacrofilter-test.cpp b/tests/unit/unittest/usedmacrofilter-test.cpp index bc5b79cccf5..b02cd7e5e02 100644 --- a/tests/unit/unittest/usedmacrofilter-test.cpp +++ b/tests/unit/unittest/usedmacrofilter-test.cpp @@ -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