00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "tag_creator.h"
00013 #include "catalog.h"
00014 #include "ast_utils.h"
00015 #include "cpp_tags.h"
00016 #include "doxydoc.h"
00017
00018 #include <kdebug.h>
00019 #include <qfileinfo.h>
00020 #include <qregexp.h>
00021
00022 DoxyDoc* TagCreator::m_documentation = new DoxyDoc( QStringList() );
00023
00024 TagCreator::TagCreator( const QString& fileName, Catalog* c )
00025 : m_catalog( c ), m_fileName( fileName ), m_anon( 0 )
00026 {
00027 }
00028
00029 TagCreator::~TagCreator()
00030 {
00031 }
00032
00033 void TagCreator::destroyDocumentation(){
00034 delete m_documentation;
00035 }
00036
00037 void TagCreator::setDocumentationDirectories(const QStringList& str){
00038 if (m_documentation)
00039 delete m_documentation;
00040 m_documentation = new DoxyDoc(str);
00041 }
00042
00043 void TagCreator::parseDeclaration( DeclarationAST* ast )
00044 {
00045 if( ast->nodeType() == NodeType_AccessDeclaration ||
00046 m_currentAccess.isEmpty() ||
00047 m_currentAccess.contains("public") ||
00048 m_currentAccess.contains("protected") ||
00049 m_currentAccess.contains("signals") )
00050
00051 TreeParser::parseDeclaration( ast );
00052 }
00053
00054 void TagCreator::parseTranslationUnit( TranslationUnitAST* ast )
00055 {
00056 m_currentScope.clear();
00057 m_currentAccess = QString::null;
00058 m_inSlots = false;
00059 m_inSignals = false;
00060 m_anon = 0;
00061 m_imports.clear();
00062 m_inClass = false;
00063
00064 m_imports << QStringList();
00065 TreeParser::parseTranslationUnit( ast );
00066 m_imports.pop_back();
00067 }
00068
00069 void TagCreator::parseNamespace( NamespaceAST* ast )
00070 {
00071 QString nsName;
00072 if( !ast->namespaceName() || ast->namespaceName()->text().isEmpty() ){
00073
00074 } else {
00075 nsName = ast->namespaceName()->text();
00076 }
00077
00078 Tag tag;
00079 tag.setKind( Tag::Kind_Namespace );
00080 tag.setFileName( m_fileName );
00081 tag.setName( nsName );
00082 tag.setScope( m_currentScope );
00083
00084 int line, col;
00085 ast->getStartPosition( &line, &col );
00086 tag.setStartPosition( line, col );
00087
00088 ast->getEndPosition( &line, &col );
00089 tag.setEndPosition( line, col );
00090
00091 m_catalog->addItem( tag );
00092
00093 m_currentScope.push_back( nsName );
00094 TreeParser::parseNamespace( ast );
00095 m_currentScope.pop_back();
00096 }
00097
00098 void TagCreator::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* ast )
00099 {
00100 TreeParser::parseElaboratedTypeSpecifier( ast );
00101 }
00102
00103 void TagCreator::parseUsingDirective( UsingDirectiveAST* ast )
00104 {
00105 QString name;
00106 if( ast->name() )
00107 name = ast->name()->text();
00108
00109 if( !name.isNull() ){
00110 Tag tag;
00111 tag.setKind( Tag::Kind_UsingDirective );
00112 tag.setFileName( m_fileName );
00113 tag.setName( name );
00114 tag.setScope( m_currentScope );
00115
00116 int line, col;
00117 ast->getStartPosition( &line, &col );
00118 tag.setStartPosition( line, col );
00119
00120 ast->getEndPosition( &line, &col );
00121 tag.setEndPosition( line, col );
00122
00123 m_catalog->addItem( tag );
00124 }
00125
00126 m_imports.back().push_back( name );
00127 }
00128
00129 void TagCreator::parseTypedef( TypedefAST* ast )
00130 {
00131 TypeSpecifierAST* typeSpec = ast->typeSpec();
00132 InitDeclaratorListAST* declarators = ast->initDeclaratorList();
00133
00134 if( typeSpec && declarators ){
00135 QString typeId;
00136
00137 if( typeSpec->name() )
00138 typeId = typeSpec->name()->text();
00139
00140 QPtrList<InitDeclaratorAST> l( declarators->initDeclaratorList() );
00141 QPtrListIterator<InitDeclaratorAST> it( l );
00142
00143 InitDeclaratorAST* initDecl = 0;
00144 while( 0 != (initDecl = it.current()) ){
00145
00146 QString type, id;
00147 if( initDecl->declarator() ){
00148 type = typeOfDeclaration( typeSpec, initDecl->declarator() );
00149
00150 DeclaratorAST* d = initDecl->declarator();
00151 while( d->subDeclarator() ){
00152 d = d->subDeclarator();
00153 }
00154
00155 if( d->declaratorId() )
00156 id = d->declaratorId()->text();
00157 }
00158
00159 Tag tag;
00160 tag.setKind( Tag::Kind_Typedef );
00161 tag.setFileName( m_fileName );
00162 tag.setName( id );
00163 tag.setScope( m_currentScope );
00164 tag.setAttribute( "t", type );
00165
00166 int line, col;
00167 initDecl->getStartPosition( &line, &col );
00168 tag.setStartPosition( line, col );
00169
00170 initDecl->getEndPosition( &line, &col );
00171 tag.setEndPosition( line, col );
00172
00173 m_catalog->addItem( tag );
00174
00175 ++it;
00176 }
00177
00178 }
00179 }
00180
00181 void TagCreator::parseTemplateDeclaration( TemplateDeclarationAST* ast )
00182 {
00183 if( ast->declaration() )
00184 parseDeclaration( ast->declaration() );
00185
00186 TreeParser::parseTemplateDeclaration( ast );
00187 }
00188
00189 void TagCreator::parseSimpleDeclaration( SimpleDeclarationAST* ast )
00190 {
00191 TypeSpecifierAST* typeSpec = ast->typeSpec();
00192 InitDeclaratorListAST* declarators = ast->initDeclaratorList();
00193
00194 if( typeSpec )
00195 parseTypeSpecifier( typeSpec );
00196
00197 if( declarators ){
00198 QPtrList<InitDeclaratorAST> l = declarators->initDeclaratorList();
00199
00200 QPtrListIterator<InitDeclaratorAST> it( l );
00201 while( it.current() ){
00202 parseMyDeclaration( ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, it.current() );
00203 ++it;
00204 }
00205 }
00206 }
00207
00208 void TagCreator::parseFunctionDefinition( FunctionDefinitionAST* ast )
00209 {
00210 TypeSpecifierAST* typeSpec = ast->typeSpec();
00211 GroupAST* funSpec = ast->functionSpecifier();
00212 GroupAST* storageSpec = ast->storageSpecifier();
00213
00214 if( !ast->initDeclarator() )
00215 return;
00216
00217 DeclaratorAST* d = ast->initDeclarator()->declarator();
00218
00219 if( !d->declaratorId() )
00220 return;
00221
00222 bool isFriend = false;
00223 bool isVirtual = false;
00224 bool isStatic = false;
00225 bool isInline = false;
00226
00227 if( funSpec ){
00228 QPtrList<AST> l = funSpec->nodeList();
00229 QPtrListIterator<AST> it( l );
00230 while( it.current() ){
00231 QString text = it.current()->text();
00232 if( text == "virtual" ) isVirtual = true;
00233 else if( text == "inline" ) isInline = true;
00234 ++it;
00235 }
00236 }
00237
00238 if( storageSpec ){
00239 QPtrList<AST> l = storageSpec->nodeList();
00240 QPtrListIterator<AST> it( l );
00241 while( it.current() ){
00242 QString text = it.current()->text();
00243 if( text == "friend" ) isFriend = true;
00244 else if( text == "static" ) isStatic = true;
00245 ++it;
00246 }
00247 }
00248
00249
00250 QString id = d->declaratorId()->unqualifiedName()->text().stripWhiteSpace();
00251 QString scopeStr = scopeOfDeclarator( d );
00252
00253 Tag tag;
00254 CppFunction<Tag> tagBuilder( tag );
00255 tag.setKind( Tag::Kind_Function );
00256
00257 tag.setFileName( m_fileName );
00258 tag.setName( id );
00259 tag.setScope( QStringList::split(".", scopeStr) );
00260
00261 int line, col;
00262 ast->getStartPosition( &line, &col );
00263 tag.setStartPosition( line, col );
00264
00265 ast->getEndPosition( &line, &col );
00266 tag.setEndPosition( line, col );
00267
00268 tagBuilder.setType( typeOfDeclaration(typeSpec, d) );
00269
00270 parseFunctionArguments( tag, d );
00271
00272 QString arguments = tag.attribute("a").toStringList().join(",");
00273 tag.setAttribute("description", m_documentation->functionDescription(scopeStr.replace(QRegExp("."),":"), id, typeOfDeclaration(typeSpec, d), arguments));
00274
00275 tagBuilder.setAccess( TagUtils::stringToAccess(m_currentAccess) );
00276
00277 tagBuilder.setFriend( isFriend );
00278 tagBuilder.setVirtual( isVirtual );
00279 tagBuilder.setStatic( isStatic );
00280 tagBuilder.setInline( isInline );
00281 tagBuilder.setPure( false );
00282 tagBuilder.setConst( d->constant() != 0 );
00283 tagBuilder.setSignal( m_inSignals );
00284 tagBuilder.setSlot( m_inSlots );
00285
00286 m_catalog->addItem( tag );
00287
00288 if( !m_currentAccess.isEmpty() ){
00289 tag.setKind( Tag::Kind_FunctionDeclaration );
00290 m_catalog->addItem( tag );
00291 }
00292 }
00293
00294 void TagCreator::parseLinkageBody( LinkageBodyAST* ast )
00295 {
00296 QPtrList<DeclarationAST> l = ast->declarationList();
00297 QPtrListIterator<DeclarationAST> it( l );
00298 while( it.current() ){
00299 parseDeclaration( it.current() );
00300 ++it;
00301 }
00302 }
00303
00304 void TagCreator::parseClassSpecifier( ClassSpecifierAST* ast )
00305 {
00306 int startLine, startColumn;
00307 int endLine, endColumn;
00308 ast->getStartPosition( &startLine, &startColumn );
00309 ast->getEndPosition( &endLine, &endColumn );
00310
00311 QString oldAccess = m_currentAccess;
00312 bool oldInSlots = m_inSlots;
00313 bool oldInSignals = m_inSignals;
00314
00315 QString kind = ast->classKey()->text();
00316 if( kind == "class" )
00317 m_currentAccess = "private";
00318 else
00319 m_currentAccess = "public";
00320 m_inSlots = false;
00321 m_inSignals = false;
00322
00323 QString className;
00324 if( !ast->name() ){
00325
00326
00327
00328 } else {
00329 className = ast->name()->text();
00330 }
00331
00332 Tag tag;
00333 tag.setKind( Tag::Kind_Class );
00334
00335 tag.setFileName( m_fileName );
00336 tag.setName( className );
00337 tag.setScope( m_currentScope );
00338
00339 int line, col;
00340 ast->getStartPosition( &line, &col );
00341 tag.setStartPosition( line, col );
00342
00343 ast->getEndPosition( &line, &col );
00344 tag.setEndPosition( line, col );
00345
00346 m_catalog->addItem( tag );
00347
00348 if ( ast->baseClause() )
00349 parseBaseClause( tag.path(), ast->baseClause() );
00350
00351 m_currentScope.push_back( className );
00352 int oldInClass = m_inClass;
00353 m_inClass = true;
00354 TreeParser::parseClassSpecifier( ast );
00355 m_currentScope.pop_back();
00356 m_inClass = oldInClass;
00357
00358 m_currentAccess = oldAccess;
00359 m_inSlots = oldInSlots;
00360 m_inSignals = oldInSignals;
00361 }
00362
00363 void TagCreator::parseEnumSpecifier( EnumSpecifierAST* ast )
00364 {
00365 Tag tag;
00366 tag.setKind( Tag::Kind_Enum );
00367
00368 tag.setFileName( m_fileName );
00369 if( ast->name() )
00370 tag.setName( ast->name()->text() );
00371 tag.setScope( m_currentScope );
00372
00373 int line, col;
00374 ast->getStartPosition( &line, &col );
00375 tag.setStartPosition( line, col );
00376
00377 ast->getEndPosition( &line, &col );
00378 tag.setEndPosition( line, col );
00379
00380 m_catalog->addItem( tag );
00381
00382 QPtrList<EnumeratorAST> l = ast->enumeratorList();
00383 QPtrListIterator<EnumeratorAST> it( l );
00384 while( it.current() ){
00385 QString name = it.current()->id()->text();
00386
00387 Tag tag;
00388 tag.setKind( Tag::Kind_Enumerator );
00389
00390 tag.setFileName( m_fileName );
00391 tag.setName( name );
00392 tag.setScope( m_currentScope );
00393
00394 int line, col;
00395 it.current()->getStartPosition( &line, &col );
00396 tag.setStartPosition( line, col );
00397
00398 it.current()->getEndPosition( &line, &col );
00399 tag.setEndPosition( line, col );
00400
00401 m_catalog->addItem( tag );
00402
00403 ++it;
00404 }
00405
00406 TreeParser::parseEnumSpecifier( ast );
00407 }
00408
00409 void TagCreator::parseMyDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl )
00410 {
00411 DeclaratorAST* d = decl->declarator();
00412
00413 if( !d )
00414 return;
00415
00416 if( !d->subDeclarator() && d->parameterDeclarationClause() )
00417 return parseFunctionDeclaration( funSpec, storageSpec, typeSpec, decl );
00418
00419 DeclaratorAST* t = d;
00420 while( t && t->subDeclarator() )
00421 t = t->subDeclarator();
00422
00423 QString id;
00424 if( t && t->declaratorId() && t->declaratorId()->unqualifiedName() )
00425 id = t->declaratorId()->unqualifiedName()->text();
00426
00427 QString scopeStr = scopeOfDeclarator( d );
00428
00429 QString type = typeOfDeclaration( typeSpec, d );
00430
00431
00432 bool isFriend = false;
00433
00434 bool isStatic = false;
00435
00436
00437
00438 if( storageSpec ){
00439 QPtrList<AST> l = storageSpec->nodeList();
00440 QPtrListIterator<AST> it( l );
00441 while( it.current() ){
00442 QString text = it.current()->text();
00443 if( text == "friend" ) isFriend = true;
00444 else if( text == "static" ) isStatic = true;
00445 ++it;
00446 }
00447 }
00448
00449 Tag tag;
00450 CppVariable<Tag> tagBuilder( tag );
00451
00452 tag.setKind( Tag::Kind_Variable );
00453 tag.setFileName( m_fileName );
00454 tag.setName( id );
00455 tag.setScope( QStringList::split(".",scopeStr) );
00456
00457 int line, col;
00458 decl->getStartPosition( &line, &col );
00459 tag.setStartPosition( line, col );
00460
00461 decl->getEndPosition( &line, &col );
00462 tag.setEndPosition( line, col );
00463
00464 tagBuilder.setType( type );
00465 tagBuilder.setFriend( isFriend );
00466 tagBuilder.setStatic( isStatic );
00467 tagBuilder.setAccess( TagUtils::stringToAccess(m_currentAccess) );
00468
00469 m_catalog->addItem( tag );
00470 }
00471
00472 void TagCreator::parseAccessDeclaration( AccessDeclarationAST * access )
00473 {
00474 QPtrList<AST> l = access->accessList();
00475
00476 m_currentAccess = l.at( 0 )->text();
00477 if( m_currentAccess == "signals" )
00478 m_currentAccess = "public";
00479
00480 m_inSlots = l.count() > 1 ? l.at( 1 )->text() == "slots" : false;
00481 m_inSignals = l.count() >= 1 ? l.at( 0 )->text() == "signals" : false;
00482 }
00483
00484 void TagCreator::parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec,
00485 TypeSpecifierAST * typeSpec, InitDeclaratorAST * decl )
00486 {
00487 bool isFriend = false;
00488 bool isVirtual = false;
00489 bool isStatic = false;
00490 bool isInline = false;
00491 bool isPure = decl->initializer() != 0;
00492
00493 if( funSpec ){
00494 QPtrList<AST> l = funSpec->nodeList();
00495 QPtrListIterator<AST> it( l );
00496 while( it.current() ){
00497 QString text = it.current()->text();
00498 if( text == "virtual" ) isVirtual = true;
00499 else if( text == "inline" ) isInline = true;
00500 ++it;
00501 }
00502 }
00503
00504 if( storageSpec ){
00505 QPtrList<AST> l = storageSpec->nodeList();
00506 QPtrListIterator<AST> it( l );
00507 while( it.current() ){
00508 QString text = it.current()->text();
00509 if( text == "friend" ) isFriend = true;
00510 else if( text == "static" ) isStatic = true;
00511 ++it;
00512 }
00513 }
00514
00515 int startLine, startColumn;
00516 int endLine, endColumn;
00517 decl->getStartPosition( &startLine, &startColumn );
00518 decl->getEndPosition( &endLine, &endColumn );
00519
00520 DeclaratorAST* d = decl->declarator();
00521 QString id = d->declaratorId()->unqualifiedName()->text();
00522
00523 QString type = typeOfDeclaration( typeSpec, d );
00524
00525 Tag tag;
00526 CppFunction<Tag> tagBuilder( tag );
00527
00528 tag.setKind( Tag::Kind_FunctionDeclaration );
00529 tag.setFileName( m_fileName );
00530 tag.setName( id );
00531 tag.setScope( m_currentScope );
00532
00533 int line, col;
00534 decl->getStartPosition( &line, &col );
00535 tag.setStartPosition( line, col );
00536
00537 decl->getEndPosition( &line, &col );
00538 tag.setEndPosition( line, col );
00539
00540 tagBuilder.setType( type );
00541 tagBuilder.setFriend( isFriend );
00542 tagBuilder.setVirtual( isVirtual );
00543 tagBuilder.setStatic( isStatic );
00544 tagBuilder.setInline( isInline );
00545 tagBuilder.setPure( isPure );
00546 tagBuilder.setConst( d->constant() != 0 );
00547 tagBuilder.setSignal( m_inSignals );
00548 tagBuilder.setSlot( m_inSlots );
00549
00550 parseFunctionArguments( tag, d );
00551
00552 QString arguments = tag.attribute("a").toStringList().join(",");
00553 QString scopeStr = m_currentScope.join("::");
00554 tag.setAttribute("description", m_documentation->functionDescription(scopeStr, id, type, arguments));
00555
00556 m_catalog->addItem( tag );
00557 }
00558
00559 void TagCreator::parseFunctionArguments( Tag& tag, DeclaratorAST* declarator )
00560 {
00561 ParameterDeclarationClauseAST* clause = declarator->parameterDeclarationClause();
00562
00563 QStringList types;
00564 QStringList args;
00565 if( clause && clause->parameterDeclarationList() ){
00566 ParameterDeclarationListAST* params = clause->parameterDeclarationList();
00567 QPtrList<ParameterDeclarationAST> l( params->parameterList() );
00568 QPtrListIterator<ParameterDeclarationAST> it( l );
00569
00570 while( it.current() ){
00571 ParameterDeclarationAST* param = it.current();
00572 ++it;
00573
00574 QString name;
00575 if( param->declarator() ){
00576 name = declaratorToString(param->declarator(), QString::null, true );
00577 }
00578
00579 QString type = typeOfDeclaration( param->typeSpec(), param->declarator() );
00580
00581 types << type;
00582 args << name;
00583 }
00584
00585 if( clause->ellipsis() ){
00586 types << "...";
00587 args << "";
00588 }
00589
00590 }
00591
00592 CppFunction<Tag> tagBuilder( tag );
00593
00594 tagBuilder.setArguments( types );
00595 tagBuilder.setArgumentNames( args );
00596 }
00597
00598 QString TagCreator::typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator )
00599 {
00600 if( !typeSpec || !declarator )
00601 return QString::null;
00602
00603 QString text;
00604
00605 text += typeSpec->text();
00606 text = text.simplifyWhiteSpace();
00607
00608 QPtrList<AST> ptrOpList = declarator->ptrOpList();
00609 for( QPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
00610 text += it.current()->text();
00611 }
00612
00613 return text;
00614 }
00615
00616 void TagCreator::parseBaseClause( const QString& className, BaseClauseAST * baseClause )
00617 {
00618 QPtrList<BaseSpecifierAST> l = baseClause->baseSpecifierList();
00619 QPtrListIterator<BaseSpecifierAST> it( l );
00620 while( it.current() ){
00621 BaseSpecifierAST* baseSpecifier = it.current();
00622
00623 QString access;
00624 if( baseSpecifier->access() )
00625 access = baseSpecifier->access()->text();
00626 bool isVirtual = baseSpecifier->isVirtual() != 0;
00627
00628 QString baseName;
00629
00630 QPtrList<ClassOrNamespaceNameAST> l = baseSpecifier->name()->classOrNamespaceNameList();
00631 QPtrListIterator<ClassOrNamespaceNameAST> nameIt( l );
00632 while( nameIt.current() ){
00633 if( nameIt.current()->name() ){
00634 baseName += nameIt.current()->name()->text() + "::";
00635 }
00636 ++nameIt;
00637 }
00638
00639 if( baseSpecifier->name()->unqualifiedName() && baseSpecifier->name()->unqualifiedName()->name() )
00640 baseName += baseSpecifier->name()->unqualifiedName()->name()->text();
00641
00642 Tag tag;
00643 CppBaseClass<Tag> tagBuilder( tag );
00644
00645 tag.setKind( Tag::Kind_Base_class );
00646 tag.setFileName( m_fileName );
00647 tag.setName( className );
00648 tag.setScope( m_currentScope );
00649
00650 tagBuilder.setBaseClass( baseName );
00651 tagBuilder.setVirtual( isVirtual );
00652 tagBuilder.setAccess( TagUtils::stringToAccess(access) );
00653
00654 m_catalog->addItem( tag );
00655
00656 int line, col;
00657 baseClause->getStartPosition( &line, &col );
00658 tag.setStartPosition( line, col );
00659
00660 baseClause->getEndPosition( &line, &col );
00661 tag.setEndPosition( line, col );
00662
00663 ++it;
00664 }
00665 }
00666
00667 QString TagCreator::scopeOfDeclarator( DeclaratorAST* d )
00668 {
00669 QStringList scope = m_currentScope;
00670 if( d && d->declaratorId() && d->declaratorId()->classOrNamespaceNameList().count() ){
00671 if( d->declaratorId()->isGlobal() )
00672 scope.clear();
00673 QPtrList<ClassOrNamespaceNameAST> l = d->declaratorId()->classOrNamespaceNameList();
00674 QPtrListIterator<ClassOrNamespaceNameAST> it( l );
00675 while( it.current() ){
00676 if( it.current()->name() ){
00677 scope << it.current()->name()->text();
00678 }
00679 ++it;
00680 }
00681 }
00682
00683 return scope.join( "." );
00684 }
00685
00686 int TagUtils::stringToAccess( const QString & access )
00687 {
00688 QStringList l = QStringList()
00689 << "public" << "protected" << "private"
00690 << "public slots" << "protected slots" << "private slots"
00691 << "signals";
00692
00693 int idx = l.findIndex( access );
00694 return idx == -1 ? 0 : idx+1;
00695 }
00696
00697 QString TagUtils::accessToString( int id )
00698 {
00699 QStringList l = QStringList()
00700 << "public" << "protected" << "private"
00701 << "public slots" << "protected slots" << "private slots"
00702 << "signals";
00703
00704 if( l.at(id-1) != l.end() )
00705 return l[ id-1 ];
00706
00707 return QString::null;
00708 }