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

0001 /*
0002     SPDX-FileCopyrightText: 2002-2005 Roberto Raggi <roberto@kdevelop.org>
0003     SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org>
0004     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
0005     SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-only
0008 */
0009 
0010 #include "classfunctiondeclaration.h"
0011 #include "ducontext.h"
0012 #include "types/functiontype.h"
0013 #include "duchainregister.h"
0014 #include <debug.h>
0015 
0016 namespace KDevelop {
0017 static Identifier& conversionIdentifier()
0018 {
0019     static Identifier conversionIdentifierObject(QStringLiteral("operator{...cast...}"));
0020     return conversionIdentifierObject;
0021 }
0022 
0023 REGISTER_DUCHAIN_ITEM(ClassFunctionDeclaration);
0024 
0025 ClassFunctionDeclaration::ClassFunctionDeclaration(const ClassFunctionDeclaration& rhs)
0026     : ClassFunctionDeclarationBase(*new ClassFunctionDeclarationData(*rhs.d_func()))
0027 {
0028 }
0029 
0030 void ClassFunctionDeclaration::setAbstractType(AbstractType::Ptr type)
0031 {
0032     ///TODO: write testcase for typealias case which used to trigger this warning:
0033     ///      typedef bool (*EventFilter)(void *message, long *result);
0034     ///      in e.g. qcoreapplication.h:172
0035     if (type && !dynamic_cast<FunctionType*>(type.data()) && type->whichType() != AbstractType::TypeAlias) {
0036         qCWarning(LANGUAGE) << "WARNING: Non-function type assigned to function declaration. Type is: "
0037                             << type->toString() << "whichType:" << type->whichType()
0038                             << "Declaration is:" << toString()
0039                             << topContext()->url().str() << range().castToSimpleRange();
0040     }
0041     ClassMemberDeclaration::setAbstractType(type);
0042 }
0043 
0044 DEFINE_LIST_MEMBER_HASH(ClassFunctionDeclarationData, m_defaultParameters, IndexedString)
0045 
0046 ClassFunctionDeclaration::ClassFunctionDeclaration(ClassFunctionDeclarationData& data) : ClassFunctionDeclarationBase(
0047         data)
0048 {
0049 }
0050 
0051 ClassFunctionDeclaration::ClassFunctionDeclaration(const RangeInRevision& range, DUContext* context)
0052     : ClassFunctionDeclarationBase(*new ClassFunctionDeclarationData, range)
0053 {
0054     d_func_dynamic()->setClassId(this);
0055     if (context)
0056         setContext(context);
0057 }
0058 
0059 ClassFunctionDeclaration::ClassFunctionDeclaration(ClassFunctionDeclarationData& data, const RangeInRevision& range,
0060                                                    DUContext* context)
0061     : ClassFunctionDeclarationBase(data, range)
0062 {
0063     if (context)
0064         setContext(context);
0065 }
0066 
0067 Declaration* ClassFunctionDeclaration::clonePrivate() const
0068 {
0069     return new ClassFunctionDeclaration(*this);
0070 }
0071 
0072 ClassFunctionDeclaration::~ClassFunctionDeclaration()
0073 {
0074 }
0075 
0076 bool ClassFunctionDeclaration::isFunctionDeclaration() const
0077 {
0078     return true;
0079 }
0080 
0081 QString ClassFunctionDeclaration::toString() const
0082 {
0083     if (!abstractType())
0084         return ClassMemberDeclaration::toString();
0085 
0086     TypePtr<FunctionType> function = type<FunctionType>();
0087     if (function) {
0088         return QStringLiteral("%1 %2 %3").arg(function->partToString(FunctionType::SignatureReturn),
0089                                               identifier().toString(),
0090                                               function->partToString(FunctionType::SignatureArguments));
0091     } else {
0092         QString type = abstractType() ? abstractType()->toString() : QStringLiteral("<notype>");
0093         qCDebug(LANGUAGE) << "A function has a bad type attached:" << type;
0094         return i18n("invalid member-function %1 type %2", identifier().toString(), type);
0095     }
0096 }
0097 
0098 /*bool ClassFunctionDeclaration::isSimilar(KDevelop::CodeItem *other, bool strict ) const
0099    {
0100    if (!CppClassMemberType::isSimilar(other,strict))
0101     return false;
0102 
0103    FunctionModelItem func = dynamic_cast<ClassFunctionDeclaration*>(other);
0104 
0105    if (isConstant() != func->isConstant())
0106     return false;
0107 
0108    if (arguments().count() != func->arguments().count())
0109     return false;
0110 
0111    for (int i=0; i<arguments().count(); ++i)
0112     {
0113       ArgumentModelItem arg1 = arguments().at(i);
0114       ArgumentModelItem arg2 = arguments().at(i);
0115 
0116       if (arg1->type() != arg2->type())
0117         return false;
0118     }
0119 
0120    return true;
0121    }*/
0122 
0123 uint setFlag(bool enable, uint flag, uint flags)
0124 {
0125     if (enable)
0126         return flags | flag;
0127     else
0128         return flags & (~flag);
0129 }
0130 
0131 bool ClassFunctionDeclaration::isAbstract() const
0132 {
0133     return d_func()->m_functionFlags & AbstractFunctionFlag;
0134 }
0135 
0136 void ClassFunctionDeclaration::setIsAbstract(bool abstract)
0137 {
0138     d_func_dynamic()->m_functionFlags = ( ClassFunctionFlags )setFlag(abstract, AbstractFunctionFlag,
0139                                                                       d_func()->m_functionFlags);
0140 }
0141 
0142 bool ClassFunctionDeclaration::isFinal() const
0143 {
0144     return d_func()->m_functionFlags & FinalFunctionFlag;
0145 }
0146 
0147 void ClassFunctionDeclaration::setIsFinal(bool final)
0148 {
0149     d_func_dynamic()->m_functionFlags = ( ClassFunctionFlags )setFlag(final, FinalFunctionFlag,
0150                                                                       d_func()->m_functionFlags);
0151 }
0152 
0153 bool ClassFunctionDeclaration::isSignal() const
0154 {
0155     return d_func()->m_functionFlags & FunctionSignalFlag;
0156 }
0157 
0158 void ClassFunctionDeclaration::setIsSignal(bool isSignal)
0159 {
0160     d_func_dynamic()->m_functionFlags = ( ClassFunctionFlags )setFlag(isSignal, FunctionSignalFlag,
0161                                                                       d_func()->m_functionFlags);
0162 }
0163 
0164 bool ClassFunctionDeclaration::isSlot() const
0165 {
0166     return d_func()->m_functionFlags & FunctionSlotFlag;
0167 }
0168 
0169 void ClassFunctionDeclaration::setIsSlot(bool isSlot)
0170 {
0171     d_func_dynamic()->m_functionFlags = ( ClassFunctionFlags )setFlag(isSlot, FunctionSlotFlag,
0172                                                                       d_func()->m_functionFlags);
0173 }
0174 
0175 bool ClassFunctionDeclaration::isConversionFunction() const
0176 {
0177     return identifier() == conversionIdentifier();
0178 }
0179 
0180 bool ClassFunctionDeclaration::isConstructor() const
0181 {
0182     DUContext* ctx = context();
0183     if (ctx && ctx->type() == DUContext::Class && ctx->localScopeIdentifier().top().nameEquals(identifier()))
0184         return true;
0185     return false;
0186 }
0187 
0188 bool ClassFunctionDeclaration::isDestructor() const
0189 {
0190     DUContext* ctx = context();
0191     QString id = identifier().toString();
0192     return ctx && ctx->type() == DUContext::Class && id.startsWith(QLatin1Char('~')) &&
0193            id.midRef(1) == ctx->localScopeIdentifier().top().toString();
0194 }
0195 
0196 uint ClassFunctionDeclaration::additionalIdentity() const
0197 {
0198     if (abstractType())
0199         return abstractType()->hash();
0200     else
0201         return 0;
0202 }
0203 
0204 const IndexedString* ClassFunctionDeclaration::defaultParameters() const
0205 {
0206     return d_func()->m_defaultParameters();
0207 }
0208 
0209 unsigned int ClassFunctionDeclaration::defaultParametersSize() const
0210 {
0211     return d_func()->m_defaultParametersSize();
0212 }
0213 
0214 void ClassFunctionDeclaration::addDefaultParameter(const IndexedString& str)
0215 {
0216     d_func_dynamic()->m_defaultParametersList().append(str);
0217 }
0218 
0219 void ClassFunctionDeclaration::clearDefaultParameters()
0220 {
0221     d_func_dynamic()->m_defaultParametersList().clear();
0222 }
0223 }