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 "ktexteditor_utils.h" 0009 0010 #include <QJsonArray> 0011 #include <QJsonObject> 0012 #include <QPointer> 0013 #include <QRegularExpression> 0014 #include <QStandardItem> 0015 0016 #include <KLocalizedString> 0017 #include <KTextEditor/Document> 0018 0019 // helper data that holds diagnostics suppressions 0020 class DiagnosticSuppression 0021 { 0022 struct Suppression { 0023 QRegularExpression diag, code; 0024 }; 0025 std::vector<Suppression> m_suppressions; 0026 QPointer<KTextEditor::Document> m_document; 0027 0028 public: 0029 // construct from configuration 0030 DiagnosticSuppression(KTextEditor::Document *doc, const std::vector<QJsonObject> &serverConfigs, const std::vector<QString> &sessionSuppressions) 0031 : m_document(doc) 0032 { 0033 // check regexp and report 0034 auto checkRegExp = [](const QRegularExpression ®Exp) { 0035 auto valid = regExp.isValid(); 0036 if (!valid) { 0037 auto error = regExp.errorString(); 0038 auto offset = regExp.patternErrorOffset(); 0039 auto msg = i18nc("@info", "Error in regular expression: %1\noffset %2: %3", regExp.pattern(), offset, error); 0040 Utils::showMessage(msg, {}, QStringLiteral("LSP Client"), MessageType::Error); 0041 } 0042 return valid; 0043 }; 0044 0045 Q_ASSERT(doc); 0046 const auto localPath = doc->url().toLocalFile(); 0047 for (const auto &serverConfig : serverConfigs) { 0048 const auto supps = serverConfig.value(QStringLiteral("suppressions")).toObject(); 0049 for (const auto &entry : supps) { 0050 // should be (array) tuple (last element optional) 0051 // [url regexp, message regexp, code regexp] 0052 const auto patterns = entry.toArray(); 0053 if (patterns.size() >= 2) { 0054 const auto urlRegExp = QRegularExpression(patterns.at(0).toString()); 0055 if (urlRegExp.isValid() && urlRegExp.match(localPath).hasMatch()) { 0056 QRegularExpression diagRegExp, codeRegExp; 0057 diagRegExp = QRegularExpression(patterns.at(1).toString()); 0058 if (patterns.size() >= 3) { 0059 codeRegExp = QRegularExpression(patterns.at(2).toString()); 0060 } 0061 if (checkRegExp(diagRegExp) && checkRegExp(codeRegExp)) { 0062 m_suppressions.push_back({diagRegExp, codeRegExp}); 0063 } 0064 } 0065 } 0066 } 0067 } 0068 0069 // also consider session suppressions 0070 for (const auto &entry : sessionSuppressions) { 0071 auto pattern = QRegularExpression::escape(entry); 0072 m_suppressions.push_back({QRegularExpression(pattern), {}}); 0073 } 0074 } 0075 0076 bool match(const QStandardItem &item) const 0077 { 0078 for (const auto &s : m_suppressions) { 0079 if (s.diag.match(item.text()).hasMatch()) { 0080 // retrieve and check code text if we need to match the content as well 0081 if (m_document && !s.code.pattern().isEmpty()) { 0082 auto range = item.data(/*RangeData::RangeRole*/).value<KTextEditor::Range>(); 0083 auto code = m_document->text(range); 0084 if (!s.code.match(code).hasMatch()) { 0085 continue; 0086 } 0087 } 0088 return true; 0089 } 0090 } 0091 return false; 0092 } 0093 0094 KTextEditor::Document *document() 0095 { 0096 return m_document; 0097 } 0098 };