• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDevelop Platform Libraries
  • Sitemap
  • Contact Us
 

language/duchain

ducontext.cpp

00001 /* This  is part of KDevelop
00002     Copyright 2006 Hamish Rodda <rodda@kde.org>
00003     Copyright 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "ducontext.h"
00021 
00022 #include <limits>
00023 
00024 #include <QMutableLinkedListIterator>
00025 #include <QSet>
00026 
00027 #include <ktexteditor/document.h>
00028 #include <ktexteditor/smartinterface.h>
00029 
00030 #include "../editor/editorintegrator.h"
00031 
00032 #include "ducontextdata.h"
00033 #include "declaration.h"
00034 #include "duchain.h"
00035 #include "duchainlock.h"
00036 #include "use.h"
00037 #include "identifier.h"
00038 #include "topducontext.h"
00039 #include "persistentsymboltable.h"
00040 #include "aliasdeclaration.h"
00041 #include "namespacealiasdeclaration.h"
00042 #include "abstractfunctiondeclaration.h"
00043 #include "indexedstring.h"
00044 #include "duchainregister.h"
00045 #include "topducontextdynamicdata.h"
00046 #include "arrayhelpers.h"
00047 #include "importers.h"
00048 
00050 
00051 const uint maxParentDepth = 20;
00052 
00053 using namespace KTextEditor;
00054 
00055 //Stored statically for performance-reasons
00056 
00057 #ifndef NDEBUG
00058 #define ENSURE_CAN_WRITE_(x) {if(x->inDUChain()) { ENSURE_CHAIN_WRITE_LOCKED }}
00059 #define ENSURE_CAN_READ_(x) {if(x->inDUChain()) { ENSURE_CHAIN_READ_LOCKED }}
00060 #else
00061 #define ENSURE_CAN_WRITE_(x)
00062 #define ENSURE_CAN_READ_(x)
00063 #endif
00064 
00065 namespace KDevelop
00066 {
00067 QMutex DUContextDynamicData::m_localDeclarationsMutex(QMutex::Recursive);
00068 
00069 DEFINE_LIST_MEMBER_HASH(DUContextData, m_childContexts, LocalIndexedDUContext)
00070 DEFINE_LIST_MEMBER_HASH(DUContextData, m_importers, IndexedDUContext)
00071 DEFINE_LIST_MEMBER_HASH(DUContextData, m_importedContexts, DUContext::Import)
00072 DEFINE_LIST_MEMBER_HASH(DUContextData, m_localDeclarations, LocalIndexedDeclaration)
00073 DEFINE_LIST_MEMBER_HASH(DUContextData, m_uses, Use)
00074 
00075 REGISTER_DUCHAIN_ITEM(DUContext);
00076 
00077 //This is ugly, but it prevents a possible crash during destruction. We don't need ~Identifier to be called.
00078 const Identifier& globalImportIdentifier(*new Identifier("{...import...}"));
00079 
00080 void DUContext::rebuildDynamicData(DUContext* parent, uint ownIndex) {
00081 
00082   Q_ASSERT(!parent || ownIndex);
00083   m_dynamicData->m_topContext = parent ? parent->topContext() : static_cast<TopDUContext*>(this);
00084   m_dynamicData->m_indexInTopContext = ownIndex;
00085   m_dynamicData->m_parentContext = DUContextPointer(parent);
00086   m_dynamicData->m_context = this;
00087 
00088   DUChainBase::rebuildDynamicData(parent, ownIndex);
00089 }
00090 
00091 DUContextData::DUContextData()
00092   : m_inSymbolTable(false), m_anonymousInParent(false), m_propagateDeclarations(false)
00093 {
00094   initializeAppendedLists();
00095 }
00096 
00097 DUContextData::~DUContextData() {
00098   freeAppendedLists();
00099 }
00100 
00101 DUContextData::DUContextData(const DUContextData& rhs)  : DUChainBaseData(rhs), m_inSymbolTable(rhs.m_inSymbolTable), m_anonymousInParent(rhs.m_anonymousInParent), m_propagateDeclarations(rhs.m_propagateDeclarations) {
00102   initializeAppendedLists();
00103   copyListsFrom(rhs);
00104   m_scopeIdentifier = rhs.m_scopeIdentifier;
00105   m_contextType = rhs.m_contextType;
00106   m_owner = rhs.m_owner;
00107 }
00108 
00109 DUContextDynamicData::DUContextDynamicData(DUContext* d)
00110   : m_topContext(0), m_hasLocalDeclarationsHash(false), m_indexInTopContext(0), m_context(d), m_rangesChanged(true)
00111 {
00112 }
00113 
00114 void DUContextDynamicData::scopeIdentifier(bool includeClasses, QualifiedIdentifier& target) const {
00115   if (m_parentContext)
00116     m_parentContext->m_dynamicData->scopeIdentifier(includeClasses, target);
00117 
00118   if (includeClasses || m_context->d_func()->m_contextType != DUContext::Class)
00119     target += m_context->d_func()->m_scopeIdentifier;
00120 }
00121 
00122 bool DUContextDynamicData::importsSafeButSlow(const DUContext* context, const TopDUContext* source, ImportsHash& checked) const {
00123   if( this == context->m_dynamicData )
00124     return true;
00125 
00126   if(checked.find(this) != checked.end())
00127     return false;
00128   checked.insert(std::make_pair(this, true));
00129 
00130   FOREACH_FUNCTION( const DUContext::Import& ctx, m_context->d_func()->m_importedContexts ) {
00131     DUContext* import = ctx.context(source);
00132     if(import == context || (import && import->m_dynamicData->importsSafeButSlow(context, source, checked)))
00133       return true;
00134   }
00135 
00136   return false;
00137 }
00138 
00139 bool DUContextDynamicData::imports(const DUContext* context, const TopDUContext* source, int maxDepth) const {
00140   if( this == context->m_dynamicData )
00141     return true;
00142 
00143   if(maxDepth == 0) {
00144     ImportsHash checked(500);
00145     checked.set_empty_key(0);
00146     return importsSafeButSlow(context, source, checked);
00147   }
00148 
00149   FOREACH_FUNCTION( const DUContext::Import& ctx, m_context->d_func()->m_importedContexts ) {
00150     DUContext* import = ctx.context(source);
00151     if(import == context || (import && import->m_dynamicData->imports(context, source, maxDepth-1)))
00152       return true;
00153   }
00154 
00155   return false;
00156 }
00157 
00158 IndexedDUContext::IndexedDUContext(uint topContext, uint contextIndex) : m_topContext(topContext), m_contextIndex(contextIndex) {
00159 }
00160 
00161 IndexedDUContext::IndexedDUContext(DUContext* ctx) {
00162   if(ctx) {
00163     m_topContext = ctx->topContext()->ownIndex();
00164     m_contextIndex = ctx->m_dynamicData->m_indexInTopContext;
00165   }else{
00166     m_topContext = 0;
00167     m_contextIndex = 0;
00168   }
00169 }
00170 
00171 IndexedTopDUContext IndexedDUContext::indexedTopContext() const {
00172   if(isDummy())
00173     return IndexedTopDUContext();
00174   return IndexedTopDUContext(m_topContext);
00175 }
00176 
00177 LocalIndexedDUContext::LocalIndexedDUContext(uint contextIndex) : m_contextIndex(contextIndex) {
00178 }
00179 
00180 LocalIndexedDUContext::LocalIndexedDUContext(DUContext* ctx) {
00181   if(ctx) {
00182     m_contextIndex = ctx->m_dynamicData->m_indexInTopContext;
00183   }else{
00184     m_contextIndex = 0;
00185   }
00186 }
00187 
00188 bool LocalIndexedDUContext::isLoaded(TopDUContext* top) const {
00189   if(!m_contextIndex)
00190     return false;
00191   else
00192     return top->m_dynamicData->isContextForIndexLoaded(m_contextIndex);
00193 }
00194 
00195 DUContext* LocalIndexedDUContext::data(TopDUContext* top) const {
00196   if(!m_contextIndex)
00197     return 0;
00198   else
00199     return top->m_dynamicData->getContextForIndex(m_contextIndex);
00200 }
00201 
00202 DUContext* IndexedDUContext::context() const {
00203   if(isDummy())
00204     return 0;
00205 //   ENSURE_CHAIN_READ_LOCKED
00206   if(!m_topContext)
00207     return 0;
00208 
00209   TopDUContext* ctx = DUChain::self()->chainForIndex(m_topContext);
00210   if(!ctx)
00211     return 0;
00212 
00213   if(!m_contextIndex)
00214     return ctx;
00215 
00216   return ctx->m_dynamicData->getContextForIndex(m_contextIndex);
00217 }
00218 
00219 void DUContext::synchronizeUsesFromSmart() const
00220 {
00221   DUCHAIN_D(DUContext);
00222 
00223   if(m_dynamicData->m_rangesForUses.isEmpty() || !m_dynamicData->m_rangesChanged)
00224     return;
00225 
00226   Q_ASSERT(uint(m_dynamicData->m_rangesForUses.count()) == d->m_usesSize());
00227 
00228   for(unsigned int a = 0; a < d->m_usesSize(); a++)
00229     if(m_dynamicData->m_rangesForUses[a]) ///@todo somehow signalize the change
00230       const_cast<Use&>(d->m_uses()[a]).m_range = SimpleRange(*m_dynamicData->m_rangesForUses[a]);
00231 
00232   m_dynamicData->m_rangesChanged = false;
00233 }
00234 
00235 void DUContext::synchronizeUsesToSmart() const
00236 {
00237   DUCHAIN_D(DUContext);
00238   if(m_dynamicData->m_rangesForUses.isEmpty())
00239     return;
00240   Q_ASSERT(uint(m_dynamicData->m_rangesForUses.count()) == d->m_usesSize());
00241 
00242   // TODO: file close race? from here
00243   KTextEditor::SmartInterface *iface = qobject_cast<KTextEditor::SmartInterface*>( smartRange()->document() );
00244   Q_ASSERT(iface);
00245 
00246   // TODO: file close race to here
00247   QMutexLocker l(iface->smartMutex());
00248 
00249   for(unsigned int a = 0; a < d->m_usesSize(); a++) {
00250     if(a % 10 == 0) { //Unlock the smart-lock time by time, to increase responsiveness
00251       l.unlock();
00252       l.relock();
00253     }
00254     if(m_dynamicData->m_rangesForUses[a]) {
00255       m_dynamicData->m_rangesForUses[a]->start() = d->m_uses()[a].m_range.start.textCursor();
00256       m_dynamicData->m_rangesForUses[a]->end() = d->m_uses()[a].m_range.end.textCursor();
00257     }else{
00258       kDebug() << "bad smart-range";
00259     }
00260   }
00261 }
00262 
00263 void DUContext::rangePositionChanged(KTextEditor::SmartRange* range)
00264 {
00265   if(range != smartRange())
00266     m_dynamicData->m_rangesChanged = true;
00267 }
00268 
00269 void DUContext::rangeDeleted(KTextEditor::SmartRange* range)
00270 {
00271   if(range == smartRange()) {
00272     DocumentRangeObject::rangeDeleted(range);
00273   } else {
00274     range->removeWatcher(this);
00275     int index = m_dynamicData->m_rangesForUses.indexOf(range);
00276     if(index != -1) {
00277       d_func_dynamic()->m_usesList()[index].m_range = SimpleRange(*range);
00278       m_dynamicData->m_rangesForUses[index] = 0;
00279     }
00280 
00281     if(m_dynamicData->m_rangesForUses.count(0) == m_dynamicData->m_rangesForUses.size())
00282       m_dynamicData->m_rangesForUses.clear();
00283   }
00284 }
00285 
00286 void DUContextDynamicData::enableLocalDeclarationsHash(DUContext* ctx, const Identifier& currentIdentifier, Declaration* currentDecl)
00287 {
00288   m_hasLocalDeclarationsHash = true;
00289 
00290   FOREACH_FUNCTION(LocalIndexedDeclaration indexedDecl, ctx->d_func()->m_localDeclarations) {
00291     Declaration* decl = indexedDecl.data(m_topContext);
00292     Q_ASSERT(decl);
00293     if(currentDecl != decl)
00294       m_localDeclarationsHash.insert( decl->identifier(), DeclarationPointer(decl) );
00295     else
00296       m_localDeclarationsHash.insert( currentIdentifier, DeclarationPointer(decl) );
00297   }
00298 
00299   FOREACH_FUNCTION(LocalIndexedDUContext child, ctx->d_func()->m_childContexts) {
00300     DUContext* childCtx = child.data(m_topContext);
00301     Q_ASSERT(childCtx);
00302     if(childCtx->d_func()->m_propagateDeclarations)
00303       enableLocalDeclarationsHash(childCtx, currentIdentifier, currentDecl);
00304   }
00305 }
00306 
00307 void DUContextDynamicData::disableLocalDeclarationsHash()
00308 {
00309   m_hasLocalDeclarationsHash = false;
00310   m_localDeclarationsHash.clear();
00311 }
00312 
00313 bool DUContextDynamicData::needsLocalDeclarationsHash()
00314 {
00316   //For now disable the hash, until we make sure that all declarations needed for the hash are loaded first
00317   //including those in propagating sub-contexts.
00318   //Then, also make sure that we create the declaration hash after loading if needed
00319   return false;
00320 
00321   if(m_context->d_func()->m_localDeclarationsSize() > 15)
00322     return true;
00323 
00324   uint propagatingChildContexts = 0;
00325 
00326   FOREACH_FUNCTION(LocalIndexedDUContext child, m_context->d_func()->m_childContexts) {
00327     DUContext* childCtx = child.data(m_topContext);
00328     Q_ASSERT(childCtx);
00329     if(childCtx->d_func()->m_propagateDeclarations)
00330       ++propagatingChildContexts;
00331   }
00332 
00333   return propagatingChildContexts > 4;
00334 }
00335 
00336 void DUContextDynamicData::addDeclarationToHash(const Identifier& identifier, Declaration* declaration)
00337 {
00338   if(m_hasLocalDeclarationsHash)
00339     m_localDeclarationsHash.insert( identifier, DeclarationPointer(declaration) );
00340 
00341   if( m_context->d_func()->m_propagateDeclarations && m_parentContext )
00342     m_parentContext->m_dynamicData->addDeclarationToHash(identifier, declaration);
00343 
00344   if(!m_hasLocalDeclarationsHash && needsLocalDeclarationsHash())
00345     enableLocalDeclarationsHash(m_context, identifier, declaration);
00346 }
00347 
00348 void DUContextDynamicData::removeDeclarationFromHash(const Identifier& identifier, Declaration* declaration)
00349 {
00350   if(m_hasLocalDeclarationsHash)
00351     m_localDeclarationsHash.remove( identifier, DeclarationPointer(declaration) );
00352 
00353   if( m_context->d_func()->m_propagateDeclarations && m_parentContext )
00354     m_parentContext->m_dynamicData->removeDeclarationFromHash(identifier,  declaration);
00355 
00356   if(m_hasLocalDeclarationsHash && !needsLocalDeclarationsHash())
00357       disableLocalDeclarationsHash();
00358 }
00359 
00360 void DUContextDynamicData::addDeclaration( Declaration * newDeclaration )
00361 {
00362   // The definition may not have its identifier set when it's assigned... allow dupes here, TODO catch the error elsewhere
00363   {
00364     QMutexLocker lock(&m_localDeclarationsMutex);
00365 
00366 //     m_localDeclarations.append(newDeclaration);
00367 
00368   if(m_indexInTopContext < (0xffffffff/2)) {
00369     //If this context is not temporary, added declarations shouldn't be either
00370     Q_ASSERT(newDeclaration->ownIndex() < (0xffffffff/2));
00371   }
00372   if(m_indexInTopContext > (0xffffffff/2)) {
00373     //If this context is temporary, added declarations should be as well
00374     Q_ASSERT(newDeclaration->ownIndex() > (0xffffffff/2));
00375   }
00376 
00377   SimpleCursor start = newDeclaration->range().start;
00379   bool inserted = false;
00380   for (int i = m_context->d_func_dynamic()->m_localDeclarationsSize()-1; i >= 0; --i) {
00381     Declaration* child = m_context->d_func_dynamic()->m_localDeclarations()[i].data(m_topContext);
00382     if(!child) {
00383       kWarning() << "child declaration number" << i << "of" << m_context->d_func_dynamic()->m_localDeclarationsSize() << "is invalid";
00384       continue;
00385     }
00386     if(child == newDeclaration)
00387       return;
00388     if (start > child->range().start) {
00389       insertToArray(m_context->d_func_dynamic()->m_localDeclarationsList(), newDeclaration, i+1);
00390       if(!m_context->d_func()->m_localDeclarations()[i+1].data(m_topContext))
00391         kFatal() << "Inserted a not addressable declaration";
00392 
00393       inserted = true;
00394       break;
00395     }
00396   }
00397   if( !inserted ) //We haven't found any child that is before this one, so prepend it
00398     insertToArray(m_context->d_func_dynamic()->m_localDeclarationsList(), newDeclaration, 0);
00399 
00400     addDeclarationToHash(newDeclaration->identifier(), newDeclaration);
00401   }
00402 
00403   //DUChain::contextChanged(m_context, DUChainObserver::Addition, DUChainObserver::LocalDeclarations, newDeclaration);
00404 }
00405 
00406 bool DUContextDynamicData::removeDeclaration(Declaration* declaration)
00407 {
00408   QMutexLocker lock(&m_localDeclarationsMutex);
00409 
00410   if(!m_topContext->deleting()) //We can save a lot of time by just not caring about the hash while deleting
00411     removeDeclarationFromHash(declaration->identifier(), declaration);
00412 
00413   if( removeOne(m_context->d_func_dynamic()->m_localDeclarationsList(), LocalIndexedDeclaration(declaration)) ) {
00414     //DUChain::contextChanged(m_context, DUChainObserver::Removal, DUChainObserver::LocalDeclarations, declaration);
00415     return true;
00416   }else {
00417     return false;
00418   }
00419 }
00420 
00421 void DUContext::changingIdentifier( Declaration* decl, const Identifier& from, const Identifier& to ) {
00422   QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
00423   m_dynamicData->removeDeclarationFromHash(from, decl);
00424   m_dynamicData->addDeclarationToHash(to, decl);
00425 }
00426 
00427 void DUContextDynamicData::addChildContext( DUContext * context )
00428 {
00429   // Internal, don't need to assert a lock
00430   Q_ASSERT(!context->m_dynamicData->m_parentContext || context->m_dynamicData->m_parentContext.data()->m_dynamicData == this );
00431 
00432   LocalIndexedDUContext indexed(context->m_dynamicData->m_indexInTopContext);
00433 
00434   if(m_indexInTopContext < (0xffffffff/2)) {
00435     //If this context is not temporary, added declarations shouldn't be either
00436     Q_ASSERT(indexed.localIndex() < (0xffffffff/2));
00437   }
00438   if(m_indexInTopContext > (0xffffffff/2)) {
00439     //If this context is temporary, added declarations should be as well
00440     Q_ASSERT(indexed.localIndex() > (0xffffffff/2));
00441   }
00442 
00443   bool inserted = false;
00444 
00445   int childCount = m_context->d_func()->m_childContextsSize();
00446 
00447   for (int i = childCount-1; i >= 0; --i) {///@todo Do binary search to find the position
00448     DUContext* child = m_context->d_func()->m_childContexts()[i].data(m_topContext);
00449     if (context == child)
00450       return;
00451     if (context->range().start >= child->range().start) {
00452       insertToArray(m_context->d_func_dynamic()->m_childContextsList(), indexed, i+1);
00453       context->m_dynamicData->m_parentContext = m_context;
00454       inserted = true;
00455       break;
00456     }
00457   }
00458 
00459   if( !inserted ) {
00460     m_context->d_func_dynamic()->m_childContextsList().insert(indexed, 0);
00461     context->m_dynamicData->m_parentContext = m_context;
00462   }
00463 
00464   if(context->d_func()->m_propagateDeclarations) {
00465     QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
00466     disableLocalDeclarationsHash();
00467     if(needsLocalDeclarationsHash())
00468       enableLocalDeclarationsHash(m_context);
00469   }
00470 
00471   //DUChain::contextChanged(m_context, DUChainObserver::Addition, DUChainObserver::ChildContexts, context);
00472 }
00473 
00474 bool DUContextDynamicData::removeChildContext( DUContext* context ) {
00475 //   ENSURE_CAN_WRITE
00476 
00477   if( removeOne(m_context->d_func_dynamic()->m_childContextsList(), LocalIndexedDUContext(context)) )
00478     return true;
00479   else
00480     return false;
00481 }
00482 
00483 void DUContextDynamicData::addImportedChildContext( DUContext * context )
00484 {
00485 //   ENSURE_CAN_WRITE
00486   DUContext::Import import(m_context, context);
00487   
00488   if(import.isDirect()) {
00489     //Direct importers are registered directly within the data
00490     if(arrayContains(m_context->d_func_dynamic()->m_importersList(), IndexedDUContext(context))) {
00491       kDebug(9505) << m_context->scopeIdentifier(true).toString() << "importer added multiple times:" << context->scopeIdentifier(true).toString();
00492       return;
00493     }
00494 
00495     m_context->d_func_dynamic()->m_importersList().append(context);
00496   }else{
00497     //Indirect importers are registered separately
00498     Importers::self().addImporter(import.indirectDeclarationId(), IndexedDUContext(context));
00499   }
00500 
00501   //DUChain::contextChanged(m_context, DUChainObserver::Addition, DUChainObserver::ImportedChildContexts, context);
00502 }
00503 
00504 //Can also be called with a context that is not in the list
00505 void DUContextDynamicData::removeImportedChildContext( DUContext * context )
00506 {
00507 //   ENSURE_CAN_WRITE
00508   DUContext::Import import(m_context, context);
00509   
00510   if(import.isDirect()) {
00511     removeOne(m_context->d_func_dynamic()->m_importersList(), IndexedDUContext(context));
00512   }else{
00513     //Indirect importers are registered separately
00514     Importers::self().removeImporter(import.indirectDeclarationId(), IndexedDUContext(context));
00515   }
00516 }
00517 
00518 int DUContext::depth() const
00519 {
00520   { if (!parentContext()) return 0; return parentContext()->depth() + 1; }
00521 }
00522 
00523 DUContext::DUContext(DUContextData& data) : DUChainBase(data), m_dynamicData(new DUContextDynamicData(this)) {
00524 }
00525 
00526 
00527 DUContext::DUContext(const SimpleRange& range, DUContext* parent, bool anonymous)
00528   : DUChainBase(*new DUContextData(), range), m_dynamicData(new DUContextDynamicData(this))
00529 {
00530   d_func_dynamic()->setClassId(this);
00531   if(parent)
00532     m_dynamicData->m_topContext = parent->topContext();
00533   else
00534     m_dynamicData->m_topContext = static_cast<TopDUContext*>(this);
00535 
00536   d_func_dynamic()->setClassId(this);
00537   DUCHAIN_D_DYNAMIC(DUContext);
00538   d->m_contextType = Other;
00539   m_dynamicData->m_parentContext = 0;
00540 
00541   d->m_anonymousInParent = anonymous;
00542   d->m_inSymbolTable = false;
00543 
00544   if (parent) {
00545     m_dynamicData->m_indexInTopContext = parent->topContext()->m_dynamicData->allocateContextIndex(this, parent->isAnonymous() || anonymous);
00546     Q_ASSERT(m_dynamicData->m_indexInTopContext);
00547 
00548     if( !anonymous )
00549       parent->m_dynamicData->addChildContext(this);
00550     else
00551       m_dynamicData->m_parentContext = parent;
00552   }
00553 
00554   if(parent && !anonymous && parent->inSymbolTable())
00555     setInSymbolTable(true);
00556 }
00557 
00558 bool DUContext::isAnonymous() const {
00559   return d_func()->m_anonymousInParent || (m_dynamicData->m_parentContext && m_dynamicData->m_parentContext->isAnonymous());
00560 }
00561 
00562 DUContext::DUContext( DUContextData& dd, const SimpleRange& range, DUContext * parent, bool anonymous )
00563   : DUChainBase(dd, range), m_dynamicData(new DUContextDynamicData(this))
00564 {
00565   if(parent)
00566     m_dynamicData->m_topContext = parent->topContext();
00567   else
00568     m_dynamicData->m_topContext = static_cast<TopDUContext*>(this);
00569 
00570   DUCHAIN_D_DYNAMIC(DUContext);
00571   d->m_contextType = Other;
00572   m_dynamicData->m_parentContext = 0;
00573   d->m_inSymbolTable = false;
00574   d->m_anonymousInParent = anonymous;
00575   if (parent) {
00576     m_dynamicData->m_indexInTopContext = parent->topContext()->m_dynamicData->allocateContextIndex(this, parent->isAnonymous() || anonymous);
00577 
00578     if( !anonymous )
00579       parent->m_dynamicData->addChildContext(this);
00580     else
00581       m_dynamicData->m_parentContext = parent;
00582   }
00583 }
00584 
00585 DUContext::DUContext(DUContext& useDataFrom)
00586   : DUChainBase(useDataFrom), m_dynamicData(useDataFrom.m_dynamicData)
00587 {
00588 }
00589 
00590 DUContext::~DUContext( )
00591 {
00592   TopDUContext* top = topContext();
00593 
00594   if(!top->deleting() || !top->isOnDisk()) {
00595     DUCHAIN_D_DYNAMIC(DUContext);
00596     QualifiedIdentifier id(scopeIdentifier(true));
00597     if(d->m_inSymbolTable && parentContext()) {
00598       PersistentSymbolTable::self().removeContext(id, this);
00599     }
00600 
00601     if(d->m_owner.declaration())
00602       d->m_owner.declaration()->setInternalContext(0);
00603 
00604     while( d->m_importersSize() != 0 ) {
00605       if(d->m_importers()[0].data())
00606         d->m_importers()[0].data()->removeImportedParentContext(this);
00607       else {
00608         kDebug() << "importer disappeared";
00609         d->m_importersList().removeOne(d->m_importers()[0]);
00610       }
00611     }
00612 
00613     clearImportedParentContexts();
00614   }
00615 
00616   deleteChildContextsRecursively();
00617 
00618   if(!topContext()->deleting() || !topContext()->isOnDisk())
00619     deleteUses();
00620   else
00621     clearUseSmartRanges();
00622 
00623   deleteLocalDeclarations();
00624 
00625   //If the top-context is being delete, we don't need to spend time rebuilding the inner structure.
00626   //That's expensive, especially when the data is not dynamic.
00627   if(!top->deleting() || !top->isOnDisk()) {
00628     if (m_dynamicData->m_parentContext)
00629       m_dynamicData->m_parentContext->m_dynamicData->removeChildContext(this);
00630     //DUChain::contextChanged(this, DUChainObserver::Deletion, DUChainObserver::NotApplicable);
00631   }
00632 
00633   top->m_dynamicData->clearContextIndex(this);
00634 
00635   Q_ASSERT(d_func()->isDynamic() == (!top->deleting() || !top->isOnDisk() || top->m_dynamicData->isTemporaryContextIndex(m_dynamicData->m_indexInTopContext)));
00636   delete m_dynamicData;
00637 }
00638 
00639 QVector< DUContext * > DUContext::childContexts( ) const
00640 {
00641   ENSURE_CAN_READ
00642 
00643   QVector< DUContext * > ret;
00644   FOREACH_FUNCTION(LocalIndexedDUContext ctx, d_func()->m_childContexts)
00645     ret << ctx.data(topContext());
00646   return ret;
00647 }
00648 
00649 Declaration* DUContext::owner() const {
00650   ENSURE_CAN_READ
00651   return d_func()->m_owner.declaration();
00652 }
00653 
00654 void DUContext::setOwner(Declaration* owner) {
00655   ENSURE_CAN_WRITE
00656   DUCHAIN_D_DYNAMIC(DUContext);
00657   if( owner == d->m_owner.declaration() )
00658     return;
00659 
00660   Declaration* oldOwner = d->m_owner.declaration();
00661 
00662   d->m_owner = owner;
00663 
00664   //Q_ASSERT(!oldOwner || oldOwner->internalContext() == this);
00665   if( oldOwner && oldOwner->internalContext() == this )
00666     oldOwner->setInternalContext(0);
00667 
00668 
00669   //The context set as internal context should always be the last opened context
00670   if( owner )
00671     owner->setInternalContext(this);
00672 }
00673 
00674 DUContext* DUContext::parentContext( ) const
00675 {
00676   //ENSURE_CAN_READ Commented out for performance reasons
00677 
00678   return m_dynamicData->m_parentContext.data();
00679 }
00680 
00681 void DUContext::setPropagateDeclarations(bool propagate)
00682 {
00683   ENSURE_CAN_WRITE
00684   DUCHAIN_D_DYNAMIC(DUContext);
00685   
00686   QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
00687   
00688   if(propagate == d->m_propagateDeclarations)
00689     return;
00690 
00691   m_dynamicData->m_parentContext->m_dynamicData->disableLocalDeclarationsHash();
00692 
00693   d->m_propagateDeclarations = propagate;
00694 
00695   if(m_dynamicData->m_parentContext->m_dynamicData->needsLocalDeclarationsHash())
00696     m_dynamicData->m_parentContext->m_dynamicData->enableLocalDeclarationsHash(m_dynamicData->m_parentContext.data());
00697 }
00698 
00699 bool DUContext::isPropagateDeclarations() const
00700 {
00701   return d_func()->m_propagateDeclarations;
00702 }
00703 
00704 QList<Declaration*> DUContext::findLocalDeclarations( const Identifier& identifier, const SimpleCursor & position, const TopDUContext* topContext, const AbstractType::Ptr& dataType, SearchFlags flags ) const
00705 {
00706   ENSURE_CAN_READ
00707 
00708   DeclarationList ret;
00709   findLocalDeclarationsInternal(identifier, position.isValid() ? position : range().end, dataType, ret, topContext ? topContext : this->topContext(), flags);
00710   return arrayToList(ret);
00711 }
00712 
00713 bool contextIsChildOrEqual(const DUContext* childContext, const DUContext* context) {
00714   if(childContext == context)
00715     return true;
00716 
00717   if(childContext->parentContext())
00718     return contextIsChildOrEqual(childContext->parentContext(), context);
00719   else
00720     return false;
00721 }
00722 
00723 void DUContext::findLocalDeclarationsInternal( const Identifier& identifier, const SimpleCursor & position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* /*source*/, SearchFlags flags ) const
00724 {
00725   IndexedIdentifier indexedIdentifier(identifier);
00726   {
00727      QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
00728 
00729      struct Checker {
00730        Checker(SearchFlags flags, const AbstractType::Ptr& dataType, const SimpleCursor & position, DUContext::ContextType ownType) : m_flags(flags), m_dataType(dataType), m_position(position), m_ownType(ownType) {
00731        }
00732 
00733        Declaration* check(Declaration* declaration) {
00734           if( declaration->kind() == Declaration::Alias ) {
00735             //Apply alias declarations
00736             AliasDeclaration* alias = static_cast<AliasDeclaration*>(declaration);
00737             if(alias->aliasedDeclaration().isValid()) {
00738               declaration = alias->aliasedDeclaration().declaration();
00739             } else {
00740 #ifndef Q_CC_MSVC
00741               kDebug() << "lost aliased declaration";
00742 #endif
00743             }
00744           }
00745 
00746           if( declaration->kind() == Declaration::NamespaceAlias && !(m_flags & NoFiltering) )
00747             return 0;
00748 
00749           if((m_flags & OnlyFunctions) && !declaration->isFunctionDeclaration())
00750             return 0;
00751 
00752           if (!m_dataType || m_dataType->indexed() == declaration->abstractType()->indexed())
00753             if (m_ownType == Class || m_ownType == Template || m_position > declaration->range().start || !m_position.isValid()) ///@todo This is C++-specific
00754               return declaration;
00755           return 0;
00756        }
00757 
00758        SearchFlags m_flags;
00759        const AbstractType::Ptr& m_dataType;
00760        const SimpleCursor& m_position;
00761        DUContext::ContextType m_ownType;
00762      };
00763 
00764      Checker checker(flags, dataType, position, type());
00765 
00766      if(m_dynamicData->m_hasLocalDeclarationsHash) {
00767        //Use a special hash that contains all declarations visible in this context
00768       QHash<Identifier, DeclarationPointer>::const_iterator it = m_dynamicData->m_localDeclarationsHash.constFind(identifier);
00769       QHash<Identifier, DeclarationPointer>::const_iterator end = m_dynamicData->m_localDeclarationsHash.constEnd();
00770 
00771       for( ; it != end && it.key() == identifier; ++it ) {
00772         Declaration* declaration = (*it).data();
00773 
00774         if( !declaration ) {
00775           //This should never happen, but let's see
00776           kDebug(9505) << "DUContext::findLocalDeclarationsInternal: Invalid declaration in local-declaration-hash";
00777           continue;
00778         }
00779 
00780         Declaration* checked = checker.check(declaration);
00781         if(checked)
00782             ret.append(checked);
00783       }
00784     }else if(d_func()->m_inSymbolTable && !this->localScopeIdentifier().isEmpty() && !identifier.isEmpty()) {
00785        //This context is in the symbol table, use the symbol-table to speed up the search
00786        QualifiedIdentifier id(scopeIdentifier(true) + identifier);
00787 
00788        TopDUContext* top = topContext();
00789 
00790        uint count;
00791        const IndexedDeclaration* declarations;
00792        PersistentSymbolTable::self().declarations(id, count, declarations);
00793        for(uint a = 0; a < count; ++a) {
00795          if(declarations[a].topContextIndex() == top->ownIndex()) {
00796            Declaration* decl = LocalIndexedDeclaration(declarations[a].localIndex()).data(top);
00797            if(decl && contextIsChildOrEqual(decl->context(), this)) {
00798              Declaration* checked = checker.check(decl);
00799              if(checked)
00800                ret.append(checked);
00801            }
00802          }
00803        }
00804      }else {
00805        //Iterate through all declarations
00806       DUContextDynamicData::VisibleDeclarationIterator it(m_dynamicData);
00807       while(it) {
00808         Declaration* declaration = *it;
00809         if(declaration->indexedIdentifier() == indexedIdentifier) {
00810           Declaration* checked = checker.check(declaration);
00811           if(checked)
00812               ret.append(checked);
00813         }
00814         ++it;
00815       }
00816      }
00817   }
00818 }
00819 
00820 bool DUContext::foundEnough( const DeclarationList& ret, SearchFlags flags ) const {
00821   if( !ret.isEmpty() && !(flags & DUContext::NoFiltering))
00822     return true;
00823   else
00824     return false;
00825 }
00826 
00827 bool DUContext::findDeclarationsInternal( const SearchItem::PtrList & baseIdentifiers, const SimpleCursor & position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* source, SearchFlags flags, uint depth ) const
00828 {
00829   if(depth > maxParentDepth) {
00830     kDebug() << "maximum depth reached in" << scopeIdentifier(true);
00831     return false;
00832   }
00833   
00834   DUCHAIN_D(DUContext);
00835   if( d_func()->m_contextType != Namespace ) { //If we're in a namespace, delay all the searching into the top-context, because only that has the overview to pick the correct declarations.
00836     for(int a = 0; a < baseIdentifiers.size(); ++a)
00837       if(!baseIdentifiers[a]->isExplicitlyGlobal && baseIdentifiers[a]->next.isEmpty()) //It makes no sense searching locally for qualified identifiers
00838         findLocalDeclarationsInternal(baseIdentifiers[a]->identifier, position, dataType, ret, source, flags);
00839 
00840     if( foundEnough(ret, flags) )
00841       return true;
00842   }
00843 
00845   SearchItem::PtrList aliasedIdentifiers;
00846   //Because of namespace-imports and aliases, this identifier may need to be searched under multiple names
00847   applyAliases(baseIdentifiers, aliasedIdentifiers, position, false,  type() != DUContext::Namespace && type() != DUContext::Global);
00848 
00849 
00850   if( d->m_importedContextsSize() != 0 ) {
00852     SearchItem::PtrList nonGlobalIdentifiers;
00853     FOREACH_ARRAY( const SearchItem::Ptr& identifier, aliasedIdentifiers )
00854       if( !identifier->isExplicitlyGlobal )
00855         nonGlobalIdentifiers << identifier;
00856 
00857     if( !nonGlobalIdentifiers.isEmpty() ) {
00858       for(int import = d->m_importedContextsSize()-1; import >= 0; --import ) {
00859         DUContext* context = d->m_importedContexts()[import].context(source);
00860 
00861         while( !context && import > 0 ) {
00862           --import;
00863           context = d->m_importedContexts()[import].context(source);
00864         }
00865 
00866         if(context == this) {
00867           kDebug() << "resolved self as import:" << scopeIdentifier(true);
00868           continue;
00869         }
00870 
00871         if( !context )
00872           break;
00873 
00874         if( position.isValid() && d->m_importedContexts()[import].position.isValid() && position < d->m_importedContexts()[import].position )
00875           continue;
00876 
00877         if( !context->findDeclarationsInternal(nonGlobalIdentifiers,  url() == context->url() ? position : context->range().end, dataType, ret, source, flags | InImportedParentContext, depth+1) )
00878           return false;
00879       }
00880     }
00881   }
00882 
00883   if( foundEnough(ret, flags) )
00884     return true;
00885 
00887   if (!(flags & DontSearchInParent) && shouldSearchInParent(flags) && m_dynamicData->m_parentContext) {
00888     applyUpwardsAliases(aliasedIdentifiers, source);
00889     return m_dynamicData->m_parentContext->findDeclarationsInternal(aliasedIdentifiers, url() == m_dynamicData->m_parentContext->url() ? position : m_dynamicData->m_parentContext->range().end, dataType, ret, source, flags, depth);
00890   }
00891   return true;
00892 }
00893 
00894 QList< QualifiedIdentifier > DUContext::fullyApplyAliases(KDevelop::QualifiedIdentifier id, const KDevelop::TopDUContext* source) const
00895 {
00896   ENSURE_CAN_READ
00897   
00898   if(!source)
00899     source = topContext();
00900 
00901   SearchItem::PtrList identifiers;
00902   identifiers << SearchItem::Ptr(new SearchItem(id));
00903 
00904   const DUContext* current = this;
00905   while(current) {
00906     SearchItem::PtrList aliasedIdentifiers;
00907     current->applyAliases(identifiers, aliasedIdentifiers, SimpleCursor::invalid(), true, false);
00908     current->applyUpwardsAliases(identifiers, source);
00909     
00910     current = current->parentContext();
00911   }
00912   
00913   QList<QualifiedIdentifier> ret;
00914   FOREACH_ARRAY(SearchItem::Ptr item, identifiers)
00915     ret += item->toList();
00916   
00917   return ret;
00918 }
00919 
00920 QList<Declaration*> DUContext::findDeclarations( const QualifiedIdentifier & identifier, const SimpleCursor & position, const AbstractType::Ptr& dataType, const TopDUContext* topContext, SearchFlags flags) const
00921 {
00922   ENSURE_CAN_READ
00923 
00924   DeclarationList ret;
00925   SearchItem::PtrList identifiers;
00926   identifiers << SearchItem::Ptr(new SearchItem(identifier));
00927 
00928   findDeclarationsInternal(identifiers, position.isValid() ? position : range().end, dataType, ret, topContext ? topContext : this->topContext(), flags, 0);
00929 
00930   return arrayToList(ret);
00931 }
00932 
00933 bool DUContext::imports(const DUContext* origin, const SimpleCursor& /*position*/ ) const
00934 {
00935   ENSURE_CAN_READ
00936 
00937   return m_dynamicData->imports(origin, topContext(), 4);
00938 }
00939 
00940 bool DUContext::addIndirectImport(const DUContext::Import& import) {
00941   ENSURE_CAN_WRITE
00942   DUCHAIN_D_DYNAMIC(DUContext);
00943 
00944   for(unsigned int a = 0; a < d->m_importedContextsSize(); ++a) {
00945     if(d->m_importedContexts()[a] == import) {
00946       d->m_importedContextsList()[a].position = import.position;
00947       return true;
00948     }
00949   }
00950 
00953 
00954   d->m_importedContextsList().append(import);
00955   return false;
00956 }
00957 
00958 void DUContext::addImportedParentContext( DUContext * context, const SimpleCursor& position, bool anonymous, bool /*temporary*/ )
00959 {
00960   ENSURE_CAN_WRITE
00961 
00962   if(context == this) {
00963     kDebug() << "Tried to import self";
00964     return;
00965   }
00966 
00967   Import import(context, this, position);
00968   if(addIndirectImport(import))
00969     return;
00970 
00971   if( !anonymous ) {
00972     ENSURE_CAN_WRITE_(context)
00973     context->m_dynamicData->addImportedChildContext(this);
00974   }
00975   //DUChain::contextChanged(this, DUChainObserver::Addition, DUChainObserver::ImportedParentContexts, context);
00976 }
00977 
00978 void DUContext::removeImportedParentContext( DUContext * context )
00979 {
00980   ENSURE_CAN_WRITE
00981   DUCHAIN_D_DYNAMIC(DUContext);
00982 
00983   Import import(context, this, SimpleCursor::invalid());
00984 
00985   for(unsigned int a = 0; a < d->m_importedContextsSize(); ++a) {
00986     if(d->m_importedContexts()[a] == import) {
00987       removeFromArray(d->m_importedContextsList(), a);
00988       break;
00989     }
00990   }
00991 
00992   if( !context )
00993     return;
00994 
00995   context->m_dynamicData->removeImportedChildContext(this);
00996 
00997   //DUChain::contextChanged(this, DUChainObserver::Removal, DUChainObserver::ImportedParentContexts, context);
00998 }
00999 
01000 KDevVarLengthArray<IndexedDUContext> DUContext::indexedImporters() const
01001 {
01002   KDevVarLengthArray<IndexedDUContext> ret;
01003   if(owner())
01004     ret = Importers::self().importers(owner()->id()); //Add indirect importers to the list
01005   
01006   FOREACH_FUNCTION(IndexedDUContext ctx, d_func()->m_importers)
01007     ret.append(ctx);
01008    
01009   return ret;
01010 }
01011 
01012 QVector<DUContext*> DUContext::importers() const
01013 {
01014   ENSURE_CAN_READ
01015 
01016   QVector<DUContext*> ret;
01017   FOREACH_FUNCTION(IndexedDUContext ctx, d_func()->m_importers)
01018     ret << ctx.context();
01019   
01020   if(owner()) {
01021     //Add indirect importers to the list
01022     KDevVarLengthArray<IndexedDUContext> indirect = Importers::self().importers(owner()->id());
01023     FOREACH_ARRAY(IndexedDUContext ctx, indirect) {
01024       ret << ctx.context();
01025     }
01026   }
01027 
01028   return ret;
01029 }
01030 
01031 DUContext * DUContext::findContext( const SimpleCursor& position, DUContext* parent) const
01032 {
01033   ENSURE_CAN_READ
01034 
01035   if (!parent)
01036     parent = const_cast<DUContext*>(this);
01037 
01038   FOREACH_FUNCTION(LocalIndexedDUContext context, parent->d_func()->m_childContexts)
01039     if (context.data(topContext())->range().contains(position)) {
01040       DUContext* ret = findContext(position, context.data(topContext()));
01041       if (!ret)
01042         ret = context.data(topContext());
01043 
01044       return ret;
01045     }
01046 
01047   return 0;
01048 }
01049 
01050 bool DUContext::parentContextOf(DUContext* context) const
01051 {
01052   if (this == context)
01053     return true;
01054 
01055   FOREACH_FUNCTION(LocalIndexedDUContext child, d_func()->m_childContexts) {
01056     if (child.data(topContext())->parentContextOf(context))
01057       return true;
01058   }
01059 
01060   return false;
01061 }
01062 
01063 QList<Declaration*> DUContext::allLocalDeclarations(const Identifier& identifier) const
01064 {
01065   IndexedIdentifier indexedIdentifier(identifier);
01066 
01067   ENSURE_CAN_READ
01068   QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
01069 
01070   QList<Declaration*> ret;
01071 
01072   if(m_dynamicData->m_hasLocalDeclarationsHash) {
01073     QHash<Identifier, DeclarationPointer>::const_iterator it = m_dynamicData->m_localDeclarationsHash.constFind(identifier);
01074     QHash<Identifier, DeclarationPointer>::const_iterator end = m_dynamicData->m_localDeclarationsHash.constEnd();
01075 
01076     for( ; it != end && it.key() == identifier; ++it )
01077       ret << (*it).data();
01078   }else{
01079     DUContextDynamicData::VisibleDeclarationIterator it(m_dynamicData);
01080     while(it) {
01081       Declaration* decl = *it;
01082       if(decl->indexedIdentifier() == indexedIdentifier)
01083         ret << decl;
01084       ++it;
01085     }
01086   }
01087   return ret;
01088 }
01089 
01090 QList< QPair<Declaration*, int> > DUContext::allDeclarations(const SimpleCursor& position, const TopDUContext* topContext, bool searchInParents) const
01091 {
01092   ENSURE_CAN_READ
01093 
01094   QList< QPair<Declaration*, int> > ret;
01095 
01096   QHash<const DUContext*, bool> hadContexts;
01097   // Iterate back up the chain
01098   mergeDeclarationsInternal(ret, position, hadContexts, topContext ? topContext : this->topContext(), searchInParents);
01099 
01100   return ret;
01101 }
01102 
01103 QVector<Declaration*> DUContext::localDeclarations(const TopDUContext* source) const
01104 {
01105   Q_UNUSED(source);
01106   ENSURE_CAN_READ
01107 
01108   QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
01109   QVector<Declaration*> ret;
01110   FOREACH_FUNCTION(LocalIndexedDeclaration decl, d_func()->m_localDeclarations) {
01111     ret << decl.data(topContext());
01112     Q_ASSERT(ret.back()->context() == this);
01113     ret.back()->identifier().isEmpty();
01114   }
01115 
01116   return ret;
01117 }
01118 
01119 void DUContext::mergeDeclarationsInternal(QList< QPair<Declaration*, int> >& definitions, const SimpleCursor& position, QHash<const DUContext*, bool>& hadContexts, const TopDUContext* source, bool searchInParents, int currentDepth) const
01120 {
01121   if((currentDepth > 300 && currentDepth < 1000) || currentDepth > 1300) {
01122     kDebug() << "too much depth";
01123     return;
01124   }
01125   DUCHAIN_D(DUContext);
01126   
01127     if(hadContexts.contains(this) && !searchInParents)
01128       return;
01129   
01130     if(!hadContexts.contains(this)) {
01131       hadContexts[this] = true;
01132 
01133       if( (type() == DUContext::Namespace || type() == DUContext::Global) && currentDepth < 1000 )
01134         currentDepth += 1000;
01135 
01136       {
01137         QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
01138         DUContextDynamicData::VisibleDeclarationIterator it(m_dynamicData);
01139         while(it) {
01140           Declaration* decl = *it;
01141 
01142           if ( decl && (!position.isValid() || decl->range().start <= position) )
01143             definitions << qMakePair(decl, currentDepth);
01144           ++it;
01145         }
01146       }
01147 
01148       for(int a = d->m_importedContextsSize()-1; a >= 0; --a) {
01149         const Import* import(&d->m_importedContexts()[a]);
01150         DUContext* context = import->context(source);
01151         while( !context && a > 0 ) {
01152           --a;
01153           import = &d->m_importedContexts()[a];
01154           context = import->context(source);
01155         }
01156         if( !context )
01157           break;
01158 
01159         if(context == this) {
01160           kDebug() << "resolved self as import:" << scopeIdentifier(true);
01161           continue;
01162         }
01163 
01164 
01165         if( position.isValid() && import->position.isValid() && position < import->position )
01166           continue;
01167 
01168         context->mergeDeclarationsInternal(definitions, SimpleCursor::invalid(), hadContexts, source, searchInParents && context->shouldSearchInParent(InImportedParentContext) &&  context->parentContext()->type() == DUContext::Helper, currentDepth+1);
01169       }
01170     }
01171     
01173   if (parentContext() && searchInParents )
01174     parentContext()->mergeDeclarationsInternal(definitions, parentContext()->type() == DUContext::Class ? parentContext()->range().end : position, hadContexts, source, searchInParents, currentDepth+1);
01175 }
01176 
01177 void DUContext::deleteLocalDeclarations()
01178 {
01179   ENSURE_CAN_WRITE
01180   KDevVarLengthArray<LocalIndexedDeclaration> declarations;
01181   {
01182     QMutexLocker lock(&DUContextDynamicData::m_localDeclarationsMutex);
01183     FOREACH_FUNCTION(const LocalIndexedDeclaration& decl, d_func()->m_localDeclarations)
01184       declarations.append(decl);
01185   }
01186 
01187   TopDUContext* top = topContext();
01188   //If we are deleting something that is not stored to disk, we need to create + delete the declarations,
01189   //so their destructor unregisters from the persistent symbol table and from TopDUContextDynamicData
01190   FOREACH_ARRAY(LocalIndexedDeclaration decl, declarations)
01191     if(decl.isLoaded(top) || !top->deleting() || !top->isOnDisk())
01192       delete decl.data(top);
01193 }
01194 
01195 void DUContext::deleteChildContextsRecursively()
01196 {
01197   ENSURE_CAN_WRITE
01198 
01199   TopDUContext* top = topContext();
01200 
01201   QVector<LocalIndexedDUContext> children;
01202   FOREACH_FUNCTION(LocalIndexedDUContext ctx, d_func()->m_childContexts)
01203     children << ctx;
01204 
01205   //If we are deleting a context that is already stored to disk, we don't need to load not yet loaded child-contexts.
01206   //Else we need to, so the declarations are unregistered from symbol-table and from TopDUContextDynamicData in their destructor
01207   foreach(const LocalIndexedDUContext &ctx, children)
01208     if(ctx.isLoaded(top) || !top->deleting() || !top->isOnDisk())
01209       delete ctx.data(top);
01210 }
01211 
01212 QVector< Declaration * > DUContext::clearLocalDeclarations( )
01213 {
01214   QVector< Declaration * > ret = localDeclarations();
01215   foreach (Declaration* dec, ret)
01216     dec->setContext(0);
01217   return ret;
01218 }
01219 
01220 QualifiedIdentifier DUContext::scopeIdentifier(bool includeClasses) const
01221 {
01222   ENSURE_CAN_READ
01223 
01224   QualifiedIdentifier ret;
01225   m_dynamicData->scopeIdentifier(includeClasses, ret);
01226 
01227   return ret;
01228 }
01229 
01230 bool DUContext::equalScopeIdentifier(const DUContext* rhs) const
01231 {
01232   ENSURE_CAN_READ
01233 
01234   const DUContext* left = this;
01235   const DUContext* right = rhs;
01236 
01237   while(left || right) {
01238     if(!left || !right)
01239       return false;
01240 
01241     if(!(left->d_func()->m_scopeIdentifier == right->d_func()->m_scopeIdentifier))
01242       return false;
01243 
01244     left = left->parentContext();
01245     right = right->parentContext();
01246   }
01247 
01248   return true;
01249 }
01250 
01251 void DUContext::setLocalScopeIdentifier(const QualifiedIdentifier & identifier)
01252 {
01253   ENSURE_CAN_WRITE
01254   //Q_ASSERT(d_func()->m_childContexts.isEmpty() && d_func()->m_localDeclarations.isEmpty());
01255   bool wasInSymbolTable = inSymbolTable();
01256   setInSymbolTable(false);
01257   d_func_dynamic()->m_scopeIdentifier = identifier;
01258   setInSymbolTable(wasInSymbolTable);
01259   //DUChain::contextChanged(this, DUChainObserver::Change, DUChainObserver::Identifier);
01260 }
01261 
01262 QualifiedIdentifier DUContext::localScopeIdentifier() const
01263 {
01264   //ENSURE_CAN_READ Commented out for performance reasons
01265 
01266   return d_func()->m_scopeIdentifier;
01267 }
01268 
01269 IndexedQualifiedIdentifier DUContext::indexedLocalScopeIdentifier() const {
01270   return d_func()->m_scopeIdentifier;
01271 }
01272 
01273 DUContext::ContextType DUContext::type() const
01274 {
01275   //ENSURE_CAN_READ This is disabled, because type() is called very often while searching, and it costs us performance
01276 
01277   return d_func()->m_contextType;
01278 }
01279 
01280 void DUContext::setType(ContextType type)
01281 {
01282   ENSURE_CAN_WRITE
01283 
01284   d_func_dynamic()->m_contextType = type;
01285 
01286   //DUChain::contextChanged(this, DUChainObserver::Change, DUChainObserver::ContextType);
01287 }
01288 
01289 QList<Declaration*> DUContext::findDeclarations(const Identifier& identifier, const SimpleCursor& position, const TopDUContext* topContext, SearchFlags flags) const
01290 {
01291   ENSURE_CAN_READ
01292 
01293   DeclarationList ret;
01294   SearchItem::PtrList identifiers;
01295   identifiers << SearchItem::Ptr(new SearchItem(QualifiedIdentifier(identifier)));
01296   findDeclarationsInternal(identifiers, position.isValid() ? position : range().end, AbstractType::Ptr(), ret, topContext ? topContext : this->topContext(), flags, 0);
01297   return arrayToList(ret);
01298 }
01299 
01300 void DUContext::deleteUse(int index)
01301 {
01302   ENSURE_CAN_WRITE
01303   DUCHAIN_D_DYNAMIC(DUContext);
01304   removeFromArray(d->m_usesList(), index);
01305 
01306   if(!m_dynamicData->m_rangesForUses.isEmpty()) {
01307     if(m_dynamicData->m_rangesForUses[index]) {
01308       EditorIntegrator editor;
01309       editor.setCurrentUrl(url(), (bool)smartRange());
01310       LockedSmartInterface iface = editor.smart();
01311       if (iface) {
01312         m_dynamicData->m_rangesForUses[index]->removeWatcher(this);
01313         EditorIntegrator::releaseRange(m_dynamicData->m_rangesForUses[index]);
01314       }
01315     }
01316     m_dynamicData->m_rangesForUses.remove(index);
01317   }
01318 }
01319 
01320 QVector<KTextEditor::SmartRange*> DUContext::takeUseRanges()
01321 {
01322   ENSURE_CAN_WRITE
01323   QVector<KTextEditor::SmartRange*> ret = m_dynamicData->m_rangesForUses;
01324 
01325   foreach(KTextEditor::SmartRange* range, ret)
01326     if(range)
01327       range->removeWatcher(this);
01328 
01329   m_dynamicData->m_rangesForUses.clear();
01330   return ret;
01331 }
01332 
01333 QVector<KTextEditor::SmartRange*> DUContext::useRanges()
01334 {
01335   ENSURE_CAN_READ
01336   return m_dynamicData->m_rangesForUses;
01337 }
01338 
01339 void DUContext::deleteUses()
01340 {
01341   ENSURE_CAN_WRITE
01342 
01343   DUCHAIN_D_DYNAMIC(DUContext);
01344   d->m_usesList().clear();
01345 
01346   clearUseSmartRanges();
01347 }
01348 
01349 void DUContext::deleteUsesRecursively()
01350 {
01351   deleteUses();
01352   
01353   FOREACH_FUNCTION(LocalIndexedDUContext childContext, d_func()->m_childContexts)
01354     childContext.data(topContext())->deleteUsesRecursively();
01355 }
01356 
01357 bool DUContext::inDUChain() const {
01358   if( d_func()->m_anonymousInParent || !m_dynamicData->m_parentContext)
01359     return false;
01360 
01361   TopDUContext* top = topContext();
01362   return top && top->inDUChain();
01363 }
01364 
01365 DUContext* DUContext::specialize(IndexedInstantiationInformation /*specialization*/, const TopDUContext* /*topContext*/, int /*upDistance*/) {
01366   return this;
01367 }
01368 
01369 SimpleCursor DUContext::importPosition(const DUContext* target) const
01370 {
01371   ENSURE_CAN_READ
01372   DUCHAIN_D(DUContext);
01373   Import import(const_cast<DUContext*>(target), this, SimpleCursor::invalid());
01374   for(unsigned int a = 0; a < d->m_importedContextsSize(); ++a)
01375     if(d->m_importedContexts()[a] == import)
01376       return d->m_importedContexts()[a].position;
01377   return SimpleCursor::invalid();
01378 }
01379 
01380 QVector<DUContext::Import> DUContext::importedParentContexts() const
01381 {
01382   ENSURE_CAN_READ
01383   QVector<DUContext::Import> ret;
01384   FOREACH_FUNCTION(const DUContext::Import& import, d_func()->m_importedContexts)
01385     ret << import;
01386   return ret;
01387 }
01388 
01389 QList<DUContext*> DUContext::findContexts(ContextType contextType, const QualifiedIdentifier& identifier, const SimpleCursor& position, const TopDUContext* top, SearchFlags flags) const
01390 {
01391   ENSURE_CAN_READ
01392 
01393   QList<DUContext*> ret;
01394   SearchItem::PtrList identifiers;
01395   identifiers << SearchItem::Ptr(new SearchItem(identifier));
01396 
01397   findContextsInternal(contextType, identifiers, position.isValid() ? position : range().end, ret, top ? top : topContext(), flags);
01398   return ret;
01399 }
01400 
01401 void DUContext::applyAliases(const SearchItem::PtrList& baseIdentifiers, SearchItem::PtrList& identifiers, const SimpleCursor& position, bool canBeNamespace, bool onlyImports) const {
01402 
01403   QList<Declaration*> imports = allLocalDeclarations(globalImportIdentifier);
01404   if(imports.isEmpty() && onlyImports) {
01405     identifiers = baseIdentifiers;
01406     return;
01407   }
01408 
01409   FOREACH_ARRAY( const SearchItem::Ptr& identifier, baseIdentifiers ) {
01410     bool addUnmodified = true;
01411 
01412     if( !identifier->isExplicitlyGlobal ) {
01413 
01414       if( !imports.isEmpty() )
01415       {
01416         //We have namespace-imports.
01417         foreach( Declaration* importDecl, imports )
01418         {
01419           if( importDecl->range().end > position )
01420             continue;
01421           //Search for the identifier with the import-identifier prepended
01422           Q_ASSERT(dynamic_cast<NamespaceAliasDeclaration*>(importDecl));
01423           NamespaceAliasDeclaration* alias = static_cast<NamespaceAliasDeclaration*>(importDecl);
01424           identifiers.append( SearchItem::Ptr( new SearchItem( alias->importIdentifier(), identifier ) ) ) ;
01425         }
01426       }
01427 
01428       if( !identifier->isEmpty() && (identifier->hasNext() || canBeNamespace) ) {
01429         QList<Declaration*> aliases = allLocalDeclarations(identifier->identifier);
01430         if(!aliases.isEmpty()) {
01431           //The first part of the identifier has been found as a namespace-alias.
01432           //In c++, we only need the first alias. However, just to be correct, follow them all for now.
01433           foreach( Declaration* aliasDecl, aliases )
01434           {
01435             if( aliasDecl->range().end > position )
01436               continue;
01437             if(!dynamic_cast<NamespaceAliasDeclaration*>(aliasDecl))
01438               continue;
01439 
01440             addUnmodified = false; //The un-modified identifier can be ignored, because it will be replaced with the resolved alias
01441             NamespaceAliasDeclaration* alias = static_cast<NamespaceAliasDeclaration*>(aliasDecl);
01442 
01443             //Create an identifier where namespace-alias part is replaced with the alias target
01444             identifiers.append( SearchItem::Ptr( new SearchItem( alias->importIdentifier(), identifier->next ) ) ) ;
01445           }
01446         }
01447       }
01448     }
01449 
01450     if( addUnmodified )
01451         identifiers.append(identifier);
01452   }
01453 }
01454 
01455 void DUContext::applyUpwardsAliases(SearchItem::PtrList& identifiers, const TopDUContext* /*source*/) const {
01456 
01457   if(type() == Namespace) {
01458     QualifiedIdentifier localId = d_func()->m_scopeIdentifier;
01459     if(localId.isEmpty())
01460       return;
01461 
01462     //Make sure we search for the items in all namespaces of the same name, by duplicating each one with the namespace-identifier prepended.
01463     //We do this by prepending items to the current identifiers that equal the local scope identifier.
01464     SearchItem::Ptr newItem( new SearchItem(localId) );
01465 
01466     //This will exclude explictly global identifiers
01467     newItem->addToEachNode( identifiers );
01468 
01469     if(!newItem->next.isEmpty()) {
01470       //Prepend the full scope before newItem
01471       DUContext* parent = m_dynamicData->m_parentContext.data();
01472       while(parent) {
01473         newItem = SearchItem::Ptr( new SearchItem(parent->d_func()->m_scopeIdentifier, newItem) );
01474         parent = parent->m_dynamicData->m_parentContext.data();
01475       }
01476 
01477       newItem->isExplicitlyGlobal = true;
01478       insertToArray(identifiers, newItem, 0);
01479     }
01480   }
01481 }
01482 
01483 void DUContext::findContextsInternal(ContextType contextType, const SearchItem::PtrList& baseIdentifiers, const SimpleCursor& position, QList<DUContext*>& ret, const TopDUContext* source, SearchFlags flags) const
01484 {
01485   DUCHAIN_D(DUContext);
01486   if (contextType == type()) {
01487     FOREACH_ARRAY( const SearchItem::Ptr& identifier, baseIdentifiers )
01488       if (identifier->match(scopeIdentifier(true)) && (!parentContext() || !identifier->isExplicitlyGlobal) )
01489         ret.append(const_cast<DUContext*>(this));
01490   }
01493   SearchItem::PtrList aliasedIdentifiers;
01494   //Because of namespace-imports and aliases, this identifier may need to be searched as under multiple names
01495   applyAliases(baseIdentifiers, aliasedIdentifiers, position, contextType == Namespace, contextType != Namespace);
01496 
01497   if( d->m_importedContextsSize() != 0 ) {
01499     SearchItem::PtrList nonGlobalIdentifiers;
01500     FOREACH_ARRAY( const SearchItem::Ptr& identifier, aliasedIdentifiers )
01501       if( !identifier->isExplicitlyGlobal )
01502         nonGlobalIdentifiers << identifier;
01503 
01504     if( !nonGlobalIdentifiers.isEmpty() ) {
01505       for(int a = d->m_importedContextsSize()-1; a >= 0; --a) {
01506 
01507         DUContext* context = d->m_importedContexts()[a].context(source);
01508 
01509         while( !context && a > 0 ) {
01510           --a;
01511           context = d->m_importedContexts()[a].context(source);
01512         }
01513 
01514         if(context == this) {
01515           kDebug() << "resolved self as import:" << scopeIdentifier(true);
01516           continue;
01517         }
01518 
01519         if( !context )
01520           break;
01521 
01522         context->findContextsInternal(contextType, nonGlobalIdentifiers, url() == context->url() ? position : context->range().end, ret, source, flags | InImportedParentContext);
01523       }
01524     }
01525   }
01526 
01528   if ( !(flags & DontSearchInParent) && shouldSearchInParent(flags) && parentContext()) {
01529     applyUpwardsAliases(aliasedIdentifiers, source);
01530     parentContext()->findContextsInternal(contextType, aliasedIdentifiers, url() == parentContext()->url() ? position : parentContext()->range().end, ret, source, flags);
01531   }
01532 }
01533 
01534 bool DUContext::shouldSearchInParent(SearchFlags flags) const
01535 {
01536   return (parentContext() && parentContext()->type() == DUContext::Helper && (flags & InImportedParentContext)) ||
01537          !(flags & InImportedParentContext);
01538 }
01539 
01540 const Use* DUContext::uses() const
01541 {
01542   ENSURE_CAN_READ
01543 
01544   synchronizeUsesFromSmart();
01545   return d_func()->m_uses();
01546 }
01547 
01548 int DUContext::usesCount() const
01549 {
01550   return d_func()->m_usesSize();
01551 }
01552 
01553 int DUContext::createUse(int declarationIndex, const SimpleRange& range, KTextEditor::SmartRange* smartRange, int insertBefore)
01554 {
01555   DUCHAIN_D_DYNAMIC(DUContext);
01556   ENSURE_CAN_WRITE
01557 
01558   if(insertBefore == -1) {
01559     //Find position where to insert
01560     unsigned int a = 0;
01561     for(; a < d->m_usesSize() && range.start > d->m_uses()[a].m_range.start; ++a) { ///@todo do binary search
01562     }
01563     insertBefore = a;
01564   }
01565 
01566   insertToArray(d->m_usesList(), Use(range, declarationIndex), insertBefore);
01567   if(smartRange) {
01569     Q_ASSERT(uint(m_dynamicData->m_rangesForUses.size()) == d->m_usesSize()-1);
01570     m_dynamicData->m_rangesForUses.insert(insertBefore, smartRange);
01571     smartRange->addWatcher(this);
01572 //     smartRange->setWantsDirectChanges(true);
01573 
01574     d->m_usesList()[insertBefore].m_range = SimpleRange(*smartRange);
01575   }else{
01576     // This can happen eg. when a document is closed during its parsing, and has no ill effects.
01577     //Q_ASSERT(m_dynamicData->m_rangesForUses.isEmpty());
01578   }
01579 
01580   return insertBefore;
01581 }
01582 
01583 KTextEditor::SmartRange* DUContext::useSmartRange(int useIndex)
01584 {
01585   ENSURE_CAN_READ
01586   if(m_dynamicData->m_rangesForUses.isEmpty())
01587     return 0;
01588   else{
01589     if(useIndex >= 0 && useIndex < m_dynamicData->m_rangesForUses.size())
01590       return m_dynamicData->m_rangesForUses.at(useIndex);
01591     else
01592       return 0;
01593   }
01594 }
01595 
01596 
01597 void DUContext::setUseSmartRange(int useIndex, KTextEditor::SmartRange* range)
01598 {
01599   ENSURE_CAN_WRITE
01600   if(m_dynamicData->m_rangesForUses.isEmpty())
01601       m_dynamicData->m_rangesForUses.insert(0, d_func()->m_usesSize(), 0);
01602 
01603   Q_ASSERT(uint(m_dynamicData->m_rangesForUses.size()) == d_func()->m_usesSize());
01604 
01605   if(m_dynamicData->m_rangesForUses[useIndex]) {
01606     EditorIntegrator editor;
01607     editor.setCurrentUrl(url(), (bool)range);
01608     LockedSmartInterface iface = editor.smart();
01609     if (iface) {
01610       m_dynamicData->m_rangesForUses[useIndex]->removeWatcher(this);
01611       EditorIntegrator::releaseRange(m_dynamicData->m_rangesForUses[useIndex]);
01612     }
01613   }
01614 
01615   m_dynamicData->m_rangesForUses[useIndex] = range;
01616   d_func_dynamic()->m_usesList()[useIndex].m_range = SimpleRange(*range);
01617   range->addWatcher(this);
01618 //   range->setWantsDirectChanges(true);
01619 }
01620 
01621 void DUContext::clearUseSmartRanges()
01622 {
01623   ENSURE_CAN_WRITE
01624 
01625   if (!m_dynamicData->m_rangesForUses.isEmpty()) {
01626     EditorIntegrator editor;
01627     editor.setCurrentUrl(url(), (bool)smartRange());
01628     LockedSmartInterface iface = editor.smart();
01629     if (iface) {
01630       foreach (SmartRange* range, m_dynamicData->m_rangesForUses) {
01631         range->removeWatcher(this);
01632         EditorIntegrator::releaseRange(range);
01633       }
01634     }
01635 
01636     m_dynamicData->m_rangesForUses.clear();
01637   }
01638 }
01639 
01640 void DUContext::setUseDeclaration(int useNumber, int declarationIndex)
01641 {
01642   ENSURE_CAN_WRITE
01643   d_func_dynamic()->m_usesList()[useNumber].m_declarationIndex = declarationIndex;
01644 }
01645 
01646 
01647 DUContext * DUContext::findContextAt(const SimpleCursor & position, bool includeRightBorder) const
01648 {
01649   ENSURE_CAN_READ
01650   
01651 //   kDebug() << "searchign" << position.textCursor() << "in:" << scopeIdentifier(true).toString() << range().textRange() << includeRightBorder;
01652 
01653   if (!range().contains(position) && (!includeRightBorder || range().end != position)) {
01654 //     kDebug() << "mismatch";
01655     return 0;
01656   }
01657 
01658   for(int a = int(d_func()->m_childContextsSize())-1; a >= 0; --a)
01659     if (DUContext* specific = d_func()->m_childContexts()[a].data(topContext())->findContextAt(position, includeRightBorder))
01660       return specific;
01661 
01662   return const_cast<DUContext*>(this);
01663 }
01664 
01665 Declaration * DUContext::findDeclarationAt(const SimpleCursor & position) const
01666 {
01667   ENSURE_CAN_READ
01668 
01669   if (!range().contains(position))
01670     return 0;
01671 
01672   FOREACH_FUNCTION(LocalIndexedDeclaration child, d_func()->m_localDeclarations)
01673     if (child.data(topContext())->range().contains(position))
01674       return child.data(topContext());
01675 
01676   return 0;
01677 }
01678 
01679 DUContext* DUContext::findContextIncluding(const SimpleRange& range) const
01680 {
01681   ENSURE_CAN_READ
01682 
01683   if (!this->range().contains(range))
01684     return 0;
01685 
01686   FOREACH_FUNCTION(LocalIndexedDUContext child, d_func()->m_childContexts)
01687     if (DUContext* specific = child.data(topContext())->findContextIncluding(range))
01688       return specific;
01689 
01690   return const_cast<DUContext*>(this);
01691 }
01692 
01693 int DUContext::findUseAt(const SimpleCursor & position) const
01694 {
01695   ENSURE_CAN_READ
01696 
01697   synchronizeUsesFromSmart();
01698 
01699   if (!range().contains(position))
01700     return -1;
01701 
01702   for(unsigned int a = 0; a < d_func()->m_usesSize(); ++a)
01703     if (d_func()->m_uses()[a].m_range.contains(position))
01704       return a;
01705 
01706   return -1;
01707 }
01708 
01709 bool DUContext::inSymbolTable() const
01710 {
01711   return d_func()->m_inSymbolTable;
01712 }
01713 
01714 void DUContext::setInSymbolTable(bool inSymbolTable)
01715 {
01716     if(parentContext()) {
01717       if(!d_func()->m_inSymbolTable && inSymbolTable) {
01718         QualifiedIdentifier id(scopeIdentifier(true));
01719         PersistentSymbolTable::self().addContext(id, this);
01720 
01721       }else if(d_func()->m_inSymbolTable && !inSymbolTable) {
01722         QualifiedIdentifier id(scopeIdentifier(true));
01723         PersistentSymbolTable::self().removeContext(id, this);
01724       }
01725     }
01726 
01727   d_func_dynamic()->m_inSymbolTable = inSymbolTable;
01728 }
01729 
01730 // kate: indent-width 2;
01731 
01732 void DUContext::clearImportedParentContexts()
01733 {
01734   ENSURE_CAN_WRITE
01735   DUCHAIN_D_DYNAMIC(DUContext);
01736 
01737   while( d->m_importedContextsSize() != 0 ) {
01738     DUContext* ctx = d->m_importedContexts()[0].context(0);
01739     if(ctx)
01740       ctx->m_dynamicData->removeImportedChildContext(this);
01741 
01742     d->m_importedContextsList().removeOne(d->m_importedContexts()[0]);
01743   }
01744 }
01745 
01746 void DUContext::cleanIfNotEncountered(const QSet<DUChainBase*>& encountered)
01747 {
01748   ENSURE_CAN_WRITE
01749 
01750   foreach (Declaration* dec, localDeclarations())
01751     if (!encountered.contains(dec))
01752       delete dec;
01753     
01754   //Copy since the array may change during the iteration
01755   KDevVarLengthArray<LocalIndexedDUContext, 10> childrenCopy = d_func_dynamic()->m_childContextsList();
01756   
01757   FOREACH_ARRAY(LocalIndexedDUContext childContext, childrenCopy)
01758     if (!encountered.contains(childContext.data(topContext())))
01759       delete childContext.data(topContext());
01760 }
01761 
01762 TopDUContext* DUContext::topContext() const
01763 {
01764   return m_dynamicData->m_topContext;
01765 }
01766 
01767 QWidget* DUContext::createNavigationWidget(Declaration* /*decl*/, TopDUContext* /*topContext*/, const QString& /*htmlPrefix*/, const QString& /*htmlSuffix*/) const
01768 {
01769   return 0;
01770 }
01771 
01772 void DUContext::squeeze()
01773 {
01774   if(!m_dynamicData->m_rangesForUses.isEmpty())
01775     m_dynamicData->m_rangesForUses.squeeze();
01776 
01777   FOREACH_FUNCTION(LocalIndexedDUContext child, d_func()->m_childContexts)
01778     child.data(topContext())->squeeze();
01779 }
01780 
01781 QList<SimpleRange> allUses(DUContext* context, int declarationIndex, bool noEmptyUses)
01782 {
01783   QList<SimpleRange> ret;
01784   for(int a = 0; a < context->usesCount(); ++a)
01785     if(context->uses()[a].m_declarationIndex == declarationIndex)
01786       if(!noEmptyUses || !context->uses()[a].m_range.isEmpty())
01787         ret << context->uses()[a].m_range;
01788 
01789   foreach(DUContext* child, context->childContexts())
01790     ret += allUses(child, declarationIndex, noEmptyUses);
01791 
01792   return ret;
01793 }
01794 
01795 QList<KTextEditor::SmartRange*> allSmartUses(DUContext* context, int declarationIndex)
01796 {
01797   QList<KTextEditor::SmartRange*> ret;
01798 
01799   const Use* uses(context->uses());
01800 
01801   for(int a = 0; a < context->usesCount(); ++a)
01802     if(uses[a].m_declarationIndex == declarationIndex) {
01803       KTextEditor::SmartRange* range = context->useSmartRange(a);
01804       if(range)
01805         ret << range;
01806     }
01807 
01808   foreach(DUContext* child, context->childContexts())
01809     ret += allSmartUses(child, declarationIndex);
01810 
01811   return ret;
01812 }
01813 
01814 DUContext::SearchItem::SearchItem(const QualifiedIdentifier& id, Ptr nextItem, int start) : isExplicitlyGlobal(start == 0 ? id.explicitlyGlobal() : false) {
01815   if(!id.isEmpty()) {
01816     if(id.count() > start)
01817       identifier = id.at(start);
01818 
01819     if(id.count() > start+1)
01820       addNext(Ptr( new SearchItem(id, nextItem, start+1) ));
01821     else if(nextItem)
01822       next.append(nextItem);
01823   }else if(nextItem) {
01825     isExplicitlyGlobal = nextItem->isExplicitlyGlobal;
01826     identifier = nextItem->identifier;
01827     next = nextItem->next;
01828   }
01829 }
01830 
01831 DUContext::SearchItem::SearchItem(const QualifiedIdentifier& id, const PtrList& nextItems, int start) : isExplicitlyGlobal(start == 0 ? id.explicitlyGlobal() : false) {
01832   if(id.count() > start)
01833     identifier = id.at(start);
01834 
01835   if(id.count() > start+1)
01836     addNext(Ptr( new SearchItem(id, nextItems, start+1) ));
01837   else
01838     next = nextItems;
01839 }
01840 
01841 DUContext::SearchItem::SearchItem(bool explicitlyGlobal, Identifier id, const PtrList& nextItems) : isExplicitlyGlobal(explicitlyGlobal), identifier(id), next(nextItems) {
01842 }
01843 
01844 DUContext::SearchItem::SearchItem(bool explicitlyGlobal, Identifier id, Ptr nextItem) : isExplicitlyGlobal(explicitlyGlobal), identifier(id) {
01845   next.append(nextItem);
01846 }
01847 
01848 bool DUContext::SearchItem::match(const QualifiedIdentifier& id, int offset) const {
01849   if(id.isEmpty()) {
01850     if(identifier.isEmpty() && next.isEmpty())
01851       return true;
01852     else
01853       return false;
01854   }
01855 
01856   if(id.at(offset) != identifier) //The identifier is different
01857     return false;
01858 
01859   if(offset == id.count()-1) {
01860     if(next.isEmpty())
01861       return true; //match
01862     else
01863       return false; //id is too short
01864   }
01865 
01866   for(int a = 0; a < next.size(); ++a)
01867     if(next[a]->match(id, offset+1))
01868       return true;
01869 
01870   return false;
01871 }
01872 
01873 bool DUContext::SearchItem::isEmpty() const {
01874   return identifier.isEmpty();
01875 }
01876 
01877 bool DUContext::SearchItem::hasNext() const {
01878   return !next.isEmpty();
01879 }
01880 
01881 QList<QualifiedIdentifier> DUContext::SearchItem::toList(const QualifiedIdentifier& prefix) const {
01882   QList<QualifiedIdentifier> ret;
01883 
01884   QualifiedIdentifier id = prefix;
01885   if(id.isEmpty())
01886   id.setExplicitlyGlobal(isExplicitlyGlobal);
01887   if(!identifier.isEmpty())
01888     id.push(identifier);
01889 
01890   if(next.isEmpty()) {
01891     ret << id;
01892   } else {
01893     for(int a = 0; a < next.size(); ++a)
01894       ret += next[a]->toList(id);
01895   }
01896   return ret;
01897 }
01898 
01899 
01900 void DUContext::SearchItem::addNext(SearchItem::Ptr other) {
01901   next.append(other);
01902 }
01903 
01904 void DUContext::SearchItem::addToEachNode(SearchItem::Ptr other) {
01905   if(other->isExplicitlyGlobal)
01906     return;
01907 
01908   next.append(other);
01909   for(int a = 0; a < next.size()-1; ++a)
01910     next[a]->addToEachNode(other);
01911 }
01912 
01913 void DUContext::SearchItem::addToEachNode(SearchItem::PtrList other) {
01914   int added = 0;
01915   FOREACH_ARRAY(SearchItem::Ptr o, other) {
01916     if(!o->isExplicitlyGlobal) {
01917       next.append(o);
01918       ++added;
01919     }
01920   }
01921 
01922   for(int a = 0; a < next.size()-added; ++a)
01923     next[a]->addToEachNode(other);
01924 }
01925 
01926 DUContext::Import::Import(DUContext* _context, const DUContext* importer, const SimpleCursor& _position) : position(_position) {
01927   if(_context && _context->owner() && (_context->owner()->specialization().index() || (importer && importer->topContext() != _context->topContext()))) {
01928     m_declaration = _context->owner()->id();
01929   }else{
01930     m_context = _context;
01931   }
01932 }
01933 
01934 DUContext::Import::Import(const DeclarationId& id, const SimpleCursor& _position) : position(_position) {
01935   m_declaration = id;
01936 }
01937 
01938 DUContext* DUContext::Import::context(const TopDUContext* topContext) const {
01939   if(m_declaration.isValid()) {
01940     Declaration* decl = m_declaration.getDeclaration(topContext);
01941     if(decl)
01942       return decl->logicalInternalContext(topContext);
01943     else
01944       return 0;
01945   }else{
01946     return m_context.data();
01947   }
01948 }
01949 
01950 bool DUContext::Import::isDirect() const {
01951   return m_context.isValid();
01952 }
01953 
01954 }
01955 
01956 // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on

language/duchain

Skip menu "language/duchain"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDevelop Platform Libraries

Skip menu "KDevelop Platform Libraries"
  • interfaces
  • language
  •   codegen
  •   duchain
  •   editor
  • outputview
  • project
  • shell
  • sublime
  • util
  • vcs
Generated for KDevelop Platform Libraries by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal