Doxygen
Loading...
Searching...
No Matches
DocParser Class Referencefinal

#include <src/docparser_p.h>

Inheritance diagram for DocParser:
Collaboration diagram for DocParser:

Classes

class  AutoSaveContext

Public Member Functions

void handleImg (DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
Token internalValidatingParseDoc (DocNodeVariant *parent, DocNodeList &children, const DString &doc)
DString processCopyDoc (const char *data, size_t &len)
DString findAndCopyImage (const DString &fileName, DocImage::Type type, bool doWarn=true)
void checkArgumentName ()
void checkRetvalName ()
void checkUnOrMultipleDocumentedParams ()
bool findDocsForMemberOrCompound (const DString &commandName, DString *pDoc, DString *pBrief, const Definition **pDef)
bool defaultHandleToken (DocNodeVariant *parent, Token &tok, DocNodeList &children, bool handleWord=true)
void errorHandleDefaultToken (DocNodeVariant *parent, Token tok, DocNodeList &children, const DString &txt)
void defaultHandleTitleAndSize (const CommandType cmd, DocNodeVariant *parent, DocNodeList &children, DString &width, DString &height)
Token handleStyleArgument (DocNodeVariant *parent, DocNodeList &children, const DString &cmdName)
void handleStyleEnter (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const DString &tagName, const HtmlAttribList *attribs)
void handleStyleLeave (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const DString &tagName)
void handlePendingStyleCommands (DocNodeVariant *parent, DocNodeList &children, size_t numberOfElementsToClose=0)
void handleInitialStyleCommands (DocNodeVariant *parent, DocNodeList &children)
Token handleAHref (DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
void handleUnclosedStyleCommands ()
void handleLinkedWord (DocNodeVariant *parent, DocNodeList &children, bool ignoreAutoLinkFlag=false, bool typeLinkOnly=false)
void handleParameterType (DocNodeVariant *parent, DocNodeList &children, const DString &paramTypes)
void handleInternalRef (DocNodeVariant *parent, DocNodeList &children)
void handleAnchor (DocNodeVariant *parent, DocNodeList &children)
void handleCite (DocNodeVariant *parent, DocNodeList &children)
void handlePrefix (DocNodeVariant *parent, DocNodeList &children)
void handleImage (DocNodeVariant *parent, DocNodeList &children)
void handleRef (DocNodeVariant *parent, DocNodeList &children, char cmdChar, const DString &cmdName)
void handleIFile (char cmdChar, const DString &cmdName)
void handleILine (char cmdChar, const DString &cmdName)
void readTextFileByName (const DString &file, DString &text)

Public Attributes

std::stack< DocParserContext > contextStack
DocParserContext context
DocTokenizer tokenizer

Private Member Functions

void pushContext ()
void popContext ()

Detailed Description

Definition at line 100 of file docparser_p.h.

Member Function Documentation

◆ checkArgumentName()

void DocParser::checkArgumentName ( )

Collects the parameters found with @param command in a list context.paramsFound. If the parameter is not an actual parameter of the current member context.memberDef, then a warning is raised (unless warnings are disabled altogether).

Definition at line 213 of file docparser.cpp.

214{
215 if (!(Config_getBool(WARN_IF_DOC_ERROR) || Config_getBool(WARN_IF_INCOMPLETE_DOC))) return;
216 if (context.memberDef==nullptr) return; // not a member
217 std::string name = context.token->name.str();
218 const ArgumentList &al=context.memberDef->isDocsForDefinition() ?
222 context.numParameters = static_cast<int>(al.size());
223 //printf("isDocsForDefinition()=%d\n",context.memberDef->isDocsForDefinition());
224 if (al.empty()) return; // no argument list
225
226 static const reg::Ex re(R"(\$?\w+\.*)");
227 static const reg::Ex re_digits(R"(\d+)");
228 reg::Iterator it(name,re);
229 reg::Iterator end;
230 for (; it!=end ; ++it)
231 {
232 const auto &match = *it;
233 DString aName=match.str();
234 int number = reg::match(aName.view(),re_digits) ? std::atoi(aName.data()) : -1;
235 if (lang==SrcLangExt::Fortran) aName=aName.lower();
236 //printf("aName='%s'\n",qPrint(aName));
237 bool found=false;
238 int position=1;
239 for (const Argument &a : al)
240 {
241 DString argName = context.memberDef->isDefine() ? a.type : a.name;
242 if (lang==SrcLangExt::Fortran) argName=argName.lower();
243 argName=argName.stripWhiteSpace();
244 //printf("argName='%s' aName=%s\n",qPrint(argName),qPrint(aName));
245 if (argName.endsWith("...")) argName=argName.left(argName.length()-3);
246 bool sameName = aName==argName;
247 bool samePosition = position==number;
248 if (samePosition || sameName) // @param <number> or @param name
249 {
250 if (!sameName) // replace positional argument with real name or -
251 {
252 context.token->name = argName.empty() ? "-" : argName;
253 }
254 context.paramsFound.insert(aName.str());
255 found=true;
256 break;
257 }
258 else if (aName==".") // replace . by - in the output
259 {
260 context.token->name = "-";
261 }
262 position++;
263 }
264 if (!found)
265 {
266 //printf("member type=%d\n",context.memberDef->memberType());
267 DString scope=context.memberDef->getScopeString();
268 if (!scope.empty()) scope+="::"; else scope="";
269 DString inheritedFrom = "";
270 DString docFile = context.memberDef->docFile();
271 int docLine = context.memberDef->docLine();
272 const MemberDef *inheritedMd = context.memberDef->inheritsDocsFrom();
273 if (inheritedMd) // documentation was inherited
274 {
275 inheritedFrom.sprintf(" inherited from member %s at line "
276 "%d in file %s",qPrint(inheritedMd->name()),
277 inheritedMd->docLine(),qPrint(inheritedMd->docFile()));
278 docFile = context.memberDef->getDefFileName();
279 docLine = context.memberDef->getDefLine();
280 }
281 DString alStr = argListToString(al);
282 if (number==0)
283 {
284 warn_doc_error(docFile,docLine,
285 "positional argument with value '0' of command @param "
286 "is invalid, first parameter has index '1' for {}{}{}{}",
287 scope, context.memberDef->name(),
288 alStr, inheritedFrom);
289 context.token->name = "-";
290 }
291 else if (number>0)
292 {
293 warn_doc_error(docFile,docLine,
294 "positional argument '{}' of command @param "
295 "is larger than the number of parameters ({}) for {}{}{}{}",
296 number, al.size(), scope, context.memberDef->name(),
297 alStr, inheritedFrom);
298 context.token->name = "-";
299 }
300 else
301 {
302 warn_doc_error(docFile,docLine,
303 "argument '{}' of command @param "
304 "is not found in the argument list of {}{}{}{}",
305 aName, scope, context.memberDef->name(),
306 alStr, inheritedFrom);
307 }
308 }
309 }
310}
size_t size() const
Definition arguments.h:101
bool empty() const
Definition arguments.h:100
DString lower() const
Definition dstring.h:326
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
std::string_view view() const
Definition dstring.h:162
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:337
DString left(size_t len) const
Definition dstring.h:306
const std::string & str() const
Definition dstring.h:645
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
bool endsWith(const char *s) const
Definition dstring.h:617
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
virtual int docLine() const =0
virtual DString getDefFileName() const =0
virtual int getDefLine() const =0
virtual const DString & name() const =0
virtual DString docFile() const =0
DocParserContext context
virtual const MemberDef * inheritsDocsFrom() const =0
virtual const ArgumentList & argumentList() const =0
virtual bool isDocsForDefinition() const =0
virtual bool isDefine() const =0
virtual DString getScopeString() const =0
virtual const ArgumentList & declArgumentList() const =0
DString name
#define Config_getBool(name)
Definition config.h:33
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:181
const char * qPrint(const char *s)
Definition dstring.h:783
#define warn_doc_error(file, line, fmt,...)
Definition message.h:112
const char * name(int level)
Definition latexgen.h:368
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:861
StringMultiSet paramsFound
Definition docparser_p.h:76
TokenInfo * token
Definition docparser_p.h:94
const MemberDef * memberDef
Definition docparser_p.h:79
SrcLangExt
Definition types.h:207
DString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:864

References argListToString(), MemberDef::argumentList(), Config_getBool, context, DString::data(), MemberDef::declArgumentList(), Definition::docFile(), Definition::docLine(), ArgumentList::empty(), DString::empty(), end(), DString::endsWith(), Definition::getDefFileName(), Definition::getDefLine(), Definition::getLanguage(), MemberDef::getScopeString(), MemberDef::inheritsDocsFrom(), MemberDef::isDefine(), MemberDef::isDocsForDefinition(), DString::left(), DString::length(), DString::lower(), reg::match(), DocParserContext::memberDef, Definition::name(), TokenInfo::name, DocParserContext::numParameters, DocParserContext::paramsFound, qPrint(), ArgumentList::size(), DString::size(), DString::sprintf(), DString::str(), DString::stripWhiteSpace(), DocParserContext::token, DString::view(), and warn_doc_error.

Referenced by DocParamList::parse(), and DocParamList::parseXml().

◆ checkRetvalName()

void DocParser::checkRetvalName ( )

Collects the return values found with @retval command in a global list g_parserContext.retvalsFound.

Definition at line 314 of file docparser.cpp.

315{
316 DString name = context.token->name;
317 if (!Config_getBool(WARN_IF_DOC_ERROR)) return;
318 if (context.memberDef==nullptr || name.empty()) return; // not a member or no valid name
319 if (context.retvalsFound.count(name.str())==1) // only report the first double entry
320 {
323 "return value '{}' of {} has multiple documentation sections",
325 }
326 context.retvalsFound.insert(name.str());
327}
virtual DString qualifiedName() const =0
StringMultiSet retvalsFound
Definition docparser_p.h:75

References Config_getBool, context, Definition::getDefFileName(), Definition::getDefLine(), DocParserContext::memberDef, TokenInfo::name, Definition::qualifiedName(), DocParserContext::retvalsFound, DocParserContext::token, and warn_doc_error.

Referenced by DocParamList::parse(), and DocParamList::parseXml().

◆ checkUnOrMultipleDocumentedParams()

void DocParser::checkUnOrMultipleDocumentedParams ( )

Checks if the parameters that have been specified using @param are indeed all parameters and that a parameter does not have multiple @param blocks. Must be called after checkArgumentName() has been called for each argument.

Definition at line 335 of file docparser.cpp.

336{
338 {
339 const ArgumentList &al=context.memberDef->isDocsForDefinition() ?
343 if (!al.empty())
344 {
345 ArgumentList undocParams;
346 int position = 1;
347 for (const Argument &a: al)
348 {
349 DString argName = context.memberDef->isDefine() ? a.type : a.name;
350 if (lang==SrcLangExt::Fortran) argName = argName.lower();
351 argName=argName.stripWhiteSpace();
352 DString aName = argName;
353 if (argName.endsWith("...")) argName=argName.left(argName.length()-3);
354 if (lang==SrcLangExt::Python && (argName=="self" || argName=="cls"))
355 {
356 // allow undocumented self / cls parameter for Python
357 }
358 else if (lang==SrcLangExt::Cpp && (a.type=="this" || a.type.startsWith("this ")))
359 {
360 // allow undocumented this (for C++23 deducing this), see issue #11123
361 }
362 else if (!argName.empty())
363 {
364 size_t count_named = context.paramsFound.count(argName.str());
365 size_t count_positional = context.paramsFound.count(std::to_string(position));
366 if (count_named==0 && count_positional==0 && a.docs.empty())
367 {
368 undocParams.push_back(a);
369 }
370 else if (count_named==1 && count_positional==1 && Config_getBool(WARN_IF_DOC_ERROR))
371 {
374 "argument {} from the argument list of {} has both named and positional @param documentation sections",
376 }
377 else if (count_named+count_positional>1 && Config_getBool(WARN_IF_DOC_ERROR))
378 {
381 "argument {} from the argument list of {} has multiple @param documentation sections",
383 }
384 }
385 position++;
386 }
387 if (!undocParams.empty() && Config_getBool(WARN_IF_INCOMPLETE_DOC))
388 {
389 bool first=true;
390 DString errMsg = "The following parameter";
391 if (undocParams.size()>1) errMsg+="s";
392 errMsg+=DString(" of ")+
394 argListToString(al) +
395 (undocParams.size()>1 ? " are" : " is") + " not documented:\n";
396 for (const Argument &a : undocParams)
397 {
398 DString argName = context.memberDef->isDefine() ? a.type : a.name;
399 if (lang==SrcLangExt::Fortran) argName = argName.lower();
400 argName=argName.stripWhiteSpace();
401 if (!first) errMsg+="\n";
402 first=false;
403 errMsg+=" parameter '"+argName+"'";
404 }
406 }
407
408 if (Config_getBool(WARN_IF_DOC_ERROR) && context.paramPosition-1 > context.numParameters)
409 {
412 "too many @param commands for function {}. Found {} while function has {} parameter{}",
414 }
415 }
416 else
417 {
418 if (context.paramsFound.empty() && Config_getBool(WARN_IF_DOC_ERROR))
419 {
422 "{} has @param documentation sections but no arguments",
424 }
425 }
426 }
427}
void push_back(const Argument &a)
Definition arguments.h:103
#define warn_incomplete_doc(file, line, fmt,...)
Definition message.h:107

References argListToString(), MemberDef::argumentList(), Config_getBool, context, MemberDef::declArgumentList(), Definition::docFile(), Definition::docLine(), ArgumentList::empty(), DString::empty(), DString::endsWith(), Definition::getLanguage(), DocParserContext::hasParamCommand, MemberDef::isDefine(), MemberDef::isDocsForDefinition(), DString::left(), DString::length(), DString::lower(), DocParserContext::memberDef, DocParserContext::numParameters, DocParserContext::paramPosition, DocParserContext::paramsFound, ArgumentList::push_back(), Definition::qualifiedName(), ArgumentList::size(), DString::str(), DString::stripWhiteSpace(), warn_doc_error, and warn_incomplete_doc.

Referenced by validatingParseDoc().

◆ defaultHandleTitleAndSize()

void DocParser::defaultHandleTitleAndSize ( const CommandType cmd,
DocNodeVariant * parent,
DocNodeList & children,
DString & width,
DString & height )

Definition at line 1231 of file docparser.cpp.

1232{
1233 AUTO_TRACE();
1234 auto ns = AutoNodeStack(this,parent);
1235
1236 // parse title
1238 Token tok = tokenizer.lex();
1239 while (!tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1240 {
1241 if (tok.is(TokenRetval::TK_WORD) && (context.token->name=="width=" || context.token->name=="height="))
1242 {
1243 // special case: no title, but we do have a size indicator
1244 break;
1245 }
1246 else if (tok.is(TokenRetval::TK_HTMLTAG))
1247 {
1249 break;
1250 }
1251 if (!defaultHandleToken(parent,tok,children))
1252 {
1253 errorHandleDefaultToken(parent,tok,children,Mappers::cmdMapper->find(cmd));
1254 }
1255 tok = tokenizer.lex();
1256 }
1257 // parse size attributes
1258 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1259 {
1260 tok=tokenizer.lex();
1261 }
1262 while (tok.is_any_of(TokenRetval::TK_WHITESPACE,TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG)) // there are values following the title
1263 {
1264 if (tok.is(TokenRetval::TK_WORD))
1265 {
1266 if (context.token->name=="width=" || context.token->name=="height=")
1267 {
1270 }
1271
1272 if (context.token->name=="width")
1273 {
1274 width = context.token->chars;
1275 }
1276 else if (context.token->name=="height")
1277 {
1278 height = context.token->chars;
1279 }
1280 else // other text after the title -> treat as normal text
1281 {
1283 //warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unknown option '{}' after \\{} command, expected 'width' or 'height'",
1284 // context.token->name, Mappers::cmdMapper->find(cmd));
1285 break;
1286 }
1287 }
1288
1289 tok=tokenizer.lex();
1290 // if we found something we did not expect, push it back to the stream
1291 // so it can still be processed
1292 if (tok.is_any_of(TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS))
1293 {
1295 tokenizer.unputString(tok.is(TokenRetval::TK_COMMAND_AT) ? "@" : "\\");
1296 break;
1297 }
1298 else if (tok.is(TokenRetval::TK_SYMBOL))
1299 {
1301 break;
1302 }
1303 else if (tok.is(TokenRetval::TK_HTMLTAG))
1304 {
1306 break;
1307 }
1308 }
1310
1312 AUTO_TRACE_EXIT("width={} height={}",width,height);
1313}
void handlePendingStyleCommands(DocNodeVariant *parent, DocNodeList &children, size_t numberOfElementsToClose=0)
DocTokenizer tokenizer
void errorHandleDefaultToken(DocNodeVariant *parent, Token tok, DocNodeList &children, const DString &txt)
bool defaultHandleToken(DocNodeVariant *parent, Token &tok, DocNodeList &children, bool handleWord=true)
void setStateTitleAttrValue()
void unputString(const DString &tag)
void setStateTitle()
void setStatePara()
bool is(TokenRetval rv) const
bool is_any_of(ARGS... args) const
DString chars
DString text
#define AUTO_TRACE(...)
Definition docnode.cpp:53
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:55
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1335
const Mapper< CommandType > * cmdMapper

References AUTO_TRACE, AUTO_TRACE_EXIT, TokenInfo::chars, Mappers::cmdMapper, context, defaultHandleToken(), errorHandleDefaultToken(), handlePendingStyleCommands(), Token::is(), Token::is_any_of(), DString::left(), DString::length(), DocTokenizer::lex(), TokenInfo::name, parent(), DocTokenizer::setStatePara(), DocTokenizer::setStateTitle(), DocTokenizer::setStateTitleAttrValue(), TokenInfo::text, DocParserContext::token, tokenizer, and DocTokenizer::unputString().

Referenced by DocPara::handleCommand(), DocDiaFile::parse(), DocDotFile::parse(), DocImage::parse(), DocMermaidFile::parse(), DocMscFile::parse(), and DocPlantUmlFile::parse().

◆ defaultHandleToken()

bool DocParser::defaultHandleToken ( DocNodeVariant * parent,
Token & tok,
DocNodeList & children,
bool handleWord = true )

Definition at line 1494 of file docparser.cpp.

1495{
1496 AUTO_TRACE("token={} handleWord={}",tok.to_string(),handleWord);
1497 if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD,TokenRetval::TK_SYMBOL,TokenRetval::TK_URL,
1498 TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS,TokenRetval::TK_HTMLTAG)
1499 )
1500 {
1501 }
1502reparsetoken:
1503 DString tokenName = context.token->name;
1504 AUTO_TRACE_ADD("tokenName={}",tokenName);
1505 switch (tok.value())
1506 {
1507 case TokenRetval::TK_COMMAND_AT:
1508 // fall through
1509 case TokenRetval::TK_COMMAND_BS:
1510 switch (Mappers::cmdMapper->map(tokenName))
1511 {
1513 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_BSlash);
1514 break;
1516 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_At);
1517 break;
1519 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Less);
1520 break;
1522 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Greater);
1523 break;
1525 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Amp);
1526 break;
1528 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dollar);
1529 break;
1531 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Hash);
1532 break;
1534 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_DoubleColon);
1535 break;
1537 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Percent);
1538 break;
1540 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1541 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1542 break;
1544 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1545 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1546 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1547 break;
1549 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quot);
1550 break;
1552 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dot);
1553 break;
1555 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Exclam);
1556 break;
1558 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quest);
1559 break;
1561 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Plus);
1562 break;
1564 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1565 break;
1567 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Equal);
1568 break;
1570 {
1571 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,true);
1572 tok=handleStyleArgument(parent,children,tokenName);
1573 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,false);
1574 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1575 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1576 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1577 {
1578 AUTO_TRACE_ADD("CommandType::CMD_EMPHASIS: reparsing");
1579 goto reparsetoken;
1580 }
1581 }
1582 break;
1584 {
1585 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,true);
1586 tok=handleStyleArgument(parent,children,tokenName);
1587 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,false);
1588 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1589 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1590 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1591 {
1592 AUTO_TRACE_ADD("CommandType::CMD_BOLD: reparsing");
1593 goto reparsetoken;
1594 }
1595 }
1596 break;
1598 {
1599 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,true);
1600 tok=handleStyleArgument(parent,children,tokenName);
1601 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,false);
1602 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1603 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1604 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1605 {
1606 AUTO_TRACE_ADD("CommandType::CMD_CODE: reparsing");
1607 goto reparsetoken;
1608 }
1609 }
1610 break;
1612 {
1614 tok = tokenizer.lex();
1616 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1617 {
1618 warn_doc_error(context.fileName,tokenizer.getLineNr(),"htmlonly section ended without end marker");
1619 }
1621 }
1622 break;
1624 {
1626 tok = tokenizer.lex();
1628 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1629 {
1630 warn_doc_error(context.fileName,tokenizer.getLineNr(),"manonly section ended without end marker");
1631 }
1633 }
1634 break;
1636 {
1638 tok = tokenizer.lex();
1640 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1641 {
1642 warn_doc_error(context.fileName,tokenizer.getLineNr(),"rtfonly section ended without end marker");
1643 }
1645 }
1646 break;
1648 {
1650 tok = tokenizer.lex();
1652 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1653 {
1654 warn_doc_error(context.fileName,tokenizer.getLineNr(),"latexonly section ended without end marker");
1655 }
1657 }
1658 break;
1660 {
1662 tok = tokenizer.lex();
1664 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1665 {
1666 warn_doc_error(context.fileName,tokenizer.getLineNr(),"xmlonly section ended without end marker");
1667 }
1669 }
1670 break;
1672 {
1674 tok = tokenizer.lex();
1676 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1677 {
1678 warn_doc_error(context.fileName,tokenizer.getLineNr(),"docbookonly section ended without end marker");
1679 }
1681 }
1682 break;
1684 {
1685 children.append<DocFormula>(this,parent,context.token->id);
1686 }
1687 break;
1690 {
1691 handleAnchor(parent,children);
1692 }
1693 break;
1695 {
1696 handleCite(parent,children);
1697 }
1698 break;
1700 {
1701 handlePrefix(parent,children);
1702 }
1703 break;
1705 {
1706 handleInternalRef(parent,children);
1708 }
1709 break;
1711 {
1713 (void)tokenizer.lex();
1715 //printf("Found scope='%s'\n",qPrint(context.context));
1717 }
1718 break;
1720 handleImage(parent,children);
1721 break;
1723 handleILine(tok.command_to_char(),tokenName);
1724 break;
1726 handleIFile(tok.command_to_char(),tokenName);
1727 break;
1728 default:
1729 return false;
1730 }
1731 break;
1732 case TokenRetval::TK_HTMLTAG:
1733 {
1734 auto handleEnterLeaveStyle = [this,&parent,&children,&tokenName](DocStyleChange::Style style) {
1735 if (!context.token->endTag)
1736 {
1737 handleStyleEnter(parent,children,style,tokenName,&context.token->attribs);
1738 }
1739 else
1740 {
1741 handleStyleLeave(parent,children,style,tokenName);
1742 }
1743 };
1744 switch (Mappers::htmlTagMapper->map(tokenName))
1745 {
1747 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <div> tag in heading");
1748 break;
1750 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <pre> tag in heading");
1751 break;
1753 handleEnterLeaveStyle(DocStyleChange::Span);
1754 break;
1756 handleEnterLeaveStyle(DocStyleChange::Bold);
1757 break;
1759 handleEnterLeaveStyle(DocStyleChange::S);
1760 break;
1762 handleEnterLeaveStyle(DocStyleChange::Strike);
1763 break;
1765 handleEnterLeaveStyle(DocStyleChange::Del);
1766 break;
1768 handleEnterLeaveStyle(DocStyleChange::Underline);
1769 break;
1771 handleEnterLeaveStyle(DocStyleChange::Ins);
1772 break;
1774 case HtmlTagType::XML_C:
1775 handleEnterLeaveStyle(DocStyleChange::Code);
1776 break;
1778 handleEnterLeaveStyle(DocStyleChange::Kbd);
1779 break;
1781 handleEnterLeaveStyle(DocStyleChange::Typewriter);
1782 break;
1784 handleEnterLeaveStyle(DocStyleChange::Italic);
1785 break;
1787 handleEnterLeaveStyle(DocStyleChange::Subscript);
1788 break;
1790 handleEnterLeaveStyle(DocStyleChange::Superscript);
1791 break;
1793 handleEnterLeaveStyle(DocStyleChange::Center);
1794 break;
1796 handleEnterLeaveStyle(DocStyleChange::Small);
1797 break;
1799 handleEnterLeaveStyle(DocStyleChange::Cite);
1800 break;
1802 if (!context.token->endTag)
1803 {
1805 }
1806 break;
1807 default:
1808 return false;
1809 break;
1810 }
1811 }
1812 break;
1813 case TokenRetval::TK_SYMBOL:
1814 {
1817 {
1818 children.append<DocSymbol>(this,parent,s);
1819 }
1820 else
1821 {
1822 return false;
1823 }
1824 }
1825 break;
1826 case TokenRetval::TK_WHITESPACE:
1827 case TokenRetval::TK_NEWPARA:
1828handlepara:
1829 if (insidePRE(parent) || !children.empty())
1830 {
1831 children.append<DocWhiteSpace>(this,parent,context.token->chars);
1832 }
1833 break;
1834 case TokenRetval::TK_LNKWORD:
1835 if (handleWord)
1836 {
1837 handleLinkedWord(parent,children);
1838 }
1839 else
1840 return false;
1841 break;
1842 case TokenRetval::TK_WORD:
1843 if (handleWord)
1844 {
1845 children.append<DocWord>(this,parent,context.token->name);
1846 }
1847 else
1848 return false;
1849 break;
1850 case TokenRetval::TK_URL:
1852 {
1853 children.append<DocWord>(this,parent,context.token->name);
1854 }
1855 else
1856 {
1857 children.append<DocURL>(this,parent,context.token->name,context.token->isEMailAddr);
1858 }
1859 break;
1860 default:
1861 return false;
1862 }
1863 return true;
1864}
void append(Args &&... args)
Append a new DocNodeVariant to the list by constructing it with type T and parameters Args.
Definition docnode.h:1404
void handleIFile(char cmdChar, const DString &cmdName)
void handleInternalRef(DocNodeVariant *parent, DocNodeList &children)
void handleStyleEnter(DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const DString &tagName, const HtmlAttribList *attribs)
Token handleStyleArgument(DocNodeVariant *parent, DocNodeList &children, const DString &cmdName)
void handleStyleLeave(DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const DString &tagName)
void handleImage(DocNodeVariant *parent, DocNodeList &children)
void handleLinkedWord(DocNodeVariant *parent, DocNodeList &children, bool ignoreAutoLinkFlag=false, bool typeLinkOnly=false)
void handleCite(DocNodeVariant *parent, DocNodeList &children)
void handlePrefix(DocNodeVariant *parent, DocNodeList &children)
void handleILine(char cmdChar, const DString &cmdName)
void handleAnchor(DocNodeVariant *parent, DocNodeList &children)
void handleImg(DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
static HtmlEntityMapper::SymType decodeSymbol(const DString &symName)
Definition docnode.cpp:168
void setStateRtfOnly()
void setStateLatexOnly()
void setStateManOnly()
int getLineNr() const
void setStateDbOnly()
void setStateHtmlOnly()
void setStateXmlOnly()
void setStateSetScope()
TOKEN_SPECIFICATIONS RETVAL_SPECIFICATIONS const char * to_string() const
TokenRetval value() const
char command_to_char() const
DString verb
HtmlAttribList attribs
bool isEMailAddr
@ CMD_INTERNALREF
Definition cmdmapper.h:66
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:54
bool insidePRE(const DocNodeVariant *n)
const Mapper< HtmlTagType > * htmlTagMapper
DocNodeStack nodeStack
Definition docparser_p.h:66
DString exampleName
Definition docparser_p.h:81

References DocNodeList::append(), TokenInfo::attribs, AUTO_TRACE, AUTO_TRACE_ADD, DocStyleChange::Bold, DocStyleChange::Center, TokenInfo::chars, DocStyleChange::Cite, CMD_AMP, CMD_ANCHOR, CMD_AT, CMD_BOLD, CMD_BSLASH, CMD_CITE, CMD_CODE, CMD_DBONLY, CMD_DCOLON, CMD_DOLLAR, CMD_EMPHASIS, CMD_EQUAL, CMD_EXCLAMATION, CMD_FORMULA, CMD_GREATER, CMD_HASH, CMD_HTMLONLY, CMD_IANCHOR, CMD_IFILE, CMD_ILINE, CMD_IMAGE, CMD_INTERNALREF, CMD_IPREFIX, CMD_LATEXONLY, CMD_LESS, CMD_MANONLY, CMD_MDASH, CMD_MINUS, CMD_NDASH, CMD_PERCENT, CMD_PLUS, CMD_PUNT, CMD_QUESTION, CMD_QUOTE, CMD_RTFONLY, CMD_SETSCOPE, CMD_XMLONLY, Mappers::cmdMapper, DocStyleChange::Code, Token::command_to_char(), context, DocParserContext::context, DocSymbol::decodeSymbol(), DocStyleChange::Del, DocVerbatim::DocbookOnly, GrowVector< T >::empty(), TokenInfo::endTag, DocParserContext::exampleName, DocParserContext::fileName, DocTokenizer::getLineNr(), handleAnchor(), handleCite(), handleIFile(), handleILine(), handleImage(), handleImg(), handleInternalRef(), handleLinkedWord(), handlePrefix(), handleStyleArgument(), handleStyleEnter(), handleStyleLeave(), HTML_BOLD, HTML_CENTER, HTML_CITE, HTML_CODE, HTML_DEL, HTML_DIV, HTML_EMPHASIS, HTML_IMG, HTML_INS, HTML_KBD, HTML_PRE, HTML_S, HTML_SMALL, HTML_SPAN, HTML_STRIKE, HTML_SUB, HTML_SUP, HTML_TT, HTML_UNDERLINE, DocVerbatim::HtmlOnly, Mappers::htmlTagMapper, TokenInfo::id, DocStyleChange::Ins, DocParserContext::insideHtmlLink, insidePRE(), Token::is(), Token::is_any_of(), TokenInfo::isEMailAddr, DocParserContext::isExample, DocStyleChange::Italic, DocStyleChange::Kbd, DocVerbatim::LatexOnly, DocTokenizer::lex(), DocVerbatim::ManOnly, TokenInfo::name, DocParserContext::nodeStack, parent(), DocVerbatim::RtfOnly, DocStyleChange::S, DocTokenizer::setStateDbOnly(), DocTokenizer::setStateHtmlOnly(), DocTokenizer::setStateLatexOnly(), DocTokenizer::setStateManOnly(), DocTokenizer::setStatePara(), DocTokenizer::setStateRtfOnly(), DocTokenizer::setStateSetScope(), DocTokenizer::setStateXmlOnly(), DocStyleChange::Small, DocStyleChange::Span, DocStyleChange::Strike, DocStyleChange::Subscript, DocStyleChange::Superscript, HtmlEntityMapper::Sym_Amp, HtmlEntityMapper::Sym_At, HtmlEntityMapper::Sym_BSlash, HtmlEntityMapper::Sym_Dollar, HtmlEntityMapper::Sym_Dot, HtmlEntityMapper::Sym_DoubleColon, HtmlEntityMapper::Sym_Equal, HtmlEntityMapper::Sym_Exclam, HtmlEntityMapper::Sym_Greater, HtmlEntityMapper::Sym_Hash, HtmlEntityMapper::Sym_Less, HtmlEntityMapper::Sym_Minus, HtmlEntityMapper::Sym_Percent, HtmlEntityMapper::Sym_Plus, HtmlEntityMapper::Sym_Quest, HtmlEntityMapper::Sym_Quot, HtmlEntityMapper::Sym_Unknown, Token::to_string(), DocParserContext::token, tokenizer, DocStyleChange::Typewriter, DocStyleChange::Underline, Token::value(), TokenInfo::verb, warn_doc_error, XML_C, and DocVerbatim::XmlOnly.

Referenced by defaultHandleTitleAndSize(), handleStyleArgument(), and DocPara::injectToken().

◆ errorHandleDefaultToken()

void DocParser::errorHandleDefaultToken ( DocNodeVariant * parent,
Token tok,
DocNodeList & children,
const DString & txt )

Definition at line 613 of file docparser.cpp.

615{
616 switch (tok.value())
617 {
618 case TokenRetval::TK_COMMAND_AT:
619 // fall through
620 case TokenRetval::TK_COMMAND_BS:
621 {
622 char cs[2] = { tok.command_to_char(), 0 };
623 children.append<DocWord>(this,parent,cs + context.token->name);
624 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Illegal command '{:c}{}' found as part of a {}",
625 tok.command_to_char(),context.token->name,txt);
626 }
627 break;
628 case TokenRetval::TK_SYMBOL:
629 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported symbol '{}' found as part of a {}",
630 qPrint(context.token->name), qPrint(txt));
631 break;
632 case TokenRetval::TK_HTMLTAG:
633 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported HTML tag <{}{}> found as part of a {}",
634 context.token->endTag ? "/" : "",context.token->name, txt);
635 break;
636 default:
637 children.append<DocWord>(this,parent,context.token->name);
638 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unexpected token {} found as part of a {}",
639 tok.to_string(), txt);
640 break;
641 }
642}

References DocNodeList::append(), Token::command_to_char(), context, TokenInfo::endTag, DocParserContext::fileName, DocTokenizer::getLineNr(), TokenInfo::name, parent(), qPrint(), Token::to_string(), DocParserContext::token, tokenizer, Token::value(), and warn_doc_error.

Referenced by defaultHandleTitleAndSize(), handleStyleArgument(), DocHRef::parse(), DocHtmlCaption::parse(), DocHtmlHeader::parse(), DocHtmlSummary::parse(), DocInternalRef::parse(), DocRef::parse(), DocSecRefItem::parse(), DocTitle::parse(), and DocVhdlFlow::parse().

◆ findAndCopyImage()

DString DocParser::findAndCopyImage ( const DString & fileName,
DocImage::Type type,
bool doWarn = true )

search for an image in the imageNameDict and if found copies the image to the output directory (which depends on the type parameter).

Definition at line 100 of file docparser.cpp.

101{
102 DString result;
103 bool ambig = false;
104 FileDef *fd = Doxygen::imageNameLinkedMap->findFileDef(fileName,ambig);
105 //printf("Search for %s\n",fileName);
106 if (fd)
107 {
108 if (ambig & doWarn)
109 {
111 "image file name '{}' is ambiguous.\n"
112 "Possible candidates:\n{}", fileName,Doxygen::imageNameLinkedMap->showFileDefMatches(fileName));
113 }
114
115 DString inputFile = fd->absFilePath();
116 FileInfo infi(inputFile.str());
117 if (infi.exists())
118 {
119 result = fileName;
120 if (size_t i = result.rfind('/') ; i!=DString::npos || (i=result.rfind('\\'))!=DString::npos)
121 {
122 result = result.mid(i+1);
123 }
124 //printf("fileName=%s result=%s\n",fileName,qPrint(result));
125 DString outputDir;
126 switch(type)
127 {
128 case DocImage::Html:
129 if (!Config_getBool(GENERATE_HTML)) return result;
130 outputDir = Config_getString(HTML_OUTPUT);
131 break;
132 case DocImage::Latex:
133 if (!Config_getBool(GENERATE_LATEX)) return result;
134 outputDir = Config_getString(LATEX_OUTPUT);
135 break;
137 if (!Config_getBool(GENERATE_DOCBOOK)) return result;
138 outputDir = Config_getString(DOCBOOK_OUTPUT);
139 break;
140 case DocImage::Rtf:
141 if (!Config_getBool(GENERATE_RTF)) return result;
142 outputDir = Config_getString(RTF_OUTPUT);
143 break;
144 case DocImage::Xml:
145 if (!Config_getBool(GENERATE_XML)) return result;
146 outputDir = Config_getString(XML_OUTPUT);
147 break;
148 }
149 DString outputFile = outputDir+"/"+result;
150 FileInfo outfi(outputFile.str());
151 if (outfi.isSymLink())
152 {
153 Dir().remove(outputFile.str());
155 "destination of image {} is a symlink, replacing with image",
156 outputFile);
157 }
158 if (outputFile!=inputFile) // prevent copying to ourself
159 {
160 if (copyFile(inputFile,outputFile) && type==DocImage::Html)
161 {
163 }
164 }
165 }
166 else
167 {
169 "could not open image {}",fileName);
170 }
171
172 if (type==DocImage::Latex && Config_getBool(USE_PDFLATEX) &&
173 fd->name().endsWith(".eps")
174 )
175 { // we have an .eps image in pdflatex mode => convert it to a pdf.
176 DString outputDir = Config_getString(LATEX_OUTPUT);
177 DString baseName = fd->name().left(fd->name().length()-4);
178 DString epstopdfArgs(4096, DString::ExplicitSize);
179 epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"",
180 qPrint(outputDir), qPrint(baseName),
181 qPrint(outputDir), qPrint(baseName));
182 if (Portable::system("epstopdf",epstopdfArgs)!=0)
183 {
184 err("Problems running epstopdf. Check your TeX installation!\n");
185 }
186 else
187 {
188 Dir().remove(outputDir.str()+"/"+baseName.str()+".eps");
189 }
190 return baseName;
191 }
192 }
193 else
194 {
195 result=fileName;
196 if (!result.startsWith("http:") && !result.startsWith("https:") && doWarn)
197 {
199 "image file {} is not found in IMAGE_PATH: "
200 "assuming external image.",fileName
201 );
202 }
203 }
204 return result;
205}
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:244
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
@ ExplicitSize
Definition dstring.h:131
@ DocBook
Definition docnode.h:644
static FileNameLinkedMap * imageNameLinkedMap
Definition doxygen.h:98
static IndexList * indexList
Definition doxygen.h:125
virtual DString absFilePath() const =0
DString showFileDefMatches(const DString &n) const
Returns a list of file definitions in fnMap that match the file name n.
Definition filename.cpp:131
FileDef * findFileDef(const DString &n, bool &ambig) const
Returns the file definition in fnMap that matches the file name n.
Definition filename.cpp:38
void addImageFile(const DString &name)
Definition indexlist.h:124
#define Config_getString(name)
Definition config.h:32
#define err(fmt,...)
Definition message.h:127
int system(const DString &command, const DString &args, bool commandHasConsole=true)
Definition portable.cpp:121
bool copyFile(const DString &src, const DString &dest)
Copies the contents of file with name src to the newly created file with name dest.
Definition util.cpp:4625

References FileDef::absFilePath(), IndexList::addImageFile(), Config_getBool, Config_getString, context, copyFile(), DocImage::DocBook, DString::endsWith(), err, FileInfo::exists(), DString::ExplicitSize, DocParserContext::fileName, FileNameLinkedMap::findFileDef(), DocTokenizer::getLineNr(), DocImage::Html, Doxygen::imageNameLinkedMap, Doxygen::indexList, FileInfo::isSymLink(), DocImage::Latex, DString::left(), DString::length(), DString::mid(), Definition::name(), DString::npos, qPrint(), Dir::remove(), DString::rfind(), DocImage::Rtf, FileNameLinkedMap::showFileDefMatches(), DString::sprintf(), DString::startsWith(), DString::str(), Portable::system(), tokenizer, warn_doc_error, and DocImage::Xml.

Referenced by handleImage(), and handleImg().

◆ findDocsForMemberOrCompound()

bool DocParser::findDocsForMemberOrCompound ( const DString & commandName,
DString * pDoc,
DString * pBrief,
const Definition ** pDef )

Looks for a documentation block with name commandName in the current context (g_parserContext.context). The resulting documentation string is put in pDoc, the definition in which the documentation was found is put in pDef.

Return values
trueif name was found.
falseif name was not found.

Definition at line 442 of file docparser.cpp.

446{
447 AUTO_TRACE("commandName={}",commandName);
448 *pDoc="";
449 *pBrief="";
450 *pDef=nullptr;
451 DString cmdArg=commandName;
452 if (cmdArg.empty())
453 {
454 AUTO_TRACE_EXIT("empty");
455 return false;
456 }
457
458 const FileDef *fd=nullptr;
459 const GroupDef *gd=nullptr;
460 const PageDef *pd=nullptr;
461 gd = Doxygen::groupLinkedMap->find(cmdArg);
462 if (gd) // group
463 {
464 *pDoc=gd->documentation();
465 *pBrief=gd->briefDescription();
466 *pDef=gd;
467 AUTO_TRACE_EXIT("group");
468 return true;
469 }
470 pd = Doxygen::pageLinkedMap->find(cmdArg);
471 if (pd) // page
472 {
473 *pDoc=pd->documentation();
474 *pBrief=pd->briefDescription();
475 *pDef=pd;
476 AUTO_TRACE_EXIT("page");
477 return true;
478 }
479 bool ambig = false;
480 fd = Doxygen::inputNameLinkedMap->findFileDef(cmdArg,ambig);
481 if (fd && !ambig) // file
482 {
483 *pDoc=fd->documentation();
484 *pBrief=fd->briefDescription();
485 *pDef=fd;
486 AUTO_TRACE_EXIT("file");
487 return true;
488 }
489
490 // for symbols we need to normalize the separator, so A#B, or A\B, or A.B becomes A::B
491 cmdArg = substitute(cmdArg,"#","::");
492 cmdArg = substitute(cmdArg,"\\","::");
493 bool extractAnonNs = Config_getBool(EXTRACT_ANON_NSPACES);
494 if (extractAnonNs &&
495 cmdArg.startsWith("anonymous_namespace{")
496 )
497 {
498 size_t rightBracePos = cmdArg.find("}", dstrlen("anonymous_namespace{"));
499 if (rightBracePos != DString::npos)
500 {
501 DString leftPart = cmdArg.left(rightBracePos + 1);
502 DString rightPart = cmdArg.mid(rightBracePos + 1);
503 rightPart = substitute(rightPart, ".", "::");
504 cmdArg = leftPart + rightPart;
505 }
506 else
507 {
508 cmdArg = substitute(cmdArg,".","::");
509 }
510 }
511 else
512 {
513 cmdArg = substitute(cmdArg,".","::");
514 }
515
516 int l=static_cast<int>(cmdArg.length());
517
518 size_t funcStart=cmdArg.find('(');
519 if (funcStart==DString::npos)
520 {
521 funcStart=l;
522 }
523 else
524 {
525 // Check for the case of operator() and the like.
526 // beware of scenarios like operator()((foo)bar)
527 size_t secondParen = cmdArg.find('(', funcStart+1);
528 size_t leftParen = cmdArg.find(')', funcStart+1);
529 if (leftParen!=DString::npos && secondParen!=DString::npos)
530 {
531 if (leftParen<secondParen)
532 {
533 funcStart=secondParen;
534 }
535 }
536 }
537
538 DString name=removeRedundantWhiteSpace(cmdArg.left(funcStart));
539 DString args=cmdArg.right(l-funcStart);
540 // try if the link is to a member
541 GetDefInput input(
542 context.context.find('.')==DString::npos ? context.context : DString(), // find('.') is a hack to detect files
543 name,
544 args);
545 input.checkCV=true;
546 // the file of the documentation block, so that a static in that file can be found
547 if (input.currentFile==nullptr)
548 {
550 }
551 GetDefResult result = getDefs(input);
552 if (!result.found && input.currentFile)
553 {
554 // not found via that file, e.g. a function in a header without \file, so retry without it
555 input.currentFile=nullptr;
556 result = getDefs(input);
557 }
558 //printf("found=%d context=%s name=%s\n",result.found,qPrint(context.context),qPrint(name));
559 if (result.found && result.md)
560 {
561 *pDoc=result.md->documentation();
562 *pBrief=result.md->briefDescription();
563 *pDef=result.md;
564 AUTO_TRACE_EXIT("member");
565 return true;
566 }
567
568 int scopeOffset=static_cast<int>(context.context.length());
569 do // for each scope
570 {
571 DString fullName=cmdArg;
572 if (scopeOffset>0)
573 {
574 fullName.prepend(context.context.left(scopeOffset)+"::");
575 }
576 //printf("Trying fullName='%s'\n",qPrint(fullName));
577
578 // try class, namespace, group, page, file reference
579 const ClassDef *cd = Doxygen::classLinkedMap->find(fullName);
580 if (cd) // class
581 {
582 *pDoc=cd->documentation();
583 *pBrief=cd->briefDescription();
584 *pDef=cd;
585 AUTO_TRACE_EXIT("class");
586 return true;
587 }
588 const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(fullName);
589 if (nd) // namespace
590 {
591 *pDoc=nd->documentation();
592 *pBrief=nd->briefDescription();
593 *pDef=nd;
594 AUTO_TRACE_EXIT("namespace");
595 return true;
596 }
597 if (scopeOffset==0)
598 {
599 scopeOffset=-1;
600 }
601 else
602 {
603 size_t o = context.context.rfind("::",scopeOffset-1);
604 scopeOffset = o!=DString::npos ? static_cast<int>(o) : 0;
605 }
606 } while (scopeOffset>=0);
607
608 AUTO_TRACE_EXIT("not found");
609 return false;
610}
DString right(size_t len) const
Definition dstring.h:311
DString & prepend(const char *s)
Definition dstring.h:515
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
bool startsWith(const char *s) const
Definition dstring.h:600
virtual DString briefDescription(bool abbreviate=false) const =0
virtual DString documentation() const =0
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:108
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:97
static ClassLinkedMap * classLinkedMap
Definition doxygen.h:88
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:92
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:107
const T * find(const std::string &key) const
Definition linkedmap.h:47
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:485
uint32_t dstrlen(const char *str)
Returns the length of string str, or 0 if a null pointer is passed.
Definition dstring.h:39
const MemberDef * md
Definition util.h:95
bool found
Definition util.h:94
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:427
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:1871

References AUTO_TRACE, AUTO_TRACE_EXIT, Definition::briefDescription(), GetDefInput::checkCV, Doxygen::classLinkedMap, Config_getBool, context, DocParserContext::context, GetDefInput::currentFile, Definition::documentation(), dstrlen(), DString::empty(), DocParserContext::fileName, DString::find(), LinkedMap< T, Hash, KeyEqual, Map >::find(), FileNameLinkedMap::findFileDef(), GetDefResult::found, getDefs(), Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, DString::left(), DString::length(), GetDefResult::md, DString::mid(), Doxygen::namespaceLinkedMap, DString::npos, Doxygen::pageLinkedMap, DString::prepend(), removeRedundantWhiteSpace(), DString::rfind(), DString::right(), DString::startsWith(), and substitute().

Referenced by processCopyDoc().

◆ handleAHref()

Token DocParser::handleAHref ( DocNodeVariant * parent,
DocNodeList & children,
const HtmlAttribList & tagHtmlAttribs )

Definition at line 799 of file docparser.cpp.

801{
802 AUTO_TRACE();
803 size_t index=0;
804 Token retval = Token::make_RetVal_OK();
805 for (const auto &opt : tagHtmlAttribs)
806 {
807 if (opt.name=="name" || opt.name=="id") // <a name=label> or <a id=label> tag
808 {
809 if (!opt.value.empty())
810 {
811 children.append<DocAnchor>(this,parent,opt.value,true);
812 break; // stop looking for other tag attribs
813 }
814 else
815 {
816 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <a> tag with name option but without value!");
817 }
818 }
819 else if (opt.name=="href") // <a href=url>..</a> tag
820 {
821 // copy attributes
822 HtmlAttribList attrList = tagHtmlAttribs;
823 // and remove the href attribute
824 attrList.erase(attrList.begin()+index);
825 DString relPath;
826 if (opt.value.at(0) != '#') relPath = context.relPath;
827 children.append<DocHRef>(this, parent, attrList,
828 opt.value, relPath,
829 convertNameToFile(context.fileName, false, true));
831 retval = children.get_last<DocHRef>()->parse();
834 break;
835 }
836 else // unsupported option for tag a
837 {
838 }
839 ++index;
840 }
841 return retval;
842}
T * get_last()
Returns a pointer to the last element in the list if that element exists and holds a T,...
Definition docnode.h:1415
bool parse(const DString &fileName, bool update=false, CompareMode compareMode=CompareMode::Full)
DString convertNameToFile(const DString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:2869

References DocNodeList::append(), AUTO_TRACE, context, convertNameToFile(), DocParserContext::fileName, DocNodeList::get_last(), DocTokenizer::getLineNr(), DocParserContext::insideHtmlLink, parent(), DocParserContext::relPath, DocTokenizer::setStatePara(), tokenizer, and warn_doc_error.

Referenced by DocPara::handleHtmlStartTag(), DocHtmlDescTitle::parse(), and DocHtmlHeader::parse().

◆ handleAnchor()

void DocParser::handleAnchor ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 1061 of file docparser.cpp.

1062{
1063 AUTO_TRACE();
1064 Token tok=tokenizer.lex();
1065 if (!tok.is(TokenRetval::TK_WHITESPACE))
1066 {
1067 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
1068 context.token->name);
1069 return;
1070 }
1071
1074 tok=tokenizer.lex();
1075 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1076 {
1077 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
1078 "argument of command {}",context.token->name);
1079 return;
1080 }
1081 else if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1082 {
1083 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
1084 tok.to_string(),context.token->name);
1085 return;
1086 }
1087 }
1088 children.append<DocAnchor>(this,parent,context.token->name,false);
1089}
void setStateAnchor()
friend class AutoSaveState

References DocNodeList::append(), AUTO_TRACE, context, DocParserContext::fileName, DocTokenizer::getLineNr(), Token::is(), Token::is_any_of(), DocTokenizer::lex(), TokenInfo::name, parent(), DocTokenizer::setStateAnchor(), Token::to_string(), DocParserContext::token, tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleCite()

void DocParser::handleCite ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 1091 of file docparser.cpp.

1092{
1093 AUTO_TRACE();
1094 // get the argument of the cite command.
1095 Token tok=tokenizer.lex();
1096
1097 CiteInfoOption option;
1098 if (tok.is(TokenRetval::TK_WORD) && context.token->name=="{")
1099 {
1101 tokenizer.lex();
1102 StringVector optList=split(context.token->name.str(),",");
1103 for (auto const &opt : optList)
1104 {
1105 if (opt == "number")
1106 {
1107 if (!option.isUnknown())
1108 {
1109 warn(context.fileName,tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", context.token->name, opt);
1110 }
1111 else
1112 {
1113 option = CiteInfoOption::makeNumber();
1114 }
1115 }
1116 else if (opt == "year")
1117 {
1118 if (!option.isUnknown())
1119 {
1120 warn(context.fileName,tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", context.token->name, opt);
1121 }
1122 else
1123 {
1124 option = CiteInfoOption::makeYear();
1125 }
1126 }
1127 else if (opt == "shortauthor")
1128 {
1129 if (!option.isUnknown())
1130 {
1131 warn(context.fileName,tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", context.token->name, opt);
1132 }
1133 else
1134 {
1136 }
1137 }
1138 else if (opt == "nopar")
1139 {
1140 option.setNoPar();
1141 }
1142 else if (opt == "nocite")
1143 {
1144 option.setNoCite();
1145 }
1146 else
1147 {
1148 warn(context.fileName,tokenizer.getLineNr(),"Unknown option specified with \\{}, discarding '{}'", context.token->name, opt);
1149 }
1150 }
1151
1152 if (option.isUnknown()) option.changeToNumber();
1153
1155 tok=tokenizer.lex();
1156 if (!tok.is(TokenRetval::TK_WHITESPACE))
1157 {
1158 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
1159 context.token->name);
1160 return;
1161 }
1162 }
1163 else if (!tok.is(TokenRetval::TK_WHITESPACE))
1164 {
1165 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after '\\{}' command",
1166 context.token->name);
1167 return;
1168 }
1169 else
1170 {
1171 option = CiteInfoOption::makeNumber();
1172 }
1173
1176 tok=tokenizer.lex();
1177 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1178 {
1179 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
1180 "argument of command '\\{}'",context.token->name);
1181 return;
1182 }
1183 else if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1184 {
1185 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of '\\{}'",
1186 tok.to_string(),context.token->name);
1187 return;
1188 }
1190 children.append<DocCite>(this,parent,context.token->name,context.context,option);
1191 }
1192
1193}
constexpr void setNoCite() noexcept
Definition cite.h:35
static constexpr CiteInfoOption makeNumber()
Definition cite.h:29
constexpr void changeToNumber() noexcept
Definition cite.h:33
constexpr void setNoPar() noexcept
Definition cite.h:34
constexpr bool isUnknown() const noexcept
Definition cite.h:37
static constexpr CiteInfoOption makeYear()
Definition cite.h:31
static constexpr CiteInfoOption makeShortAuthor()
Definition cite.h:30
void setStateCite()
void setStateOptions()
DString sectionId
std::vector< std::string > StringVector
Definition containers.h:33
#define warn(file, line, fmt,...)
Definition message.h:97
StringVector split(const std::string &s, const std::string &delimiter, bool retainEmpty=false)
split input string s by string delimiter delimiter.
Definition stringutil.h:119

References DocNodeList::append(), AUTO_TRACE, CiteInfoOption::changeToNumber(), context, DocParserContext::context, DocParserContext::fileName, DocTokenizer::getLineNr(), Token::is(), Token::is_any_of(), CiteInfoOption::isUnknown(), DocTokenizer::lex(), CiteInfoOption::makeNumber(), CiteInfoOption::makeShortAuthor(), CiteInfoOption::makeYear(), TokenInfo::name, parent(), TokenInfo::sectionId, CiteInfoOption::setNoCite(), CiteInfoOption::setNoPar(), DocTokenizer::setStateCite(), DocTokenizer::setStateOptions(), DocTokenizer::setStatePara(), split(), DString::str(), Token::to_string(), DocParserContext::token, tokenizer, warn, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleIFile()

void DocParser::handleIFile ( char cmdChar,
const DString & cmdName )

Definition at line 1447 of file docparser.cpp.

1448{
1449 AUTO_TRACE();
1450 Token tok=tokenizer.lex();
1451 if (!tok.is(TokenRetval::TK_WHITESPACE))
1452 {
1453 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after '{:c}{}' command",
1454 cmdChar,cmdName);
1455 return;
1456 }
1458 tok=tokenizer.lex();
1460 if (!tok.is(TokenRetval::TK_WORD))
1461 {
1462 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of '{:c}{}'",
1463 tok.to_string(),cmdChar,cmdName);
1464 return;
1465 }
1467}
void setStateIFile()

References AUTO_TRACE, context, DocParserContext::fileName, DocTokenizer::getLineNr(), Token::is(), DocTokenizer::lex(), TokenInfo::name, DocTokenizer::setStateIFile(), DocTokenizer::setStatePara(), Token::to_string(), DocParserContext::token, tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleILine()

void DocParser::handleILine ( char cmdChar,
const DString & cmdName )

Definition at line 1469 of file docparser.cpp.

1470{
1471 AUTO_TRACE();
1473 Token tok = tokenizer.lex();
1475 if (!tok.is(TokenRetval::TK_WORD))
1476 {
1477 warn_doc_error(context.fileName,tokenizer.getLineNr(),"invalid argument for command '{:c}{}'",
1478 cmdChar,cmdName);
1479 return;
1480 }
1481}
void setStateILine()

References AUTO_TRACE, context, DocParserContext::fileName, DocTokenizer::getLineNr(), Token::is(), DocTokenizer::lex(), DocTokenizer::setStateILine(), DocTokenizer::setStatePara(), tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleImage()

void DocParser::handleImage ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 1315 of file docparser.cpp.

1316{
1317 AUTO_TRACE();
1318 bool inlineImage = false;
1319 DString anchorStr;
1320
1321 Token tok=tokenizer.lex();
1322 if (!tok.is(TokenRetval::TK_WHITESPACE))
1323 {
1324 if (tok.is(TokenRetval::TK_WORD))
1325 {
1326 if (context.token->name == "{")
1327 {
1329 tokenizer.lex();
1331 StringVector optList=split(context.token->name.str(),",");
1332 for (const auto &opt : optList)
1333 {
1334 if (opt.empty()) continue;
1335 DString locOpt(opt);
1336 DString locOptLow;
1337 locOpt = locOpt.stripWhiteSpace();
1338 locOptLow = locOpt.lower();
1339 if (locOptLow == "inline")
1340 {
1341 inlineImage = true;
1342 }
1343 else if (locOptLow.startsWith("anchor:"))
1344 {
1345 if (!anchorStr.empty())
1346 {
1348 "multiple use of option 'anchor' for 'image' command, ignoring: '{}'",
1349 locOpt.mid(7));
1350 }
1351 else
1352 {
1353 anchorStr = locOpt.mid(7);
1354 }
1355 }
1356 else
1357 {
1359 "unknown option '{}' for 'image' command specified",
1360 locOpt);
1361 }
1362 }
1363 tok=tokenizer.lex();
1364 if (!tok.is(TokenRetval::TK_WHITESPACE))
1365 {
1366 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1367 return;
1368 }
1369 }
1370 }
1371 else
1372 {
1373 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1374 return;
1375 }
1376 }
1377 tok=tokenizer.lex();
1378 if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1379 {
1380 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of \\image",
1381 tok.to_string());
1382 return;
1383 }
1384 tok=tokenizer.lex();
1385 if (!tok.is(TokenRetval::TK_WHITESPACE))
1386 {
1387 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1388 return;
1389 }
1391 DString imgType = context.token->name.lower();
1392 if (imgType=="html") t=DocImage::Html;
1393 else if (imgType=="latex") t=DocImage::Latex;
1394 else if (imgType=="docbook") t=DocImage::DocBook;
1395 else if (imgType=="rtf") t=DocImage::Rtf;
1396 else if (imgType=="xml") t=DocImage::Xml;
1397 else
1398 {
1399 warn_doc_error(context.fileName,tokenizer.getLineNr(),"output format `{}` specified as the first argument of "
1400 "\\image command is not valid", imgType);
1401 return;
1402 }
1404 tok=tokenizer.lex();
1406 if (!tok.is(TokenRetval::TK_WORD))
1407 {
1408 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of \\image", tok.to_string());
1409 return;
1410 }
1411 if (!anchorStr.empty())
1412 {
1413 children.append<DocAnchor>(this,parent,anchorStr,true);
1414 }
1415 HtmlAttribList attrList;
1416 children.append<DocImage>(this,parent,attrList,
1417 findAndCopyImage(context.token->name,t),t,"",inlineImage);
1418 children.get_last<DocImage>()->parse();
1419}
DString findAndCopyImage(const DString &fileName, DocImage::Type type, bool doWarn=true)
void setStateFile()

References DocNodeList::append(), AUTO_TRACE, context, DocImage::DocBook, DString::empty(), DocParserContext::fileName, findAndCopyImage(), DocNodeList::get_last(), DocTokenizer::getLineNr(), DocImage::Html, Token::is(), Token::is_any_of(), DocImage::Latex, DocTokenizer::lex(), DString::lower(), DString::mid(), TokenInfo::name, parent(), DocImage::Rtf, DocTokenizer::setStateFile(), DocTokenizer::setStateOptions(), DocTokenizer::setStatePara(), split(), DString::startsWith(), DString::str(), DString::stripWhiteSpace(), Token::to_string(), DocParserContext::token, tokenizer, warn_doc_error, and DocImage::Xml.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleImg()

void DocParser::handleImg ( DocNodeVariant * parent,
DocNodeList & children,
const HtmlAttribList & tagHtmlAttribs )

Definition at line 1868 of file docparser.cpp.

1869{
1870 AUTO_TRACE();
1871 bool found=false;
1872 size_t index=0;
1873 for (const auto &opt : tagHtmlAttribs)
1874 {
1875 AUTO_TRACE_ADD("option name={} value='{}'",opt.name,opt.value);
1876 if (opt.name=="src" && !opt.value.empty())
1877 {
1878 // copy attributes
1879 HtmlAttribList attrList = tagHtmlAttribs;
1880 // and remove the src attribute
1881 attrList.erase(attrList.begin()+index);
1883 children.append<DocImage>(
1884 this,parent,attrList,
1885 findAndCopyImage(opt.value,t,false),
1886 t,opt.value);
1887 found = true;
1888 }
1889 ++index;
1890 }
1891 if (!found)
1892 {
1893 warn_doc_error(context.fileName,tokenizer.getLineNr(),"IMG tag does not have a SRC attribute!");
1894 }
1895}

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, context, DocParserContext::fileName, findAndCopyImage(), DocTokenizer::getLineNr(), DocImage::Html, parent(), tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleHtmlStartTag().

◆ handleInitialStyleCommands()

void DocParser::handleInitialStyleCommands ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 788 of file docparser.cpp.

789{
790 AUTO_TRACE();
791 while (!context.initialStyleStack.empty())
792 {
793 const DocStyleChange &sc = std::get<DocStyleChange>(*context.initialStyleStack.top());
794 handleStyleEnter(parent,children,sc.style(),sc.tagName(),&sc.attribs());
796 }
797}
const HtmlAttribList & attribs() const
Definition docnode.h:311
Style style() const
Definition docnode.h:307
DString tagName() const
Definition docnode.h:312
DocStyleChangeStack initialStyleStack
Definition docparser_p.h:68

References DocStyleChange::attribs(), AUTO_TRACE, context, handleStyleEnter(), DocParserContext::initialStyleStack, parent(), DocStyleChange::style(), and DocStyleChange::tagName().

Referenced by DocPara::parse().

◆ handleInternalRef()

void DocParser::handleInternalRef ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 1039 of file docparser.cpp.

1040{
1041 Token tok=tokenizer.lex();
1042 DString tokenName = context.token->name;
1043 AUTO_TRACE("name={}",tokenName);
1044 if (!tok.is(TokenRetval::TK_WHITESPACE))
1045 {
1046 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command", tokenName);
1047 return;
1048 }
1050 tok=tokenizer.lex(); // get the reference id
1051 if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1052 {
1053 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
1054 tok.to_string(),tokenName);
1055 return;
1056 }
1057 children.append<DocInternalRef>(this,parent,context.token->name);
1058 children.get_last<DocInternalRef>()->parse();
1059}
void setStateInternalRef()

References DocNodeList::append(), AUTO_TRACE, context, DocParserContext::fileName, DocNodeList::get_last(), DocTokenizer::getLineNr(), Token::is(), Token::is_any_of(), DocTokenizer::lex(), TokenInfo::name, parent(), DocTokenizer::setStateInternalRef(), Token::to_string(), DocParserContext::token, tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleLinkedWord()

void DocParser::handleLinkedWord ( DocNodeVariant * parent,
DocNodeList & children,
bool ignoreAutoLinkFlag = false,
bool typeLinkOnly = false )

Definition at line 868 of file docparser.cpp.

869{
870 // helper to check if word w starts with any of the words in AUTOLINK_IGNORE_WORDS
871 auto ignoreWord = [](const DString &w) -> bool {
872 auto list = Config_getList(AUTOLINK_IGNORE_WORDS);
873 return std::find_if(list.begin(), list.end(),
874 [&w](const auto &ignore) { return w.startsWith(ignore); }
875 )!=list.end();
876 };
877 DString name = linkToText(context.lang,context.token->name,true);
878 AUTO_TRACE("word={}",name);
879 if (!context.autolinkSupport || ignoreAutoLinkFlag || ignoreWord(context.token->name)) // no autolinking -> add as normal word
880 {
881 children.append<DocWord>(this,parent,name);
882 return;
883 }
884
885 // ------- try to turn the word 'name' into a link
886
887 const Definition *compound=nullptr;
888 const MemberDef *member=nullptr;
889 size_t len = context.token->name.length();
890 ClassDef *cd=nullptr;
891 bool ambig = false;
893 auto lang = context.lang;
894 bool inSeeBlock = context.inSeeBlock || context.inCodeStyle;
895 //printf("handleLinkedWord(%s) context.context=%s\n",qPrint(context.token->name),qPrint(context.context));
896 if (!context.insideHtmlLink &&
897 (resolveRef(context.context,context.token->name,inSeeBlock,&compound,&member,lang,true,fd,true)
898 || (!context.context.empty() && // also try with global scope
899 resolveRef(DString(),context.token->name,inSeeBlock,&compound,&member,lang,false,nullptr,true))
900 )
901 )
902 {
903 //printf("ADD %s = %p (linkable?=%d typeLinkOnly=%d)\n",
904 // qPrint(context.token->name),(void*)member,member ? member->isLinkable() : false, typeLinkOnly);
905 if (member && member->isLinkable())
906 {
907 if (!typeLinkOnly || context.token->name.startsWith("#") ||
908 member->isTypedef() || member->isEnumerate() || member->isEnumValue()) // filter on type links
909 {
910 AUTO_TRACE_ADD("resolved reference as member link");
911 if (member->isObjCMethod())
912 {
913 bool localLink = context.memberDef ? member->getClassDef()==context.memberDef->getClassDef() : false;
914 name = member->objCMethodName(localLink,inSeeBlock);
915 }
916 children.append<DocLinkedWord>(
917 this,parent,name,
918 member->getReference(),
919 member->getOutputFileBase(),
920 member->anchor(),
921 member->briefDescriptionAsTooltip());
922 }
923 else // explicit type link, but not a type
924 {
925 AUTO_TRACE_ADD("no link as request is type but member is not a type or explicit link");
926 children.append<DocWord>(this,parent,context.token->name);
927 }
928 }
929 else if (compound->isLinkable()) // compound link
930 {
931 AUTO_TRACE_ADD("resolved reference as compound link");
932 DString anchor = compound->anchor();
933 if (compound->definitionType()==Definition::TypeFile)
934 {
936 }
937 else if (compound->definitionType()==Definition::TypeGroup)
938 {
939 name=toGroupDef(compound)->groupTitle();
940 }
941 children.append<DocLinkedWord>(
942 this,parent,name,
943 compound->getReference(),
944 compound->getOutputFileBase(),
945 anchor,
946 compound->briefDescriptionAsTooltip());
947 }
948 else if (compound->definitionType()==Definition::TypeFile &&
949 (toFileDef(compound))->generateSourceFile()
950 ) // undocumented file that has source code we can link to
951 {
952 AUTO_TRACE_ADD("resolved reference as source link");
953 children.append<DocLinkedWord>(
954 this,parent,context.token->name,
955 compound->getReference(),
956 compound->getSourceFileBase(),
957 "",
958 compound->briefDescriptionAsTooltip());
959 }
960 else // not linkable
961 {
962 AUTO_TRACE_ADD("resolved reference as unlinkable compound={} (linkable={}) member={} (linkable={})",
963 compound ? compound->name() : "<none>", compound ? (int)compound->isLinkable() : -1,
964 member ? member->name() : "<none>", member ? (int)member->isLinkable() : -1);
965 children.append<DocWord>(this,parent,name);
966 }
967 }
968 else if (!context.insideHtmlLink && len>1 && context.token->name.at(len-1)==':')
969 {
970 // special case, where matching Foo: fails to be an Obj-C reference,
971 // but Foo itself might be linkable.
973 handleLinkedWord(parent,children,ignoreAutoLinkFlag);
974 children.append<DocWord>(this,parent,":");
975 }
976 else if (!context.insideHtmlLink && (cd=getClass(context.token->name+"-p")))
977 {
978 // special case 2, where the token name is not a class, but could
979 // be a Obj-C protocol
980 children.append<DocLinkedWord>(
981 this,parent,name,
982 cd->getReference(),
983 cd->getOutputFileBase(),
984 cd->anchor(),
986 }
987 else if (const RequirementIntf *req = RequirementManager::instance().find(name); req!=nullptr) // link to requirement
988 {
989 if (Config_getBool(GENERATE_REQUIREMENTS))
990 {
991 children.append<DocLinkedWord>(
992 this,parent,name,
993 DString(), // link to local requirements overview also for external references
994 req->getOutputFileBase(),
995 req->id(),
996 req->title()
997 );
998 }
999 else // cannot link to a page that does not exist
1000 {
1001 children.append<DocWord>(this,parent,name);
1002 }
1003 }
1004 else // normal non-linkable word
1005 {
1006 AUTO_TRACE_ADD("non-linkable");
1007 if (context.token->name.startsWith("#"))
1008 {
1009 warn_doc_error(context.fileName,tokenizer.getLineNr(),"explicit link request to '{}' could not be resolved",name);
1010 }
1011 children.append<DocWord>(this,parent,context.token->name);
1012 }
1013}
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
virtual bool isLinkable() const =0
virtual DefType definitionType() const =0
virtual DString briefDescriptionAsTooltip() const =0
virtual DString anchor() const =0
virtual DString getReference() const =0
virtual DString getSourceFileBase() const =0
virtual DString getOutputFileBase() const =0
virtual DString groupTitle() const =0
virtual bool isObjCMethod() const =0
virtual DString objCMethodName(bool localLink, bool showStatic) const =0
virtual const ClassDef * getClassDef() const =0
virtual bool isTypedef() const =0
virtual bool isEnumerate() const =0
virtual bool isEnumValue() const =0
static RequirementManager & instance()
ClassDef * getClass(const DString &n)
#define Config_getList(name)
Definition config.h:38
FileDef * toFileDef(Definition *d)
Definition filedef.cpp:2033
GroupDef * toGroupDef(Definition *d)
SrcLangExt lang
Definition docparser_p.h:84
bool resolveRef(const DString &scName, const DString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
Definition util.cpp:2013
DString linkToText(SrcLangExt lang, const DString &link, bool ignoreDots)
Definition util.cpp:2270

References Definition::anchor(), DocNodeList::append(), DString::at(), AUTO_TRACE, AUTO_TRACE_ADD, DocParserContext::autolinkSupport, Definition::briefDescriptionAsTooltip(), Config_getBool, Config_getList, context, DocParserContext::context, Definition::definitionType(), DString::empty(), DocParserContext::fileName, FileNameLinkedMap::findFileDef(), getClass(), MemberDef::getClassDef(), DocTokenizer::getLineNr(), Definition::getOutputFileBase(), Definition::getReference(), Definition::getSourceFileBase(), GroupDef::groupTitle(), handleLinkedWord(), DocParserContext::inCodeStyle, Doxygen::inputNameLinkedMap, DocParserContext::inSeeBlock, DocParserContext::insideHtmlLink, RequirementManager::instance(), MemberDef::isEnumerate(), MemberDef::isEnumValue(), Definition::isLinkable(), MemberDef::isObjCMethod(), MemberDef::isTypedef(), DocParserContext::lang, DString::left(), DString::length(), linkToText(), DocParserContext::memberDef, Definition::name(), TokenInfo::name, MemberDef::objCMethodName(), parent(), resolveRef(), DString::startsWith(), toFileDef(), toGroupDef(), DocParserContext::token, tokenizer, Definition::TypeFile, Definition::TypeGroup, and warn_doc_error.

Referenced by defaultHandleToken(), DocPara::handleHtmlStartTag(), handleLinkedWord(), handleParameterType(), DocPara::parse(), DocParamList::parse(), and DocParamList::parseXml().

◆ handleParameterType()

void DocParser::handleParameterType ( DocNodeVariant * parent,
DocNodeList & children,
const DString & paramTypes )

Definition at line 1015 of file docparser.cpp.

1016{
1017 DString name = context.token->name; // save token name
1018 AUTO_TRACE("name={}",name);
1019 DString name1;
1020 size_t p=0, i=0, ii=0;
1021 while ((i=paramTypes.find('|',p))!=DString::npos)
1022 {
1023 name1 = paramTypes.mid(p,i-p);
1024 ii=name1.find('[');
1025 context.token->name=ii!=DString::npos ? name1.mid(0,ii) : name1; // take part without []
1026 handleLinkedWord(parent,children);
1027 if (ii!=DString::npos) children.append<DocWord>(this,parent,name1.mid(ii)); // add [] part
1028 p=i+1;
1029 children.append<DocSeparator>(this,parent,"|");
1030 }
1031 name1 = paramTypes.mid(p);
1032 ii=name1.find('[');
1033 context.token->name=ii!=DString::npos ? name1.mid(0,ii) : name1;
1034 handleLinkedWord(parent,children);
1035 if (ii!=DString::npos) children.append<DocWord>(this,parent,name1.mid(ii));
1036 context.token->name = name; // restore original token name
1037}

References DocNodeList::append(), AUTO_TRACE, context, DString::find(), handleLinkedWord(), DString::mid(), TokenInfo::name, DString::npos, parent(), and DocParserContext::token.

Referenced by DocParamList::parse().

◆ handlePendingStyleCommands()

void DocParser::handlePendingStyleCommands ( DocNodeVariant * parent,
DocNodeList & children,
size_t numberOfElementsToClose = 0 )

Called at the end of a paragraph to close all open style changes (e.g. a without a ). The closed styles are pushed onto a stack and entered again at the start of a new paragraph.

Definition at line 768 of file docparser.cpp.

769{
770 AUTO_TRACE("context.styleStack.size()={} numberOfElementsToClose={}",context.styleStack.size(),numberOfElementsToClose);
771 if (!context.styleStack.empty())
772 {
773 if (numberOfElementsToClose==0) numberOfElementsToClose = context.styleStack.size(); // 0 is special value for "close all"
774 const DocStyleChange *sc = &std::get<DocStyleChange>(*context.styleStack.top());
775 while (sc && sc->position()>=context.nodeStack.size() && numberOfElementsToClose>0)
776 { // there are unclosed style modifiers in the paragraph
777 AUTO_TRACE_ADD("unclosed style {} at position {}",sc->styleString(),sc->position());
778 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),
779 sc->style(),sc->tagName(),false);
781 context.styleStack.pop();
782 sc = !context.styleStack.empty() ? &std::get<DocStyleChange>(*context.styleStack.top()) : nullptr;
783 numberOfElementsToClose--;
784 }
785 }
786}
const char * styleString() const
Definition docnode.cpp:140
size_t position() const
Definition docnode.h:310
DocStyleChangeStack styleStack
Definition docparser_p.h:67

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, context, DocParserContext::initialStyleStack, DocParserContext::nodeStack, parent(), DocStyleChange::position(), DocStyleChange::style(), DocParserContext::styleStack, DocStyleChange::styleString(), and DocStyleChange::tagName().

Referenced by defaultHandleTitleAndSize(), handleStyleArgument(), DocHRef::parse(), DocHtmlCaption::parse(), DocHtmlDescTitle::parse(), DocHtmlHeader::parse(), DocInternalRef::parse(), DocLink::parse(), DocPara::parse(), DocRef::parse(), DocSecRefItem::parse(), DocTitle::parse(), and DocVhdlFlow::parse().

◆ handlePrefix()

void DocParser::handlePrefix ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 1195 of file docparser.cpp.

1196{
1197 AUTO_TRACE();
1198 Token tok=tokenizer.lex();
1199 if (!tok.is(TokenRetval::TK_WHITESPACE))
1200 {
1201 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command", context.token->name);
1202 return;
1203 }
1205 tok=tokenizer.lex();
1206 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1207 {
1208 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
1209 "argument of command {}",context.token->name);
1210 return;
1211 }
1212 else if (!tok.is(TokenRetval::TK_WORD))
1213 {
1214 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
1215 tok.to_string(),context.token->name);
1216 return;
1217 }
1220}
void setStatePrefix()

References AUTO_TRACE, context, DocParserContext::fileName, DocTokenizer::getLineNr(), Token::is(), Token::is_any_of(), DocTokenizer::lex(), TokenInfo::name, parent(), DocParserContext::prefix, DocTokenizer::setStatePara(), DocTokenizer::setStatePrefix(), Token::to_string(), DocParserContext::token, tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleRef()

void DocParser::handleRef ( DocNodeVariant * parent,
DocNodeList & children,
char cmdChar,
const DString & cmdName )

Definition at line 1421 of file docparser.cpp.

1422{
1423 AUTO_TRACE("cmdName={}",cmdName);
1424 DString saveCmdName = cmdName;
1426 Token tok=tokenizer.lex();
1427 if (!tok.is(TokenRetval::TK_WHITESPACE))
1428 {
1429 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after '{:c}{}' command",
1430 cmdChar,qPrint(saveCmdName));
1431 return;
1432 }
1434 tok=tokenizer.lex(); // get the reference id
1435 if (!tok.is(TokenRetval::TK_WORD))
1436 {
1437 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of '{:c}{}'",
1438 tok.to_string(),cmdChar,saveCmdName);
1439 return;
1440 }
1441 children.append<DocRef>(this,parent,
1444 children.get_last<DocRef>()->parse(cmdChar,saveCmdName);
1445}

References DocNodeList::append(), AUTO_TRACE, context, DocParserContext::context, DocParserContext::fileName, DocNodeList::get_last(), DocTokenizer::getLineNr(), Token::is(), DocTokenizer::lex(), TokenInfo::name, parent(), qPrint(), DocTokenizer::setStateRef(), Token::to_string(), DocParserContext::token, tokenizer, and warn_doc_error.

Referenced by DocPara::handleCommand(), and DocHtmlSummary::parse().

◆ handleStyleArgument()

Token DocParser::handleStyleArgument ( DocNodeVariant * parent,
DocNodeList & children,
const DString & cmdName )

Definition at line 646 of file docparser.cpp.

647{
648 AUTO_TRACE("cmdName={}",cmdName);
649 DString saveCmdName = cmdName;
650 Token tok=tokenizer.lex();
651 size_t styleStackSizeAtStart = context.styleStack.size();
652 if (!tok.is(TokenRetval::TK_WHITESPACE))
653 {
654 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
655 saveCmdName);
656 return tok;
657 }
658 tok = tokenizer.lex();
659 while (!tok.is_any_of(TokenRetval::TK_NONE, TokenRetval::TK_EOF, TokenRetval::TK_WHITESPACE,
660 TokenRetval::TK_NEWPARA, TokenRetval::TK_LISTITEM, TokenRetval::TK_ENDLIST)
661 )
662 {
663 static const reg::Ex specialChar(R"([.,|()\‍[\‍]:;?])");
664 if (tok.is(TokenRetval::TK_WORD) && context.token->name.length()==1 &&
665 reg::match(context.token->name.str(),specialChar))
666 {
667 // special character that ends the markup command
668 AUTO_TRACE_ADD("special character ending style argument: '{}' styleStackSize {}->{}",context.token->name,styleStackSizeAtStart,context.styleStack.size());
669 if (context.styleStack.size() > styleStackSizeAtStart) // new styles opened inside command, but not closed
670 {
671 handlePendingStyleCommands(parent,children,context.styleStack.size()-styleStackSizeAtStart);
672 }
673 return tok;
674 }
675 if (!defaultHandleToken(parent,tok,children))
676 {
677 switch (tok.value())
678 {
679 case TokenRetval::TK_HTMLTAG:
681 {
682 // ignore </li> as the end of a style command
683 }
684 else
685 {
686 AUTO_TRACE_EXIT("end tok={}",tok.to_string());
687 return tok;
688 }
689 break;
690 default:
691 errorHandleDefaultToken(parent,tok,children,"\\" + saveCmdName + " command");
692 break;
693 }
694 break;
695 }
696 tok = tokenizer.lex();
697 }
698 AUTO_TRACE_EXIT("end tok={}",tok.to_string());
699 return (tok.is_any_of(TokenRetval::TK_NEWPARA,TokenRetval::TK_LISTITEM,TokenRetval::TK_ENDLIST)) ? tok : Token::make_RetVal_OK();
700}
bool insideLI(const DocNodeVariant *n)

References AUTO_TRACE, AUTO_TRACE_ADD, AUTO_TRACE_EXIT, context, defaultHandleToken(), TokenInfo::endTag, errorHandleDefaultToken(), DocParserContext::fileName, DocTokenizer::getLineNr(), handlePendingStyleCommands(), Mappers::htmlTagMapper, insideLI(), Token::is(), Token::is_any_of(), DString::length(), DocTokenizer::lex(), reg::match(), TokenInfo::name, parent(), DString::str(), DocParserContext::styleStack, Token::to_string(), DocParserContext::token, tokenizer, UNKNOWN, Token::value(), and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleStyleEnter()

void DocParser::handleStyleEnter ( DocNodeVariant * parent,
DocNodeList & children,
DocStyleChange::Style s,
const DString & tagName,
const HtmlAttribList * attribs )

Called when a style change starts. For instance a <b> command is encountered.

Definition at line 705 of file docparser.cpp.

707{
708 AUTO_TRACE("tagName={}",tagName);
709 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),s,tagName,true,
711 context.styleStack.push(&children.back());
713}
T & back()
access the last element
Definition growvector.h:135

References DocNodeList::append(), AUTO_TRACE, GrowVector< T >::back(), context, DocParserContext::fileName, DocTokenizer::getLineNr(), DocParserContext::inCodeStyle, DocParserContext::nodeStack, parent(), DocParserContext::styleStack, tokenizer, and DocStyleChange::Typewriter.

Referenced by defaultHandleToken(), DocPara::handleHtmlStartTag(), and handleInitialStyleCommands().

◆ handleStyleLeave()

void DocParser::handleStyleLeave ( DocNodeVariant * parent,
DocNodeList & children,
DocStyleChange::Style s,
const DString & tagName )

Called when a style change ends. For instance a </b> command is encountered.

Definition at line 718 of file docparser.cpp.

720{
721 AUTO_TRACE("tagName={}",tagName);
722 DString tagNameLower = DString(tagName).lower();
723
724 auto topStyleChange = [](const DocStyleChangeStack &stack) -> const DocStyleChange &
725 {
726 return std::get<DocStyleChange>(*stack.top());
727 };
728
729 if (context.styleStack.empty() || // no style change
730 topStyleChange(context.styleStack).style()!=s || // wrong style change
731 topStyleChange(context.styleStack).tagName()!=tagNameLower || // wrong style change
732 topStyleChange(context.styleStack).position()!=context.nodeStack.size() // wrong position
733 )
734 {
735 if (context.styleStack.empty())
736 {
737 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{0}> tag without matching <{0}>",tagName);
738 }
739 else if (topStyleChange(context.styleStack).tagName()!=tagNameLower ||
740 topStyleChange(context.styleStack).style()!=s)
741 {
742 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{}> tag while expecting </{}>",
743 tagName,topStyleChange(context.styleStack).tagName());
744 }
745 else
746 {
747 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{}> at different nesting level ({}) than expected ({})",
748 tagName,context.nodeStack.size(),topStyleChange(context.styleStack).position());
749 }
750 }
751 else // end the section
752 {
753 children.append<DocStyleChange>(
754 this,parent,context.nodeStack.size(),s,
755 topStyleChange(context.styleStack).tagName(),false);
756 context.styleStack.pop();
757 }
759 {
760 context.inCodeStyle = false;
761 }
762}
IterableStack< const DocNodeVariant * > DocStyleChangeStack
Definition docparser_p.h:54

References DocNodeList::append(), AUTO_TRACE, context, DocParserContext::fileName, DocTokenizer::getLineNr(), DocParserContext::inCodeStyle, DString::lower(), DocParserContext::nodeStack, parent(), DocParserContext::styleStack, tokenizer, DocStyleChange::Typewriter, and warn_doc_error.

Referenced by defaultHandleToken(), DocPara::handleHtmlEndTag(), and DocPara::handleHtmlStartTag().

◆ handleUnclosedStyleCommands()

void DocParser::handleUnclosedStyleCommands ( )

Definition at line 844 of file docparser.cpp.

845{
846 AUTO_TRACE("content.initialStyleStack.size()={}",context.initialStyleStack.size());
847 if (!context.initialStyleStack.empty())
848 {
849 DString tagName = std::get<DocStyleChange>(*context.initialStyleStack.top()).tagName();
850 DString fileName = std::get<DocStyleChange>(*context.initialStyleStack.top()).fileName();
851 int lineNr = std::get<DocStyleChange>(*context.initialStyleStack.top()).lineNr();
854 if (lineNr != -1)
855 {
857 "end of comment block while expecting "
858 "command </{}> (Probable start '{}' at line {})",tagName, fileName, lineNr);
859 }
860 else
861 {
863 "end of comment block while expecting command </{}>",tagName);
864 }
865 }
866}
void handleUnclosedStyleCommands()

References AUTO_TRACE, context, DocParserContext::fileName, DocTokenizer::getLineNr(), handleUnclosedStyleCommands(), DocParserContext::initialStyleStack, tokenizer, and warn_doc_error.

Referenced by handleUnclosedStyleCommands(), DocRoot::parse(), and DocText::parse().

◆ internalValidatingParseDoc()

Token DocParser::internalValidatingParseDoc ( DocNodeVariant * parent,
DocNodeList & children,
const DString & doc )

Definition at line 1899 of file docparser.cpp.

1901{
1902 AUTO_TRACE();
1903 Token retval = Token::make_RetVal_OK();
1904
1905 if (doc.empty()) return retval;
1906
1908
1909 // first parse any number of paragraphs
1910 bool isFirst=true;
1911 DocPara *lastPar=!children.empty() ? std::get_if<DocPara>(&children.back()): nullptr;
1912 if (lastPar)
1913 { // last child item was a paragraph
1914 isFirst=false;
1915 }
1916 do
1917 {
1918 children.append<DocPara>(this,parent);
1919 DocPara *par = children.get_last<DocPara>();
1920 if (isFirst) { par->markFirst(); isFirst=false; }
1921 retval=par->parse();
1922 if (!par->empty())
1923 {
1924 if (lastPar) lastPar->markLast(false);
1925 lastPar=par;
1926 }
1927 else
1928 {
1929 children.pop_back();
1930 }
1931 } while (retval.is(TokenRetval::TK_NEWPARA));
1932 if (lastPar) lastPar->markLast();
1933
1934 AUTO_TRACE_EXIT("isFirst={} isLast={}",lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
1935 return retval;
1936}
bool isLast() const
Definition docnode.h:1097
bool isFirst() const
Definition docnode.h:1096
void markLast(bool v=true)
Definition docnode.h:1095
void init(const char *input, const DString &fileName, bool markdownSupport, bool insideHtmlLink)
void pop_back()
removes the last element
Definition growvector.h:115
bool empty() const
checks whether the container is empty
Definition growvector.h:140

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_EXIT, GrowVector< T >::back(), context, DString::data(), DString::empty(), GrowVector< T >::empty(), DocParserContext::fileName, DocNodeList::get_last(), DocTokenizer::init(), DocParserContext::insideHtmlLink, Token::is(), DocPara::isFirst(), DocPara::isLast(), DocParserContext::markdownSupport, DocPara::markLast(), parent(), GrowVector< T >::pop_back(), and tokenizer.

Referenced by DocPara::handleInheritDoc(), DocRef::parse(), DocXRefItem::parse(), DocTitle::parseFromString(), and DocSimpleSect::parseRcs().

◆ popContext()

void DocParser::popContext ( )
private

Definition at line 79 of file docparser.cpp.

80{
81 auto &ctx = contextStack.top();
82 context = ctx;
83 tokenizer.setFileName(ctx.fileName);
84 tokenizer.setLineNr(ctx.lineNo);
85 contextStack.pop();
88
89 //DString indent;
90 //indent.fill(' ',contextStack.size()*2+2);
91 //printf("%sdocParserPopContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
92}
std::stack< DocParserContext > contextStack
TokenInfo * token()
void setLineNr(int lineno)
void setFileName(const DString &fileName)

References context, contextStack, DocTokenizer::popContext(), DocTokenizer::setFileName(), DocTokenizer::setLineNr(), DocParserContext::token, DocTokenizer::token(), and tokenizer.

Referenced by DocParser::AutoSaveContext::~AutoSaveContext().

◆ processCopyDoc()

DString DocParser::processCopyDoc ( const char * data,
size_t & len )

Definition at line 2098 of file docparser.cpp.

2099{
2100 AUTO_TRACE("data={} len={}",Trace::trunc(data),len);
2101 DString result;
2102 result.reserve(len+32);
2103 size_t i=0;
2104 int lineNr = tokenizer.getLineNr();
2105 while (i<len)
2106 {
2107 char c = data[i];
2108 if (c=='@' || c=='\\') // look for a command
2109 {
2110 bool isBrief=true;
2111 size_t j=isCopyBriefOrDetailsCmd(data,i,len,isBrief);
2112 if (j>0)
2113 {
2114 // skip whitespace
2115 while (j<len && (data[j]==' ' || data[j]=='\t')) j++;
2116 // extract the argument
2117 DString id = extractCopyDocId(data,j,len);
2118 const Definition *def = nullptr;
2119 DString doc,brief;
2120 //printf("resolving docs='%s'\n",qPrint(id));
2121 bool found = findDocsForMemberOrCompound(id,&doc,&brief,&def);
2122 if (found && def->isReference())
2123 {
2125 "@copy{} or @copydoc target '{}' found but is from a tag file, skipped",
2126 isBrief?"brief":"details", id);
2127 }
2128 else if (found)
2129 {
2130 //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,qPrint(brief),qPrint(doc),isBrief);
2131 auto it = std::find(context.copyStack.begin(),context.copyStack.end(),def);
2132 if (it==context.copyStack.end()) // definition not parsed earlier
2133 {
2134 DString orgFileName = context.fileName;
2135 context.copyStack.push_back(def);
2136 auto addDocs = [&](const DString &file_,int line_,const DString &doc_)
2137 {
2138 result+=" \\ifile \""+file_+"\" ";
2139 result+="\\iline "+DString().setNum(line_)+" \\ilinebr ";
2140 size_t len_ = doc_.length();
2141 result+=processCopyDoc(doc_.data(),len_);
2142 };
2143 if (isBrief)
2144 {
2145 addDocs(def->briefFile(),def->briefLine(),brief);
2146 }
2147 else
2148 {
2149 addDocs(def->docFile(),def->docLine(),doc);
2151 {
2152 const MemberDef *md = toMemberDef(def);
2153 const ArgumentList &docArgList = md->templateMaster() ?
2154 md->templateMaster()->argumentList() :
2155 md->argumentList();
2156 result+=inlineArgListToDoc(docArgList);
2157 }
2158 }
2159 context.copyStack.pop_back();
2160 result+=" \\ilinebr \\ifile \""+context.fileName+"\" ";
2161 result+="\\iline "+DString().setNum(lineNr)+" ";
2162 }
2163 else
2164 {
2166 "Found recursive @copy{} or @copydoc relation for argument '{}'.",
2167 isBrief?"brief":"details",id);
2168 }
2169 }
2170 else
2171 {
2173 "@copy{} or @copydoc target '{}' not found", isBrief?"brief":"details",id);
2174 }
2175 // skip over command
2176 i=j;
2177 }
2178 else
2179 {
2180 DString endMarker;
2181 size_t k = isVerbatimSection(data,i,len,endMarker);
2182 if (k>0)
2183 {
2184 size_t orgPos = i;
2185 i=skipToEndMarker(data,k,len,endMarker);
2186 result+=DString(data+orgPos,i-orgPos);
2187 // TODO: adjust lineNr
2188 }
2189 else
2190 {
2191 result+=c;
2192 i++;
2193 }
2194 }
2195 }
2196 else // not a command, just copy
2197 {
2198 result+=c;
2199 i++;
2200 lineNr += (c=='\n') ? 1 : 0;
2201 }
2202 }
2203 len = result.length();
2204 AUTO_TRACE_EXIT("result={}",Trace::trunc(result));
2205 return result;
2206}
DString & setNum(short n)
Definition dstring.h:552
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition dstring.h:217
virtual DString briefFile() const =0
virtual int briefLine() const =0
virtual bool isReference() const =0
bool findDocsForMemberOrCompound(const DString &commandName, DString *pDoc, DString *pBrief, const Definition **pDef)
DString processCopyDoc(const char *data, size_t &len)
virtual const MemberDef * templateMaster() const =0
static DString extractCopyDocId(const char *data, size_t &j, size_t len)
static size_t isVerbatimSection(const char *data, size_t i, size_t len, DString &endMarker)
static size_t skipToEndMarker(const char *data, size_t i, size_t len, const DString &endMarker)
static size_t isCopyBriefOrDetailsCmd(const char *data, size_t i, size_t len, bool &brief)
MemberDef * toMemberDef(Definition *d)
DString trunc(const DString &s, size_t numChars=15)
Definition trace.h:56
DefinitionStack copyStack
Definition docparser_p.h:69
DString inlineArgListToDoc(const ArgumentList &al)
Definition util.cpp:4871

References MemberDef::argumentList(), AUTO_TRACE, AUTO_TRACE_EXIT, Definition::briefFile(), Definition::briefLine(), context, DocParserContext::copyStack, Definition::definitionType(), Definition::docFile(), Definition::docLine(), extractCopyDocId(), DocParserContext::fileName, findDocsForMemberOrCompound(), DocTokenizer::getLineNr(), inlineArgListToDoc(), isCopyBriefOrDetailsCmd(), Definition::isReference(), isVerbatimSection(), DString::length(), processCopyDoc(), DString::reserve(), DString::setNum(), skipToEndMarker(), MemberDef::templateMaster(), tokenizer, toMemberDef(), Trace::trunc(), Definition::TypeMember, and warn_doc_error.

Referenced by processCopyDoc(), and validatingParseDoc().

◆ pushContext()

void DocParser::pushContext ( )
private

Definition at line 64 of file docparser.cpp.

65{
66 //DString indent;
67 //indent.fill(' ',contextStack.size()*2+2);
68 //printf("%sdocParserPushContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
69
71 contextStack.emplace();
72 auto &ctx = contextStack.top();
73 ctx = context;
75 ctx.lineNo = tokenizer.getLineNr();
77}
DString getFileName() const

References context, contextStack, DocParserContext::fileName, DocTokenizer::getFileName(), DocTokenizer::getLineNr(), DocTokenizer::pushContext(), DocParserContext::token, DocTokenizer::token(), and tokenizer.

Referenced by DocParser::AutoSaveContext::AutoSaveContext().

◆ readTextFileByName()

void DocParser::readTextFileByName ( const DString & file,
DString & text )

Definition at line 1940 of file docparser.cpp.

1941{
1942 AUTO_TRACE("file={} text={}",file,text);
1943 bool ambig = false;
1944 DString filePath = findExampleFilePath(file,ambig);
1945 if (!filePath.empty())
1946 {
1947 size_t indent = 0;
1948 text = detab(fileToString(filePath,Config_getBool(FILTER_SOURCE_FILES)),indent);
1949 if (ambig)
1950 {
1951 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file name '{}' is ambiguous"
1952 "Possible candidates:\n{}",file, Doxygen::exampleNameLinkedMap->showFileDefMatches(file));
1953 }
1954 }
1955 else
1956 {
1957 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file '{}' is not found. "
1958 "Check your EXAMPLE_PATH",file);
1959 }
1960}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:95
DString detab(const DString &s, size_t &refIndent)
Definition util.cpp:5200
DString fileToString(const DString &name, bool filter, bool isSourceCode)
Definition util.cpp:1058
DString findExampleFilePath(const DString &file, bool &ambig)
Definition util.cpp:2457

References AUTO_TRACE, Config_getBool, context, detab(), DString::empty(), Doxygen::exampleNameLinkedMap, DocParserContext::fileName, fileToString(), findExampleFilePath(), DocTokenizer::getLineNr(), FileNameLinkedMap::showFileDefMatches(), tokenizer, and warn_doc_error.

Referenced by DocInclude::parse().

Member Data Documentation

◆ context

DocParserContext DocParser::context

Definition at line 152 of file docparser_p.h.

Referenced by DocSimpleSect::appendLinkWord(), AutoNodeStack::AutoNodeStack(), checkArgumentName(), checkIfHtmlEndTagEndsAutoList(), checkRetvalName(), checkUnOrMultipleDocumentedParams(), createRef(), currentFileDef(), defaultHandleTitleAndSize(), defaultHandleToken(), DocAnchor::DocAnchor(), DocCite::DocCite(), DocDiaFile::DocDiaFile(), DocDotFile::DocDotFile(), DocEmoji::DocEmoji(), DocFormula::DocFormula(), DocHtmlCaption::DocHtmlCaption(), DocLink::DocLink(), DocLinkedWord::DocLinkedWord(), DocMermaidFile::DocMermaidFile(), DocMscFile::DocMscFile(), DocPlantUmlFile::DocPlantUmlFile(), DocRef::DocRef(), DocWord::DocWord(), errorHandleDefaultToken(), findAndCopyImage(), findDocsForMemberOrCompound(), handleAHref(), handleAnchor(), handleCite(), DocPara::handleCommand(), DocPara::handleDoxyConfig(), DocPara::handleEmoji(), DocPara::handleFile(), DocPara::handleHtmlStartTag(), handleIFile(), handleILine(), handleImage(), handleImg(), DocPara::handleInclude(), DocPara::handleIncludeOperator(), DocPara::handleInheritDoc(), handleInitialStyleCommands(), handleInternalRef(), DocPara::handleLink(), handleLinkedWord(), handleParameterType(), handlePendingStyleCommands(), handlePrefix(), handleRef(), DocPara::handleSection(), DocPara::handleShowDate(), DocPara::handleStartCode(), handleStyleArgument(), handleStyleEnter(), handleStyleLeave(), handleUnclosedStyleCommands(), DocPara::handleXRefItem(), DocPara::injectToken(), internalValidatingParseDoc(), DocAutoList::parse(), DocHRef::parse(), DocHtmlCaption::parse(), DocHtmlDescData::parse(), DocHtmlDescList::parse(), DocHtmlDescTitle::parse(), DocHtmlHeader::parse(), DocHtmlList::parse(), DocHtmlRow::parse(), DocHtmlTable::parse(), DocInclude::parse(), DocIncOperator::parse(), DocIndexEntry::parse(), DocInternal::parse(), DocLink::parse(), DocPara::parse(), DocParamList::parse(), DocRef::parse(), DocRoot::parse(), DocSecRefList::parse(), DocSection::parse(), DocText::parse(), DocTitle::parseFromString(), DocSimpleSect::parseRcs(), DocHtmlList::parseXml(), DocHtmlRow::parseXml(), DocHtmlTable::parseXml(), DocParamList::parseXml(), popContext(), processCopyDoc(), pushContext(), readTextFileByName(), skipSpacesForTable(), validatingParseDoc(), validatingParseText(), validatingParseTitle(), and AutoNodeStack::~AutoNodeStack().

◆ contextStack

std::stack< DocParserContext > DocParser::contextStack

Definition at line 151 of file docparser_p.h.

Referenced by popContext(), and pushContext().

◆ tokenizer

DocTokenizer DocParser::tokenizer

Definition at line 153 of file docparser_p.h.

Referenced by checkIfHtmlEndTagEndsAutoList(), createRef(), defaultHandleTitleAndSize(), defaultHandleToken(), DocAnchor::DocAnchor(), DocCite::DocCite(), DocEmoji::DocEmoji(), docFindSections(), DocFormula::DocFormula(), DocHtmlCaption::DocHtmlCaption(), DocLink::DocLink(), DocRef::DocRef(), errorHandleDefaultToken(), findAndCopyImage(), handleAHref(), handleAnchor(), handleCite(), DocPara::handleCommand(), DocPara::handleDoxyConfig(), DocPara::handleEmoji(), DocPara::handleFile(), DocPara::handleHtmlEndTag(), DocPara::handleHtmlStartTag(), handleIFile(), handleILine(), handleImage(), handleImg(), DocPara::handleInclude(), DocPara::handleIncludeOperator(), handleInternalRef(), DocPara::handleLink(), handleLinkedWord(), handlePrefix(), handleRef(), DocPara::handleSection(), DocPara::handleShowDate(), DocPara::handleStartCode(), handleStyleArgument(), handleStyleEnter(), handleStyleLeave(), handleUnclosedStyleCommands(), DocPara::handleXRefItem(), internalValidatingParseDoc(), DocAutoList::parse(), DocHRef::parse(), DocHtmlCaption::parse(), DocHtmlDescList::parse(), DocHtmlDescTitle::parse(), DocHtmlHeader::parse(), DocHtmlList::parse(), DocHtmlRow::parse(), DocHtmlSummary::parse(), DocHtmlTable::parse(), DocIndexEntry::parse(), DocInternalRef::parse(), DocLink::parse(), DocPara::parse(), DocParamList::parse(), DocRef::parse(), DocRoot::parse(), DocSecRefItem::parse(), DocSecRefList::parse(), DocText::parse(), DocTitle::parse(), DocVhdlFlow::parse(), DocTitle::parseFromString(), DocHtmlList::parseXml(), DocHtmlRow::parseXml(), DocHtmlTable::parseXml(), popContext(), processCopyDoc(), pushContext(), readTextFileByName(), skipSpacesForTable(), validatingParseDoc(), validatingParseText(), and validatingParseTitle().


The documentation for this class was generated from the following files: