File indexing completed on 2024-05-12 04:37:42
0001 /* 0002 SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org> 0003 SPDX-FileCopyrightText: 2007 Kris Wong <kris.p.wong@gmail.com> 0004 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef KDEVPLATFORM_BACKGROUNDPARSER_H 0010 #define KDEVPLATFORM_BACKGROUNDPARSER_H 0011 0012 #include <language/languageexport.h> 0013 #include <interfaces/istatus.h> 0014 #include <language/duchain/topducontext.h> 0015 #include <language/interfaces/ilanguagesupport.h> 0016 #include "parsejob.h" 0017 0018 namespace ThreadWeaver { 0019 class Job; 0020 class QObjectDecorator; 0021 class Weaver; 0022 } 0023 0024 namespace KDevelop { 0025 class DocumentChangeTracker; 0026 0027 class IDocument; 0028 class IProject; 0029 class ILanguageController; 0030 class ParserDependencyPolicy; 0031 0032 /** 0033 * This class handles the creation of parse jobs for given file URLs. 0034 * 0035 * For performance reasons you must always use clean, canonical URLs. If you do not do that, 0036 * issues might arise (and the debug build will assert). 0037 */ 0038 class KDEVPLATFORMLANGUAGE_EXPORT BackgroundParser 0039 : public QObject 0040 , public IStatus 0041 { 0042 Q_OBJECT 0043 Q_INTERFACES(KDevelop::IStatus) 0044 0045 public: 0046 explicit BackgroundParser(ILanguageController* languageController); 0047 ~BackgroundParser() override; 0048 0049 QString statusName() const override; 0050 0051 enum { 0052 BestPriority = -10000, ///Best possible job-priority. No jobs should actually have this. 0053 NormalPriority = 0, ///Standard job-priority. This priority is used for parse-jobs caused by document-editing/opening. 0054 ///There is an additional parsing-thread reserved for jobs with this and better priority, to improve responsiveness. 0055 InitialParsePriority = 10000, ///Priority used when adding file on project loading 0056 WorstPriority = 100000 ///Worst possible job-priority. 0057 }; 0058 0059 /** 0060 * Queries the background parser as to whether there is currently 0061 * a parse job for @p document, and if so, returns it. 0062 * 0063 * This may not contain all of the parse jobs that are intended 0064 * unless you call in from your job's ThreadWeaver::Job::aboutToBeQueued() 0065 * function. 0066 */ 0067 ParseJob* parseJobForDocument(const IndexedString& document) const; 0068 0069 /** 0070 * Set how many ThreadWeaver threads the background parser should set up and use. 0071 */ 0072 void setThreadCount(int threadCount); 0073 0074 /** 0075 * Return how many ThreadWeaver threads the background parser should set up and use. 0076 */ 0077 int threadCount() const; 0078 0079 /** 0080 * Set the delay in milliseconds before the background parser starts parsing. 0081 */ 0082 void setDelay(int milliseconds); 0083 0084 /** 0085 * Returns all documents that were added through addManagedTopRange. This is typically the currently 0086 * open documents. 0087 */ 0088 QList<IndexedString> managedDocuments(); 0089 0090 /** 0091 * Returns the tracker for the given url if the document is being tracked, else returns zero. 0092 * This function is thread-safe, but the returned object also isn't, so you must not use it 0093 * when you're in a background thread without the foreground lock acquired. 0094 * */ 0095 DocumentChangeTracker* trackerForUrl(const IndexedString& url) const; 0096 0097 bool waitForIdle() const; 0098 0099 Q_SIGNALS: 0100 /** 0101 * Emitted whenever a document parse-job has finished. 0102 * The job contains the du-chain(if one was created) etc. 0103 * 0104 * The job is deleted after this signal has been emitted. Receivers should not hold 0105 * references to it. 0106 * 0107 * Note that if you want to be get updated for all DUChain updates, use 0108 * DUChain::updateReady instead, as a single ParseJob may update multiple 0109 * DUChain top contexts. 0110 * 0111 * @sa DUChain::updateReady 0112 */ 0113 void parseJobFinished(KDevelop::ParseJob* job); 0114 0115 // Implementations of IStatus signals 0116 void clearMessage(KDevelop::IStatus*) override; 0117 void showMessage(KDevelop::IStatus*, const QString& message, int timeout = 0) override; 0118 void hideProgress(KDevelop::IStatus*) override; 0119 void showProgress(KDevelop::IStatus*, int minimum, int maximum, int value) override; 0120 void showErrorMessage(const QString&, int) override; 0121 0122 public Q_SLOTS: 0123 /** 0124 * Aborts all parse jobs 0125 */ 0126 void abortAllJobs(); 0127 0128 /** 0129 * Suspends execution of the background parser 0130 * 0131 * NOTE: Only the Core should call this 0132 */ 0133 void suspend(); 0134 0135 /** 0136 * Resumes execution of the background parser 0137 * 0138 * NOTE: Only the Core should call this 0139 */ 0140 void resume(); 0141 0142 /// Reverts all requests that were made for the given notification-target. 0143 /// priorities and requested features will be reverted as well. 0144 void revertAllRequests(QObject* notifyWhenReady); 0145 0146 /** 0147 * Queues up the @p url to be parsed. 0148 * @p features The minimum features that should be computed for this top-context 0149 * @p priority A value that manages the order of parsing. Documents with lowest priority are parsed first. 0150 * @param notifyWhenReady An optional pointer to a QObject that should contain a slot 0151 * "void updateReady(KDevelop::IndexedString url, KDevelop::ReferencedTopDUContext topContext)". 0152 * The notification is guaranteed to be called once for each call to addDocument. The given top-context 0153 * may be invalid if the update failed. 0154 * @param flags Flags indicating how the document should be treated in the queue 0155 * @param delay_ms The delay in milliseconds to add the job with, or one of the values of the 0156 * ILanguageSupport::ReparseDelaySpecialValues enum. 0157 */ 0158 void addDocument(const IndexedString& url, 0159 TopDUContext::Features features = TopDUContext::VisibleDeclarationsAndContexts, 0160 int priority = 0, 0161 QObject* notifyWhenReady = nullptr, 0162 ParseJob::SequentialProcessingFlags flags = ParseJob::IgnoresSequentialProcessing, 0163 int delay_ms = ILanguageSupport::DefaultDelay); 0164 0165 /** 0166 * try to add a listener to an existing document 0167 * @see addDocument(...) for parameter description 0168 * @returns true if the document existed and a listener was added 0169 */ 0170 [[nodiscard]] 0171 bool addListenerToDocumentIfExist(const IndexedString& url, 0172 TopDUContext::Features features = TopDUContext::VisibleDeclarationsAndContexts, 0173 int priority = 0, 0174 QObject* notifyWhenReady = nullptr, 0175 ParseJob::SequentialProcessingFlags flags = ParseJob::IgnoresSequentialProcessing, 0176 int delay_ms = ILanguageSupport::DefaultDelay); 0177 0178 /** 0179 * Removes the @p url that is registered for the given notification from the url. 0180 * 0181 * @param notifyWhenReady Notifier the document was added with. 0182 */ 0183 void removeDocument(const IndexedString& url, QObject* notifyWhenReady = nullptr); 0184 0185 /** 0186 * Forces the current queue to be parsed. 0187 */ 0188 void parseDocuments(); 0189 0190 void updateProgressData(); 0191 0192 /// Disables processing for all jobs that have a worse priority than @p priority 0193 /// This can be used to temporarily limit the processing to only the most important jobs. 0194 /// To only enable processing for important jobs, call setNeededPriority(0). 0195 /// This should only be used to temporarily alter the processing. A progress-bar 0196 /// will still be shown for the not yet processed jobs. 0197 void setNeededPriority(int priority); 0198 /// Disables all processing of new jobs, equivalent to setNeededPriority(BestPriority) 0199 void disableProcessing(); 0200 /// Enables all processing of new jobs, equivalent to setNeededPriority(WorstPriority) 0201 void enableProcessing(); 0202 0203 /// Returns true if the given url is queued for parsing 0204 bool isQueued(const IndexedString& url) const; 0205 0206 /// Retrieve the current priority for the given URL. 0207 /// You need to check whether @param url is queued before calling this function. 0208 int priorityForDocument(const IndexedString& url) const; 0209 0210 /// Returns the number of queued jobs (not yet running nor submitted to ThreadWeaver) 0211 int queuedCount() const; 0212 0213 /// Returns true if there are no jobs running nor queued anywhere 0214 bool isIdle() const; 0215 0216 void documentClosed(KDevelop::IDocument*); 0217 void documentLoaded(KDevelop::IDocument*); 0218 void documentUrlChanged(KDevelop::IDocument*); 0219 0220 void loadSettings(); 0221 0222 protected Q_SLOTS: 0223 void parseComplete(const ThreadWeaver::JobPointer& job); 0224 void parseProgress(KDevelop::ParseJob*, float value, const QString& text); 0225 void startTimer(int delay); 0226 void aboutToQuit(); 0227 void updateProgressBar(); 0228 0229 private: 0230 friend class BackgroundParserPrivate; 0231 class BackgroundParserPrivate* d_ptr; 0232 Q_DECLARE_PRIVATE(BackgroundParser) 0233 0234 private Q_SLOTS: 0235 /// Tracking of projects in state of loading. 0236 void projectAboutToBeOpened(KDevelop::IProject* project); 0237 void projectOpened(KDevelop::IProject* project); 0238 void projectOpeningAborted(KDevelop::IProject* project); 0239 }; 0240 } 0241 #endif