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

0001 /*
0002     SPDX-FileCopyrightText: 2006-2008 Hamish Rodda <rodda@kde.org>
0003     SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KDEVPLATFORM_CODECOMPLETIONMODEL_H
0009 #define KDEVPLATFORM_CODECOMPLETIONMODEL_H
0010 
0011 #include <QPair>
0012 #include <QMap>
0013 #include <QPointer>
0014 #include <QExplicitlySharedDataPointer>
0015 #include <QUrl>
0016 
0017 #include "../duchain/duchainpointer.h"
0018 #include <language/languageexport.h>
0019 #include "codecompletioncontext.h"
0020 #include "codecompletionitem.h"
0021 
0022 #include <KTextEditor/CodeCompletionModel>
0023 #include <KTextEditor/CodeCompletionModelControllerInterface>
0024 
0025 class QMutex;
0026 
0027 namespace KDevelop {
0028 class DUContext;
0029 class Declaration;
0030 class CodeCompletionWorker;
0031 class CompletionWorkerThread;
0032 
0033 class KDEVPLATFORMLANGUAGE_EXPORT CodeCompletionModel
0034     : public KTextEditor::CodeCompletionModel
0035     , public KTextEditor::CodeCompletionModelControllerInterface
0036 {
0037     Q_OBJECT
0038     Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface)
0039 
0040 public:
0041     explicit CodeCompletionModel(QObject* parent);
0042     ~CodeCompletionModel() override;
0043 
0044     ///This MUST be called after the creation of this completion-model.
0045     ///If you use the KDevelop::CodeCompletion helper-class, that one cares about it.
0046     virtual void initialize();
0047 
0048     ///Entry-point for code-completion. This determines ome settings, clears the model, and then calls completionInvokedInternal for further processing.
0049     void completionInvoked(KTextEditor::View* view, const KTextEditor::Range& range,
0050                            KTextEditor::CodeCompletionModel::InvocationType invocationType) override;
0051 
0052     QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) const override;
0053 
0054     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
0055     int rowCount (const QModelIndex& parent = QModelIndex()) const override;
0056     QModelIndex parent (const QModelIndex& index) const override;
0057 
0058     ///Use this to set whether the code-completion widget should wait for this model until it's shown
0059     ///This makes sense when the model takes some time but not too much time, to make the UI less flickering and
0060     ///annoying.
0061     ///The default is false
0062     ///@todo Remove this option, make it true by default, and make sure in CodeCompletionWorker that the whole thing cannot break
0063     void setForceWaitForModel(bool wait);
0064 
0065     bool forceWaitForModel();
0066 
0067     ///Convenience-storage for use by the inherited completion model
0068     void setCompletionContext(const QExplicitlySharedDataPointer<CodeCompletionContext>& completionContext);
0069     QExplicitlySharedDataPointer<CodeCompletionContext> completionContext() const;
0070 
0071     ///Convenience-storage for use by the inherited completion model
0072     KDevelop::TopDUContextPointer currentTopContext() const;
0073     void setCurrentTopContext(const KDevelop::TopDUContextPointer& topContext);
0074 
0075     ///Whether the completion should be fully detailed. If false, it should be simplified, so no argument-hints,
0076     ///no expanding information, no type-information, etc.
0077     bool fullCompletion() const;
0078 
0079     MatchReaction matchingItem(const QModelIndex& matched) override;
0080 
0081     QString filterString(KTextEditor::View* view, const KTextEditor::Range& range,
0082                          const KTextEditor::Cursor& position) override;
0083 
0084     void clear();
0085 
0086     ///Returns the tree-element that belongs to the index, or zero
0087     QExplicitlySharedDataPointer<CompletionTreeElement> itemForIndex(const QModelIndex& index) const;
0088 
0089 Q_SIGNALS:
0090     ///Connection from this completion-model into the background worker thread. You should emit this from within completionInvokedInternal.
0091     void completionsNeeded(const KDevelop::DUContextPointer& context, const KTextEditor::Cursor& position,
0092                            KTextEditor::View* view);
0093     ///Additional signal that allows directly stepping into the worker-thread, bypassing computeCompletions(..) etc.
0094     ///doSpecialProcessing(data) will be executed in the background thread.
0095     void doSpecialProcessingInBackground(uint data);
0096 
0097 protected Q_SLOTS:
0098     ///Connection from the background-thread into the model: This is called when the background-thread is ready
0099     virtual void foundDeclarations(const QList<QExplicitlySharedDataPointer<CompletionTreeElement>>& item,
0100                                    const QExplicitlySharedDataPointer<CodeCompletionContext>& completionContext);
0101 
0102 protected:
0103     ///Eventually override this, determine the context or whatever, and then emit completionsNeeded(..) to continue processing in the background tread.
0104     ///The default-implementation does this completely, so if you don't need to do anything special, you can just leave it.
0105     virtual void completionInvokedInternal(KTextEditor::View* view, const KTextEditor::Range& range,
0106                                            KTextEditor::CodeCompletionModel::InvocationType invocationType,
0107                                            const QUrl& url);
0108 
0109     void executeCompletionItem(KTextEditor::View* view, const KTextEditor::Range& word,
0110                                const QModelIndex& index) const override;
0111 
0112     QExplicitlySharedDataPointer<CodeCompletionContext> m_completionContext;
0113     using DeclarationContextPair = QPair<KDevelop::DeclarationPointer,
0114         QExplicitlySharedDataPointer<CodeCompletionContext>>;
0115 
0116     QList<QExplicitlySharedDataPointer<CompletionTreeElement>> m_completionItems;
0117 
0118     /// Should create a completion-worker. The worker must have no parent object,
0119     /// because else its thread-affinity can not be changed.
0120     virtual CodeCompletionWorker* createCompletionWorker() = 0;
0121     friend class CompletionWorkerThread;
0122 
0123     CodeCompletionWorker* worker() const;
0124 
0125 private:
0126     bool m_forceWaitForModel;
0127     bool m_fullCompletion;
0128     QMutex* m_mutex;
0129     CompletionWorkerThread* m_thread;
0130     QString m_filterString;
0131     KDevelop::TopDUContextPointer m_currentTopContext;
0132 };
0133 }
0134 
0135 #endif