File indexing completed on 2024-05-12 04:37:43

0001 /*
0002     SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org>
0003     SPDX-FileCopyrightText: 2006-2008 Hamish Rodda <rodda@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KDEVPLATFORM_PARSEJOB_H
0009 #define KDEVPLATFORM_PARSEJOB_H
0010 
0011 #include <QPointer>
0012 
0013 #include <ThreadWeaver/Sequence>
0014 
0015 #include <serialization/indexedstring.h>
0016 #include <language/duchain/topducontext.h>
0017 #include <language/editor/modificationrevision.h>
0018 
0019 namespace ThreadWeaver {
0020 class QObjectDecorator;
0021 }
0022 
0023 namespace KDevelop {
0024 class ParsingEnvironment;
0025 class ControlFlowGraph;
0026 class DataAccessRepository;
0027 class TopDUContext;
0028 class ReferencedTopDUContext;
0029 class ILanguageSupport;
0030 class ParseJobPrivate;
0031 
0032 /**
0033  * The base class for background parser jobs.
0034  *
0035  * In your language plugin, don't forget to use acquire an UrlParseLock before starting to the actual parsing.
0036  */
0037 class KDEVPLATFORMLANGUAGE_EXPORT ParseJob
0038     : public QObject
0039     , public ThreadWeaver::Sequence
0040 {
0041     Q_OBJECT
0042 
0043 public:
0044     explicit ParseJob(const IndexedString& url, ILanguageSupport* languageSupport);
0045     /**
0046      * _No_ mutexes/locks are allowed to be locked when this object is destroyed (except for optionally the foreground lock)
0047      * */
0048     ~ParseJob() override;
0049 
0050     /**
0051      * @return the language support that created this parse job.
0052      */
0053     ILanguageSupport* languageSupport() const;
0054 
0055     struct Contents
0056     {
0057         // Modification-time of the read content
0058         ModificationRevision modification;
0059         // The contents in utf-8 format
0060         QByteArray contents;
0061     };
0062 
0063     enum SequentialProcessingFlag {
0064         IgnoresSequentialProcessing = 0,
0065         RequiresSequentialProcessing = 1,
0066         RespectsSequentialProcessing = 2,
0067         FullSequentialProcessing = 3
0068     };
0069     Q_DECLARE_FLAGS(SequentialProcessingFlags, SequentialProcessingFlag)
0070 
0071     ///Sets the priority of this parse job. This is just for the purpose of
0072     ///reading it later, and does not affect the actual behaviour in any way.
0073     void setParsePriority(int priority);
0074     ///Get the priority of this parse job.
0075     ///Other than priority(), this will give you the "KDevelop-priority" of the job,
0076     ///not the QThread one (which is always zero).
0077     int parsePriority() const;
0078 
0079     /**
0080      * _No_ mutexes/locks are allowed to be locked when this is called (except for optionally the foreground lock)
0081      *
0082      * Locks the document revision so that mapping from/to the revision in the editor using MovingInterface will be possible.
0083      *
0084      * Returns an invalid pointer if the call succeeds, and a valid one if the reading fails.
0085      * */
0086     KDevelop::ProblemPointer readContents();
0087 
0088     /**
0089      * After reading the contents, you can call this to retrieve it.
0090      * */
0091     const Contents& contents() const;
0092 
0093     /**
0094      * Translates the given context from its previous revision to the revision that has
0095      * been retrieved during readContents(). The top-context meta-data will be updated
0096      * with the revision.
0097      *
0098      * This can be done after reading the context before updating, so
0099      * that the correct ranges are matched onto each other during the update.
0100      *
0101      * _No_ mutexes/locks are allowed to be locked when this is called (except for optionally the foreground lock)
0102      */
0103     void translateDUChainToRevision(TopDUContext* context);
0104 
0105     /**
0106      * Query whether this job is needed to be waited for when trying to process a job with a lower priority.
0107      **/
0108     bool respectsSequentialProcessing() const;
0109 
0110     /**
0111      * Query whether this job requires all higher-priority jobs to finish before being processed itself.
0112      **/
0113     bool requiresSequentialProcessing() const;
0114 
0115     void setSequentialProcessingFlags(SequentialProcessingFlags flags);
0116 
0117     /**
0118      * Files greater than this size will not be parsed.
0119      *
0120      * Plugins can use the setMaximumFileSize method to override the default value of 5 MB for internal files
0121      * they might require to be parsed.
0122      **/
0123     qint64 maximumFileSize() const;
0124 
0125     void setMaximumFileSize(qint64 value);
0126 
0127     /// \returns the indexed url of the document to be parsed.
0128     KDevelop::IndexedString document() const;
0129 
0130     /**
0131      * Sets a list of QObjects that should contain a slot
0132      * "void updateReady(KDevelop::IndexedString url, KDevelop::ReferencedTopDUContext topContext)".
0133      * The notification is guaranteed to be called once the parse-job finishes, from within its destructor.
0134      * The given top-context may be invalid if the update failed.
0135      */
0136     void setNotifyWhenReady(const QVector<QPointer<QObject>>& notify);
0137 
0138     /// Sets the du-context that was created by this parse-job
0139     virtual void setDuChain(const ReferencedTopDUContext& duChain);
0140     /// Returns the set du-context, or zero of none was set.
0141     virtual ReferencedTopDUContext duChain() const;
0142 
0143     /// Overridden to allow jobs to determine if they've been requested to abort
0144     void requestAbort() override;
0145     /// Determine if the job has been requested to abort
0146     bool abortRequested() const;
0147     /// Sets success to false, causing failed() to be emitted
0148     void abortJob();
0149 
0150     /// Overridden to convey whether the job succeeded or not.
0151     bool success() const override;
0152 
0153     /// Set the minimum features the resulting top-context should have
0154     void setMinimumFeatures(TopDUContext::Features features);
0155 
0156     /// Minimum set of features the resulting top-context should have
0157     TopDUContext::Features minimumFeatures() const;
0158 
0159     /// Allows statically specifying an amount of features required for an url.
0160     /// These features will automatically be or'ed with the minimumFeatures() returned
0161     /// by any ParseJob with the given url.
0162     /// Since this causes some additional complexity in update-checking, minimum features should not
0163     /// be set permanently.
0164     static void setStaticMinimumFeatures(const IndexedString& url, TopDUContext::Features features);
0165 
0166     /// Must be called exactly once for each call to setStaticMinimumFeatures, with the same features.
0167     static void unsetStaticMinimumFeatures(const IndexedString& url, TopDUContext::Features features);
0168 
0169     /// Returns the statically set minimum features for  the given url, or zero.
0170     static TopDUContext::Features staticMinimumFeatures(const IndexedString& url);
0171 
0172     /// Returns whether there is minimum features set up for some url
0173     static bool hasStaticMinimumFeatures();
0174 
0175     ///Returns a structure containing information about data accesses in the parsed file.
0176     /// It's up to the caller to remove the returned instance
0177     virtual KDevelop::DataAccessRepository* dataAccessInformation();
0178 
0179     ///Returns a control flow graph for the code in the parsed file.
0180     /// It's up to the caller to remove the returned instance
0181     virtual KDevelop::ControlFlowGraph* controlFlowGraph();
0182 
0183 Q_SIGNALS:
0184     /**Can be used to give progress feedback to the background-parser. @param value should be between 0 and 1, where 0 = 0% and 1 = 100%
0185      * @param text may be a text that describes the current state of parsing
0186      * Do not trigger this too often, for performance reasons. */
0187     void progress(KDevelop::ParseJob*, float value, const QString& text);
0188 
0189 protected:
0190     /**
0191      * Should return an environment for this parse job.
0192      *
0193      * This is then used to check whether existing cached data of previous parse jobs need an update.
0194      * The default implementation returns a nullptr.
0195      */
0196     virtual const ParsingEnvironment* environment() const;
0197 
0198     /**
0199      * Checks whether there is already an up to date context available for the
0200      * current document. If so, it returns true and ensures that the document
0201      * is highlighted properly. Otherwise returns false.
0202      *
0203      * NOTE: This should be called while holding an URLParseLock for the
0204      * current document.
0205      *
0206      * @param languageString The unique string identifying your language.
0207      * This must be the same as you assign to the DUChain's environment file.
0208      *
0209      * @return True if an update is required, false if the job can return early.
0210      */
0211     bool isUpdateRequired(const IndexedString& languageString);
0212 
0213     /**
0214      * Trigger an update to the code highlighting of the current file based
0215      * on the DUChain set in setDuChain.
0216      *
0217      * If the file for this parse job is not opened in an editor or if the language
0218      * support does not return a code highlighter, this will do nothing.
0219      *
0220      * NOTE: No DUChain lock should be held when you call this.
0221      */
0222     void highlightDUChain();
0223 
0224     /**
0225      * Returns whether there is a tracker for the current document.
0226      */
0227     bool hasTracker() const;
0228 
0229 private:
0230     const QScopedPointer<class ParseJobPrivate> d_ptr;
0231     Q_DECLARE_PRIVATE(ParseJob)
0232 };
0233 
0234 Q_DECLARE_OPERATORS_FOR_FLAGS(ParseJob::SequentialProcessingFlags)
0235 }
0236 
0237 #endif