/*************************************************************************** * 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 "store_walker.h" #include "ast_utils.h" #include "urlutil.h" #include "driver.h" #include #include #include StoreWalker::StoreWalker( const TQString& fileName, CodeModel* store ) : m_store( store ), m_anon( 0 ) { m_fileName = URLUtil::canonicalPath( fileName ); m_hashedFileName = HashedString( m_fileName ); //kdDebug(9007) << "StoreWalker::StoreWalker(" << m_fileName << ")" << endl; } StoreWalker::~StoreWalker() {} void StoreWalker::parseTranslationUnit( const ParsedFile& ast ) { m_file = m_store->create(); m_file->setName( m_fileName ); /// @todo ?!? m_currentScope.clear(); m_currentNamespace.clear(); m_currentClass.clear(); ParsedFilePointer p = new ParsedFile( ast ); p->setTranslationUnit( 0 ); //Necessary so the memory is not bloated after the first parse m_file->setParseResult( p.data() ); ///@todo beautify m_currentAccess = CodeModelItem::Public; m_inSlots = false; m_inSignals = false; m_inStorageSpec = false; m_inTypedef = false; m_currentDeclarator = 0; m_anon = 0; m_imports.clear(); m_imports << TQPair, TQStringList>(TQMap(), TQStringList()); TreeParser::parseTranslationUnit( ast ); m_imports.pop_back(); } void StoreWalker::parseDeclaration( DeclarationAST* ast ) { TreeParser::parseDeclaration( ast ); } void StoreWalker::parseLinkageSpecification( LinkageSpecificationAST* ast ) { int inStorageSpec = m_inStorageSpec; m_inStorageSpec = true; TreeParser::parseLinkageSpecification( ast ); m_inStorageSpec = inStorageSpec; } void StoreWalker::parseNamespace( NamespaceAST* ast ) { if ( !m_currentClass.isEmpty() ) { kdDebug( 9007 ) << "!!!!!!!!!!!!!!!!!!!!!!!!!! **error** !!!!!!!!!!!!!!!!!!!!" << endl; return ; } int startLine, startColumn; int endLine, endColumn; ast->getStartPosition( &startLine, &startColumn ); ast->getEndPosition( &endLine, &endColumn ); TQString nsName; if ( !ast->namespaceName() || ast->namespaceName()->text().isEmpty() ) { TQFileInfo fileInfo( m_fileName ); TQString shortFileName = fileInfo.baseName(); nsName.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ ); } else { nsName = ast->namespaceName() ->text(); } NamespaceDom ns = findOrInsertNamespace( ast, nsName ); m_currentScope.push_back( nsName ); m_currentNamespace.push( ns ); TreeParser::parseNamespace( ast ); m_currentNamespace.pop(); m_currentScope.pop_back(); } void StoreWalker::parseNamespaceAlias( NamespaceAliasAST* ast ) { TQString nsName; TQString aliasName; if( !ast->namespaceName() || ast->namespaceName()->text().isEmpty() ) { // anonymous namespace } else nsName = ast->namespaceName()->text(); if( ast->aliasName() ) aliasName = ast->aliasName()->text(); if( !nsName.isNull() ) { NamespaceAliasModel m; m.setName( nsName ); m.setAliasName( aliasName ); m.setFileName( m_hashedFileName ); if( m_currentNamespace.empty() ) m_file->addNamespaceAlias( m ); else m_currentNamespace.top() ->addNamespaceAlias( m ); } TreeParser::parseNamespaceAlias( ast ); } void StoreWalker::parseUsing( UsingAST* ast ) { TreeParser::parseUsing( ast ); } void StoreWalker::parseUsingDirective( UsingDirectiveAST* ast ) { TQString name; if( ast->name() ) name = ast->name()->text(); if( !name.isNull() ) { NamespaceImportModel m; m.setName( name ); m.setFileName( m_hashedFileName ); if( m_currentNamespace.empty() ) m_file->addNamespaceImport( m ); else m_currentNamespace.top() ->addNamespaceImport( m ); } m_imports.back().second.push_back( name ); } void StoreWalker::parseTypedef( TypedefAST* ast ) { #if 0 DeclaratorAST * oldDeclarator = m_currentDeclarator; if ( ast && ast->initDeclaratorList() && ast->initDeclaratorList() ->initDeclaratorList().count() > 0 ) { TQPtrList lst( ast->initDeclaratorList() ->initDeclaratorList() ); m_currentDeclarator = lst.at( 0 ) ->declarator(); } m_inTypedef = true; TreeParser::parseTypedef( ast ); m_inTypedef = false; m_currentDeclarator = oldDeclarator; #else TypeSpecifierAST* typeSpec = ast->typeSpec(); InitDeclaratorListAST* declarators = ast->initDeclaratorList(); if ( typeSpec && declarators ) { TQString typeId; if ( typeSpec->name() ) typeId = typeSpec->name() ->text(); TQPtrList l( declarators->initDeclaratorList() ); TQPtrListIterator it( l ); InitDeclaratorAST* initDecl = 0; while ( 0 != ( initDecl = it.current() ) ) { TQString type, id; if ( initDecl->declarator() ) { type = typeOfDeclaration( typeSpec, initDecl->declarator() ); DeclaratorAST* d = initDecl->declarator(); while ( d->subDeclarator() ) { d = d->subDeclarator(); } if ( d->declaratorId() ) id = d->declaratorId() ->text(); } TypeAliasDom typeAlias = m_store->create(); typeAlias->setFileName( m_fileName ); typeAlias->setName( id ); typeAlias->setType( type ); typeAlias->setComment( ast->comment() ); int line, col; initDecl->getStartPosition( &line, &col ); typeAlias->setStartPosition( line, col ); initDecl->getEndPosition( &line, &col ); typeAlias->setEndPosition( line, col ); if ( m_currentClass.top() ) m_currentClass.top() ->addTypeAlias( typeAlias ); else if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addTypeAlias( typeAlias ); else m_file->addTypeAlias( typeAlias ); #if 0 Tag tag; tag.setKind( Tag::Kind_Typedef ); tag.setFileName( m_fileName ); tag.setName( id ); tag.setScope( m_currentScope ); tag.setAttribute( "t", type ); int line, col; initDecl->getStartPosition( &line, &col ); tag.setStartPosition( line, col ); initDecl->getEndPosition( &line, &col ); tag.setEndPosition( line, col ); m_catalog->addItem( tag ); #endif ++it; } } #endif } void StoreWalker::parseTemplateDeclaration( TemplateDeclarationAST* ast ) { m_currentTemplateDeclarator.push( ast ); if ( ast->declaration() ) parseDeclaration( ast->declaration() ); TreeParser::parseTemplateDeclaration( ast ); m_currentTemplateDeclarator.pop(); } void StoreWalker::parseSimpleDeclaration( SimpleDeclarationAST* ast ) { TypeSpecifierAST * typeSpec = ast->typeSpec(); InitDeclaratorListAST* declarators = ast->initDeclaratorList(); CommentPusher push( *this, ast->comment() ); if ( typeSpec ) parseTypeSpecifier( typeSpec ); if ( declarators ) { TQPtrList l = declarators->initDeclaratorList(); TQPtrListIterator it( l ); while ( it.current() ) { parseDeclaration( ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, it.current() ); ++it; } } } TQStringList StoreWalker::findScope( const TQStringList& scope ) { ClassDom d = findClassFromScope( scope ); if( d ) { TQStringList ret = d->scope(); ret << d->name(); return ret; } return scope; } void StoreWalker::parseFunctionDefinition( FunctionDefinitionAST* ast ) { TypeSpecifierAST * typeSpec = ast->typeSpec(); GroupAST* funSpec = ast->functionSpecifier(); GroupAST* storageSpec = ast->storageSpecifier(); if ( !ast->initDeclarator() ) return ; DeclaratorAST* d = ast->initDeclarator() ->declarator(); if ( !d->declaratorId() ) return ; bool isFriend = false; bool isVirtual = false; bool isStatic = false; bool isInline = false; if ( funSpec ) { TQPtrList l = funSpec->nodeList(); TQPtrListIterator it( l ); while ( it.current() ) { TQString text = it.current() ->text(); if ( text == "virtual" ) isVirtual = true; else if ( text == "inline" ) isInline = true; ++it; } } if ( storageSpec ) { TQPtrList l = storageSpec->nodeList(); TQPtrListIterator it( l ); while ( it.current() ) { TQString text = it.current() ->text(); if ( text == "friend" ) isFriend = true; else if ( text == "static" ) isStatic = true; ++it; } } int startLine, startColumn; int endLine, endColumn; ast->getStartPosition( &startLine, &startColumn ); ast->getEndPosition( &endLine, &endColumn ); TQString id = d->declaratorId() ->unqualifiedName() ->text().stripWhiteSpace(); TQStringList scope = scopeOfDeclarator( d, m_currentScope ); ClassDom c; ///c should be nonzero if it is a function-definition for a function within another class if( !m_currentClass.top() ) { ///It is not a local definition within a class, so search the scope so it can be corrected using imports c = findClassFromScope( scope ); } if( c ) { scope = c->scope(); scope << c->name(); } FunctionDefinitionDom method = m_store->create(); method->setScope( scope ); method->setName( id ); parseFunctionArguments( d, model_cast( method ) ); TQString text = typeOfDeclaration( typeSpec, d ); if ( !text.isEmpty() ) method->setResultType( text ); method->setFileName( m_fileName ); method->setStartPosition( startLine, startColumn ); method->setEndPosition( endLine, endColumn ); if( !ast->comment().isEmpty() ) method->setComment( ast->comment() ); checkTemplateDeclarator( & (*method) ); if ( m_inSignals ) method->setSignal( true ); if ( m_inSlots ) method->setSlot( true ); if( c && c->isClass() ) method->setConstant( d->constant() != 0 ); else if ( m_currentClass.top() || ( method->name() == "main" && scope.isEmpty() ) ) { method->setConstant( d->constant() != 0 ); method->setAccess( m_currentAccess ); method->setStatic( isStatic ); method->setVirtual( isVirtual ); if ( m_currentClass.top() ) m_currentClass.top() ->addFunction( model_cast( method ) ); else m_file->addFunction( model_cast( method ) ); } if ( m_currentClass.top() ) m_currentClass.top() ->addFunctionDefinition( method ); else if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addFunctionDefinition( method ); else m_file->addFunctionDefinition( method ); } void StoreWalker::parseLinkageBody( LinkageBodyAST* ast ) { TreeParser::parseLinkageBody( ast ); } void StoreWalker::parseTypeSpecifier( TypeSpecifierAST* ast ) { TreeParser::parseTypeSpecifier( ast ); } void StoreWalker::takeTemplateParams( TemplateModelItem& target, TemplateDeclarationAST* ast) { TemplateParameterListAST* pl = ast->templateParameterList(); if( pl ) { TQPtrList list = pl->templateParameterList(); TemplateParameterAST* curr = list.first(); while( curr != 0 ) { TQString a, b; if( curr->typeParameter() && curr->typeParameter()->name() ) { a = curr->typeParameter()->name()->text(); if( curr->typeParameter()->typeId() ) b = curr->typeParameter()->typeId()->text(); } target.addTemplateParam( a, b ); CodeModelItem* cmi = dynamic_cast(&target); TQString nm = "0"; if(cmi) nm = cmi->name(); kdDebug() << "item " << nm << " taking template-parameters " << a << ", default=" << b << "\n"; curr = list.next(); } } } void StoreWalker::checkTemplateDeclarator( TemplateModelItem* item ) { if( !m_currentTemplateDeclarator.empty() && m_currentTemplateDeclarator.top() != 0) { TemplateDeclarationAST* a = m_currentTemplateDeclarator.top(); m_currentTemplateDeclarator.pop(); m_currentTemplateDeclarator.push(0); takeTemplateParams( *item, a ); } } int StoreWalker::mergeGroups( int g1, int g2 ) { int ng = m_store->mergeGroups( g1, g2 ); for( TQMap::iterator it = m_overrides.begin(); it != m_overrides.end(); ++it ) { int g =(*it)->groupId(); if( g == g1 || g == g2 ) (*it)->setGroupId( ng ); } return ng; } void StoreWalker::parseClassSpecifier( ClassSpecifierAST* ast ) { int startLine, startColumn; int endLine, endColumn; ast->getStartPosition( &startLine, &startColumn ); ast->getEndPosition( &endLine, &endColumn ); int oldAccess = m_currentAccess; bool oldInSlots = m_inSlots; bool oldInSignals = m_inSignals; TQString kind = ast->classKey() ->text(); if ( kind == "class" ) m_currentAccess = CodeModelItem::Private; else m_currentAccess = CodeModelItem::Public; m_inSlots = false; m_inSignals = false; TQString className; if ( !ast->name() && m_currentDeclarator && m_currentDeclarator->declaratorId() ) { className = m_currentDeclarator->declaratorId() ->text().stripWhiteSpace(); } else if ( !ast->name() ) { TQFileInfo fileInfo( m_fileName ); TQString shortFileName = fileInfo.baseName(); className.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ ); } else { className = ast->name() ->unqualifiedName() ->text().stripWhiteSpace(); } ClassDom klass = m_store->create(); klass->setStartPosition( startLine, startColumn ); klass->setEndPosition( endLine, endColumn ); klass->setFileName( m_fileName ); int i = className.find( '<' ); if( i != -1 ) { klass->setSpecializationDeclaration( className.mid( i ) ); className = className.left( i ); } klass->setName( className ); klass->setComment( ast->comment() ); checkTemplateDeclarator( &(*klass) ); bool embed = !scopeOfName( ast->name(), TQStringList() ).isEmpty(); TQStringList oldScope; if( embed ) { ClassDom embedderClass = findClassFromScope( m_currentScope + scopeOfName( ast->name(), TQStringList() )); if(embedderClass) { if(embedderClass->fileName() != klass->fileName()) { ///since we are creating a link between both files, put them into the same parsing-group FileDom dm = embedderClass->file(); if( dm ) { m_file->setGroupId( mergeGroups( dm->groupId(), m_file->groupId() ) ); }else{ kdDebug() << "file " << embedderClass->fileName() << " missing in store \n"; } } oldScope = m_currentScope; m_currentScope = embedderClass->scope(); m_currentScope.push_back( embedderClass->name() ); m_currentClass.push( embedderClass ); //m_file->addClass( klass );//experiment }else{ kdDebug( 9007 ) << "could not find embedding class " << TQStringList(m_currentScope + scopeOfName( ast->name(), TQStringList() )).join("::") << " for " << className << endl; embed = false; } } if ( m_currentClass.top() ) m_currentClass.top() ->addClass( klass ); else if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addClass( klass ); else m_file->addClass( klass ); klass->setScope( m_currentScope ); if ( ast->baseClause() ) parseBaseClause( ast->baseClause(), klass ); m_currentScope.push_back( className ); m_currentClass.push( klass ); //m_imports.push_back( TQStringList() ); TreeParser::parseClassSpecifier( ast ); //m_imports.pop_back(); m_currentClass.pop(); m_currentScope.pop_back(); if( embed ) { m_currentScope = oldScope; m_currentClass.pop(); } m_currentAccess = oldAccess; m_inSlots = oldInSlots; m_inSignals = oldInSignals; } void StoreWalker::parseEnumSpecifier( EnumSpecifierAST* ast ) { if( ast->name() ) { TypeAliasDom typeAlias = m_store->create(); typeAlias->setFileName( m_fileName ); typeAlias->setName( ast->name()->text() ); typeAlias->setType( "const int" ); typeAlias->setComment( ast->comment() ); int line, col; ast->getStartPosition( &line, &col ); typeAlias->setStartPosition( line, col ); ast->getEndPosition( &line, &col ); typeAlias->setEndPosition( line, col ); if ( m_currentClass.top() ) m_currentClass.top() ->addTypeAlias( typeAlias ); else if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addTypeAlias( typeAlias ); else m_file->addTypeAlias( typeAlias ); } TQPtrList l = ast->enumeratorList(); TQPtrListIterator it( l ); while ( it.current() ) { VariableDom attr = m_store->create(); attr->setName( it.current() ->id() ->text() ); attr->setFileName( m_fileName ); attr->setAccess( m_currentAccess ); if( !ast->name() ) { attr->setType( "const int" ); } else { attr->setType( ast->name()->text() ); } attr->setEnumeratorVariable( true ); attr->setComment( (*it)->comment() ); attr->setStatic( true ); int startLine, startColumn; int endLine, endColumn; it.current() ->getStartPosition( &startLine, &startColumn ); attr->setStartPosition( startLine, startColumn ); it.current() ->getEndPosition( &endLine, &endColumn ); attr->setEndPosition( endLine, endColumn ); if ( m_currentClass.top() ) m_currentClass.top() ->addVariable( attr ); else if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addVariable( attr ); else m_file->addVariable( attr ); ++it; } } void StoreWalker::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* ast ) { TreeParser::parseElaboratedTypeSpecifier( ast ); } void StoreWalker::parseTypeDeclaratation( TypeSpecifierAST* typeSpec ) { parseTypeSpecifier( typeSpec ); } void StoreWalker::parseDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl ) { if ( m_inStorageSpec ) return ; DeclaratorAST* d = decl->declarator(); if ( !d ) return ; if ( !d->subDeclarator() && d->parameterDeclarationClause() ) return parseFunctionDeclaration( funSpec, storageSpec, typeSpec, decl ); DeclaratorAST* t = d; while ( t && t->subDeclarator() ) t = t->subDeclarator(); TQString id; if ( t && t->declaratorId() && t->declaratorId() ->unqualifiedName() ) id = t->declaratorId() ->unqualifiedName() ->text(); if ( !scopeOfDeclarator( d, TQStringList() ).isEmpty() ) { kdDebug( 9007 ) << "skip declaration of " << TQStringList(scopeOfDeclarator( d, TQStringList() )).join("::") << "::" << id << endl; return ; } VariableDom attr = m_store->create(); attr->setName( id ); attr->setFileName( m_fileName ); attr->setComment( comment() ); if ( m_currentClass.top() ) m_currentClass.top() ->addVariable( attr ); else if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addVariable( attr ); else m_file->addVariable( attr ); attr->setAccess( m_currentAccess ); TQString text = typeOfDeclaration( typeSpec, d ); if ( !text.isEmpty() ) { attr->setType( text ); } bool isFriend = false; //bool isVirtual = false; bool isStatic = false; //bool isInline = false; //bool isInitialized = decl->initializer() != 0; if ( storageSpec ) { TQPtrList l = storageSpec->nodeList(); TQPtrListIterator it( l ); while ( it.current() ) { TQString text = it.current() ->text(); if ( text == "friend" ) isFriend = true; else if ( text == "static" ) isStatic = true; ++it; } } int startLine, startColumn; int endLine, endColumn; decl->getStartPosition( &startLine, &startColumn ); decl->getEndPosition( &endLine, &endColumn ); attr->setStartPosition( startLine, startColumn ); attr->setEndPosition( endLine, endColumn ); attr->setStatic( isStatic ); } void StoreWalker::parseAccessDeclaration( AccessDeclarationAST * access ) { TQPtrList l = access->accessList(); TQString accessStr = l.at( 0 ) ->text(); if ( accessStr == "public" ) m_currentAccess = CodeModelItem::Public; else if ( accessStr == "protected" ) m_currentAccess = CodeModelItem::Protected; else if ( accessStr == "private" ) m_currentAccess = CodeModelItem::Private; else if ( accessStr == "signals" ) m_currentAccess = CodeModelItem::Protected; else m_currentAccess = CodeModelItem::Public; m_inSlots = l.count() > 1 ? l.at( 1 ) ->text() == "slots" : false; m_inSignals = l.count() >= 1 ? l.at( 0 ) ->text() == "signals" : false; } NamespaceDom StoreWalker::findOrInsertNamespace( NamespaceAST* ast, const TQString & name ) { if ( m_currentNamespace.top() && m_currentNamespace.top() ->hasNamespace( name ) ) return m_currentNamespace.top() ->namespaceByName( name ); if ( m_file->hasNamespace( name ) ) return m_file->namespaceByName( name ); int startLine, startColumn; int endLine, endColumn; ast->getStartPosition( &startLine, &startColumn ); ast->getEndPosition( &endLine, &endColumn ); NamespaceDom ns = m_store->create(); ns->setFileName( m_fileName ); ns->setName( name ); ns->setStartPosition( startLine, startColumn ); ns->setEndPosition( endLine, endColumn ); ns->setComment( ast->comment() ); ns->setScope( m_currentScope ); if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addNamespace( ns ); else m_file->addNamespace( ns ); return ns; } void StoreWalker::parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST * typeSpec, InitDeclaratorAST * decl ) { bool isFriend = false; bool isVirtual = false; bool isStatic = false; bool isInline = false; bool isPure = decl->initializer() != 0; if ( funSpec ) { TQPtrList l = funSpec->nodeList(); TQPtrListIterator it( l ); while ( it.current() ) { TQString text = it.current() ->text(); if ( text == "virtual" ) isVirtual = true; else if ( text == "inline" ) isInline = true; ++it; } } if ( storageSpec ) { TQPtrList l = storageSpec->nodeList(); TQPtrListIterator it( l ); while ( it.current() ) { TQString text = it.current() ->text(); if ( text == "friend" ) isFriend = true; else if ( text == "static" ) isStatic = true; ++it; } } int startLine, startColumn; int endLine, endColumn; decl->getStartPosition( &startLine, &startColumn ); decl->getEndPosition( &endLine, &endColumn ); DeclaratorAST* d = decl->declarator(); TQString id = d->declaratorId() ->unqualifiedName() ->text(); FunctionDom method = m_store->create(); method->setName( id ); method->setComment( comment() ); method->setFileName( m_fileName ); method->setStartPosition( startLine, startColumn ); method->setEndPosition( endLine, endColumn ); method->setAccess( m_currentAccess ); method->setStatic( isStatic ); method->setVirtual( isVirtual ); method->setAbstract( isPure ); parseFunctionArguments( d, method ); checkTemplateDeclarator( & (*method) ); if ( m_inSignals ) method->setSignal( true ); if ( m_inSlots ) method->setSlot( true ); TQString text = typeOfDeclaration( typeSpec, d ); if ( !text.isEmpty() ) method->setResultType( text ); method->setConstant( d->constant() != 0 ); method->setScope( scopeOfDeclarator( d, m_currentScope ) ); if ( m_currentClass.top() ) m_currentClass.top() ->addFunction( method ); else if ( m_currentNamespace.top() ) m_currentNamespace.top() ->addFunction( method ); else m_file->addFunction( method ); } void StoreWalker::parseFunctionArguments( DeclaratorAST* declarator, FunctionDom method ) { ParameterDeclarationClauseAST * clause = declarator->parameterDeclarationClause(); if ( clause && clause->parameterDeclarationList() ) { ParameterDeclarationListAST * params = clause->parameterDeclarationList(); TQPtrList l( params->parameterList() ); TQPtrListIterator it( l ); while ( it.current() ) { ParameterDeclarationAST * param = it.current(); ++it; ArgumentDom arg = m_store->create(); if ( param->declarator() ) { TQString text = declaratorToString( param->declarator(), TQString(), true ); if ( !text.isEmpty() ) arg->setName( text ); } TQString tp = typeOfDeclaration( param->typeSpec(), param->declarator() ); if ( !tp.isEmpty() ) arg->setType( tp ); method->addArgument( arg ); } } } TQString StoreWalker::typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator ) { if ( !typeSpec || !declarator ) return TQString(); TQString text; text += typeSpec->text(); TQPtrList ptrOpList = declarator->ptrOpList(); for ( TQPtrListIterator it( ptrOpList ); it.current(); ++it ) { text += it.current() ->text(); } for( int a = 0; a < declarator->arrayDimensionList().count(); a++ ) text += "*"; return text; } void StoreWalker::parseBaseClause( BaseClauseAST * baseClause, ClassDom klass ) { TQPtrList l = baseClause->baseSpecifierList(); TQPtrListIterator it( l ); while ( it.current() ) { BaseSpecifierAST * baseSpecifier = it.current(); TQString baseName; if ( baseSpecifier->name() ) baseName = baseSpecifier->name() ->text(); klass->addBaseClass( baseName ); ++it; } } TQStringList StoreWalker::scopeOfName( NameAST* id, const TQStringList& startScope ) { TQStringList scope = startScope; if ( id && id->classOrNamespaceNameList().count() ) { if ( id->isGlobal() ) scope.clear(); TQPtrList l = id->classOrNamespaceNameList(); TQPtrListIterator it( l ); while ( it.current() ) { if ( it.current() ->name() ) { scope << it.current() ->name() ->text(); } ++it; } } return scope; } ///@todo respect the imports that result from the headers etc. ClassDom StoreWalker::findClassFromScope( const TQStringList& scope ) { TQString scopeText = scope.join("::"); if( !m_imports.isEmpty() ) { TQMapIterator it = m_imports.back().first.find( scopeText ); if( it != m_imports.back().first.end() ) { return *it; } } ClassDom c = classFromScope( scope ); if( c ) { if( !m_imports.isEmpty() ) m_imports.back().first[ scopeText ] = c; return c; } if(!m_imports.isEmpty() && !m_imports.back().second.isEmpty()) { ///try the same using one of the imports(performance-wise this is not good, but simple) TQStringList::iterator it = m_imports.back().second.begin(); while(it != m_imports.back().second.end()) { TQStringList scp = TQStringList::split("::", *it) + m_currentScope + scope; c = classFromScope( scp ); if( c ) { if( !m_imports.isEmpty() ) m_imports.back().first[ scopeText ] = c; return c; } ++it; } } return c; } ClassDom findScopeInFile( const TQStringList& scope, NamespaceModel* glob ) { if( !glob ) return ClassDom(); ClassModel* curr = glob ; TQStringList::const_iterator mit = scope.begin(); while(curr->isNamespace() && mit != scope.end() && ((NamespaceModel*)curr)->hasNamespace( *mit )) { curr = &(*( ((NamespaceModel*)curr)->namespaceByName( *mit ) )); ++mit; } while((curr->isNamespace() || curr->isClass()) && mit != scope.end() && curr->hasClass( *mit )) { ClassList cl = curr->classByName( *mit ); curr = &(**cl.begin() ); ++mit; } if(mit == scope.end()) { return curr; } else { return ClassDom(0); } } ClassDom StoreWalker::classFromScope(const TQStringList& scope) { if(scope.isEmpty())return ClassDom(0); //Since another instance of the current file may still be in the code-model this must be testede BEFORE the code-model ClassDom c = findScopeInFile( scope, m_file.data() ); if( c ) return c; NamespaceDom glob = m_store->globalNamespace(); if( !glob ) return ClassDom(); c = findScopeInFile( scope, glob ); TQMap::const_iterator it; if( c ) { ///Check the file that overrides the code-model file it = m_overrides.find( c->fileName() ); //Find the class within the file that is overriding the one in code-model. if( it != m_overrides.end() ) { return findScopeInFile( scope, *it ); } else { return c; } } else { ///Search in all overrides, because they will be added later all at once for( TQMap::const_iterator it = m_overrides.begin(); it != m_overrides.end(); ++it ) { c = findScopeInFile( scope, *it ); if( c ) return c; } } return ClassDom(0); } TQStringList StoreWalker::scopeOfDeclarator( DeclaratorAST* d, const TQStringList& startScope ) { return scopeOfName( d->declaratorId(), startScope ); } //kate: indent-mode csands; tab-width 4; space-indent off;