summaryrefslogtreecommitdiffstats
path: root/languages/cpp/simpletype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'languages/cpp/simpletype.cpp')
-rw-r--r--languages/cpp/simpletype.cpp1051
1 files changed, 1051 insertions, 0 deletions
diff --git a/languages/cpp/simpletype.cpp b/languages/cpp/simpletype.cpp
new file mode 100644
index 00000000..e4334ae5
--- /dev/null
+++ b/languages/cpp/simpletype.cpp
@@ -0,0 +1,1051 @@
+/***************************************************************************
+ copyright : (C) 2006 by David Nolden
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "simpletype.h"
+#include "safetycounter.h"
+#include "simpletypefunction.h"
+#include <klocale.h>
+
+QMap<QString, QString> BuiltinTypes::m_types;
+BuiltinTypes builtin; //Needed so BuiltinTypes::BuiltinTypes is called and the types are initialized
+
+BuiltinTypes::BuiltinTypes() {
+ m_types[ "void" ] = i18n( "typeless" );
+ m_types[ "bool" ] = i18n("boolean value, 1 byte, ( \"true\" or \"false\" )");
+ m_types["char" ] = i18n("signed/unsigned character, 1 byte");
+ m_types["signed char" ] = i18n("signed character, 1 byte, ranged -128 to 127");
+ m_types["unsigned char"] = i18n("unsigned character, 1 byte, ranged 0 to 255");
+ m_types["wchar_t"] = i18n("wide character, 2 bytes, ranged 0 to 65.535");
+ m_types["long"] = m_types["long int"] = m_types["int"] = m_types["signed int"] = i18n("signed integer, 4 bytes, ranged -2.147.483.648 to 2.147.483.647");
+ m_types["unsigned"] = m_types["unsigned int"] = i18n("unsigned integer, 4 bytes, ranged 0 to 4.294.967.295");
+ m_types["short"] = m_types["short int"] = i18n("short integer, 2 bytes, ranged -32.768 to 32.768");
+ m_types["unsigned short int"] = i18n("unsigned short integer, 2 bytes, ranged 0 to 65.535");
+ m_types["float"] = i18n("floating point value, 4 bytes, ranged ca. -3,4E+38 to 3,4E+38");
+ m_types["double"] = i18n("double floating point value, 8 bytes, ranged ca. -1,8E+308 to 1,8E+308");
+ m_types["long double"] = i18n("double long floating point value, 10 bytes, ranged ca. -3,4E+4932 to 3,4E+4932");
+ m_types["size_t"] = i18n("unsigned integer, byte-count dependent on operating-system" );
+
+}
+
+bool BuiltinTypes::isBuiltin( const TypeDesc& desc ) {
+ return m_types.find( desc.name() ) != m_types.end();
+}
+
+QString BuiltinTypes::comment( const TypeDesc& desc ) {
+ QMap<QString, QString>::iterator it = m_types.find( desc.name() );
+ if( it != m_types.end() ) {
+ return *it;
+ } else {
+ return QString::null;
+ }
+}
+
+extern SafetyCounter safetyCounter;
+
+TypePointer SimpleType::m_globalNamespace;
+SimpleType::TypeStore SimpleType::m_typeStore;
+SimpleType::TypeStore SimpleType::m_destroyedStore;
+QString globalCurrentFile = "";
+
+//SimpleType implementation
+
+void SimpleType::resolve( Repository rep ) const {
+ if ( !m_resolved ) {
+ if ( m_globalNamespace ) {
+ if ( ( rep == RepoUndefined || rep == RepoBoth ) ) {
+ m_resolved = true;
+ if ( scope().isEmpty() || str().isEmpty() ) {
+ m_type = m_globalNamespace;
+ return ;
+ } else {
+ TypeDesc d( scope().join( "::" ) );
+ d.setIncludeFiles( m_includeFiles );
+ LocateResult t = m_globalNamespace->locateDecType( d );
+ if ( t && t->resolved() ) {
+ m_type = t->resolved();
+ return ;
+ } else {
+ ifVerbose( dbg() << "\"" << scope().join( "::" ) << "\": The type could not be located in the global scope while resolving it" << endl );
+ }
+ }
+ }
+ } else {
+ ifVerbose( dbg() << "warning: no global namespace defined! " << endl );
+ }
+
+ TypePointer cm;
+
+ if ( rep == RepoUndefined || rep == RepoCodeModel ) {
+ if ( !m_type ) {
+ cm = TypePointer( new SimpleTypeCachedCodeModel( scope() ) );
+ } else {
+ cm = TypePointer( new SimpleTypeCachedCodeModel( &( *m_type ) ) );
+ }
+
+ if ( cm->hasNode() || rep == RepoCodeModel ) {
+ if ( cm->hasNode() ) {
+ ifVerbose( dbg() << "resolved \"" << str() << "\" from the code-model" << endl );
+ if ( cm->isNamespace() && rep != RepoCodeModel ) {
+ ifVerbose( dbg() << "\"" << str() << "\": is namespace, resolving proxy" << endl );
+ resolve( RepoBoth );
+ return ;
+ }
+ } else {
+ ifVerbose( dbg() << "forced \"" << str() << "\" to be resolved from code-model" << endl );
+ }
+ m_type = cm;
+ m_resolved = true;
+ return ;
+ }
+ }
+ if ( rep == RepoUndefined || rep == RepoCatalog ) {
+
+ if ( !m_type ) {
+ cm = TypePointer( new SimpleTypeCachedCatalog( scope() ) );
+ } else {
+ cm = TypePointer( new SimpleTypeCachedCatalog( &( *m_type ) ) );
+ }
+
+ if ( cm->hasNode() || rep == RepoCatalog ) {
+ if ( cm->hasNode() ) {
+ ifVerbose( dbg() << "resolved \"" << str() << "\" from the catalog" << endl );
+ if ( cm->isNamespace() && rep != RepoCatalog ) {
+ ifVerbose( dbg() << "\"" << str() << "\": is namespace, resolving proxy" << endl );
+ resolve( RepoBoth );
+ return ;
+ }
+ } else {
+ ifVerbose( dbg() << "forced \"" << str() << "\" to be resolved from catalog" << endl );
+ }
+ m_type = cm;
+ m_resolved = true;
+ return ;
+ }
+ }
+
+ if ( rep == RepoBoth ) {
+ cm = new SimpleTypeCachedNamespace( scope() );
+ m_type = cm;
+ m_resolved = true;
+ return ;
+ }
+
+ m_resolved = true;
+ ifVerbose( dbg() << "could not resolve \"" << m_type->desc().fullNameChain() << "\"" << endl );
+ }
+}
+
+void SimpleType::destroyStore() {
+ resetGlobalNamespace();
+ int cnt = m_typeStore.size();
+ kdDebug( 9007 ) << cnt << "types in type-store before destruction" << endl;
+
+ SafetyCounter s( 30000 );
+ while ( !m_typeStore.empty() && s ) {
+ TypeStore::iterator it = m_typeStore.begin();
+ TypePointer tp = *it;
+ m_destroyedStore.insert( tp );
+ m_typeStore.erase( it );
+ tp->breakReferences();
+ }
+
+ if ( !m_destroyedStore.empty() ) {
+ kdDebug( 9007 ) << "type-store is not empty, " << m_destroyedStore.size() << " types are left over" << endl;
+ for ( TypeStore::iterator it = m_destroyedStore.begin(); it != m_destroyedStore.end(); ++it ) {
+ kdDebug( 9007 ) << "type left: " << ( *it ) ->describe() << endl;
+ }
+ }
+
+ ///move them over so they will be cleared again next time, hoping that they will vanish
+ m_typeStore = m_destroyedStore;
+ m_destroyedStore.clear();
+}
+
+///This does not necessarily make the TypeDesc's private, so before editing them
+///their makePrivate must be called too
+void SimpleType::makePrivate() {
+ m_type = m_type->clone();
+}
+
+const QStringList& SimpleType::scope() const {
+ return m_type -> scope();
+}
+
+const QString SimpleType::str() const {
+ return m_type -> str();
+}
+
+void SimpleType::init( const QStringList& scope, const HashedStringSet& files, Repository rep ) {
+ m_includeFiles = files;
+
+ m_type = TypePointer( new SimpleTypeImpl( scope ) );
+ if ( rep != RepoUndefined )
+ resolve( rep );
+}
+
+SimpleType::SimpleType( ItemDom item ) : m_resolved( true ) {
+ m_type = TypePointer( new SimpleTypeCachedCodeModel( item ) );
+}
+/*
+SimpleType::SimpleType( Tag tag ) : m_resolved(true) {
+ m_type = TypePointer( new SimpleTypeCatalog( tag ) );
+}*/
+//
+//SimpleTypeImpl implementation
+
+QValueList<LocateResult> SimpleTypeImpl::getBases() {
+QValueList<LocateResult> ret;
+ QStringList bases = getBaseStrings();
+ for( QStringList::const_iterator it = bases.begin(); it != bases.end(); ++it ) {
+ TypeDesc d( *it );
+ d.setIncludeFiles( m_findIncludeFiles );
+ LocateResult res = locateDecType( d, LocateBase );
+ //if( res )
+ ret << res;
+ }
+ return ret;
+}
+
+void SimpleTypeImpl::setFindIncludeFiles( const IncludeFiles& files ) {
+ m_findIncludeFiles = files;
+}
+
+IncludeFiles SimpleTypeImpl::getFindIncludeFiles() {
+ return m_findIncludeFiles;
+}
+
+/**
+Searches for a member called "name", considering all types selected through "typ"*/
+SimpleTypeImpl::TypeOfResult SimpleTypeImpl::typeOf( const TypeDesc& name, MemberInfo::MemberType typ ) {
+ Debug d( "#to#" );
+ if ( !d ) {
+ ifVerbose( dbg() << "stopping typeOf-evaluation because the recursion-depth is too high" << endl );
+ return TypeOfResult( LocateResult( TypeDesc( "CompletionError::too_much_recursion" ) ) );
+ }
+ ifVerbose( dbg() << "\"" << str() << "\"------------>: searching for type of member \"" << name.fullNameChain() << "\"" << endl );
+
+ TypeDesc td = resolveTemplateParams( name );
+
+ MemberInfo mem = findMember( td, typ );
+
+ if ( mem ) {
+ mem.type = resolveTemplateParams( mem.type );
+
+ ifVerbose( dbg() << "\"" << str() << "\": found member " << name.fullNameChain() << ", type: " << mem.type->fullNameChain() << endl );
+ if ( mem.memberType == MemberInfo::Function ) {
+ ///For functions, find all functions with the same name, so that overloaded functions can be identified correctly
+ TypePointer ret = mem.build();
+ if ( ret && ret->asFunction() ) {
+ return TypeOfResult( LocateResult( ret->desc() ) );
+ } else {
+ ifVerbose( dbg() << "error, using old function-type-evaluation" << endl );
+
+ TypeDesc d( mem.type );
+ if( m_findIncludeFiles.size() != 0 )
+ d.setIncludeFiles( m_findIncludeFiles );
+ else
+ d.setIncludeFiles( name.includeFiles() );
+
+ return TypeOfResult( locateDecType( d ), mem.decl );
+ }
+ } else if ( mem.memberType == MemberInfo::Variable ) {
+ TypeDesc d( mem.type );
+ if( m_findIncludeFiles.size() != 0 )
+ d.setIncludeFiles( m_findIncludeFiles );
+ else
+ d.setIncludeFiles( name.includeFiles() );
+
+ return TypeOfResult( locateDecType( d ), mem.decl );
+ } else {
+ ifVerbose( dbg() << "while searching for the type of \"" << name.fullNameChain() << "\" in \"" << str() << "\": member has wrong type: \"" << mem.memberTypeToString() << "\"" << endl );
+ return TypeOfResult();
+ }
+ }
+
+ TypeOfResult ret = searchBases( td );
+ if ( !ret ) {
+ ifVerbose( dbg() << "\"" << str() << "\"------------>: failed to resolve the type of member \"" << name.fullNameChain() << "\"" << endl );
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\"------------>: successfully resolved the type of the member \"" << name.fullNameChain() << "\"" << endl );
+ }
+ return ret;
+}
+
+SimpleTypeFunctionInterface* SimpleTypeImpl::asFunction() {
+ return dynamic_cast<SimpleTypeFunctionInterface*> ( this );
+}
+
+QString SimpleTypeImpl::operatorToString( Operator op ) {
+ switch ( op ) {
+ case NoOp:
+ return "NoOp";
+ case IndexOp:
+ return "index-operator";
+ case ArrowOp:
+ return "arrow-operator";
+ case StarOp:
+ return "star-operator";
+ case AddrOp:
+ return "address-operator";
+ case ParenOp:
+ return "paren-operator";
+ default:
+ return QString( "%1" ).arg( ( long ) op );
+ };
+}
+
+LocateResult SimpleTypeImpl::getFunctionReturnType( QString functionName, QValueList<LocateResult> params ) {
+ LocateResult t = typeOf( functionName, MemberInfo::Function ).type;
+ if ( t->resolved() && t->resolved() ->asFunction() ) {
+ return t->resolved() ->applyOperator( ParenOp, params );
+ } else {
+ ifVerbose( dbg() << "error : could not find function \"" << functionName << "\" in \"" << str() << "\"" << endl );
+ return LocateResult();
+ }
+}
+
+LocateResult SimpleTypeImpl::applyOperator( Operator op , QValueList<LocateResult> params ) {
+ Debug d( "#applyn#" );
+ if ( !d || !safetyCounter )
+ return LocateResult();
+
+ ifVerbose( dbg() << "applying operator " << operatorToString( op ) << " to \"" << desc().fullNameChain() << "\"" << endl );
+ LocateResult ret;
+ if ( op == NoOp )
+ return LocateResult( desc() );
+
+ switch ( op ) {
+ case IndexOp:
+ return getFunctionReturnType( "operator [ ]", params );
+ break;
+ case StarOp:
+ return getFunctionReturnType( "operator *", params );
+ break;
+ case ArrowOp:
+ /** Dereference one more because the type must be a pointer */
+ ret = getFunctionReturnType( "operator ->", params );
+ if ( ret->totalPointerDepth() ) {
+ ret->setTotalPointerDepth( ret->totalPointerDepth() - 1 );
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\": " << " \"operator ->\" returns a type with the wrong pointer-depth" << endl );
+ }
+ return ret;
+ break;
+ case ParenOp:
+ /** Dereference one more because the type must be a pointer */
+ return getFunctionReturnType( "operator ( )", params );
+ default:
+ ifVerbose( dbg() << "wrong operator\n" );
+ }
+
+ return LocateResult();
+}
+
+TypeDesc SimpleTypeImpl::replaceTemplateParams( TypeDesc desc, TemplateParamInfo& paramInfo ) {
+ Debug d( "#repl#" );
+ if ( !d || !safetyCounter )
+ return desc;
+
+ TypeDesc ret = desc;
+ if ( !ret.hasTemplateParams() && !ret.next() ) {
+ TemplateParamInfo::TemplateParam t;
+ if ( paramInfo.getParam( t, desc.name() ) ) {
+
+ if ( t.value )
+ ret = t.value;
+ else if ( t.def )
+ ret = t.def;
+
+ if ( ret.name() != desc.name() )
+ ret.setTotalPointerDepth( ret.totalPointerDepth() + desc.totalPointerDepth() );
+ }
+ } else {
+ TypeDesc::TemplateParams& params = ret.templateParams();
+ for ( TypeDesc::TemplateParams::iterator it = params.begin(); it != params.end(); ++it ) {
+ *it = new TypeDescShared( replaceTemplateParams( **it, paramInfo ) );
+ }
+ }
+
+ if ( ret.next() ) {
+ ret.setNext( new TypeDescShared( replaceTemplateParams( *ret.next(), paramInfo ) ) );
+ }
+
+ return ret;
+}
+
+TypeDesc SimpleTypeImpl::resolveTemplateParams( LocateResult desc, LocateMode mode ) {
+ Debug d( "#resd#" );
+ if ( !d || !safetyCounter )
+ return desc;
+
+ LocateResult ret = desc;
+ if ( ret->hasTemplateParams() ) {
+ TypeDesc::TemplateParams & params = ret->templateParams();
+ for ( TypeDesc::TemplateParams::iterator it = params.begin(); it != params.end(); ++it ) {
+ if ( !( *it ) ->resolved() && !( *it ) ->hasFlag( ResolutionTried ) ) {
+ TypeDesc d( **it );
+ if( d.includeFiles().size() == 0 )
+ d.setIncludeFiles( this->getFindIncludeFiles() );
+ *it = locateDecType( d, mode );
+ ( *it ) ->setFlag( ResolutionTried );
+ }
+ }
+ }
+
+ if ( ret->next() ) {
+ ret->setNext( new TypeDescShared( resolveTemplateParams( *ret->next(), mode ) ) );
+ }
+
+ return ret;
+}
+
+class TemplateParamMatch {
+ public:
+ TemplateParamMatch() : m_matched( false ), m_maxDepth( 0 ), m_candidate( 0 ) {}
+
+ TemplateParamMatch( TypePointer candidate, const TypeDesc& params ) : m_matched( false ), m_maxDepth( 0 ), m_candidate( candidate ) {
+ m_candidateParams = candidate->getTemplateParamInfo();
+ TypeDesc specialization( candidate->specialization() );
+
+ TypeDesc cleanParams = params;
+ cleanParams.setName( "" );
+
+ m_matched = matchParameters( specialization, cleanParams );
+
+ if( m_matched ) {
+ //Make sure that all template-parameters were found
+ for( int a = 0; a < m_candidateParams.count(); a++ ) {
+ SimpleTypeImpl::TemplateParamInfo::TemplateParam t;
+ if( m_candidateParams.getParam( t, a ) ) {
+ if( !m_hadParameters.contains( t.name ) ) {
+ m_matched = false;
+ }
+ } else {
+ m_matched = false;
+ }
+ }
+ }
+ }
+
+ ///@todo: use all default-parameters if some are missing
+ ///@todo: also use decoration like "const" or "&" for specialization.
+ bool matchParameters( const TypeDesc& specialization, const LocateResult& params, int depth = 0 ) {
+ if( depth > m_maxDepth ) m_maxDepth = depth;
+
+ if( specialization.name().isEmpty() ) {
+ if( specialization.templateParams().count() != params->templateParams().count() )
+ return false;
+ } else {
+ SimpleTypeImpl::TemplateParamInfo::TemplateParam t;
+ if( m_candidateParams.getParam( t, specialization.name() ) ) {
+ TypeDesc oldValue = t.value;
+
+ //Check if the decoration of the specialization matches the decoration of the arguments, if not we have a mismatch.
+
+ if( specialization.totalPointerDepth() > params->totalPointerDepth() ) {
+ return false; //The decoration does not match the given argument
+ } else {
+ depth += specialization.totalPointerDepth();
+ if( depth > m_maxDepth ) m_maxDepth = depth;
+ }
+
+ //Fill the template-parameter, or compare if the one we already found out matches this one
+ LocateResult val;
+ if( specialization.hasTemplateParams() ) {
+ val = params->decoratedName();
+ } else {
+ val = params; //No more parameters have to be checked, so take the value and return later
+ }
+
+ val->setTotalPointerDepth( val->totalPointerDepth() - specialization.totalPointerDepth() );
+
+ t.value = val;
+
+ if( m_hadParameters.contains( t.name ) && oldValue != t.value ) {
+ return false; ///We have a mismatch, two different values for the same template-parameter.
+ } else {
+ m_candidateParams.addParam( t );
+ m_hadParameters[ t.name ] = val;
+ if( !specialization.hasTemplateParams() ) return true;
+ }
+ } else {
+ if( m_candidate->locateDecType( specialization.decoratedName() )->decoratedName() != params->decoratedName() ) {
+ //We have a mismatch
+ return false;
+ }
+ }
+ }
+
+
+ if( specialization.templateParams().count() != params->templateParams().count() ) {
+ return false; //mismatch in count of template-parameters
+ }
+
+ TypeDesc::TemplateParams::const_iterator specialIt = specialization.templateParams().begin();
+ TypeDesc::TemplateParams::const_iterator paramsIt = params->templateParams().begin();
+
+ while( specialIt != specialization.templateParams().end() && paramsIt != params->templateParams().end() ) {
+ if( !matchParameters( (*specialIt).desc(), (*paramsIt), depth+10 ) ) return false;
+
+ ++paramsIt;
+ ++specialIt;
+ }
+ return true;
+ }
+
+ operator bool() const {
+ return m_matched;
+ }
+
+ ///True if this match is better than the given one
+ bool operator > ( const TemplateParamMatch& rhs ) const {
+ if( !m_matched ) return false;
+ if(!rhs.m_matched ) return true;
+ return m_maxDepth > rhs.m_maxDepth;
+ }
+
+ TypePointer type() {
+ if( m_candidate ) {
+ TypePointer ret = m_candidate->clone();
+ ret->descForEdit().templateParams().clear();
+ for( int a = 0; a < m_candidateParams.count(); a++ ) {
+ SimpleTypeImpl::TemplateParamInfo::TemplateParam tp;
+ if( m_candidateParams.getParam( tp, a ) ) {
+ ret->descForEdit().templateParams().push_back( m_hadParameters[tp.name] );
+ } else {
+ ret->descForEdit().templateParams().push_back( LocateResult() ); //error
+ }
+ }
+ return ret;
+ } else {
+ return 0;
+ }
+ }
+
+ SimpleTypeImpl::TemplateParamInfo& templateParams() {
+ return m_candidateParams;
+ }
+
+ private:
+ TypePointer m_candidate;
+ SimpleTypeImpl::TemplateParamInfo m_candidateParams;
+ QMap<QString, LocateResult> m_hadParameters;
+ bool m_matched;
+ int m_maxDepth;
+};
+
+void SimpleTypeImpl::chooseSpecialization( MemberInfo& member ) {
+
+ if ( member.memberType != MemberInfo::NestedType )
+ return ;
+ if ( !member.type->hasTemplateParams() )
+ return ;
+
+ TypePointer type = member.build();
+
+ if ( !type )
+ return ;
+
+ //Get a list of all candidate-classes
+ TypePointer t = this;
+ if ( m_masterProxy )
+ t = m_masterProxy;
+
+ QValueList<TypePointer> classes = t->getMemberClasses( type->desc() );
+
+ //Find the specialization that fits the given template-parameters the best
+
+ if ( !type->specialization().isEmpty() ) {
+ kdDebug( 9007 ) << "a specialized template-class was suggested as primary class while searching for specialization, search problematic" << endl;
+ //return;
+ } else {
+ TemplateParamInfo params = type->getTemplateParamInfo();
+
+ int dif = params.count() - member.type->templateParams().count();
+
+ if ( dif > 0 ) {
+ //fill up missing template-parameters with their default-parameters, maybe should be done in findMember
+ for ( int a = member.type->templateParams().count(); a < params.count(); a++ ) {
+ LocateResult r;
+ TemplateParamInfo::TemplateParam tp;
+ if ( params.getParam( tp, a ) ) {
+ r = t->locateDecType( tp.value );
+ }
+ member.type->templateParams().push_back( r );
+ }
+ }
+ }
+
+ //now find the class that is most specialized and matches the template-parameters
+
+ TemplateParamMatch bestMatch;
+
+ for ( QValueList<TypePointer>::iterator it = classes.begin(); it != classes.end(); ++it ) {
+ if ( ( *it ) ->specialization().isEmpty() )
+ continue;
+ TemplateParamMatch match( ( *it ), member.type.desc() );
+
+ if ( match > bestMatch )
+ bestMatch = match;
+ }
+
+ if ( bestMatch ) {
+ TypePointer tp = bestMatch.type();
+ if ( tp ) {
+ member.setBuilt( tp );
+ }
+ }
+}
+
+
+LocateResult SimpleTypeImpl::locateType( TypeDesc name , LocateMode mode , int dir , MemberInfo::MemberType typeMask ) {
+ Debug d( "#lo#" );
+ if( BuiltinTypes::isBuiltin( name ) )
+ return name;
+
+ if ( !name || !safetyCounter || !d ) {
+ return desc();
+ }
+ if ( !d ) {
+ ifVerbose( dbg() << "stopping location because the recursion-depth is too high" << endl );
+ return TypeDesc( "CompletionError::too_much_recursion" );
+ }
+ ifVerbose( dbg() << "\(" << uint(this) << ")\"" << str() << "\": locating type \"" << name.fullNameChain() << "\"" << endl );
+ if ( name.resolved() && !name.next() ) {
+ ifVerbose( dbg() << "\"" << desc().fullName() << "\": type \"" << name.fullNameChain() << "\" is already resolved, returning stored instance" << endl );
+ return name;
+ }
+ /*
+ if( name.resolved() && name.length() == name.resolved()->desc().length() ) {
+ ifVerbose( dbg() << "\"" << desc().fullName() << "\": type \"" << name.fullNameChain() << "\" is already resolved, returning stored instance" << endl;
+ SimpleType ret = SimpleType( name.resolved() );
+
+ if( ! (name == ret->desc()) ) {
+ ret.makePrivate(); ///Maybe some small parameters like the pointer-depth were changed, so customize those
+ ret->parseParams( name );
+ }
+
+ return ret;
+ }*/
+ /*
+ //This optimization is now disabled, because it allows following a wrong path.
+ if( name.next() ) {
+ //This is an optimization for better use of the cache: Find the elements separately, so searches
+ //For elements that start with the same scope will be speeded up.
+ LocateResult r = locateType( name.firstType(), mode, dir, typeMask );
+ if( r && r->resolved() && r.locateMode().valid ) {
+ ifVerbose( dbg() << "splitting location" );
+ TypeDesc d( *name.next() );
+ d.setIncludeFiles( name.includeFiles() );
+ return r->resolved()->locateType( d, (LocateMode)r.locateMode().mode, r.locateMode().dir );
+ }
+ }*/
+
+ LocateResult ret = name; ///In case the type cannot be located, this helps to find at least the best match
+ //LocateResult ret;
+
+ TypeDesc first = resolveTemplateParams( name.firstType(), mode );
+
+ MemberInfo mem = findMember( first, typeMask );
+
+ switch ( mem.memberType ) {
+ case MemberInfo::Namespace:
+ if ( mode & ExcludeNamespaces )
+ break;
+ case MemberInfo::NestedType: {
+ if ( mem.memberType == MemberInfo::NestedType && mode & ExcludeNestedTypes )
+ break;
+
+ SimpleType sub;
+ if ( TypePointer t = mem.build() ) {
+ sub = SimpleType( t );
+#ifdef PHYSICAL_IMPORT
+ setSlaveParent( *sub );
+#endif
+ } else {
+ ///Should not happen..
+ kdDebug( 9007 ) << "\"" << str() << "\": Warning: the nested-type " << name.name() << " was found, but has no build-info" << endl;
+ return TypeDesc( "CompletionError::unknown" );
+ }
+
+ TypeDesc rest;
+ LocateMode newMode = addFlag( mode, ExcludeTemplates );
+ int newDir = 1;
+ if ( name.next() ) {
+ ifVerbose( dbg() << "\"" << str() << "\": found nested type \"" << name.name() << "\", passing control to it\n" );
+ ret = sub->locateType( resolveTemplateParams( *name.next(), Normal ), newMode, newDir ); ///since template-names cannot be referenced from outside, exclude them for the first cycle
+ ret.increaseResolutionCount();
+ if ( ret->resolved() )
+ return ret.resetDepth();
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\": successfully located searched type \"" << name.fullNameChain() << "\"\n" );
+ ret->setResolved( sub.get() );
+ ret->resolved()->setFindIncludeFiles( name.includeFiles() );
+ ret.locateMode().valid = true;
+ ret.locateMode().mode = (uint)newMode;
+ ret.locateMode().dir = newDir;
+ return ret.resetDepth();
+ }
+ break;
+ }
+ case MemberInfo::Typedef:
+ if ( mode & ExcludeTypedefs )
+ break;
+ case MemberInfo::Template: {
+ if ( mem.memberType == MemberInfo::Template && ( mode & ExcludeTemplates ) )
+ break;
+ ifVerbose( dbg() << "\"" << str() << "\": found " << mem.memberTypeToString() << " \"" << name.name() << "\" -> \"" << mem.type->fullNameChain() << "\", recursing \n" );
+ if ( name.hasTemplateParams() ) {
+ ifVerbose( dbg() << "\"" << str() << "\":warning: \"" << name.fullName() << "\" is a " << mem.memberTypeToString() << ", but it has template-params itself! Not matching" << endl );
+ } else {
+ if ( mem.type->name() != name.name() ) {
+
+ MemberInfo m = mem;
+ if ( name.next() ) {
+ mem.type->makePrivate();
+ mem.type->append( name.next() );
+ }
+ ret = locateDecType( mem.type, remFlag( mode, ExcludeTemplates ) );
+
+ if ( mem.memberType == MemberInfo::Template )
+ ret.addResolutionFlag( HadTemplate );
+ if ( mem.memberType == MemberInfo::Typedef )
+ ret.addResolutionFlag( HadTypedef );
+ ret.increaseResolutionCount();
+ // if( mode & TraceAliases && ret->resolved() )
+ {
+ m.name = "";
+
+ if ( !scope().isEmpty() ) {
+ m.name = fullTypeUnresolvedWithScope() + "::";
+ }
+ m.name += name.nameWithParams();
+ //m.name += name.fullNameChain();
+
+ if ( name.next() ) {
+ if ( m.type.trace() ) {
+ ret.trace() ->prepend( *m.type.trace(), 1 );
+ }
+ ret.trace() ->prepend( m, *name.next() );
+ } else {
+ if ( m.type.trace() )
+ ret.trace() ->prepend( *m.type.trace(), 1 );
+ ret.trace() ->prepend( m );
+ }
+ }
+
+ if ( ret->resolved() )
+ return ret.resetDepth();
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\"recursive typedef/template found: \"" << name.fullNameChain() << "\" -> \"" << mem.type->fullNameChain() << "\"" << endl );
+ }
+ }
+ break;
+ }
+ ///A Function is treated similar to a type
+ case MemberInfo::Function: {
+ if ( !name.next() ) {
+ TypePointer t = mem.build();
+ if ( t ) {
+ return t->desc();
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\"" << ": could not build function: \"" << name.fullNameChain() << "\"" );
+ }
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\"" << ": name-conflict: searched for \"" << name.fullNameChain() << "\" and found function \"" << mem.name << "\"" );
+ }
+ break;
+ };
+ ///Currently there is no representation of a Variable as a SimpleType, so only the type of the variable is used.
+ case MemberInfo::Variable: {
+ return locateDecType( mem.type, remFlag( mode, ExcludeTemplates ) ).resetDepth();
+ }
+ }
+
+ ///Ask bases but only on this level
+ if ( ! ( mode & ExcludeBases ) ) {
+
+ QValueList<LocateResult> bases = getBases();
+ if ( !bases.isEmpty() ) {
+ TypeDesc nameInBase = resolveTemplateParams( name, LocateBase ); ///Resolve all template-params that are at least visible in the scope of the base-declaration
+
+ for ( QValueList<LocateResult>::iterator it = bases.begin(); it != bases.end(); ++it ) {
+ if ( !( *it ) ->resolved() )
+ continue;
+ LocateResult t = ( *it ) ->resolved() ->locateType( nameInBase, addFlag( addFlag( mode, ExcludeTemplates ), ExcludeParents ), dir ); ///The searched Type cannot directly be a template-param in the base-class, so ExcludeTemplates. It's forgotten early enough.
+ if ( t->resolved() )
+ return t.increaseDepth();
+ else
+ if ( t > ret )
+ ret = t.increaseDepth();
+ }
+ }
+ }
+
+ ///Ask parentsc
+ if ( !scope().isEmpty() && dir != 1 && ! ( mode & ExcludeParents ) ) {
+ LocateResult rett = parent() ->locateType( resolveTemplateParams( name, mode & ExcludeBases ? ExcludeBases : mode ), mode & ForgetModeUpwards ? Normal : mode );
+ if ( rett->resolved() )
+ return rett.increaseDepth();
+ else
+ if ( rett > ret )
+ ret = rett.increaseDepth();
+ }
+
+ ///Ask the bases and allow them to search in their parents.
+ if ( ! ( mode & ExcludeBases ) ) {
+ TypeDesc baseName = resolveTemplateParams( name, LocateBase ); ///Resolve all template-params that are at least visible in the scope of the base-declaration
+ QValueList<LocateResult> bases = getBases();
+ if ( !bases.isEmpty() ) {
+ for ( QValueList<LocateResult>::iterator it = bases.begin(); it != bases.end(); ++it ) {
+ if ( !( *it ) ->resolved() )
+ continue;
+ LocateResult t = ( *it ) ->resolved() ->locateType( baseName, addFlag( mode, ExcludeTemplates ), dir ); ///The searched Type cannot directly be a template-param in the base-class, so ExcludeTemplates. It's forgotten early enough.
+ if ( t->resolved() )
+ return t.increaseDepth();
+ else
+ if ( t > ret )
+ ret = t.increaseDepth();
+ }
+ }
+ }
+
+ ///Give the type a desc, so the nearest point to the searched type is stored
+ ifVerbose( dbg() << "\"" << str() << "\": search for \"" << name.fullNameChain() << "\" FAILED" << endl );
+ return ret;
+}
+
+void SimpleTypeImpl::breakReferences() {
+ TypePointer p( this ); ///necessary so this type is not deleted in between
+ m_parent = 0;
+ m_desc.resetResolved();
+ // m_trace.clear();
+ m_masterProxy = 0;
+ invalidateCache();
+}
+
+TypePointer SimpleTypeImpl::bigContainer() {
+ if ( m_masterProxy )
+ return m_masterProxy;
+ else
+ return TypePointer( this );
+}
+
+SimpleType SimpleTypeImpl::parent() {
+ if ( m_parent ) {
+ //ifVerbose( dbg() << "\"" << str() << "\": returning parent" << endl;
+ return SimpleType( m_parent );
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\": locating parent" << endl );
+ invalidateSecondaryCache();
+ QStringList sc = scope();
+
+ if ( !sc.isEmpty() ) {
+ sc.pop_back();
+ SimpleType r = SimpleType( sc, m_desc.includeFiles() );
+ if ( &( *r.get() ) == this ) {
+ kdDebug( 9007 ) << "error: self set as parent: " << m_scope.join( "::" ) << "(" << m_scope.count() << ")" << ", " << sc.join( "::" ) << "(" << sc.count() << ")" /* << kdBacktrace()*/ << endl;
+ return SimpleType( new SimpleTypeImpl( "" ) );
+ }
+ m_parent = r.get();
+ return r;
+ } else {
+ ifVerbose( dbg() << "\"" << str() << "\"warning: returning parent of global scope!" << endl );
+ return SimpleType( new SimpleTypeImpl( "" ) );
+ }
+ }
+}
+
+const TypeDesc& SimpleTypeImpl::desc() {
+ if ( m_desc.name().isEmpty() )
+ m_desc.setName( cutTemplateParams( scope().back() ) );
+ m_desc.setResolved( this );
+ return m_desc;
+}
+
+TypeDesc& SimpleTypeImpl::descForEdit() {
+ desc();
+ invalidateCache();
+ return m_desc;
+}
+
+QString SimpleTypeImpl::describeWithParams() {
+ TemplateParamInfo pinfo = getTemplateParamInfo();
+ int num = 0;
+ TemplateParamInfo::TemplateParam param;
+ QString str = desc().name();
+ if ( desc().hasTemplateParams() ) {
+ str += "< ";
+
+ for ( TypeDesc::TemplateParams::const_iterator it = desc().templateParams().begin(); it != desc().templateParams().end(); ++it ) {
+ if ( pinfo.getParam( param, num ) && !param.name.isEmpty() )
+ str += param.name;
+ else
+ str += "[unknown name]";
+
+ str += " = " + ( *it ) ->fullNameChain() + ", ";
+ ++num;
+ }
+
+ str.truncate( str.length() - 2 );
+ str += " >";
+ }
+ return str;
+}
+
+QString SimpleTypeImpl::fullTypeResolved( int depth ) {
+ Debug d( "#tre#" );
+
+ TypeDesc t = desc();
+ if ( !scope().isEmpty() ) {
+ if ( depth > 10 )
+ return "KDevParseError::ToDeep";
+ if ( !safetyCounter )
+ return "KDevParseError::MaximumCountReached";
+
+ ifVerbose( dbg() << "fully resolving type " << t.fullName() << endl );
+ if ( scope().size() != 0 ) {
+ t = resolveTemplateParams( t, LocateBase );
+ }
+ }
+
+ return t.fullNameChain();
+}
+
+
+QString SimpleTypeImpl::fullTypeUnresolvedWithScope( ) {
+ if ( m_parent && !m_parent->scope().isEmpty() ) {
+ return m_parent->fullTypeUnresolvedWithScope() + "::" + m_desc.fullNameChain();
+ } else {
+ return m_desc.fullNameChain();
+ }
+}
+
+QString SimpleTypeImpl::fullTypeResolvedWithScope( int depth ) {
+ Q_UNUSED( depth );
+ if ( !m_scope.isEmpty() && parent() ) {
+ return parent() ->fullTypeResolvedWithScope() + "::" + fullTypeResolved();
+ } else {
+ return fullTypeResolved();
+ }
+}
+
+void SimpleTypeImpl::checkTemplateParams () {
+ invalidateCache();
+ if ( ! m_scope.isEmpty() ) {
+ QString str = m_scope.back();
+ m_desc = str;
+ if ( !m_desc.name().isEmpty() ) {
+ m_scope.pop_back();
+ m_scope << m_desc.name();
+ } else {
+ kdDebug() << "checkTemplateParams() produced bad scope-tail: \"" << m_desc.name() << "\", \"" << m_scope.join( "::" ) << "\"" << endl;
+ }
+ }
+}
+
+void SimpleTypeImpl::setScope( const QStringList& scope ) {
+ invalidateCache();
+ m_scope = scope;
+ if ( m_scope.count() == 1 && m_scope.front().isEmpty() ) {
+ //kdDebug() << "bad scope set " << kdBacktrace() << endl;
+ m_scope = QStringList();
+ }
+}
+
+SimpleTypeImpl::TypeOfResult SimpleTypeImpl::searchBases ( const TypeDesc& name /*option!!*/ ) {
+ QValueList<LocateResult> parents = getBases();
+ for ( QValueList<LocateResult>::iterator it = parents.begin(); it != parents.end(); ++it ) {
+ if ( !( *it ) ->resolved() )
+ continue;
+ TypeOfResult type = ( *it ) ->resolved() ->typeOf( name );
+ if ( type )
+ return type;
+ }
+ return TypeOfResult();
+}
+
+void SimpleTypeImpl::setSlaveParent( SimpleTypeImpl& slave ) {
+ if ( ! m_masterProxy ) {
+ slave.setParent( this );
+ } else {
+ slave.setParent( m_masterProxy );
+ }
+}
+
+void SimpleTypeImpl::parseParams( TypeDesc desc ) {
+ invalidateCache();
+ m_desc = desc;
+ m_desc.clearInstanceInfo();
+}
+
+void SimpleTypeImpl::takeTemplateParams( TypeDesc desc ) {
+ invalidateCache();
+ m_desc.templateParams() = desc.templateParams();
+}
+
+//SimpleTypeImpl::TemplateParamInfo implementation
+
+bool SimpleTypeImpl::TemplateParamInfo::getParam( TemplateParam& target, QString name ) const {
+ QMap<QString, TemplateParam>::const_iterator it = m_paramsByName.find( name );
+ if ( it != m_paramsByName.end() ) {
+ target = *it;
+ return true;
+ }
+ return false;
+}
+
+bool SimpleTypeImpl::TemplateParamInfo::getParam( TemplateParam& target, int number ) const {
+ QMap<int, TemplateParam>::const_iterator it = m_paramsByNumber.find( number );
+ if ( it != m_paramsByNumber.end() ) {
+ target = *it;
+ return true;
+ }
+ return false;
+}
+
+void SimpleTypeImpl::TemplateParamInfo::removeParam( int number ) {
+ QMap<int, TemplateParam>::iterator it = m_paramsByNumber.find( number );
+ if ( it != m_paramsByNumber.end() ) {
+ m_paramsByName.remove( ( *it ).name );
+ m_paramsByNumber.remove( it );
+ }
+}
+
+void SimpleTypeImpl::TemplateParamInfo::addParam( const TemplateParam& param ) {
+ m_paramsByNumber[ param.number ] = param;
+ m_paramsByName[ param.name ] = param;
+}
+
+int SimpleTypeImpl::TemplateParamInfo::count() const {
+ QMap<int, TemplateParam>::const_iterator it = m_paramsByNumber.end();
+ if ( it != m_paramsByNumber.begin() ) {
+ --it;
+ return ( *it ).number + 1;
+ } else {
+ return 0;
+ }
+}
+
+void SimpleTypeConfiguration::setGlobalNamespace( TypePointer globalNamespace ) {
+ if ( !globalNamespace->scope().isEmpty() ) {
+ kdDebug( 9007 ) << "error while setting global scope\n" << kdBacktrace() << endl;
+ SimpleType::setGlobalNamespace( new SimpleTypeImpl( "" ) );
+ } else {
+ SimpleType::setGlobalNamespace( globalNamespace );
+ }
+}
+
+// kate: indent-mode csands; tab-width 4;
+