2012-10-02 09:12:39 +02:00
/****************************************************************************
2010-08-03 17:24:20 +02:00
* *
2016-01-15 14:57:40 +01:00
* * Copyright ( C ) 2016 The Qt Company Ltd .
* * Contact : https : //www.qt.io/licensing/
2010-08-03 17:24:20 +02:00
* *
2012-10-02 09:12:39 +02:00
* * This file is part of Qt Creator .
2010-08-03 17:24:20 +02:00
* *
2012-10-02 09:12:39 +02:00
* * Commercial License Usage
* * Licensees holding valid commercial Qt licenses may use this file in
* * accordance with the commercial license agreement provided with the
* * Software or , alternatively , in accordance with the terms contained in
2016-01-15 14:57:40 +01:00
* * a written agreement between you and The Qt Company . For licensing terms
* * and conditions see https : //www.qt.io/terms-conditions. For further
* * information use the contact form at https : //www.qt.io/contact-us.
2010-08-03 17:24:20 +02:00
* *
2016-01-15 14:57:40 +01:00
* * GNU General Public License Usage
* * Alternatively , this file may be used under the terms of the GNU
* * General Public License version 3 as published by the Free Software
* * Foundation with exceptions as appearing in the file LICENSE . GPL3 - EXCEPT
* * included in the packaging of this file . Please review the following
* * information to ensure the GNU General Public License requirements will
* * be met : https : //www.gnu.org/licenses/gpl-3.0.html.
2010-12-17 16:01:08 +01:00
* *
2012-10-02 09:12:39 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-08-03 17:24:20 +02:00
# include "qtparser.h"
2011-08-18 13:46:52 +02:00
# include <projectexplorer/task.h>
2010-08-03 17:24:20 +02:00
# include <projectexplorer/projectexplorerconstants.h>
2011-08-18 13:46:52 +02:00
2020-04-16 13:53:05 +02:00
# include <QFileInfo>
# ifdef WITH_TESTS
# include "qtsupportplugin.h"
# include <projectexplorer/outputparser_test.h>
# include <QTest>
# endif
2020-01-15 08:56:11 +01:00
using namespace ProjectExplorer ;
2010-08-03 17:24:20 +02:00
2020-04-16 13:53:05 +02:00
namespace QtSupport {
2011-08-17 11:34:57 +02:00
// opt. drive letter + filename: (2 brackets)
2021-07-26 17:51:55 +02:00
# define FILE_PATTERN R"(^(?<file>(?:[A-Za-z]:)?[^:\(]+\.[^:\(]+))"
2010-08-03 17:24:20 +02:00
2011-08-18 13:46:52 +02:00
QtParser : : QtParser ( ) :
2021-07-26 17:51:55 +02:00
m_mocRegExp ( FILE_PATTERN R " ([: \ (](?<line> \ d+)?(?::(?<column> \ d+))? \ )?: \ s(?<level>[Ww]arning|[Ee]rror|[Nn]ote): \ s(?<description>.+?)$) " ) ,
2021-07-26 16:54:14 +02:00
m_uicRegExp ( FILE_PATTERN R " (: Warning: \ s(?<msg>.+?)$) " ) ,
2021-07-26 17:07:04 +02:00
m_translationRegExp ( R " (^(?<level>[Ww]arning|[Ee]rror): \ s+(?<description>.*?) in '(?<file>.*?)'$) " )
2010-08-03 17:24:20 +02:00
{
2010-09-15 13:55:01 +02:00
setObjectName ( QLatin1String ( " QtParser " ) ) ;
2010-08-03 17:24:20 +02:00
}
2020-04-16 13:53:05 +02:00
Utils : : OutputLineParser : : Result QtParser : : handleLine ( const QString & line , Utils : : OutputFormat type )
2010-08-03 17:24:20 +02:00
{
2020-04-08 17:45:39 +02:00
if ( type ! = Utils : : StdErrFormat )
return Status : : NotHandled ;
2013-04-02 15:21:59 +02:00
QString lne = rightTrimmed ( line ) ;
2020-06-16 08:59:54 +02:00
QRegularExpressionMatch match = m_mocRegExp . match ( lne ) ;
if ( match . hasMatch ( ) ) {
2010-08-03 17:24:20 +02:00
bool ok ;
2021-07-26 17:07:04 +02:00
int lineno = match . captured ( " line " ) . toInt ( & ok ) ;
2010-08-03 17:24:20 +02:00
if ( ! ok )
lineno = - 1 ;
2014-01-14 10:28:16 +01:00
Task : : TaskType type = Task : : Error ;
2021-07-26 17:07:04 +02:00
const QString level = match . captured ( " level " ) ;
2014-07-24 11:46:58 +02:00
if ( level . compare ( QLatin1String ( " Warning " ) , Qt : : CaseInsensitive ) = = 0 )
2014-01-14 10:28:16 +01:00
type = Task : : Warning ;
2014-07-24 11:46:58 +02:00
if ( level . compare ( QLatin1String ( " Note " ) , Qt : : CaseInsensitive ) = = 0 )
type = Task : : Unknown ;
2020-04-16 13:53:05 +02:00
LinkSpecs linkSpecs ;
const Utils : : FilePath file
2021-07-26 17:07:04 +02:00
= absoluteFilePath ( Utils : : FilePath : : fromUserInput ( match . captured ( " file " ) ) ) ;
addLinkSpecForAbsoluteFilePath ( linkSpecs , file , lineno , match , " file " ) ;
CompileTask task ( type , match . captured ( " description " ) . trimmed ( ) , file , lineno ) ;
2021-07-26 17:51:55 +02:00
task . column = match . captured ( " column " ) . toInt ( ) ;
2020-04-16 13:53:05 +02:00
scheduleTask ( task , 1 ) ;
return { Status : : Done , linkSpecs } ;
2010-08-03 17:24:20 +02:00
}
2021-05-06 16:29:42 +02:00
match = m_uicRegExp . match ( lne ) ;
if ( match . hasMatch ( ) ) {
const QString fileName = match . captured ( 1 ) ;
QString message = match . captured ( " msg " ) . trimmed ( ) ;
Utils : : FilePath filePath ;
LinkSpecs linkSpecs ;
bool isUicMessage = true ;
if ( fileName = = " uic " | | fileName = = " stdin " ) {
message . prepend ( " : " ) . prepend ( fileName ) ;
} else if ( fileName . endsWith ( " .ui " ) ) {
filePath = absoluteFilePath ( Utils : : FilePath : : fromUserInput ( fileName ) ) ;
2021-07-26 17:07:04 +02:00
addLinkSpecForAbsoluteFilePath ( linkSpecs , filePath , - 1 , match , " file " ) ;
2021-05-06 16:29:42 +02:00
} else {
isUicMessage = false ;
}
if ( isUicMessage ) {
scheduleTask ( CompileTask ( Task : : Warning , message , filePath ) , 1 ) ;
return { Status : : Done , linkSpecs } ;
}
}
2020-06-16 08:59:54 +02:00
match = m_translationRegExp . match ( line ) ;
if ( match . hasMatch ( ) ) {
2013-12-11 17:50:17 +01:00
Task : : TaskType type = Task : : Warning ;
2021-07-26 17:07:04 +02:00
if ( match . captured ( " level " ) = = QLatin1String ( " Error " ) )
2013-12-11 17:50:17 +01:00
type = Task : : Error ;
2020-04-16 13:53:05 +02:00
LinkSpecs linkSpecs ;
const Utils : : FilePath file
2021-07-26 17:07:04 +02:00
= absoluteFilePath ( Utils : : FilePath : : fromUserInput ( match . captured ( " file " ) ) ) ;
addLinkSpecForAbsoluteFilePath ( linkSpecs , file , 0 , match , " file " ) ;
CompileTask task ( type , match . captured ( " description " ) , file ) ;
2020-04-16 13:53:05 +02:00
scheduleTask ( task , 1 ) ;
return { Status : : Done , linkSpecs } ;
2013-12-11 17:50:17 +01:00
}
2020-04-08 17:45:39 +02:00
return Status : : NotHandled ;
2010-08-03 17:24:20 +02:00
}
// Unit tests:
# ifdef WITH_TESTS
2020-04-16 13:53:05 +02:00
namespace Internal {
2010-08-03 17:24:20 +02:00
2011-05-24 16:15:15 +02:00
void QtSupportPlugin : : testQtOutputParser_data ( )
2010-08-03 17:24:20 +02:00
{
QTest : : addColumn < QString > ( " input " ) ;
QTest : : addColumn < OutputParserTester : : Channel > ( " inputChannel " ) ;
QTest : : addColumn < QString > ( " childStdOutLines " ) ;
QTest : : addColumn < QString > ( " childStdErrLines " ) ;
2019-05-27 16:09:44 +02:00
QTest : : addColumn < Tasks > ( " tasks " ) ;
2010-08-03 17:24:20 +02:00
QTest : : addColumn < QString > ( " outputLines " ) ;
QTest : : newRow ( " pass-through stdout " )
< < QString : : fromLatin1 ( " Sometext " ) < < OutputParserTester : : STDOUT
2011-05-18 18:39:14 +02:00
< < QString : : fromLatin1 ( " Sometext \n " ) < < QString ( )
2019-05-27 16:09:44 +02:00
< < Tasks ( )
2010-08-03 17:24:20 +02:00
< < QString ( ) ;
QTest : : newRow ( " pass-through stderr " )
< < QString : : fromLatin1 ( " Sometext " ) < < OutputParserTester : : STDERR
2011-05-18 18:39:14 +02:00
< < QString ( ) < < QString : : fromLatin1 ( " Sometext \n " )
2019-05-27 16:09:44 +02:00
< < Tasks ( )
2010-08-03 17:24:20 +02:00
< < QString ( ) ;
2010-09-15 13:55:01 +02:00
QTest : : newRow ( " pass-through gcc infos " )
< < QString : : fromLatin1 ( " /temp/test/untitled8/main.cpp: In function `int main(int, char**)': \n "
" ../../scriptbug/main.cpp: At global scope: \n "
" ../../scriptbug/main.cpp: In instantiation of void bar(i) [with i = double]: \n "
" ../../scriptbug/main.cpp:8: instantiated from void foo(i) [with i = double] \n "
2011-05-18 18:39:14 +02:00
" ../../scriptbug/main.cpp:22: instantiated from here " )
2010-09-15 13:55:01 +02:00
< < OutputParserTester : : STDERR
< < QString ( )
< < QString : : fromLatin1 ( " /temp/test/untitled8/main.cpp: In function `int main(int, char**)': \n "
" ../../scriptbug/main.cpp: At global scope: \n "
" ../../scriptbug/main.cpp: In instantiation of void bar(i) [with i = double]: \n "
" ../../scriptbug/main.cpp:8: instantiated from void foo(i) [with i = double] \n "
" ../../scriptbug/main.cpp:22: instantiated from here \n " )
2019-05-27 16:09:44 +02:00
< < Tasks ( )
2010-09-15 13:55:01 +02:00
< < QString ( ) ;
2012-10-11 18:32:08 +02:00
QTest : : newRow ( " qdoc warning " )
< < QString : : fromLatin1 ( " /home/user/dev/qt5/qtscript/src/script/api/qscriptengine.cpp:295: warning: Can't create link to 'Object Trees & Ownership' " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
2020-01-15 08:56:11 +01:00
< < ( Tasks ( ) < < CompileTask ( Task : : Warning ,
2012-10-11 18:32:08 +02:00
QLatin1String ( " Can't create link to 'Object Trees & Ownership' " ) ,
2020-01-15 08:56:11 +01:00
Utils : : FilePath : : fromUserInput ( QLatin1String ( " /home/user/dev/qt5/qtscript/src/script/api/qscriptengine.cpp " ) ) , 295 ) )
2012-10-11 18:32:08 +02:00
< < QString ( ) ;
2010-08-03 17:24:20 +02:00
QTest : : newRow ( " moc warning " )
< < QString : : fromLatin1 ( " .. \\ untitled \\ errorfile.h:0: Warning: No relevant classes found. No output generated. " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
2020-01-15 08:56:11 +01:00
< < ( Tasks ( ) < < CompileTask ( Task : : Warning ,
2010-08-03 17:24:20 +02:00
QLatin1String ( " No relevant classes found. No output generated. " ) ,
2020-04-16 13:53:05 +02:00
Utils : : FilePath : : fromUserInput ( QLatin1String ( " .. \\ untitled \\ errorfile.h " ) ) , - 1 ) )
2010-08-03 17:24:20 +02:00
< < QString ( ) ;
2011-01-20 11:16:00 +01:00
QTest : : newRow ( " moc warning 2 " )
< < QString : : fromLatin1 ( " c: \\ code \\ test.h(96): Warning: Property declaration ) has no READ accessor function. The property will be invalid. " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
2020-01-15 08:56:11 +01:00
< < ( Tasks ( ) < < CompileTask ( Task : : Warning ,
2011-01-20 11:16:00 +01:00
QLatin1String ( " Property declaration ) has no READ accessor function. The property will be invalid. " ) ,
2020-01-15 08:56:11 +01:00
Utils : : FilePath : : fromUserInput ( QLatin1String ( " c: \\ code \\ test.h " ) ) , 96 ) )
2011-01-20 11:16:00 +01:00
< < QString ( ) ;
2021-07-26 17:51:55 +02:00
QTest : : newRow ( " moc warning (Qt 6/Windows) " )
< < QString : : fromLatin1 ( R " (C:/Users/alportal/dev/qt-creator-qt6/src/plugins/qmlprofiler/qmlprofilerplugin.h(38:1): error: Plugin Metadata file " QmlProfiler . json " does not exist. Declaration will be ignored) " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
< < ( Tasks ( ) < < CompileTask ( Task : : Error ,
R " (Plugin Metadata file " QmlProfiler . json " does not exist. Declaration will be ignored) " ,
Utils : : FilePath : : fromUserInput ( " C:/Users/alportal/dev/qt-creator-qt6/src/plugins/qmlprofiler/qmlprofilerplugin.h " ) , 38 , 1 ) )
< < QString ( ) ;
QTest : : newRow ( " moc warning (Qt 6/Unix) " )
< < QString : : fromLatin1 ( R " (/Users/alportal/dev/qt-creator-qt6/src/plugins/qmlprofiler/qmlprofilerplugin.h:38:1: error: Plugin Metadata file " QmlProfiler . json " does not exist. Declaration will be ignored) " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
< < ( Tasks ( ) < < CompileTask ( Task : : Error ,
R " (Plugin Metadata file " QmlProfiler . json " does not exist. Declaration will be ignored) " ,
Utils : : FilePath : : fromUserInput ( " /Users/alportal/dev/qt-creator-qt6/src/plugins/qmlprofiler/qmlprofilerplugin.h " ) , 38 , 1 ) )
< < QString ( ) ;
2014-07-24 11:46:58 +02:00
QTest : : newRow ( " moc note " )
< < QString : : fromLatin1 ( " /home/qtwebkithelpviewer.h:0: Note: No relevant classes found. No output generated. " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
2020-01-15 08:56:11 +01:00
< < ( Tasks ( ) < < CompileTask ( Task : : Unknown ,
2014-07-24 11:46:58 +02:00
QLatin1String ( " No relevant classes found. No output generated. " ) ,
2020-04-16 13:53:05 +02:00
Utils : : FilePath : : fromUserInput ( QLatin1String ( " /home/qtwebkithelpviewer.h " ) ) , - 1 ) )
2014-07-24 11:46:58 +02:00
< < QString ( ) ;
2012-09-26 17:41:50 +02:00
QTest : : newRow ( " ninja with moc " )
< < QString : : fromLatin1 ( " E:/sandbox/creator/loaden/src/libs/utils/iwelcomepage.h(54): Error: Undefined interface " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
2020-01-15 08:56:11 +01:00
< < ( Tasks ( ) < < CompileTask ( Task : : Error ,
2012-09-26 17:41:50 +02:00
QLatin1String ( " Undefined interface " ) ,
2020-01-15 08:56:11 +01:00
Utils : : FilePath : : fromUserInput ( QLatin1String ( " E:/sandbox/creator/loaden/src/libs/utils/iwelcomepage.h " ) ) , 54 ) )
2012-09-26 17:41:50 +02:00
< < QString ( ) ;
2021-05-06 16:29:42 +02:00
QTest : : newRow ( " uic warning " )
< < QString : : fromLatin1 ( " mainwindow.ui: Warning: The name 'pushButton' (QPushButton) is already in use, defaulting to 'pushButton1'. " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
< < ( Tasks ( )
< < CompileTask ( Task : : Warning ,
" The name 'pushButton' (QPushButton) is already in use, defaulting to 'pushButton1'. " ,
Utils : : FilePath : : fromUserInput ( " mainwindow.ui " ) ) )
< < QString ( ) ;
2013-12-11 17:50:17 +01:00
QTest : : newRow ( " translation " )
< < QString : : fromLatin1 ( " Warning: dropping duplicate messages in '/some/place/qtcreator_fr.qm' " )
< < OutputParserTester : : STDERR
< < QString ( ) < < QString ( )
2020-01-15 08:56:11 +01:00
< < ( Tasks ( ) < < CompileTask ( Task : : Warning ,
2013-12-11 17:50:17 +01:00
QLatin1String ( " dropping duplicate messages " ) ,
2020-01-15 08:56:11 +01:00
Utils : : FilePath : : fromUserInput ( QLatin1String ( " /some/place/qtcreator_fr.qm " ) ) , - 1 ) )
2013-12-11 17:50:17 +01:00
< < QString ( ) ;
2010-08-03 17:24:20 +02:00
}
2011-05-24 16:15:15 +02:00
void QtSupportPlugin : : testQtOutputParser ( )
2010-08-03 17:24:20 +02:00
{
OutputParserTester testbench ;
2020-04-08 17:45:39 +02:00
testbench . addLineParser ( new QtParser ) ;
2010-08-03 17:24:20 +02:00
QFETCH ( QString , input ) ;
QFETCH ( OutputParserTester : : Channel , inputChannel ) ;
2019-05-27 16:09:44 +02:00
QFETCH ( Tasks , tasks ) ;
2010-08-03 17:24:20 +02:00
QFETCH ( QString , childStdOutLines ) ;
QFETCH ( QString , childStdErrLines ) ;
QFETCH ( QString , outputLines ) ;
testbench . testParsing ( input , inputChannel , tasks , childStdOutLines , childStdErrLines , outputLines ) ;
}
2020-04-16 13:53:05 +02:00
} // namespace Internal
2010-08-03 17:24:20 +02:00
# endif
2020-04-16 13:53:05 +02:00
} // namespace QtSupport