diff options
Diffstat (limited to 'src/docparser.cpp')
-rw-r--r-- | src/docparser.cpp | 736 |
1 files changed, 374 insertions, 362 deletions
diff --git a/src/docparser.cpp b/src/docparser.cpp index 4db4dd7..f09a1ee 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -87,7 +87,7 @@ static const char *sectionLevelToName[] = //--------------------------------------------------------------------------- // Parser state: global variables during a call to validatingParseDoc -static Definition * g_scope; +static const Definition * g_scope; static QCString g_context; static bool g_inSeeBlock; static bool g_xmlComment; @@ -101,8 +101,9 @@ static QCString g_relPath; static bool g_hasParamCommand; static bool g_hasReturnCommand; +static QDict<void> g_retvalsFound; static QDict<void> g_paramsFound; -static MemberDef * g_memberDef; +static const MemberDef * g_memberDef; static bool g_isExample; static QCString g_exampleName; static SectionDict * g_sectionDict; @@ -112,13 +113,15 @@ static QCString g_includeFileName; static QCString g_includeFileText; static uint g_includeFileOffset; static uint g_includeFileLength; +static uint g_includeFileLine; +static bool g_includeFileShowLineNo; /** Parser's context to store all global variables. */ struct DocParserContext { - Definition *scope; + const Definition *scope; QCString context; bool inSeeBlock; bool xmlComment; @@ -133,7 +136,8 @@ struct DocParserContext bool hasParamCommand; bool hasReturnCommand; - MemberDef * memberDef; + const MemberDef * memberDef; + QDict<void> retvalsFound; QDict<void> paramsFound; bool isExample; QCString exampleName; @@ -143,6 +147,8 @@ struct DocParserContext QCString includeFileText; uint includeFileOffset; uint includeFileLength; + uint includeFileLine; + bool includeFileLineNo; TokenInfo *token; }; @@ -179,6 +185,7 @@ static void docParserPushContext(bool saveParamInfo=TRUE) ctx->hasParamCommand = g_hasParamCommand; ctx->hasReturnCommand = g_hasReturnCommand; ctx->paramsFound = g_paramsFound; + ctx->retvalsFound = g_retvalsFound; } ctx->memberDef = g_memberDef; @@ -190,6 +197,8 @@ static void docParserPushContext(bool saveParamInfo=TRUE) ctx->includeFileText = g_includeFileText; ctx->includeFileOffset = g_includeFileOffset; ctx->includeFileLength = g_includeFileLength; + ctx->includeFileLine = g_includeFileLine; + ctx->includeFileLineNo = g_includeFileShowLineNo; ctx->token = g_token; g_token = new TokenInfo; @@ -217,6 +226,7 @@ static void docParserPopContext(bool keepParamInfo=FALSE) { g_hasParamCommand = ctx->hasParamCommand; g_hasReturnCommand = ctx->hasReturnCommand; + g_retvalsFound = ctx->retvalsFound; g_paramsFound = ctx->paramsFound; } g_memberDef = ctx->memberDef; @@ -228,6 +238,8 @@ static void docParserPopContext(bool keepParamInfo=FALSE) g_includeFileText = ctx->includeFileText; g_includeFileOffset = ctx->includeFileOffset; g_includeFileLength = ctx->includeFileLength; + g_includeFileLine = ctx->includeFileLine; + g_includeFileShowLineNo = ctx->includeFileLineNo; delete g_token; g_token = ctx->token; @@ -388,19 +400,19 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool return result; } -/*! Collects the parameters found with \@param or \@retval commands - * in a global list g_paramsFound. If \a isParam is set to TRUE - * and the parameter is not an actual parameter of the current +/*! Collects the parameters found with \@param command + * in a global list g_paramsFound. If + * the parameter is not an actual parameter of the current * member g_memberDef, then a warning is raised (unless warnings * are disabled altogether). */ -static void checkArgumentName(const QCString &name,bool isParam) +static void checkArgumentName(const QCString &name) { if (!Config_getBool(WARN_IF_DOC_ERROR)) return; if (g_memberDef==0) return; // not a member - ArgumentList *al=g_memberDef->isDocsForDefinition() ? - g_memberDef->argumentList() : - g_memberDef->declArgumentList(); + const ArgumentList *al=g_memberDef->isDocsForDefinition() ? + g_memberDef->argumentList() : + g_memberDef->declArgumentList(); SrcLangExt lang = g_memberDef->getLanguage(); //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition()); if (al==0) return; // no argument list @@ -413,7 +425,7 @@ static void checkArgumentName(const QCString &name,bool isParam) if (lang==SrcLangExt_Fortran) aName=aName.lower(); //printf("aName=`%s'\n",aName.data()); ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; bool found=FALSE; for (ali.toFirst();(a=ali.current());++ali) { @@ -422,14 +434,14 @@ static void checkArgumentName(const QCString &name,bool isParam) argName=argName.stripWhiteSpace(); //printf("argName=`%s' aName=%s\n",argName.data(),aName.data()); if (argName.right(3)=="...") argName=argName.left(argName.length()-3); - if (aName==argName && isParam) + if (aName==argName) { g_paramsFound.insert(aName,(void *)(0x8)); found=TRUE; break; } } - if (!found && isParam) + if (!found) { //printf("member type=%d\n",g_memberDef->memberType()); QCString scope=g_memberDef->getScopeString(); @@ -457,6 +469,23 @@ static void checkArgumentName(const QCString &name,bool isParam) p=i+l; } } +/*! Collects the return values found with \@retval command + * in a global list g_retvalsFound. + */ +static void checkRetvalName(const QCString &name) +{ + if (!Config_getBool(WARN_IF_DOC_ERROR)) return; + if (g_memberDef==0 || name.isEmpty()) return; // not a member or no valid name + if (g_retvalsFound.find(name)) + { + warn_doc_error(g_memberDef->getDefFileName(), + g_memberDef->getDefLine(), + "return value '" + name + "' of " + + QCString(g_memberDef->qualifiedName()) + + " has multiple documentation sections"); + } + g_retvalsFound.insert(name,(void *)(0x8)); +} /*! Checks if the parameters that have been specified using \@param are * indeed all parameters and that a parameter does not have multiple @@ -468,14 +497,14 @@ static void checkUnOrMultipleDocumentedParams() { if (g_memberDef && g_hasParamCommand && Config_getBool(WARN_IF_DOC_ERROR)) { - ArgumentList *al=g_memberDef->isDocsForDefinition() ? + const ArgumentList *al=g_memberDef->isDocsForDefinition() ? g_memberDef->argumentList() : g_memberDef->declArgumentList(); SrcLangExt lang = g_memberDef->getLanguage(); if (al!=0) { ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; bool found=FALSE; for (ali.toFirst();(a=ali.current());++ali) { @@ -550,106 +579,6 @@ static void checkUnOrMultipleDocumentedParams() } } -/*! Check if a member has documentation for its parameter and or return - * type, if applicable. If found this will be stored in the member, this - * is needed as a member can have brief and detailed documentation, while - * only one of these needs to document the parameters. - */ -static void detectNoDocumentedParams() -{ - if (g_memberDef && Config_getBool(WARN_NO_PARAMDOC)) - { - ArgumentList *al = g_memberDef->argumentList(); - ArgumentList *declAl = g_memberDef->declArgumentList(); - QCString returnType = g_memberDef->typeString(); - bool isPython = g_memberDef->getLanguage()==SrcLangExt_Python; - - if (!g_memberDef->hasDocumentedParams() && - g_hasParamCommand) - { - //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data()); - g_memberDef->setHasDocumentedParams(TRUE); - } - else if (!g_memberDef->hasDocumentedParams()) - { - bool allDoc=TRUE; // no parameter => all parameters are documented - if ( // member has parameters - al!=0 && // but the member has a parameter list - al->count()>0 // with at least one parameter (that is not void) - ) - { - ArgumentListIterator ali(*al); - Argument *a; - - // see if all parameters have documentation - for (ali.toFirst();(a=ali.current()) && allDoc;++ali) - { - if (!a->name.isEmpty() && a->type!="void" && - !(isPython && (a->name=="self" || a->name=="cls")) - ) - { - allDoc = !a->docs.isEmpty(); - } - //printf("a->type=%s a->name=%s doc=%s\n", - // a->type.data(),a->name.data(),a->docs.data()); - } - if (!allDoc && declAl!=0) // try declaration arguments as well - { - allDoc=TRUE; - ArgumentListIterator ali(*declAl); - Argument *a; - for (ali.toFirst();(a=ali.current()) && allDoc;++ali) - { - if (!a->name.isEmpty() && a->type!="void" && - !(isPython && (a->name=="self" || a->name=="cls")) - ) - { - allDoc = !a->docs.isEmpty(); - } - //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data()); - } - } - } - if (allDoc) - { - //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data()); - g_memberDef->setHasDocumentedParams(TRUE); - } - } - //printf("Member %s hasDocumentedReturnType()=%d hasReturnCommand=%d\n", - // g_memberDef->name().data(),g_memberDef->hasDocumentedReturnType(),g_hasReturnCommand); - if (!g_memberDef->hasDocumentedReturnType() && // docs not yet found - g_hasReturnCommand) - { - g_memberDef->setHasDocumentedReturnType(TRUE); - } - else if ( // see if return type is documented in a function w/o return type - g_hasReturnCommand && - (//returnType.isEmpty() || // empty return type - returnType.find("void")!=-1 || // void return type - returnType.find("subroutine")!=-1 || // fortran subroutine - g_memberDef->isConstructor() || // a constructor - g_memberDef->isDestructor() // or destructor - ) - ) - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"documented empty return type of %s",g_memberDef->qualifiedName().data()); - } - else if ( // see if return needs to documented - g_memberDef->hasDocumentedReturnType() || - //returnType.isEmpty() || // empty return type - returnType.find("void")!=-1 || // void return type - returnType.find("subroutine")!=-1 || // fortran subroutine - g_memberDef->isConstructor() || // a constructor - g_memberDef->isDestructor() // or destructor - ) - { - g_memberDef->setHasDocumentedReturnType(TRUE); - } - } -} - - //--------------------------------------------------------------------------- /*! Strips known html and tex extensions from \a text. */ @@ -747,7 +676,7 @@ static bool insideTable(DocNode *n) static bool findDocsForMemberOrCompound(const char *commandName, QCString *pDoc, QCString *pBrief, - Definition **pDef) + const Definition **pDef) { //printf("findDocsForMemberOrCompound(%s)\n",commandName); *pDoc=""; @@ -781,12 +710,12 @@ static bool findDocsForMemberOrCompound(const char *commandName, QCString args=cmdArg.right(l-funcStart); // try if the link is to a member - MemberDef *md=0; - ClassDef *cd=0; - FileDef *fd=0; - NamespaceDef *nd=0; - GroupDef *gd=0; - PageDef *pd=0; + const MemberDef *md=0; + const ClassDef *cd=0; + const FileDef *fd=0; + const NamespaceDef *nd=0; + const GroupDef *gd=0; + const PageDef *pd=0; bool found = getDefs( g_context.find('.')==-1?g_context.data():"", // `find('.') is a hack to detect files name, @@ -908,8 +837,8 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return tok; } while ((tok=doctokenizerYYlex()) && @@ -944,7 +873,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, break; } } - DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(cmdName),tok)); + DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(saveCmdName),tok)); return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST ) ? tok : RetVal_OK; } @@ -1037,6 +966,11 @@ static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttrib { if (!opt->value.isEmpty()) { + // copy attributes + HtmlAttribList attrList = tagHtmlAttribs; + // and remove the href attribute + bool result = attrList.remove(index); + ASSERT(result); DocAnchor *anc = new DocAnchor(parent,opt->value,TRUE); children.append(anc); break; // stop looking for other tag attribs @@ -1082,7 +1016,9 @@ const char *DocStyleChange::styleString() const case DocStyleChange::Div: return "div"; case DocStyleChange::Span: return "span"; case DocStyleChange::Strike: return "strike"; + case DocStyleChange::Del: return "del"; case DocStyleChange::Underline: return "u"; + case DocStyleChange::Ins: return "ins"; } return "<invalid>"; } @@ -1112,8 +1048,8 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor // ------- try to turn the word 'name' into a link - Definition *compound=0; - MemberDef *member=0; + const Definition *compound=0; + const MemberDef *member=0; int len = g_token->name.length(); ClassDef *cd=0; bool ambig; @@ -1152,7 +1088,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor } else if (compound->definitionType()==Definition::TypeGroup) { - name=((GroupDef*)compound)->groupTitle(); + name=(dynamic_cast<const GroupDef*>(compound))->groupTitle(); } children.append(new DocLinkedWord(parent,name, @@ -1164,7 +1100,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor ); } else if (compound->definitionType()==Definition::TypeFile && - ((FileDef*)compound)->generateSourceFile() + (dynamic_cast<const FileDef*>(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { children.append(new @@ -1229,33 +1165,25 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor static void handleParameterType(DocNode *parent,QList<DocNode> &children,const QCString ¶mTypes) { - static QRegExp re("[ \t\r\n\\[\\]]"); - QCString name = g_token->name; + QCString name = g_token->name; // save token name QCString name1; int p=0,i,l,ii; while ((i=paramTypes.find('|',p))!=-1) { name1 = paramTypes.mid(p,i-p); - ii=re.match(name1,0,&l); - if (ii != -1) - g_token->name=name1.mid(0,ii); - else - g_token->name=name1; + ii=name1.find('['); + g_token->name=ii!=-1 ? name1.mid(0,ii) : name1; // take part without [] handleLinkedWord(parent,children); - if (ii != -1) children.append(new DocWord(parent,name1.mid(ii).data())); + if (ii!=-1) children.append(new DocWord(parent,name1.mid(ii))); // add [] part p=i+1; children.append(new DocSeparator(parent,"|")); } name1 = paramTypes.mid(p); - ii=re.match(name1,0,&l); - if (ii != -1) - g_token->name=name1.mid(0,ii); - else - g_token->name=name1; + ii=name1.find('['); + g_token->name=ii!=-1 ? name1.mid(0,ii) : name1; handleLinkedWord(parent,children); - if (ii != -1) children.append(new DocWord(parent,name1.mid(ii).data())); - - g_token->name = name; + if (ii!=-1) children.append(new DocWord(parent,name1.mid(ii))); + g_token->name = name; // restore original token name } static DocInternalRef *handleInternalRef(DocNode *parent) @@ -1265,7 +1193,7 @@ static DocInternalRef *handleInternalRef(DocNode *parent) QCString tokenName = g_token->name; if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(tokenName)); return 0; } @@ -1285,7 +1213,7 @@ static DocAnchor *handleAnchor(DocNode *parent) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(g_token->name)); return 0; } @@ -1628,6 +1556,16 @@ reparsetoken: handleStyleLeave(parent,children,DocStyleChange::Strike,tokenName); } break; + case HTML_DEL: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Del,&g_token->attribs); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Del,tokenName); + } + break; case HTML_UNDERLINE: if (!g_token->endTag) { @@ -1638,6 +1576,16 @@ reparsetoken: handleStyleLeave(parent,children,DocStyleChange::Underline,tokenName); } break; + case HTML_INS: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Ins,&g_token->attribs); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Ins,tokenName); + } + break; case HTML_CODE: case XML_C: if (!g_token->endTag) @@ -1945,12 +1893,13 @@ DocLinkedWord::DocLinkedWord(DocNode *parent,const QCString &word, //--------------------------------------------------------------------------- -DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) +DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) { m_parent = parent; if (id.isEmpty()) { warn_doc_error(g_fileName,doctokenizerYYlineno,"Empty anchor label"); + return; } if (id.left(CiteConsts::anchorPrefix.length()) == CiteConsts::anchorPrefix) @@ -2015,6 +1964,8 @@ void DocInclude::parse() DBG(("DocInclude::parse(file=%s,text=%s)\n",qPrint(m_file),qPrint(m_text))); switch(m_type) { + case DontIncWithLines: + // fall through case IncWithLines: // fall through case Include: @@ -2025,6 +1976,8 @@ void DocInclude::parse() g_includeFileText = m_text; g_includeFileOffset = 0; g_includeFileLength = m_text.length(); + g_includeFileLine = 0; + g_includeFileShowLineNo = (m_type == DontIncWithLines || m_type == IncWithLines); //printf("g_includeFile=<<%s>>\n",g_includeFileText.data()); break; case VerbInclude: @@ -2059,10 +2012,18 @@ void DocInclude::parse() void DocIncOperator::parse() { + if (g_includeFileName.isEmpty()) + { + warn_doc_error(g_fileName,doctokenizerYYlineno, + "No previous '\\include' or '\\dontinclude' command for '\\%s' present", + typeAsString()); + } + m_includeFileName = g_includeFileName; const char *p = g_includeFileText; uint l = g_includeFileLength; uint o = g_includeFileOffset; + uint il = g_includeFileLine; DBG(("DocIncOperator::parse() text=%s off=%d len=%d\n",qPrint(p),o,l)); uint so = o,bo; bool nonEmpty = FALSE; @@ -2074,6 +2035,7 @@ void DocIncOperator::parse() char c = p[o]; if (c=='\n') { + g_includeFileLine++; if (nonEmpty) break; // we have a pattern to match so=o+1; // no pattern, skip empty line } @@ -2085,10 +2047,12 @@ void DocIncOperator::parse() } if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1) { + m_line = il; m_text = g_includeFileText.mid(so,o-so); DBG(("DocIncOperator::parse() Line: %s\n",qPrint(m_text))); } g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line + m_showLineNo = g_includeFileShowLineNo; break; case SkipLine: while (o<l) @@ -2099,6 +2063,7 @@ void DocIncOperator::parse() char c = p[o]; if (c=='\n') { + g_includeFileLine++; if (nonEmpty) break; // we have a pattern to match so=o+1; // no pattern, skip empty line } @@ -2110,6 +2075,7 @@ void DocIncOperator::parse() } if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1) { + m_line = il; m_text = g_includeFileText.mid(so,o-so); DBG(("DocIncOperator::parse() SkipLine: %s\n",qPrint(m_text))); break; @@ -2117,6 +2083,7 @@ void DocIncOperator::parse() o++; // skip new line } g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line + m_showLineNo = g_includeFileShowLineNo; break; case Skip: while (o<l) @@ -2127,6 +2094,7 @@ void DocIncOperator::parse() char c = p[o]; if (c=='\n') { + g_includeFileLine++; if (nonEmpty) break; // we have a pattern to match so=o+1; // no pattern, skip empty line } @@ -2143,6 +2111,7 @@ void DocIncOperator::parse() o++; // skip new line } g_includeFileOffset = so; // set pointer to start of new line + m_showLineNo = g_includeFileShowLineNo; break; case Until: bo=o; @@ -2154,6 +2123,7 @@ void DocIncOperator::parse() char c = p[o]; if (c=='\n') { + g_includeFileLine++; if (nonEmpty) break; // we have a pattern to match so=o+1; // no pattern, skip empty line } @@ -2165,6 +2135,7 @@ void DocIncOperator::parse() } if (g_includeFileText.mid(so,o-so).find(m_pattern)!=-1) { + m_line = il; m_text = g_includeFileText.mid(bo,o-bo); DBG(("DocIncOperator::parse() Until: %s\n",qPrint(m_text))); break; @@ -2172,106 +2143,13 @@ void DocIncOperator::parse() o++; // skip new line } g_includeFileOffset = QMIN(l,o+1); // set pointer to start of new line + m_showLineNo = g_includeFileShowLineNo; break; } } //--------------------------------------------------------------------------- -void DocCopy::parse(QList<DocNode> &children) -{ - QCString doc,brief; - Definition *def; - if (findDocsForMemberOrCompound(m_link,&doc,&brief,&def)) - { - if (g_copyStack.findRef(def)==-1) // definition not parsed earlier - { - bool hasParamCommand = g_hasParamCommand; - bool hasReturnCommand = g_hasReturnCommand; - QDict<void> paramsFound = g_paramsFound; - //printf("..1 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - - docParserPushContext(FALSE); - g_scope = def; - if (def->definitionType()==Definition::TypeMember && def->getOuterScope()) - { - if (def->getOuterScope()!=Doxygen::globalScope) - { - g_context=def->getOuterScope()->name(); - } - } - else if (def!=Doxygen::globalScope) - { - g_context=def->name(); - } - g_styleStack.clear(); - g_nodeStack.clear(); - g_paramsFound.clear(); - g_copyStack.append(def); - // make sure the descriptions end with a newline, so the parser will correctly - // handle them in all cases. - //printf("doc='%s'\n",doc.data()); - //printf("brief='%s'\n",brief.data()); - if (m_copyBrief) - { - brief+='\n'; - internalValidatingParseDoc(m_parent,children,brief); - - //printf("..2 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - hasParamCommand = hasParamCommand || g_hasParamCommand; - hasReturnCommand = hasReturnCommand || g_hasReturnCommand; - QDictIterator<void> it(g_paramsFound); - void *item; - for (;(item=it.current());++it) - { - paramsFound.insert(it.currentKey(),it.current()); - } - } - if (m_copyDetails) - { - doc+='\n'; - internalValidatingParseDoc(m_parent,children,doc); - - //printf("..3 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - hasParamCommand = hasParamCommand || g_hasParamCommand; - hasReturnCommand = hasReturnCommand || g_hasReturnCommand; - QDictIterator<void> it(g_paramsFound); - void *item; - for (;(item=it.current());++it) - { - paramsFound.insert(it.currentKey(),it.current()); - } - } - g_copyStack.remove(def); - ASSERT(g_styleStack.isEmpty()); - ASSERT(g_nodeStack.isEmpty()); - docParserPopContext(TRUE); - - g_hasParamCommand = hasParamCommand; - g_hasReturnCommand = hasReturnCommand; - g_paramsFound = paramsFound; - - //printf("..4 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - } - else // oops, recursion - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"recursive call chain of \\copydoc commands detected at %d\n", - doctokenizerYYlineno); - } - } - else - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"target %s of \\copydoc command not found", - qPrint(m_link)); - } -} - -//--------------------------------------------------------------------------- - DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) : m_id(id), m_key(key), m_relPath(g_relPath) { @@ -2527,7 +2405,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : m_refType(Unknown), m_isSubPage(FALSE) { m_parent = parent; - Definition *compound = 0; + const Definition *compound = 0; QCString anchor; //printf("DocRef::DocRef(target=%s,context=%s)\n",target.data(),context.data()); ASSERT(!target.isEmpty()); @@ -2580,16 +2458,16 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : { if (anchor.isEmpty() && /* compound link */ compound->definitionType()==Definition::TypeGroup && /* is group */ - ((GroupDef *)compound)->groupTitle() /* with title */ + (dynamic_cast<const GroupDef *>(compound))->groupTitle() /* with title */ ) { - m_text=((GroupDef *)compound)->groupTitle(); // use group's title as link + m_text=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeMember && - ((MemberDef*)compound)->isObjCMethod()) + (dynamic_cast<const MemberDef*>(compound))->isObjCMethod()) { // Objective C Method - MemberDef *member = (MemberDef*)compound; + const MemberDef *member = dynamic_cast<const MemberDef*>(compound); bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE; m_text = member->objCMethodName(localLink,g_inSeeBlock); } @@ -2601,7 +2479,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : return; } else if (compound && compound->definitionType()==Definition::TypeFile && - ((FileDef*)compound)->generateSourceFile() + (dynamic_cast<const FileDef*>(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2723,7 +2601,7 @@ DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //cont DocLink::DocLink(DocNode *parent,const QCString &target) { m_parent = parent; - Definition *compound = 0; + const Definition *compound = 0; QCString anchor; m_refText = target; m_relPath = g_relPath; @@ -2740,8 +2618,8 @@ DocLink::DocLink(DocNode *parent,const QCString &target) m_file = compound->getOutputFileBase(); m_ref = compound->getReference(); } - else if (compound && compound->definitionType()==Definition::TypeFile && - ((FileDef*)compound)->generateSourceFile() + else if (compound && compound->definitionType()==Definition::TypeFile && + (dynamic_cast<const FileDef*>(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2855,8 +2733,9 @@ DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocDotFile::parse() +bool DocDotFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_DOTFILE,this,m_children,m_width,m_height); bool ambig; @@ -2868,6 +2747,7 @@ void DocDotFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2881,6 +2761,7 @@ void DocDotFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found " "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name)); } + return ok; } DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) : @@ -2889,8 +2770,9 @@ DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocMscFile::parse() +bool DocMscFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_MSCFILE,this,m_children,m_width,m_height); bool ambig; @@ -2902,6 +2784,7 @@ void DocMscFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2915,6 +2798,7 @@ void DocMscFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found " "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name)); } + return ok; } //--------------------------------------------------------------------------- @@ -2925,8 +2809,9 @@ DocDiaFile::DocDiaFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocDiaFile::parse() +bool DocDiaFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_DIAFILE,this,m_children,m_width,m_height); bool ambig; @@ -2938,6 +2823,7 @@ void DocDiaFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2951,6 +2837,7 @@ void DocDiaFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found " "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name)); } + return ok; } //--------------------------------------------------------------------------- @@ -2999,7 +2886,11 @@ DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString bool DocImage::isSVG() const { - return m_url.isEmpty() ? m_name.right(4)==".svg" : m_url.right(4)==".svg"; + QCString locName = m_url.isEmpty() ? m_name : m_url; + int len = locName.length(); + int fnd = locName.find('?'); // ignore part from ? until end + if (fnd!=-1) fnd=len; + return fnd>=4 && locName.mid(fnd-4,4)==".svg"; } void DocImage::parse() @@ -3089,7 +2980,7 @@ int DocHtmlHeader::parse() } else if (tagId==HTML_BR) { - DocLineBreak *lb = new DocLineBreak(this); + DocLineBreak *lb = new DocLineBreak(this,g_token->attribs); m_children.append(lb); } else @@ -3333,7 +3224,7 @@ DocHtmlCaption::DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs) HtmlAttrib *opt; for (li.toFirst();(opt=li.current());++li) { - if (opt->name=="id") // interpret id attribute as an anchor + if (opt->name=="id" && !opt->value.isEmpty()) // interpret id attribute as an anchor { SectionInfo *sec = Doxygen::sectionDict->find(opt->value); if (sec) @@ -4719,8 +4610,8 @@ int DocParamList::parse(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); retval=0; goto endparamlist; } @@ -4736,19 +4627,19 @@ int DocParamList::parse(const QCString &cmdName) handleParameterType(this,m_paramTypes,g_token->name.left(typeSeparator)); g_token->name = g_token->name.mid(typeSeparator+1); g_hasParamCommand=TRUE; - checkArgumentName(g_token->name,TRUE); + checkArgumentName(g_token->name); ((DocParamSect*)parent())->m_hasTypeSpecifier=TRUE; } else { g_hasParamCommand=TRUE; - checkArgumentName(g_token->name,TRUE); + checkArgumentName(g_token->name); } } else if (m_type==DocParamSect::RetVal) { g_hasReturnCommand=TRUE; - checkArgumentName(g_token->name,FALSE); + checkRetvalName(g_token->name); } //m_params.append(g_token->name); handleLinkedWord(this,m_params); @@ -4758,7 +4649,7 @@ int DocParamList::parse(const QCString &cmdName) if (tok==0) /* premature end of comment block */ { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s",qPrint(cmdName)); + "argument of command %s",qPrint(saveCmdName)); retval=0; goto endparamlist; } @@ -4793,12 +4684,12 @@ int DocParamList::parseXml(const QCString ¶mName) if (m_type==DocParamSect::Param) { g_hasParamCommand=TRUE; - checkArgumentName(g_token->name,TRUE); + checkArgumentName(g_token->name); } else if (m_type==DocParamSect::RetVal) { g_hasReturnCommand=TRUE; - checkArgumentName(g_token->name,FALSE); + checkRetvalName(g_token->name); } handleLinkedWord(this,m_params); @@ -4956,7 +4847,7 @@ void DocPara::handleCite() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint("cite")); return; } @@ -4988,7 +4879,7 @@ void DocPara::handleEmoji() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint("emoji")); return; } @@ -5035,12 +4926,13 @@ int DocPara::handleXRefItem() void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type t) { - DBG(("handleIncludeOperator(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; + DBG(("handleIncludeOperator(%s)\n",qPrint(saveCmdName))); int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStatePattern(); @@ -5049,13 +4941,13 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s", qPrint(cmdName)); + "argument of command %s", qPrint(saveCmdName)); return; } else if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName); @@ -5121,7 +5013,7 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command with option", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command with option", qPrint(saveCmdName)); return; } @@ -5129,7 +5021,7 @@ void DocPara::handleImage(const QCString &cmdName) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5144,7 +5036,7 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5179,11 +5071,12 @@ void DocPara::handleImage(const QCString &cmdName) template<class T> void DocPara::handleFile(const QCString &cmdName) { + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateFile(); @@ -5192,13 +5085,19 @@ void DocPara::handleFile(const QCString &cmdName) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } QCString name = g_token->name; T *df = new T(this,name,g_context); - m_children.append(df); - df->parse(); + if (df->parse()) + { + m_children.append(df); + } + else + { + delete df; + } } void DocPara::handleVhdlFlow() @@ -5210,11 +5109,12 @@ void DocPara::handleVhdlFlow() void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) { + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateLink(); @@ -5222,7 +5122,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } doctokenizerYYsetStatePara(); @@ -5237,12 +5137,13 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) void DocPara::handleRef(const QCString &cmdName) { - DBG(("handleRef(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; + DBG(("handleRef(%s)\n",qPrint(saveCmdName))); int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateRef(); @@ -5251,7 +5152,7 @@ void DocPara::handleRef(const QCString &cmdName) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); goto endref; } ref = new DocRef(this,g_token->name,g_context); @@ -5264,6 +5165,7 @@ endref: void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) { DBG(("handleInclude(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); bool isBlock = false; if (tok==TK_WORD && g_token->name=="{") @@ -5280,6 +5182,10 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) { t = DocInclude::SnipWithLines; } + else if (t==DocInclude::DontInclude && optList.contains("lineno")) + { + t = DocInclude::DontIncWithLines; + } else if (t==DocInclude::Include && optList.contains("doc")) { t = DocInclude::IncludeDoc; @@ -5300,8 +5206,8 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) } else if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateFile(); @@ -5310,13 +5216,13 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s",qPrint(cmdName)); + "argument of command %s",qPrint(saveCmdName)); return; } else if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } QCString fileName = g_token->name; @@ -5330,7 +5236,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } blockId = "["+g_token->name+"]"; @@ -5364,25 +5270,26 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) void DocPara::handleSection(const QCString &cmdName) { + QCString saveCmdName = cmdName; // get the argument of the section command. int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } tok=doctokenizerYYlex(); if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s\n", qPrint(cmdName)); + "argument of command %s\n", qPrint(saveCmdName)); return; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } g_token->sectionId = g_token->name; @@ -5440,7 +5347,7 @@ void DocPara::handleInheritDoc() MemberDef *reMd = g_memberDef->reimplements(); if (reMd) // member from which was inherited. { - MemberDef *thisMd = g_memberDef; + const MemberDef *thisMd = g_memberDef; //printf("{InheritDocs:%s=>%s}\n",g_memberDef->qualifiedName().data(),reMd->qualifiedName().data()); docParserPushContext(); g_scope=reMd->getOuterScope(); @@ -6017,9 +5924,15 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta case HTML_STRIKE: handleStyleEnter(this,m_children,DocStyleChange::Strike,&g_token->attribs); break; + case HTML_DEL: + handleStyleEnter(this,m_children,DocStyleChange::Del,&g_token->attribs); + break; case HTML_UNDERLINE: handleStyleEnter(this,m_children,DocStyleChange::Underline,&g_token->attribs); break; + case HTML_INS: + handleStyleEnter(this,m_children,DocStyleChange::Ins,&g_token->attribs); + break; case HTML_CODE: if (/*getLanguageFromFileName(g_fileName)==SrcLangExt_CSharp ||*/ g_xmlComment) // for C# source or inside a <summary> or <remark> section we @@ -6096,13 +6009,13 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta break; case HTML_BR: { - DocLineBreak *lb = new DocLineBreak(this); + DocLineBreak *lb = new DocLineBreak(this,tagHtmlAttribs); m_children.append(lb); } break; case HTML_HR: { - DocHorRuler *hr = new DocHorRuler(this); + DocHorRuler *hr = new DocHorRuler(this,tagHtmlAttribs); m_children.append(hr); } break; @@ -6432,9 +6345,15 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_STRIKE: handleStyleLeave(this,m_children,DocStyleChange::Strike,"strike"); break; + case HTML_DEL: + handleStyleLeave(this,m_children,DocStyleChange::Del,"del"); + break; case HTML_UNDERLINE: handleStyleLeave(this,m_children,DocStyleChange::Underline,"u"); break; + case HTML_INS: + handleStyleLeave(this,m_children,DocStyleChange::Ins,"ins"); + break; case HTML_CODE: handleStyleLeave(this,m_children,DocStyleChange::Code,"code"); break; @@ -6877,6 +6796,11 @@ endparagraph: DocNode *n = g_nodeStack.pop(); ASSERT(n==this); DBG(("DocPara::parse() end retval=%x\n",retval)); + if (!g_token->endTag && n->kind()==DocNode::Kind_Para && + retval==TK_NEWPARA && g_token->name.lower() == "p") + { + ((DocPara *)n)->setAttribs(g_token->attribs); + } INTERNAL_ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM || retval==TK_ENDLIST || retval>RetVal_OK ); @@ -6952,54 +6876,55 @@ int DocSection::parse() //printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel); - if (retval==RetVal_Subsection && m_level==Doxygen::subpageNestingLevel+1) + while (true) { - // then parse any number of nested sections - while (retval==RetVal_Subsection) // more sections follow + if (retval==RetVal_Subsection && m_level<=Doxygen::subpageNestingLevel+1) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + // then parse any number of nested sections + while (retval==RetVal_Subsection) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + break; } - } - else if (retval==RetVal_Subsubsection && m_level==Doxygen::subpageNestingLevel+2) - { - // then parse any number of nested sections - while (retval==RetVal_Subsubsection) // more sections follow + else if (retval==RetVal_Subsubsection && m_level<=Doxygen::subpageNestingLevel+2) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + if ((m_level<=1+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]); + // then parse any number of nested sections + while (retval==RetVal_Subsubsection) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + if (!(m_level<Doxygen::subpageNestingLevel+2 && retval == RetVal_Subsection)) break; } - } - else if (retval==RetVal_Paragraph && m_level==QMIN(5,Doxygen::subpageNestingLevel+3)) - { - // then parse any number of nested sections - while (retval==RetVal_Paragraph) // more sections follow + else if (retval==RetVal_Paragraph && m_level<=QMIN(5,Doxygen::subpageNestingLevel+3)) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + if ((m_level<=2+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]); + // then parse any number of nested sections + while (retval==RetVal_Paragraph) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + if (!(m_level<Doxygen::subpageNestingLevel+3 && (retval == RetVal_Subsection || retval == RetVal_Subsubsection))) break; + } + else + { + break; } - } - else if ((m_level<=1+Doxygen::subpageNestingLevel && retval==RetVal_Subsubsection) || - (m_level<=2+Doxygen::subpageNestingLevel && retval==RetVal_Paragraph) - ) - { - int level = (retval==RetVal_Subsubsection) ? 3 : 4; - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected %s " - "command found inside %s!", - sectionLevelToName[level],sectionLevelToName[m_level]); - retval=0; // stop parsing - } - else - { } INTERNAL_ASSERT(retval==0 || @@ -7144,7 +7069,7 @@ void DocRoot::parse() DocPara *par = new DocPara(this); if (isFirst) { par->markFirst(); isFirst=FALSE; } retval=par->parse(); - if (!par->isEmpty()) + if (!par->isEmpty() || par->attribs().count()>0) { m_children.append(par); lastPar=par; @@ -7153,21 +7078,96 @@ void DocRoot::parse() { delete par; } - if (retval==TK_LISTITEM) + if (retval==RetVal_Paragraph) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + if (!QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); + while (retval==RetVal_Paragraph) + { + if (!g_token->sectionId.isEmpty()) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid paragraph id `%s'; ignoring paragraph",qPrint(g_token->sectionId)); + retval = 0; + } + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for paragraph; ignoring paragraph"); + retval = 0; + } + } } - else if (retval==RetVal_Subsection) + if (retval==RetVal_Subsubsection) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!"); + if (!(QString(g_token->sectionId).startsWith("autotoc_md"))) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!"); + while (retval==RetVal_Subsubsection) + { + if (!g_token->sectionId.isEmpty()) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsubsection id `%s'; ignoring subsubsection",qPrint(g_token->sectionId)); + retval = 0; + } + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for subsubsection; ignoring subsubsection"); + retval = 0; + } + } } - else if (retval==RetVal_Subsubsection) + if (retval==RetVal_Subsection) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!"); + if (!(QString(g_token->sectionId).startsWith("autotoc_md"))) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!"); + while (retval==RetVal_Subsection) + { + if (!g_token->sectionId.isEmpty()) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsection id `%s'; ignoring subsection",qPrint(g_token->sectionId)); + retval = 0; + } + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for subsection; ignoring subsection"); + retval = 0; + } + } } - else if (retval==RetVal_Paragraph) + if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); } if (retval==RetVal_Internal) { @@ -7182,17 +7182,25 @@ void DocRoot::parse() // then parse any number of level1 sections while (retval==RetVal_Section) { - SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); - if (sec) + if (!g_token->sectionId.isEmpty()) { - DocSection *s=new DocSection(this, - QMIN(1+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(1+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid section id `%s'; ignoring section",qPrint(g_token->sectionId)); + retval = 0; + } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid section id `%s'; ignoring section",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for section; ignoring section"); retval = 0; } } @@ -7337,7 +7345,7 @@ static QCString processCopyDoc(const char *data,uint &len) while (j<len && (data[j]==' ' || data[j]=='\t')) j++; // extract the argument QCString id = extractCopyDocId(data,j,len); - Definition *def; + const Definition *def = 0; QCString doc,brief; //printf("resolving docs='%s'\n",id.data()); if (findDocsForMemberOrCompound(id,&doc,&brief,&def)) @@ -7526,7 +7534,7 @@ QCString getJsDirEmbedingChar(QString::Direction textDir) //--------------------------------------------------------------------------- DocRoot *validatingParseDoc(const char *fileName,int startLine, - Definition *ctx,MemberDef *md, + const Definition *ctx,const MemberDef *md, const char *input,bool indexWords, bool isExample, const char *exampleName, bool singleLine, bool linkFromIndex) @@ -7552,12 +7560,12 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, } else if (ctx && ctx->definitionType()==Definition::TypePage) { - Definition *scope = ((PageDef*)ctx)->getPageScope(); + const Definition *scope = (dynamic_cast<const PageDef*>(ctx))->getPageScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else if (ctx && ctx->definitionType()==Definition::TypeGroup) { - Definition *scope = ((GroupDef*)ctx)->getGroupScope(); + const Definition *scope = (dynamic_cast<const GroupDef*>(ctx))->getGroupScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else @@ -7682,6 +7690,8 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, g_exampleName = exampleName; g_hasParamCommand = FALSE; g_hasReturnCommand = FALSE; + g_retvalsFound.setAutoDelete(FALSE); + g_retvalsFound.clear(); g_paramsFound.setAutoDelete(FALSE); g_paramsFound.clear(); g_sectionDict = 0; //sections; @@ -7711,7 +7721,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, } checkUnOrMultipleDocumentedParams(); - detectNoDocumentedParams(); + if (g_memberDef) g_memberDef->detectUndocumentedParams(g_hasParamCommand,g_hasReturnCommand); // TODO: These should be called at the end of the program. //doctokenizerYYcleanup(); @@ -7752,6 +7762,8 @@ DocText *validatingParseText(const char *input) g_exampleName = ""; g_hasParamCommand = FALSE; g_hasReturnCommand = FALSE; + g_retvalsFound.setAutoDelete(FALSE); + g_retvalsFound.clear(); g_paramsFound.setAutoDelete(FALSE); g_paramsFound.clear(); g_searchUrl=""; |