Warning, file /kdevelop/kdevelop/kdevplatform/outputview/outputfilteringstrategies.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2012 Morten Danielsen Volden <mvolden2@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "outputfilteringstrategies.h" 0008 #include "outputformats.h" 0009 #include "filtereditem.h" 0010 #include <util/path.h> 0011 0012 #include <KLocalizedString> 0013 0014 #include <QFileInfo> 0015 0016 #include <algorithm> 0017 0018 namespace KDevelop 0019 { 0020 void initializeFilteredItem(FilteredItem& item, const ErrorFormat& filter, const QRegularExpressionMatch& match) 0021 { 0022 item.lineNo = match.capturedRef(filter.lineGroup).toInt() - 1; 0023 item.columnNo = filter.columnNumber(match); 0024 } 0025 0026 0027 template<typename ErrorFormats> 0028 FilteredItem match(const ErrorFormats& errorFormats, const QString& line) 0029 { 0030 FilteredItem item(line); 0031 for( const ErrorFormat& curErrFilter : errorFormats ) { 0032 const auto match = curErrFilter.expression.match(line); 0033 if( match.hasMatch() ) { 0034 initializeFilteredItem(item, curErrFilter, match); 0035 item.url = QUrl::fromUserInput(match.captured( curErrFilter.fileGroup )); 0036 0037 item.type = FilteredItem::ErrorItem; 0038 0039 // Make the item clickable if it comes with the necessary file & line number information 0040 if (curErrFilter.fileGroup > 0 && curErrFilter.lineGroup > 0) { 0041 item.isActivatable = true; 0042 } 0043 break; 0044 } 0045 } 0046 return item; 0047 } 0048 0049 /// --- No filter strategy --- 0050 0051 NoFilterStrategy::NoFilterStrategy() 0052 { 0053 } 0054 0055 FilteredItem NoFilterStrategy::actionInLine(const QString& line) 0056 { 0057 return FilteredItem( line ); 0058 } 0059 0060 FilteredItem NoFilterStrategy::errorInLine(const QString& line) 0061 { 0062 return FilteredItem( line ); 0063 } 0064 0065 /// --- Compiler error filter strategy --- 0066 0067 /// Impl. of CompilerFilterStrategy. 0068 class CompilerFilterStrategyPrivate 0069 { 0070 public: 0071 explicit CompilerFilterStrategyPrivate(const QUrl& buildDir); 0072 Path pathForFile( const QString& ) const; 0073 bool isMultiLineCase(const ErrorFormat& curErrFilter) const; 0074 void putDirAtEnd(const Path& pathToInsert); 0075 0076 QVector<Path> m_currentDirs; 0077 Path m_buildDir; 0078 0079 using PositionMap = QHash<Path, int>; 0080 PositionMap m_positionInCurrentDirs; 0081 }; 0082 0083 CompilerFilterStrategyPrivate::CompilerFilterStrategyPrivate(const QUrl& buildDir) 0084 : m_buildDir(buildDir) 0085 { 0086 } 0087 0088 Path CompilerFilterStrategyPrivate::pathForFile(const QString& filename) const 0089 { 0090 QFileInfo fi( filename ); 0091 Path currentPath; 0092 if( fi.isRelative() ) { 0093 if( m_currentDirs.isEmpty() ) { 0094 return Path(m_buildDir, filename ); 0095 } 0096 0097 auto it = m_currentDirs.constEnd() - 1; 0098 do { 0099 currentPath = Path(*it, filename); 0100 } while( (it-- != m_currentDirs.constBegin()) && !QFileInfo::exists(currentPath.toLocalFile()) ); 0101 0102 return currentPath; 0103 } else { 0104 currentPath = Path(filename); 0105 } 0106 return currentPath; 0107 } 0108 0109 bool CompilerFilterStrategyPrivate::isMultiLineCase(const KDevelop::ErrorFormat& curErrFilter) const 0110 { 0111 if(curErrFilter.compiler == QLatin1String("gfortran") || curErrFilter.compiler == QLatin1String("cmake")) { 0112 return true; 0113 } 0114 return false; 0115 } 0116 0117 void CompilerFilterStrategyPrivate::putDirAtEnd(const Path& pathToInsert) 0118 { 0119 CompilerFilterStrategyPrivate::PositionMap::iterator it = m_positionInCurrentDirs.find( pathToInsert ); 0120 // Encountered new build directory? 0121 if (it == m_positionInCurrentDirs.end()) { 0122 m_currentDirs.push_back( pathToInsert ); 0123 m_positionInCurrentDirs.insert( pathToInsert, m_currentDirs.size() - 1 ); 0124 } else { 0125 // Build dir already in currentDirs, but move it to back of currentDirs list 0126 // (this gives us most-recently-used semantics in pathForFile) 0127 std::rotate(m_currentDirs.begin() + it.value(), m_currentDirs.begin() + it.value() + 1, m_currentDirs.end() ); 0128 it.value() = m_currentDirs.size() - 1; 0129 } 0130 } 0131 0132 CompilerFilterStrategy::CompilerFilterStrategy(const QUrl& buildDir) 0133 : d_ptr(new CompilerFilterStrategyPrivate(buildDir)) 0134 { 0135 } 0136 0137 CompilerFilterStrategy::~CompilerFilterStrategy() = default; 0138 0139 QVector<QString> CompilerFilterStrategy::currentDirs() const 0140 { 0141 Q_D(const CompilerFilterStrategy); 0142 0143 QVector<QString> ret; 0144 ret.reserve(d->m_currentDirs.size()); 0145 for (const auto& path : qAsConst(d->m_currentDirs)) { 0146 ret << path.pathOrUrl(); 0147 } 0148 return ret; 0149 } 0150 0151 FilteredItem CompilerFilterStrategy::actionInLine(const QString& line) 0152 { 0153 Q_D(CompilerFilterStrategy); 0154 0155 // A list of filters for possible compiler, linker, and make actions 0156 static const ActionFormat ACTION_FILTERS[] = { 0157 ActionFormat( 2, 0158 QStringLiteral("(?:^|[^=])\\b(gcc|CC|cc|distcc|c\\+\\+|g\\+\\+|clang(?:\\+\\+)|mpicc|icc|icpc)\\s+.*-c.*[/ '\\\\]+(\\w+\\.(?:cpp|CPP|c|C|cxx|CXX|cs|java|hpf|f|F|f90|F90|f95|F95))")), 0159 //moc and uic 0160 ActionFormat( 2, QStringLiteral("/(moc|uic)\\b.*\\s-o\\s([^\\s;]+)")), 0161 //libtool linking 0162 ActionFormat( QStringLiteral("libtool"), QStringLiteral("/bin/sh\\s.*libtool.*--mode=link\\s.*\\s-o\\s([^\\s;]+)"), 1 ), 0163 //unsermake 0164 ActionFormat( 1, QStringLiteral("^compiling (.*)") ), 0165 ActionFormat( 2, QStringLiteral("^generating (.*)") ), 0166 ActionFormat( 2, QStringLiteral("(gcc|cc|c\\+\\+|g\\+\\+|clang(?:\\+\\+)|mpicc|icc|icpc)\\S* (?:\\S* )*-o ([^\\s;]+)")), 0167 ActionFormat( 2, QStringLiteral("^linking (.*)") ), 0168 //cmake 0169 ActionFormat( 1, QStringLiteral("\\[.+%\\] Built target (.*)") ), 0170 ActionFormat( QStringLiteral("cmake"), 0171 QStringLiteral("\\[.+%\\] Building .* object (.*)"), 1 ), 0172 ActionFormat( 1, QStringLiteral("\\[.+%\\] Generating (.*)") ), 0173 ActionFormat( 1, QStringLiteral("^Linking (.*)") ), 0174 ActionFormat( QStringLiteral("cmake"), 0175 QStringLiteral("(-- (?:Configuring|Generating) (?:done|incomplete)|-- Found|-- Adding|-- Enabling)"), -1 ), 0176 ActionFormat( 1, QStringLiteral("-- Installing (.*)") ), 0177 //cmake - cd - filter for project directory 0178 ActionFormat( QStringLiteral("cd"), 0179 QStringLiteral("cmake(?:\\.exe|\\.bat)? (?:.*?) ((?:[A-Za-z]:|/).*$)"), 1), 0180 //libtool install 0181 ActionFormat( {}, 0182 QStringLiteral("/(?:bin/sh\\s.*mkinstalldirs).*\\s([^\\s;]+)"), 1 ), 0183 ActionFormat( {}, 0184 QStringLiteral("/(?:usr/bin/install|bin/sh\\s.*mkinstalldirs|bin/sh\\s.*libtool.*--mode=install).*\\s([^\\s;]+)"), 1 ), 0185 //dcop 0186 ActionFormat( QStringLiteral("dcopidl"), 0187 QStringLiteral("dcopidl .* > ([^\\s;]+)"), 1 ), 0188 ActionFormat( QStringLiteral("dcopidl2cpp"), 0189 QStringLiteral("dcopidl2cpp (?:\\S* )*([^\\s;]+)"), 1 ), 0190 // match against Entering directory to update current build dir 0191 ActionFormat( QStringLiteral("cd"), 0192 QStringLiteral("make\\[\\d+\\]: Entering directory (\\`|\\')(.+)'"), 2), 0193 // waf and scons use the same basic convention as make 0194 ActionFormat( QStringLiteral("cd"), 0195 QStringLiteral("(Waf|scons): Entering directory (\\`|\\')(.+)'"), 3) 0196 }; 0197 0198 FilteredItem item(line); 0199 for (const auto& curActFilter : ACTION_FILTERS) { 0200 const auto match = curActFilter.expression.match(line); 0201 if( match.hasMatch() ) { 0202 item.type = FilteredItem::ActionItem; 0203 0204 if( curActFilter.tool == QLatin1String("cd") ) { 0205 const Path path(match.captured(curActFilter.fileGroup)); 0206 d->m_currentDirs.push_back( path ); 0207 d->m_positionInCurrentDirs.insert( path , d->m_currentDirs.size() - 1 ); 0208 } 0209 0210 // Special case for cmake: we parse the "Compiling <objectfile>" expression 0211 // and use it to find out about the build paths encountered during a build. 0212 // They are later searched by pathForFile to find source files corresponding to 0213 // compiler errors. 0214 // Note: CMake objectfile has the format: "/path/to/four/CMakeFiles/file.o" 0215 if ( curActFilter.fileGroup != -1 && curActFilter.tool == QLatin1String("cmake") && line.contains(QLatin1String("Building"))) { 0216 const auto objectFile = match.captured(curActFilter.fileGroup); 0217 const auto dir = objectFile.section(QStringLiteral("CMakeFiles/"), 0, 0); 0218 d->putDirAtEnd(Path(d->m_buildDir, dir)); 0219 } 0220 break; 0221 } 0222 } 0223 return item; 0224 } 0225 0226 FilteredItem CompilerFilterStrategy::errorInLine(const QString& line) 0227 { 0228 Q_D(CompilerFilterStrategy); 0229 0230 // All the possible string that indicate an error if we via Regex have been able to 0231 // extract file and linenumber from a given outputline 0232 // TODO: This seems clumsy -- and requires another scan of the line. 0233 // Merge this information into ErrorFormat? --Kevin 0234 using Indicator = QPair<QString, FilteredItem::FilteredOutputItemType>; 0235 static const Indicator INDICATORS[] = { 0236 // ld 0237 Indicator(QStringLiteral("undefined reference"), FilteredItem::ErrorItem), 0238 Indicator(QStringLiteral("undefined symbol"), FilteredItem::ErrorItem), 0239 Indicator(QStringLiteral("ld: cannot find"), FilteredItem::ErrorItem), 0240 Indicator(QStringLiteral("no such file"), FilteredItem::ErrorItem), 0241 // gcc 0242 Indicator(QStringLiteral("error"), FilteredItem::ErrorItem), 0243 // generic 0244 Indicator(QStringLiteral("warning"), FilteredItem::WarningItem), 0245 Indicator(QStringLiteral("info"), FilteredItem::InformationItem), 0246 Indicator(QStringLiteral("note"), FilteredItem::InformationItem), 0247 }; 0248 0249 // A list of filters for possible compiler, linker, and make errors 0250 static const ErrorFormat ERROR_FILTERS[] = { 0251 #ifdef Q_OS_WIN 0252 // MSVC 0253 ErrorFormat( QStringLiteral("^([a-zA-Z]:\\\\.+)\\(([1-9][0-9]*)\\): ((?:error|warning) .+\\:).*$"), 1, 2, 3 ), 0254 #endif 0255 // GCC - another case, eg. for #include "pixmap.xpm" which does not exists 0256 ErrorFormat( QStringLiteral("^(.:?[^:\\t]+):([0-9]+):([0-9]+):([^0-9]+)"), 1, 2, 4, 3 ), 0257 // ant 0258 ErrorFormat( QStringLiteral("\\[javac\\][\\s]+([^:\\t]+):([0-9]+): (warning: .*|error: .*)"), 1, 2, 3, QStringLiteral("javac")), 0259 // GCC 0260 ErrorFormat( QStringLiteral("^(.:?[^:\\t]+):([0-9]+):([^0-9]+)"), 1, 2, 3 ), 0261 // GCC 0262 ErrorFormat( QStringLiteral("^(In file included from |[ ]+from )(..[^:\\t]+):([0-9]+)(:|,)(|[0-9]+)"), 2, 3, 5 ), 0263 // ICC 0264 ErrorFormat( QStringLiteral("^(.:?[^:\\t]+)\\(([0-9]+)\\):([^0-9]+)"), 1, 2, 3, QStringLiteral("intel") ), 0265 //libtool link 0266 ErrorFormat( QStringLiteral("^(libtool):( link):( warning): "), 0, 0, 0 ), 0267 // make 0268 ErrorFormat( QStringLiteral("No rule to make target"), 0, 0, 0 ), 0269 // cmake - multiline expression 0270 ErrorFormat( QStringLiteral("((^\\/|^[a-zA-Z]:)[\\w|\\/| |\\.]+):([0-9]+):"), 1, 2, 0, QStringLiteral("cmake") ), 0271 // cmake 0272 ErrorFormat( QStringLiteral("CMake (Error|Warning) (|\\([a-zA-Z]+\\) )(in|at) ([^:]+):($|[0-9]+)"), 4, 5, 1, QStringLiteral("cmake") ), 0273 // cmake/automoc 0274 // example: AUTOMOC: error: /foo/bar.cpp The file includes (...), 0275 // example: AUTOMOC: error: /foo/bar.cpp: The file includes (...) 0276 // note: ':' after file name isn't always appended, see https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=317d8498aa02c9f486bf5071963bb2034777cdd6 0277 // example: AUTOGEN: error: /foo/bar.cpp: The file includes (...) 0278 // note: AUTOMOC got renamed to AUTOGEN at some point 0279 ErrorFormat( QStringLiteral("^(AUTOMOC|AUTOGEN): error: (.*?) (The file .*)$"), 2, 0, 0 ), 0280 // via qt4_automoc 0281 // example: automoc4: The file "/foo/bar.cpp" includes the moc file "bar1.moc", but ... 0282 ErrorFormat( QStringLiteral("^automoc4: The file \"([^\"]+)\" includes the moc file"), 1, 0, 0 ), 0283 // Fortran 0284 ErrorFormat( QStringLiteral("\"(.*)\", line ([0-9]+):(.*)"), 1, 2, 3 ), 0285 // GFortran 0286 ErrorFormat( QStringLiteral("^(.*):([0-9]+)\\.([0-9]+):(.*)"), 1, 2, 4, QStringLiteral("gfortran"), 3 ), 0287 // Jade 0288 ErrorFormat( QStringLiteral("^[a-zA-Z]+:([^:\\t]+):([0-9]+):[0-9]+:[a-zA-Z]:(.*)"), 1, 2, 3 ), 0289 // ifort 0290 ErrorFormat( QStringLiteral("^fortcom: (.*): (.*), line ([0-9]+):(.*)"), 2, 3, 1, QStringLiteral("intel") ), 0291 // PGI 0292 ErrorFormat( QStringLiteral("PGF9(.*)-(.*)-(.*)-(.*) \\((.*): ([0-9]+)\\)"), 5, 6, 4, QStringLiteral("pgi") ), 0293 // PGI (2) 0294 ErrorFormat( QStringLiteral("PGF9(.*)-(.*)-(.*)-Symbol, (.*) \\((.*)\\)"), 5, 5, 4, QStringLiteral("pgi") ), 0295 }; 0296 0297 FilteredItem item(line); 0298 for (const auto& curErrFilter : ERROR_FILTERS) { 0299 const auto match = curErrFilter.expression.match(line); 0300 if( match.hasMatch() && !( line.contains( QLatin1String("Each undeclared identifier is reported only once") ) 0301 || line.contains( QLatin1String("for each function it appears in.") ) ) ) 0302 { 0303 if(curErrFilter.fileGroup > 0) { 0304 if( curErrFilter.compiler == QLatin1String("cmake") ) { // Unfortunately we cannot know if an error or an action comes first in cmake, and therefore we need to do this 0305 if( d->m_currentDirs.empty() ) { 0306 d->putDirAtEnd( d->m_buildDir.parent() ); 0307 } 0308 } 0309 item.url = d->pathForFile( match.captured( curErrFilter.fileGroup ) ).toUrl(); 0310 } 0311 initializeFilteredItem(item, curErrFilter, match); 0312 0313 const QStringRef txt = match.capturedRef(curErrFilter.textGroup); 0314 0315 // Find the indicator which happens most early. 0316 int earliestIndicatorIdx = txt.length(); 0317 for (const auto& curIndicator : INDICATORS) { 0318 int curIndicatorIdx = txt.indexOf(curIndicator.first, 0, Qt::CaseInsensitive); 0319 if((curIndicatorIdx >= 0) && (earliestIndicatorIdx > curIndicatorIdx)) { 0320 earliestIndicatorIdx = curIndicatorIdx; 0321 item.type = curIndicator.second; 0322 } 0323 } 0324 0325 // Make the item clickable if it comes with the necessary file information 0326 if (item.url.isValid()) { 0327 item.isActivatable = true; 0328 if(item.type == FilteredItem::InvalidItem) { 0329 // If there are no error indicators in the line 0330 // maybe this is a multiline case 0331 if(d->isMultiLineCase(curErrFilter)) { 0332 item.type = FilteredItem::ErrorItem; 0333 } else { 0334 // Okay so we couldn't find anything to indicate an error, but we have file and lineGroup 0335 // Lets keep this item clickable and indicate this to the user. 0336 item.type = FilteredItem::InformationItem; 0337 } 0338 } 0339 } 0340 break; 0341 } 0342 } 0343 return item; 0344 } 0345 0346 0347 /// --- Script error filter strategy --- 0348 0349 ScriptErrorFilterStrategy::ScriptErrorFilterStrategy() 0350 { 0351 } 0352 0353 FilteredItem ScriptErrorFilterStrategy::actionInLine(const QString& line) 0354 { 0355 return FilteredItem(line); 0356 } 0357 0358 FilteredItem ScriptErrorFilterStrategy::errorInLine(const QString& line) 0359 { 0360 // A list of filters for possible Python and PHP errors 0361 static const ErrorFormat SCRIPT_ERROR_FILTERS[] = { 0362 ErrorFormat( QStringLiteral("^ File \"(.*)\", line ([0-9]+)(.*$|, in(.*)$)"), 1, 2, -1 ), 0363 ErrorFormat( QStringLiteral("^.*(/.*):([0-9]+).*$"), 1, 2, -1 ), 0364 ErrorFormat( QStringLiteral("^.* in (/.*) on line ([0-9]+).*$"), 1, 2, -1 ) 0365 }; 0366 0367 return match(SCRIPT_ERROR_FILTERS, line); 0368 } 0369 0370 /// --- Native application error filter strategy --- 0371 0372 NativeAppErrorFilterStrategy::NativeAppErrorFilterStrategy() 0373 { 0374 } 0375 0376 FilteredItem NativeAppErrorFilterStrategy::actionInLine(const QString& line) 0377 { 0378 return FilteredItem(line); 0379 } 0380 0381 FilteredItem NativeAppErrorFilterStrategy::errorInLine(const QString& line) 0382 { 0383 static const ErrorFormat NATIVE_APPLICATION_ERROR_FILTERS[] = { 0384 // BEGIN: C++ 0385 0386 // assert(false) 0387 // a.out: test.cpp:5: int main(): Assertion `false' failed. 0388 0389 // this may also match custom assert message like this one from OSM2go: 0390 // code at: /osm2go/tests/osm_edit.cpp:47: int main(): Assertion foo = bar failed: foo = 5, bar = 4 0391 // If there is a technical reason not to do so: fine. But for the moment it's easy enough to catch it. 0392 ErrorFormat(QStringLiteral("^.+: (.+):([1-9][0-9]*): .+: Assertion .+ failed"), 1, 2, -1), 0393 0394 // assert_perror(42) 0395 // a.out: test.cpp:2009: void {anonymous}::test(): Unexpected error: Broken pipe. 0396 ErrorFormat(QStringLiteral("^.+: (.+):([1-9][0-9]*): .+: Unexpected error: "), 1, 2, -1), 0397 0398 // END: C++ 0399 0400 // BEGIN: Qt 0401 0402 // Note: Scan the whole line for catching Qt runtime warnings (-> no ^$) 0403 // Reasoning: With QT_MESSAGE_PATTERN you can configure the output to your desire, 0404 // which means the output could be arbitrarily prefixed or suffixed with other content 0405 0406 // QObject::connect related errors, also see err_method_notfound() in qobject.cpp 0407 // QObject::connect: No such slot Foo::bar() in /foo/bar.cpp:313 0408 ErrorFormat(QStringLiteral("QObject::connect: (?:No such|Parentheses expected,) (?:slot|signal) [^ ]* in (.*):([0-9]+)"), 1, 2, -1), 0409 // ASSERT: "errors().isEmpty()" in file /foo/bar.cpp, line 49 0410 ErrorFormat(QStringLiteral("ASSERT: \"(.*)\" in file (.*), line ([0-9]+)"), 2, 3, -1), 0411 // Catch: 0412 // FAIL! : FooTest::testBar() Compared pointers are not the same 0413 // Actual ... 0414 // Expected ... 0415 // Loc: [/foo/bar.cpp(33)] 0416 // 0417 // Do *not* catch: 0418 // ... 0419 // Loc: [Unknown file(0)] 0420 ErrorFormat(QStringLiteral(" Loc: \\[(.*)\\(([1-9][0-9]*)\\)\\]"), 1, 2, -1), 0421 0422 // file:///path/to/foo.qml:7:1: Bar is not a type 0423 // file:///path/to/foo.qml:49:5: QML Row: Binding loop detected for property "height" 0424 ErrorFormat(QStringLiteral("(file:\\/\\/(?:[^:]+)):([1-9][0-9]*):([1-9][0-9]*): (.*) (?:is not a type|is ambiguous|is instantiated recursively|Binding loop detected)"), 1, 2, -1, 3), 0425 0426 // file:///path/to/foo.qml:52: TypeError: Cannot read property 'height' of null 0427 ErrorFormat(QStringLiteral("(file:\\/\\/(?:[^:]+)):([1-9][0-9]*): ([a-zA-Z]+)Error"), 1, 2, -1), 0428 0429 // END: Qt 0430 0431 // BEGIN: glib 0432 0433 // all messages may have an initial entry like "GIO:" in case the log domain was set 0434 // the function name after the line number may be missing 0435 0436 // g_assert(0) 0437 // ERROR:/foo/test.cpp:46:int main(): assertion failed: (0) 0438 ErrorFormat(QStringLiteral("^(.+:)?ERROR:(.+):([1-9][0-9]*):(.+:)? assertion failed"), 2, 3, -1), 0439 0440 // g_assert_not_reached() 0441 // ERROR:/foo/test.cpp:2024:int main(): code should not be reached 0442 ErrorFormat(QStringLiteral("^(.+:)?ERROR:(.+):([1-9][0-9]*):(.+:)? code should not be reached"), 2, 3, -1), 0443 0444 // g_assert_null() / g_assert_nonnull() 0445 // ERROR:/foo/test.cpp:18:int main(): 'bar' should not be nullptr 0446 // ERROR:/foo/test.c:18:int main(): 'bar' should not be NULL 0447 ErrorFormat(QStringLiteral("^(.+:)?ERROR:(.+):([1-9][0-9]*):(.+:)? '.+' should (not )?be (nullptr|NULL)"), 2, 3, -1), 0448 0449 // g_assert_true() / g_assert_false() 0450 // ERROR:/foo/test.cpp:18:int main(): 'foo' should be TRUE 0451 // ERROR:/foo/test.cpp:18:int main(): 'foo' should be FALSE 0452 ErrorFormat(QStringLiteral("^(.+:)?ERROR:(.+):([1-9][0-9]*):(.+:)? '.+' should be (TRUE|FALSE)"), 2, 3, -1), 0453 0454 // END: glib 0455 }; 0456 0457 return match(NATIVE_APPLICATION_ERROR_FILTERS, line); 0458 } 0459 0460 /// --- Static Analysis filter strategy --- 0461 0462 StaticAnalysisFilterStrategy::StaticAnalysisFilterStrategy() 0463 { 0464 } 0465 0466 FilteredItem StaticAnalysisFilterStrategy::actionInLine(const QString& line) 0467 { 0468 return FilteredItem(line); 0469 } 0470 0471 FilteredItem StaticAnalysisFilterStrategy::errorInLine(const QString& line) 0472 { 0473 // A list of filters for static analysis tools (krazy2, cppcheck) 0474 static const ErrorFormat STATIC_ANALYSIS_FILTERS[] = { 0475 // CppCheck 0476 ErrorFormat( QStringLiteral("^\\[(.*):([0-9]+)\\]:(.*)"), 1, 2, 3 ), 0477 // krazy2 0478 ErrorFormat( QStringLiteral("^\\t([^:]+).*line#([0-9]+).*"), 1, 2, -1 ), 0479 // krazy2 without line info 0480 ErrorFormat( QStringLiteral("^\\t(.*): missing license"), 1, -1, -1 ) 0481 }; 0482 0483 return match(STATIC_ANALYSIS_FILTERS, line); 0484 } 0485 0486 }