File indexing completed on 2024-05-05 08:44:17

0001 /*
0002  * This file is part of KDevelop Krazy2 Plugin.
0003  *
0004  * Copyright 2012 Daniel Calviño Sánchez <danxuliu@gmail.com>
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public License
0008  * as published by the Free Software Foundation; either version 2
0009  * of the License, or (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License
0017  * along with this program. If not, see <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #ifndef ANALYSISPROGRESSPARSER_H
0021 #define ANALYSISPROGRESSPARSER_H
0022 
0023 #include <QHash>
0024 
0025 #include <interfaces/istatus.h>
0026 
0027 /**
0028  * Shows progress information about krazy2 execution.
0029  * krazy2 shows a line with the progress of each test. Each test progress is
0030  * shown using dots after the test information. A new dot is printed for each
0031  * group of 10 files checked (even if tests are skipped on those files), but
0032  * there is no (easy) way to know how many files will be checked before krazy2
0033  * starts. However, the same files are checked for all the tests of the same
0034  * filetype. When the test ends, "done" is printed.
0035  *
0036  * Example for "foo" file type and "bar" checker program on 100 files:
0037  * =>foo/bar test in-progress..........done
0038  *
0039  * The progress is updated proportionally to how many checker programs are going
0040  * to be run and how many checker programs have been already run. Also, after
0041  * the first checker program for a filetype is run, the progress will be updated
0042  * also taking into account each checker program individual progress. The
0043  * progress will never reach the 100% before krazy2 finishes; that is, the
0044  * progress shown when the last checker is run is 99%, even if mathematically it
0045  * should be 100%.
0046  *
0047  * Also, the status message will specify which checker is being run.
0048  *
0049  * If, for any reason, there are more checkers parsed than the number set, each
0050  * time a new checker name is parsed the number of checkers is increased by one.
0051  * If the number of dots that will be outputted for that checker is known
0052  * (because its file type is already known), this will cause the progress to go
0053  * back from 99% (from the last checker run) to a smaller value which will
0054  * increase with each dot up to 99% when that unexpected checker is done.
0055  *
0056  * Note that, before starting the analysis itself, krazy2 performs a run over
0057  * all the files to be analyzed to filter out those that will not be checked
0058  * (because the file can not be accessed, or because the file type is not
0059  * supported). When a file is filtered out, krazy2 prints a message explaining
0060  * why. Those messages are parsed and discarded by the AnalysisProgressParser.
0061  *
0062  * The AnalysisProgressParser can be used to parse the progress of several
0063  * krazy2 executions in one single batch. That is, if two executions are parsed
0064  * one after the other, and the first execution runs seven checkers and the
0065  * second executions runs three checkers, the progress reported at the end of
0066  * the first execution will be 70%, and the progress reported at the end of the
0067  * second execution will be 99%. start() must be called before the first krazy2
0068  * execution, and end() must be called after the last krazy2 execution, like
0069  * done with a single execution. The only difference with several executions is
0070  * that, whenever the analyzed files change between executions,
0071  * resetNumberOfFilesForEachFileType() must be called, as the number of files
0072  * analyzed by the checkers of each file type may have changed.
0073  */
0074 class AnalysisProgressParser: public QObject, public KDevelop::IStatus {
0075 Q_OBJECT
0076 Q_INTERFACES(KDevelop::IStatus)
0077 public:
0078 
0079     /**
0080      * Creates a new AnalysisProgressParser.
0081      *
0082      * @param parent The parent QObject.
0083      */
0084     explicit AnalysisProgressParser(QObject* parent = nullptr);
0085 
0086     //<KDevelop::IStatus>
0087 
0088     /**
0089      * The name of this status update.
0090      *
0091      * @return "Running krazy2"
0092      */
0093     QString statusName() const override;
0094 
0095 Q_SIGNALS:
0096 
0097     void clearMessage(KDevelop::IStatus* status) override;
0098     void showMessage(KDevelop::IStatus* status, const QString & message, int timeout = 0) override;
0099     void showErrorMessage(const QString & message, int timeout = 0) override;
0100     void hideProgress(KDevelop::IStatus* status) override;
0101     void showProgress(KDevelop::IStatus* status, int minimum, int maximum, int value) override;
0102 
0103     //</KDevelop::IStatus>
0104 
0105 public:
0106 
0107     /**
0108      * Sets the number of checkers that will be run.
0109      *
0110      * @param numberOfCheckers The number of checkers that will be run.
0111      */
0112     void setNumberOfCheckers(int numberOfCheckers);
0113 
0114     /**
0115      * Resets the number of files assumed for each file type.
0116      * If this AnalysisProgressParser is used to parse the progress of several
0117      * krazy2 executions in a single batch, this method must be called whenever
0118      * the analyzed files change between executions.
0119      */
0120     void resetNumberOfFilesForEachFileType();
0121 
0122 public Q_SLOTS:
0123 
0124     /**
0125      * Reports that krazy2 has been started.
0126      * No message will be given.
0127      */
0128     void start();
0129 
0130     /**
0131      * Parses the next progress data outputted by krazy2 process.
0132      *
0133      * @param data The next progress data to parse.
0134      */
0135     void parse(const QByteArray& data);
0136 
0137     /**
0138      * Reports that krazy2 has finished, no matter why.
0139      * Shows a 100% progress before hidding it.
0140      */
0141     void finish();
0142 
0143 private:
0144 
0145     /**
0146      * Buffered data from previous outputs not parsed yet.
0147      */
0148     QString m_buffer;
0149 
0150     /**
0151      * The number of checkers that will be run.
0152      */
0153     int m_numberOfCheckers;
0154 
0155     /**
0156      * The number of checkers that have been already run.
0157      */
0158     int m_numberOfCheckersRun;
0159 
0160     /**
0161      * Maps a file type with the number of dots outputted when checking them.
0162      */
0163     QHash<QString, int> m_fileTypeToNumberOfDots;
0164 
0165     /**
0166      * The file type of the checker being run,
0167      */
0168     QString m_currentFileType;
0169 
0170     /**
0171      * The number of dots already outputted by the checker being run.
0172      */
0173     int m_currentNumberOfDots;
0174 
0175     /**
0176      * Discards the "Cannot access file" and "Unsupported file type" messages.
0177      */
0178     void discardFilteredOutFileMessages();
0179 
0180     /**
0181      * Discards a single "Cannot access file" message.
0182      */
0183     bool discardCannotAccessFileMessage();
0184 
0185     /**
0186      * Discards a single "Unsupported file type" message.
0187      */
0188     bool discardUnsupportedFileTypeMessage();
0189 
0190     /**
0191      * Parses the "=>fileType" chunk.
0192      *
0193      * @return True if the data in the buffer matched, false otherwise.
0194      */
0195     bool parseFileType();
0196 
0197     /**
0198      * Parses the "/checkerName test in-progress" chunk.
0199      * A message is shown with the file type and name of the checker being run.
0200      *
0201      * @return True if the data in the buffer matched, false otherwise.
0202      */
0203     bool parseCheckerName();
0204 
0205     /**
0206      * Parses the dots.
0207      * If it is known how many dots will be outputted for the current file type,
0208      * the progress is updated with the progress of the current checker program.
0209      * It is proportional to how many dots are going to be outputted and how
0210      * many dots have been already outputted.
0211      *
0212      * @return True if the data in the buffer matched, false otherwise.
0213      */
0214     bool parseDots();
0215 
0216     /**
0217      * Parses the "done\n" chunk.
0218      * The progress is updated proportionally to how many checker programs are
0219      * going to be run and how many checker programs have been already run,
0220      * although it is limited to 99% at most, never 100%.
0221      *
0222      * @return True if the data in the buffer matched, false otherwise.
0223      */
0224     bool parseDone();
0225 
0226 };
0227 
0228 #endif