Changeset View
Changeset View
Standalone View
Standalone View
outputview/outputfilteringstrategies.cpp
Show All 21 Lines | |||||
22 | #include <util/path.h> | 22 | #include <util/path.h> | ||
23 | 23 | | |||
24 | #include <KLocalizedString> | 24 | #include <KLocalizedString> | ||
25 | 25 | | |||
26 | #include <QFileInfo> | 26 | #include <QFileInfo> | ||
27 | 27 | | |||
28 | #include <algorithm> | 28 | #include <algorithm> | ||
29 | 29 | | |||
30 | using namespace KDevelop; | 30 | namespace KDevelop | ||
31 | { | ||||
31 | 32 | | |||
32 | namespace { | 33 | FilteredItem match(const QVector<ErrorFormat>& errorFormats, const QString& line) | ||
mwolff: keep this template here and use it in this file. that way, we can still have the simple data… | |||||
33 | template<typename ErrorFormats> | | |||
34 | FilteredItem match(const ErrorFormats& errorFormats, const QString& line) | | |||
35 | { | 34 | { | ||
36 | FilteredItem item(line); | 35 | FilteredItem item(line); | ||
37 | for( const ErrorFormat& curErrFilter : errorFormats ) { | 36 | for( const ErrorFormat& curErrFilter : errorFormats ) { | ||
38 | const auto match = curErrFilter.expression.match(line); | 37 | const auto match = curErrFilter.expression.match(line); | ||
39 | if( match.hasMatch() ) { | 38 | if( match.hasMatch() ) { | ||
40 | item.url = QUrl::fromUserInput(match.captured( curErrFilter.fileGroup )); | 39 | item.url = QUrl::fromUserInput(match.captured( curErrFilter.fileGroup )); | ||
41 | item.lineNo = match.captured( curErrFilter.lineGroup ).toInt() - 1; | 40 | item.lineNo = match.captured( curErrFilter.lineGroup ).toInt() - 1; | ||
42 | if(curErrFilter.columnGroup >= 0) { | 41 | if(curErrFilter.columnGroup >= 0) { | ||
Show All 10 Lines | |||||
53 | if (curErrFilter.fileGroup > 0 && curErrFilter.lineGroup > 0) { | 52 | if (curErrFilter.fileGroup > 0 && curErrFilter.lineGroup > 0) { | ||
54 | item.isActivatable = true; | 53 | item.isActivatable = true; | ||
55 | } | 54 | } | ||
56 | break; | 55 | break; | ||
57 | } | 56 | } | ||
58 | } | 57 | } | ||
59 | return item; | 58 | return item; | ||
60 | } | 59 | } | ||
61 | } | | |||
62 | 60 | | |||
63 | /// --- No filter strategy --- | 61 | /// --- No filter strategy --- | ||
64 | 62 | | |||
65 | NoFilterStrategy::NoFilterStrategy() | 63 | NoFilterStrategy::NoFilterStrategy() | ||
66 | { | 64 | { | ||
67 | } | 65 | } | ||
68 | 66 | | |||
69 | FilteredItem NoFilterStrategy::actionInLine(const QString& line) | 67 | FilteredItem NoFilterStrategy::actionInLine(const QString& line) | ||
70 | { | 68 | { | ||
71 | return FilteredItem( line ); | 69 | return FilteredItem( line ); | ||
72 | } | 70 | } | ||
73 | 71 | | |||
74 | FilteredItem NoFilterStrategy::errorInLine(const QString& line) | 72 | FilteredItem NoFilterStrategy::errorInLine(const QString& line) | ||
75 | { | 73 | { | ||
76 | return FilteredItem( line ); | 74 | return FilteredItem( line ); | ||
77 | } | 75 | } | ||
78 | 76 | | |||
79 | /// --- Compiler error filter strategy --- | 77 | /// --- Compiler error filter strategy --- | ||
80 | 78 | | |||
81 | CompilerFilterStrategy::CompilerFilterStrategy(const QUrl& buildDir) | 79 | /// Impl. of CompilerFilterStrategy. | ||
80 | struct CompilerFilterStrategyPrivate | ||||
81 | { | ||||
82 | CompilerFilterStrategyPrivate(const QUrl& buildDir); | ||||
83 | Path pathForFile( const QString& ) const; | ||||
84 | bool isMultiLineCase(ErrorFormat curErrFilter) const; | ||||
85 | void putDirAtEnd(const Path& pathToInsert); | ||||
86 | | ||||
87 | QVector<Path> m_currentDirs; | ||||
88 | Path m_buildDir; | ||||
89 | | ||||
90 | using PositionMap = QHash<Path, int>; | ||||
91 | PositionMap m_positionInCurrentDirs; | ||||
92 | }; | ||||
93 | | ||||
94 | | ||||
95 | CompilerFilterStrategyPrivate::CompilerFilterStrategyPrivate(const QUrl& buildDir) | ||||
82 | : m_buildDir(buildDir) | 96 | : m_buildDir(buildDir) | ||
83 | { | 97 | { | ||
84 | } | 98 | } | ||
85 | 99 | | |||
86 | Path CompilerFilterStrategy::pathForFile(const QString& filename) const | 100 | Path CompilerFilterStrategyPrivate::pathForFile(const QString& filename) const | ||
87 | { | 101 | { | ||
88 | QFileInfo fi( filename ); | 102 | QFileInfo fi( filename ); | ||
89 | Path currentPath; | 103 | Path currentPath; | ||
90 | if( fi.isRelative() ) { | 104 | if( fi.isRelative() ) { | ||
91 | if( m_currentDirs.isEmpty() ) { | 105 | if( m_currentDirs.isEmpty() ) { | ||
92 | return Path(m_buildDir, filename ); | 106 | return Path(m_buildDir, filename ); | ||
93 | } | 107 | } | ||
94 | 108 | | |||
95 | auto it = m_currentDirs.constEnd() - 1; | 109 | auto it = m_currentDirs.constEnd() - 1; | ||
96 | do { | 110 | do { | ||
97 | currentPath = Path(*it, filename); | 111 | currentPath = Path(*it, filename); | ||
98 | } while( (it-- != m_currentDirs.constBegin()) && !QFileInfo(currentPath.toLocalFile()).exists() ); | 112 | } while( (it-- != m_currentDirs.constBegin()) && !QFileInfo(currentPath.toLocalFile()).exists() ); | ||
99 | 113 | | |||
100 | return currentPath; | 114 | return currentPath; | ||
101 | } else { | 115 | } else { | ||
102 | currentPath = Path(filename); | 116 | currentPath = Path(filename); | ||
103 | } | 117 | } | ||
104 | return currentPath; | 118 | return currentPath; | ||
105 | } | 119 | } | ||
106 | 120 | | |||
107 | bool CompilerFilterStrategy::isMultiLineCase(KDevelop::ErrorFormat curErrFilter) const | 121 | bool CompilerFilterStrategyPrivate::isMultiLineCase(KDevelop::ErrorFormat curErrFilter) const | ||
108 | { | 122 | { | ||
109 | if(curErrFilter.compiler == QLatin1String("gfortran") || curErrFilter.compiler == QLatin1String("cmake")) { | 123 | if(curErrFilter.compiler == QLatin1String("gfortran") || curErrFilter.compiler == QLatin1String("cmake")) { | ||
110 | return true; | 124 | return true; | ||
111 | } | 125 | } | ||
112 | return false; | 126 | return false; | ||
113 | } | 127 | } | ||
114 | 128 | | |||
115 | void CompilerFilterStrategy::putDirAtEnd(const Path& pathToInsert) | 129 | void CompilerFilterStrategyPrivate::putDirAtEnd(const Path& pathToInsert) | ||
116 | { | 130 | { | ||
117 | auto it = m_positionInCurrentDirs.find( pathToInsert ); | 131 | CompilerFilterStrategyPrivate::PositionMap::iterator it = m_positionInCurrentDirs.find( pathToInsert ); | ||
118 | // Encountered new build directory? | 132 | // Encountered new build directory? | ||
119 | if (it == m_positionInCurrentDirs.end()) { | 133 | if (it == m_positionInCurrentDirs.end()) { | ||
120 | m_currentDirs.push_back( pathToInsert ); | 134 | m_currentDirs.push_back( pathToInsert ); | ||
121 | m_positionInCurrentDirs.insert( pathToInsert, m_currentDirs.size() - 1 ); | 135 | m_positionInCurrentDirs.insert( pathToInsert, m_currentDirs.size() - 1 ); | ||
122 | } else { | 136 | } else { | ||
123 | // Build dir already in currentDirs, but move it to back of currentDirs list | 137 | // Build dir already in currentDirs, but move it to back of currentDirs list | ||
124 | // (this gives us most-recently-used semantics in pathForFile) | 138 | // (this gives us most-recently-used semantics in pathForFile) | ||
125 | std::rotate(m_currentDirs.begin() + it.value(), m_currentDirs.begin() + it.value() + 1, m_currentDirs.end() ); | 139 | std::rotate(m_currentDirs.begin() + it.value(), m_currentDirs.begin() + it.value() + 1, m_currentDirs.end() ); | ||
126 | it.value() = m_currentDirs.size() - 1; | 140 | it.value() = m_currentDirs.size() - 1; | ||
127 | } | 141 | } | ||
128 | } | 142 | } | ||
129 | 143 | | |||
144 | CompilerFilterStrategy::CompilerFilterStrategy(const QUrl& buildDir) | ||||
145 | : d(new CompilerFilterStrategyPrivate( buildDir )) | ||||
146 | { | ||||
147 | } | ||||
148 | | ||||
149 | CompilerFilterStrategy::~CompilerFilterStrategy() | ||||
150 | { | ||||
151 | delete d; | ||||
152 | } | ||||
153 | | ||||
130 | QVector<QString> CompilerFilterStrategy::getCurrentDirs() | 154 | QVector<QString> CompilerFilterStrategy::getCurrentDirs() | ||
131 | { | 155 | { | ||
132 | QVector<QString> ret; | 156 | QVector<QString> ret; | ||
133 | ret.reserve(m_currentDirs.size()); | 157 | ret.reserve(d->m_currentDirs.size()); | ||
134 | for (const auto& path : m_currentDirs) { | 158 | for (const auto& path : d->m_currentDirs) { | ||
135 | ret << path.pathOrUrl(); | 159 | ret << path.pathOrUrl(); | ||
136 | } | 160 | } | ||
137 | return ret; | 161 | return ret; | ||
138 | } | 162 | } | ||
139 | 163 | | |||
140 | FilteredItem CompilerFilterStrategy::actionInLine(const QString& line) | 164 | FilteredItem CompilerFilterStrategy::actionInLine(const QString& line) | ||
141 | { | 165 | { | ||
142 | // A list of filters for possible compiler, linker, and make actions | 166 | // A list of filters for possible compiler, linker, and make actions | ||
Show All 39 Lines | |||||
182 | FilteredItem item(line); | 206 | FilteredItem item(line); | ||
183 | for (const auto& curActFilter : ACTION_FILTERS) { | 207 | for (const auto& curActFilter : ACTION_FILTERS) { | ||
184 | const auto match = curActFilter.expression.match(line); | 208 | const auto match = curActFilter.expression.match(line); | ||
185 | if( match.hasMatch() ) { | 209 | if( match.hasMatch() ) { | ||
186 | item.type = FilteredItem::ActionItem; | 210 | item.type = FilteredItem::ActionItem; | ||
187 | 211 | | |||
188 | if( curActFilter.tool == "cd" ) { | 212 | if( curActFilter.tool == "cd" ) { | ||
189 | const Path path(match.captured(curActFilter.fileGroup)); | 213 | const Path path(match.captured(curActFilter.fileGroup)); | ||
190 | m_currentDirs.push_back( path ); | 214 | d->m_currentDirs.push_back( path ); | ||
191 | m_positionInCurrentDirs.insert( path , m_currentDirs.size() - 1 ); | 215 | d->m_positionInCurrentDirs.insert( path , d->m_currentDirs.size() - 1 ); | ||
192 | } | 216 | } | ||
193 | 217 | | |||
194 | // Special case for cmake: we parse the "Compiling <objectfile>" expression | 218 | // Special case for cmake: we parse the "Compiling <objectfile>" expression | ||
195 | // and use it to find out about the build paths encountered during a build. | 219 | // and use it to find out about the build paths encountered during a build. | ||
196 | // They are later searched by pathForFile to find source files corresponding to | 220 | // They are later searched by pathForFile to find source files corresponding to | ||
197 | // compiler errors. | 221 | // compiler errors. | ||
198 | // Note: CMake objectfile has the format: "/path/to/four/CMakeFiles/file.o" | 222 | // Note: CMake objectfile has the format: "/path/to/four/CMakeFiles/file.o" | ||
199 | if ( curActFilter.fileGroup != -1 && curActFilter.tool == "cmake" && line.contains("Building")) { | 223 | if ( curActFilter.fileGroup != -1 && curActFilter.tool == "cmake" && line.contains("Building")) { | ||
200 | const auto objectFile = match.captured(curActFilter.fileGroup); | 224 | const auto objectFile = match.captured(curActFilter.fileGroup); | ||
201 | const auto dir = objectFile.section(QStringLiteral("CMakeFiles/"), 0, 0); | 225 | const auto dir = objectFile.section(QStringLiteral("CMakeFiles/"), 0, 0); | ||
202 | putDirAtEnd(Path(m_buildDir, dir)); | 226 | d->putDirAtEnd(Path(d->m_buildDir, dir)); | ||
203 | } | 227 | } | ||
204 | break; | 228 | break; | ||
205 | } | 229 | } | ||
206 | } | 230 | } | ||
207 | return item; | 231 | return item; | ||
208 | } | 232 | } | ||
209 | 233 | | |||
210 | FilteredItem CompilerFilterStrategy::errorInLine(const QString& line) | 234 | FilteredItem CompilerFilterStrategy::errorInLine(const QString& line) | ||
Show All 13 Lines | 241 | static const Indicator INDICATORS[] = { | |||
224 | Indicator(QStringLiteral("error"), FilteredItem::ErrorItem), | 248 | Indicator(QStringLiteral("error"), FilteredItem::ErrorItem), | ||
225 | // generic | 249 | // generic | ||
226 | Indicator(QStringLiteral("warning"), FilteredItem::WarningItem), | 250 | Indicator(QStringLiteral("warning"), FilteredItem::WarningItem), | ||
227 | Indicator(QStringLiteral("info"), FilteredItem::InformationItem), | 251 | Indicator(QStringLiteral("info"), FilteredItem::InformationItem), | ||
228 | Indicator(QStringLiteral("note"), FilteredItem::InformationItem), | 252 | Indicator(QStringLiteral("note"), FilteredItem::InformationItem), | ||
229 | }; | 253 | }; | ||
230 | 254 | | |||
231 | // A list of filters for possible compiler, linker, and make errors | 255 | // A list of filters for possible compiler, linker, and make errors | ||
232 | static const ErrorFormat ERROR_FILTERS[] = { | 256 | static const QVector<ErrorFormat> ERROR_FILTERS = { | ||
mwolff: revert this, see above | |||||
233 | #ifdef Q_OS_WIN | 257 | #ifdef Q_OS_WIN | ||
234 | // MSVC | 258 | // MSVC | ||
235 | ErrorFormat( QStringLiteral("^([a-zA-Z]:\\\\.+)\\(([1-9][0-9]*)\\): ((?:error|warning) .+\\:).*$"), 1, 2, 3 ), | 259 | ErrorFormat( QStringLiteral("^([a-zA-Z]:\\\\.+)\\(([1-9][0-9]*)\\): ((?:error|warning) .+\\:).*$"), 1, 2, 3 ), | ||
236 | #endif | 260 | #endif | ||
237 | // GCC - another case, eg. for #include "pixmap.xpm" which does not exists | 261 | // GCC - another case, eg. for #include "pixmap.xpm" which does not exists | ||
238 | ErrorFormat( QStringLiteral("^([^:\t]+):([0-9]+):([0-9]+):([^0-9]+)"), 1, 2, 4, 3 ), | 262 | ErrorFormat( QStringLiteral("^([^:\t]+):([0-9]+):([0-9]+):([^0-9]+)"), 1, 2, 4, 3 ), | ||
239 | // GCC | 263 | // GCC | ||
240 | ErrorFormat( QStringLiteral("^([^:\t]+):([0-9]+):([^0-9]+)"), 1, 2, 3 ), | 264 | ErrorFormat( QStringLiteral("^([^:\t]+):([0-9]+):([^0-9]+)"), 1, 2, 3 ), | ||
Show All 36 Lines | |||||
277 | FilteredItem item(line); | 301 | FilteredItem item(line); | ||
278 | for (const auto& curErrFilter : ERROR_FILTERS) { | 302 | for (const auto& curErrFilter : ERROR_FILTERS) { | ||
279 | const auto match = curErrFilter.expression.match(line); | 303 | const auto match = curErrFilter.expression.match(line); | ||
280 | if( match.hasMatch() && !( line.contains( QLatin1String("Each undeclared identifier is reported only once") ) | 304 | if( match.hasMatch() && !( line.contains( QLatin1String("Each undeclared identifier is reported only once") ) | ||
281 | || line.contains( QLatin1String("for each function it appears in.") ) ) ) | 305 | || line.contains( QLatin1String("for each function it appears in.") ) ) ) | ||
282 | { | 306 | { | ||
283 | if(curErrFilter.fileGroup > 0) { | 307 | if(curErrFilter.fileGroup > 0) { | ||
284 | if( curErrFilter.compiler == "cmake" ) { // Unfortunately we cannot know if an error or an action comes first in cmake, and therefore we need to do this | 308 | if( curErrFilter.compiler == "cmake" ) { // Unfortunately we cannot know if an error or an action comes first in cmake, and therefore we need to do this | ||
285 | if( m_currentDirs.empty() ) { | 309 | if( d->m_currentDirs.empty() ) { | ||
286 | putDirAtEnd( m_buildDir.parent() ); | 310 | d->putDirAtEnd( d->m_buildDir.parent() ); | ||
287 | } | 311 | } | ||
288 | } | 312 | } | ||
289 | item.url = pathForFile( match.captured( curErrFilter.fileGroup ) ).toUrl(); | 313 | item.url = d->pathForFile( match.captured( curErrFilter.fileGroup ) ).toUrl(); | ||
290 | } | 314 | } | ||
291 | item.lineNo = match.captured( curErrFilter.lineGroup ).toInt() - 1; | 315 | item.lineNo = match.captured( curErrFilter.lineGroup ).toInt() - 1; | ||
292 | if(curErrFilter.columnGroup >= 0) { | 316 | if(curErrFilter.columnGroup >= 0) { | ||
293 | item.columnNo = match.captured( curErrFilter.columnGroup ).toInt() - 1; | 317 | item.columnNo = match.captured( curErrFilter.columnGroup ).toInt() - 1; | ||
294 | } else { | 318 | } else { | ||
295 | item.columnNo = 0; | 319 | item.columnNo = 0; | ||
296 | } | 320 | } | ||
297 | 321 | | |||
Show All 10 Lines | |||||
308 | } | 332 | } | ||
309 | 333 | | |||
310 | // Make the item clickable if it comes with the necessary file information | 334 | // Make the item clickable if it comes with the necessary file information | ||
311 | if (item.url.isValid()) { | 335 | if (item.url.isValid()) { | ||
312 | item.isActivatable = true; | 336 | item.isActivatable = true; | ||
313 | if(item.type == FilteredItem::InvalidItem) { | 337 | if(item.type == FilteredItem::InvalidItem) { | ||
314 | // If there are no error indicators in the line | 338 | // If there are no error indicators in the line | ||
315 | // maybe this is a multiline case | 339 | // maybe this is a multiline case | ||
316 | if(isMultiLineCase(curErrFilter)) { | 340 | if(d->isMultiLineCase(curErrFilter)) { | ||
317 | item.type = FilteredItem::ErrorItem; | 341 | item.type = FilteredItem::ErrorItem; | ||
318 | } else { | 342 | } else { | ||
319 | // Okay so we couldn't find anything to indicate an error, but we have file and lineGroup | 343 | // Okay so we couldn't find anything to indicate an error, but we have file and lineGroup | ||
320 | // Lets keep this item clickable and indicate this to the user. | 344 | // Lets keep this item clickable and indicate this to the user. | ||
321 | item.type = FilteredItem::InformationItem; | 345 | item.type = FilteredItem::InformationItem; | ||
322 | } | 346 | } | ||
323 | } | 347 | } | ||
324 | } | 348 | } | ||
Show All 13 Lines | |||||
338 | FilteredItem ScriptErrorFilterStrategy::actionInLine(const QString& line) | 362 | FilteredItem ScriptErrorFilterStrategy::actionInLine(const QString& line) | ||
339 | { | 363 | { | ||
340 | return FilteredItem(line); | 364 | return FilteredItem(line); | ||
341 | } | 365 | } | ||
342 | 366 | | |||
343 | FilteredItem ScriptErrorFilterStrategy::errorInLine(const QString& line) | 367 | FilteredItem ScriptErrorFilterStrategy::errorInLine(const QString& line) | ||
344 | { | 368 | { | ||
345 | // A list of filters for possible Python and PHP errors | 369 | // A list of filters for possible Python and PHP errors | ||
346 | static const ErrorFormat SCRIPT_ERROR_FILTERS[] = { | 370 | static const QVector<ErrorFormat> SCRIPT_ERROR_FILTERS = { | ||
347 | ErrorFormat( QStringLiteral("^ File \"(.*)\", line ([0-9]+)(.*$|, in(.*)$)"), 1, 2, -1 ), | 371 | ErrorFormat( QStringLiteral("^ File \"(.*)\", line ([0-9]+)(.*$|, in(.*)$)"), 1, 2, -1 ), | ||
348 | ErrorFormat( QStringLiteral("^.*(/.*):([0-9]+).*$"), 1, 2, -1 ), | 372 | ErrorFormat( QStringLiteral("^.*(/.*):([0-9]+).*$"), 1, 2, -1 ), | ||
349 | ErrorFormat( QStringLiteral("^.* in (/.*) on line ([0-9]+).*$"), 1, 2, -1 ) | 373 | ErrorFormat( QStringLiteral("^.* in (/.*) on line ([0-9]+).*$"), 1, 2, -1 ) | ||
350 | }; | 374 | }; | ||
351 | 375 | | |||
352 | return match(SCRIPT_ERROR_FILTERS, line); | 376 | return match(SCRIPT_ERROR_FILTERS, line); | ||
353 | } | 377 | } | ||
354 | 378 | | |||
355 | /// --- Native application error filter strategy --- | 379 | /// --- Native application error filter strategy --- | ||
356 | 380 | | |||
357 | NativeAppErrorFilterStrategy::NativeAppErrorFilterStrategy() | 381 | NativeAppErrorFilterStrategy::NativeAppErrorFilterStrategy() | ||
358 | { | 382 | { | ||
359 | } | 383 | } | ||
360 | 384 | | |||
361 | FilteredItem NativeAppErrorFilterStrategy::actionInLine(const QString& line) | 385 | FilteredItem NativeAppErrorFilterStrategy::actionInLine(const QString& line) | ||
362 | { | 386 | { | ||
363 | return FilteredItem(line); | 387 | return FilteredItem(line); | ||
364 | } | 388 | } | ||
365 | 389 | | |||
366 | FilteredItem NativeAppErrorFilterStrategy::errorInLine(const QString& line) | 390 | FilteredItem NativeAppErrorFilterStrategy::errorInLine(const QString& line) | ||
367 | { | 391 | { | ||
368 | static const ErrorFormat NATIVE_APPLICATION_ERROR_FILTERS[] = { | 392 | static const QVector<ErrorFormat> NATIVE_APPLICATION_ERROR_FILTERS = { | ||
369 | // BEGIN: C++ | 393 | // BEGIN: C++ | ||
370 | 394 | | |||
371 | // a.out: test.cpp:5: int main(): Assertion `false' failed. | 395 | // a.out: test.cpp:5: int main(): Assertion `false' failed. | ||
372 | ErrorFormat(QStringLiteral("^.+: (.+):([1-9][0-9]*): .*: Assertion `.*' failed\\.$"), 1, 2, -1), | 396 | ErrorFormat(QStringLiteral("^.+: (.+):([1-9][0-9]*): .*: Assertion `.*' failed\\.$"), 1, 2, -1), | ||
373 | 397 | | |||
374 | // END: C++ | 398 | // END: C++ | ||
375 | 399 | | |||
376 | // BEGIN: Qt | 400 | // BEGIN: Qt | ||
Show All 35 Lines | |||||
412 | FilteredItem StaticAnalysisFilterStrategy::actionInLine(const QString& line) | 436 | FilteredItem StaticAnalysisFilterStrategy::actionInLine(const QString& line) | ||
413 | { | 437 | { | ||
414 | return FilteredItem(line); | 438 | return FilteredItem(line); | ||
415 | } | 439 | } | ||
416 | 440 | | |||
417 | FilteredItem StaticAnalysisFilterStrategy::errorInLine(const QString& line) | 441 | FilteredItem StaticAnalysisFilterStrategy::errorInLine(const QString& line) | ||
418 | { | 442 | { | ||
419 | // A list of filters for static analysis tools (krazy2, cppcheck) | 443 | // A list of filters for static analysis tools (krazy2, cppcheck) | ||
420 | static const ErrorFormat STATIC_ANALYSIS_FILTERS[] = { | 444 | static const QVector<ErrorFormat> STATIC_ANALYSIS_FILTERS = { | ||
421 | // CppCheck | 445 | // CppCheck | ||
422 | ErrorFormat( QStringLiteral("^\\[(.*):([0-9]+)\\]:(.*)"), 1, 2, 3 ), | 446 | ErrorFormat( QStringLiteral("^\\[(.*):([0-9]+)\\]:(.*)"), 1, 2, 3 ), | ||
423 | // krazy2 | 447 | // krazy2 | ||
424 | ErrorFormat( QStringLiteral("^\\t([^:]+).*line#([0-9]+).*"), 1, 2, -1 ), | 448 | ErrorFormat( QStringLiteral("^\\t([^:]+).*line#([0-9]+).*"), 1, 2, -1 ), | ||
425 | // krazy2 without line info | 449 | // krazy2 without line info | ||
426 | ErrorFormat( QStringLiteral("^\\t(.*): missing license"), 1, -1, -1 ) | 450 | ErrorFormat( QStringLiteral("^\\t(.*): missing license"), 1, -1, -1 ) | ||
427 | }; | 451 | }; | ||
428 | 452 | | |||
429 | return match(STATIC_ANALYSIS_FILTERS, line); | 453 | return match(STATIC_ANALYSIS_FILTERS, line); | ||
430 | } | 454 | } | ||
455 | | ||||
456 | } |
keep this template here and use it in this file. that way, we can still have the simple data here in RO memory.
for the outside, feel free to offer a public QVector match function or similar (too bad we don't have array_view yet), and then call this template internally.