/*************************************************************************** * Copyright (C) 2003 by Roberto Raggi * * roberto@kdevelop.org * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "codeinformationrepository.h" #include "cpp_tags.h" #include #include /// @todo move in utils.cpp static TQValueList my_unique( const TQValueList& entryList ) { TQValueList< KTextEditor::CompletionEntry > l; TQMap map; TQValueList< KTextEditor::CompletionEntry >::ConstIterator it = entryList.begin(); while ( it != entryList.end() ) { KTextEditor::CompletionEntry e = *it++; TQString key = e.type + " " + e.text + " " + e.prefix + " " + e.postfix + " "; if ( map.tqfind( key ) == map.end() ) { map[ key ] = TRUE; l << e; } } return l; } CodeInformationRepository::CodeInformationRepository( KDevCodeRepository* rep ) : m_rep( rep ) {} CodeInformationRepository::~CodeInformationRepository() {} TQValueList CodeInformationRepository::query( const TQValueList & args ) { // kdDebug( 9007 ) << "CodeInformationRepository::query()" << endl; TQValueList tags; TQValueList catalogs = m_rep->registeredCatalogs(); TQValueList::Iterator it = catalogs.begin(); while ( it != catalogs.end() ) { Catalog * catalog = *it; ++it; if ( !catalog->enabled() ) continue; tags += catalog->query( args ); } return tags; } TQValueList CodeInformationRepository::getTagsInFile( const TQString & fileName ) { kdDebug( 9007 ) << "CodeInformationRepository::getTagsInFile()" << endl; TQValueList args; args << Catalog::QueryArgument( "fileName", fileName ); TQValueList catalogs = m_rep->registeredCatalogs(); TQValueList::Iterator it = catalogs.begin(); while ( it != catalogs.end() ) { Catalog * catalog = *it; ++it; TQValueList tags = catalog->query( args ); if ( tags.size() ) return tags; } return TQValueList(); } TQValueList CodeInformationRepository::getTagsInScope( const TQStringList & scope, bool // isInstance ) { kdDebug( 9007 ) << "CodeInformationRepository::getTagsInScope()" << endl; TQValueList tags; TQValueList args; #if 0 args.clear(); args << Catalog::QueryArgument( "kind", Tag::Kind_Namespace ) << Catalog::QueryArgument( "scope", scope ); tags += query( args ); args.clear(); args << Catalog::QueryArgument( "kind", Tag::Kind_Class ) << Catalog::QueryArgument( "scope", scope ); tags += query( args ); #endif args.clear(); args << Catalog::QueryArgument( "kind", Tag::Kind_FunctionDeclaration ) << Catalog::QueryArgument( "scope", scope ); tags += query( args ); args.clear(); args << Catalog::QueryArgument( "kind", Tag::Kind_Variable ) << Catalog::QueryArgument( "scope", scope ); tags += query( args ); if ( true /*!isInstance*/ ) { args.clear(); args << Catalog::QueryArgument( "kind", Tag::Kind_Enumerator ) << Catalog::QueryArgument( "scope", scope ); tags += query( args ); } return tags; } TQValueList CodeInformationRepository::getEntriesInScope( const TQStringList & scope, bool isInstance, bool recompute ) { kdDebug( 9007 ) << "CodeInformationRepository::getEntriesInScope()" << endl; if ( !recompute && !scope.size() && m_globalEntries.size() ) return m_globalEntries; else if ( scope.size() == 0 ) { m_globalEntries = my_unique( toEntryList( getTagsInScope( scope, isInstance ) ) ); return m_globalEntries; } return toEntryList( getTagsInScope( scope, isInstance ) ); } TQValueList CodeInformationRepository::getBaseClassList( const TQString& className ) { // kdDebug( 9007 ) << "CodeInformationRepository::getBaseClassList()" << endl; if ( className.isEmpty() ) return TQValueList(); TQValueList args; args << Catalog::QueryArgument( "kind", Tag::Kind_Base_class ); /* if( className.length() >= 2 ) args << Catalog::QueryArgument( "prefix", className.left(2) );*/ args << Catalog::QueryArgument( "name", className ); return query( args ); } TQValueList CodeInformationRepository::getClassOrNamespaceList( const TQStringList & scope ) { kdDebug( 9007 ) << "CodeInformationRepository::getClassOrNamespaceList()" << endl; TQValueList tags; TQValueList args; args << Catalog::QueryArgument( "kind", Tag::Kind_Namespace ) << Catalog::QueryArgument( "scope", scope ); tags += query( args ); args.clear(); args << Catalog::QueryArgument( "kind", Tag::Kind_Class ) << Catalog::QueryArgument( "scope", scope ); tags += query( args ); return tags; } TQValueList CodeInformationRepository::getTagsInScope( const TQString & name, const TQStringList & scope ) { TQValueList tags; TQValueList args; args.clear(); args << Catalog::QueryArgument( "scope", scope ); /* if( name.length() >= 2 ) args << Catalog::QueryArgument( "prefix", name.left(2) ); */ args << Catalog::QueryArgument( "name", name ); tags += query( args ); return tags; } KTextEditor::CompletionEntry CodeInformationRepository::toEntry( Tag & tag, CppCodeCompletion::CompletionMode completionMode, TypeProcessor* proc ) { KTextEditor::CompletionEntry entry; if ( tag.name().isEmpty() ) return entry; switch ( tag.kind() ) { case Tag::Kind_Typedef: entry.prefix = "typedef"; entry.text = tag.name(); break; case Tag::Kind_Class: entry.prefix = "class"; entry.text = tag.name(); break; case Tag::Kind_Struct: entry.prefix = "struct"; entry.text = tag.name(); break; case Tag::Kind_Namespace: entry.prefix = "namespace"; entry.text = tag.name(); break; case Tag::Kind_FunctionDeclaration: //case Tag::Kind_Function: { CppFunction tagInfo( tag ); TQStringList arguments = tagInfo.arguments(); TQStringList argumentNames = tagInfo.argumentNames(); if ( completionMode == CppCodeCompletion::VirtualDeclCompletion ) { //Ideally the type info would be a entry.prefix, but we need them to be //inserted upon completion so they have to be part of entry.text entry.text = tagInfo.type(); entry.text += " "; entry.text += tag.name(); } else entry.text = tag.name(); if ( !arguments.size() ) entry.text += "("; else entry.text += "( "; TQString signature; for ( uint i = 0; i < arguments.size(); ++i ) { if( !proc ) signature += arguments[ i ]; else signature += proc->processType( arguments[ i ] ); if ( completionMode == CppCodeCompletion::NormalCompletion || completionMode == CppCodeCompletion::VirtualDeclCompletion ) { TQString argName = argumentNames[ i ]; if ( !argName.isEmpty() ) signature += TQString::tqfromLatin1( " " ) + argName; } if ( i != ( arguments.size() - 1 ) ) { signature += ", "; } } if ( signature.isEmpty() ) entry.text += ")"; else entry.postfix = signature + " )"; if ( tagInfo.isConst() ) entry.postfix += " const"; if ( completionMode == CppCodeCompletion::VirtualDeclCompletion ) { entry.text += entry.postfix + ";"; entry.postfix = TQString(); } else if ( completionMode != CppCodeCompletion::NormalCompletion ) { entry.text += entry.postfix; entry.postfix = TQString(); } TQString comment = tag.attribute( "description" ).toString(); if ( !comment.isNull() ) entry.comment = comment; //else //entry.comment = "no documentation available!"; } break; case Tag::Kind_Enumerator: case Tag::Kind_Variable: entry.text = tag.name(); break; default: ; } entry.comment = tag.comment(); return entry; } TQValueList CodeInformationRepository::toEntryList( const TQValueList & tags, CppCodeCompletion::CompletionMode completionMode ) { TQValueList entryList; TQMap ns; TQValueList::ConstIterator it = tags.begin(); while ( it != tags.end() ) { Tag tag = *it; ++it; KTextEditor::CompletionEntry entry = toEntry( tag, completionMode ); if ( !entry.text.isEmpty() ) entryList << entry; } return entryList; }