File indexing completed on 2024-05-12 04:37:45
0001 /* 0002 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "normaldeclarationcompletionitem.h" 0008 #include "codecompletionmodel.h" 0009 #include "../duchain/duchainlock.h" 0010 #include "../duchain/duchain.h" 0011 #include "../duchain/classfunctiondeclaration.h" 0012 #include "../duchain/types/functiontype.h" 0013 #include "../duchain/types/enumeratortype.h" 0014 #include "../duchain/duchainutils.h" 0015 #include "../duchain/navigation/abstractdeclarationnavigationcontext.h" 0016 #include <debug.h> 0017 0018 #include <KTextEditor/Document> 0019 #include <KTextEditor/View> 0020 0021 namespace KDevelop { 0022 const int NormalDeclarationCompletionItem::normalBestMatchesCount = 5; 0023 //If this is true, the return-values of argument-hints will be just written as "..." if they are too long 0024 const bool NormalDeclarationCompletionItem::shortenArgumentHintReturnValues = true; 0025 const int NormalDeclarationCompletionItem::maximumArgumentHintReturnValueLength = 30; 0026 const int NormalDeclarationCompletionItem::desiredTypeLength = 20; 0027 0028 NormalDeclarationCompletionItem::NormalDeclarationCompletionItem(const KDevelop::DeclarationPointer& decl, 0029 const QExplicitlySharedDataPointer<CodeCompletionContext>& context, 0030 int inheritanceDepth) 0031 : m_completionContext(context) 0032 , m_declaration(decl) 0033 , m_inheritanceDepth(inheritanceDepth) 0034 { 0035 } 0036 0037 KDevelop::DeclarationPointer NormalDeclarationCompletionItem::declaration() const 0038 { 0039 return m_declaration; 0040 } 0041 0042 QExplicitlySharedDataPointer<KDevelop::CodeCompletionContext> NormalDeclarationCompletionItem::completionContext() const 0043 { 0044 return m_completionContext; 0045 } 0046 0047 int NormalDeclarationCompletionItem::inheritanceDepth() const 0048 { 0049 return m_inheritanceDepth; 0050 } 0051 0052 int NormalDeclarationCompletionItem::argumentHintDepth() const 0053 { 0054 if (m_completionContext) 0055 return m_completionContext->depth(); 0056 else 0057 return 0; 0058 } 0059 0060 QString NormalDeclarationCompletionItem::declarationName() const 0061 { 0062 if (!m_declaration) { 0063 return QStringLiteral("<unknown>"); 0064 } 0065 QString ret = m_declaration->identifier().toString(); 0066 if (ret.isEmpty()) 0067 return QStringLiteral("<unknown>"); 0068 else 0069 return ret; 0070 } 0071 0072 void NormalDeclarationCompletionItem::execute(KTextEditor::View* view, const KTextEditor::Range& word) 0073 { 0074 if (m_completionContext && m_completionContext->depth() != 0) 0075 return; //Do not replace any text when it is an argument-hint 0076 0077 KTextEditor::Document* document = view->document(); 0078 QString newText; 0079 0080 { 0081 KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock()); 0082 if (m_declaration) { 0083 newText = declarationName(); 0084 } else { 0085 qCDebug(LANGUAGE) << "Declaration disappeared"; 0086 return; 0087 } 0088 } 0089 0090 document->replaceText(word, newText); 0091 KTextEditor::Range newRange = word; 0092 newRange.setEnd(KTextEditor::Cursor(newRange.end().line(), newRange.start().column() + newText.length())); 0093 0094 executed(view, newRange); 0095 } 0096 0097 QWidget* NormalDeclarationCompletionItem::createExpandingWidget(const KDevelop::CodeCompletionModel* model) const 0098 { 0099 Q_UNUSED(model); 0100 return nullptr; 0101 } 0102 0103 bool NormalDeclarationCompletionItem::createsExpandingWidget() const 0104 { 0105 return false; 0106 } 0107 0108 QString NormalDeclarationCompletionItem::shortenedTypeString(const KDevelop::DeclarationPointer& decl, 0109 int desiredTypeLength) const 0110 { 0111 Q_UNUSED(desiredTypeLength); 0112 return decl->abstractType()->toString(); 0113 } 0114 0115 void NormalDeclarationCompletionItem::executed(KTextEditor::View* view, const KTextEditor::Range& word) 0116 { 0117 Q_UNUSED(view); 0118 Q_UNUSED(word); 0119 } 0120 0121 QVariant NormalDeclarationCompletionItem::data(const QModelIndex& index, int role, 0122 const KDevelop::CodeCompletionModel* model) const 0123 { 0124 DUChainReadLocker lock(DUChain::lock(), 500); 0125 if (!lock.locked()) { 0126 qCDebug(LANGUAGE) << "Failed to lock the du-chain in time"; 0127 return QVariant(); 0128 } 0129 0130 if (!m_declaration) 0131 return QVariant(); 0132 0133 switch (role) { 0134 case Qt::DisplayRole: 0135 if (index.column() == CodeCompletionModel::Name) { 0136 return declarationName(); 0137 } else if (index.column() == CodeCompletionModel::Postfix) { 0138 if (FunctionType::Ptr functionType = m_declaration->type<FunctionType>()) { 0139 // Retrieve const/volatile string 0140 return functionType->AbstractType::toString(); 0141 } 0142 } else if (index.column() == CodeCompletionModel::Prefix) { 0143 if (m_declaration->kind() == Declaration::Namespace) 0144 return QStringLiteral("namespace"); 0145 if (m_declaration->abstractType()) { 0146 if (EnumeratorType::Ptr enumerator = m_declaration->type<EnumeratorType>()) { 0147 if (m_declaration->context()->owner() && m_declaration->context()->owner()->abstractType()) { 0148 if (!m_declaration->context()->owner()->identifier().isEmpty()) 0149 return shortenedTypeString(DeclarationPointer( 0150 m_declaration->context()->owner()), desiredTypeLength); 0151 else 0152 return QStringLiteral("enum"); 0153 } 0154 } 0155 if (FunctionType::Ptr functionType = m_declaration->type<FunctionType>()) { 0156 auto* funDecl = dynamic_cast<ClassFunctionDeclaration*>(m_declaration.data()); 0157 0158 if (functionType->returnType()) { 0159 QString ret = shortenedTypeString(m_declaration, desiredTypeLength); 0160 if (shortenArgumentHintReturnValues && argumentHintDepth() && 0161 ret.length() > maximumArgumentHintReturnValueLength) 0162 return QStringLiteral("..."); 0163 else 0164 return ret; 0165 } else if (argumentHintDepth()) { 0166 return QString();//Don't show useless prefixes in the argument-hints 0167 } else if (funDecl && funDecl->isConstructor()) 0168 return QStringLiteral("<constructor>"); 0169 else if (funDecl && funDecl->isDestructor()) 0170 return QStringLiteral("<destructor>"); 0171 else 0172 return QStringLiteral("<incomplete type>"); 0173 } else { 0174 return shortenedTypeString(m_declaration, desiredTypeLength); 0175 } 0176 } else { 0177 return QStringLiteral("<incomplete type>"); 0178 } 0179 } else if (index.column() == CodeCompletionModel::Arguments) { 0180 if (m_declaration->isFunctionDeclaration()) { 0181 auto functionType = declaration()->type<FunctionType>(); 0182 return functionType ? functionType->partToString(FunctionType::SignatureArguments) : QVariant(); 0183 } 0184 } 0185 break; 0186 case CodeCompletionModel::BestMatchesCount: 0187 return QVariant(normalBestMatchesCount); 0188 case CodeCompletionModel::IsExpandable: 0189 return QVariant(createsExpandingWidget()); 0190 case CodeCompletionModel::ExpandingWidget: { 0191 if (!createsExpandingWidget()) 0192 return {}; 0193 0194 QWidget* nav = createExpandingWidget(model); 0195 Q_ASSERT(nav); 0196 0197 QVariant v; 0198 v.setValue<QWidget*>(nav); 0199 return v; 0200 } 0201 case CodeCompletionModel::ScopeIndex: 0202 return static_cast<int>(reinterpret_cast<quintptr>(m_declaration->context())); 0203 0204 case CodeCompletionModel::CompletionRole: 0205 return ( int )completionProperties(); 0206 case CodeCompletionModel::ItemSelected: { 0207 NavigationContextPointer ctx(new AbstractDeclarationNavigationContext(DeclarationPointer( 0208 m_declaration), 0209 TopDUContextPointer())); 0210 return ctx->html(true); 0211 } 0212 case Qt::DecorationRole: 0213 { 0214 if (index.column() == CodeCompletionModel::Icon) { 0215 CodeCompletionModel::CompletionProperties p = completionProperties(); 0216 lock.unlock(); 0217 return DUChainUtils::iconForProperties(p); 0218 } 0219 break; 0220 } 0221 } 0222 return QVariant(); 0223 } 0224 }