File indexing completed on 2024-05-12 04:39:22
0001 /* 0002 SPDX-FileCopyrightText: 2016 Carlos Nihelton <carlosnsoliveira@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "clangtidyparser.h" 0008 0009 // KDevPlatform 0010 #include <language/editor/documentrange.h> 0011 #include <serialization/indexedstring.h> 0012 #include <shell/problem.h> 0013 0014 namespace ClangTidy 0015 { 0016 using KDevelop::IProblem; 0017 using KDevelop::DetectedProblem; 0018 using KDevelop::DocumentRange; 0019 using KDevelop::IndexedString; 0020 /** 0021 * Convert the value of <verbose> attribute of <error> element from clang-tidy's 0022 * XML-output to 'good-looking' HTML-version. This is necessary because the 0023 * displaying of the original message is performed without line breaks - such 0024 * tooltips are uncomfortable to read, and large messages will not fit into the 0025 * screen. 0026 * 0027 * This function put the original message into \<html\> tag that automatically 0028 * provides line wrapping by builtin capabilities of Qt library. The source text 0029 * also can contain tokens '\012' (line break) - they are present in the case of 0030 * source code examples. In such cases, the entire text between the first and 0031 * last tokens (i.e. source code) is placed into \<pre\> tag. 0032 * 0033 * @param[in] input the original value of <verbose> attribute 0034 * @return HTML version for displaying in problem's tooltip 0035 */ 0036 QString verboseMessageToHtml(const QString& input) 0037 { 0038 QString output(QStringLiteral("<html>%1</html>").arg(input.toHtmlEscaped())); 0039 0040 output.replace(QLatin1String("\\012"), QLatin1String("\n")); 0041 0042 if (output.count(QLatin1Char('\n')) >= 2) { 0043 output.replace(output.indexOf(QLatin1Char('\n')), 1, QStringLiteral("<pre>")); 0044 output.replace(output.lastIndexOf(QLatin1Char('\n')), 1, QStringLiteral("</pre><br>")); 0045 } 0046 0047 return output; 0048 } 0049 0050 ClangTidyParser::ClangTidyParser(QObject* parent) 0051 : QObject(parent) 0052 // (1 filename ) (2ln) (3cl) (4se) (5d) (6expln) 0053 , m_hitRegExp(QStringLiteral(R"(((?:[A-Za-z]:\\|\/).+\.[ch]{1,2}[px]{0,2}):(\d+):(\d+): (.+?): (.+) (\[.+\]))")) 0054 { 0055 } 0056 0057 void ClangTidyParser::addData(const QStringList& stdoutList) 0058 { 0059 QVector<KDevelop::IProblem::Ptr> problems; 0060 0061 for (const auto& line : qAsConst(stdoutList)) { 0062 auto smatch = m_hitRegExp.match(line); 0063 0064 if (!smatch.hasMatch()) { 0065 continue; 0066 } 0067 0068 IProblem::Ptr problem(new DetectedProblem()); 0069 problem->setSource(IProblem::Plugin); 0070 problem->setDescription(smatch.captured(5)); 0071 problem->setExplanation(smatch.captured(6)); 0072 0073 DocumentRange range; 0074 range.document = IndexedString(smatch.captured(1)); 0075 range.setBothColumns(smatch.capturedRef(3).toInt() - 1); 0076 range.setBothLines(smatch.capturedRef(2).toInt() - 1); 0077 problem->setFinalLocation(range); 0078 0079 const auto sev = smatch.capturedRef(4); 0080 const IProblem::Severity erity = 0081 (sev == QLatin1String("error")) ? IProblem::Error : 0082 (sev == QLatin1String("warning")) ? IProblem::Warning : 0083 (sev == QLatin1String("note")) ? IProblem::Hint : 0084 /* else */ IProblem::NoSeverity; 0085 problem->setSeverity(erity); 0086 0087 problems.append(problem); 0088 } 0089 0090 if (!problems.isEmpty()) { 0091 emit problemsDetected(problems); 0092 } 0093 } 0094 0095 } // namespace ClangTidy 0096 0097 #include "moc_clangtidyparser.cpp"