File indexing completed on 2024-05-12 04:37:56
0001 /* 0002 SPDX-FileCopyrightText: 2007 David Nolden <david.nolden@kdevelop.org> 0003 SPDX-FileCopyrightText: 2009 Lior Mualem <lior.m.kde@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "classdeclaration.h" 0009 #include "identifier.h" 0010 #include <language/duchain/declaration.h> 0011 #include <language/duchain/appendedlist.h> 0012 #include <language/duchain/duchainregister.h> 0013 #include "types/structuretype.h" 0014 #include <debug.h> 0015 0016 namespace KDevelop { 0017 DEFINE_LIST_MEMBER_HASH(ClassDeclarationData, baseClasses, BaseClassInstance) 0018 0019 ClassDeclaration::ClassDeclaration(const KDevelop::RangeInRevision& range, DUContext* context) 0020 : ClassMemberDeclaration(*new ClassDeclarationData, range) 0021 { 0022 d_func_dynamic()->setClassId(this); 0023 setContext(context); 0024 } 0025 0026 ClassDeclaration::ClassDeclaration(ClassDeclarationData& data, const KDevelop::RangeInRevision& range, 0027 DUContext* context) 0028 : ClassMemberDeclaration(data, range) 0029 { 0030 setContext(context); 0031 } 0032 0033 ClassDeclaration::ClassDeclaration(ClassDeclarationData& data) 0034 : ClassMemberDeclaration(data) 0035 { 0036 } 0037 0038 REGISTER_DUCHAIN_ITEM(ClassDeclaration); 0039 0040 void ClassDeclaration::clearBaseClasses() 0041 { 0042 d_func_dynamic()->baseClassesList().clear(); 0043 } 0044 0045 uint ClassDeclaration::baseClassesSize() const 0046 { 0047 return d_func()->baseClassesSize(); 0048 } 0049 0050 const BaseClassInstance* ClassDeclaration::baseClasses() const 0051 { 0052 return d_func()->baseClasses(); 0053 } 0054 0055 void ClassDeclaration::addBaseClass(const BaseClassInstance& klass) 0056 { 0057 d_func_dynamic()->baseClassesList().append(klass); 0058 } 0059 0060 void ClassDeclaration::replaceBaseClass(uint n, const BaseClassInstance& klass) 0061 { 0062 Q_ASSERT(n <= d_func()->baseClassesSize()); 0063 d_func_dynamic()->baseClassesList()[n] = klass; 0064 } 0065 0066 ClassDeclaration::~ClassDeclaration() 0067 { 0068 } 0069 0070 ClassDeclaration::ClassDeclaration(const ClassDeclaration& rhs) 0071 : ClassMemberDeclaration(*new ClassDeclarationData(*rhs.d_func())) 0072 { 0073 d_func_dynamic()->setClassId(this); 0074 } 0075 0076 Declaration* ClassDeclaration::clonePrivate() const 0077 { 0078 return new ClassDeclaration(*this); 0079 } 0080 0081 namespace { 0082 bool isPublicBaseClassInternal(const ClassDeclaration* self, ClassDeclaration* base, 0083 const KDevelop::TopDUContext* topContext, 0084 int* baseConversionLevels, int depth, QSet<const ClassDeclaration*>* checked) 0085 { 0086 if (checked) { 0087 if (checked->contains(self)) 0088 return false; 0089 checked->insert(self); 0090 } else if (depth > 3) { 0091 //Too much depth, to prevent endless recursion, we control the recursion using the 'checked' set 0092 QSet<const ClassDeclaration*> checkedSet; 0093 return isPublicBaseClassInternal(self, base, topContext, baseConversionLevels, depth, &checkedSet); 0094 } 0095 0096 if (baseConversionLevels) 0097 *baseConversionLevels = 0; 0098 0099 if (self->indexedType() == base->indexedType()) 0100 return true; 0101 0102 FOREACH_FUNCTION(const BaseClassInstance &b, self->baseClasses) 0103 { 0104 if (baseConversionLevels) 0105 ++(*baseConversionLevels); 0106 //qCDebug(LANGUAGE) << "public base of" << c->toString() << "is" << b.baseClass->toString(); 0107 if (b.access != KDevelop::Declaration::Private) { 0108 int nextBaseConversion = 0; 0109 if (StructureType::Ptr c = b.baseClass.type<StructureType>()) { 0110 auto* decl = dynamic_cast<ClassDeclaration*>(c->declaration(topContext)); 0111 if (decl && 0112 isPublicBaseClassInternal(decl, base, topContext, &nextBaseConversion, depth + 1, checked)) { 0113 if (baseConversionLevels) 0114 *baseConversionLevels += nextBaseConversion; 0115 return true; 0116 } 0117 } 0118 } 0119 if (baseConversionLevels) 0120 --(*baseConversionLevels); 0121 } 0122 return false; 0123 } 0124 } 0125 0126 bool ClassDeclaration::isPublicBaseClass(ClassDeclaration* base, const KDevelop::TopDUContext* topContext, 0127 int* baseConversionLevels) const 0128 { 0129 return isPublicBaseClassInternal(this, base, topContext, baseConversionLevels, 0, nullptr); 0130 } 0131 0132 QString ClassDeclaration::toString() const 0133 { 0134 QString ret; 0135 switch (classModifier()) { 0136 case ClassDeclarationData::None: 0137 //nothing 0138 break; 0139 case ClassDeclarationData::Abstract: 0140 ret += QLatin1String("abstract "); 0141 break; 0142 case ClassDeclarationData::Final: 0143 ret += QLatin1String("final "); 0144 break; 0145 } 0146 switch (classType()) { 0147 case ClassDeclarationData::Class: 0148 ret += QLatin1String("class "); 0149 break; 0150 case ClassDeclarationData::Interface: 0151 ret += QLatin1String("interface "); 0152 break; 0153 case ClassDeclarationData::Trait: 0154 ret += QLatin1String("trait "); 0155 break; 0156 case ClassDeclarationData::Union: 0157 ret += QLatin1String("union "); 0158 break; 0159 case ClassDeclarationData::Struct: 0160 ret += QLatin1String("struct "); 0161 break; 0162 } 0163 return ret + identifier().toString(); 0164 } 0165 0166 ClassDeclarationData::ClassType ClassDeclaration::classType() const 0167 { 0168 return d_func()->m_classType; 0169 } 0170 0171 void ClassDeclaration::setClassType(ClassDeclarationData::ClassType type) 0172 { 0173 d_func_dynamic()->m_classType = type; 0174 } 0175 0176 ClassDeclarationData::ClassModifier ClassDeclaration::classModifier() const 0177 { 0178 return d_func()->m_classModifier; 0179 } 0180 0181 void ClassDeclaration::setClassModifier(ClassDeclarationData::ClassModifier modifier) 0182 { 0183 d_func_dynamic()->m_classModifier = modifier; 0184 } 0185 }