00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 {}
00070 if (member->isFriend())
00071 p |= CodeCompletionModel::Friend;
00072 if (member->isRegister())
00073 {}
00074 if (member->isExtern())
00075 {}
00076 if (member->isMutable())
00077 {}
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 {}
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
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) )
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
00258 foreach( DUContext* subCtx, ctx->childContexts() ) {
00259
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
00279 Declaration* decl = declarationUnderCursor(c, ctx);
00280 if(decl)
00281 return decl;
00282
00283
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();
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
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 }