File indexing completed on 2024-05-12 05:52:03
0001 /* 0002 SPDX-FileCopyrightText: 2019 Mark Nauwelaerts <mark.nauwelaerts@gmail.com> 0003 SPDX-FileCopyrightText: 2022 Waqar Ahmed <waqar.17a@gmail.com> 0004 SPDX-License-Identifier: MIT 0005 */ 0006 #pragma once 0007 0008 #include "diagnostic_suppression.h" 0009 #include "diagnostic_types.h" 0010 #include "diagnosticview.h" 0011 0012 #include <QStandardItem> 0013 0014 namespace DiagnosticModelRole 0015 { 0016 enum { 0017 // preserve UserRole for generic use where needed 0018 FileUrlRole = Qt::UserRole + 1, 0019 RangeRole, 0020 KindRole, 0021 ProviderRole, 0022 }; 0023 } 0024 0025 enum { 0026 DiagnosticItem_File = QStandardItem::UserType + 1, 0027 DiagnosticItem_Diag, 0028 DiagnosticItem_Fix, 0029 }; 0030 0031 // custom item subclass that captures additional attributes; 0032 // a bit more convenient than the variant/role way 0033 struct DiagnosticItem : public QStandardItem { 0034 Diagnostic m_diagnostic; 0035 0036 explicit DiagnosticItem(const Diagnostic &d) 0037 : m_diagnostic(d) 0038 { 0039 } 0040 0041 int type() const override 0042 { 0043 return DiagnosticItem_Diag; 0044 } 0045 0046 bool hasFixes() const 0047 { 0048 if (!hasChildren()) { 0049 return false; 0050 } 0051 for (int i = 0; i < rowCount(); ++i) { 0052 if (child(i)->type() == DiagnosticItem_Fix) { 0053 return true; 0054 } 0055 } 0056 return false; 0057 } 0058 }; 0059 0060 // likewise; a custom item for document level model item 0061 struct DocumentDiagnosticItem : public QStandardItem { 0062 private: 0063 QList<DiagnosticsProvider *> m_providers; 0064 0065 public: 0066 bool enabled = true; 0067 std::unique_ptr<DiagnosticSuppression> diagnosticSuppression; 0068 int type() const override 0069 { 0070 return DiagnosticItem_File; 0071 } 0072 0073 const QList<DiagnosticsProvider *> &providers() const 0074 { 0075 return m_providers; 0076 } 0077 void addProvider(DiagnosticsProvider *p) 0078 { 0079 if (!m_providers.contains(p)) { 0080 m_providers.push_back(p); 0081 } 0082 } 0083 0084 /** 0085 * Remove items for given provider. If p == null, remove all items of the file 0086 * except the items whose provider has m_persistentDiagnostics. 0087 */ 0088 int removeItemsForProvider(DiagnosticsProvider *p) 0089 { 0090 int removedCount = 0; 0091 if (m_providers.size() == 1) { 0092 if (p == nullptr && m_providers.back()->persistentDiagnostics()) { 0093 // If there is only 1 provider and it's diagnostics are persistent, we have nothing to do here 0094 return removedCount; 0095 } else if (m_providers.contains(p)) { 0096 m_providers.clear(); 0097 removedCount = rowCount(); 0098 setRowCount(0); 0099 return removedCount; 0100 } else { 0101 // if we don't have any diagnostics from this provider, we have nothing to do 0102 return removedCount; 0103 } 0104 } 0105 0106 QVarLengthArray<DiagnosticsProvider *, 3> removedProviders; 0107 auto removeProvider = [&removedProviders](DiagnosticsProvider *p) { 0108 if (!removedProviders.contains(p)) { 0109 removedProviders.append(p); 0110 } 0111 }; 0112 // We have more than one diagnostic provider for this file 0113 if (p == nullptr) { 0114 // Remove all diagnostics where provider->persistentDiagnostics() == false 0115 int start = -1; 0116 int count = 0; 0117 for (int i = 0; i < rowCount(); ++i) { 0118 auto item = child(i); 0119 auto itemProvider = item->data(DiagnosticModelRole::ProviderRole).value<DiagnosticsProvider *>(); 0120 if (!itemProvider->persistentDiagnostics()) { 0121 if (start == -1) { 0122 start = i; 0123 } 0124 count++; 0125 removeProvider(itemProvider); 0126 } else { 0127 if (start > -1 && count != 0) { 0128 removedCount += count; 0129 removeRows(start, count); 0130 i = start - 1; 0131 start = -1; 0132 count = 0; 0133 } 0134 } 0135 } 0136 if (start > -1 && count != 0) { 0137 removedCount += count; 0138 removeRows(start, count); 0139 } 0140 } else { 0141 // remove all diagnostics from the given provider 0142 int start = -1; 0143 int count = 0; 0144 for (int i = 0; i < rowCount(); ++i) { 0145 auto item = child(i); 0146 auto itemProvider = item->data(DiagnosticModelRole::ProviderRole).value<DiagnosticsProvider *>(); 0147 if (itemProvider == p) { 0148 if (start == -1) { 0149 start = i; 0150 } 0151 removeProvider(itemProvider); 0152 count++; 0153 } else { 0154 if (start > -1 && count != 0) { 0155 removedCount += count; 0156 removeRows(start, count); 0157 i = start - 1; 0158 start = -1; 0159 count = 0; 0160 } 0161 } 0162 } 0163 if (start > -1 && count != 0) { 0164 removedCount += count; 0165 removeRows(start, count); 0166 } 0167 } 0168 0169 // remove the providers for which we don't have diagnostics 0170 for (auto p : removedProviders) { 0171 m_providers.removeOne(p); 0172 } 0173 return removedCount; 0174 } 0175 }; 0176 0177 struct DiagnosticFixItem : public QStandardItem { 0178 DiagnosticFix fix; 0179 int type() const override 0180 { 0181 return DiagnosticItem_Fix; 0182 } 0183 };