/*************************************************************************** copyright : (C) 2006 by David Nolden email : david.nolden.tdevelop@art-master.de ***************************************************************************/ /*************************************************************************** * * * 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 "simpletypecatalog.h" #include "simpletypefunction.h" #include "safetycounter.h" extern SafetyCounter safetyCounter; extern CppCodeCompletion* cppCompletionInstance; //SimpleTypeCatalog implementation TypePointer SimpleTypeCatalog::clone() { return new SimpleTypeCachedCatalog( this ); } TQString SimpleTypeCatalog::specialization() const { return m_tag.getSpecializationDeclaration(); } void SimpleTypeCatalog::addAliasesTo( SimpleTypeNamespace* ns ) { if ( m_tag.kind() != Tag::Kind_Namespace ) return; TQValueList args; ///Insert all namespace-imports args << Catalog::QueryArgument( "scope", specializedScope() ); args << Catalog::QueryArgument( "kind", Tag::Kind_UsingDirective ); TQValueList tags( cppCompletionInstance->m_repository->query( args ) ); for ( TQValueList::iterator it = tags.begin(); it != tags.end(); ++it ) { TypeDesc d( (*it).name() ); d.setIncludeFiles( HashedString((*it).fileName()) ); ///@todo implement the include-file-logic ns->addAliasMap( TypeDesc(), d, HashedString((*it).fileName()), true, false, bigContainer() ); } ///Insert all namespace-aliases args.clear(); args << Catalog::QueryArgument( "scope", specializedScope() ); args << Catalog::QueryArgument( "kind", Tag::Kind_NamespaceAlias ); tags = cppCompletionInstance->m_repository->query( args ); for ( TQValueList::iterator it = tags.begin(); it != tags.end(); ++it ) { TQVariant v = (*it).attribute( "alias" ); if ( v.type() == TQVariant::String ) { TypeDesc d( v.asString() ); d.setIncludeFiles( HashedString((*it).fileName()) ); ns->addAliasMap( (*it).name(), d, HashedString((*it).fileName()), true, false, bigContainer() ); } else kdDebug( 9007 ) << "namespace-alias has no alias-text" << endl; } } TQValueList SimpleTypeCatalog::getMemberClasses( const TypeDesc& name ) { TQValueList ret; TQValueList args; args << Catalog::QueryArgument( "scope", specializedScope() ); args << Catalog::QueryArgument( "name", name.name() ); TQValueList tags( cppCompletionInstance->m_repository->query( args ) ); for ( TQValueList::iterator it = tags.begin(); it != tags.end(); ++it ) { if ( (*it).kind() == Tag::Kind_Class ) { ///It would be better to return all matched class-names from within findMember and use them from there so all this will be cached too. CatalogBuildInfo b( *it, name, TypePointer( this ) ); TypePointer t = b.buildCached(); if ( t ) ret << t; } } return ret; } SimpleTypeImpl::MemberInfo SimpleTypeCatalog::findMember( TypeDesc name, SimpleTypeImpl::MemberInfo::MemberType type ) { MemberInfo ret; ret.name = name.name(); ret.memberType = MemberInfo::NotFound; if ( !name ) return ret; if ( ( type & MemberInfo::Template) ) { LocateResult s = findTemplateParam( name.name() ); if ( s ) { ret.memberType = MemberInfo::Template; ret.type = s; ret.decl.name = name.name(); ret.decl.file = m_tag.fileName(); m_tag.getStartPosition( &ret.decl.startLine, &ret.decl.startCol ); m_tag.getEndPosition( &ret.decl.endLine, &ret.decl.endCol ); } } TQValueList args; args << Catalog::QueryArgument( "scope", specializedScope() ); args << Catalog::QueryArgument( "name", name.name() ); TQValueList tags( cppCompletionInstance->m_repository->query( args ) ); if ( tags.isEmpty() ) return ret; ///skip all using-directives TQValueList::iterator it = tags.begin(); while ( ( (*it).kind() == Tag::Kind_UsingDirective || (*it).kind() == Tag::Kind_NamespaceAlias ) && it != tags.end() ) ++it; if ( it == tags.end() ) return ret; Tag tag = *it; if ( tag.kind() == Tag::Kind_Variable && (type & MemberInfo::Variable) ) { ret.memberType = MemberInfo::Variable; ret.type = tagType( tag ); ret.decl.name = tag.name(); ret.decl.comment = tag.comment(); tag.getStartPosition( &ret.decl.startLine, &ret.decl.startCol ); tag.getEndPosition( &ret.decl.endLine, &ret.decl.endCol ); ret.decl.file = tag.fileName(); } if ( tag.kind() == Tag::Kind_Enumerator && (type & MemberInfo::Variable) ) { ret.memberType = MemberInfo::Variable; if ( !tag.hasAttribute( "enum" ) ) { ret.type = TypeDesc( "const int" ); } else { ret.type = tag.attribute( "enum" ).asString(); if ( ret.type->name().isEmpty() ) ret.type = TypeDesc( "const int" ); } ret.decl.name = tag.name(); ret.decl.comment = tag.comment(); tag.getStartPosition( &ret.decl.startLine, &ret.decl.startCol ); tag.getEndPosition( &ret.decl.endLine, &ret.decl.endCol ); ret.decl.file = tag.fileName(); } else if ( tag.kind() == Tag::Kind_Class && ( type & MemberInfo::NestedType ) ) { //if( tag.hasSpecializationDeclaration() ) { //Choose another tag(the main class, not a specialization). bool hasSpecializationDeclaration = tag.hasSpecializationDeclaration(); bool isIncluded = name.includeFiles()[tag.fileName()]; if ( hasSpecializationDeclaration || !isIncluded ) { for ( TQValueList::const_iterator it = tags.begin(); it != tags.end(); ++it ) { if ( (*it).kind() == Tag::Kind_Class && !(*it).hasSpecializationDeclaration() ) { if ( name.includeFiles()[(*it).fileName()] ) { tag = *it; isIncluded = true; hasSpecializationDeclaration = false; } else if ( hasSpecializationDeclaration ) { tag = *it; hasSpecializationDeclaration = false; isIncluded = false; } if ( isIncluded && !hasSpecializationDeclaration ) break; } } } //only accept non-specialized classes if ( !tag.hasSpecializationDeclaration() ) { ret.setBuildInfo( new CatalogBuildInfo( tag, name, TypePointer( this ) ) ); ret.memberType = MemberInfo::NestedType; ret.type = name; } } else if ( tag.kind() == Tag::Kind_Typedef && ( type & MemberInfo::Typedef ) ) { ret.memberType = MemberInfo::Typedef; ret.type = tagType( tag ); ret.decl.name = tag.name(); ret.decl.comment = tag.comment(); tag.getStartPosition( &ret.decl.startLine, &ret.decl.startCol ); tag.getEndPosition( &ret.decl.endLine, &ret.decl.endCol ); ret.decl.file = tag.fileName(); } else if ( tag.kind() == Tag::Kind_Enum && ( type & MemberInfo::Typedef ) ) { ret.memberType = MemberInfo::Typedef; ret.type = TypeDesc( "const int" ); ret.decl.name = tag.name(); ret.decl.comment = tag.comment(); tag.getStartPosition( &ret.decl.startLine, &ret.decl.startCol ); tag.getEndPosition( &ret.decl.endLine, &ret.decl.endCol ); ret.decl.file = tag.fileName(); } else if ( (tag.kind() == Tag::Kind_FunctionDeclaration || tag.kind() == Tag::Kind_Function) && ( type & MemberInfo::Function ) ) { ret.memberType = MemberInfo::Function; ret.type = tagType( tag ); ret.type->increaseFunctionDepth(); ret.setBuildInfo( new SimpleTypeCatalogFunction::CatalogFunctionBuildInfo( tags, name, TypePointer( this ) ) ); } else if ( tag.kind() == Tag::Kind_Namespace && ( type & MemberInfo::Namespace ) ) { ret.setBuildInfo( new CatalogBuildInfo( tag , name, TypePointer( this ) ) ); ret.memberType = MemberInfo::Namespace; ret.type = name; } ///Check if it is a template-name //if( !ret.type) ret.memberType = MemberInfo::NotFound; //constructor.. if( ret.memberType == MemberInfo::Function || ret.memberType == MemberInfo::Variable || ret.memberType == MemberInfo::Template || ret.memberType == MemberInfo::Typedef || ret.memberType == MemberInfo::NestedType ) { //For redirected types it is necessary to add the include-files of the context they were searched in. //That is not quite correct, but it makes sure that at least the same namespace-aliases will be activated while the search for the type. ret.type->addIncludeFiles( name.includeFiles() ); } chooseSpecialization( ret ); return ret; } Tag SimpleTypeCatalog::findSubTag( const TQString& name ) { if ( name.isEmpty() ) return Tag(); TQValueList args; TQTime t; t.start(); args << Catalog::QueryArgument( "scope", specializedScope() ); args << Catalog::QueryArgument( "name", name ); TQValueList tags( cppCompletionInstance->m_repository->query( args ) ); if ( ! tags.isEmpty() ) { //ifVerbose( dbg() << "findTag: \"" << str() << "\": tag \"" << name << "\" found " << endl ); return tags.front(); } else { //ifVerbose( dbg() << "findTag: \"" << str() << "\": tag \"" << name << "\" not found " << endl ); return Tag(); } } TQValueList SimpleTypeCatalog::getBaseClassList( ) { if ( scope().isEmpty() ) return TQValueList(); return cppCompletionInstance->m_repository->getBaseClassList( scope().join("::") + specialization() ); } void SimpleTypeCatalog::initFromTag() { TQStringList l = m_tag.scope(); l << m_tag.name(); setScope( l ); } void SimpleTypeCatalog::init() { if ( !scope().isEmpty() ) { TQStringList l = scope(); TQStringList cp = l; cp.pop_back(); setScope( cp ); m_tag = findSubTag( l.back() ); setScope( l ); //initFromTag( ); ///must not be done, because it may initialize to wrong namespaces etc. } } DeclarationInfo SimpleTypeCatalog::getDeclarationInfo() { DeclarationInfo ret; ret.name = fullTypeResolved(); if ( m_tag ) { ret.file = m_tag.fileName(); m_tag.getStartPosition( &ret.startLine, &ret.startCol ); m_tag.getEndPosition( &ret.endLine, &ret.endCol ); ret.comment = m_tag.comment(); } return ret; } TQStringList SimpleTypeCatalog::getBaseStrings() { Debug d( "#getbases#" ); if ( !d || !safetyCounter ) { //ifVerbose( dbg() << "\"" << str() << "\": recursion to deep while getting bases" << endl ); return TQStringList(); } TQStringList ret; TQMap bases; // try with parentsc TQTime t; t.restart(); TQValueList parents( getBaseClassList() ); TQValueList::Iterator it = parents.begin(); while ( it != parents.end() ) { Tag & tag = *it; ++it; CppBaseClass info( tag ); bases[ info.baseClass() ] = true; } return bases.keys(); } SimpleTypeImpl::TemplateParamInfo SimpleTypeCatalog::getTemplateParamInfo() { TemplateParamInfo ret; if ( m_tag ) { if ( m_tag.hasAttribute( "tpl" ) ) { TQStringList l = m_tag.attribute( "tpl" ).asStringList(); TypeDesc::TemplateParams templateParams = m_desc.templateParams(); uint pi = 0; TQStringList::const_iterator it = l.begin(); while ( it != l.end() ) { TemplateParamInfo::TemplateParam curr; curr.name = *it; curr.number = pi; ++pi; ++it; if ( it != l.end() ) { curr.def = *it; ++it; } if ( pi < templateParams.count() ) curr.value = *templateParams[pi]; ret.addParam( curr ); }; } } return ret; } const LocateResult SimpleTypeCatalog::findTemplateParam( const TQString& name ) { if ( m_tag ) { if ( m_tag.hasAttribute( "tpl" ) ) { TQStringList l = m_tag.attribute( "tpl" ).asStringList(); ///we need the index, so count the items through uint pi = 0; TQStringList::const_iterator it = l.begin(); while ( it != l.end() && *it != name ) { ++pi; ++it; if ( it != l.end() ) ++it; }; TypeDesc::TemplateParams templateParams = m_desc.templateParams(); if ( it != l.end() && pi < templateParams.count() ) { return *templateParams[pi]; } else { if ( it != l.end() && *it == name && !(*it).isEmpty()) { ++it; if ( it != l.end() && !(*it).isEmpty() ) { ifVerbose( dbg() << "using default-template-type " << *it << " for " << name << endl ); return TypeDesc( *it ); ///return default-parameter } } } } } return LocateResult(); } //SimpleTypeCatalog::CatalogBuildInfo implementation TypePointer SimpleTypeCatalog::CatalogBuildInfo::build() { if ( !m_tag ) return TypePointer(); else { TypePointer tp = new SimpleTypeCachedCatalog( m_tag ); tp->parseParams( m_desc ); if ( m_parent ) tp->setParent( m_parent->bigContainer() ); return tp; } } // kate: indent-mode csands; tab-width 4;