diff options
Diffstat (limited to 'src/plugins/projectexplorer/gnumakeparser.cpp')
-rw-r--r-- | src/plugins/projectexplorer/gnumakeparser.cpp | 228 |
1 files changed, 55 insertions, 173 deletions
diff --git a/src/plugins/projectexplorer/gnumakeparser.cpp b/src/plugins/projectexplorer/gnumakeparser.cpp index 506f0cfe2d..6bb7442e0c 100644 --- a/src/plugins/projectexplorer/gnumakeparser.cpp +++ b/src/plugins/projectexplorer/gnumakeparser.cpp @@ -29,7 +29,7 @@ #include "task.h" #include <utils/qtcassert.h> -#include <utils/temporarydirectory.h> +#include <utils/temporaryfile.h> #include <QDir> #include <QFile> @@ -56,33 +56,6 @@ GnuMakeParser::GnuMakeParser() QTC_CHECK(m_errorInMakefile.isValid()); } -void GnuMakeParser::setWorkingDirectory(const QString &workingDirectory) -{ - addDirectory(workingDirectory); - IOutputParser::setWorkingDirectory(workingDirectory); -} - -bool GnuMakeParser::hasFatalErrors() const -{ - return (m_fatalErrorCount > 0) || IOutputParser::hasFatalErrors(); -} - -void GnuMakeParser::stdOutput(const QString &line) -{ - const QString lne = rightTrimmed(line); - - QRegularExpressionMatch match = m_makeDir.match(lne); - if (match.hasMatch()) { - if (match.captured(6) == QLatin1String("Leaving")) - removeDirectory(match.captured(7)); - else - addDirectory(match.captured(7)); - return; - } - - IOutputParser::stdOutput(line); -} - class Result { public: Result() = default; @@ -123,78 +96,57 @@ static Result parseDescription(const QString &description) return result; } -void GnuMakeParser::stdError(const QString &line) +void GnuMakeParser::emitTask(const ProjectExplorer::Task &task) { - const QString lne = rightTrimmed(line); + if (task.type == Task::Error) // Assume that all make errors will be follow up errors. + m_suppressIssues = true; + scheduleTask(task, 1, 0); +} +OutputLineParser::Result GnuMakeParser::handleLine(const QString &line, OutputFormat type) +{ + const QString lne = rightTrimmed(line); + if (type == StdOutFormat) { + QRegularExpressionMatch match = m_makeDir.match(lne); + if (match.hasMatch()) { + if (match.captured(6) == QLatin1String("Leaving")) + emit searchDirExpired(FilePath::fromString(match.captured(7))); + else + emit newSearchDir(FilePath::fromString(match.captured(7))); + return Status::Done; + } + return Status::NotHandled; + } QRegularExpressionMatch match = m_errorInMakefile.match(lne); if (match.hasMatch()) { - flush(); - Result res = parseDescription(match.captured(5)); + ProjectExplorer::Result res = parseDescription(match.captured(5)); if (res.isFatal) ++m_fatalErrorCount; + LinkSpecs linkSpecs; if (!m_suppressIssues) { - taskAdded(BuildSystemTask(res.type, res.description, - FilePath::fromUserInput(match.captured(1)) /* filename */, - match.captured(4).toInt() /* line */), - 1, 0); + const FilePath file = absoluteFilePath(FilePath::fromUserInput(match.captured(1))); + const int lineNo = match.captured(4).toInt(); + addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1); + emitTask(BuildSystemTask(res.type, res.description, file, lineNo)); } - return; + return {Status::Done, linkSpecs}; } match = m_makeLine.match(lne); if (match.hasMatch()) { - flush(); - Result res = parseDescription(match.captured(6)); + ProjectExplorer::Result res = parseDescription(match.captured(6)); if (res.isFatal) ++m_fatalErrorCount; if (!m_suppressIssues) - taskAdded(BuildSystemTask(res.type, res.description), 1, 0); - return; + emitTask(BuildSystemTask(res.type, res.description)); + return Status::Done; } - IOutputParser::stdError(line); + return Status::NotHandled; } -void GnuMakeParser::addDirectory(const QString &dir) -{ - if (dir.isEmpty()) - return; - m_directories.append(dir); -} - -void GnuMakeParser::removeDirectory(const QString &dir) -{ - m_directories.removeOne(dir); -} - -void GnuMakeParser::taskAdded(const Task &task, int linkedLines, int skippedLines) +bool GnuMakeParser::hasFatalErrors() const { - Task editable(task); - - if (task.type == Task::Error) { - // assume that all make errors will be follow up errors: - m_suppressIssues = true; - } - - QString filePath(task.file.toString()); - - if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) { - QFileInfoList possibleFiles; - foreach (const QString &dir, m_directories) { - QFileInfo candidate(dir + QLatin1Char('/') + filePath); - if (candidate.exists() - && !possibleFiles.contains(candidate)) { - possibleFiles << candidate; - } - } - if (possibleFiles.size() == 1) - editable.file = Utils::FilePath::fromFileInfo(possibleFiles.first()); - // Let the Makestep apply additional heuristics (based on - // files in ther project) if we cannot uniquely - // identify the file! - } - - IOutputParser::taskAdded(editable, linkedLines, skippedLines); + return m_fatalErrorCount > 0; } } // ProjectExplorer @@ -210,11 +162,6 @@ void GnuMakeParser::taskAdded(const Task &task, int linkedLines, int skippedLine namespace ProjectExplorer { -QStringList GnuMakeParser::searchDirectories() const -{ - return m_directories; -} - GnuMakeParserTester::GnuMakeParserTester(GnuMakeParser *p, QObject *parent) : QObject(parent), parser(p) @@ -410,7 +357,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing() connect(&testbench, &OutputParserTester::aboutToDeleteParser, tester, &GnuMakeParserTester::parserIsAboutToBeDeleted); - testbench.appendOutputParser(childParser); + testbench.addLineParser(childParser); QFETCH(QStringList, extraSearchDirs); QFETCH(QString, input); QFETCH(OutputParserTester::Channel, inputChannel); @@ -420,117 +367,52 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing() QFETCH(QString, outputLines); QFETCH(QStringList, additionalSearchDirs); - QStringList searchDirs = childParser->searchDirectories(); + FilePaths searchDirs = childParser->searchDirectories(); // add extra directories: foreach (const QString &dir, extraSearchDirs) - childParser->addDirectory(dir); + testbench.addSearchDir(FilePath::fromString(dir)); testbench.testParsing(input, inputChannel, tasks, childStdOutLines, childStdErrLines, outputLines); // make sure we still have all the original dirs - QStringList newSearchDirs = tester->directories; - foreach (const QString &dir, searchDirs) { + FilePaths newSearchDirs = tester->directories; + foreach (const FilePath &dir, searchDirs) { QVERIFY(newSearchDirs.contains(dir)); newSearchDirs.removeOne(dir); } // make sure we have all additional dirs: foreach (const QString &dir, additionalSearchDirs) { - QVERIFY(newSearchDirs.contains(dir)); - newSearchDirs.removeOne(dir); + const FilePath fp = FilePath::fromString(dir); + QVERIFY(newSearchDirs.contains(fp)); + newSearchDirs.removeOne(fp); } // make sure we have no extra cruft: QVERIFY(newSearchDirs.isEmpty()); delete tester; } -void ProjectExplorerPlugin::testGnuMakeParserTaskMangling_data() -{ - QTest::addColumn<QStringList>("files"); - QTest::addColumn<QStringList>("searchDirectories"); - QTest::addColumn<Task>("inputTask"); - QTest::addColumn<Task>("outputTask"); - - QTest::newRow("no filename") - << QStringList() - << QStringList() - << Task(CompileTask(Task::Error, - "no filename, no mangling")) - << Task(CompileTask(Task::Error, - "no filename, no mangling")); - - QTest::newRow("no mangling") - << QStringList() - << QStringList() - << Task(CompileTask(Task::Error, - "unknown filename, no mangling", - FilePath::fromUserInput("some/path/unknown.cpp"))) - << Task(CompileTask(Task::Error, - "unknown filename, no mangling", - FilePath::fromUserInput("some/path/unknown.cpp"))); - - QTest::newRow("find file") - << QStringList("test/file.cpp") - << QStringList("test") - << Task(CompileTask(Task::Error, - "mangling", - FilePath::fromUserInput("file.cpp"), - 10)) - << Task(CompileTask(Task::Error, - "mangling", - FilePath::fromUserInput("$TMPDIR/test/file.cpp"), - 10)); -} - void ProjectExplorerPlugin::testGnuMakeParserTaskMangling() { + TemporaryFile theMakeFile("Makefile.XXXXXX"); + QVERIFY2(theMakeFile.open(), qPrintable(theMakeFile.errorString())); + QFileInfo fi(theMakeFile); + QVERIFY2(fi.fileName().startsWith("Makefile"), qPrintable(theMakeFile.fileName())); + OutputParserTester testbench; auto *childParser = new GnuMakeParser; - testbench.appendOutputParser(childParser); - - QFETCH(QStringList, files); - QFETCH(QStringList, searchDirectories); - QFETCH(Task, inputTask); - QFETCH(Task, outputTask); - - // setup files: - const QString tempdir - = Utils::TemporaryDirectory::masterDirectoryPath() + '/' + QUuid::createUuid().toString() + '/'; - QDir filedir(tempdir); - foreach (const QString &file, files) { - Q_ASSERT(!file.startsWith('/')); - Q_ASSERT(!file.contains("../")); - - filedir.mkpath(file.left(file.lastIndexOf('/'))); - - QFile tempfile(tempdir + file); - if (!tempfile.open(QIODevice::WriteOnly)) - continue; - tempfile.write("Delete me again!"); - tempfile.close(); - } - - // setup search dirs: - foreach (const QString &dir, searchDirectories) { - Q_ASSERT(!dir.startsWith(QLatin1Char('/'))); - Q_ASSERT(!dir.contains(QLatin1String("../"))); - childParser->addDirectory(tempdir + dir); - } - - // fix up output task file: - QString filePath = outputTask.file.toString(); - if (filePath.startsWith(QLatin1String("$TMPDIR/"))) - outputTask.file = Utils::FilePath::fromString(filePath.replace(QLatin1String("$TMPDIR/"), tempdir)); - - // test mangling: - testbench.testTaskMangling(inputTask, outputTask); - - // clean up: - foreach (const QString &file, files) - filedir.rmpath(tempdir + file); + testbench.addLineParser(childParser); + childParser->addSearchDir(FilePath::fromString(fi.absolutePath())); + testbench.testParsing( + fi.fileName() + ":360: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.", + OutputParserTester::STDERR, + {BuildSystemTask(Task::Error, + "missing separator (did you mean TAB instead of 8 spaces?). Stop.", + FilePath::fromString(theMakeFile.fileName()), 360)}, + QString(), QString(), QString()); } } // ProjectExplorer |