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

0001 /*
0002     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "codecompletion.h"
0008 
0009 #include <interfaces/icore.h>
0010 #include <interfaces/ilanguagecontroller.h>
0011 #include <interfaces/ilanguagesupport.h>
0012 
0013 #include "../duchain/duchain.h"
0014 #include "../duchain/topducontext.h"
0015 #include <debug.h>
0016 #include "codecompletionmodel.h"
0017 #include <interfaces/idocumentcontroller.h>
0018 
0019 #include <KTextEditor/View>
0020 #include <KTextEditor/Document>
0021 #include <KTextEditor/CodeCompletionModel>
0022 #include <KTextEditor/CodeCompletionInterface>
0023 
0024 using namespace KTextEditor;
0025 using namespace KDevelop;
0026 
0027 CodeCompletion::CodeCompletion(QObject* parent, KTextEditor::CodeCompletionModel* aModel, const QString& language)
0028     : QObject(parent)
0029     , m_model(aModel)
0030     , m_language(language)
0031 {
0032     auto* kdevModel = qobject_cast<KDevelop::CodeCompletionModel*>(aModel);
0033     if (kdevModel)
0034         kdevModel->initialize();
0035     connect(KDevelop::ICore::self()->documentController(), &IDocumentController::textDocumentCreated,
0036             this, &CodeCompletion::textDocumentCreated);
0037     connect(ICore::self()->documentController(), &IDocumentController::documentUrlChanged,
0038             this, &CodeCompletion::documentUrlChanged);
0039     aModel->setParent(this);
0040 
0041     // prevent deadlock
0042     QMetaObject::invokeMethod(this, "checkDocuments", Qt::QueuedConnection);
0043 }
0044 
0045 CodeCompletion::~CodeCompletion()
0046 {
0047 }
0048 
0049 void CodeCompletion::checkDocuments()
0050 {
0051     const auto documents = KDevelop::ICore::self()->documentController()->openDocuments();
0052     for (KDevelop::IDocument* doc : documents) {
0053         if (doc->textDocument()) {
0054             checkDocument(doc->textDocument());
0055         }
0056     }
0057 }
0058 
0059 void CodeCompletion::viewCreated(KTextEditor::Document* document, KTextEditor::View* view)
0060 {
0061     Q_UNUSED(document);
0062 
0063     if (auto* cc = qobject_cast<CodeCompletionInterface*>(view)) {
0064         cc->registerCompletionModel(m_model);
0065         qCDebug(LANGUAGE) << "Registered completion model";
0066         emit registeredToView(view);
0067     }
0068 }
0069 
0070 void CodeCompletion::documentUrlChanged(KDevelop::IDocument* document)
0071 {
0072     // The URL has changed (might have a different language now), so we re-register the document
0073     Document* textDocument = document->textDocument();
0074 
0075     if (textDocument) {
0076         checkDocument(textDocument);
0077     }
0078 }
0079 
0080 void CodeCompletion::textDocumentCreated(KDevelop::IDocument* document)
0081 {
0082     Q_ASSERT(document->textDocument());
0083     checkDocument(document->textDocument());
0084 }
0085 
0086 void CodeCompletion::unregisterDocument(Document* textDocument)
0087 {
0088     const auto views = textDocument->views();
0089     for (KTextEditor::View* view : views) {
0090         if (auto* cc = qobject_cast<CodeCompletionInterface*>(view)) {
0091             cc->unregisterCompletionModel(m_model);
0092             emit unregisteredFromView(view);
0093         }
0094     }
0095 
0096     disconnect(textDocument, &Document::viewCreated, this, &CodeCompletion::viewCreated);
0097 }
0098 
0099 void CodeCompletion::checkDocument(Document* textDocument)
0100 {
0101     unregisterDocument(textDocument);
0102 
0103     const auto langs = ICore::self()->languageController()->languagesForUrl(textDocument->url());
0104 
0105     bool found = false;
0106     for (const auto lang : langs) {
0107         if (m_language == lang->name()) {
0108             found = true;
0109             break;
0110         }
0111     }
0112 
0113     if (!found && !m_language.isEmpty())
0114         return;
0115 
0116     const auto views = textDocument->views();
0117     for (KTextEditor::View* view : views) {
0118         viewCreated(textDocument, view);
0119     }
0120 
0121     connect(textDocument, &Document::viewCreated, this, &CodeCompletion::viewCreated);
0122 }
0123 
0124 #include "moc_codecompletion.cpp"