File indexing completed on 2024-05-19 04:41:21

0001 /*
0002     SPDX-FileCopyrightText: 2019 Daniel Mensinger <daniel@mensinger-ka.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "mesonrewriterjob.h"
0008 #include "mesonconfig.h"
0009 
0010 #include "interfaces/iproject.h"
0011 #include "util/path.h"
0012 
0013 #include <KLocalizedString>
0014 #include <KProcess>
0015 #include <QJsonArray>
0016 #include <QJsonDocument>
0017 #include <QTemporaryFile>
0018 #include <QtConcurrentRun>
0019 
0020 #include "debug.h"
0021 
0022 using namespace KDevelop;
0023 
0024 MesonRewriterJob::MesonRewriterJob(IProject* project, const QVector<MesonRewriterActionPtr>& actions, QObject* parent)
0025     : KJob(parent)
0026     , m_project(project)
0027     , m_actions(actions)
0028 {
0029     connect(&m_futureWatcher, &QFutureWatcher<QString>::finished, this, &MesonRewriterJob::finished);
0030 }
0031 
0032 QString MesonRewriterJob::execute()
0033 {
0034     QJsonArray command;
0035     for (auto& i : m_actions) {
0036         command.append(i->command());
0037     }
0038 
0039     QTemporaryFile tempFile;
0040     tempFile.setAutoRemove(false);
0041     if (!tempFile.open()) {
0042         return i18n("Failed to create a temporary file.");
0043     }
0044 
0045     QJsonDocument doc(command);
0046     tempFile.write(doc.toJson());
0047     tempFile.flush();
0048 
0049     Meson::BuildDir buildDir = Meson::currentBuildDir(m_project);
0050 
0051     KProcess proc(this);
0052     proc.setWorkingDirectory(m_project->path().toLocalFile());
0053     proc.setOutputChannelMode(KProcess::SeparateChannels);
0054     proc.setProgram(buildDir.mesonExecutable.toLocalFile());
0055     proc << QStringLiteral("rewrite") << QStringLiteral("command") << tempFile.fileName();
0056 
0057     int ret = proc.execute();
0058     if (ret != 0) {
0059         return i18n("%1 returned %2", proc.program().join(QLatin1Char(' ')), ret);
0060     }
0061 
0062     auto rawData = proc.readAllStandardError();
0063     if (rawData.isEmpty()) {
0064         return QString();
0065     }
0066 
0067     QJsonParseError error;
0068     QJsonDocument result = QJsonDocument::fromJson(rawData, &error);
0069     if (error.error) {
0070         return i18n("JSON parser error: %1", error.errorString());
0071     }
0072 
0073     if (!result.isObject()) {
0074         return i18n("The rewriter output of '%1' is not an object", proc.program().join(QLatin1Char(' ')));
0075     }
0076 
0077     for (auto& i : m_actions) {
0078         i->parseResult(result.object());
0079     }
0080 
0081     return QString();
0082 }
0083 
0084 void MesonRewriterJob::finished()
0085 {
0086     QString result = m_futureWatcher.result();
0087     if (!result.isEmpty()) {
0088         qCWarning(KDEV_Meson) << "REWRITER " << result;
0089         setError(true);
0090         setErrorText(result);
0091         emitResult();
0092         return;
0093     }
0094 
0095     qCDebug(KDEV_Meson) << "REWRITER: Meson rewriter job finished";
0096     emitResult();
0097 }
0098 
0099 bool MesonRewriterJob::doKill()
0100 {
0101     if (m_futureWatcher.isRunning()) {
0102         m_futureWatcher.cancel();
0103     }
0104     return true;
0105 }
0106 
0107 void MesonRewriterJob::start()
0108 {
0109     auto future = QtConcurrent::run(this, &MesonRewriterJob::execute);
0110     m_futureWatcher.setFuture(future);
0111 }
0112 
0113 #include "moc_mesonrewriterjob.cpp"