File indexing completed on 2024-04-21 15:24:06
0001 /* 0002 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> 0003 SPDX-FileCopyrightText: 2008 Hamish Rodda <rodda@kde.org> 0004 SPDX-FileCopyrightText: 2008 Niko Sams <niko.sams@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "item.h" 0010 0011 #include <KTextEditor/Range> 0012 #include <KTextEditor/View> 0013 #include <KTextEditor/Document> 0014 0015 #include <language/duchain/duchain.h> 0016 #include <language/duchain/duchainlock.h> 0017 #include <language/duchain/declaration.h> 0018 #include <language/duchain/namespacealiasdeclaration.h> 0019 #include <language/duchain/duchainutils.h> 0020 #include <language/duchain/types/functiontype.h> 0021 #include <language/codecompletion/codecompletionmodel.h> 0022 #include <language/codecompletion/codecompletionhelper.h> 0023 0024 #include "../duchain/declarations/classdeclaration.h" 0025 #include "../duchain/declarations/classmethoddeclaration.h" 0026 #include "../duchain/declarations/variabledeclaration.h" 0027 #include "../duchain/types/structuretype.h" 0028 #include "../duchain/navigation/navigationwidget.h" 0029 #include "../duchain/helper.h" 0030 0031 #include "helpers.h" 0032 #include "context.h" 0033 #include "completiondebug.h" 0034 0035 using namespace KDevelop; 0036 0037 namespace Php 0038 { 0039 0040 QString NormalDeclarationCompletionItem::declarationName() const 0041 { 0042 QString ret = prettyName(m_declaration.data()); 0043 if ( ret.isEmpty() ) { 0044 return QStringLiteral("<unknown>"); 0045 } 0046 bool isStatic = false; 0047 if (!m_declaration->isFunctionDeclaration()) { 0048 if (dynamic_cast<VariableDeclaration*>(m_declaration.data())) { 0049 ret = '$' + ret; 0050 } else if (ClassMemberDeclaration* memberDec = dynamic_cast<ClassMemberDeclaration*>(m_declaration.data())) { 0051 isStatic = memberDec->isStatic(); 0052 if (memberDec->isStatic() && memberDec->abstractType() && !(memberDec->abstractType()->modifiers() & AbstractType::ConstModifier)) { 0053 // PHP is strange, $obj->asdf, class::const but class::$static ... 0054 ret = '$' + ret; 0055 } 0056 } 0057 } else if ( ClassFunctionDeclaration* funDec = dynamic_cast<ClassFunctionDeclaration*>(m_declaration.data()) ) { 0058 isStatic = funDec->isStatic(); 0059 } 0060 0061 const QExplicitlySharedDataPointer<CodeCompletionContext>& ctx = completionContext(); 0062 0063 if ( ctx->memberAccessOperation() == CodeCompletionContext::NoMemberAccess ) { 0064 // if we complete a class member or method (inside a method) 0065 // we might have to add "self::", "parent::" or "$this->" 0066 if ( ctx->duContext() && ctx->duContext()->parentContext() 0067 && ctx->duContext()->parentContext()->type() == DUContext::Class ) 0068 { 0069 if ( m_declaration->context() && m_declaration->context()->type() == DUContext::Class ) { 0070 if ( isStatic ) { 0071 ret = "self::" + ret; 0072 } else { 0073 ret = "$this->" + ret; 0074 } 0075 } 0076 } 0077 } 0078 return ret; 0079 } 0080 0081 void NormalDeclarationCompletionItem::executed(KTextEditor::View* view, const KTextEditor::Range& word) 0082 { 0083 if (m_declaration && dynamic_cast<AbstractFunctionDeclaration*>(m_declaration.data())) { 0084 //Do some intelligent stuff for functions with the parens: 0085 insertFunctionParenText(view, word.end(), m_declaration); 0086 } 0087 } 0088 0089 QVariant NormalDeclarationCompletionItem::data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const 0090 { 0091 0092 DUChainReadLocker lock(DUChain::lock(), 500); 0093 if (!lock.locked()) { 0094 qCDebug(COMPLETION) << "Failed to lock the du-chain in time"; 0095 return QVariant(); 0096 } 0097 0098 if (!m_declaration) { 0099 return QVariant(); 0100 } 0101 0102 Declaration* dec = const_cast<Declaration*>(m_declaration.data()); 0103 0104 switch (role) { 0105 case CodeCompletionModel::ItemSelected: 0106 return QVariant(NavigationWidget::shortDescription(dec)); 0107 case Qt::DisplayRole: 0108 switch (index.column()) { 0109 case CodeCompletionModel::Postfix: 0110 return QVariant(); 0111 case CodeCompletionModel::Prefix: 0112 if (dec->kind() == Declaration::Type && !dec->isTypeAlias()) { 0113 if (dec->isFunctionDeclaration()) { 0114 FunctionType::Ptr funcType = dec->type<FunctionType>(); 0115 if ( funcType && funcType->returnType() ) { 0116 return funcType->returnType()->toString(); 0117 } else { 0118 return "<notype>"; 0119 } 0120 } else if (dec->internalContext() && dec->internalContext()->type() == DUContext::Class) { 0121 ClassDeclaration* classDec = dynamic_cast<ClassDeclaration*>(dec); 0122 if (classDec) { 0123 if (classDec->classType() == ClassDeclarationData::Interface) { 0124 return "interface"; 0125 } else { 0126 return "class"; 0127 } 0128 } 0129 } 0130 return QVariant(); 0131 } else if (dec->kind() == Declaration::Namespace) { 0132 return "namespace"; 0133 } 0134 break; 0135 0136 case CodeCompletionModel::Arguments: 0137 if (FunctionType::Ptr functionType = dec->type<FunctionType>()) { 0138 QString ret; 0139 createArgumentList(*this, ret, nullptr); 0140 return ret; 0141 } 0142 break; 0143 } 0144 break; 0145 case CodeCompletionModel::HighlightingMethod: 0146 if (index.column() == CodeCompletionModel::Arguments) { 0147 if (completionContext()->memberAccessOperation() == CodeCompletionContext::FunctionCallAccess) { 0148 return QVariant(CodeCompletionModel::CustomHighlighting); 0149 } else { 0150 return QVariant(); 0151 } 0152 break; 0153 } 0154 0155 break; 0156 0157 case CodeCompletionModel::CustomHighlight: 0158 if (index.column() == CodeCompletionModel::Arguments && completionContext()->memberAccessOperation() == CodeCompletionContext::FunctionCallAccess) { 0159 QString ret; 0160 QList<QVariant> highlight; 0161 createArgumentList(*this, ret, &highlight); 0162 return QVariant(highlight); 0163 } 0164 break; 0165 } 0166 lock.unlock(); 0167 0168 return KDevelop::NormalDeclarationCompletionItem::data(index, role, model); 0169 } 0170 0171 QWidget* NormalDeclarationCompletionItem::createExpandingWidget(const KDevelop::CodeCompletionModel* model) const 0172 { 0173 return new NavigationWidget(m_declaration, model->currentTopContext()); 0174 } 0175 0176 bool NormalDeclarationCompletionItem::createsExpandingWidget() const 0177 { 0178 return true; 0179 } 0180 0181 QExplicitlySharedDataPointer<Php::CodeCompletionContext> NormalDeclarationCompletionItem::completionContext() const 0182 { 0183 auto context = dynamic_cast<Php::CodeCompletionContext*>(m_completionContext.data()); 0184 return QExplicitlySharedDataPointer<Php::CodeCompletionContext>(context); 0185 } 0186 0187 0188 } 0189