00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "declaration.h"
00021 #include "declarationdata.h"
00022
00023 #include <QtCore/QByteArray>
00024
00025 #include <ktexteditor/smartrange.h>
00026 #include <ktexteditor/document.h>
00027
00028 #include <limits>
00029
00030 #include "topducontext.h"
00031 #include "topducontextdynamicdata.h"
00032 #include "use.h"
00033 #include "forwarddeclaration.h"
00034 #include "duchain.h"
00035 #include "duchainlock.h"
00036 #include "ducontextdata.h"
00037 #include "declarationid.h"
00038 #include "uses.h"
00039 #include "indexedstring.h"
00040 #include "duchainregister.h"
00041 #include "persistentsymboltable.h"
00042 #include "repositories/stringrepository.h"
00043 #include "types/identifiedtype.h"
00044 #include "types/structuretype.h"
00045 #include "functiondefinition.h"
00046 #include "codemodel.h"
00047 #include "specializationstore.h"
00048 #include "types/typeutils.h"
00049 #include "types/typealiastype.h"
00050
00051 using namespace KTextEditor;
00052
00053 namespace KDevelop
00054 {
00055
00057 Repositories::StringRepository commentRepository("Comment Repository");
00058
00059 REGISTER_DUCHAIN_ITEM(Declaration);
00060
00061 DeclarationData::DeclarationData()
00062 : m_comment(0), m_isDefinition(false), m_inSymbolTable(false),
00063 m_isTypeAlias(false), m_anonymousInContext(false), m_isFinal(false)
00064 {
00065 m_kind = Declaration::Instance;
00066 }
00067
00068 DeclarationData::DeclarationData( const DeclarationData& rhs ) : DUChainBaseData(rhs),
00069 m_internalContext(rhs.m_internalContext),
00070 m_type(rhs.m_type),
00071 m_identifier(rhs.m_identifier),
00072 m_declaration(rhs.m_declaration),
00073 m_comment(rhs.m_comment),
00074 m_kind(rhs.m_kind),
00075 m_isDefinition(rhs.m_isDefinition),
00076 m_inSymbolTable(rhs.m_inSymbolTable),
00077 m_isTypeAlias(rhs.m_isTypeAlias),
00078 m_anonymousInContext(rhs.m_anonymousInContext),
00079 m_isFinal(rhs.m_isFinal)
00080 {
00081 }
00082
00083 Declaration::Kind Declaration::kind() const {
00084 DUCHAIN_D(Declaration);
00085 return d->m_kind;
00086 }
00087
00088 void Declaration::setKind(Kind kind) {
00089 DUCHAIN_D_DYNAMIC(Declaration);
00090 d->m_kind = kind;
00091 updateCodeModel();
00092 }
00093
00094 bool Declaration::inDUChain() const {
00095 DUCHAIN_D(Declaration);
00096 if( d->m_anonymousInContext )
00097 return false;
00098 if( !context() )
00099 return false;
00100 TopDUContext* top = topContext();
00101 return top && top->inDUChain();
00102 }
00103
00104 Declaration::Declaration( const SimpleRange& range, DUContext* context )
00105 : DUChainBase(*new DeclarationData, range)
00106 {
00107 d_func_dynamic()->setClassId(this);
00108 m_topContext = 0;
00109 m_context = 0;
00110 m_indexInTopContext = 0;
00111
00112 if(context)
00113 setContext(context);
00114 }
00115
00116 uint Declaration::ownIndex() const
00117 {
00118 ENSURE_CAN_READ
00119 return m_indexInTopContext;
00120 }
00121
00122 Declaration::Declaration(const Declaration& rhs)
00123 : DUChainBase(*new DeclarationData( *rhs.d_func() )) {
00124 setSmartRange(rhs.smartRange(), DocumentRangeObject::DontOwn);
00125 m_topContext = 0;
00126 m_context = 0;
00127 m_indexInTopContext = 0;
00128 }
00129
00130 Declaration::Declaration( DeclarationData & dd ) : DUChainBase(dd)
00131 {
00132 m_topContext = 0;
00133 m_context = 0;
00134 m_indexInTopContext = 0;
00135 }
00136
00137 Declaration::Declaration( DeclarationData & dd, const SimpleRange& range )
00138 : DUChainBase(dd, range)
00139 {
00140 m_topContext = 0;
00141 m_context = 0;
00142 m_indexInTopContext = 0;
00143 }
00144
00145 Declaration::~Declaration()
00146 {
00147 uint oldOwnIndex = m_indexInTopContext;
00148
00149 TopDUContext* topContext = this->topContext();
00150
00151
00152 if(!topContext->deleting() || !topContext->isOnDisk()) {
00153 DUCHAIN_D_DYNAMIC(Declaration);
00154
00155 if( d->m_internalContext.context() )
00156 d->m_internalContext.context()->setOwner(0);
00157
00158 if (d->m_inSymbolTable && !d->m_identifier.isEmpty()) {
00159 QualifiedIdentifier id = qualifiedIdentifier();
00160 PersistentSymbolTable::self().removeDeclaration(id, this);
00161 CodeModel::self().removeItem(url(), id);
00162 }
00163
00164 d->m_inSymbolTable = false;
00165 }
00166
00167
00168
00169 if (context() && !d_func()->m_anonymousInContext) {
00170 if(!topContext->deleting() || !topContext->isOnDisk() || context()->d_func()->isDynamic())
00171 context()->m_dynamicData->removeDeclaration(this);
00172 }
00173
00174 clearOwnIndex();
00175
00176 if(!topContext->deleting() || !topContext->isOnDisk()) {
00177 setContext(0);
00178
00179 setAbstractType(AbstractType::Ptr());
00180 }
00181 Q_ASSERT(d_func()->isDynamic() == (!topContext->deleting() || !topContext->isOnDisk() || topContext->m_dynamicData->isTemporaryDeclarationIndex(oldOwnIndex)));
00182
00183 }
00184
00185 QByteArray Declaration::comment() const {
00186 DUCHAIN_D(Declaration);
00187 if(!d->m_comment)
00188 return 0;
00189 else
00190 return Repositories::arrayFromItem(commentRepository.itemFromIndex(d->m_comment));
00191 }
00192
00193 void Declaration::setComment(const QByteArray& str) {
00194 DUCHAIN_D_DYNAMIC(Declaration);
00195 if(str.isEmpty())
00196 d->m_comment = 0;
00197 else
00198 d->m_comment = commentRepository.index(Repositories::StringRepositoryItemRequest(str, IndexedString::hashString(str, str.length()), str.length()));
00199 }
00200
00201 void Declaration::setComment(const QString& str) {
00202 setComment(str.toUtf8());
00203 }
00204
00205 Identifier Declaration::identifier( ) const
00206 {
00207
00208 return d_func()->m_identifier.identifier();
00209 }
00210
00211 IndexedIdentifier Declaration::indexedIdentifier( ) const
00212 {
00213
00214 return d_func()->m_identifier;
00215 }
00216
00217 LocalIndexedDeclaration::LocalIndexedDeclaration(Declaration* decl) {
00218 if(!decl)
00219 m_declarationIndex = 0;
00220 else
00221 m_declarationIndex = decl->m_indexInTopContext;
00222 }
00223
00224 LocalIndexedDeclaration::LocalIndexedDeclaration(uint declarationIndex) : m_declarationIndex(declarationIndex) {
00225 }
00226
00227 Declaration* LocalIndexedDeclaration::data(TopDUContext* top) const {
00228 if(!m_declarationIndex)
00229 return 0;
00230 return top->m_dynamicData->getDeclarationForIndex(m_declarationIndex);
00231 }
00232
00233 bool LocalIndexedDeclaration::isLoaded(TopDUContext* top) const {
00234 if(m_declarationIndex)
00235 return top->m_dynamicData->isDeclarationForIndexLoaded(m_declarationIndex);
00236 else
00237 return false;
00238 }
00239
00240 IndexedDeclaration::IndexedDeclaration(uint topContext, uint declarationIndex) : m_topContext(topContext), m_declarationIndex(declarationIndex) {
00241 }
00242
00243 IndexedDeclaration::IndexedDeclaration(Declaration* decl) {
00244 if(decl) {
00245 m_topContext = decl->topContext()->ownIndex();
00246 m_declarationIndex = decl->m_indexInTopContext;
00247 }else{
00248 m_topContext = 0;
00249 m_declarationIndex = 0;
00250 }
00251 }
00252
00253 Declaration* IndexedDeclaration::declaration() const {
00254 if(isDummy())
00255 return 0;
00256
00257 if(!m_topContext || !m_declarationIndex)
00258 return 0;
00259
00260 TopDUContext* ctx = DUChain::self()->chainForIndex(m_topContext);
00261 if(!ctx)
00262 return 0;
00263
00264 return ctx->m_dynamicData->getDeclarationForIndex(m_declarationIndex);
00265 }
00266
00267 void Declaration::rebuildDynamicData(DUContext* parent, uint ownIndex)
00268 {
00269 DUChainBase::rebuildDynamicData(parent, ownIndex);
00270
00271 m_context = parent;
00272 m_topContext = parent->topContext();
00273 m_indexInTopContext = ownIndex;
00274
00275 parent->m_dynamicData->addDeclarationToHash(d_func()->m_identifier.identifier(), this);
00276 }
00277
00278 void Declaration::setIdentifier(const Identifier& identifier)
00279 {
00280 ENSURE_CAN_WRITE
00281 DUCHAIN_D_DYNAMIC(Declaration);
00282 bool wasInSymbolTable = d->m_inSymbolTable;
00283
00284 setInSymbolTable(false);
00285
00286 if( m_context && !d->m_anonymousInContext )
00287 m_context->changingIdentifier( this, d->m_identifier, identifier );
00288
00289 d->m_identifier = identifier;
00290
00291 setInSymbolTable(wasInSymbolTable);
00292
00293 }
00294
00295 IndexedType Declaration::indexedType() const
00296 {
00297 return d_func()->m_type;
00298 }
00299
00300 AbstractType::Ptr Declaration::abstractType( ) const
00301 {
00302
00303 return d_func()->m_type.abstractType();
00304 }
00305
00306 void Declaration::setAbstractType(AbstractType::Ptr type)
00307 {
00308 ENSURE_CAN_WRITE
00309 DUCHAIN_D_DYNAMIC(Declaration);
00310
00311
00312
00313
00314 d->m_type = type->indexed();
00315
00316 updateCodeModel();
00317
00318
00319 }
00320
00321 Declaration* Declaration::specialize(IndexedInstantiationInformation , const TopDUContext* , int )
00322 {
00323 return this;
00324 }
00325
00326 QualifiedIdentifier Declaration::qualifiedIdentifier() const
00327 {
00328 ENSURE_CAN_READ
00329
00330 QualifiedIdentifier ret;
00331 DUContext* ctx = m_context;
00332 if(ctx)
00333 ret = ctx->scopeIdentifier(true);
00334 ret.push(d_func()->m_identifier);
00335 return ret;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 DUContext * Declaration::context() const
00350 {
00351
00352 return m_context;
00353 }
00354
00355 bool Declaration::isAnonymous() const
00356 {
00357 return d_func()->m_anonymousInContext;
00358 }
00359
00360 void Declaration::setContext(DUContext* context, bool anonymous)
00361 {
00362 Q_ASSERT(!context || context->topContext());
00364 if(!specialization().index()) {
00365
00366
00367 }
00368
00369 setInSymbolTable(false);
00370
00371
00372
00373
00374
00375 DUCHAIN_D_DYNAMIC(Declaration);
00376 if (m_context && context) {
00377 Q_ASSERT(m_context->topContext() == context->topContext());
00378 }
00379
00380 if (m_context) {
00381 if( !d->m_anonymousInContext ) {
00382 m_context->m_dynamicData->removeDeclaration(this);
00383
00384 }
00385 }
00386
00387 if(context)
00388 m_topContext = context->topContext();
00389 else
00390 m_topContext = 0;
00391
00392 d->m_anonymousInContext = anonymous;
00393 m_context = context;
00394
00395 if (context) {
00396 if(!m_indexInTopContext)
00397 allocateOwnIndex();
00398
00399 if(!d->m_anonymousInContext) {
00400 context->m_dynamicData->addDeclaration(this);
00401
00402 }
00403
00404 if(context->inSymbolTable() && !anonymous)
00405 setInSymbolTable(true);
00406 }
00407 }
00408
00409 void Declaration::clearOwnIndex() {
00410
00411 if(!m_indexInTopContext)
00412 return;
00413
00414 if(!context() || (!d_func()->m_anonymousInContext && !context()->isAnonymous())) {
00415 ENSURE_CAN_WRITE
00416 }
00417
00418 if(m_indexInTopContext) {
00419 Q_ASSERT(m_topContext);
00420 m_topContext->m_dynamicData->clearDeclarationIndex(this);
00421 }
00422 m_indexInTopContext = 0;
00423 }
00424
00425 void Declaration::allocateOwnIndex() {
00426
00428
00429
00430
00431
00432 Q_ASSERT(m_topContext);
00433
00434 m_indexInTopContext = m_topContext->m_dynamicData->allocateDeclarationIndex(this, d_func()->m_anonymousInContext || !context() || context()->isAnonymous());
00435 Q_ASSERT(m_indexInTopContext);
00436
00437 if(!m_topContext->m_dynamicData->getDeclarationForIndex(m_indexInTopContext))
00438 kFatal() << "Could not re-retrieve declaration" << "index:" << m_indexInTopContext;
00439
00440 }
00441
00442 const Declaration* Declaration::logicalDeclaration(const TopDUContext* topContext) const {
00443 ENSURE_CAN_READ
00444 if(isForwardDeclaration()) {
00445 const ForwardDeclaration* dec = toForwardDeclaration();
00446 Declaration* ret = dec->resolve(topContext);
00447 if(ret)
00448 return ret;
00449 }
00450 return this;
00451 }
00452
00453 Declaration* Declaration::logicalDeclaration(const TopDUContext* topContext) {
00454 ENSURE_CAN_READ
00455 if(isForwardDeclaration()) {
00456 ForwardDeclaration* dec = toForwardDeclaration();
00457 Declaration* ret = dec->resolve(topContext);
00458 if(ret)
00459 return ret;
00460 }
00461 return this;
00462 }
00463
00464 DUContext * Declaration::logicalInternalContext(const TopDUContext* topContext) const {
00465 ENSURE_CAN_READ
00466
00467 if(!isDefinition()) {
00468 Declaration* def = FunctionDefinition::definition(this);
00469 if( def )
00470 return def->internalContext();
00471 }
00472
00473 if( d_func()->m_isTypeAlias ) {
00475 TypeAliasType::Ptr t = type<TypeAliasType>();
00476 if(t) {
00477 AbstractType::Ptr target = t->type();
00478
00479 IdentifiedType* idType = dynamic_cast<IdentifiedType*>(target.unsafeData());
00480 if( idType ) {
00481 Declaration* decl = idType->declaration(topContext);
00482 if(decl && decl != this) {
00483 return decl->logicalInternalContext( topContext );
00484 }
00485 }
00486 }
00487 }
00488
00489 return internalContext();
00490 }
00491
00492 DUContext * Declaration::internalContext() const
00493 {
00494
00495 return d_func()->m_internalContext.context();
00496 }
00497
00498 void Declaration::setInternalContext(DUContext* context)
00499 {
00500 if(this->context()) {
00501 ENSURE_CAN_WRITE
00502 }
00503 DUCHAIN_D_DYNAMIC(Declaration);
00504
00505 if( context == d->m_internalContext.context() )
00506 return;
00507
00508 if(!m_topContext) {
00509
00510 m_topContext = context->topContext();
00511 allocateOwnIndex();
00512 }
00513
00514 DUContext* oldInternalContext = d->m_internalContext.context();
00515
00516 d->m_internalContext = context;
00517
00518
00519 if( oldInternalContext && oldInternalContext->owner() == this )
00520 oldInternalContext->setOwner(0);
00521
00522
00523 if( context )
00524 context->setOwner(this);
00525 }
00526
00527
00528 bool Declaration::operator ==(const Declaration & other) const
00529 {
00530 ENSURE_CAN_READ
00531
00532 return this == &other;
00533 }
00534
00535 QString Declaration::toString() const
00536 {
00537 return QString("%3 %4").arg(abstractType() ? abstractType()->toString() : QString("<notype>")).arg(identifier().toString());
00538 }
00539
00540
00541
00542 bool Declaration::isDefinition() const
00543 {
00544 ENSURE_CAN_READ
00545 DUCHAIN_D(Declaration);
00546
00547 return d->m_isDefinition;
00548 }
00549
00550 void Declaration::setDeclarationIsDefinition(bool dd)
00551 {
00552 ENSURE_CAN_WRITE
00553 DUCHAIN_D_DYNAMIC(Declaration);
00554 d->m_isDefinition = dd;
00555
00556
00557
00558 }
00559
00560 bool Declaration::isFinal() const
00561 {
00562 return d_func()->m_isFinal;
00563 }
00564
00565 void Declaration::setFinal(bool final)
00566 {
00567 d_func_dynamic()->m_isFinal = final;
00568 }
00569
00571 bool Declaration::isTypeAlias() const {
00572 DUCHAIN_D(Declaration);
00573 return d->m_isTypeAlias;
00574 }
00575
00576 void Declaration::setIsTypeAlias(bool isTypeAlias) {
00577 DUCHAIN_D_DYNAMIC(Declaration);
00578 d->m_isTypeAlias = isTypeAlias;
00579 }
00580
00581 IndexedInstantiationInformation Declaration::specialization() const {
00582 return IndexedInstantiationInformation();
00583 }
00584
00585 void Declaration::activateSpecialization()
00586 {
00587 if(specialization().index()) {
00588 DeclarationId baseId(id());
00589 baseId.setSpecialization(IndexedInstantiationInformation());
00590 SpecializationStore::self().set(baseId, specialization());
00591 }
00592 }
00593
00594 DeclarationId Declaration::id(bool forceDirect) const
00595 {
00596 ENSURE_CAN_READ
00597 if(inSymbolTable() && !forceDirect)
00598 return DeclarationId(qualifiedIdentifier(), additionalIdentity(), specialization());
00599 else
00600 return DeclarationId(IndexedDeclaration(const_cast<Declaration*>(this)), specialization());
00601 }
00602
00603 bool Declaration::inSymbolTable() const
00604 {
00605 DUCHAIN_D(Declaration);
00606 return d->m_inSymbolTable;
00607 }
00608
00609 CodeModelItem::Kind kindForDeclaration(Declaration* decl) {
00610 CodeModelItem::Kind kind = CodeModelItem::Unknown;
00611
00612 if(decl->kind() == Declaration::Namespace)
00613 return CodeModelItem::Namespace;
00614
00615 if(decl->isFunctionDeclaration()) {
00616 kind = CodeModelItem::Function;
00617 }
00618
00619 if(decl->kind() == Declaration::Type && decl->type<StructureType>())
00620 kind = CodeModelItem::Class;
00621
00622 if(kind == CodeModelItem::Unknown && decl->kind() == Declaration::Instance)
00623 kind = CodeModelItem::Variable;
00624
00625 if(decl->isForwardDeclaration())
00626 kind = (CodeModelItem::Kind)(kind | CodeModelItem::ForwardDeclaration);
00627
00628 return kind;
00629 }
00630
00631 void Declaration::updateCodeModel()
00632 {
00633 DUCHAIN_D(Declaration);
00634 if(!d->m_identifier.isEmpty() && d->m_inSymbolTable) {
00635 QualifiedIdentifier id(qualifiedIdentifier());
00636 CodeModel::self().updateItem(url(), id, kindForDeclaration(this));
00637 }
00638 }
00639
00640 void Declaration::setInSymbolTable(bool inSymbolTable)
00641 {
00642 DUCHAIN_D_DYNAMIC(Declaration);
00643 if(!d->m_identifier.isEmpty()) {
00644 if(!d->m_inSymbolTable && inSymbolTable) {
00645 QualifiedIdentifier id(qualifiedIdentifier());
00646 PersistentSymbolTable::self().addDeclaration(id, this);
00647
00648 CodeModel::self().addItem(url(), id, kindForDeclaration(this));
00649 }
00650
00651 else if(d->m_inSymbolTable && !inSymbolTable) {
00652 QualifiedIdentifier id(qualifiedIdentifier());
00653 PersistentSymbolTable::self().removeDeclaration(id, this);
00654
00655 CodeModel::self().removeItem(url(), id);
00656 }
00657 }
00658 d->m_inSymbolTable = inSymbolTable;
00659 }
00660
00661 ForwardDeclaration* Declaration::toForwardDeclaration()
00662 {
00663 return static_cast<ForwardDeclaration*>(this);
00664 }
00665
00666 const ForwardDeclaration* Declaration::toForwardDeclaration() const
00667 {
00668 return static_cast<const ForwardDeclaration*>(this);
00669 }
00670
00671 TopDUContext * Declaration::topContext() const
00672 {
00673 return m_topContext;
00674 }
00675
00676 Declaration* Declaration::clonePrivate() const {
00677 return new Declaration(*this);
00678 }
00679
00680 Declaration* Declaration::clone() const {
00681 Declaration* ret = clonePrivate();
00682 ret->d_func_dynamic()->m_inSymbolTable = false;
00683 return ret;
00684 }
00685
00686 bool Declaration::isForwardDeclaration() const
00687 {
00688 return false;
00689 }
00690
00691 bool Declaration::isFunctionDeclaration() const
00692 {
00693 return false;
00694 }
00695
00696 uint Declaration::additionalIdentity() const
00697 {
00698 return 0;
00699 }
00700
00701 bool Declaration::equalQualifiedIdentifier(const Declaration* rhs) const {
00702 ENSURE_CAN_READ
00703 DUCHAIN_D(Declaration);
00704 if(d->m_identifier != rhs->d_func()->m_identifier)
00705 return false;
00706
00707 return m_context->equalScopeIdentifier(m_context);
00708 }
00709
00710 QList<KTextEditor::SmartRange*> Declaration::smartUses() const
00711 {
00712 Q_ASSERT(topContext());
00713 ENSURE_CAN_READ
00714 QSet<KTextEditor::SmartRange*> tempUses;
00715
00716 {
00717 foreach(KTextEditor::SmartRange* range, allSmartUses(topContext(), const_cast<Declaration*>(this)))
00718 tempUses.insert(range);
00719 }
00720
00721 KDevVarLengthArray<IndexedTopDUContext> useContexts = DUChain::uses()->uses(id());
00722
00723 FOREACH_ARRAY(IndexedTopDUContext indexedContext, useContexts) {
00724 if(!indexedContext.isLoaded())
00725 continue;
00726 TopDUContext* context = indexedContext.data();
00727 if(context) {
00728 foreach(KTextEditor::SmartRange* range, allSmartUses(context, const_cast<Declaration*>(this)))
00729 tempUses.insert(range);
00730 }
00731 }
00732
00733 return tempUses.toList();
00734 }
00735
00736 QMap<IndexedString, QList<SimpleRange> > Declaration::uses() const
00737 {
00738 ENSURE_CAN_READ
00739 QMap<IndexedString, QMap<SimpleRange, bool> > tempUses;
00740
00741
00742 {
00743 QMap<SimpleRange, bool>& ranges(tempUses[topContext()->url()]);
00744 foreach(const SimpleRange& range, allUses(topContext(), const_cast<Declaration*>(this)))
00745 ranges[range] = true;
00746 }
00747
00748 KDevVarLengthArray<IndexedTopDUContext> useContexts = DUChain::uses()->uses(id());
00749
00750 FOREACH_ARRAY(IndexedTopDUContext indexedContext, useContexts) {
00751 TopDUContext* context = indexedContext.data();
00752 if(context) {
00753 QMap<SimpleRange, bool>& ranges(tempUses[context->url()]);
00754 foreach(const SimpleRange& range, allUses(context, const_cast<Declaration*>(this)))
00755 ranges[range] = true;
00756 }
00757 }
00758
00759 QMap<IndexedString, QList<SimpleRange> > ret;
00760
00761 for(QMap<IndexedString, QMap<SimpleRange, bool> >::const_iterator it = tempUses.constBegin(); it != tempUses.constEnd(); ++it) {
00762 if(!(*it).isEmpty()) {
00763 QList<SimpleRange>& list(ret[it.key()]);
00764 for(QMap<SimpleRange, bool>::const_iterator it2 = (*it).constBegin(); it2 != (*it).constEnd(); ++it2)
00765 list << it2.key();
00766 }
00767 }
00768 return ret;
00769 }
00770
00771 }
00772
00773
00774
00775