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

#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 QCString &doc)
QCString processCopyDoc (const char *data, size_t &len)
QCString findAndCopyImage (const QCString &fileName, DocImage::Type type, bool doWarn=true)
void checkArgumentName ()
void checkRetvalName ()
void checkUnOrMultipleDocumentedParams ()
bool findDocsForMemberOrCompound (const QCString &commandName, QCString *pDoc, QCString *pBrief, const Definition **pDef)
bool defaultHandleToken (DocNodeVariant *parent, Token &tok, DocNodeList &children, bool handleWord=TRUE)
void errorHandleDefaultToken (DocNodeVariant *parent, Token tok, DocNodeList &children, const QCString &txt)
void defaultHandleTitleAndSize (const CommandType cmd, DocNodeVariant *parent, DocNodeList &children, QCString &width, QCString &height)
Token handleStyleArgument (DocNodeVariant *parent, DocNodeList &children, const QCString &cmdName)
void handleStyleEnter (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName, const HtmlAttribList *attribs)
void handleStyleLeave (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &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 QCString &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 QCString &cmdName)
void handleIFile (char cmdChar, const QCString &cmdName)
void handleILine (char cmdChar, const QCString &cmdName)
void readTextFileByName (const QCString &file, QCString &text)

Public Attributes

std::stack< DocParserContextcontextStack
DocParserContext context
DocTokenizer tokenizer

Private Member Functions

void pushContext ()
void popContext ()

Detailed Description

Definition at line 101 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 210 of file docparser.cpp.

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

References argListToString(), Config_getBool, context, QCString::data(), Definition::docFile(), Definition::docLine(), ArgumentList::empty(), end(), QCString::endsWith(), FALSE, QCString::isEmpty(), QCString::left(), QCString::length(), QCString::lower(), reg::match(), Definition::name(), qPrint(), ArgumentList::size(), QCString::size(), QCString::sprintf(), QCString::str(), QCString::stripWhiteSpace(), QCString::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 311 of file docparser.cpp.

312{
313 QCString name = context.token->name;
314 if (!Config_getBool(WARN_IF_DOC_ERROR)) return;
315 if (context.memberDef==nullptr || name.isEmpty()) return; // not a member or no valid name
316 if (context.retvalsFound.count(name.str())==1) // only report the first double entry
317 {
318 warn_doc_error(context.memberDef->getDefFileName(),
319 context.memberDef->getDefLine(),
320 "return value '{}' of {} has multiple documentation sections",
321 name, context.memberDef->qualifiedName());
322 }
323 context.retvalsFound.insert(name.str());
324}

References Config_getBool, context, QCString::isEmpty(), QCString::str(), 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 332 of file docparser.cpp.

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

References argListToString(), Config_getBool, context, ArgumentList::empty(), QCString::endsWith(), FALSE, QCString::isEmpty(), QCString::left(), QCString::length(), QCString::lower(), ArgumentList::push_back(), ArgumentList::size(), QCString::str(), QCString::stripWhiteSpace(), TRUE, warn_doc_error, and warn_incomplete_doc.

Referenced by validatingParseDoc().

◆ defaultHandleTitleAndSize()

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

Definition at line 1210 of file docparser.cpp.

1211{
1212 AUTO_TRACE();
1213 auto ns = AutoNodeStack(this,parent);
1214
1215 // parse title
1216 tokenizer.setStateTitle();
1217 Token tok = tokenizer.lex();
1218 while (!tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1219 {
1220 if (tok.is(TokenRetval::TK_WORD) && (context.token->name=="width=" || context.token->name=="height="))
1221 {
1222 // special case: no title, but we do have a size indicator
1223 break;
1224 }
1225 else if (tok.is(TokenRetval::TK_HTMLTAG))
1226 {
1227 tokenizer.unputString(context.token->text);
1228 break;
1229 }
1230 if (!defaultHandleToken(parent,tok,children))
1231 {
1232 errorHandleDefaultToken(parent,tok,children,Mappers::cmdMapper->find(cmd));
1233 }
1234 tok = tokenizer.lex();
1235 }
1236 // parse size attributes
1237 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1238 {
1239 tok=tokenizer.lex();
1240 }
1241 while (tok.is_any_of(TokenRetval::TK_WHITESPACE,TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG)) // there are values following the title
1242 {
1243 if (tok.is(TokenRetval::TK_WORD))
1244 {
1245 if (context.token->name=="width=" || context.token->name=="height=")
1246 {
1247 tokenizer.setStateTitleAttrValue();
1248 context.token->name = context.token->name.left(context.token->name.length()-1);
1249 }
1250
1251 if (context.token->name=="width")
1252 {
1253 width = context.token->chars;
1254 }
1255 else if (context.token->name=="height")
1256 {
1257 height = context.token->chars;
1258 }
1259 else // other text after the title -> treat as normal text
1260 {
1261 tokenizer.unputString(context.token->name);
1262 //warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unknown option '{}' after \\{} command, expected 'width' or 'height'",
1263 // context.token->name, Mappers::cmdMapper->find(cmd));
1264 break;
1265 }
1266 }
1267
1268 tok=tokenizer.lex();
1269 // if we found something we did not expect, push it back to the stream
1270 // so it can still be processed
1271 if (tok.is_any_of(TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS))
1272 {
1273 tokenizer.unputString(context.token->name);
1274 tokenizer.unputString(tok.is(TokenRetval::TK_COMMAND_AT) ? "@" : "\\");
1275 break;
1276 }
1277 else if (tok.is(TokenRetval::TK_SYMBOL))
1278 {
1279 tokenizer.unputString(context.token->name);
1280 break;
1281 }
1282 else if (tok.is(TokenRetval::TK_HTMLTAG))
1283 {
1284 tokenizer.unputString(context.token->text);
1285 break;
1286 }
1287 }
1288 tokenizer.setStatePara();
1289
1291 AUTO_TRACE_EXIT("width={} height={}",width,height);
1292}
void handlePendingStyleCommands(DocNodeVariant *parent, DocNodeList &children, size_t numberOfElementsToClose=0)
DocTokenizer tokenizer
bool defaultHandleToken(DocNodeVariant *parent, Token &tok, DocNodeList &children, bool handleWord=TRUE)
void errorHandleDefaultToken(DocNodeVariant *parent, Token tok, DocNodeList &children, const QCString &txt)
bool is(TokenRetval rv) const
bool is_any_of(ARGS... args) const
#define AUTO_TRACE(...)
Definition docnode.cpp:48
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:50
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, Mappers::cmdMapper, context, defaultHandleToken(), errorHandleDefaultToken(), handlePendingStyleCommands(), Token::is(), Token::is_any_of(), parent(), and tokenizer.

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 1473 of file docparser.cpp.

1474{
1475 AUTO_TRACE("token={} handleWord={}",tok.to_string(),handleWord);
1476 if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD,TokenRetval::TK_SYMBOL,TokenRetval::TK_URL,
1477 TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS,TokenRetval::TK_HTMLTAG)
1478 )
1479 {
1480 }
1481reparsetoken:
1482 QCString tokenName = context.token->name;
1483 AUTO_TRACE_ADD("tokenName={}",tokenName);
1484 switch (tok.value())
1485 {
1486 case TokenRetval::TK_COMMAND_AT:
1487 // fall through
1488 case TokenRetval::TK_COMMAND_BS:
1489 switch (Mappers::cmdMapper->map(tokenName))
1490 {
1492 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_BSlash);
1493 break;
1495 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_At);
1496 break;
1498 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Less);
1499 break;
1501 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Greater);
1502 break;
1504 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Amp);
1505 break;
1507 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dollar);
1508 break;
1510 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Hash);
1511 break;
1513 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_DoubleColon);
1514 break;
1516 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Percent);
1517 break;
1519 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1520 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1521 break;
1523 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1524 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1525 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1526 break;
1528 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quot);
1529 break;
1531 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dot);
1532 break;
1534 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Exclam);
1535 break;
1537 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quest);
1538 break;
1540 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Plus);
1541 break;
1543 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1544 break;
1546 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Equal);
1547 break;
1549 {
1550 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,TRUE);
1551 tok=handleStyleArgument(parent,children,tokenName);
1552 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,FALSE);
1553 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1554 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1555 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1556 {
1557 AUTO_TRACE_ADD("CommandType::CMD_EMPHASIS: reparsing");
1558 goto reparsetoken;
1559 }
1560 }
1561 break;
1563 {
1564 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,TRUE);
1565 tok=handleStyleArgument(parent,children,tokenName);
1566 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,FALSE);
1567 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1568 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1569 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1570 {
1571 AUTO_TRACE_ADD("CommandType::CMD_BOLD: reparsing");
1572 goto reparsetoken;
1573 }
1574 }
1575 break;
1577 {
1578 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,TRUE);
1579 tok=handleStyleArgument(parent,children,tokenName);
1580 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,FALSE);
1581 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1582 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1583 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1584 {
1585 AUTO_TRACE_ADD("CommandType::CMD_CODE: reparsing");
1586 goto reparsetoken;
1587 }
1588 }
1589 break;
1591 {
1592 tokenizer.setStateHtmlOnly();
1593 tok = tokenizer.lex();
1594 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::HtmlOnly,context.isExample,context.exampleName,context.token->name=="block");
1595 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1596 {
1597 warn_doc_error(context.fileName,tokenizer.getLineNr(),"htmlonly section ended without end marker");
1598 }
1599 tokenizer.setStatePara();
1600 }
1601 break;
1603 {
1604 tokenizer.setStateManOnly();
1605 tok = tokenizer.lex();
1606 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::ManOnly,context.isExample,context.exampleName);
1607 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1608 {
1609 warn_doc_error(context.fileName,tokenizer.getLineNr(),"manonly section ended without end marker");
1610 }
1611 tokenizer.setStatePara();
1612 }
1613 break;
1615 {
1616 tokenizer.setStateRtfOnly();
1617 tok = tokenizer.lex();
1618 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::RtfOnly,context.isExample,context.exampleName);
1619 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1620 {
1621 warn_doc_error(context.fileName,tokenizer.getLineNr(),"rtfonly section ended without end marker");
1622 }
1623 tokenizer.setStatePara();
1624 }
1625 break;
1627 {
1628 tokenizer.setStateLatexOnly();
1629 tok = tokenizer.lex();
1630 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::LatexOnly,context.isExample,context.exampleName);
1631 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1632 {
1633 warn_doc_error(context.fileName,tokenizer.getLineNr(),"latexonly section ended without end marker");
1634 }
1635 tokenizer.setStatePara();
1636 }
1637 break;
1639 {
1640 tokenizer.setStateXmlOnly();
1641 tok = tokenizer.lex();
1642 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::XmlOnly,context.isExample,context.exampleName);
1643 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1644 {
1645 warn_doc_error(context.fileName,tokenizer.getLineNr(),"xmlonly section ended without end marker");
1646 }
1647 tokenizer.setStatePara();
1648 }
1649 break;
1651 {
1652 tokenizer.setStateDbOnly();
1653 tok = tokenizer.lex();
1654 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::DocbookOnly,context.isExample,context.exampleName);
1655 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1656 {
1657 warn_doc_error(context.fileName,tokenizer.getLineNr(),"docbookonly section ended without end marker");
1658 }
1659 tokenizer.setStatePara();
1660 }
1661 break;
1663 {
1664 children.append<DocFormula>(this,parent,context.token->id);
1665 }
1666 break;
1669 {
1670 handleAnchor(parent,children);
1671 }
1672 break;
1674 {
1675 handleCite(parent,children);
1676 }
1677 break;
1679 {
1680 handlePrefix(parent,children);
1681 }
1682 break;
1684 {
1685 handleInternalRef(parent,children);
1686 tokenizer.setStatePara();
1687 }
1688 break;
1690 {
1691 tokenizer.setStateSetScope();
1692 (void)tokenizer.lex();
1693 context.context = context.token->name;
1694 //printf("Found scope='%s'\n",qPrint(context.context));
1695 tokenizer.setStatePara();
1696 }
1697 break;
1699 handleImage(parent,children);
1700 break;
1702 handleILine(tok.command_to_char(),tokenName);
1703 break;
1705 handleIFile(tok.command_to_char(),tokenName);
1706 break;
1707 default:
1708 return FALSE;
1709 }
1710 break;
1711 case TokenRetval::TK_HTMLTAG:
1712 {
1713 auto handleEnterLeaveStyle = [this,&parent,&children,&tokenName](DocStyleChange::Style style) {
1714 if (!context.token->endTag)
1715 {
1716 handleStyleEnter(parent,children,style,tokenName,&context.token->attribs);
1717 }
1718 else
1719 {
1720 handleStyleLeave(parent,children,style,tokenName);
1721 }
1722 };
1723 switch (Mappers::htmlTagMapper->map(tokenName))
1724 {
1726 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <div> tag in heading");
1727 break;
1729 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <pre> tag in heading");
1730 break;
1732 handleEnterLeaveStyle(DocStyleChange::Span);
1733 break;
1735 handleEnterLeaveStyle(DocStyleChange::Bold);
1736 break;
1738 handleEnterLeaveStyle(DocStyleChange::S);
1739 break;
1741 handleEnterLeaveStyle(DocStyleChange::Strike);
1742 break;
1744 handleEnterLeaveStyle(DocStyleChange::Del);
1745 break;
1747 handleEnterLeaveStyle(DocStyleChange::Underline);
1748 break;
1750 handleEnterLeaveStyle(DocStyleChange::Ins);
1751 break;
1753 case HtmlTagType::XML_C:
1754 handleEnterLeaveStyle(DocStyleChange::Code);
1755 break;
1757 handleEnterLeaveStyle(DocStyleChange::Kbd);
1758 break;
1760 handleEnterLeaveStyle(DocStyleChange::Typewriter);
1761 break;
1763 handleEnterLeaveStyle(DocStyleChange::Italic);
1764 break;
1766 handleEnterLeaveStyle(DocStyleChange::Subscript);
1767 break;
1769 handleEnterLeaveStyle(DocStyleChange::Superscript);
1770 break;
1772 handleEnterLeaveStyle(DocStyleChange::Center);
1773 break;
1775 handleEnterLeaveStyle(DocStyleChange::Small);
1776 break;
1778 handleEnterLeaveStyle(DocStyleChange::Cite);
1779 break;
1781 if (!context.token->endTag)
1782 {
1783 handleImg(parent,children,context.token->attribs);
1784 }
1785 break;
1786 default:
1787 return FALSE;
1788 break;
1789 }
1790 }
1791 break;
1792 case TokenRetval::TK_SYMBOL:
1793 {
1796 {
1797 children.append<DocSymbol>(this,parent,s);
1798 }
1799 else
1800 {
1801 return FALSE;
1802 }
1803 }
1804 break;
1805 case TokenRetval::TK_WHITESPACE:
1806 case TokenRetval::TK_NEWPARA:
1807handlepara:
1808 if (insidePRE(parent) || !children.empty())
1809 {
1810 children.append<DocWhiteSpace>(this,parent,context.token->chars);
1811 }
1812 break;
1813 case TokenRetval::TK_LNKWORD:
1814 if (handleWord)
1815 {
1816 handleLinkedWord(parent,children);
1817 }
1818 else
1819 return FALSE;
1820 break;
1821 case TokenRetval::TK_WORD:
1822 if (handleWord)
1823 {
1824 children.append<DocWord>(this,parent,context.token->name);
1825 }
1826 else
1827 return FALSE;
1828 break;
1829 case TokenRetval::TK_URL:
1830 if (context.insideHtmlLink)
1831 {
1832 children.append<DocWord>(this,parent,context.token->name);
1833 }
1834 else
1835 {
1836 children.append<DocURL>(this,parent,context.token->name,context.token->isEMailAddr);
1837 }
1838 break;
1839 default:
1840 return FALSE;
1841 }
1842 return TRUE;
1843}
void handleInternalRef(DocNodeVariant *parent, DocNodeList &children)
void handleStyleLeave(DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName)
void handleImage(DocNodeVariant *parent, DocNodeList &children)
void handleStyleEnter(DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName, const HtmlAttribList *attribs)
void handleCite(DocNodeVariant *parent, DocNodeList &children)
void handlePrefix(DocNodeVariant *parent, DocNodeList &children)
Token handleStyleArgument(DocNodeVariant *parent, DocNodeList &children, const QCString &cmdName)
void handleIFile(char cmdChar, const QCString &cmdName)
void handleLinkedWord(DocNodeVariant *parent, DocNodeList &children, bool ignoreAutoLinkFlag=FALSE, bool typeLinkOnly=false)
void handleILine(char cmdChar, const QCString &cmdName)
void handleAnchor(DocNodeVariant *parent, DocNodeList &children)
void handleImg(DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
static HtmlEntityMapper::SymType decodeSymbol(const QCString &symName)
Definition docnode.cpp:155
TOKEN_SPECIFICATIONS RETVAL_SPECIFICATIONS const char * to_string() const
TokenRetval value() const
char command_to_char() const
@ CMD_INTERNALREF
Definition cmdmapper.h:65
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:49
bool insidePRE(const DocNodeVariant *n)
const Mapper< HtmlTagType > * htmlTagMapper
void append(Args &&... args)
Append a new DocNodeVariant to the list by constructing it with type T and parameters Args.
Definition docnode.h:1404

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, DocStyleChange::Bold, DocStyleChange::Center, 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, DocSymbol::decodeSymbol(), DocStyleChange::Del, DocVerbatim::DocbookOnly, GrowVector< T >::empty(), FALSE, 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, DocStyleChange::Ins, insidePRE(), Token::is(), Token::is_any_of(), DocStyleChange::Italic, DocStyleChange::Kbd, DocVerbatim::LatexOnly, DocVerbatim::ManOnly, parent(), DocVerbatim::RtfOnly, DocStyleChange::S, 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(), tokenizer, TRUE, DocStyleChange::Typewriter, DocStyleChange::Underline, Token::value(), 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 QCString & txt )

Definition at line 592 of file docparser.cpp.

594{
595 switch (tok.value())
596 {
597 case TokenRetval::TK_COMMAND_AT:
598 // fall through
599 case TokenRetval::TK_COMMAND_BS:
600 {
601 char cs[2] = { tok.command_to_char(), 0 };
602 children.append<DocWord>(this,parent,cs + context.token->name);
603 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Illegal command '{:c}{}' found as part of a {}",
604 tok.command_to_char(),context.token->name,txt);
605 }
606 break;
607 case TokenRetval::TK_SYMBOL:
608 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported symbol '{}' found as part of a {}",
609 qPrint(context.token->name), qPrint(txt));
610 break;
611 case TokenRetval::TK_HTMLTAG:
612 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported HTML tag <{}{}> found as part of a {}",
613 context.token->endTag ? "/" : "",context.token->name, txt);
614 break;
615 default:
616 children.append<DocWord>(this,parent,context.token->name);
617 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unexpected token {} found as part of a {}",
618 tok.to_string(), txt);
619 break;
620 }
621}

References DocNodeList::append(), Token::command_to_char(), context, parent(), qPrint(), Token::to_string(), 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()

QCString DocParser::findAndCopyImage ( const QCString & 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 96 of file docparser.cpp.

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

References FileDef::absFilePath(), Config_getBool, Config_getString, context, copyFile(), DocImage::DocBook, QCString::endsWith(), err, FileInfo::exists(), QCString::ExplicitSize, findFileDef(), QCString::findRev(), DocImage::Html, Doxygen::imageNameLinkedMap, Doxygen::indexList, FileInfo::isSymLink(), DocImage::Latex, QCString::left(), QCString::length(), Definition::name(), qPrint(), Dir::remove(), QCString::right(), DocImage::Rtf, showFileDefMatches(), QCString::sprintf(), QCString::startsWith(), QCString::str(), Portable::system(), tokenizer, warn_doc_error, and DocImage::Xml.

Referenced by handleImage(), and handleImg().

◆ findDocsForMemberOrCompound()

bool DocParser::findDocsForMemberOrCompound ( const QCString & commandName,
QCString * pDoc,
QCString * 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 439 of file docparser.cpp.

443{
444 AUTO_TRACE("commandName={}",commandName);
445 *pDoc="";
446 *pBrief="";
447 *pDef=nullptr;
448 QCString cmdArg=commandName;
449 if (cmdArg.isEmpty())
450 {
451 AUTO_TRACE_EXIT("empty");
452 return false;
453 }
454
455 const FileDef *fd=nullptr;
456 const GroupDef *gd=nullptr;
457 const PageDef *pd=nullptr;
458 gd = Doxygen::groupLinkedMap->find(cmdArg);
459 if (gd) // group
460 {
461 *pDoc=gd->documentation();
462 *pBrief=gd->briefDescription();
463 *pDef=gd;
464 AUTO_TRACE_EXIT("group");
465 return true;
466 }
467 pd = Doxygen::pageLinkedMap->find(cmdArg);
468 if (pd) // page
469 {
470 *pDoc=pd->documentation();
471 *pBrief=pd->briefDescription();
472 *pDef=pd;
473 AUTO_TRACE_EXIT("page");
474 return true;
475 }
476 bool ambig = false;
477 fd = findFileDef(Doxygen::inputNameLinkedMap,cmdArg,ambig);
478 if (fd && !ambig) // file
479 {
480 *pDoc=fd->documentation();
481 *pBrief=fd->briefDescription();
482 *pDef=fd;
483 AUTO_TRACE_EXIT("file");
484 return true;
485 }
486
487 // for symbols we need to normalize the separator, so A#B, or A\B, or A.B becomes A::B
488 cmdArg = substitute(cmdArg,"#","::");
489 cmdArg = substitute(cmdArg,"\\","::");
490 bool extractAnonNs = Config_getBool(EXTRACT_ANON_NSPACES);
491 if (extractAnonNs &&
492 cmdArg.startsWith("anonymous_namespace{")
493 )
494 {
495 size_t rightBracePos = cmdArg.find("}", static_cast<int>(qstrlen("anonymous_namespace{")));
496 QCString leftPart = cmdArg.left(rightBracePos + 1);
497 QCString rightPart = cmdArg.right(cmdArg.size() - rightBracePos - 1);
498 rightPart = substitute(rightPart, ".", "::");
499 cmdArg = leftPart + rightPart;
500 }
501 else
502 {
503 cmdArg = substitute(cmdArg,".","::");
504 }
505
506 int l=static_cast<int>(cmdArg.length());
507
508 int funcStart=cmdArg.find('(');
509 if (funcStart==-1)
510 {
511 funcStart=l;
512 }
513 else
514 {
515 // Check for the case of operator() and the like.
516 // beware of scenarios like operator()((foo)bar)
517 int secondParen = cmdArg.find('(', funcStart+1);
518 int leftParen = cmdArg.find(')', funcStart+1);
519 if (leftParen!=-1 && secondParen!=-1)
520 {
521 if (leftParen<secondParen)
522 {
523 funcStart=secondParen;
524 }
525 }
526 }
527
528 QCString name=removeRedundantWhiteSpace(cmdArg.left(funcStart));
529 QCString args=cmdArg.right(l-funcStart);
530 // try if the link is to a member
531 GetDefInput input(
532 context.context.find('.')==-1 ? context.context : QCString(), // find('.') is a hack to detect files
533 name,
534 args);
535 input.checkCV=true;
536 GetDefResult result = getDefs(input);
537 //printf("found=%d context=%s name=%s\n",result.found,qPrint(context.context),qPrint(name));
538 if (result.found && result.md)
539 {
540 *pDoc=result.md->documentation();
541 *pBrief=result.md->briefDescription();
542 *pDef=result.md;
543 AUTO_TRACE_EXIT("member");
544 return true;
545 }
546
547 int scopeOffset=static_cast<int>(context.context.length());
548 do // for each scope
549 {
550 QCString fullName=cmdArg;
551 if (scopeOffset>0)
552 {
553 fullName.prepend(context.context.left(scopeOffset)+"::");
554 }
555 //printf("Trying fullName='%s'\n",qPrint(fullName));
556
557 // try class, namespace, group, page, file reference
558 const ClassDef *cd = Doxygen::classLinkedMap->find(fullName);
559 if (cd) // class
560 {
561 *pDoc=cd->documentation();
562 *pBrief=cd->briefDescription();
563 *pDef=cd;
564 AUTO_TRACE_EXIT("class");
565 return true;
566 }
567 const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(fullName);
568 if (nd) // namespace
569 {
570 *pDoc=nd->documentation();
571 *pBrief=nd->briefDescription();
572 *pDef=nd;
573 AUTO_TRACE_EXIT("namespace");
574 return true;
575 }
576 if (scopeOffset==0)
577 {
578 scopeOffset=-1;
579 }
580 else
581 {
582 scopeOffset = context.context.findRev("::",scopeOffset-1);
583 if (scopeOffset==-1) scopeOffset=0;
584 }
585 } while (scopeOffset>=0);
586
587 AUTO_TRACE_EXIT("not found");
588 return FALSE;
589}
virtual QCString briefDescription(bool abbreviate=FALSE) const =0
virtual QCString documentation() const =0
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:115
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:104
static ClassLinkedMap * classLinkedMap
Definition doxygen.h:95
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:99
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:114
const T * find(const std::string &key) const
Definition linkedmap.h:47
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:422
bool startsWith(const char *s) const
Definition qcstring.h:507
size_t size() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:169
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:571
uint32_t qstrlen(const char *str)
Returns the length of string str, or 0 if a null pointer is passed.
Definition qcstring.h:58
const MemberDef * md
Definition util.h:173
bool found
Definition util.h:172
QCString removeRedundantWhiteSpace(const QCString &s)
Definition util.cpp:567
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:2308

References AUTO_TRACE, AUTO_TRACE_EXIT, Definition::briefDescription(), GetDefInput::checkCV, Doxygen::classLinkedMap, Config_getBool, context, Definition::documentation(), FALSE, QCString::find(), findFileDef(), GetDefResult::found, getDefs(), Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, QCString::isEmpty(), QCString::left(), QCString::length(), GetDefResult::md, Doxygen::namespaceLinkedMap, Doxygen::pageLinkedMap, QCString::prepend(), qstrlen(), removeRedundantWhiteSpace(), QCString::right(), QCString::size(), QCString::startsWith(), and substitute().

Referenced by processCopyDoc().

◆ handleAHref()

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

Definition at line 778 of file docparser.cpp.

780{
781 AUTO_TRACE();
782 size_t index=0;
783 Token retval = Token::make_RetVal_OK();
784 for (const auto &opt : tagHtmlAttribs)
785 {
786 if (opt.name=="name" || opt.name=="id") // <a name=label> or <a id=label> tag
787 {
788 if (!opt.value.isEmpty())
789 {
790 children.append<DocAnchor>(this,parent,opt.value,TRUE);
791 break; // stop looking for other tag attribs
792 }
793 else
794 {
795 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <a> tag with name option but without value!");
796 }
797 }
798 else if (opt.name=="href") // <a href=url>..</a> tag
799 {
800 // copy attributes
801 HtmlAttribList attrList = tagHtmlAttribs;
802 // and remove the href attribute
803 attrList.erase(attrList.begin()+index);
804 QCString relPath;
805 if (opt.value.at(0) != '#') relPath = context.relPath;
806 children.append<DocHRef>(this, parent, attrList,
807 opt.value, relPath,
808 convertNameToFile(context.fileName, FALSE, TRUE));
809 context.insideHtmlLink=TRUE;
810 retval = children.get_last<DocHRef>()->parse();
811 context.insideHtmlLink=FALSE;
812 tokenizer.setStatePara();
813 break;
814 }
815 else // unsupported option for tag a
816 {
817 }
818 ++index;
819 }
820 return retval;
821}
bool parse(const QCString &fileName, bool update=FALSE, CompareMode compareMode=CompareMode::Full)
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
QCString convertNameToFile(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:3525

References DocNodeList::append(), AUTO_TRACE, context, convertNameToFile(), FALSE, DocNodeList::get_last(), parent(), tokenizer, TRUE, and warn_doc_error.

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

◆ handleAnchor()

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

Definition at line 1040 of file docparser.cpp.

1041{
1042 AUTO_TRACE();
1043 Token tok=tokenizer.lex();
1044 if (!tok.is(TokenRetval::TK_WHITESPACE))
1045 {
1046 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
1047 context.token->name);
1048 return;
1049 }
1050
1052 tokenizer.setStateAnchor();
1053 tok=tokenizer.lex();
1054 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1055 {
1056 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
1057 "argument of command {}",context.token->name);
1058 return;
1059 }
1060 else if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1061 {
1062 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
1063 tok.to_string(),context.token->name);
1064 return;
1065 }
1066 }
1067 children.append<DocAnchor>(this,parent,context.token->name,FALSE);
1068}
friend class AutoSaveState

References DocNodeList::append(), AUTO_TRACE, context, FALSE, Token::is(), Token::is_any_of(), parent(), Token::to_string(), tokenizer, and warn_doc_error.

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

◆ handleCite()

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

Definition at line 1070 of file docparser.cpp.

1071{
1072 AUTO_TRACE();
1073 // get the argument of the cite command.
1074 Token tok=tokenizer.lex();
1075
1076 CiteInfoOption option;
1077 if (tok.is(TokenRetval::TK_WORD) && context.token->name=="{")
1078 {
1079 tokenizer.setStateOptions();
1080 tokenizer.lex();
1081 StringVector optList=split(context.token->name.str(),",");
1082 for (auto const &opt : optList)
1083 {
1084 if (opt == "number")
1085 {
1086 if (!option.isUnknown())
1087 {
1088 warn(context.fileName,tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", context.token->name, opt);
1089 }
1090 else
1091 {
1092 option = CiteInfoOption::makeNumber();
1093 }
1094 }
1095 else if (opt == "year")
1096 {
1097 if (!option.isUnknown())
1098 {
1099 warn(context.fileName,tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", context.token->name, opt);
1100 }
1101 else
1102 {
1103 option = CiteInfoOption::makeYear();
1104 }
1105 }
1106 else if (opt == "shortauthor")
1107 {
1108 if (!option.isUnknown())
1109 {
1110 warn(context.fileName,tokenizer.getLineNr(),"Multiple options specified with \\{}, discarding '{}'", context.token->name, opt);
1111 }
1112 else
1113 {
1115 }
1116 }
1117 else if (opt == "nopar")
1118 {
1119 option.setNoPar();
1120 }
1121 else if (opt == "nocite")
1122 {
1123 option.setNoCite();
1124 }
1125 else
1126 {
1127 warn(context.fileName,tokenizer.getLineNr(),"Unknown option specified with \\{}, discarding '{}'", context.token->name, opt);
1128 }
1129 }
1130
1131 if (option.isUnknown()) option.changeToNumber();
1132
1133 tokenizer.setStatePara();
1134 tok=tokenizer.lex();
1135 if (!tok.is(TokenRetval::TK_WHITESPACE))
1136 {
1137 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
1138 context.token->name);
1139 return;
1140 }
1141 }
1142 else if (!tok.is(TokenRetval::TK_WHITESPACE))
1143 {
1144 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after '\\{}' command",
1145 context.token->name);
1146 return;
1147 }
1148 else
1149 {
1150 option = CiteInfoOption::makeNumber();
1151 }
1152
1154 tokenizer.setStateCite();
1155 tok=tokenizer.lex();
1156 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1157 {
1158 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
1159 "argument of command '\\{}'",context.token->name);
1160 return;
1161 }
1162 else if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1163 {
1164 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of '\\{}'",
1165 tok.to_string(),context.token->name);
1166 return;
1167 }
1168 context.token->sectionId = context.token->name;
1169 children.append<DocCite>(this,parent,context.token->name,context.context,option);
1170 }
1171
1172}
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
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)
split input string s by string delimiter delimiter.
Definition util.cpp:6636

References DocNodeList::append(), AUTO_TRACE, CiteInfoOption::changeToNumber(), context, Token::is(), Token::is_any_of(), CiteInfoOption::isUnknown(), CiteInfoOption::makeNumber(), CiteInfoOption::makeShortAuthor(), CiteInfoOption::makeYear(), parent(), CiteInfoOption::setNoCite(), CiteInfoOption::setNoPar(), split(), Token::to_string(), tokenizer, warn, and warn_doc_error.

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

◆ handleIFile()

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

Definition at line 1426 of file docparser.cpp.

1427{
1428 AUTO_TRACE();
1429 Token tok=tokenizer.lex();
1430 if (!tok.is(TokenRetval::TK_WHITESPACE))
1431 {
1432 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after '{:c}{}' command",
1433 cmdChar,cmdName);
1434 return;
1435 }
1436 tokenizer.setStateIFile();
1437 tok=tokenizer.lex();
1438 tokenizer.setStatePara();
1439 if (!tok.is(TokenRetval::TK_WORD))
1440 {
1441 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of '{:c}{}'",
1442 tok.to_string(),cmdChar,cmdName);
1443 return;
1444 }
1445 context.fileName = context.token->name;
1446}

References AUTO_TRACE, context, Token::is(), Token::to_string(), tokenizer, and warn_doc_error.

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

◆ handleILine()

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

Definition at line 1448 of file docparser.cpp.

1449{
1450 AUTO_TRACE();
1451 tokenizer.setStateILine();
1452 Token tok = tokenizer.lex();
1453 tokenizer.setStatePara();
1454 if (!tok.is(TokenRetval::TK_WORD))
1455 {
1456 warn_doc_error(context.fileName,tokenizer.getLineNr(),"invalid argument for command '{:c}{}'",
1457 cmdChar,cmdName);
1458 return;
1459 }
1460}

References AUTO_TRACE, context, Token::is(), tokenizer, and warn_doc_error.

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

◆ handleImage()

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

Definition at line 1294 of file docparser.cpp.

1295{
1296 AUTO_TRACE();
1297 bool inlineImage = false;
1298 QCString anchorStr;
1299
1300 Token tok=tokenizer.lex();
1301 if (!tok.is(TokenRetval::TK_WHITESPACE))
1302 {
1303 if (tok.is(TokenRetval::TK_WORD))
1304 {
1305 if (context.token->name == "{")
1306 {
1307 tokenizer.setStateOptions();
1308 tokenizer.lex();
1309 tokenizer.setStatePara();
1310 StringVector optList=split(context.token->name.str(),",");
1311 for (const auto &opt : optList)
1312 {
1313 if (opt.empty()) continue;
1314 QCString locOpt(opt);
1315 QCString locOptLow;
1316 locOpt = locOpt.stripWhiteSpace();
1317 locOptLow = locOpt.lower();
1318 if (locOptLow == "inline")
1319 {
1320 inlineImage = true;
1321 }
1322 else if (locOptLow.startsWith("anchor:"))
1323 {
1324 if (!anchorStr.isEmpty())
1325 {
1326 warn_doc_error(context.fileName,tokenizer.getLineNr(),
1327 "multiple use of option 'anchor' for 'image' command, ignoring: '{}'",
1328 locOpt.mid(7));
1329 }
1330 else
1331 {
1332 anchorStr = locOpt.mid(7);
1333 }
1334 }
1335 else
1336 {
1337 warn_doc_error(context.fileName,tokenizer.getLineNr(),
1338 "unknown option '{}' for 'image' command specified",
1339 locOpt);
1340 }
1341 }
1342 tok=tokenizer.lex();
1343 if (!tok.is(TokenRetval::TK_WHITESPACE))
1344 {
1345 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1346 return;
1347 }
1348 }
1349 }
1350 else
1351 {
1352 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1353 return;
1354 }
1355 }
1356 tok=tokenizer.lex();
1357 if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1358 {
1359 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of \\image",
1360 tok.to_string());
1361 return;
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 }
1370 QCString imgType = context.token->name.lower();
1371 if (imgType=="html") t=DocImage::Html;
1372 else if (imgType=="latex") t=DocImage::Latex;
1373 else if (imgType=="docbook") t=DocImage::DocBook;
1374 else if (imgType=="rtf") t=DocImage::Rtf;
1375 else if (imgType=="xml") t=DocImage::Xml;
1376 else
1377 {
1378 warn_doc_error(context.fileName,tokenizer.getLineNr(),"output format `{}` specified as the first argument of "
1379 "\\image command is not valid", imgType);
1380 return;
1381 }
1382 tokenizer.setStateFile();
1383 tok=tokenizer.lex();
1384 tokenizer.setStatePara();
1385 if (!tok.is(TokenRetval::TK_WORD))
1386 {
1387 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of \\image", tok.to_string());
1388 return;
1389 }
1390 if (!anchorStr.isEmpty())
1391 {
1392 children.append<DocAnchor>(this,parent,anchorStr,true);
1393 }
1394 HtmlAttribList attrList;
1395 children.append<DocImage>(this,parent,attrList,
1396 findAndCopyImage(context.token->name,t),t,"",inlineImage);
1397 children.get_last<DocImage>()->parse();
1398}
QCString findAndCopyImage(const QCString &fileName, DocImage::Type type, bool doWarn=true)
Definition docparser.cpp:96
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241

References DocNodeList::append(), AUTO_TRACE, context, DocImage::DocBook, findAndCopyImage(), DocNodeList::get_last(), DocImage::Html, Token::is(), Token::is_any_of(), QCString::isEmpty(), DocImage::Latex, QCString::lower(), QCString::mid(), parent(), DocImage::Rtf, split(), QCString::startsWith(), QCString::stripWhiteSpace(), Token::to_string(), 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 1847 of file docparser.cpp.

1848{
1849 AUTO_TRACE();
1850 bool found=FALSE;
1851 size_t index=0;
1852 for (const auto &opt : tagHtmlAttribs)
1853 {
1854 AUTO_TRACE_ADD("option name={} value='{}'",opt.name,opt.value);
1855 if (opt.name=="src" && !opt.value.isEmpty())
1856 {
1857 // copy attributes
1858 HtmlAttribList attrList = tagHtmlAttribs;
1859 // and remove the src attribute
1860 attrList.erase(attrList.begin()+index);
1862 children.append<DocImage>(
1863 this,parent,attrList,
1864 findAndCopyImage(opt.value,t,false),
1865 t,opt.value);
1866 found = TRUE;
1867 }
1868 ++index;
1869 }
1870 if (!found)
1871 {
1872 warn_doc_error(context.fileName,tokenizer.getLineNr(),"IMG tag does not have a SRC attribute!");
1873 }
1874}

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, context, FALSE, findAndCopyImage(), DocImage::Html, parent(), tokenizer, TRUE, and warn_doc_error.

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

◆ handleInitialStyleCommands()

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

Definition at line 767 of file docparser.cpp.

768{
769 AUTO_TRACE();
770 while (!context.initialStyleStack.empty())
771 {
772 const DocStyleChange &sc = std::get<DocStyleChange>(*context.initialStyleStack.top());
773 handleStyleEnter(parent,children,sc.style(),sc.tagName(),&sc.attribs());
774 context.initialStyleStack.pop();
775 }
776}
const HtmlAttribList & attribs() const
Definition docnode.h:311
QCString tagName() const
Definition docnode.h:312
Style style() const
Definition docnode.h:307

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

Referenced by DocPara::parse().

◆ handleInternalRef()

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

Definition at line 1018 of file docparser.cpp.

1019{
1020 Token tok=tokenizer.lex();
1021 QCString tokenName = context.token->name;
1022 AUTO_TRACE("name={}",tokenName);
1023 if (!tok.is(TokenRetval::TK_WHITESPACE))
1024 {
1025 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command", tokenName);
1026 return;
1027 }
1028 tokenizer.setStateInternalRef();
1029 tok=tokenizer.lex(); // get the reference id
1030 if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1031 {
1032 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
1033 tok.to_string(),tokenName);
1034 return;
1035 }
1036 children.append<DocInternalRef>(this,parent,context.token->name);
1037 children.get_last<DocInternalRef>()->parse();
1038}

References DocNodeList::append(), AUTO_TRACE, context, DocNodeList::get_last(), Token::is(), Token::is_any_of(), parent(), Token::to_string(), 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 847 of file docparser.cpp.

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

References Definition::anchor(), DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, Definition::briefDescriptionAsTooltip(), Config_getBool, Config_getList, context, Definition::definitionType(), FALSE, findFileDef(), getClass(), MemberDef::getClassDef(), Definition::getOutputFileBase(), Definition::getReference(), Definition::getSourceFileBase(), GroupDef::groupTitle(), handleLinkedWord(), Doxygen::inputNameLinkedMap, RequirementManager::instance(), MemberDef::isEnumerate(), MemberDef::isEnumValue(), Definition::isLinkable(), MemberDef::isObjCMethod(), MemberDef::isTypedef(), linkToText(), Definition::name(), MemberDef::objCMethodName(), parent(), resolveRef(), toFileDef(), toGroupDef(), tokenizer, TRUE, 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 QCString & paramTypes )

Definition at line 994 of file docparser.cpp.

995{
996 QCString name = context.token->name; // save token name
997 AUTO_TRACE("name={}",name);
998 QCString name1;
999 int p=0, i=0, ii=0;
1000 while ((i=paramTypes.find('|',p))!=-1)
1001 {
1002 name1 = paramTypes.mid(p,i-p);
1003 ii=name1.find('[');
1004 context.token->name=ii!=-1 ? name1.mid(0,ii) : name1; // take part without []
1005 handleLinkedWord(parent,children);
1006 if (ii!=-1) children.append<DocWord>(this,parent,name1.mid(ii)); // add [] part
1007 p=i+1;
1008 children.append<DocSeparator>(this,parent,"|");
1009 }
1010 name1 = paramTypes.mid(p);
1011 ii=name1.find('[');
1012 context.token->name=ii!=-1 ? name1.mid(0,ii) : name1;
1013 handleLinkedWord(parent,children);
1014 if (ii!=-1) children.append<DocWord>(this,parent,name1.mid(ii));
1015 context.token->name = name; // restore original token name
1016}

References DocNodeList::append(), AUTO_TRACE, context, QCString::find(), handleLinkedWord(), QCString::mid(), and parent().

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 747 of file docparser.cpp.

748{
749 AUTO_TRACE("context.styleStack.size()={} numberOfElementsToClose={}",context.styleStack.size(),numberOfElementsToClose);
750 if (!context.styleStack.empty())
751 {
752 if (numberOfElementsToClose==0) numberOfElementsToClose = context.styleStack.size(); // 0 is special value for "close all"
753 const DocStyleChange *sc = &std::get<DocStyleChange>(*context.styleStack.top());
754 while (sc && sc->position()>=context.nodeStack.size() && numberOfElementsToClose>0)
755 { // there are unclosed style modifiers in the paragraph
756 AUTO_TRACE_ADD("unclosed style {} at position {}",sc->styleString(),sc->position());
757 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),
758 sc->style(),sc->tagName(),FALSE);
759 context.initialStyleStack.push(context.styleStack.top());
760 context.styleStack.pop();
761 sc = !context.styleStack.empty() ? &std::get<DocStyleChange>(*context.styleStack.top()) : nullptr;
762 numberOfElementsToClose--;
763 }
764 }
765}
const char * styleString() const
Definition docnode.cpp:127
size_t position() const
Definition docnode.h:310

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, context, FALSE, parent(), DocStyleChange::position(), DocStyleChange::style(), 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 1174 of file docparser.cpp.

1175{
1176 AUTO_TRACE();
1177 Token tok=tokenizer.lex();
1178 if (!tok.is(TokenRetval::TK_WHITESPACE))
1179 {
1180 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command", context.token->name);
1181 return;
1182 }
1183 tokenizer.setStatePrefix();
1184 tok=tokenizer.lex();
1185 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1186 {
1187 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
1188 "argument of command {}",context.token->name);
1189 return;
1190 }
1191 else if (!tok.is(TokenRetval::TK_WORD))
1192 {
1193 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
1194 tok.to_string(),context.token->name);
1195 return;
1196 }
1197 context.prefix = context.token->name;
1198 tokenizer.setStatePara();
1199}

References AUTO_TRACE, context, Token::is(), Token::is_any_of(), parent(), Token::to_string(), tokenizer, and warn_doc_error.

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

◆ handleRef()

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

Definition at line 1400 of file docparser.cpp.

1401{
1402 AUTO_TRACE("cmdName={}",cmdName);
1403 QCString saveCmdName = cmdName;
1405 Token tok=tokenizer.lex();
1406 if (!tok.is(TokenRetval::TK_WHITESPACE))
1407 {
1408 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after '{:c}{}' command",
1409 cmdChar,qPrint(saveCmdName));
1410 return;
1411 }
1412 tokenizer.setStateRef();
1413 tok=tokenizer.lex(); // get the reference id
1414 if (!tok.is(TokenRetval::TK_WORD))
1415 {
1416 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of '{:c}{}'",
1417 tok.to_string(),cmdChar,saveCmdName);
1418 return;
1419 }
1420 children.append<DocRef>(this,parent,
1421 context.token->name,
1422 context.context);
1423 children.get_last<DocRef>()->parse(cmdChar,saveCmdName);
1424}

References DocNodeList::append(), AUTO_TRACE, context, DocNodeList::get_last(), Token::is(), parent(), qPrint(), Token::to_string(), tokenizer, and warn_doc_error.

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

◆ handleStyleArgument()

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

Definition at line 625 of file docparser.cpp.

626{
627 AUTO_TRACE("cmdName={}",cmdName);
628 QCString saveCmdName = cmdName;
629 Token tok=tokenizer.lex();
630 size_t styleStackSizeAtStart = context.styleStack.size();
631 if (!tok.is(TokenRetval::TK_WHITESPACE))
632 {
633 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
634 saveCmdName);
635 return tok;
636 }
637 tok = tokenizer.lex();
638 while (!tok.is_any_of(TokenRetval::TK_NONE, TokenRetval::TK_EOF, TokenRetval::TK_WHITESPACE,
639 TokenRetval::TK_NEWPARA, TokenRetval::TK_LISTITEM, TokenRetval::TK_ENDLIST)
640 )
641 {
642 static const reg::Ex specialChar(R"([.,|()\‍[\‍]:;?])");
643 if (tok.is(TokenRetval::TK_WORD) && context.token->name.length()==1 &&
644 reg::match(context.token->name.str(),specialChar))
645 {
646 // special character that ends the markup command
647 AUTO_TRACE_ADD("special character ending style argument: '{}' styleStackSize {}->{}",context.token->name,styleStackSizeAtStart,context.styleStack.size());
648 if (context.styleStack.size() > styleStackSizeAtStart) // new styles opened inside command, but not closed
649 {
650 handlePendingStyleCommands(parent,children,context.styleStack.size()-styleStackSizeAtStart);
651 }
652 return tok;
653 }
654 if (!defaultHandleToken(parent,tok,children))
655 {
656 switch (tok.value())
657 {
658 case TokenRetval::TK_HTMLTAG:
659 if (insideLI(parent) && Mappers::htmlTagMapper->map(context.token->name)!=HtmlTagType::UNKNOWN && context.token->endTag)
660 {
661 // ignore </li> as the end of a style command
662 }
663 else
664 {
665 AUTO_TRACE_EXIT("end tok={}",tok.to_string());
666 return tok;
667 }
668 break;
669 default:
670 errorHandleDefaultToken(parent,tok,children,"\\" + saveCmdName + " command");
671 break;
672 }
673 break;
674 }
675 tok = tokenizer.lex();
676 }
677 AUTO_TRACE_EXIT("end tok={}",tok.to_string());
678 return (tok.is_any_of(TokenRetval::TK_NEWPARA,TokenRetval::TK_LISTITEM,TokenRetval::TK_ENDLIST)) ? tok : Token::make_RetVal_OK();
679}
bool insideLI(const DocNodeVariant *n)

References AUTO_TRACE, AUTO_TRACE_ADD, AUTO_TRACE_EXIT, context, defaultHandleToken(), errorHandleDefaultToken(), handlePendingStyleCommands(), Mappers::htmlTagMapper, insideLI(), Token::is(), Token::is_any_of(), reg::match(), parent(), Token::to_string(), 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 QCString & tagName,
const HtmlAttribList * attribs )

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

Definition at line 684 of file docparser.cpp.

686{
687 AUTO_TRACE("tagName={}",tagName);
688 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),s,tagName,TRUE,
689 context.fileName,tokenizer.getLineNr(),attribs);
690 context.styleStack.push(&children.back());
692}
T & back()
access the last element
Definition growvector.h:135

References DocNodeList::append(), AUTO_TRACE, GrowVector< T >::back(), context, parent(), tokenizer, TRUE, and DocStyleChange::Typewriter.

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

◆ handleStyleLeave()

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

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

Definition at line 697 of file docparser.cpp.

699{
700 AUTO_TRACE("tagName={}",tagName);
701 QCString tagNameLower = QCString(tagName).lower();
702
703 auto topStyleChange = [](const DocStyleChangeStack &stack) -> const DocStyleChange &
704 {
705 return std::get<DocStyleChange>(*stack.top());
706 };
707
708 if (context.styleStack.empty() || // no style change
709 topStyleChange(context.styleStack).style()!=s || // wrong style change
710 topStyleChange(context.styleStack).tagName()!=tagNameLower || // wrong style change
711 topStyleChange(context.styleStack).position()!=context.nodeStack.size() // wrong position
712 )
713 {
714 if (context.styleStack.empty())
715 {
716 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{0}> tag without matching <{0}>",tagName);
717 }
718 else if (topStyleChange(context.styleStack).tagName()!=tagNameLower ||
719 topStyleChange(context.styleStack).style()!=s)
720 {
721 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{}> tag while expecting </{}>",
722 tagName,topStyleChange(context.styleStack).tagName());
723 }
724 else
725 {
726 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{}> at different nesting level ({}) than expected ({})",
727 tagName,context.nodeStack.size(),topStyleChange(context.styleStack).position());
728 }
729 }
730 else // end the section
731 {
732 children.append<DocStyleChange>(
733 this,parent,context.nodeStack.size(),s,
734 topStyleChange(context.styleStack).tagName(),FALSE);
735 context.styleStack.pop();
736 }
738 {
739 context.inCodeStyle = false;
740 }
741}
IterableStack< const DocNodeVariant * > DocStyleChangeStack
Definition docparser_p.h:55

References DocNodeList::append(), AUTO_TRACE, context, FALSE, QCString::lower(), parent(), tokenizer, DocStyleChange::Typewriter, and warn_doc_error.

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

◆ handleUnclosedStyleCommands()

void DocParser::handleUnclosedStyleCommands ( )

Definition at line 823 of file docparser.cpp.

824{
825 AUTO_TRACE("content.initialStyleStack.size()={}",context.initialStyleStack.size());
826 if (!context.initialStyleStack.empty())
827 {
828 QCString tagName = std::get<DocStyleChange>(*context.initialStyleStack.top()).tagName();
829 QCString fileName = std::get<DocStyleChange>(*context.initialStyleStack.top()).fileName();
830 int lineNr = std::get<DocStyleChange>(*context.initialStyleStack.top()).lineNr();
831 context.initialStyleStack.pop();
833 if (lineNr != -1)
834 {
835 warn_doc_error(context.fileName,tokenizer.getLineNr(),
836 "end of comment block while expecting "
837 "command </{}> (Probable start '{}' at line {})",tagName, fileName, lineNr);
838 }
839 else
840 {
841 warn_doc_error(context.fileName,tokenizer.getLineNr(),
842 "end of comment block while expecting command </{}>",tagName);
843 }
844 }
845}
void handleUnclosedStyleCommands()

References AUTO_TRACE, context, handleUnclosedStyleCommands(), tokenizer, and warn_doc_error.

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

◆ internalValidatingParseDoc()

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

Definition at line 1878 of file docparser.cpp.

1880{
1881 AUTO_TRACE();
1882 Token retval = Token::make_RetVal_OK();
1883
1884 if (doc.isEmpty()) return retval;
1885
1886 tokenizer.init(doc.data(),context.fileName,context.markdownSupport,context.insideHtmlLink);
1887
1888 // first parse any number of paragraphs
1889 bool isFirst=TRUE;
1890 DocPara *lastPar=!children.empty() ? std::get_if<DocPara>(&children.back()): nullptr;
1891 if (lastPar)
1892 { // last child item was a paragraph
1893 isFirst=FALSE;
1894 }
1895 do
1896 {
1897 children.append<DocPara>(this,parent);
1898 DocPara *par = children.get_last<DocPara>();
1899 if (isFirst) { par->markFirst(); isFirst=FALSE; }
1900 retval=par->parse();
1901 if (!par->isEmpty())
1902 {
1903 if (lastPar) lastPar->markLast(FALSE);
1904 lastPar=par;
1905 }
1906 else
1907 {
1908 children.pop_back();
1909 }
1910 } while (retval.is(TokenRetval::TK_NEWPARA));
1911 if (lastPar) lastPar->markLast();
1912
1913 AUTO_TRACE_EXIT("isFirst={} isLast={}",lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
1914 return retval;
1915}
bool isLast() const
Definition docnode.h:1097
void markLast(bool v=TRUE)
Definition docnode.h:1095
bool isFirst() const
Definition docnode.h:1096
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, QCString::data(), GrowVector< T >::empty(), FALSE, DocNodeList::get_last(), Token::is(), QCString::isEmpty(), DocPara::isFirst(), DocPara::isLast(), DocPara::markLast(), parent(), GrowVector< T >::pop_back(), tokenizer, and TRUE.

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

◆ popContext()

void DocParser::popContext ( )
private

Definition at line 75 of file docparser.cpp.

76{
77 auto &ctx = contextStack.top();
78 context = ctx;
79 tokenizer.setFileName(ctx.fileName);
80 tokenizer.setLineNr(ctx.lineNo);
81 contextStack.pop();
82 tokenizer.popContext();
83 context.token = tokenizer.token();
84
85 //QCString indent;
86 //indent.fill(' ',contextStack.size()*2+2);
87 //printf("%sdocParserPopContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
88}
std::stack< DocParserContext > contextStack

References context, contextStack, and tokenizer.

◆ processCopyDoc()

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

Definition at line 2074 of file docparser.cpp.

2075{
2076 AUTO_TRACE("data={} len={}",Trace::trunc(data),len);
2077 QCString result;
2078 result.reserve(len+32);
2079 size_t i=0;
2080 int lineNr = tokenizer.getLineNr();
2081 while (i<len)
2082 {
2083 char c = data[i];
2084 if (c=='@' || c=='\\') // look for a command
2085 {
2086 bool isBrief=TRUE;
2087 size_t j=isCopyBriefOrDetailsCmd(data,i,len,isBrief);
2088 if (j>0)
2089 {
2090 // skip whitespace
2091 while (j<len && (data[j]==' ' || data[j]=='\t')) j++;
2092 // extract the argument
2093 QCString id = extractCopyDocId(data,j,len);
2094 const Definition *def = nullptr;
2095 QCString doc,brief;
2096 //printf("resolving docs='%s'\n",qPrint(id));
2097 bool found = findDocsForMemberOrCompound(id,&doc,&brief,&def);
2098 if (found && def->isReference())
2099 {
2100 warn_doc_error(context.fileName,tokenizer.getLineNr(),
2101 "@copy{} or @copydoc target '{}' found but is from a tag file, skipped",
2102 isBrief?"brief":"details", id);
2103 }
2104 else if (found)
2105 {
2106 //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,qPrint(brief),qPrint(doc),isBrief);
2107 auto it = std::find(context.copyStack.begin(),context.copyStack.end(),def);
2108 if (it==context.copyStack.end()) // definition not parsed earlier
2109 {
2110 QCString orgFileName = context.fileName;
2111 context.copyStack.push_back(def);
2112 auto addDocs = [&](const QCString &file_,int line_,const QCString &doc_)
2113 {
2114 result+=" \\ifile \""+file_+"\" ";
2115 result+="\\iline "+QCString().setNum(line_)+" \\ilinebr ";
2116 size_t len_ = doc_.length();
2117 result+=processCopyDoc(doc_.data(),len_);
2118 };
2119 if (isBrief)
2120 {
2121 addDocs(def->briefFile(),def->briefLine(),brief);
2122 }
2123 else
2124 {
2125 addDocs(def->docFile(),def->docLine(),doc);
2127 {
2128 const MemberDef *md = toMemberDef(def);
2129 const ArgumentList &docArgList = md->templateMaster() ?
2130 md->templateMaster()->argumentList() :
2131 md->argumentList();
2132 result+=inlineArgListToDoc(docArgList);
2133 }
2134 }
2135 context.copyStack.pop_back();
2136 result+=" \\ilinebr \\ifile \""+context.fileName+"\" ";
2137 result+="\\iline "+QCString().setNum(lineNr)+" ";
2138 }
2139 else
2140 {
2141 warn_doc_error(context.fileName,tokenizer.getLineNr(),
2142 "Found recursive @copy{} or @copydoc relation for argument '{}'.",
2143 isBrief?"brief":"details",id);
2144 }
2145 }
2146 else
2147 {
2148 warn_doc_error(context.fileName,tokenizer.getLineNr(),
2149 "@copy{} or @copydoc target '{}' not found", isBrief?"brief":"details",id);
2150 }
2151 // skip over command
2152 i=j;
2153 }
2154 else
2155 {
2156 QCString endMarker;
2157 size_t k = isVerbatimSection(data,i,len,endMarker);
2158 if (k>0)
2159 {
2160 size_t orgPos = i;
2161 i=skipToEndMarker(data,k,len,endMarker);
2162 result+=QCString(data+orgPos,i-orgPos);
2163 // TODO: adjust lineNr
2164 }
2165 else
2166 {
2167 result+=c;
2168 i++;
2169 }
2170 }
2171 }
2172 else // not a command, just copy
2173 {
2174 result+=c;
2175 i++;
2176 lineNr += (c=='\n') ? 1 : 0;
2177 }
2178 }
2179 len = result.length();
2180 AUTO_TRACE_EXIT("result={}",Trace::trunc(result));
2181 return result;
2182}
virtual int briefLine() const =0
virtual QCString briefFile() const =0
virtual bool isReference() const =0
QCString processCopyDoc(const char *data, size_t &len)
bool findDocsForMemberOrCompound(const QCString &commandName, QCString *pDoc, QCString *pBrief, const Definition **pDef)
virtual const ArgumentList & argumentList() const =0
virtual const MemberDef * templateMaster() const =0
QCString & setNum(short n)
Definition qcstring.h:459
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
static QCString extractCopyDocId(const char *data, size_t &j, size_t len)
static size_t skipToEndMarker(const char *data, size_t i, size_t len, const QCString &endMarker)
static size_t isVerbatimSection(const char *data, size_t i, size_t len, QCString &endMarker)
static size_t isCopyBriefOrDetailsCmd(const char *data, size_t i, size_t len, bool &brief)
MemberDef * toMemberDef(Definition *d)
QCString trunc(const QCString &s, size_t numChars=15)
Definition trace.h:56
QCString inlineArgListToDoc(const ArgumentList &al)
Definition util.cpp:1204

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

Referenced by processCopyDoc(), and validatingParseDoc().

◆ pushContext()

void DocParser::pushContext ( )
private

Definition at line 60 of file docparser.cpp.

61{
62 //QCString indent;
63 //indent.fill(' ',contextStack.size()*2+2);
64 //printf("%sdocParserPushContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
65
66 tokenizer.pushContext();
67 contextStack.emplace();
68 auto &ctx = contextStack.top();
69 ctx = context;
70 ctx.fileName = tokenizer.getFileName();
71 ctx.lineNo = tokenizer.getLineNr();
72 context.token = tokenizer.token();
73}

References context, contextStack, and tokenizer.

◆ readTextFileByName()

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

Definition at line 1919 of file docparser.cpp.

1920{
1921 AUTO_TRACE("file={} text={}",file,text);
1922 bool ambig = false;
1923 QCString filePath = findFilePath(file,ambig);
1924 if (!filePath.isEmpty())
1925 {
1926 size_t indent = 0;
1927 text = detab(fileToString(filePath,Config_getBool(FILTER_SOURCE_FILES)),indent);
1928 if (ambig)
1929 {
1930 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file name '{}' is ambiguous"
1931 "Possible candidates:\n{}",file, showFileDefMatches(Doxygen::exampleNameLinkedMap,file));
1932 }
1933 }
1934 else
1935 {
1936 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file '{}' is not found. "
1937 "Check your EXAMPLE_PATH",file);
1938 }
1939}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:102
QCString findFilePath(const QCString &file, bool &ambig)
Definition util.cpp:2996
QCString fileToString(const QCString &name, bool filter, bool isSourceCode)
Definition util.cpp:1494
QCString detab(const QCString &s, size_t &refIndent)
Definition util.cpp:6738

References AUTO_TRACE, Config_getBool, context, detab(), Doxygen::exampleNameLinkedMap, fileToString(), findFilePath(), QCString::isEmpty(), showFileDefMatches(), tokenizer, and warn_doc_error.

Referenced by DocInclude::parse().

Member Data Documentation

◆ context

DocParserContext DocParser::context

Definition at line 153 of file docparser_p.h.

Referenced by DocSimpleSect::appendLinkWord(), checkArgumentName(), checkIfHtmlEndTagEndsAutoList(), checkRetvalName(), checkUnOrMultipleDocumentedParams(), createRef(), defaultHandleTitleAndSize(), defaultHandleToken(), 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(), 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(), and validatingParseTitle().

◆ contextStack

std::stack< DocParserContext > DocParser::contextStack

Definition at line 152 of file docparser_p.h.

Referenced by popContext(), and pushContext().

◆ tokenizer

DocTokenizer DocParser::tokenizer

Definition at line 154 of file docparser_p.h.

Referenced by checkIfHtmlEndTagEndsAutoList(), createRef(), defaultHandleTitleAndSize(), defaultHandleToken(), docFindSections(), 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: