You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/languages/cpp/simpletypefunction.cpp

725 lines
25 KiB

/***************************************************************************
copyright : (C) 2006 by David Nolden
email : david.nolden.kdevelop@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 "simpletypefunction.h"
#include "safetycounter.h"
#include "simpletypenamespace.h"
extern SafetyCounter safetyCounter;
extern CppCodeCompletion* cppCompletionInstance;
HashedStringSet getIncludeFiles( const ItemDom& item ) {
if ( item ) {
FileDom f = item->file();
if ( f ) {
ParseResultPointer p = f->parseResult();
if ( p ) {
ParsedFilePointer pp = dynamic_cast<ParsedFile*>( p.data() );
if ( pp ) {
return pp->includeFiles();
}
}
}
}
return HashedStringSet();
}
//SimpleTypeFunctionInterface implementation
TQString SimpleTypeFunctionInterface::signature() {
TQString sig = "( ";
SimpleTypeImpl* asType = dynamic_cast<SimpleTypeImpl*>( this );
TQStringList argDefaults = getArgumentDefaults();
TQStringList argNames = getArgumentNames();
TQValueList<TypeDesc> argTypes = getArgumentTypes();
TQValueList<LocateResult> argRealTypes;
if ( asType ) {
for ( TQValueList<TypeDesc>::iterator it = argTypes.begin(); it != argTypes.end(); ++it ) {
argRealTypes << asType->locateDecType( *it );
}
}
TQStringList::iterator def = argDefaults.begin();
TQStringList::iterator name = argNames.begin();
TQValueList<LocateResult>::iterator realType = argRealTypes.begin();
while ( realType != argRealTypes.end() ) {
if ( sig != "( " )
sig += ", ";
sig += ( *realType )->fullNameChain();
++realType;
if ( name != argNames.end() ) {
if ( !( *name ).isEmpty() ) sig += " " + *name;
++name;
}
if ( def != argDefaults.end() && !( *def ).isEmpty() ) {
sig += " = " + *def;
++def;
}
}
sig += " )";
return sig;
}
bool SimpleTypeFunctionInterface::containsUndefinedTemplateParam( TypeDesc& desc, SimpleTypeImpl::TemplateParamInfo& paramInfo ) {
TypeDesc::TemplateParams& pm = desc.templateParams();
SimpleTypeImpl::TemplateParamInfo::TemplateParam t;
if ( pm.isEmpty() && paramInfo.getParam( t, desc.name() ) )
if ( !t.value ) return true;
if ( desc.next() )
if ( containsUndefinedTemplateParam( *desc.next(), paramInfo ) )
return true;
for ( TypeDesc::TemplateParams::iterator it = pm.begin(); it != pm.end(); ++it ) {
if ( containsUndefinedTemplateParam( **it, paramInfo ) ) return true;
}
return false;
}
void SimpleTypeFunctionInterface::resolveImplicitTypes( TypeDesc& argType, TypeDesc& gottenArgType, SimpleTypeImpl::TemplateParamInfo& paramInfo ) {
if ( argType.templateParams().isEmpty() ) { ///Template-types may not be templates.
SimpleTypeImpl::TemplateParamInfo::TemplateParam p;
if ( paramInfo.getParam( p, argType.name() ) && !p.value ) {
ifVerbose( dbg() << "choosing \"" << gottenArgType.fullNameChain() << "\" as implicit template-parameter for \"" << argType.name() << "\"" << endl );
p.value = gottenArgType;
p.value.makePrivate();
for ( int d = 0; d < argType.totalPointerDepth(); d++ )
p.value.setTotalPointerDepth( p.value.totalPointerDepth() - 1 );
paramInfo.addParam( p );
}
} else {
if ( argType.name() == gottenArgType.name() )
resolveImplicitTypes( argType.templateParams(), gottenArgType.templateParams(), paramInfo );
}
}
void SimpleTypeFunctionInterface::resolveImplicitTypes( TypeDesc::TemplateParams& argTypes, TypeDesc::TemplateParams& gottenArgTypes, SimpleTypeImpl::TemplateParamInfo& paramInfo ) {
TypeDesc::TemplateParams::iterator it = argTypes.begin();
TypeDesc::TemplateParams::iterator it2 = gottenArgTypes.begin();
while ( it != argTypes.end() && it2 != gottenArgTypes.end() ) {
resolveImplicitTypes( **it, **it2, paramInfo );
++it;
++it2;
}
}
void SimpleTypeFunctionInterface::resolveImplicitTypes( TQValueList<TypeDesc>& argTypes, TQValueList<TypeDesc>& gottenArgTypes, SimpleTypeImpl::TemplateParamInfo& paramInfo ) {
TQValueList<TypeDesc>::iterator it = argTypes.begin();
TQValueList<TypeDesc>::iterator it2 = gottenArgTypes.begin();
while ( it != argTypes.end() && it2 != gottenArgTypes.end() ) {
resolveImplicitTypes( *it, *it2, paramInfo );
++it;
++it2;
}
}
void SimpleTypeFunctionInterface::appendNextFunction( SimpleType func ) {
Debug d( "#fapp#" );
if ( !func || !d ) return;
if (( SimpleTypeImpl* ) func.get() == ( SimpleTypeImpl* ) this ) return;
if ( m_nextFunction && m_nextFunction->asFunction() ) {
m_nextFunction->asFunction()->appendNextFunction( func );
} else {
m_nextFunction = func;
}
}
//SimpleTypeCodeModel implementation
void SimpleTypeCodeModel::addAliasesTo( SimpleTypeNamespace* ns ) {
const NamespaceModel* m = dynamic_cast<const NamespaceModel*>( m_item.data() );
if ( m ) {
const NamespaceModel::NamespaceAliasModelList& namespaceAliases = m->namespaceAliases();
const NamespaceModel::NamespaceImportModelList& namespaceImports = m->namespaceImports();
for ( NamespaceModel::NamespaceAliasModelList::const_iterator it = namespaceAliases.begin(); it != namespaceAliases.end(); ++it ) {
HashedStringSet searchFiles;
FileDom d = m->codeModel()->fileByName( it->fileName().str() );
ParsedFilePointer p = dynamic_cast<ParsedFile*>( d->parseResult().data() );
if ( p ) {
searchFiles = p->includeFiles();
} else {
searchFiles = HashedStringSet( HashedString( it->fileName() ) );
}
TypeDesc ds( it->aliasName() );
ds.setIncludeFiles( searchFiles );
ns->addAliasMap( it->name(), ds, HashedString( it->fileName() ), true, false, bigContainer() );
}
for ( NamespaceModel::NamespaceImportModelList::const_iterator it = namespaceImports.begin(); it != namespaceImports.end(); ++it ) {
HashedStringSet searchFiles;
FileDom d = m->codeModel()->fileByName( it->fileName().str() );
ParsedFilePointer p = dynamic_cast<ParsedFile*>( d->parseResult().data() );
if ( p ) {
searchFiles = p->includeFiles();
} else {
searchFiles = HashedStringSet( HashedString( it->fileName() ) );
}
TypeDesc ds( it->name() );
ds.setIncludeFiles( searchFiles );
ns->addAliasMap( TypeDesc(), ds, HashedString( it->fileName() ), true, false, bigContainer() );
}
}
}
SimpleTypeCodeModel::SimpleTypeCodeModel( ItemDom& item ) : m_item( item ) {
CodeModelItem* i = & ( *item );
FunctionModel* m = dynamic_cast<FunctionModel*>( i );
ClassModel* c = dynamic_cast<ClassModel*>( i );
if ( m ) {
TQStringList l = m->scope();
l << m->name();
setScope( l );
return;
}
if ( c ) {
TQStringList l = c->scope();
l << c->name();
setScope( l );
return;
}
ifVerbose( dbg() << "code-model-item has an unsupported type: " << i->name() << endl );
}
ItemDom SimpleTypeCodeModel::locateModelContainer( class CodeModel* m, TypeDesc t, ClassDom cnt ) {
if ( !cnt ) {
if ( m->globalNamespace() ) {
cnt = model_cast<ClassDom> ( m->globalNamespace() );
} else {
return ItemDom();
}
}
if ( t ) {
if ( cnt->hasClass( t.name() ) ) {
ClassList l = cnt->classByName( t.name() );
if ( !l.isEmpty() ) {
if ( t.next() )
return locateModelContainer( m, *t.next(), l.front() );
else
return model_cast<ItemDom> ( l.front() );
}
}
NamespaceModel* ns = dynamic_cast<NamespaceModel*>( & ( *cnt ) );
if ( ns ) {
NamespaceDom n = ns->namespaceByName( t.name() );
if ( t.next() )
return locateModelContainer( m, *t.next(), model_cast<ClassDom> ( n ) );
else
return model_cast<ItemDom> ( n );
}
}
return ItemDom();
}
///Until header-parsing is implemented, this tries to find the class that is most related to this item
/*ClassDom SimpleTypeCodeModel::pickMostRelated( ClassList lst, TQString fn ) {
if( lst.isEmpty() ) return ClassDom();
ClassDom best = lst.front();
uint bestMatch = 0;
//kdDebug() << "searching most related to " << fn << endl;
for( ClassList::iterator it = lst.begin(); it != lst.end(); ++it ) {
if( !(*it)->getSpecializationDeclaration().isEmpty() ) continue; ///Don't consider specialized classes
//kdDebug() << "comparing " << (*it)->fileName() << endl;
TQString str = (*it)->fileName();
uint len = str.length();
if( fn.length() < len ) len = fn.length();
uint matchLen = 0;
for( uint a = 0; a < len; a++ ) {
if( str[a] == fn[a] )
matchLen++;
else
break;
}
if( matchLen > bestMatch ) {
//kdDebug() << "picking " << str << endl;
bestMatch = matchLen;
best = *it;
}
}
//kdDebug() << "picked " << best->fileName() << endl;
if( !best->getSpecializationDeclaration().isEmpty() ) best = 0; ///only accept non-specialized classes
return best;
}*/
/*TQValueList<TypePointer> SimpleTypeCodeModel::findSpecializations( const TQString& name ) {
ClassModel* klass = dynamic_cast<ClassModel*> ( & (*m_item) );
if( !klass ) {
ifVerbose( dbg() << "\"" << str() << "\": search for member " << name.name() << " unsuccessful because the own type is invalid" << endl );
return TQValueList<TypePointer>();
}
ClassList l = klass->classByName( name.name() );
if( !l.isEmpty() ) {
ClassDom i = pickMostRelated( l, globalCurrentFile );
if( i ) {
ret.setBuildInfo( new CodeModelBuildInfo( model_cast<ItemDom>( i ), name, TypePointer( this ) ) );
ret.memberType = MemberInfo::NestedType;
ret.type = name;
}
}
return TQValueList<TypePointer>();
}*/
TQValueList<TypePointer> SimpleTypeCodeModel::getMemberClasses( const TypeDesc& name ) {
TQValueList<TypePointer> ret;
if ( !m_item ) return ret;
ClassModel* klass = dynamic_cast<ClassModel*>( & ( *m_item ) );
if ( !klass ) {
ifVerbose( dbg() << "\"" << str() << "\": search for member " << name.name() << " unsuccessful because the own type is invalid" << endl );
return ret;
}
ClassList l = klass->classByName( name.name() );
if ( !l.isEmpty() ) {
for ( ClassList::iterator it = l.begin(); it != l.end(); ++it ) {
CodeModelBuildInfo b( model_cast<ItemDom> ( *it ), name, TypePointer( this ) );
TypePointer r = b.build();
if ( r )
ret << r;
}
}
return ret;
}
template<class Item>
Item pickMostRelated( const HashedStringSet& includeFiles, const TQValueList<Item>& list ) {
if ( list.isEmpty() ) return Item();
for ( typename TQValueList<Item>::const_iterator it = list.begin(); it != list.end(); ++it ) {
if ( includeFiles[( *it )->fileName()] )
return *it;
}
return list.front();
}
template<>
ClassDom pickMostRelated( const HashedStringSet& includeFiles, const TQValueList<ClassDom>& list ) {
if ( list.isEmpty() ) return ClassDom(); ///@todo the current file must be preferred
for ( TQValueList<ClassDom>::const_iterator it = list.begin(); it != list.end(); ++it ) {
if ( !( *it )->getSpecializationDeclaration().isEmpty() ) continue; ///Don't consider specialized classes
if ( includeFiles[( *it )->fileName()] )
return *it;
}
if ( !list.front()->getSpecializationDeclaration().isEmpty() ) return ClassDom(); ///Don't consider specialized classes
return list.front();
}
SimpleTypeImpl::MemberInfo SimpleTypeCodeModel::findMember( TypeDesc name , MemberInfo::MemberType type ) {
MemberInfo ret;
ret.name = name.name();
ret.memberType = MemberInfo::NotFound;
if ( !name || !m_item ) return ret;
ClassModel* klass = dynamic_cast<ClassModel*>( & ( *m_item ) );
if ( !klass ) {
ifVerbose( dbg() << "\"" << str() << "\": search for member " << name.name() << " unsuccessful because the own type is invalid" << endl );
return ret;
}
NamespaceModel* ns = dynamic_cast<NamespaceModel*>( klass );
if ( klass->hasVariable( name.name() ) && ( type & MemberInfo::Variable ) ) {
ret.memberType = MemberInfo::Variable;
VariableDom d = klass->variableByName( name.name() );
if ( d ) {
ret.type = d->type();
ret.type->setIncludeFiles( HashedString( d->fileName() ) );
ret.decl.name = d->name();
ret.decl.file = d->fileName();
ret.decl.comment = d->comment();
d->getStartPosition( &ret.decl.startLine, &ret.decl.startCol );
d->getEndPosition( &ret.decl.endLine, &ret.decl.endCol );
}
} else if ( klass->hasTypeAlias( name.name() ) && ( type & MemberInfo::Typedef ) ) {
ret.memberType = MemberInfo::Typedef;
TypeAliasList li = klass->typeAliasByName( name.name() );
TypeAliasDom a = pickMostRelated( name.includeFiles(), li );
if ( a ) {
ret.type = a->type();
ret.type->setIncludeFiles( getIncludeFiles( a.data() ) );
ret.decl.name = a->name();
ret.decl.file = a->fileName();
ret.decl.comment = a->comment();
a->getStartPosition( &ret.decl.startLine, &ret.decl.startCol );
a->getEndPosition( &ret.decl.endLine, &ret.decl.endCol );
}
} else if ( klass->hasEnum( name.name() ) && ( type & MemberInfo::Typedef ) ) {
ret.memberType = MemberInfo::Typedef;
EnumDom e = klass->enumByName( name.name() );
ret.type = TypeDesc( "const int" );
ret.type->setIncludeFiles( HashedString( e->fileName() ) );
ret.decl.name = e->name();
ret.decl.file = e->fileName();
ret.decl.comment = e->comment();
e->getStartPosition( &ret.decl.startLine, &ret.decl.startCol );
e->getEndPosition( &ret.decl.endLine, &ret.decl.endCol );
} else if ( klass->hasClass( name.name() ) && ( type & MemberInfo::NestedType ) ) {
ClassList l = klass->classByName( name.name() );
if ( !l.isEmpty() ) {
ClassDom i = pickMostRelated( name.includeFiles(), l );
if ( i ) {
ret.setBuildInfo( new CodeModelBuildInfo( model_cast<ItemDom> ( i ), name, TypePointer( this ) ) );
ret.memberType = MemberInfo::NestedType;
ret.type = name;
ret.type->setIncludeFiles( HashedString( i->fileName() ) );
}
}
} else if ( klass->hasFunction( name.name() ) && ( type & MemberInfo::Function ) ) {
ret.memberType = MemberInfo::Function;
FunctionList l = klass->functionByName( name.name() );
if ( !l.isEmpty() && l.front() ) {
ret.setBuildInfo( new SimpleTypeCodeModelFunction::CodeModelFunctionBuildInfo( l, name , TypePointer( this ) ) );
ret.type = l.front()->resultType();
ret.type->setIncludeFiles( HashedString( l.front()->fileName() ) );
ret.type->increaseFunctionDepth();
}
} else if ( ns && ns->hasNamespace( name.name() ) && ( type & MemberInfo::Namespace ) ) {
NamespaceDom n = ns->namespaceByName( name.name() );
ret.setBuildInfo( new CodeModelBuildInfo( model_cast<ItemDom> ( n ), name, TypePointer( this ) ) );
ret.memberType = MemberInfo::Namespace;
ret.type = name;
//ret.type->setIncludeFiles( d->fileName() );
} else if ( klass->hasFunctionDefinition( name.name() ) && ( type & MemberInfo::Function ) ) {
FunctionDefinitionList l = klass->functionDefinitionByName( name.name() );
for ( FunctionDefinitionList::iterator it = l.begin(); it != l.end(); ++it ) {
if ( !( *it )->scope().isEmpty() && ( *it )->scope() != scope() ) continue; ///Only use definitions with empty scope or that are within this class
ret.setBuildInfo( new SimpleTypeCodeModelFunction::CodeModelFunctionBuildInfo( l, name, TypePointer( this ) ) );
ret.type = l.front()->resultType();
ret.type->setIncludeFiles( HashedString(( *it )->fileName() ) );
ret.type->increaseFunctionDepth();
ret.memberType = MemberInfo::Function;
break;
}
}
if ( ret.memberType == MemberInfo::NotFound ) {
if ( type & MemberInfo::Template ) {
LocateResult s = findTemplateParam( name.name() );
if ( s ) {
ret.memberType = MemberInfo::Template;
ret.type = s;
if ( m_item )
ret.type->setIncludeFiles( getIncludeFiles( m_item.data() ) );
ret.decl.name = name.name();
if ( m_item ) {
ret.decl.file = m_item->fileName();
m_item->getStartPosition( &ret.decl.startLine, &ret.decl.startCol );
m_item->getEndPosition( &ret.decl.endLine, &ret.decl.endCol );
}
}
}
}
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,
//Which is necessary because the alias is parented by exactly this class.
ret.type->addIncludeFiles( name.includeFiles() );
}
chooseSpecialization( ret );
return ret;
}
bool SimpleTypeCodeModel::findItem() {
TQString key = str();
m_item = locateModelContainer( cppCompletionInstance->m_pSupport->codeModel(), str() );
return ( bool ) m_item;
}
void SimpleTypeCodeModel::init() {
if ( scope().isEmpty() ) {
m_item = cppCompletionInstance->m_pSupport->codeModel() ->globalNamespace();
} else {
findItem();
}
}
DeclarationInfo SimpleTypeCodeModel::getDeclarationInfo() {
DeclarationInfo ret;
ItemDom i = item();
ret.name = fullTypeResolved();
if ( i ) {
ret.file = i->fileName();
i->getStartPosition( &ret.startLine, &ret.startCol );
i->getEndPosition( &ret.endLine, &ret.endCol );
ret.comment = i->comment();
}
return ret;
}
TQString SimpleTypeCodeModel::specialization() const {
const ClassModel* klass = dynamic_cast<const ClassModel*>( m_item.data() );
if ( !klass ) return TQString();
return klass->getSpecializationDeclaration();
}
SimpleTypeImpl::TemplateParamInfo SimpleTypeCodeModel::getTemplateParamInfo() {
TemplateParamInfo ret;
if ( m_item ) {
TemplateModelItem* ti = dynamic_cast<TemplateModelItem*>( & ( *m_item ) );
TypeDesc::TemplateParams& templateParams = m_desc.templateParams();
TemplateModelItem::ParamMap m = ti->getTemplateParams();
for ( uint a = 0; a < m.size(); a++ ) {
TemplateParamInfo::TemplateParam t;
t.number = a;
t.name = m[a].first;
t.def = m[a].second;
if ( templateParams.count() > a )
t.value = *templateParams[a];
ret.addParam( t );
}
}
return ret;
}
const LocateResult SimpleTypeCodeModel::findTemplateParam( const TQString& name ) {
if ( m_item ) {
TemplateModelItem* ti = dynamic_cast<TemplateModelItem*>( & ( *m_item ) );
TypeDesc::TemplateParams& templateParams = m_desc.templateParams();
int pi = ti->findTemplateParam( name );
if ( pi != -1 && ( int ) templateParams.count() > pi ) {
return *templateParams[pi];
} else {
if ( pi != -1 && !ti->getParam( pi ).second.isEmpty() ) {
TQString def = ti->getParam( pi ).second;
ifVerbose( dbg() << "\"" << str() << "\": using default-template-parameter \"" << def << "\" for " << name << endl );
return TypeDesc( def );
} else if ( pi != -1 ) {
ifVerbose( dbg() << "\"" << str() << "\": template-type \"" << name << "\" has no pameter! " << endl );
}
}
}
return LocateResult();
}
TQStringList SimpleTypeCodeModel::getBaseStrings() {
Debug d( "#getbases#" );
if ( !d || !safetyCounter ) {
//ifVerbose( dbg() << "\"" << str() << "\": recursion to deep while getting bases" << endl );
return TQStringList();
}
TQStringList ret;
ClassModel* klass;
if ( !m_item || ( klass = dynamic_cast<ClassModel*>( & ( *m_item ) ) ) == 0 ) return ret;
TQStringList parents = klass->baseClassList();
for ( TQStringList::Iterator it = parents.begin(); it != parents.end(); ++it ) {
ret << *it;
}
return ret;
}
TypePointer SimpleTypeCodeModel::CodeModelBuildInfo::build() {
TypePointer tp = new SimpleTypeCachedCodeModel( m_item );
tp->parseParams( m_desc );
if ( m_parent ) tp->setParent( m_parent->bigContainer() );
return tp;
}
//SimpleTypeCodeModelFunction implementation
TypeDesc SimpleTypeCodeModelFunction::getReturnType() {
if ( item() ) {
IncludeFiles files;
if( parent() )
files = parent()->getFindIncludeFiles();
if ( FunctionModel* m = dynamic_cast<FunctionModel*>( & ( *item() ) ) ) {
TypeDesc d = m->resultType();
d.setIncludeFiles( files );
return d;
}
}
return TypeDesc();
}
bool SimpleTypeCodeModelFunction::isConst() {
if ( asFunctionModel() )
return asFunctionModel()->isConstant();
return false;
}
TQValueList<TypeDesc> SimpleTypeCodeModelFunction::getArgumentTypes() {
TQValueList<TypeDesc> ret;
if ( item() ) {
IncludeFiles files;
if( parent() )
files = parent()->getFindIncludeFiles();
if ( FunctionModel* m = dynamic_cast<FunctionModel*>( & ( *item() ) ) ) {
ArgumentList l = m->argumentList();
for ( ArgumentList::iterator it = l.begin(); it != l.end(); ++it ) {
ret << TypeDesc(( *it )->type() );
ret.back().setIncludeFiles( files );
}
}
}
return ret;
}
TQStringList SimpleTypeCodeModelFunction::getArgumentNames() {
TQStringList ret;
if ( item() ) {
if ( FunctionModel* m = dynamic_cast<FunctionModel*>( & ( *item() ) ) ) {
ArgumentList l = m->argumentList();
for ( ArgumentList::iterator it = l.begin(); it != l.end(); ++it )
ret << ( *it )->name();
}
}
return ret;
}
TQStringList SimpleTypeCodeModelFunction::getArgumentDefaults() {
TQStringList ret;
if ( item() ) {
if ( FunctionModel* m = dynamic_cast<FunctionModel*>( & ( *item() ) ) ) {
ArgumentList l = m->argumentList();
for ( ArgumentList::iterator it = l.begin(); it != l.end(); ++it )
ret << ( *it )->defaultValue();
}
}
return ret;
}
//SimpleTypeCodeModelFunction::CodeModelFunctionBuildInfo implementation
SimpleTypeCodeModelFunction::CodeModelFunctionBuildInfo::CodeModelFunctionBuildInfo( FunctionDefinitionList items, TypeDesc& desc, TypePointer parent ) : m_desc( desc ), m_parent( parent ) {
for ( FunctionDefinitionList::iterator it = items.begin(); it != items.end(); ++it ) {
m_items << model_cast<FunctionDom> ( *it );
}
}
TypePointer SimpleTypeCodeModelFunction::CodeModelFunctionBuildInfo::build() {
TQValueList<TypePointer> ret;
TypePointer last;
for ( FunctionList::iterator it = m_items.begin(); it != m_items.end(); ++it ) {
TypePointer tp = new SimpleTypeCodeModelFunction( model_cast<ItemDom> ( *it ) );
tp->takeTemplateParams( m_desc );
tp->descForEdit().increaseFunctionDepth();
tp->setParent( m_parent->bigContainer() );
if ( last && last->asFunction() ) last->asFunction()->appendNextFunction( SimpleType( tp ) );
last = tp;
ret << tp;
}
if ( ret.isEmpty() ) {
ifVerbose( dbg() << "error" << endl );
return TypePointer();
} else
return ret.front();
}
//SimpleTypeCatalogFunction implementation
TypeDesc SimpleTypeCatalogFunction::getReturnType() {
if ( tag() ) {
return tagType( tag() );
}
return TypeDesc();
}
bool SimpleTypeCatalogFunction::isConst() {
Tag t = tag();
CppFunction<Tag> tagInfo( t );
return tagInfo.isConst();
}
TQStringList SimpleTypeCatalogFunction::getArgumentNames() {
TQStringList ret;
Tag t = tag();
CppFunction<Tag> tagInfo( t );
return tagInfo.argumentNames();
}
TQValueList<TypeDesc> SimpleTypeCatalogFunction::getArgumentTypes() {
TQValueList<TypeDesc> ret;
Tag t = tag();
CppFunction<Tag> tagInfo( t );
TQStringList arguments = tagInfo.arguments();
for ( TQStringList::iterator it = arguments.begin(); it != arguments.end(); ++it )
ret << TypeDesc( *it );
return ret;
}
//SimpleTypeCatalogFunction::CatalogFunctionBuildInfo implementation
TypePointer SimpleTypeCatalogFunction::CatalogFunctionBuildInfo::build() {
TQValueList<TypePointer> ret;
TypePointer last;
for ( TQValueList<Tag>::iterator it = m_tags.begin(); it != m_tags.end(); ++it ) {
TypePointer tp = new SimpleTypeCatalogFunction( *it );
tp->takeTemplateParams( m_desc );
tp->descForEdit().increaseFunctionDepth();
if ( m_parent ) tp->setParent( m_parent->bigContainer() );
if ( last && last->asFunction() ) last->asFunction()->appendNextFunction( SimpleType( tp ) );
last = tp;
ret << tp;
}
if ( ret.isEmpty() ) {
ifVerbose( dbg() << "error" << endl );
return TypePointer();
}
return ret.front();
}