Changeset View
Changeset View
Standalone View
Standalone View
kdevplatform/outputview/outputfilteringstrategies.cpp
Show All 18 Lines | |||||
19 | #include "outputfilteringstrategies.h" | 19 | #include "outputfilteringstrategies.h" | ||
20 | #include "outputformats.h" | 20 | #include "outputformats.h" | ||
21 | #include "filtereditem.h" | 21 | #include "filtereditem.h" | ||
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 | #include <QDir> | ||||
27 | 28 | | |||
28 | #include <algorithm> | 29 | #include <algorithm> | ||
29 | 30 | | |||
30 | namespace KDevelop | 31 | namespace KDevelop | ||
31 | { | 32 | { | ||
32 | void initializeFilteredItem(FilteredItem& item, const ErrorFormat& filter, const QRegularExpressionMatch& match) | 33 | void initializeFilteredItem(FilteredItem& item, const ErrorFormat& filter, const QRegularExpressionMatch& match) | ||
33 | { | 34 | { | ||
34 | item.lineNo = match.captured( filter.lineGroup ).toInt() - 1; | 35 | item.lineNo = match.captured( filter.lineGroup ).toInt() - 1; | ||
▲ Show 20 Lines • Show All 312 Lines • ▼ Show 20 Line(s) | 305 | for (const auto& curErrFilter : ERROR_FILTERS) { | |||
347 | } | 348 | } | ||
348 | } | 349 | } | ||
349 | return item; | 350 | return item; | ||
350 | } | 351 | } | ||
351 | 352 | | |||
352 | 353 | | |||
353 | /// --- Script error filter strategy --- | 354 | /// --- Script error filter strategy --- | ||
354 | 355 | | |||
355 | ScriptErrorFilterStrategy::ScriptErrorFilterStrategy() | 356 | ScriptErrorFilterStrategy::ScriptErrorFilterStrategy(const QString &scriptdir) | ||
357 | : scriptDir(scriptdir) | ||||
356 | { | 358 | { | ||
357 | } | 359 | } | ||
358 | 360 | | |||
359 | FilteredItem ScriptErrorFilterStrategy::actionInLine(const QString& line) | 361 | FilteredItem ScriptErrorFilterStrategy::actionInLine(const QString& line) | ||
360 | { | 362 | { | ||
361 | return FilteredItem(line); | 363 | return FilteredItem(line); | ||
362 | } | 364 | } | ||
363 | 365 | | |||
364 | FilteredItem ScriptErrorFilterStrategy::errorInLine(const QString& line) | 366 | FilteredItem ScriptErrorFilterStrategy::errorInLine(const QString& line) | ||
365 | { | 367 | { | ||
366 | // A list of filters for possible Python and PHP errors | 368 | // A list of filters for possible Python and PHP errors | ||
367 | static const ErrorFormat SCRIPT_ERROR_FILTERS[] = { | 369 | static const ErrorFormat SCRIPT_ERROR_FILTERS[] = { | ||
370 | // php trigger_error message | ||||
371 | ErrorFormat( QStringLiteral("^PHP\\s+(.*?):.* in\\s+(/.*) on line ([0-9]+)$"), 2, 3, 1, QStringLiteral("PHP") ), | ||||
372 | // php trigger_error stack trace | ||||
373 | // PHP 2. trigger_error() /home/proyect/yii:6 | ||||
374 | ErrorFormat( QStringLiteral("^(PHP\\s+)[0-9]+\\.\\s+.*\\s+(/.*):([0-9]+)$"), 2, 3, 1, QStringLiteral("PHP") ), | ||||
375 | // PHP Uncaught Error | ||||
376 | ErrorFormat( QStringLiteral("^PHP.*(error):.* in (/.*):([0-9]+)$"), 2, 3, 1, QStringLiteral("PHP") ), | ||||
377 | // PHP Uncaught Error stack trace | ||||
378 | // #0 /home/proyect/yii(6): bad() | ||||
379 | ErrorFormat( QStringLiteral("^\\#[0-9]+\\s+(/.*)\\(([0-9]+)\\):.*$"), 1, 2, -1, QStringLiteral("PHP") ), | ||||
380 | // PHP Uncaught Error stack trace, last thrown | ||||
381 | ErrorFormat( QStringLiteral("^(thrown) in\\s+(/.*) on line ([0-9]+)$"), 2, 3, 1, QStringLiteral("PHP") ), | ||||
382 | // ungreedy with no trailing text, usually the output of the php function trigger_error() | ||||
383 | ErrorFormat( QStringLiteral("^.*\\.\\s+(/.*?):([0-9]+)$"), 1, 2, 0 ), | ||||
384 | // Another stack trace format (seen with CodeCeption) | ||||
385 | // #0 /home/proyect/yii:6 | ||||
386 | ErrorFormat( QStringLiteral("^\\#[0-9]+\\s+(/.*):([0-9]+)$"), 1, 2, -1, QStringLiteral("PHP") ), | ||||
387 | // Codeception scenario steps | ||||
388 | ErrorFormat( QStringLiteral("^.*at\\s+(.*):([0-9]+)$"), 1, 2, 0, QStringLiteral("PHP") ), | ||||
389 | // Codeception summary failed tests | ||||
390 | ErrorFormat( QStringLiteral("^\\s*Test\\s+(.*):.*$"), 1, -1, -1, QStringLiteral("CodeCeption") ), | ||||
391 | // Codeception functional tests response | ||||
392 | ErrorFormat( QStringLiteral("^\\s*(Response:)\\s+(/.*)$"), 2, -1, 1), | ||||
368 | ErrorFormat( QStringLiteral("^ File \"(.*)\", line ([0-9]+)(.*$|, in(.*)$)"), 1, 2, -1 ), | 393 | ErrorFormat( QStringLiteral("^ File \"(.*)\", line ([0-9]+)(.*$|, in(.*)$)"), 1, 2, -1 ), | ||
369 | ErrorFormat( QStringLiteral("^.*(/.*):([0-9]+).*$"), 1, 2, -1 ), | 394 | ErrorFormat( QStringLiteral("^.*(/.*):([0-9]+).*$"), 1, 2, -1 ), | ||
370 | ErrorFormat( QStringLiteral("^.* in (/.*) on line ([0-9]+).*$"), 1, 2, -1 ) | 395 | ErrorFormat( QStringLiteral("^.* in (/.*) on line ([0-9]+).*$"), 1, 2, -1 ), | ||
396 | | ||||
397 | }; | ||||
398 | using Indicator = QPair<QString, FilteredItem::FilteredOutputItemType>; | ||||
399 | static const Indicator INDICATORS[] = { | ||||
400 | // PHP | ||||
401 | Indicator(QStringLiteral("Warning"), FilteredItem::WarningItem), | ||||
402 | // Indicator(QStringLiteral("Notice:"), FilteredItem::InformationItem), | ||||
403 | // Indicator(QStringLiteral("thrown:"), FilteredItem::InformationItem), | ||||
404 | Indicator(QStringLiteral("error"), FilteredItem::ErrorItem), | ||||
405 | Indicator(QStringLiteral("DEPRECATION"), FilteredItem::WarningItem), | ||||
406 | // Indicator(QStringLiteral("Response:"), FilteredItem::InformationItem), | ||||
407 | // Indicator(QStringLiteral("PHP "), FilteredItem::InformationItem), | ||||
371 | }; | 408 | }; | ||
409 | FilteredItem item(line); | ||||
410 | for (const auto& curErrFilter : SCRIPT_ERROR_FILTERS) { | ||||
411 | const auto match = curErrFilter.expression.match(line); | ||||
412 | if( match.hasMatch() ) | ||||
413 | { | ||||
414 | QString url; | ||||
415 | if(curErrFilter.fileGroup > 0) { | ||||
416 | url = match.captured( curErrFilter.fileGroup ); | ||||
417 | QFileInfo fi(url); | ||||
418 | if( fi.isRelative() ) { | ||||
419 | url = scriptDir + QDir::separator() + url; | ||||
420 | } | ||||
421 | } | ||||
422 | item.type = FilteredItem::InformationItem; | ||||
423 | item.url = Path(url).toUrl(); | ||||
424 | initializeFilteredItem(item, curErrFilter, match); | ||||
425 | const QString txt = match.captured(curErrFilter.textGroup); | ||||
426 | | ||||
427 | // Find the indicator which happens most early. | ||||
428 | int earliestIndicatorIdx = txt.length(); | ||||
429 | for (const auto& curIndicator : INDICATORS) { | ||||
430 | int curIndicatorIdx = txt.indexOf(curIndicator.first, 0, Qt::CaseInsensitive); | ||||
431 | if((curIndicatorIdx >= 0) && (earliestIndicatorIdx > curIndicatorIdx)) { | ||||
432 | earliestIndicatorIdx = curIndicatorIdx; | ||||
433 | item.type = curIndicator.second; | ||||
434 | } | ||||
435 | } | ||||
372 | 436 | | |||
373 | return match(SCRIPT_ERROR_FILTERS, line); | 437 | // Make the item clickable if it comes with the necessary file information | ||
438 | if (item.url.isValid()) { | ||||
439 | item.isActivatable = true; | ||||
440 | if(item.type == FilteredItem::InvalidItem) { | ||||
441 | // Okay so we couldn't find anything to indicate an error, but we have file and lineGroup | ||||
442 | // Lets keep this item clickable and indicate this to the user. | ||||
443 | item.type = FilteredItem::InformationItem; | ||||
444 | } | ||||
445 | } | ||||
446 | break; | ||||
447 | } | ||||
448 | } | ||||
449 | return item; | ||||
374 | } | 450 | } | ||
375 | 451 | | |||
376 | /// --- Native application error filter strategy --- | 452 | /// --- Native application error filter strategy --- | ||
377 | 453 | | |||
378 | NativeAppErrorFilterStrategy::NativeAppErrorFilterStrategy() | 454 | NativeAppErrorFilterStrategy::NativeAppErrorFilterStrategy() | ||
379 | { | 455 | { | ||
380 | } | 456 | } | ||
381 | 457 | | |||
▲ Show 20 Lines • Show All 77 Lines • Show Last 20 Lines |