diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/code.l | 20 | ||||
-rw-r--r-- | src/docparser.cpp | 2 | ||||
-rw-r--r-- | src/doxygen.cpp | 250 | ||||
-rw-r--r-- | src/doxygen.h | 1 | ||||
-rw-r--r-- | src/htmlgen.cpp | 2 | ||||
-rw-r--r-- | src/htmlhelp.cpp | 8 | ||||
-rw-r--r-- | src/namespacedef.cpp | 14 | ||||
-rw-r--r-- | src/pre.l | 2 | ||||
-rw-r--r-- | src/scanner.l | 50 |
9 files changed, 225 insertions, 124 deletions
@@ -909,6 +909,10 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, { //printf("non-dummy context lcd=%s!\n",lcd->name().data()); g_theCallContext.setClass(lcd); + if (getLink(g_classScope,clName,ol,clName)) + { + return; + } } isLocal=TRUE; //fprintf(stderr,"is a local variable cd=%p!\n",cd); @@ -1014,7 +1018,7 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,ClassDef *mcd,const } } - ClassDef *typeClass = stripClassName(xmd->typeString()); + ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString())); //fprintf(stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass); g_theCallContext.setClass(typeClass); @@ -2055,6 +2059,13 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} endFontClass(); g_name.resize(0);g_type.resize(0); } +<Body>{FLOWKW}/{B}*"(" { + startFontClass("keywordflow"); + codifyLines(yytext); + endFontClass(); + g_name.resize(0);g_type.resize(0); + BEGIN(FuncCall); + } <Body>{FLOWKW}/([^a-z_A-Z0-9]) { startFontClass("keywordflow"); codifyLines(yytext); @@ -2069,13 +2080,6 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} codifyLines(yytext); endFontClass(); } -<Body>{FLOWKW}/{B}*"(" { - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - g_name.resize(0);g_type.resize(0); - BEGIN(FuncCall); - } <Body>[\\|\)\+\-\/\%\~\!] { g_code->codify(yytext); g_name.resize(0);g_type.resize(0); diff --git a/src/docparser.cpp b/src/docparser.cpp index ee03c9a..b8d11e7 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -262,7 +262,7 @@ static void checkArgumentName(const QString &name,bool isParam) static QRegExp re("[a-zA-Z0-9_]+\\.*"); int p=0,i=0,l; - while ((i=re.match(name,p,&l))!=-1) + while ((i=re.match(name,p,&l))!=-1) // to handle @param x,y { QString aName=name.mid(i,l); //printf("aName=`%s'\n",aName.data()); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 0e3133d..66406bb 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -43,7 +43,6 @@ #include "dot.h" #include "docparser.h" #include "dirdef.h" - #include "outputlist.h" #include "declinfo.h" #include "htmlgen.h" @@ -73,8 +72,7 @@ #define pclose _pclose #endif -static QDict<Entry> classEntries(1009); - +// globally accessible variables ClassSDict Doxygen::classSDict(1009); ClassSDict Doxygen::hiddenClasses(257); @@ -126,11 +124,18 @@ QCache<LookupInfo> Doxygen::lookupCache(20000,20000); DirSDict Doxygen::directories(17); SDict<DirRelation> Doxygen::dirRelations(257); ParserManager *Doxygen::parserManager = 0; +QCString Doxygen::htmlFileExtension; +// locally accessible globals +static QDict<Entry> classEntries(1009); static StringList inputFiles; static StringDict excludeNameDict(1009); // sections static QDict<void> compoundKeywordDict(7); // keywords recognised as compounds static OutputList *outputList = 0; // list of output generating objects +static QDict<FileDef> g_usingDeclarations(1009); // used classes +static const char idMask[] = "[A-Za-z_][A-Za-z_0-9]*"; + +QCString spaces; void clearAll() @@ -201,9 +206,6 @@ static void findMember(Entry *root, bool isFunc ); -const char idMask[] = "[A-Za-z_][A-Za-z_0-9]*"; -QCString spaces; -QCString Doxygen::htmlFileExtension; struct STLInfo { @@ -396,32 +398,6 @@ static void addRelatedPage(Entry *root) ); if (pd) { -#if 0 - Definition *ctx = 0; - - // find the page's context - if (root->parent->section & Entry::COMPOUND_MASK ) // inside class - { - QCString fullName=removeRedundantWhiteSpace(root->parent->name); - fullName=stripAnonymousNamespaceScope(fullName); - fullName=stripTemplateSpecifiersFromScope(fullName); - ctx=getClass(fullName); - } - if (ctx==0 && root->parent->section == Entry::NAMESPACE_SEC ) // inside namespace - { - QCString nscope=removeAnonymousScopes(root->parent->name); - if (!nscope.isEmpty()) - { - ctx = getResolvedNamespace(nscope); - } - } - if (ctx==0) // inside file - { - bool ambig; - ctx=findFileDef(Doxygen::inputNameDict,root->fileName,ambig); - } - pd->setOuterScope(ctx); -#endif pd->addSectionsToDefinition(root->anchors); //pi->context = ctx; } @@ -747,7 +723,57 @@ static Definition *findScope(Entry *root,int level=0) return result; } -static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n) +/*! returns the Definition object belonging to the first \a level levels of + * full qualified name \a name. Creates an artificial scope if the scope is + * not found and set the parent/child scope relation if the scope is found. + */ +static Definition *buildScopeFromQualifiedName(const QCString name,int level) +{ + int i=0; + int p=0,l; + Definition *prevScope=Doxygen::globalScope; + QCString fullScope; + while (i<level) + { + int idx=getScopeFragment(name,p,&l); + QCString nsName = name.mid(idx,l); + if (!fullScope.isEmpty()) fullScope+="::"; + fullScope+=nsName; + NamespaceDef *nd=Doxygen::namespaceSDict.find(fullScope); + Definition *innerScope = nd; + ClassDef *cd=0; + if (nd==0) cd = getClass(fullScope); + if (nd==0 && cd) // scope is a class + { + innerScope = cd; + } + else if (nd==0 && cd==0) // scope is not known! + { + // introduce bogus namespace + //printf("adding dummy namespace %s to %s\n",nsName.data(),prevScope->name().data()); + nd=new NamespaceDef( + "[generated]",1,fullScope); + + // add namespace to the list + Doxygen::namespaceSDict.inSort(fullScope,nd); + innerScope = nd; + } + else // scope is a namespace + { + } + // make the parent/child scope relation + prevScope->addInnerCompound(innerScope); + innerScope->setOuterScope(prevScope); + // proceed to the next scope fragment + p=idx+l+2; + prevScope=innerScope; + i++; + } + return prevScope; +} + +static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n, + FileDef *fileScope=0) { //printf("findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data()); Definition *resultScope=startScope; @@ -760,13 +786,55 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr while ((i2=getScopeFragment(scope,p,&l2))!=-1) { QCString nestedNameSpecifier = scope.mid(i1,l1); - //Definition *oldScope = resultScope; + Definition *orgScope = resultScope; resultScope = resultScope->findInnerCompound(nestedNameSpecifier); if (resultScope==0) { - //printf("name %s not found in scope %s\n",nestedNameSpecifier.data(),oldScope->name().data()); + if (orgScope==Doxygen::globalScope && fileScope) + // also search for used namespaces + { + NamespaceSDict *usedNamespaces = fileScope->getUsedNamespaces(); + if (usedNamespaces) + { + NamespaceSDict::Iterator ni(*usedNamespaces); + NamespaceDef *nd; + for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni) + { + // restart search within the used namespace + resultScope = findScopeFromQualifiedName(nd,n,fileScope); + } + if (resultScope) goto nextFragment; + } + } + + // also search for used classes. Complication: we haven't been able + // to put them in the right scope yet, because we are still resolving + // the scope relations! + // Therefore loop through all used classes and see if there is a right + // scope match between the used class and nestedNameSpecifier. + QDictIterator<FileDef> ui(g_usingDeclarations); + FileDef *usedFd; + for (ui.toFirst();(usedFd=ui.current());++ui) + { + //printf("Checking using class %s\n",ui.currentKey()); + if (rightScopeMatch(ui.currentKey(),nestedNameSpecifier)) + { + // ui.currentKey() is the fully qualified name of nestedNameSpecifier + // so use this instead. + QCString fqn = QCString(ui.currentKey())+ + scope.right(scope.length()-p); + resultScope = buildScopeFromQualifiedName(fqn,fqn.contains("::")); + //printf("Creating scope from fqn=%s result %p\n",fqn.data(),resultScope); + //resultScope = findScopeFromQualifiedName(startScope,fqn,usedFd); + //printf("Match! resultScope=%p\n",resultScope); + if (resultScope) return resultScope; + } + } + + //printf("name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data()); return 0; } + nextFragment: i1=i2; l1=l2; p=i2+l2; @@ -840,23 +908,6 @@ static ClassDef::CompoundType convertToCompoundType(int section) static void addClassToContext(Entry *root) { -// QCString fullName=removeRedundantWhiteSpace(root->name); -// -// if (fullName.isEmpty()) -// { -// // this should not be called -// warn(root->fileName,root->startLine, -// "Warning: invalid class name found!" -// ); -// return; -// } -// Debug::print(Debug::Classes,0," Found class with raw name %s\n",fullName.data()); -// -// fullName=stripAnonymousNamespaceScope(fullName); -// fullName=stripTemplateSpecifiersFromScope(fullName); -// -// Debug::print(Debug::Classes,0," Found class with name %s\n",fullName.data()); - bool ambig; //NamespaceDef *nd = 0; @@ -945,6 +996,7 @@ static void addClassToContext(Entry *root) ClassDef::CompoundType sec = convertToCompoundType(root->section); Debug::print(Debug::Classes,0," New class `%s' (sec=0x%08x)! #tArgLists=%d\n", fullName.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1); + QCString className; QCString namespaceName; extractNamespaceName(fullName,className,namespaceName); @@ -1049,38 +1101,6 @@ static void buildClassDocList(Entry *root) } } -Definition *buildScopeFromQualifiedName(const QCString name,int level) -{ - int i=0; - int p=0,l; - Definition *prevScope=Doxygen::globalScope; - QCString fullScope; - while (i<level) - { - int idx=getScopeFragment(name,p,&l); - QCString nsName = name.mid(idx,l); - if (!fullScope.isEmpty()) fullScope+="::"; - fullScope+=nsName; - NamespaceDef *nd=Doxygen::namespaceSDict.find(fullScope); - if (nd==0) - { - // introduce bogus namespace - //printf("adding dummy namespace %s to %s\n",nsName.data(),prevScope->name().data()); - nd=new NamespaceDef( - "[generated]",1,fullScope); - - // add namespace to the list - Doxygen::namespaceSDict.inSort(fullScope,nd); - } - prevScope->addInnerCompound(nd); - nd->setOuterScope(prevScope); - p=idx+l+2; - prevScope=nd; - i++; - } - return prevScope; -} - static void resolveClassNestingRelations() { ClassSDict::Iterator cli(Doxygen::classSDict); @@ -1103,16 +1123,18 @@ static void resolveClassNestingRelations() cd->visited=TRUE; //printf("Level=%d processing=%s\n",nestingLevel,cd->name().data()); // also add class to the correct structural context - Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,cd->name()); - if (d==0) + Definition *d = findScopeFromQualifiedName(Doxygen::globalScope, + cd->name(),cd->getFileDef()); + if (d==0) // we didn't find anything, create the scope artificially + // anyway, so we can at least relate scopes properly. { Definition *d = buildScopeFromQualifiedName(cd->name(),cd->name().contains("::")); d->addInnerCompound(cd); cd->setOuterScope(d); - //warn(cd->getDefFileName(),cd->getDefLine(), - // "Warning: Internal inconsistency: scope for class %s not " - // "found!\n",cd->name().data() - // ); + warn(cd->getDefFileName(),cd->getDefLine(), + "Warning: Internal inconsistency: scope for class %s not " + "found!\n",cd->name().data() + ); } else { @@ -1231,7 +1253,8 @@ static void buildNamespaceList(Entry *root) // also add namespace to the correct structural context Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,fullName); //printf("adding namespace %s to context %s\n",nd->name().data(),d?d->name().data():"none"); - if (d==0) + if (d==0) // we didn't find anything, create the scope artificially + // anyway, so we can at least relate scopes properly. { Definition *d = buildScopeFromQualifiedName(fullName,fullName.contains("::")); d->addInnerCompound(nd); @@ -1364,6 +1387,32 @@ static void findUsingDirectives(Entry *root) //---------------------------------------------------------------------- +static void buildListOfUsingDecls(Entry *root) +{ + if (root->section==Entry::USINGDECL_SEC && + !(root->parent->section&Entry::COMPOUND_MASK) // not a class/struct member + ) + { + QCString name = substitute(root->name,".","::"); + if (g_usingDeclarations.find(name)==0) + { + bool ambig; + FileDef *fd = findFileDef(Doxygen::inputNameDict,root->fileName,ambig); + if (fd) + { + g_usingDeclarations.insert(name,fd); + } + } + } + EntryListIterator eli(*root->sublist); + Entry *e; + for (;(e=eli.current());++eli) + { + buildListOfUsingDecls(e); + } +} + + static void findUsingDeclarations(Entry *root) { if (root->section==Entry::USINGDECL_SEC && @@ -2420,19 +2469,22 @@ static void buildFunctionList(Entry *root) // root->type.find(re,0)); QCString scope=root->parent->name; //stripAnonymousNamespaceScope(root->parent->name); scope=stripTemplateSpecifiersFromScope(scope,FALSE); - //printf("scope=%s\n",scope.data()); + + bool ambig; + FileDef *rfd=findFileDef(Doxygen::inputNameDict,root->fileName,ambig); + + int memIndex=rname.findRev("::"); cd=getClass(scope); - //printf("cd=%p\n",cd); if (cd && scope+"::"==rname.left(scope.length()+2)) // found A::f inside A { // strip scope from name rname=rname.right(rname.length()-root->parent->name.length()-2); } + NamespaceDef *nd = 0; bool isMember=FALSE; - int memIndex=rname.findRev("::"); if (memIndex!=-1) { int ts=rname.find('<'); @@ -2452,6 +2504,7 @@ static void buildFunctionList(Entry *root) { isMember=memIndex<ts || memIndex>te; } + } if (root->parent && @@ -2501,8 +2554,6 @@ static void buildFunctionList(Entry *root) QCString nsName,rnsName; if (mnd) nsName = mnd->name().copy(); if (rnd) rnsName = rnd->name().copy(); - bool ambig; - FileDef *rfd=findFileDef(Doxygen::inputNameDict,root->fileName,ambig); //printf("matching arguments for %s%s %s%s\n", // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data()); if ( @@ -8608,15 +8659,22 @@ void parseInput() msg("Associating documentation with classes...\n"); buildClassDocList(root); + // build list of using declarations here (global list) + buildListOfUsingDecls(root); + msg("Computing nesting relations for classes...\n"); resolveClassNestingRelations(); + // calling buildClassList may result in cached relations that // become invalid after resolveClassNestingRelation(), that's why // we need to clear the cache here Doxygen::lookupCache.clear(); + // we don't need the list of using declaration anymore + g_usingDeclarations.clear(); msg("Searching for members imported via using declarations...\n"); findUsingDeclImports(root); + findUsingDeclarations(root); msg("Building example list...\n"); diff --git a/src/doxygen.h b/src/doxygen.h index dd6ae1f..5f9dd16 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -64,7 +64,6 @@ struct LookupInfo QCString templSpec; }; - extern QCString spaces; /*! \brief This class serves as a namespace for global variables used by doxygen. diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 9ff634d..45f495b 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -1747,7 +1747,7 @@ static void writeDefaultQuickLinks(QTextStream &t,bool compact, { t << " <li>\n"; t << " <form action=\"search.php\" method=\"get\">\n"; - t << " <table cellspacing=\"0\" callpadding=\"0\" border=\"0\">\n"; + t << " <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n"; t << " <tr>\n"; t << " <td><label> " << searchFor << " </label></td>\n"; if (hli!=HLI_Search) diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index 4836663..825a4be 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -446,10 +446,10 @@ void HtmlHelp::createProjectFile() t << s << endl; s = indexFiles.next(); } - t << "tabs.css"; - t << "tab_b.gif"; - t << "tab_l.gif"; - t << "tab_r.gif"; + t << "tabs.css" << endl; + t << "tab_b.gif" << endl; + t << "tab_l.gif" << endl; + t << "tab_r.gif" << endl; f.close(); } else diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index b7c92d8..32bdf87 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -516,7 +516,19 @@ QCString NamespaceDef::getOutputFileBase() const Definition *NamespaceDef::findInnerCompound(const char *n) { if (n==0) return 0; - return m_innerCompounds->find(n); + Definition *d = m_innerCompounds->find(n); + if (d==0) + { + if (usingDirList) + { + d = usingDirList->find(n); + } + if (d==0 && usingDeclList) + { + d = usingDirList->find(n); + } + } + return d; } void NamespaceDef::addListReferences() @@ -1389,6 +1389,8 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yytext,yyleng); } } +<CopyLine>"\\"\r?/\n { // strip line continuation characters + } <CopyLine>. { outputChar(*yytext); } diff --git a/src/scanner.l b/src/scanner.l index b69690c..b41027f 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -82,6 +82,7 @@ static Entry* global_root = 0 ; static Entry* current = 0 ; static Entry* previous = 0 ; static Entry* tempEntry = 0 ; +static Entry* firstTypedefEntry = 0 ; static int yyLineNr = 1 ; static int anonCount = 0 ; static QCString yyFileName; @@ -1478,7 +1479,7 @@ IDLATTR ("["[^\]]*"]"){BN}* <QtPropType>{B}+ { current->type+=yytext; } -<QtPropType>{ID} { +<QtPropType>({ID}"::")*{ID} { current->type+=yytext; BEGIN(QtPropName); } @@ -2343,7 +2344,6 @@ IDLATTR ("["[^\]]*"]"){BN}* if (!cn.isEmpty() && !rn.isEmpty()) { prependScope(); - //cn.prepend(rn+"::"); } if (isTypedef && cn.isEmpty()) { @@ -2420,8 +2420,13 @@ IDLATTR ("["[^\]]*"]"){BN}* current->type = current->type.simplifyWhiteSpace(); //printf("Adding compound %s %s %s\n",current->type.data(),current->name.data(),current->args.data()); current_root->addSubEntry( current ) ; + if (!firstTypedefEntry) + { + firstTypedefEntry = current; + } current = new Entry; initEntry(); + isTypedef=TRUE; // to undo reset by initEntry() BEGIN(MemberSpecSkip); } <TypedefName>";" { /* typedef of anonymous type */ @@ -2438,7 +2443,7 @@ IDLATTR ("["[^\]]*"]"){BN}* unput(';'); BEGIN( MemberSpec ) ; } -<MemberSpec>([*&]*{BN}*)*{ID}("["[^\]\n]*"]")* { // the [] part could be improved. +<MemberSpec>([*&]*{BN}*)*{ID}{BN}*("["[^\]\n]*"]")* { // the [] part could be improved. lineCount(); int i=0,l=yyleng,j; while (i<l && (!isId(yytext[i]))) i++; @@ -2451,11 +2456,31 @@ IDLATTR ("["[^\]]*"]"){BN}* msName=msName.left(j); } msType = yytext; msType=msType.left(i); + + // handle *pName in: typedef { ... } name, *pName; + if (firstTypedefEntry) + { + if (firstTypedefEntry->section==Entry::STRUCT_SEC) + { + msType.prepend("struct "+firstTypedefEntry->name); + } + else if (firstTypedefEntry->section==Entry::UNION_SEC) + { + msType.prepend("union "+firstTypedefEntry->name); + } + else if (firstTypedefEntry->section==Entry::ENUM_SEC) + { + msType.prepend("enum "+firstTypedefEntry->name); + } + else + { + msType.prepend(firstTypedefEntry->name); + } + } } <MemberSpec>[,;] { //printf("current->name=`%s' msName=`%s'\n",current->name.data(),msName.data()); if (msName.isEmpty() && !current->name.isEmpty()) - /* && (current->section & Entry::COMPOUND_MASK)) */ { // see if the compound does not have a name or is inside another // annonymous compound. If so we insert a @@ -2497,14 +2522,14 @@ IDLATTR ("["[^\]]*"]"){BN}* if (isTypedef) { varEntry->type.prepend("typedef "); - // //printf("current->name = %s %s\n",current->name.data(),msName.data()); - // if (!current->name.isEmpty() && current->name.at(0)!='@') - // { - // //printf("2>>>>>>>>>> adding %s->%s\n",msName.data(),current->name.data()); - // QCString scope; - // if (current_root->section & Entry::SCOPE_MASK) scope=current_root->name; - // Doxygen::typedefDict.insert(msName,new TypedefInfo(current->name,scope)); - // } + // //printf("current->name = %s %s\n",current->name.data(),msName.data()); + // if (!current->name.isEmpty() && current->name.at(0)!='@') + // { + // //printf("2>>>>>>>>>> adding %s->%s\n",msName.data(),current->name.data()); + // QCString scope; + // if (current_root->section & Entry::SCOPE_MASK) scope=current_root->name; + // Doxygen::typedefDict.insert(msName,new TypedefInfo(current->name,scope)); + // } } varEntry->type+=current->name+msType; varEntry->fileName = yyFileName; @@ -2543,6 +2568,7 @@ IDLATTR ("["[^\]]*"]"){BN}* msName.resize(0); msArgs.resize(0); isTypedef=FALSE; + firstTypedefEntry=0; current->reset(); initEntry(); BEGIN( FindMembers ); |