File indexing completed on 2024-05-19 15:41:37
0001 /* 0002 SPDX-FileCopyrightText: 2011 Sven Brauch <svenbrauch@googlemail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "functiondeclaration.h" 0008 0009 #include <language/codecompletion/normaldeclarationcompletionitem.h> 0010 #include <language/codecompletion/codecompletionmodel.h> 0011 #include <language/duchain/types/functiontype.h> 0012 #include <language/duchain/aliasdeclaration.h> 0013 #include <language/duchain/types/containertypes.h> 0014 0015 #include <KTextEditor/View> 0016 #include <KTextEditor/Document> 0017 #include <KLocalizedString> 0018 0019 #include "duchain/navigation/navigationwidget.h" 0020 #include "codecompletion/helpers.h" 0021 #include "declaration.h" 0022 #include "declarations/functiondeclaration.h" 0023 #include "duchain/helpers.h" 0024 0025 #include <QDebug> 0026 #include <codecompletiondebug.h> 0027 0028 using namespace KDevelop; 0029 using namespace KTextEditor; 0030 0031 namespace Python { 0032 0033 FunctionDeclarationCompletionItem::FunctionDeclarationCompletionItem(DeclarationPointer decl, CodeCompletionContext::Ptr context) 0034 : PythonDeclarationCompletionItem(decl, context) 0035 , m_atArgument(-1) 0036 , m_depth(0) 0037 , m_doNotCall(false) 0038 { 0039 0040 } 0041 0042 int FunctionDeclarationCompletionItem::atArgument() const 0043 { 0044 return m_atArgument; 0045 } 0046 0047 void FunctionDeclarationCompletionItem::setDepth(int d) 0048 { 0049 m_depth = d; 0050 } 0051 0052 void FunctionDeclarationCompletionItem::setAtArgument(int d) 0053 { 0054 m_atArgument = d; 0055 } 0056 0057 int FunctionDeclarationCompletionItem::argumentHintDepth() const 0058 { 0059 return m_depth; 0060 } 0061 0062 QVariant FunctionDeclarationCompletionItem::data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const 0063 { 0064 DUChainReadLocker lock; 0065 FunctionDeclaration* dec = dynamic_cast<FunctionDeclaration*>(m_declaration.data()); 0066 switch ( role ) { 0067 case Qt::DisplayRole: { 0068 if ( ! dec ) { 0069 break; // use the default 0070 } 0071 if ( index.column() == KDevelop::CodeCompletionModel::Arguments ) { 0072 if (FunctionType::Ptr functionType = dec->type<FunctionType>()) { 0073 QString ret; 0074 createArgumentList(dec, ret, nullptr, 0, false); 0075 return ret; 0076 } 0077 } 0078 if ( index.column() == KDevelop::CodeCompletionModel::Prefix ) { 0079 FunctionType::Ptr type = dec->type<FunctionType>(); 0080 if ( type && type->returnType() ) { 0081 return i18n("function") + " -> " + type->returnType()->toString(); 0082 } 0083 } 0084 break; 0085 } 0086 case KDevelop::CodeCompletionModel::HighlightingMethod: { 0087 if ( index.column() == KDevelop::CodeCompletionModel::Arguments ) 0088 return QVariant(KDevelop::CodeCompletionModel::CustomHighlighting); 0089 break; 0090 } 0091 case KDevelop::CodeCompletionModel::CustomHighlight: { 0092 if ( index.column() == KDevelop::CodeCompletionModel::Arguments ) { 0093 if ( ! dec ) return QVariant(); 0094 QString ret; 0095 QList<QVariant> highlight; 0096 if ( atArgument() ) { 0097 createArgumentList(dec, ret, &highlight, atArgument(), false); 0098 } 0099 else { 0100 createArgumentList(dec, ret, nullptr, false); 0101 } 0102 return QVariant(highlight); 0103 } 0104 break; 0105 } 0106 case KDevelop::CodeCompletionModel::MatchQuality: { 0107 if ( m_typeHint == PythonCodeCompletionContext::IterableRequested 0108 && dec && dec->type<FunctionType>() 0109 && dynamic_cast<ListType*>(dec->type<FunctionType>()->returnType().data()) ) 0110 { 0111 return 2 + PythonDeclarationCompletionItem::data(index, role, model).toInt(); 0112 } 0113 return PythonDeclarationCompletionItem::data(index, role, model); 0114 } 0115 } 0116 return Python::PythonDeclarationCompletionItem::data(index, role, model); 0117 } 0118 0119 void FunctionDeclarationCompletionItem::setDoNotCall(bool doNotCall) 0120 { 0121 m_doNotCall = doNotCall; 0122 } 0123 0124 void FunctionDeclarationCompletionItem::executed(KTextEditor::View* view, const KTextEditor::Range& word) 0125 { 0126 qCDebug(KDEV_PYTHON_CODECOMPLETION) << "FunctionDeclarationCompletionItem executed"; 0127 KTextEditor::Document* document = view->document(); 0128 auto resolvedDecl = Helper::resolveAliasDeclaration(declaration().data()); 0129 DUChainReadLocker lock; 0130 auto functionDecl = Helper::functionForCalled(resolvedDecl).declaration; 0131 lock.unlock(); 0132 if ( ! functionDecl && (! resolvedDecl || ! resolvedDecl->abstractType() 0133 || resolvedDecl->abstractType()->whichType() != AbstractType::TypeStructure) ) { 0134 qCritical(KDEV_PYTHON_CODECOMPLETION) << "ERROR: could not get declaration data, not executing completion item!"; 0135 return; 0136 } 0137 QString suffix = "()"; 0138 KTextEditor::Range checkPrefix(word.start().line(), 0, word.start().line(), word.start().column()); 0139 KTextEditor::Range checkSuffix(word.end().line(), word.end().column(), word.end().line(), document->lineLength(word.end().line())); 0140 if ( m_doNotCall || document->text(checkSuffix).trimmed().startsWith('(') 0141 || document->text(checkPrefix).trimmed().endsWith('@') 0142 || (functionDecl && functionDecl->isProperty()) ) 0143 { 0144 // don't insert brackets if they're already there, 0145 // the item is a decorator, or if it's an import item. 0146 suffix.clear(); 0147 } 0148 // place cursor behind bracktes by default 0149 int skip = 2; 0150 if ( functionDecl ) { 0151 bool needsArguments = false; 0152 int argumentCount = functionDecl->type<FunctionType>()->arguments().length(); 0153 if ( functionDecl->context()->type() == KDevelop::DUContext::Class ) { 0154 // it's a member function, so it has the implicit self 0155 // TODO static methods 0156 needsArguments = argumentCount > 1; 0157 } 0158 else { 0159 // it's a free function 0160 needsArguments = argumentCount > 0; 0161 } 0162 if ( needsArguments ) { 0163 // place cursor in brackets if there's parameters 0164 skip = 1; 0165 } 0166 } 0167 document->replaceText(word, declaration()->identifier().toString() + suffix); 0168 view->setCursorPosition( Cursor(word.end().line(), word.end().column() + skip) ); 0169 } 0170 0171 FunctionDeclarationCompletionItem::~FunctionDeclarationCompletionItem() { } 0172 0173 }