File indexing completed on 2024-04-21 04:34:32

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 ANALYSISJOB_H
0021 #define ANALYSISJOB_H
0022 
0023 #include <KJob>
0024 
0025 #include <QProcess>
0026 
0027 class AnalysisParameters;
0028 class AnalysisProgressParser;
0029 class AnalysisResults;
0030 class Checker;
0031 
0032 /**
0033  * Job to analyze a directory with krazy2.
0034  * The job executes a krazy2 process asking it to analyze all the files
0035  * specified in the AnalysisParameters and then parses the output to populate an
0036  * AnalysisResults object. The checkers to run on the files are specified in the
0037  * AnalysisParameters too. The progress of the analysis is also notified.
0038  *
0039  * Several AnalysisParameters can be added to the job to be executed in the same
0040  * batch. That is, the AnalysisResults object will contain all the issues found
0041  * using each of the AnalysisParameters (although without duplicated issues) and
0042  * the progress report will take into account all the AnalysisParameters (the
0043  * progress will be proportional to the total number of checkers to be run), but
0044  * from the analysis perspective, each AnalysisParameters will be executed on
0045  * its own, like running several jobs each one with a single AnalysisParameters.
0046  *
0047  * The path to the krazy2 executable is got from "Krazy2" configuration group.
0048  *
0049  * The job is killable.
0050  */
0051 class AnalysisJob: public KJob {
0052 Q_OBJECT
0053 public:
0054 
0055     /**
0056      * Creates a new AnalysisJob with the given parent.
0057      *
0058      * @param parent The parent QObject.
0059      */
0060     explicit AnalysisJob(QObject* parent = nullptr);
0061 
0062     //<KJob>
0063 
0064     /**
0065      * Starts the analysis.
0066      */
0067     void start() override;
0068 
0069     //</KJob>
0070 
0071     /**
0072      * Adds analysis parameters.
0073      * The checkers have to have been initialized.
0074      *
0075      * The checkers from the list of available checkers will be copied to the
0076      * AnalysisResults object, so they must be fully initialized. The reason is
0077      * that krazy2 does not provide information in the results about whether a
0078      * checker is extra or not, so that information has to be got from the list
0079      * of available checkers.
0080      *
0081      * @param analysisParameters The analysis parameters to add.
0082      */
0083     void addAnalysisParameters(const AnalysisParameters* analysisParameters);
0084 
0085     /**
0086      * Sets the AnalysisResults to populate.
0087      *
0088      * @param analysisResults The AnalysisResults to populate.
0089      */
0090     void setAnalysisResults(AnalysisResults* analysisResults);
0091 
0092 protected:
0093 
0094     //<KJob>
0095 
0096     /**
0097      * Kills the underlying process.
0098      *
0099      * @return Always true.
0100      */
0101     bool doKill() override;
0102 
0103     //</KJob>
0104 
0105 private:
0106 
0107     /**
0108      * The list of AnalysisParameters.
0109      */
0110     QList<const AnalysisParameters*> m_analysisParametersList;
0111 
0112     /**
0113      * The analysis parameters to use for the current krazy2 execution.
0114      */
0115     const AnalysisParameters* m_currentAnalysisParameters;
0116 
0117     /**
0118      * A list of the lists with the names of the files to be analyzed.
0119      * They are just the names returned by each AnalysisParameters, stored to
0120      * avoid resolving the file names each time a new process is executed.
0121      */
0122     QList<QStringList> m_namesOfFilesToBeAnalyzed;
0123 
0124     /**
0125      * A list with the names of the files to be analyzed in the current krazy2
0126      * execution.
0127      */
0128     QStringList m_currentNamesOfFilesToBeAnalyzed;
0129 
0130     /**
0131      * The file types of the checkers to run of the current analysis parameters
0132      * that have not been run yet.
0133      * Only the checkers with a given file type are run each time. Thus, several
0134      * krazy2 executions may be needed to run all the checkers of the current
0135      * analysis parameters, and this list keeps track of the pending file types.
0136      *
0137      * @see checkersToRunAsKrazy2Arguments(QString)
0138      */
0139     QStringList m_pendingFileTypes;
0140 
0141     /**
0142      * The analysis results to populate.
0143      */
0144     AnalysisResults* m_analysisResults;
0145 
0146     /**
0147      * The KDevelop::IStatus to show the analysis progress.
0148      */
0149     AnalysisProgressParser* m_analysisProgressParser;
0150 
0151     /**
0152      * The krazy2 process to parse its output.
0153      */
0154     QProcess* m_process;
0155 
0156     /**
0157      * Returns the number of checkers that will be executed.
0158      * The executed checkers will depend on the types of the files analyzed and
0159      * the file types supported by each checker.
0160      * The returned number is just a hint. It will probably be the right number,
0161      * but it also may not.
0162      *
0163      * @param namesOfFilesToBeAnalyzed A list with file names.
0164      * @param checkersToRun The list of checkers to run on the given file names.
0165      * @return The number of checkers that will be executed.
0166      * @see isCheckerCompatibleWith(Checker*,QString)
0167      */
0168     int calculateNumberOfCheckersToBeExecuted(const QStringList& namesOfFilesToBeAnalyzed,
0169                                               const QList<const Checker*>& checkersToRun) const;
0170 
0171     /**
0172      * Returns whether the given checker can analyze any of the files with the
0173      * given names or not.
0174      *
0175      * @param checker The checker.
0176      * @param fileNames The names of the files.
0177      * @return True if the checker can analyze any file, false otherwise.
0178      * @see isCheckerCompatibleWith(Checker*,QString)
0179      */
0180     bool isCheckerCompatibleWithAnyFile(const Checker* checker,
0181                                         const QStringList& fileNames) const;
0182 
0183     /**
0184      * Returns whether the given checker can analyze the file with the given
0185      * name or not.
0186      * Being able to analyze the file or not depends on the file type of the
0187      * checker and the extension of the file. The file types and extensions
0188      * known by this method are based on Krazy2 lib/Krazy/Utils.pm fileType
0189      * function (commit d2301b9, 2012-05-26). Note, however, that future Krazy2
0190      * versions may support extensions not listed here. Thus, the value returned
0191      * by this method is just a hint.
0192      *
0193      * @param checker The checker.
0194      * @param fileName The name of the file.
0195      * @return True if the checker can analyze the file, false otherwise.
0196      */
0197     bool isCheckerCompatibleWithFile(const Checker* checker, const QString& fileName) const;
0198 
0199     /**
0200      * Sets the current analysis parameters (and names of files to be analyzed).
0201      * The list with the pending file types is populated with the file types of
0202      * the checkers of the now current analysis parameters.
0203      *
0204      * As a new set of analysis parameters is going to be used the number of
0205      * files for each file type assumed by the progress parser is reset too.
0206      */
0207     void prepareNextAnalysisParameters();
0208 
0209     /**
0210      * Returns the list of checkers to run as a list of strings to be passed to
0211      * krazy2 as arguments.
0212      * The checkers to run are got from the current analysis parameters. The
0213      * list returned by AnalysisParameters contains both normal and extra
0214      * checkers. However, when telling krazy2 which checkers to run, normal
0215      * checkers and extra checkers must be passed in different arguments.
0216      *
0217      * Moreover, normal checkers and extra checkers can not be specified at the
0218      * same time; if "--check" argument is used, "--extra" argument takes no
0219      * effect. Thus, to execute extra checkers along with a subset of the normal
0220      * checkers, the "--exclude" argument has to be used to specify which normal
0221      * checkers should not be run (from all the available checkers), along with
0222      * an "--extra" argument to specify which extra checkers should be run.
0223      *
0224      * When the name of the checker is provided using "--check", "--extra" or
0225      * "--exclude" every checker with the given name is taken into account. For
0226      * example, as the spelling checker supports several file types,
0227      * "--checker spelling" would execute the spelling checker for c++, cmake,
0228      * desktop... To limit the file types of the checkers to run, "--types"
0229      * should be used. However, there is no way (that I am aware of) to run a
0230      * checker X for file type A and a checker Y for file type B but not a
0231      * checker X for file type B at the same time. Thus, only the checkers to
0232      * run for the given file type are executed at the same time.
0233      *
0234      * @param fileType The file type of the subgroup of checkers to run.
0235      * @return The krazy2 arguments as a list of strings.
0236      */
0237     QStringList checkersToRunAsKrazy2Arguments(const QString& fileType) const;
0238 
0239     /**
0240      * Starts the krazy2 process.
0241      * Only the checkers to run of the current analysis parameters and for the
0242      * given file type are executed.
0243      *
0244      * @param fileType The file type of the subgroup of checkers to run.
0245      */
0246     void startAnalysis(const QString& fileType);
0247 
0248 private Q_SLOTS:
0249 
0250     /**
0251      * Updates the progress.
0252      */
0253     void handleProcessReadyStandardError();
0254 
0255     /**
0256      * Adds the results for the current file type to the general results.
0257      * The next AnalysisParameters are prepared, if needed. Then, if there are
0258      * other file types pending, starts a new analysis for the next file type.
0259      * Else, ends this AnalysisJob emitting the result.
0260      *
0261      * @param exitCode Unused.
0262      */
0263     void handleProcessFinished(int exitCode);
0264 
0265     /**
0266      * Sets the error code and error text for this AnalysisJob and ends it
0267      * emitting the result.
0268      *
0269      * @param processError The error occurred in the underlying process.
0270      */
0271     void handleProcessError(QProcess::ProcessError processError);
0272 
0273 };
0274 
0275 #endif