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

language/duchain

duchainutils.cpp

00001 /*
00002  * DUChain Utilities
00003  *
00004  * Copyright 2007 Hamish Rodda <rodda@kde.org>
00005  * Copyright 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU Library General Public License as
00009  * published by the Free Software Foundation; either version 2 of the
00010  * License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public
00018  * License along with this program; if not, write to the
00019  * Free Software Foundation, Inc.,
00020  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #include "duchainutils.h"
00024 
00025 #include <kiconloader.h>
00026 
00027 #include <interfaces/ilanguage.h>
00028 #include <interfaces/icore.h>
00029 #include <interfaces/ilanguagecontroller.h>
00030 
00031 #include "../interfaces/ilanguagesupport.h"
00032 
00033 #include "declaration.h"
00034 #include "classfunctiondeclaration.h"
00035 #include "ducontext.h"
00036 #include "duchain.h"
00037 #include "use.h"
00038 #include "duchainlock.h"
00039 #include "classmemberdeclaration.h"
00040 #include "functiondefinition.h"
00041 #include "specializationstore.h"
00042 #include "persistentsymboltable.h"
00043 #include "classdeclaration.h"
00044 
00045 using namespace KDevelop;
00046 using namespace KTextEditor;
00047 
00048 CodeCompletionModel::CompletionProperties DUChainUtils::completionProperties(const Declaration* dec)
00049 {
00050   CodeCompletionModel::CompletionProperties p;
00051 
00052   if(dec->context()->type() == DUContext::Class) {
00053     if (const ClassMemberDeclaration* member = dynamic_cast<const ClassMemberDeclaration*>(dec)) {
00054       switch (member->accessPolicy()) {
00055         case Declaration::Public:
00056           p |= CodeCompletionModel::Public;
00057           break;
00058         case Declaration::Protected:
00059           p |= CodeCompletionModel::Protected;
00060           break;
00061         case Declaration::Private:
00062           p |= CodeCompletionModel::Private;
00063           break;
00064       }
00065 
00066       if (member->isStatic())
00067         p |= CodeCompletionModel::Static;
00068       if (member->isAuto())
00069         {}//TODO
00070       if (member->isFriend())
00071         p |= CodeCompletionModel::Friend;
00072       if (member->isRegister())
00073         {}//TODO
00074       if (member->isExtern())
00075         {}//TODO
00076       if (member->isMutable())
00077         {}//TODO
00078     }
00079   }
00080 
00081   if (const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(dec)) {
00082     p |= CodeCompletionModel::Function;
00083     if (function->isVirtual())
00084       p |= CodeCompletionModel::Virtual;
00085     if (function->isInline())
00086       p |= CodeCompletionModel::Inline;
00087     if (function->isExplicit())
00088       {}//TODO
00089   }
00090 
00091   if( dec->isTypeAlias() )
00092     p |= CodeCompletionModel::TypeAlias;
00093 
00094   if (dec->abstractType()) {
00095     switch (dec->abstractType()->whichType()) {
00096       case AbstractType::TypeIntegral:
00097         p |= CodeCompletionModel::Variable;
00098         break;
00099       case AbstractType::TypePointer:
00100         p |= CodeCompletionModel::Variable;
00101         break;
00102       case AbstractType::TypeReference:
00103         p |= CodeCompletionModel::Variable;
00104         break;
00105       case AbstractType::TypeFunction:
00106         p |= CodeCompletionModel::Function;
00107         break;
00108       case AbstractType::TypeStructure:
00109         p |= CodeCompletionModel::Class;
00110         break;
00111       case AbstractType::TypeArray:
00112         p |= CodeCompletionModel::Variable;
00113         break;
00114       case AbstractType::TypeEnumeration:
00115       case AbstractType::TypeEnumerator:
00116         p |= CodeCompletionModel::Enum;
00117         break;
00118       case AbstractType::TypeAbstract:
00119       case AbstractType::TypeDelayed:
00120         // TODO
00121         break;
00122     }
00123 
00124     if( dec->kind() == Declaration::Instance && !dec->isFunctionDeclaration() )
00125       p |= CodeCompletionModel::Variable;
00126   }
00127 
00128   if (dec->context()) {
00129     if( dec->context()->type() == DUContext::Global )
00130       p |= CodeCompletionModel::GlobalScope;
00131     else if( dec->context()->type() == DUContext::Namespace )
00132       p |= CodeCompletionModel::NamespaceScope;
00133     else if( dec->context()->type() != DUContext::Class && dec->context()->type() != DUContext::Enum )
00134       p |= CodeCompletionModel::LocalScope;
00135   }
00136 
00137   return p;
00138 }
00143 #define RETURN_CACHED_ICON(name) {static QIcon icon(KIcon(name).pixmap(QSize(16, 16))); return icon;}
00144 
00145 QIcon DUChainUtils::iconForProperties(KTextEditor::CodeCompletionModel::CompletionProperties p)
00146 {
00147 
00148   if( (p & CodeCompletionModel::Variable) )
00149     if( (p & CodeCompletionModel::Protected) )
00150       RETURN_CACHED_ICON("CVprotected_var")
00151     else if( p & CodeCompletionModel::Private )
00152       RETURN_CACHED_ICON("CVprivate_var")
00153     else
00154       RETURN_CACHED_ICON("CVpublic_var")
00155   else
00156   if( (p & CodeCompletionModel::Union) && (p & CodeCompletionModel::Protected) )
00157     RETURN_CACHED_ICON("protected_union")
00158 
00159   else if( p & CodeCompletionModel::Enum )
00160     if( p & CodeCompletionModel::Protected )
00161       RETURN_CACHED_ICON("protected_enum")
00162     else if( p & CodeCompletionModel::Private )
00163       RETURN_CACHED_ICON("private_enum")
00164     else
00165       RETURN_CACHED_ICON("enum")
00166 
00167   else if( p & CodeCompletionModel::Struct )
00168     if( p & CodeCompletionModel::Private )
00169       RETURN_CACHED_ICON("private_struct")
00170     else
00171       RETURN_CACHED_ICON("struct")
00172 
00173   else if( p & CodeCompletionModel::Slot )
00174     if( p & CodeCompletionModel::Protected )
00175       RETURN_CACHED_ICON("CVprotected_slot")
00176     else if( p & CodeCompletionModel::Private )
00177       RETURN_CACHED_ICON("CVprivate_slot")
00178     else if(p & CodeCompletionModel::Public )
00179       RETURN_CACHED_ICON("CVpublic_slot")
00180     else RETURN_CACHED_ICON("slot")
00181   else if( p & CodeCompletionModel::Signal )
00182     if( p & CodeCompletionModel::Protected )
00183       RETURN_CACHED_ICON("CVprotected_signal")
00184     else
00185       RETURN_CACHED_ICON("signal")
00186 
00187   else if( p & CodeCompletionModel::Class )
00188     if( (p & CodeCompletionModel::Class) && (p & CodeCompletionModel::Protected) )
00189       RETURN_CACHED_ICON("protected_class")
00190     else if( (p & CodeCompletionModel::Class) && (p & CodeCompletionModel::Private) )
00191       RETURN_CACHED_ICON("private_class")
00192     else
00193       RETURN_CACHED_ICON("code-class")
00194 
00195   else if( p & CodeCompletionModel::Union )
00196     if( p & CodeCompletionModel::Private )
00197       RETURN_CACHED_ICON("private_union")
00198     else
00199       RETURN_CACHED_ICON("union")
00200 
00201   else if( p & CodeCompletionModel::TypeAlias )
00202     if ((p & CodeCompletionModel::Const) /*||  (p & CodeCompletionModel::Volatile)*/)
00203       RETURN_CACHED_ICON("CVtypedef")
00204     else
00205       RETURN_CACHED_ICON("typedef")
00206 
00207   else if( p & CodeCompletionModel::Function ) {
00208     if( p & CodeCompletionModel::Protected )
00209       RETURN_CACHED_ICON("protected_function")
00210     else if( p & CodeCompletionModel::Private )
00211       RETURN_CACHED_ICON("private_function")
00212     else
00213       RETURN_CACHED_ICON("code-function")
00214   }
00215 
00216   if( p & CodeCompletionModel::Protected )
00217     RETURN_CACHED_ICON("protected_field")
00218   else if( p & CodeCompletionModel::Private )
00219     RETURN_CACHED_ICON("private_field")
00220   else
00221     RETURN_CACHED_ICON("field")
00222 
00223   return KIcon();
00224 }
00225 
00226 QIcon DUChainUtils::iconForDeclaration(const Declaration* dec)
00227 {
00228   return iconForProperties(completionProperties(dec));
00229 }
00230 
00231 TopDUContext* DUChainUtils::standardContextForUrl(const KUrl& url) {
00232   KDevelop::TopDUContext* chosen = 0;
00233 
00234   QList<KDevelop::ILanguage*> languages = ICore::self()->languageController()->languagesForUrl(url);
00235 
00236   foreach( KDevelop::ILanguage* language, languages)
00237   {
00238     if(!chosen)
00239     {
00240       if (language->languageSupport())
00241         chosen = language->languageSupport()->standardContext(url);
00242     }
00243   }
00244 
00245   if(!chosen)
00246     return DUChain::self()->chainForDocument(IndexedString(url.pathOrUrl()));
00247 
00248   return chosen;
00249 }
00250 
00251 Declaration* declarationUnderCursor(const SimpleCursor& c, DUContext* ctx)
00252 {
00253   foreach( Declaration* decl, ctx->localDeclarations() )
00254     if( decl->range().contains(c) )
00255       return decl;
00256 
00257   //Search all collapsed sub-contexts. In C++, those can contain declarations that have ranges out of the context
00258   foreach( DUContext* subCtx, ctx->childContexts() ) {
00259     //This is a little hacky, but we need it in case of foreach macros and similar stuff
00260     if(subCtx->range().isEmpty() || subCtx->range().start.line == c.line || subCtx->range().end.line == c.line) {
00261       Declaration* decl = declarationUnderCursor(c, subCtx);
00262       if(decl)
00263         return decl;
00264     }
00265   }
00266   return 0;
00267 }
00268 
00269 Declaration* DUChainUtils::itemUnderCursor(const KUrl& url, const SimpleCursor& c)
00270 {
00271   KDevelop::TopDUContext* chosen = standardContextForUrl(url);
00272 
00273   if( chosen )
00274   {
00275     DUContext* ctx = chosen->findContextAt(c);
00276 
00277     while( ctx ) {
00278       //Try finding a declaration under the cursor
00279       Declaration* decl = declarationUnderCursor(c, ctx);
00280       if(decl)
00281         return decl;
00282 
00283       //Try finding a use under the cursor
00284       for(int a = 0; a < ctx->usesCount(); ++a)
00285         if( ctx->uses()[a].m_range.contains(c) )
00286           return ctx->topContext()->usedDeclarationForIndex(ctx->uses()[a].m_declarationIndex);
00287 
00288       ctx = ctx->parentContext(); //It may happen, for example in the case of function-declarations, that the use is one context higher.
00289     }
00290   }
00291   return 0;
00292 }
00293 
00294 Declaration* DUChainUtils::declarationForDefinition(Declaration* definition, TopDUContext* topContext)
00295 {
00296   if(!definition)
00297     return 0;
00298 
00299   if(!topContext)
00300     topContext = definition->topContext();
00301 
00302   if(dynamic_cast<FunctionDefinition*>(definition)) {
00303     Declaration* ret = static_cast<FunctionDefinition*>(definition)->declaration();
00304     if(ret)
00305       return ret;
00306   }
00307 
00308   return definition;
00309 }
00310 
00311 Declaration* DUChainUtils::declarationInLine(const KDevelop::SimpleCursor& cursor, DUContext* ctx) {
00312   if(!ctx)
00313     return 0;
00314   
00315   foreach(Declaration* decl, ctx->localDeclarations()) {
00316     if(decl->range().start.line == cursor.line)
00317       return decl;
00318     DUContext* funCtx = getFunctionContext(decl);
00319     if(funCtx && funCtx->contains(cursor))
00320       return decl;
00321   }
00322 
00323   foreach(DUContext* child, ctx->childContexts()){
00324     Declaration* decl = declarationInLine(cursor, child);
00325     if(decl)
00326       return decl;
00327   }
00328 
00329   return 0;
00330 }
00331 
00332 DUChainUtils::DUChainItemFilter::~DUChainItemFilter() {
00333 }
00334 
00335 void DUChainUtils::collectItems( DUContext* context, DUChainItemFilter& filter ) {
00336 
00337   QVector<DUContext*> children = context->childContexts();
00338   QVector<Declaration*> localDeclarations = context->localDeclarations();
00339 
00340   QVector<DUContext*>::const_iterator childIt = children.constBegin();
00341   QVector<Declaration*>::const_iterator declIt = localDeclarations.constBegin();
00342 
00343   while(childIt != children.constEnd() || declIt != localDeclarations.constEnd()) {
00344 
00345     DUContext* child = 0;
00346     if(childIt != children.constEnd())
00347       child = *childIt;
00348 
00349     Declaration* decl = 0;
00350     if(declIt != localDeclarations.constEnd())
00351       decl = *declIt;
00352 
00353     if(decl) {
00354       if(child && child->range().start.line >= decl->range().start.line)
00355         child = 0;
00356     }
00357 
00358     if(child) {
00359       if(decl && decl->range().start >= child->range().start)
00360         decl = 0;
00361     }
00362 
00363     if(decl) {
00364       if( filter.accept(decl) ) {
00365         //Action is done in the filter
00366       }
00367 
00368       ++declIt;
00369       continue;
00370     }
00371 
00372     if(child) {
00373       if( filter.accept(child) )
00374         collectItems(child, filter);
00375       ++childIt;
00376       continue;
00377     }
00378   }
00379 }
00380 
00381 KDevelop::DUContext* DUChainUtils::getArgumentContext(KDevelop::Declaration* decl) {
00382   DUContext* internal = decl->internalContext();
00383   if( !internal )
00384     return 0;
00385   if( internal->type() == DUContext::Function )
00386     return internal;
00387   foreach( const DUContext::Import &ctx, internal->importedParentContexts() ) {
00388     if( ctx.context(decl->topContext()) )
00389       if( ctx.context(decl->topContext())->type() == DUContext::Function )
00390         return ctx.context(decl->topContext());
00391   }
00392   return 0;
00393 }
00394 
00395 QList<IndexedDeclaration> DUChainUtils::collectAllVersions(Declaration* decl) {
00396   QList<IndexedDeclaration> ret;
00397   ret << IndexedDeclaration(decl);
00398   
00399   if(decl->inSymbolTable())
00400   {
00401     uint count;
00402     const IndexedDeclaration* allDeclarations;
00403     PersistentSymbolTable::self().declarations(decl->qualifiedIdentifier(), count, allDeclarations);
00404     for(uint a = 0; a < count; ++a)
00405       if(!(allDeclarations[a] == IndexedDeclaration(decl)))
00406         ret << allDeclarations[a];
00407   }
00408   
00409   return ret;
00410 }
00411 
00413 QList<Declaration*> DUChainUtils::getInheriters(const Declaration* decl, uint& maxAllowedSteps, bool collectVersions)
00414 {
00415   QList<Declaration*> ret;
00416   
00417   if(!dynamic_cast<const ClassDeclaration*>(decl))
00418     return ret;
00419 
00420   if(maxAllowedSteps == 0)
00421     return ret;
00422 
00423   if(decl->internalContext() && decl->internalContext()->type() == DUContext::Class)
00424     FOREACH_ARRAY(IndexedDUContext importer, decl->internalContext()->indexedImporters()) {
00425       
00426       DUContext* imp = importer.data();
00427       
00428       if(!imp)
00429         continue;
00430       
00431       if(imp->type() == DUContext::Class && imp->owner())
00432         ret << imp->owner();
00433 
00434       --maxAllowedSteps;
00435       
00436       if(maxAllowedSteps == 0)
00437         return ret;
00438     }
00439     
00440     if(maxAllowedSteps == 0)
00441       return ret;
00442 
00443   if(collectVersions && decl->inSymbolTable()) {
00444     uint count;
00445     const IndexedDeclaration* allDeclarations;
00446     PersistentSymbolTable::self().declarations(decl->qualifiedIdentifier(), count, allDeclarations);
00447     for(uint a = 0; a < count; ++a) {
00448       ++maxAllowedSteps;
00449       
00450       if(allDeclarations[a].data() && allDeclarations[a].data() != decl) {
00451         ret += getInheriters(allDeclarations[a].data(), maxAllowedSteps, false);
00452       }
00453       
00454       if(maxAllowedSteps == 0)
00455         return ret;
00456     }
00457   }
00458   
00459   return ret;
00460 }
00461 
00462 QList<Declaration*> DUChainUtils::getOverriders(const Declaration* currentClass, const Declaration* overriddenDeclaration, uint& maxAllowedSteps) {
00463   QList<Declaration*> ret;
00464   
00465   if(maxAllowedSteps == 0)
00466     return ret;
00467   
00468   if(currentClass != overriddenDeclaration->context()->owner() && currentClass->internalContext())
00469     ret += currentClass->internalContext()->findLocalDeclarations(overriddenDeclaration->identifier(), SimpleCursor::invalid(), currentClass->topContext(), overriddenDeclaration->abstractType());
00470   
00471   foreach(Declaration* inheriter, getInheriters(currentClass, maxAllowedSteps))
00472     ret += getOverriders(inheriter, overriddenDeclaration, maxAllowedSteps);
00473   
00474   return ret;
00475 }
00476 
00477 static bool hasUse(DUContext* context, int usedDeclarationIndex) {
00478   if(usedDeclarationIndex == std::numeric_limits<int>::max())
00479     return false;
00480   
00481   for(int a = 0; a < context->usesCount(); ++a)
00482     if(context->uses()[a].m_declarationIndex == usedDeclarationIndex)
00483       return true;
00484     
00485   foreach(DUContext* child, context->childContexts())
00486     if(hasUse(child, usedDeclarationIndex))
00487       return true;
00488   return false;
00489 }
00490 
00491 bool DUChainUtils::contextHasUse(DUContext* context, Declaration* declaration) {
00492   return hasUse(context, context->topContext()->indexForUsedDeclaration(declaration, false));
00493 }
00494 
00495 static uint countUses(DUContext* context, int usedDeclarationIndex) {
00496   if(usedDeclarationIndex == std::numeric_limits<int>::max())
00497     return 0;
00498   
00499   uint ret = 0;
00500   
00501   for(int a = 0; a < context->usesCount(); ++a)
00502     if(context->uses()[a].m_declarationIndex == usedDeclarationIndex)
00503       ++ret;
00504     
00505   foreach(DUContext* child, context->childContexts())
00506     ret += countUses(child, usedDeclarationIndex);
00507   
00508   return ret;
00509 }
00510 
00511 uint DUChainUtils::contextCountUses(DUContext* context, Declaration* declaration) {
00512   return countUses(context, context->topContext()->indexForUsedDeclaration(declaration, false));
00513 }
00514 
00515 Declaration* DUChainUtils::getOverridden(const Declaration* decl) {
00516   const ClassFunctionDeclaration* classFunDecl = dynamic_cast<const ClassFunctionDeclaration*>(decl);
00517   if(!classFunDecl || !classFunDecl->isVirtual())
00518     return 0;
00519   
00520   QList<Declaration*> decls;
00521 
00522   foreach(const DUContext::Import &import, decl->context()->importedParentContexts()) {
00523     DUContext* ctx = import.context(decl->topContext());
00524     if(ctx)
00525       decls += ctx->findDeclarations(QualifiedIdentifier(decl->identifier()), 
00526                                             SimpleCursor::invalid(), decl->abstractType(), decl->topContext(), DUContext::DontSearchInParent);
00527   }
00528 
00529   foreach(Declaration* found, decls) {
00530     const ClassFunctionDeclaration* foundClassFunDecl = dynamic_cast<const ClassFunctionDeclaration*>(found);
00531     if(foundClassFunDecl && foundClassFunDecl->isVirtual())
00532       return found;
00533   }
00534     
00535   return 0;
00536 }
00537 
00538 DUContext* DUChainUtils::getFunctionContext(Declaration* decl) {
00539   DUContext* functionContext = decl->internalContext();
00540   if(functionContext && functionContext->type() != DUContext::Function) {
00541     foreach(DUContext::Import import, functionContext->importedParentContexts()) {
00542       DUContext* ctx = import.context(decl->topContext());
00543       if(ctx && ctx->type() == DUContext::Function)
00544         functionContext = ctx;
00545     }
00546   }
00547   
00548   if(functionContext && functionContext->type() == DUContext::Function)
00549     return functionContext;
00550   return 0;
00551 }

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