|
|
|
/***************************************************************************
|
|
|
|
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 "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<Catalog::QueryArgument> args;
|
|
|
|
|
|
|
|
///Insert all namespace-imports
|
|
|
|
args << Catalog::QueryArgument( "scope", specializedScope() );
|
|
|
|
args << Catalog::QueryArgument( "kind", Tag::Kind_UsingDirective );
|
|
|
|
|
|
|
|
TQValueList<Tag> tags( cppCompletionInstance->m_repository->query( args ) );
|
|
|
|
|
|
|
|
for ( TQValueList<Tag>::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<Tag>::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<TypePointer> SimpleTypeCatalog::getMemberClasses( const TypeDesc& name ) {
|
|
|
|
TQValueList<TypePointer> ret;
|
|
|
|
|
|
|
|
TQValueList<Catalog::QueryArgument> args;
|
|
|
|
|
|
|
|
args << Catalog::QueryArgument( "scope", specializedScope() );
|
|
|
|
args << Catalog::QueryArgument( "name", name.name() );
|
|
|
|
|
|
|
|
TQValueList<Tag> tags( cppCompletionInstance->m_repository->query( args ) );
|
|
|
|
|
|
|
|
for ( TQValueList<Tag>::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<Catalog::QueryArgument> args;
|
|
|
|
|
|
|
|
args << Catalog::QueryArgument( "scope", specializedScope() );
|
|
|
|
args << Catalog::QueryArgument( "name", name.name() );
|
|
|
|
|
|
|
|
TQValueList<Tag> tags( cppCompletionInstance->m_repository->query( args ) );
|
|
|
|
|
|
|
|
if ( tags.isEmpty() ) return ret;
|
|
|
|
|
|
|
|
///skip all using-directives
|
|
|
|
TQValueList<Tag>::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<Tag>::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<Catalog::QueryArgument> args;
|
|
|
|
TQTime t;
|
|
|
|
|
|
|
|
t.start();
|
|
|
|
args << Catalog::QueryArgument( "scope", specializedScope() );
|
|
|
|
args << Catalog::QueryArgument( "name", name );
|
|
|
|
|
|
|
|
TQValueList<Tag> 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<Tag> SimpleTypeCatalog::getBaseClassList( ) {
|
|
|
|
if ( scope().isEmpty() )
|
|
|
|
return TQValueList<Tag>();
|
|
|
|
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<TQString, bool> bases;
|
|
|
|
// try with parentsc
|
|
|
|
TQTime t;
|
|
|
|
t.restart();
|
|
|
|
TQValueList<Tag> parents( getBaseClassList() );
|
|
|
|
|
|
|
|
TQValueList<Tag>::Iterator it = parents.begin();
|
|
|
|
while ( it != parents.end() ) {
|
|
|
|
Tag & tag = *it;
|
|
|
|
++it;
|
|
|
|
|
|
|
|
CppBaseClass<Tag> 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;
|
|
|
|
|