yql_issue_manager.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include "yql_issue_manager.h"
  2. #include <util/string/cast.h>
  3. #include <util/string/builder.h>
  4. using namespace NYql;
  5. void TIssueManager::AddScope(std::function<TIssuePtr()> fn) {
  6. RawIssues_.emplace(std::make_pair(TMaybe<TIssuePtr>(), fn));
  7. }
  8. void TIssueManager::LeaveScope() {
  9. Y_ASSERT(HasOpenScopes());
  10. if (RawIssues_.size() == 1) {
  11. // Last scope, just dump it
  12. auto maybeIssue = RawIssues_.top().first;
  13. if (maybeIssue) {
  14. if ((*maybeIssue)->GetCode() == Max<ui32>()) {
  15. for (const auto& nestedIssue : (*maybeIssue.Get())->GetSubIssues()) {
  16. CompletedIssues_.AddIssue(*nestedIssue);
  17. }
  18. } else {
  19. CompletedIssues_.AddIssue(**maybeIssue);
  20. }
  21. }
  22. RawIssues_.pop();
  23. return;
  24. }
  25. if (RawIssues_.top().first.Empty()) {
  26. // No issues in this scope
  27. RawIssues_.pop();
  28. return;
  29. }
  30. auto subIssue = *RawIssues_.top().first;
  31. if (subIssue->GetSubIssues().size() == 1) {
  32. auto nestedIssue = subIssue->GetSubIssues().front();
  33. if (!nestedIssue->GetSubIssues().empty() && nestedIssue->Position == subIssue->Position && nestedIssue->EndPosition == subIssue->EndPosition) {
  34. auto msg = subIssue->GetMessage();
  35. if (nestedIssue->GetMessage()) {
  36. if (msg) {
  37. msg.append(", ");
  38. }
  39. msg.append(nestedIssue->GetMessage());
  40. }
  41. subIssue = nestedIssue;
  42. subIssue->SetMessage(msg);
  43. }
  44. }
  45. RawIssues_.pop();
  46. if (RawIssues_.top().first.Empty()) {
  47. RawIssues_.top().first = RawIssues_.top().second();
  48. if (!*RawIssues_.top().first) {
  49. RawIssues_.top().first = new TIssue();
  50. (*RawIssues_.top().first)->SetCode(Max<ui32>(), ESeverity::TSeverityIds_ESeverityId_S_INFO);
  51. } else {
  52. (*RawIssues_.top().first)->Severity = ESeverity::TSeverityIds_ESeverityId_S_INFO;
  53. }
  54. }
  55. if (subIssue->GetCode() == Max<ui32>()) {
  56. for (const auto& nestedIssue : subIssue->GetSubIssues()) {
  57. RawIssues_.top().first->Get()->AddSubIssue(nestedIssue);
  58. }
  59. } else {
  60. RawIssues_.top().first->Get()->AddSubIssue(subIssue);
  61. }
  62. }
  63. void TIssueManager::RaiseIssueForEmptyScope() {
  64. if (RawIssues_.top().first.Empty()) {
  65. TIssuePtr materialized = RawIssues_.top().second();
  66. if (auto p = CheckUniqAndLimit(materialized)) {
  67. RawIssues_.top().first = p;
  68. }
  69. }
  70. }
  71. void TIssueManager::LeaveAllScopes() {
  72. while (!RawIssues_.empty()) {
  73. LeaveScope();
  74. }
  75. }
  76. TIssuePtr TIssueManager::CheckUniqAndLimit(TIssuePtr issue) {
  77. const auto severity = issue->GetSeverity();
  78. if (OverflowIssues_[severity]) {
  79. return {};
  80. }
  81. if (UniqueIssues_[severity].contains(issue)) {
  82. return {};
  83. }
  84. if (IssueLimit_ && UniqueIssues_[severity].size() == IssueLimit_) {
  85. OverflowIssues_[severity] = MakeIntrusive<TIssue>(TStringBuilder()
  86. << "Too many " << SeverityToString(issue->GetSeverity()) << " issues");
  87. OverflowIssues_[severity]->Severity = severity;
  88. return {};
  89. }
  90. UniqueIssues_[severity].insert(issue);
  91. return issue;
  92. }
  93. TIssuePtr TIssueManager::CheckUniqAndLimit(const TIssue& issue) {
  94. const auto severity = issue.GetSeverity();
  95. if (OverflowIssues_[severity]) {
  96. return {};
  97. }
  98. return CheckUniqAndLimit(MakeIntrusive<TIssue>(issue));
  99. }
  100. void TIssueManager::RaiseIssue(const TIssue& issue) {
  101. TIssuePtr p = CheckUniqAndLimit(issue);
  102. if (!p) {
  103. return;
  104. }
  105. if (RawIssues_.empty()) {
  106. CompletedIssues_.AddIssue(issue);
  107. return;
  108. }
  109. if (RawIssues_.top().first.Empty()) {
  110. RawIssues_.top().first = RawIssues_.top().second();
  111. if (!*RawIssues_.top().first) {
  112. RawIssues_.top().first = new TIssue();
  113. (*RawIssues_.top().first)->SetCode(Max<ui32>(), ESeverity::TSeverityIds_ESeverityId_S_INFO);
  114. } else {
  115. (*RawIssues_.top().first)->Severity = ESeverity::TSeverityIds_ESeverityId_S_INFO;
  116. }
  117. }
  118. RawIssues_.top().first->Get()->AddSubIssue(p);
  119. }
  120. void TIssueManager::RaiseIssues(const TIssues& issues) {
  121. for (const auto& x : issues) {
  122. RaiseIssue(x);
  123. }
  124. }
  125. bool TIssueManager::RaiseWarning(TIssue issue) {
  126. bool isWarning = true;
  127. if (issue.GetSeverity() == ESeverity::TSeverityIds_ESeverityId_S_WARNING) {
  128. const auto action = WarningPolicy_.GetAction(issue.GetCode());
  129. switch (action) {
  130. case EWarningAction::DISABLE:
  131. return isWarning;
  132. case EWarningAction::ERROR:
  133. issue.Severity = ESeverity::TSeverityIds_ESeverityId_S_ERROR;
  134. if (WarningToErrorTreatMessage_) {
  135. TIssue newIssue;
  136. newIssue.SetCode(issue.GetCode(), ESeverity::TSeverityIds_ESeverityId_S_ERROR);
  137. newIssue.SetMessage(WarningToErrorTreatMessage_.GetRef());
  138. newIssue.AddSubIssue(new TIssue(issue));
  139. issue = newIssue;
  140. }
  141. isWarning = false;
  142. break;
  143. case EWarningAction::DEFAULT:
  144. break;
  145. default:
  146. Y_ENSURE(false, "Unknown action");
  147. }
  148. }
  149. RaiseIssue(issue);
  150. return isWarning;
  151. }
  152. bool TIssueManager::HasOpenScopes() const {
  153. return !RawIssues_.empty();
  154. }
  155. TIssues TIssueManager::GetIssues() {
  156. auto tmp = RawIssues_;
  157. LeaveAllScopes();
  158. auto result = GetCompletedIssues();
  159. RawIssues_ = tmp;
  160. return result;
  161. }
  162. TIssues TIssueManager::GetCompletedIssues() const {
  163. TIssues res;
  164. for (auto& p: OverflowIssues_) {
  165. if (p) {
  166. res.AddIssue(*p);
  167. }
  168. }
  169. res.AddIssues(CompletedIssues_);
  170. return res;
  171. }
  172. void TIssueManager::AddIssues(const TIssues& issues) {
  173. for (auto& issue: issues) {
  174. if (auto p = CheckUniqAndLimit(issue)) {
  175. CompletedIssues_.AddIssue(*p);
  176. }
  177. }
  178. }
  179. void TIssueManager::AddIssues(const TPosition& pos, const TIssues& issues) {
  180. for (auto& issue: issues) {
  181. if (auto p = CheckUniqAndLimit(TIssue(pos, issue.GetMessage()))) {
  182. CompletedIssues_.AddIssue(*p);
  183. }
  184. }
  185. }
  186. void TIssueManager::Reset(const TIssues& issues) {
  187. for (auto& p: OverflowIssues_) {
  188. p.Drop();
  189. }
  190. for (auto& s: UniqueIssues_) {
  191. s.clear();
  192. }
  193. CompletedIssues_.Clear();
  194. while (!RawIssues_.empty()) {
  195. RawIssues_.pop();
  196. }
  197. AddIssues(issues);
  198. }
  199. void TIssueManager::Reset() {
  200. Reset(TIssues());
  201. }
  202. void TIssueManager::AddWarningRule(const TWarningRule &rule)
  203. {
  204. WarningPolicy_.AddRule(rule);
  205. }
  206. void TIssueManager::SetWarningToErrorTreatMessage(const TString& msg) {
  207. WarningToErrorTreatMessage_ = msg;
  208. }