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 #include "codecompletionworker.h" 0009 0010 #include <KTextEditor/View> 0011 #include <KTextEditor/Document> 0012 #include <KLocalizedString> 0013 0014 #include "../duchain/ducontext.h" 0015 #include "../duchain/duchainlock.h" 0016 #include "../duchain/duchain.h" 0017 #include <debug.h> 0018 #include "codecompletion.h" 0019 #include "codecompletionitem.h" 0020 #include "codecompletionmodel.h" 0021 #include "codecompletionitemgrouper.h" 0022 #include <util/foregroundlock.h> 0023 0024 using namespace KTextEditor; 0025 using namespace KDevelop; 0026 0027 CodeCompletionWorker::CodeCompletionWorker(KDevelop::CodeCompletionModel* model) : 0028 m_hasFoundDeclarations(false) 0029 , m_mutex(new QMutex()) 0030 , m_abort(false) 0031 , m_fullCompletion(true) 0032 , m_model(model) 0033 { 0034 } 0035 0036 CodeCompletionWorker::~CodeCompletionWorker() 0037 { 0038 delete m_mutex; 0039 } 0040 0041 void CodeCompletionWorker::setFullCompletion(bool full) 0042 { 0043 m_fullCompletion = full; 0044 } 0045 0046 bool CodeCompletionWorker::fullCompletion() const 0047 { 0048 return m_fullCompletion; 0049 } 0050 0051 void CodeCompletionWorker::failed() 0052 { 0053 foundDeclarations({}, {}); 0054 } 0055 0056 void CodeCompletionWorker::foundDeclarations(const QList<CompletionTreeElementPointer>& items, 0057 const CodeCompletionContext::Ptr& completionContext) 0058 { 0059 m_hasFoundDeclarations = true; 0060 emit foundDeclarationsReal(items, completionContext); 0061 } 0062 0063 void CodeCompletionWorker::computeCompletions(const KDevelop::DUContextPointer& context, 0064 const KTextEditor::Cursor& position, KTextEditor::View* view) 0065 { 0066 { 0067 QMutexLocker lock(m_mutex); 0068 m_abort = false; 0069 } 0070 0071 ///@todo It's not entirely safe to pass KTextEditor::View* through a queued connection 0072 // We access the view/document which is not thread-safe, so we need the foreground lock 0073 ForegroundLock foreground; 0074 0075 //Compute the text we should complete on 0076 KTextEditor::Document* doc = view->document(); 0077 if (!doc) { 0078 qCDebug(LANGUAGE) << "No document for completion"; 0079 failed(); 0080 return; 0081 } 0082 0083 KTextEditor::Range range; 0084 QString text; 0085 { 0086 QMutexLocker lock(m_mutex); 0087 DUChainReadLocker lockDUChain; 0088 0089 if (context) { 0090 qCDebug(LANGUAGE) << context->localScopeIdentifier().toString(); 0091 range = KTextEditor::Range(context->rangeInCurrentRevision().start(), position); 0092 } else 0093 range = KTextEditor::Range(KTextEditor::Cursor(position.line(), 0), position); 0094 0095 updateContextRange(range, view, context); 0096 0097 text = doc->text(range); 0098 } 0099 0100 if (position.column() == 0) //Seems like when the cursor is a the beginning of a line, kate does not give the \n 0101 text += QLatin1Char('\n'); 0102 0103 if (aborting()) { 0104 failed(); 0105 return; 0106 } 0107 m_hasFoundDeclarations = false; 0108 0109 KTextEditor::Cursor cursorPosition = view->cursorPosition(); 0110 QString followingText; //followingText may contain additional text that stands for the current item. For example in the case "QString|", QString is in addedText. 0111 if (position < cursorPosition) 0112 followingText = view->document()->text(KTextEditor::Range(position, cursorPosition)); 0113 0114 foreground.unlock(); 0115 0116 computeCompletions(context, position, followingText, range, text); 0117 0118 if (!m_hasFoundDeclarations) 0119 failed(); 0120 } 0121 0122 void KDevelop::CodeCompletionWorker::doSpecialProcessing(uint) 0123 { 0124 } 0125 0126 CodeCompletionContext* CodeCompletionWorker::createCompletionContext(const KDevelop::DUContextPointer& context, 0127 const QString& contextText, 0128 const QString& followingText, 0129 const KDevelop::CursorInRevision& position) const 0130 { 0131 Q_UNUSED(context); 0132 Q_UNUSED(contextText); 0133 Q_UNUSED(followingText); 0134 Q_UNUSED(position); 0135 return nullptr; 0136 } 0137 0138 void CodeCompletionWorker::computeCompletions(const KDevelop::DUContextPointer& context, 0139 const KTextEditor::Cursor& position, const QString& followingText, 0140 const KTextEditor::Range& contextRange, const QString& contextText) 0141 { 0142 Q_UNUSED(contextRange); 0143 0144 qCDebug(LANGUAGE) << "added text:" << followingText; 0145 0146 CodeCompletionContext::Ptr completionContext(createCompletionContext(context, contextText, followingText, CursorInRevision::castFromSimpleCursor(KTextEditor::Cursor( 0147 position)))); 0148 if (KDevelop::CodeCompletionModel* m = model()) 0149 m->setCompletionContext(completionContext); 0150 0151 if (completionContext && completionContext->isValid()) { 0152 { 0153 DUChainReadLocker lock(DUChain::lock()); 0154 0155 if (!context) { 0156 failed(); 0157 qCDebug(LANGUAGE) << "Completion context disappeared before completions could be calculated"; 0158 return; 0159 } 0160 } 0161 QList<CompletionTreeItemPointer> items = completionContext->completionItems(aborting(), fullCompletion()); 0162 0163 if (aborting()) { 0164 failed(); 0165 return; 0166 } 0167 0168 QList<QExplicitlySharedDataPointer<CompletionTreeElement>> tree = computeGroups(items, completionContext); 0169 0170 if (aborting()) { 0171 failed(); 0172 return; 0173 } 0174 0175 tree += completionContext->ungroupedElements(); 0176 0177 foundDeclarations(tree, completionContext); 0178 } else { 0179 qCDebug(LANGUAGE) << "setContext: Invalid code-completion context"; 0180 } 0181 } 0182 0183 QList<QExplicitlySharedDataPointer<CompletionTreeElement>> CodeCompletionWorker::computeGroups( 0184 const QList<CompletionTreeItemPointer>& items, 0185 const QExplicitlySharedDataPointer<CodeCompletionContext>& completionContext) 0186 { 0187 Q_UNUSED(completionContext); 0188 QList<QExplicitlySharedDataPointer<CompletionTreeElement>> tree; 0189 /** 0190 * 1. Group by argument-hint depth 0191 * 2. Group by inheritance depth 0192 * 3. Group by simplified attributes 0193 * */ 0194 CodeCompletionItemGrouper<ArgumentHintDepthExtractor, CodeCompletionItemGrouper<InheritanceDepthExtractor, 0195 CodeCompletionItemGrouper<SimplifiedAttributesExtractor>>> argumentHintDepthGrouper(tree, nullptr, std::move( 0196 items)); 0197 return tree; 0198 } 0199 0200 void CodeCompletionWorker::abortCurrentCompletion() 0201 { 0202 QMutexLocker lock(m_mutex); 0203 m_abort = true; 0204 } 0205 0206 bool& CodeCompletionWorker::aborting() 0207 { 0208 return m_abort; 0209 } 0210 0211 KDevelop::CodeCompletionModel* CodeCompletionWorker::model() const 0212 { 0213 return m_model; 0214 } 0215 0216 void CodeCompletionWorker::updateContextRange(Range& contextRange, View* view, const DUContextPointer& context) const 0217 { 0218 Q_UNUSED(contextRange); 0219 Q_UNUSED(view); 0220 Q_UNUSED(context); 0221 } 0222 0223 #include "moc_codecompletionworker.cpp"