/***************************************************************************
 *   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 "tag_creator.h"
#include "catalog.h"
#include "ast_utils.h"
#include "cpp_tags.h"
#include "doxydoc.h"
#include "driver.h" 

#include <kdebug.h>
#include <tqfileinfo.h>
#include <tqregexp.h>

DoxyDoc* TagCreator::m_documentation = new DoxyDoc( TQStringList() );

TagCreator::TagCreator( const TQString& fileName, Catalog* c )
: m_catalog( c ), m_fileName( fileName ), m_anon( 0 )
{
}

TagCreator::~TagCreator()
{
}

void TagCreator::destroyDocumentation()
{
	delete m_documentation;
}

void TagCreator::setDocumentationDirectories( const TQStringList& str )
{
	if ( m_documentation )
		delete m_documentation;
	m_documentation = new DoxyDoc( str );
}

void TagCreator::parseDeclaration( DeclarationAST* ast )
{
	if( ast->nodeType() == NodeType_AccessDeclaration ||
	    m_currentAccess.isEmpty() ||
	    m_currentAccess.contains("private")	||	///In order to correctly evaluate templates, the private members are necessary too
	    m_currentAccess.contains("public") ||
	    m_currentAccess.contains("protected") ||
	    m_currentAccess.contains("signals") )
	{
		TreeParser::parseDeclaration( ast );
	}
}

void TagCreator::parseTranslationUnit( const ParsedFile& ast )
{
	m_currentScope.clear();
	m_currentAccess = TQString();
	m_inSlots = false;
	m_inSignals = false;
	m_anon = 0;
	m_imports.clear();
	m_inClass = false;
	
	m_imports << TQStringList();

  	Tag tag;
  	tag.setKind( Tag::Kind_TranslationUnit );
  	tag.setFileName( m_fileName );
  	tag.setName( m_fileName );

	TQByteArray data;
	TQDataStream stream(data, IO_WriteOnly );
	ast.write( stream );
	tag.setAttribute( "cppparsedfile", data );
	tag.setAttribute( "includedFrom", ast.includedFrom() );
	tag.setAttribute( "skippedLines", TQString("%1").arg( ast.skippedLines()) );
	tag.setAttribute( "macroValueHash", TQString("%1").arg( ast.usedMacros().valueHash()) );
	tag.setAttribute( "macroIdHash", TQString("%1").arg( ast.usedMacros().idHash() ) );
	
  	tag.setScope( m_currentScope );
  	if( !ast->comment().isEmpty() )
		tag.setComment( ast->comment() );
	  
  	m_catalog->addItem( tag );
	
	TreeParser::parseTranslationUnit( ast );
	m_imports.pop_back();
}

void TagCreator::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();
  
  Tag tag;
  tag.setKind( Tag::Kind_Namespace );
  tag.setFileName( m_fileName );
  tag.setName( nsName ); ///nsName is the new name of the namespace
  tag.setAttribute( "alias", aliasName ); ///aliasName is the name of the real namespace
  tag.setScope( m_currentScope );
  if( !ast->comment().isEmpty() )
    tag.setComment( ast->comment() );
  
  int line, col;
  ast->getStartPosition( &line, &col );
  tag.setStartPosition( line, col );
  
  ast->getEndPosition( &line, &col );
  tag.setEndPosition( line, col );
  
  m_catalog->addItem( tag );
  
  TreeParser::parseNamespaceAlias( ast );
}

void TagCreator::parseNamespace( NamespaceAST* ast )
{
	TQString nsName;
	if( !ast->namespaceName() || ast->namespaceName()->text().isEmpty() )
	{
        // anonymous namespace
	}
	else
		nsName = ast->namespaceName()->text();
	
	Tag tag;
	tag.setKind( Tag::Kind_Namespace );
	tag.setFileName( m_fileName );
	tag.setName( nsName );
	tag.setScope( m_currentScope );
	if( !ast->comment().isEmpty() )
		tag.setComment( ast->comment() );
	
	int line, col;
	ast->getStartPosition( &line, &col );
	tag.setStartPosition( line, col );
	
	ast->getEndPosition( &line, &col );
	tag.setEndPosition( line, col );
	
	m_catalog->addItem( tag );
	
	m_currentScope.push_back( nsName );
	TreeParser::parseNamespace( ast );
	m_currentScope.pop_back();
}

void TagCreator::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* ast )
{
	TreeParser::parseElaboratedTypeSpecifier( ast );
}

void TagCreator::parseUsingDirective( UsingDirectiveAST* ast )
{
	TQString name;
	if( ast->name() )
		name = ast->name()->text();
	
	if( !name.isNull() ){
		Tag tag;
		tag.setKind( Tag::Kind_UsingDirective );
		tag.setFileName( m_fileName );
		tag.setName( name );
		tag.setScope( m_currentScope );
		
		int line, col;
		ast->getStartPosition( &line, &col );
		tag.setStartPosition( line, col );
		
		ast->getEndPosition( &line, &col );
		tag.setEndPosition( line, col );
		
		m_catalog->addItem( tag );
	}
	
	m_imports.back().push_back( name );
}

void TagCreator::parseTypedef( TypedefAST* ast )
{
	TypeSpecifierAST* typeSpec = ast->typeSpec();
	InitDeclaratorListAST* declarators = ast->initDeclaratorList();
	
	if( typeSpec && declarators ){
		TQString typeId;
		
		if( typeSpec->name() )
			typeId = typeSpec->name()->text();
		
		TQPtrList<InitDeclaratorAST> l( declarators->initDeclaratorList() );
		TQPtrListIterator<InitDeclaratorAST> 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();
			}
			
			Tag tag;
			if( !ast->comment().isEmpty() )
				tag.setComment( ast->comment() );
			
			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 );
			
			++it;
		}
		
	}
}

void TagCreator::parseTemplateDeclaration( TemplateDeclarationAST* ast )
{
	m_currentTemplateDeclarator.push( ast );
	if ( ast->declaration() )
		parseDeclaration( ast->declaration() );
	
	
	
	TreeParser::parseTemplateDeclaration( ast );
	
	m_currentTemplateDeclarator.pop();
}


void TagCreator::parseSimpleDeclaration( SimpleDeclarationAST* ast )
{
	CommentPusher push( *this, ast->comment() );
	
	TypeSpecifierAST* typeSpec = ast->typeSpec();
	InitDeclaratorListAST* declarators = ast->initDeclaratorList();
	
	if( typeSpec )
		parseTypeSpecifier( typeSpec );
	
	if( declarators )
	{
		TQPtrList<InitDeclaratorAST> l = declarators->initDeclaratorList();
		
		TQPtrListIterator<InitDeclaratorAST> it( l );
		while( it.current() )
		{
			parseMyDeclaration(  ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, it.current() );
			++it;
		}
	}
}

void TagCreator::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<AST> l = funSpec->nodeList();
		TQPtrListIterator<AST> 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<AST> l = storageSpec->nodeList();
		TQPtrListIterator<AST> it( l );
		while ( it.current() )
		{
			TQString text = it.current() ->text();
			if ( text == "friend" )
				isFriend = true;
			else if ( text == "static" )
				isStatic = true;
			++it;
		}
	}
	
	
	TQString id = d->declaratorId() ->unqualifiedName() ->text().stripWhiteSpace();
	TQString scopeStr = scopeOfDeclarator( d );
	
	Tag tag;
	if( !comment() )
		tag.setComment( ast->comment() );
	
	CppFunction<Tag> tagBuilder( tag );
	tag.setKind( Tag::Kind_Function );
	
	tag.setFileName( m_fileName );
	tag.setName( id );
	tag.setScope( TQStringList::split( ".", scopeStr ) );
	if( !ast->comment().isEmpty() )
		tag.setComment( ast->comment() );
	
	int line, col;
	ast->getStartPosition( &line, &col );
	tag.setStartPosition( line, col );
	
	ast->getEndPosition( &line, &col );
	tag.setEndPosition( line, col );
	
	tagBuilder.setType( typeOfDeclaration( typeSpec, d ) );
	
	parseFunctionArguments( tag, d );
	checkTemplateDeclarator( tag );
	
	TQString arguments = tag.attribute( "a" ).toStringList().join( "," );
tag.setAttribute( "description", m_documentation->functionDescription( scopeStr.replace( TQRegExp( "." ), ":" ), id, typeOfDeclaration( typeSpec, d ), arguments ) );
	
	tagBuilder.setAccess( TagUtils::stringToAccess( m_currentAccess ) );
	
	tagBuilder.setFriend( isFriend );
	tagBuilder.setVirtual( isVirtual );
	tagBuilder.setStatic( isStatic );
	tagBuilder.setInline( isInline );
	tagBuilder.setPure( false );
	tagBuilder.setConst( d->constant() != 0 );
	tagBuilder.setSignal( m_inSignals );
	tagBuilder.setSlot( m_inSlots );
	
	m_catalog->addItem( tag );
	
	if ( !m_currentAccess.isEmpty() )
	{
		tag.setKind( Tag::Kind_FunctionDeclaration );
		m_catalog->addItem( tag );
	}
}

void TagCreator::parseLinkageBody( LinkageBodyAST* ast )
{
	TQPtrList<DeclarationAST> l = ast->declarationList();
	TQPtrListIterator<DeclarationAST> it( l );
	while ( it.current() )
	{
		parseDeclaration( it.current() );
		++it;
	}
}

void TagCreator::checkTemplateDeclarator( Tag& tag ) {
	if( !m_currentTemplateDeclarator.empty() && m_currentTemplateDeclarator.top() != 0) {
		TemplateDeclarationAST* a = m_currentTemplateDeclarator.top();
		
		m_currentTemplateDeclarator.pop();
		m_currentTemplateDeclarator.push(0);
		
		///the template-declarator belongs to exactly this declaration
		takeTemplateParams( tag, a );
	}
}


void TagCreator::takeTemplateParams( Tag& target, TemplateDeclarationAST* ast) {
	TemplateParameterListAST* pl = ast->templateParameterList();
	if( pl ) {
		TQPtrList<TemplateParameterAST> list = pl->templateParameterList();
		
		TemplateParameterAST* curr = list.first();
		while( curr != 0 ) {
			TQString a, b;
			if( curr->typeParameter() ) {
				if( curr->typeParameter()->name() )
					a = curr->typeParameter()->name()->text();
				if( curr->typeParameter()->typeId() ) 
					b =  curr->typeParameter()->typeId()->text();
			}
			
			target.addTemplateParam( a, b );
			curr = list.next();
		}
	}
}


void TagCreator::parseClassSpecifier( ClassSpecifierAST* ast )
{
	int startLine, startColumn;
	int endLine, endColumn;
	ast->getStartPosition( &startLine, &startColumn );
	ast->getEndPosition( &endLine, &endColumn );
	
	TQString oldAccess = m_currentAccess;
	bool oldInSlots = m_inSlots;
	bool oldInSignals = m_inSignals;
	
	TQString kind = ast->classKey() ->text();
	if ( kind == "class" )
		m_currentAccess = "private";
	else
		m_currentAccess = "public";
	m_inSlots = false;
	m_inSignals = false;
	
	TQString className;
	if ( !ast->name() )
	{
		//TQFileInfo fileInfo( m_fileName );
		//TQString shortFileName = fileInfo.baseName();
		//className.sprintf( "(%s_%d)", shortFileName.local8Bit(), m_anon++ );
	}
	else
	{
		className = ast->name() ->text();
	}
	
	Tag tag;
	if( !ast->comment().isEmpty() )
		tag.setComment( ast->comment() );
	
	tag.setKind( Tag::Kind_Class );
	
	tag.setFileName( m_fileName );

	int i = className.find( '<' );
	TQString specialization;
	
	if( i != -1 ) {
		specialization = className.mid( i );
		tag.setSpecializationDeclaration( specialization );
		className = className.left( i );
	}
		
	tag.setName( className );
	tag.setScope( m_currentScope );
	
	int line, col;
	ast->getStartPosition( &line, &col );
	tag.setStartPosition( line, col );
	
	ast->getEndPosition( &line, &col );
	tag.setEndPosition( line, col );
	
	checkTemplateDeclarator( tag );

	m_catalog->addItem( tag );
	
	if ( ast->baseClause() )
		parseBaseClause( tag.path()+specialization, ast->baseClause() );
	
	m_currentScope.push_back( className + specialization );
	int oldInClass = m_inClass;
	m_inClass = true;
	TreeParser::parseClassSpecifier( ast );
	m_currentScope.pop_back();
	m_inClass = oldInClass;
	
	m_currentAccess = oldAccess;
	m_inSlots = oldInSlots;
	m_inSignals = oldInSignals;
}

void TagCreator::parseEnumSpecifier( EnumSpecifierAST* ast )
{
	Tag tag;
	if( !ast->comment().isEmpty() )
		tag.setComment( ast->comment() );
	
	tag.setKind( Tag::Kind_Enum );
	
	tag.setFileName( m_fileName );
	if ( ast->name() )
		tag.setName( ast->name() ->text() );
	tag.setScope( m_currentScope );
	
	int line, col;
	ast->getStartPosition( &line, &col );
	tag.setStartPosition( line, col );
	
	ast->getEndPosition( &line, &col );
	tag.setEndPosition( line, col );
	
	m_catalog->addItem( tag );
	
	TQPtrList<EnumeratorAST> l = ast->enumeratorList();
	TQPtrListIterator<EnumeratorAST> it( l );
	while ( it.current() )
	{
		TQString name = it.current() ->id() ->text();
		
		Tag tag;
		tag.setKind( Tag::Kind_Enumerator );
		tag.setComment( it.current()->comment() );
		
		tag.setFileName( m_fileName );
		tag.setName( name );
		tag.setScope( m_currentScope );

		if( ast->name() ) {
			tag.setAttribute( "enum", ast->name()->text() );
		} else {
			tag.setAttribute( "enum", "const int" );
		}
		
		int line, col;
		it.current() ->getStartPosition( &line, &col );
		tag.setStartPosition( line, col );
		
		it.current() ->getEndPosition( &line, &col );
		tag.setEndPosition( line, col );
		
		m_catalog->addItem( tag );
		
		++it;
	}
	
	TreeParser::parseEnumSpecifier( ast );
}

void TagCreator::parseMyDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl )
{
	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();
	
	TQString scopeStr = scopeOfDeclarator( d );
	
	TQString type = typeOfDeclaration( typeSpec, d );
	
	
	bool isFriend = false;
	//bool isVirtual = false;
	bool isStatic = false;
	//bool isInline = false;
	//bool isInitialized = decl->initializer() != 0;
	
	if ( storageSpec )
	{
		TQPtrList<AST> l = storageSpec->nodeList();
		TQPtrListIterator<AST> it( l );
		while ( it.current() )
		{
			TQString text = it.current() ->text();
			if ( text == "friend" )
				isFriend = true;
			else if ( text == "static" )
				isStatic = true;
			++it;
		}
	}
	
	Tag tag;
	CppVariable<Tag> tagBuilder( tag );
	
	tag.setKind( Tag::Kind_Variable );
	tag.setFileName( m_fileName );
	tag.setName( id );
	tag.setScope( TQStringList::split( ".", scopeStr ) );
	if( !comment().isEmpty() )
		tag.setComment( comment() );
	
	int line, col;
	decl->getStartPosition( &line, &col );
	tag.setStartPosition( line, col );
	
	decl->getEndPosition( &line, &col );
	tag.setEndPosition( line, col );
	
	tagBuilder.setType( type );
	tagBuilder.setFriend( isFriend );
	tagBuilder.setStatic( isStatic );
	tagBuilder.setAccess( TagUtils::stringToAccess( m_currentAccess ) );
	
	m_catalog->addItem( tag );
}

void TagCreator::parseAccessDeclaration( AccessDeclarationAST * access )
{
	TQPtrList<AST> l = access->accessList();
	
	m_currentAccess = l.at( 0 )->text();
	if( m_currentAccess == "signals" )
		m_currentAccess = "protected";
	
	m_inSlots = l.count() > 1 ? l.at( 1 )->text() == "slots" : false;
	m_inSignals = l.count() >= 1 ? l.at( 0 )->text() == "signals" : false;
}

void TagCreator::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<AST> l = funSpec->nodeList();
		TQPtrListIterator<AST> 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<AST> l = storageSpec->nodeList();
		TQPtrListIterator<AST> 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();

	TQString type = typeOfDeclaration( typeSpec, d );

	Tag tag;
	CppFunction<Tag> tagBuilder( tag );

	if( !comment().isEmpty() )
		tag.setComment( comment() );
	tag.setKind( Tag::Kind_FunctionDeclaration );
	tag.setFileName( m_fileName );
	tag.setName( id );
	tag.setScope( m_currentScope );

	int line, col;
	decl->getStartPosition( &line, &col );
	tag.setStartPosition( line, col );

	decl->getEndPosition( &line, &col );
	tag.setEndPosition( line, col );

	tagBuilder.setType( type );
	tagBuilder.setFriend( isFriend );
	tagBuilder.setVirtual( isVirtual );
	tagBuilder.setStatic( isStatic );
	tagBuilder.setInline( isInline );
	tagBuilder.setPure( isPure );
	tagBuilder.setConst( d->constant() != 0 );
	tagBuilder.setSignal( m_inSignals );
	tagBuilder.setSlot( m_inSlots );

	parseFunctionArguments( tag, d );
	checkTemplateDeclarator( tag );
	
	TQString arguments = tag.attribute( "a" ).toStringList().join( "," );
	TQString scopeStr = m_currentScope.join( "::" );
	tag.setAttribute( "description", m_documentation->functionDescription( scopeStr, id, type, arguments ) );

	m_catalog->addItem( tag );
}

void TagCreator::parseFunctionArguments( Tag& tag, DeclaratorAST* declarator )
{
	ParameterDeclarationClauseAST* clause = declarator->parameterDeclarationClause();
	
	TQStringList types;
	TQStringList args;
	if( clause && clause->parameterDeclarationList() ){
		ParameterDeclarationListAST* params = clause->parameterDeclarationList();
		TQPtrList<ParameterDeclarationAST> l( params->parameterList() );
		TQPtrListIterator<ParameterDeclarationAST> it( l );
		
		while( it.current() ){
			ParameterDeclarationAST* param = it.current();
			++it;
			
			TQString name;
			if( param->declarator() ){
				name = declaratorToString(param->declarator(), TQString(), true );
			}
			
			TQString type = typeOfDeclaration( param->typeSpec(), param->declarator() );
			
			types << type;
			args << name;
		}
		
		if( clause->ellipsis() ){
			types << "...";
			args << "";
		}
		
	}
	
	CppFunction<Tag> tagBuilder( tag );
	
	tagBuilder.setArguments( types );
	tagBuilder.setArgumentNames( args );
}

TQString TagCreator::typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator )
{
	if( !typeSpec || !declarator )
		return TQString();
	
	TQString text;
	
	text += typeSpec->text();
	text = text.simplifyWhiteSpace();
	
	TQPtrList<AST> ptrOpList = declarator->ptrOpList();
	for( TQPtrListIterator<AST> it(ptrOpList); it.current(); ++it )
		text += it.current()->text();
	
    for( int a = 0; a < declarator->arrayDimensionList().count(); a++ )
        text += "*";
	
  return text;
}

void TagCreator::parseBaseClause( const TQString& className, BaseClauseAST * baseClause )
{
	TQPtrList<BaseSpecifierAST> l = baseClause->baseSpecifierList();
	TQPtrListIterator<BaseSpecifierAST> it( l );
	while ( it.current() )
	{
		BaseSpecifierAST * baseSpecifier = it.current();
		
		TQString access;
		if ( baseSpecifier->access() )
			access = baseSpecifier->access() ->text();
		bool isVirtual = baseSpecifier->isVirtual() != 0;
		
		if( baseSpecifier->name() == 0 ) return; ///Workaround for some bug elsewhere

		TQString baseName;
		if ( baseSpecifier->name() )
			baseName = baseSpecifier->name() ->text();

		Tag tag;
		CppBaseClass<Tag> tagBuilder( tag );
		
		tag.setKind( Tag::Kind_Base_class );
		tag.setFileName( m_fileName );
		tag.setName( className );
		tag.setScope( m_currentScope );
		
		tagBuilder.setBaseClass( baseName );
		tagBuilder.setVirtual( isVirtual );
		tagBuilder.setAccess( TagUtils::stringToAccess( access ) );
		
		int line, col;
		baseClause->getStartPosition( &line, &col );
		tag.setStartPosition( line, col );
		
		baseClause->getEndPosition( &line, &col );
		tag.setEndPosition( line, col );
		
        m_catalog->addItem( tag );
		
        ++it;
	}
}

TQString TagCreator::scopeOfDeclarator( DeclaratorAST* d )
{
	TQStringList scope = m_currentScope;
	if ( d && d->declaratorId() && d->declaratorId() ->classOrNamespaceNameList().count() )
	{
		if ( d->declaratorId() ->isGlobal() )
			scope.clear();
		TQPtrList<ClassOrNamespaceNameAST> l = d->declaratorId() ->classOrNamespaceNameList();
		TQPtrListIterator<ClassOrNamespaceNameAST> it( l );
		while ( it.current() )
		{
			if ( it.current() ->name() )
				scope << it.current() ->name() ->text();
			
			++it;
		}
	}
	
	return scope.join( "." );
}

int TagUtils::stringToAccess( const TQString & access )
{
	TQStringList l = TQStringList()
		<< "public" << "protected" << "private"
		<< "public slots" << "protected slots" << "private slots"
		<< "signals";
	
	int idx = l.findIndex( access );
	return idx == -1 ? 0 : idx+1;
}

TQString TagUtils::accessToString( int id )
{
	if( id == 0 ) return "unknown";
	
	TQStringList l = TQStringList()
		<< "public" << "protected" << "private"
		<< "public slots" << "protected slots" << "private slots"
		<< "signals";
	
	if( l.at(id-1) != l.end() )
		return l[ id-1 ];
	
	return TQString();
}
