File indexing completed on 2024-04-28 04:37:26

0001 /*
0002     SPDX-FileCopyrightText: 2008 Cédric Pasteur <cedric.pasteur@free.fr>
0003     SPDX-FileCopyrightText: 2009 Andreas Pakulat <apaku@gmx.de>
0004     SPDX-FileCopyrightText: 2017 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "sourceformatterjob.h"
0010 
0011 #include "sourceformattercontroller.h"
0012 
0013 #include <debug.h>
0014 
0015 #include <QTextStream>
0016 
0017 #include <KIO/StoredTransferJob>
0018 #include <KLocalizedString>
0019 
0020 #include <interfaces/icore.h>
0021 #include <interfaces/iuicontroller.h>
0022 #include <interfaces/idocumentcontroller.h>
0023 #include <sublime/message.h>
0024 
0025 using namespace KDevelop;
0026 
0027 
0028 SourceFormatterJob::SourceFormatterJob(SourceFormatterController* sourceFormatterController)
0029     : KJob(sourceFormatterController)
0030     , m_sourceFormatterController(sourceFormatterController)
0031     , m_workState(WorkIdle)
0032     , m_fileIndex(0)
0033 {
0034     setCapabilities(Killable);
0035     // set name for job listing
0036     setObjectName(i18n("Reformatting"));
0037 
0038     KDevelop::ICore::self()->uiController()->registerStatus(this);
0039 
0040     connect(this, &SourceFormatterJob::finished, this, [this]() {
0041         emit hideProgress(this);
0042     });
0043 }
0044 
0045 QString SourceFormatterJob::statusName() const
0046 {
0047     return i18n("Reformat Files");
0048 }
0049 
0050 void SourceFormatterJob::doWork()
0051 {
0052     // TODO: consider to use ExecuteCompositeJob, with every file a separate subjob
0053     switch (m_workState) {
0054         case WorkIdle:
0055             m_workState = WorkFormat;
0056             m_fileIndex = 0;
0057             emit showProgress(this, 0, 0, 0);
0058             emit showMessage(this, i18np("Reformatting one file",
0059                                          "Reformatting %1 files",
0060                                          m_fileList.length()));
0061 
0062             QMetaObject::invokeMethod(this, "doWork", Qt::QueuedConnection);
0063             break;
0064         case WorkFormat:
0065             if (m_fileIndex < m_fileList.length()) {
0066                 emit showProgress(this, 0, m_fileList.length(), m_fileIndex);
0067                 formatFile(m_fileList[m_fileIndex]);
0068 
0069                 // trigger formatting of next file
0070                 ++m_fileIndex;
0071                 QMetaObject::invokeMethod(this, "doWork", Qt::QueuedConnection);
0072             } else {
0073                 m_workState = WorkIdle;
0074                 emitResult();
0075             }
0076             break;
0077         case WorkCancelled:
0078             break;
0079     }
0080 }
0081 
0082 void SourceFormatterJob::start()
0083 {
0084     if (m_workState != WorkIdle)
0085         return;
0086 
0087     m_workState = WorkIdle;
0088 
0089     QMetaObject::invokeMethod(this, "doWork", Qt::QueuedConnection);
0090 }
0091 
0092 bool SourceFormatterJob::doKill()
0093 {
0094     m_workState = WorkCancelled;
0095     return true;
0096 }
0097 
0098 void SourceFormatterJob::setFiles(const QList<QUrl>& fileList)
0099 {
0100     m_fileList = fileList;
0101 }
0102 
0103 void SourceFormatterJob::formatFile(const QUrl& url)
0104 {
0105     qCDebug(SHELL) << "Checking whether to format file" << url;
0106     SourceFormatterController::FileFormatter ff(url);
0107     if (!ff.readFormatterAndStyle(m_sourceFormatterController->formatters())) {
0108         return; // unsupported MIME type or no configured formatter for it
0109     }
0110 
0111     // if the file is opened in the editor, format the text in the editor without saving it
0112     auto doc = ICore::self()->documentController()->documentForUrl(url);
0113     if (doc) {
0114         qCDebug(SHELL) << "Processing file " << url << "opened in editor";
0115         ff.formatDocument(*doc);
0116         return;
0117     }
0118 
0119     qCDebug(SHELL) << "Processing file " << url;
0120     auto getJob = KIO::storedGet(url);
0121     // TODO: make also async and use start() and integrate using setError and setErrorString.
0122     if (getJob->exec()) {
0123         // TODO: really fromLocal8Bit/toLocal8Bit? no encoding detection? added in b8062f736a2bf2eec098af531a7fda6ebcdc7cde
0124         QString text = QString::fromLocal8Bit(getJob->data());
0125         text = ff.format(text);
0126         text = ff.addModeline(text);
0127 
0128         auto putJob = KIO::storedPut(text.toLocal8Bit(), url, -1, KIO::Overwrite);
0129         // see getJob
0130         if (!putJob->exec()) {
0131             auto* message = new Sublime::Message(putJob->errorString(), Sublime::Message::Error);
0132             ICore::self()->uiController()->postMessage(message);
0133         }
0134     } else {
0135         auto* message = new Sublime::Message(getJob->errorString(), Sublime::Message::Error);
0136         ICore::self()->uiController()->postMessage(message);
0137     }
0138 }
0139 
0140 #include "moc_sourceformatterjob.cpp"