yql_issue_utils.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include "yql_issue_utils.h"
  2. #include <util/system/yassert.h>
  3. #include <tuple>
  4. #include <list>
  5. #include <algorithm>
  6. #include <deque>
  7. namespace NYql {
  8. TIssue TruncateIssueLevels(const TIssue& topIssue, TTruncateIssueOpts opts) {
  9. // [issue, level, parent, visibleParent]
  10. std::list<std::tuple<const TIssue*, ui32, size_t, size_t>> issueQueue;
  11. // [issue, targetIssue, level, parent, visible, visibleParent, targetSkipIssue]
  12. std::deque<std::tuple<const TIssue*, TIssue*, ui32, size_t, bool, size_t, TIssue*>> issues;
  13. // [depth from bottom, position]
  14. std::list<size_t> leafs;
  15. const auto depthBeforeLeaf = std::max(opts.KeepTailLevels, ui32(1)) - 1;
  16. const auto maxLevels = std::max(opts.MaxLevels - std::min(opts.MaxLevels, depthBeforeLeaf + 1), ui32(1));
  17. issueQueue.emplace_front(&topIssue, 0, 0, 0);
  18. while (!issueQueue.empty()) {
  19. const auto issue = std::get<0>(issueQueue.back());
  20. const auto level = std::get<1>(issueQueue.back());
  21. const auto parent = std::get<2>(issueQueue.back());
  22. const auto visibleParent = std::get<3>(issueQueue.back());
  23. issueQueue.pop_back();
  24. const bool visible = issue->GetSubIssues().empty() || level < maxLevels;
  25. const auto pos = issues.size();
  26. issues.emplace_back(issue, nullptr, level, parent, visible, visibleParent, nullptr);
  27. if (issue->GetSubIssues().empty()) {
  28. if (level != 0) {
  29. leafs.push_back(pos);
  30. }
  31. } else {
  32. for (auto subIssue : issue->GetSubIssues()) {
  33. issueQueue.emplace_front(subIssue.Get(), level + 1, pos, visible ? pos : visibleParent);
  34. }
  35. }
  36. }
  37. if (depthBeforeLeaf && !leafs.empty()) {
  38. for (size_t pos: leafs) {
  39. ui32 depth = depthBeforeLeaf;
  40. auto parent = std::get<3>(issues.at(pos));
  41. while (depth && parent) {
  42. auto& visible = std::get<4>(issues.at(parent));
  43. auto& visibleParent = std::get<5>(issues.at(pos));
  44. if (!visible || visibleParent != parent) {
  45. visible = true;
  46. visibleParent = parent; // Update visible parent
  47. --depth;
  48. pos = parent;
  49. parent = std::get<3>(issues.at(parent));
  50. } else {
  51. break;
  52. }
  53. }
  54. }
  55. }
  56. leafs.clear();
  57. TIssue result;
  58. for (auto& i: issues) {
  59. const auto srcIssue = std::get<0>(i);
  60. auto& targetIssue = std::get<1>(i);
  61. const auto level = std::get<2>(i);
  62. const auto parent = std::get<3>(i);
  63. const auto visible = std::get<4>(i);
  64. const auto visibleParent = std::get<5>(i);
  65. if (0 == level) {
  66. targetIssue = &result;
  67. targetIssue->CopyWithoutSubIssues(*srcIssue);
  68. } else if (visible) {
  69. auto& parentRec = issues.at(visibleParent);
  70. auto& parentTargetIssue = std::get<1>(parentRec);
  71. if (parent != visibleParent) {
  72. auto& parentSkipIssue = std::get<6>(parentRec);
  73. if (!parentSkipIssue) {
  74. const auto parentIssue = std::get<0>(parentRec);
  75. auto newIssue = MakeIntrusive<TIssue>("(skipped levels)");
  76. newIssue->SetCode(parentIssue->GetCode(), parentIssue->GetSeverity());
  77. parentTargetIssue->AddSubIssue(newIssue);
  78. parentSkipIssue = newIssue.Get();
  79. }
  80. auto newIssue = MakeIntrusive<TIssue>(TString{});
  81. newIssue->CopyWithoutSubIssues(*srcIssue);
  82. parentSkipIssue->AddSubIssue(newIssue);
  83. targetIssue = newIssue.Get();
  84. } else {
  85. auto newIssue = MakeIntrusive<TIssue>(TString{});
  86. newIssue->CopyWithoutSubIssues(*srcIssue);
  87. parentTargetIssue->AddSubIssue(newIssue);
  88. targetIssue = newIssue.Get();
  89. }
  90. }
  91. }
  92. return result;
  93. }
  94. } // namspace NYql