File indexing completed on 2024-06-16 04:23:16

0001 /*
0002     SPDX-FileCopyrightText: 2006 Roberto Raggi <roberto@kdevelop.org>
0003     SPDX-FileCopyrightText: 2006-2008 Hamish Rodda <rodda@kde.org>
0004     SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #include "functiontype.h"
0010 
0011 #include "typeregister.h"
0012 #include "typesystem.h"
0013 
0014 namespace KDevelop {
0015 REGISTER_TYPE(FunctionType);
0016 
0017 DEFINE_LIST_MEMBER_HASH(FunctionTypeData, m_arguments, IndexedType)
0018 
0019 FunctionType::FunctionType(const FunctionType& rhs) : AbstractType(copyData<FunctionType>(*rhs.d_func()))
0020 {
0021 }
0022 
0023 FunctionType::FunctionType(FunctionTypeData& data) : AbstractType(data)
0024 {
0025 }
0026 
0027 AbstractType* FunctionType::clone() const
0028 {
0029     return new FunctionType(*this);
0030 }
0031 
0032 bool FunctionType::equals(const AbstractType* _rhs) const
0033 {
0034     if (this == _rhs)
0035         return true;
0036 
0037     if (!AbstractType::equals(_rhs))
0038         return false;
0039 
0040     Q_ASSERT(dynamic_cast<const FunctionType*>(_rhs));
0041     const auto* rhs = static_cast<const FunctionType*>(_rhs);
0042 
0043     TYPE_D(FunctionType);
0044     if (d->m_argumentsSize() != rhs->d_func()->m_argumentsSize())
0045         return false;
0046 
0047     if (( bool )rhs->d_func()->m_returnType != ( bool )d->m_returnType)
0048         return false;
0049 
0050     if (d->m_returnType != rhs->d_func()->m_returnType)
0051         return false;
0052 
0053     for (unsigned int a = 0; a < d->m_argumentsSize(); ++a)
0054         if (d->m_arguments()[a] != rhs->d_func()->m_arguments()[a])
0055             return false;
0056 
0057     return true;
0058 }
0059 
0060 FunctionType::FunctionType()
0061     : AbstractType(createData<FunctionType>())
0062 {
0063 }
0064 
0065 FunctionType::~FunctionType()
0066 {
0067 }
0068 
0069 void FunctionType::addArgument(const AbstractType::Ptr& argument, int index)
0070 {
0071     if (index == -1)
0072         d_func_dynamic()->m_argumentsList().append(IndexedType(argument));
0073     else
0074         d_func_dynamic()->m_argumentsList().insert(index, IndexedType(argument));
0075 }
0076 
0077 void FunctionType::removeArgument(int i)
0078 {
0079     d_func_dynamic()->m_argumentsList().remove(i);
0080 }
0081 
0082 void FunctionType::setReturnType(const AbstractType::Ptr& returnType)
0083 {
0084     d_func_dynamic()->m_returnType = IndexedType(returnType);
0085 }
0086 
0087 AbstractType::Ptr FunctionType::returnType() const
0088 {
0089     return d_func()->m_returnType.abstractType();
0090 }
0091 
0092 QList<AbstractType::Ptr> FunctionType::arguments() const
0093 {
0094     ///@todo Don't do the conversion
0095     QList<AbstractType::Ptr> ret;
0096     ret.reserve(d_func()->m_argumentsSize());
0097     FOREACH_FUNCTION(const IndexedType &arg, d_func()->m_arguments)
0098     ret << arg.abstractType();
0099     return ret;
0100 }
0101 
0102 const IndexedType* FunctionType::indexedArguments() const
0103 {
0104     return d_func()->m_arguments();
0105 }
0106 
0107 uint FunctionType::indexedArgumentsSize() const
0108 {
0109     return d_func()->m_argumentsSize();
0110 }
0111 
0112 void FunctionType::accept0(TypeVisitor* v) const
0113 {
0114     TYPE_D(FunctionType);
0115     if (v->visit(this)) {
0116         acceptType(d->m_returnType.abstractType(), v);
0117 
0118         for (unsigned int i = 0; i < d->m_argumentsSize(); ++i)
0119             acceptType(d->m_arguments()[i].abstractType(), v);
0120     }
0121 
0122     v->endVisit(this);
0123 }
0124 
0125 void FunctionType::exchangeTypes(TypeExchanger* exchanger)
0126 {
0127     TYPE_D_DYNAMIC(FunctionType);
0128     for (uint i = 0; i < d->m_argumentsSize(); ++i)
0129         d->m_argumentsList()[i] = IndexedType(exchanger->exchange(d->m_arguments()[i].abstractType()));
0130 
0131     d->m_returnType = IndexedType(exchanger->exchange(d->m_returnType.abstractType()));
0132 }
0133 
0134 QString FunctionType::partToString(SignaturePart sigPart) const
0135 {
0136     QString args;
0137     TYPE_D(FunctionType);
0138     if (sigPart == SignatureArguments || sigPart == SignatureWhole) {
0139         QStringList types;
0140         types.reserve(d->m_argumentsSize());
0141         FOREACH_FUNCTION(const IndexedType &type, d->m_arguments) {
0142             types.append(type ? type.abstractType()->toString() : QStringLiteral("<notype>"));
0143         }
0144         args += QLatin1Char('(') + types.join(QLatin1String(", ")) + QLatin1Char(')');
0145     }
0146 
0147     if (sigPart == SignatureArguments)
0148         return args;
0149     else if (sigPart == SignatureWhole)
0150         return QStringLiteral("function %1 %2").arg(returnType() ? returnType()->toString() : QStringLiteral(
0151                                                         "<notype>"), args);
0152     else if (sigPart == SignatureReturn)
0153         return returnType() ? returnType()->toString() : QString();
0154 
0155     return QStringLiteral("ERROR");
0156 }
0157 
0158 QString FunctionType::toString() const
0159 {
0160     return partToString(SignatureWhole) + AbstractType::toString(true);
0161 }
0162 
0163 AbstractType::WhichType FunctionType::whichType() const
0164 {
0165     return TypeFunction;
0166 }
0167 
0168 uint FunctionType::hash() const
0169 {
0170     KDevHash kdevhash(AbstractType::hash());
0171     kdevhash << d_func()->m_returnType.hash();
0172 
0173     FOREACH_FUNCTION(const IndexedType &t, d_func()->m_arguments) {
0174         kdevhash << t.hash();
0175     }
0176 
0177     return kdevhash;
0178 }
0179 }