/***************************************************************************
* 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 <kdebug.h>
# include <tqfileinfo.h>
# include <tqdir.h>
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 < FileModel > ( ) ;
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 < TQMap < TQString , ClassDom > , TQStringList > ( TQMap < TQString , ClassDom > ( ) , 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 < InitDeclaratorAST > 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 < 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 ( ) ;
}
TypeAliasDom typeAlias = m_store - > create < TypeAliasModel > ( ) ;
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 < InitDeclaratorAST > l = declarators - > initDeclaratorList ( ) ;
TQPtrListIterator < InitDeclaratorAST > 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 < 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 ;
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 < FunctionDefinitionModel > ( ) ;
method - > setScope ( scope ) ;
method - > setName ( id ) ;
parseFunctionArguments ( d , model_cast < FunctionDom > ( 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 < FunctionDom > ( method ) ) ;
else
m_file - > addFunction ( model_cast < FunctionDom > ( 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 < TemplateParameterAST > 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 < CodeModelItem * > ( & 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 < TQString , FileDom > : : 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 < ClassModel > ( ) ;
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 < TypeAliasModel > ( ) ;
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 < EnumeratorAST > l = ast - > enumeratorList ( ) ;
TQPtrListIterator < EnumeratorAST > it ( l ) ;
while ( it . current ( ) )
{
VariableDom attr = m_store - > create < VariableModel > ( ) ;
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 < VariableModel > ( ) ;
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 < 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 ) ;
attr - > setStartPosition ( startLine , startColumn ) ;
attr - > setEndPosition ( endLine , endColumn ) ;
attr - > setStatic ( isStatic ) ;
}
void StoreWalker : : parseAccessDeclaration ( AccessDeclarationAST * access )
{
TQPtrList < AST > 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 < NamespaceModel > ( ) ;
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 < 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 ( ) ;
FunctionDom method = m_store - > create < FunctionModel > ( ) ;
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 < ParameterDeclarationAST > l ( params - > parameterList ( ) ) ;
TQPtrListIterator < ParameterDeclarationAST > it ( l ) ;
while ( it . current ( ) )
{
ParameterDeclarationAST * param = it . current ( ) ;
+ + it ;
ArgumentDom arg = m_store - > create < ArgumentModel > ( ) ;
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 < 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 StoreWalker : : parseBaseClause ( BaseClauseAST * baseClause , ClassDom klass )
{
TQPtrList < BaseSpecifierAST > l = baseClause - > baseSpecifierList ( ) ;
TQPtrListIterator < BaseSpecifierAST > 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 < ClassOrNamespaceNameAST > l = id - > classOrNamespaceNameList ( ) ;
TQPtrListIterator < ClassOrNamespaceNameAST > 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 < TQString , ClassDom > 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 < TQString , FileDom > : : 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 < TQString , FileDom > : : 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 ) ;
}