Doxygen
Loading...
Searching...
No Matches
definition.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2023 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include <algorithm>
17#include <iterator>
18#include <mutex>
19#include <unordered_map>
20#include <string>
21#include <optional>
22#include <cctype>
23#include <cstdio>
24#include <cstdlib>
25#include <cassert>
26
27#include "anchor.h"
28#include "md5.h"
29#include "regex.h"
30#include "config.h"
31#include "definitionimpl.h"
32#include "doxygen.h"
33#include "language.h"
34#include "message.h"
35#include "portable.h"
36#include "outputlist.h"
37#include "code.h"
38#include "util.h"
39#include "groupdef.h"
40#include "pagedef.h"
41#include "section.h"
42#include "htags.h"
43#include "parserintf.h"
44#include "debug.h"
45#include "vhdldocgen.h"
46#include "memberlist.h"
47#include "namespacedef.h"
48#include "filedef.h"
49#include "dirdef.h"
50#include "reflist.h"
51#include "utf8.h"
52#include "indexlist.h"
53#include "fileinfo.h"
54
55//-----------------------------------------------------------------------------------------
56
57/** once_flag wrapper that is copyable (copy default-initializes the flag) and resettable. */
59{
60 mutable std::once_flag flag;
61 ResettableOnce() = default;
62 ResettableOnce(const ResettableOnce &) {} // copy: leave flag in not-yet-called state
63 ResettableOnce &operator=(const ResettableOnce &) { return *this; }
64 void reset() { flag.~once_flag(); new (&flag) std::once_flag{}; }
65};
66
67/** Private data associated with a Symbol DefinitionImpl object. */
69{
70 public:
71 void init(const QCString &df, const QCString &n);
72 void setDefFileName(const QCString &df);
73
74 Definition *def = nullptr;
75
77
78 std::unordered_map<std::string,MemberDef *> sourceRefByDict;
79 std::unordered_map<std::string,MemberDef *> sourceRefsDict;
83
84 std::optional<DocInfo> details; // not exported
85 std::optional<DocInfo> inbodyDocs; // not exported
86 std::optional<BriefInfo> brief; // not exported
87 std::optional<BodyInfo> body; // not exported
88
91
92 QCString localName; // local (unqualified) name of the definition
93 // in the future m_name should become m_localName
96 QCString ref; // reference to external documentation
97
98 bool hidden = FALSE;
102
103 Definition *outerScope = nullptr; // not owner
104
105 // where the item was defined
108
109 SrcLangExt lang = SrcLangExt::Unknown;
110
111 QCString id; // clang unique id
112
118
119 MemberVector referencesMembers; // cache for getReferencesMembers()
120 MemberVector referencedByMembers; // cache for getReferencedByMembers()
121};
122
123
125{
126 defFileName = df;
127 FileInfo fi(df.data());
128 QCString ext = fi.extension(false);
129 if (!ext.isEmpty()) defFileExt = "." + ext;
130}
131
133{
134 setDefFileName(df);
135 if (n!="<globalScope>")
136 {
137 //extractNamespaceName(m_name,m_localName,ns);
139 }
140 else
141 {
142 localName=n;
143 }
144 //printf("localName=%s\n",qPrint(localName));
145
146 brief.reset();
147 details.reset();
148 body.reset();
149 inbodyDocs.reset();
150 sourceRefByDict.clear();
151 sourceRefsDict.clear();
152 requirementRefs.clear();
154 hidden = FALSE;
157 lang = SrcLangExt::Unknown;
158}
159
160void DefinitionImpl::setDefFile(const QCString &df,int defLine,int defCol)
161{
162 p->setDefFileName(df);
163 p->defLine = defLine;
164 p->defColumn = defCol;
165}
166
167//-----------------------------------------------------------------------------------------
168
170{
171 const StringVector &exclSyms = Config_getList(EXCLUDE_SYMBOLS);
172 if (exclSyms.empty()) return FALSE; // nothing specified
173 const std::string &symName = name.str();
174 for (const auto &pat : exclSyms)
175 {
176 QCString pattern = pat;
177 bool forceStart=FALSE;
178 bool forceEnd=FALSE;
179 if (pattern.at(0)=='^')
180 {
181 pattern = pattern.mid(1);
182 forceStart = true;
183 }
184 if (pattern.at(pattern.length() - 1) == '$')
185 {
186 pattern = pattern.left(pattern.length() - 1);
187 forceEnd = true;
188 }
189 if (pattern.find('*')!=-1) // wildcard mode
190 {
191 const reg::Ex re(substitute(pattern,"*",".*").str());
192 reg::Match match;
193 if (reg::search(symName,match,re)) // wildcard match
194 {
195 size_t ui = match.position();
196 size_t pl = match.length();
197 size_t sl = symName.length();
198 if ((ui==0 || pattern.at(0)=='*' || (!isId(symName.at(ui-1)) && !forceStart)) &&
199 (ui+pl==sl || pattern.at(pattern.length()-1)=='*' || (!isId(symName.at(ui+pl)) && !forceEnd))
200 )
201 {
202 //printf("--> name=%s pattern=%s match at %d\n",qPrint(symName),qPrint(pattern),i);
203 return TRUE;
204 }
205 }
206 }
207 else if (!pattern.isEmpty()) // match words
208 {
209 size_t i = symName.find(pattern.str());
210 if (i!=std::string::npos) // we have a match!
211 {
212 size_t ui=i;
213 size_t pl=pattern.length();
214 size_t sl=symName.length();
215 // check if it is a whole word match
216 if ((ui==0 || (!isId(symName.at(ui-1)) && !forceStart)) &&
217 (ui+pl==sl || (!isId(symName.at(ui+pl)) && !forceEnd))
218 )
219 {
220 //printf("--> name=%s pattern=%s match at %d\n",qPrint(symName),qPrint(pattern),i);
221 return TRUE;
222 }
223 }
224 }
225 }
226 //printf("--> name=%s: no match\n",name);
227 return FALSE;
228}
229
230static void addToMap(const QCString &name,Definition *d)
231{
232 bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
235 if (!vhdlOpt && index!=-1) symbolName=symbolName.mid(index+2);
236 if (!symbolName.isEmpty())
237 {
238 //printf("adding symbol %s\n",qPrint(symbolName));
240
242 }
243}
244
245static void removeFromMap(const QCString &name,Definition *d)
246{
247 Doxygen::symbolMap->remove(name,d);
248}
249
251 const QCString &df,int dl,int dc,
252 const QCString &name,const char *b,
253 const char *d,bool isSymbol)
254 : p(std::make_unique<Private>())
255{
256 setName(name);
257 p->def = def;
258 p->defLine = dl;
259 p->defColumn = dc;
260 p->init(df,name);
261 p->isSymbol = isSymbol;
262 if (isSymbol) addToMap(name,def);
263 _setBriefDescription(b,df,dl);
266 {
267 p->hidden = TRUE;
268 }
269}
270
272 : p(std::make_unique<Private>(*d.p))
273{
274 if (p->isSymbol) addToMap(p->name,p->def);
275}
276
278{
279 if (this!=&other)
280 {
281 p = std::make_unique<Private>(*other.p);
282 }
283 return *this;
284}
285
287{
288 if (p->isSymbol)
289 {
290 removeFromMap(p->symbolName,p->def);
291 }
292}
293
295{
296 if (name.isEmpty()) return;
297 p->name = name;
298 p->isAnonymous = p->name.isEmpty() ||
299 p->name.at(0)=='@' ||
300 p->name.find("::@")!=-1;
301}
302
304{
305 if (id.isEmpty()) return;
306 p->id = id;
308 {
309 //printf("DefinitionImpl::setId '%s'->'%s'\n",id,qPrint(p->name));
310 Doxygen::clangUsrMap->emplace(id.str(),p->def);
311 }
312}
313
315{
316 return p->id;
317}
318
319void DefinitionImpl::addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList)
320{
321 //printf("%s: addSectionsToDefinition(%d)\n",qPrint(name()),anchorList->count());
322 for (const SectionInfo *si : anchorList)
323 {
324 //printf("Add section '%s' to definition '%s'\n",
325 // qPrint(si->label()),qPrint(name()));
327 SectionInfo *gsi=sm.find(si->label());
328 //printf("===== label=%s gsi=%p\n",qPrint(si->label()),(void*)gsi);
329 if (gsi==nullptr)
330 {
331 gsi = sm.add(*si);
332 }
333 if (p->sectionRefs.find(gsi->label())==nullptr)
334 {
335 p->sectionRefs.add(gsi);
336 }
337 gsi->setDefinition(p->def);
338 }
339}
340
342{
343 //printf("DefinitionImpl::hasSections(%s) #sections=%zu\n",qPrint(name()), p->sectionRefs.size());
344 if (p->sectionRefs.empty()) return FALSE;
345 for (const SectionInfo *si : p->sectionRefs)
346 {
347 if (si->type().isSection())
348 {
349 return TRUE;
350 }
351 }
352 return FALSE;
353}
354
356{
357 if (!p->sectionRefs.empty())
358 {
359 //printf("%s: writeDocAnchorsToTagFile(%d)\n",qPrint(name()),p->sectionRef.size());
360 for (const SectionInfo *si : p->sectionRefs)
361 {
362 if (!si->generated() && si->ref().isEmpty() && !AnchorGenerator::instance().isGenerated(si->label().str()))
363 {
364 //printf("write an entry!\n");
365 if (p->def->definitionType()==Definition::TypeMember) tagFile << " ";
366 QCString fn = si->fileName();
368 tagFile << " <docanchor file=\"" << fn << "\"";
369 if (!si->title().isEmpty())
370 {
371 tagFile << " title=\"" << convertToXML(si->title()) << "\"";
372 }
373 tagFile << ">" << si->label() << "</docanchor>\n";
374 }
375 }
376 }
377}
378
380{
381 uint8_t md5_sig[16];
382 char sigStr[33];
383 // to avoid mismatches due to differences in indenting, we first remove
384 // double whitespaces...
385 QCString docStr = doc.simplifyWhiteSpace();
386 MD5Buffer(docStr.data(),static_cast<unsigned int>(docStr.length()),md5_sig);
387 MD5SigToString(md5_sig,sigStr);
388 //printf("%s:_docsAlreadyAdded doc='%s' sig='%s' docSigs='%s'\n",
389 // qPrint(name()),qPrint(doc),qPrint(sigStr),qPrint(sigList));
390 if (sigList.find(sigStr)==-1) // new docs, add signature to prevent re-adding it
391 {
392 sigList+=QCString(":")+sigStr;
393 return FALSE;
394 }
395 else
396 {
397 return TRUE;
398 }
399}
400
402 bool stripWhiteSpace,bool atTop)
403{
404 //printf("%s::setDocumentation(%s,%s,%d,%d)\n",qPrint(name()),d,docFile,docLine,stripWhiteSpace);
405 if (d.isEmpty()) return;
406 QCString doc = d;
407 if (stripWhiteSpace)
408 {
410 }
411 else // don't strip whitespace
412 {
413 doc=d;
414 }
415 if (!_docsAlreadyAdded(doc,p->docSignatures))
416 {
417 //printf("setting docs for %s: '%s'\n",qPrint(name()),qPrint(m_doc));
418 if (!p->details.has_value())
419 {
420 p->details = std::make_optional<DocInfo>();
421 }
422 DocInfo &details = p->details.value();
423 if (details.doc.isEmpty()) // fresh detailed description
424 {
425 details.doc = doc;
426 }
427 else if (atTop) // another detailed description, append it to the start
428 {
429 details.doc = doc+"\n\n"+details.doc;
430 }
431 else // another detailed description, append it to the end
432 {
433 details.doc += "\n\n"+doc;
434 }
435 if (docLine!=-1) // store location if valid
436 {
437 details.file = docFile;
438 details.line = docLine;
439 }
440 else
441 {
442 details.file = docFile;
443 details.line = 1;
444 }
445 }
446}
447
453
455{
456 QCString brief = b;
457 brief = brief.stripWhiteSpace();
459 brief = brief.stripWhiteSpace();
460 if (brief.isEmpty()) return;
461 size_t bl = brief.length();
462 if (bl>0)
463 {
464 if (!theTranslator || theTranslator->needsPunctuation()) // add punctuation if needed
465 {
466 int c = brief.at(bl-1);
467 switch(c)
468 {
469 case '.': case '!': case '?': case ':': break;
470 default:
471 if (isUTF8CharUpperCase(brief.str(),0) && !lastUTF8CharIsMultibyte(brief.str())) brief+='.';
472 break;
473 }
474 }
475 }
476
477 if (!_docsAlreadyAdded(brief,p->briefSignatures))
478 {
479 if (p->brief && !p->brief->doc.isEmpty())
480 {
481 //printf("adding to details\n");
483 }
484 else
485 {
486 //fprintf(stderr,"DefinitionImpl::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine);
487 if (!p->brief.has_value())
488 {
489 p->brief = std::make_optional<BriefInfo>();
490 }
491 BriefInfo &briefInfo = p->brief.value();
492 briefInfo.doc=brief;
493 if (briefLine!=-1)
494 {
495 briefInfo.file = briefFile;
496 briefInfo.line = briefLine;
497 }
498 else
499 {
500 briefInfo.file = briefFile;
501 briefInfo.line = 1;
502 }
503 }
504 }
505 else
506 {
507 //printf("do nothing!\n");
508 }
509}
510
516
518{
519 if (!_docsAlreadyAdded(doc,p->docSignatures))
520 {
521 if (!p->inbodyDocs.has_value())
522 {
523 p->inbodyDocs = std::make_optional<DocInfo>();
524 }
525 DocInfo &inbodyDocs = p->inbodyDocs.value();
526 if (inbodyDocs.doc.isEmpty()) // fresh inbody docs
527 {
528 inbodyDocs.doc = doc;
529 inbodyDocs.file = inbodyFile;
530 inbodyDocs.line = inbodyLine;
531 }
532 else // another inbody documentation fragment, append this to the end
533 {
534 inbodyDocs.doc += QCString("\n\n")+doc;
535 }
536 }
537}
538
544
545//---------------------------------------
546
547/*! Cache for storing the result of filtering a file */
549{
550 private:
552 {
553 size_t filePos;
554 size_t fileSize;
555 };
556 using LineOffsets = std::vector<size_t>;
557
558 public:
559 static FilterCache &instance();
560
561 //! collects the part of file \a fileName starting at \a startLine and ending at \a endLine into
562 //! buffer \a str. Applies filtering if FILTER_SOURCE_FILES is enabled and the file extension
563 //! matches a filter. Caches file information so that subsequent extraction of blocks from
564 //! the same file can be performed efficiently
565 bool getFileContents(const QCString &fileName,size_t startLine,size_t endLine, std::string &str)
566 {
567 bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
568 QCString filter = getFileFilter(fileName,TRUE);
569 bool usePipe = !filter.isEmpty() && filterSourceFiles;
570 return usePipe ? getFileContentsPipe(fileName,filter,startLine,endLine,str)
571 : getFileContentsDisk(fileName,startLine,endLine,str);
572 }
573 private:
574 bool getFileContentsPipe(const QCString &fileName,const QCString &filter,
575 size_t startLine,size_t endLine,std::string &str)
576 {
577 std::unique_lock<std::mutex> lock(m_mutex);
578 auto it = m_cache.find(fileName.str());
579 if (it!=m_cache.end()) // cache hit: reuse stored result
580 {
581 lock.unlock();
582 auto item = it->second;
583 //printf("getFileContents(%s): cache hit\n",qPrint(fileName));
584 // file already processed, get the results after filtering from the tmp file
585 Debug::print(Debug::FilterOutput,0,"Reusing filter result for {} from {} at offset={} size={}\n",
586 fileName,Doxygen::filterDBFileName,item.filePos,item.fileSize);
587
588 auto it_off = m_lineOffsets.find(fileName.str());
589 assert(it_off!=m_lineOffsets.end());
590 auto [ startLineOffset, fragmentSize] = getFragmentLocation(it_off->second,startLine,endLine);
591 //printf("%s: existing file [%zu-%zu]->[%zu-%zu] size=%zu\n",
592 // qPrint(fileName),startLine,endLine,startLineOffset,endLineOffset,fragmentSize);
594 item.filePos+startLineOffset, fragmentSize);
595 return true;
596 }
597 else // cache miss: filter active but file not previously processed
598 {
599 //printf("getFileContents(%s): cache miss\n",qPrint(fileName));
600 // filter file
601 QCString cmd=filter+" \""+fileName+"\"";
602 Debug::print(Debug::ExtCmd,0,"Executing popen(`{}`)\n",cmd);
603 FILE *f = Portable::popen(cmd,"r");
604 if (f==nullptr)
605 {
606 // handle error
607 err("Error opening filter pipe command '{}'\n",cmd);
608 return false;
609 }
611 FilterCacheItem item;
612 item.filePos = m_endPos;
613 if (bf==nullptr)
614 {
615 // handle error
616 err("Error opening filter database file {}\n",Doxygen::filterDBFileName);
618 return false;
619 }
620 // append the filtered output to the database file
621 size_t size=0;
622 while (!feof(f))
623 {
624 const int blockSize = 4096;
625 char buf[blockSize];
626 size_t bytesRead = fread(buf,1,blockSize,f);
627 size_t bytesWritten = fwrite(buf,1,bytesRead,bf);
628 if (bytesRead!=bytesWritten)
629 {
630 // handle error
631 err("Failed to write to filter database {}. Wrote {} out of {} bytes\n",
632 Doxygen::filterDBFileName,bytesWritten,bytesRead);
634 fclose(bf);
635 return false;
636 }
637 size+=bytesWritten;
638 str+=std::string_view(buf,bytesWritten);
639 }
640 item.fileSize = size;
641 // add location entry to the dictionary
642 m_cache.emplace(fileName.str(),item);
643 Debug::print(Debug::FilterOutput,0,"Storing new filter result for {} in {} at offset={} size={}\n",
644 fileName,Doxygen::filterDBFileName,item.filePos,item.fileSize);
645 // update end of file position
646 m_endPos += size;
648 fclose(bf);
649
650 // shrink buffer to [startLine..endLine] part
651 shrinkBuffer(str,fileName,startLine,endLine);
652 }
653 return true;
654 }
655
656 //! reads the fragment start at \a startLine and ending at \a endLine from file \a fileName
657 //! into buffer \a str
658 bool getFileContentsDisk(const QCString &fileName,size_t startLine,size_t endLine,std::string &str)
659 {
660 std::unique_lock<std::mutex> lock(m_mutex);
661 // normal file
662 //printf("getFileContents(%s): no filter\n",qPrint(fileName));
663 auto it = m_lineOffsets.find(fileName.str());
664 if (it == m_lineOffsets.end()) // new file
665 {
666 // read file completely into str buffer
667 readFragmentFromFile(str,fileName,0);
668 // shrink buffer to [startLine..endLine] part
669 shrinkBuffer(str,fileName,startLine,endLine);
670 }
671 else // file already processed before
672 {
673 lock.unlock();
674 auto [ startLineOffset, fragmentSize] = getFragmentLocation(it->second,startLine,endLine);
675 //printf("%s: existing file [%zu-%zu] -> start=%zu size=%zu\n",
676 // qPrint(fileName),startLine,endLine,startLineOffset,fragmentSize);
677 readFragmentFromFile(str,fileName,startLineOffset,fragmentSize);
678 }
679 return true;
680 }
681
682 //! computes the starting offset for each line for file \a fileName, whose contents should
683 //! already be stored in buffer \a str.
684 void compileLineOffsets(const QCString &fileName,const std::string &str)
685 {
686 // line 1 (index 0) is at offset 0
687 auto it = m_lineOffsets.emplace(fileName.data(),LineOffsets{0}).first;
688 const char *p=str.data();
689 while (*p)
690 {
691 char c=0;
692 while ((c=*p)!='\n' && c!=0) p++; // search until end of the line
693 if (c!=0) p++;
694 it->second.push_back(p-str.data());
695 }
696 }
697
698 //! Returns the byte offset and size within a file of a fragment given the array of
699 //! line offsets and the start and end line of the fragment.
700 auto getFragmentLocation(const LineOffsets &lineOffsets,
701 size_t startLine,size_t endLine) -> std::tuple<size_t,size_t>
702 {
703 assert(startLine > 0);
704 assert(startLine <= endLine);
705 const size_t startLineOffset = lineOffsets[std::min(startLine-1,lineOffsets.size()-1)];
706 const size_t endLineOffset = lineOffsets[std::min(endLine, lineOffsets.size()-1)];
707 assert(startLineOffset <= endLineOffset);
708 const size_t fragmentSize = endLineOffset-startLineOffset;
709 return std::tie(startLineOffset,fragmentSize);
710 }
711
712 //! Shrinks buffer \a str which should hold the contents of \a fileName to the
713 //! fragment starting a line \a startLine and ending at line \a endLine
714 void shrinkBuffer(std::string &str,const QCString &fileName,size_t startLine,size_t endLine)
715 {
716 // compute offsets from start for each line
717 compileLineOffsets(fileName,str);
718 auto it = m_lineOffsets.find(fileName.str());
719 assert(it!=m_lineOffsets.end());
720 const LineOffsets &lineOffsets = it->second;
721 auto [ startLineOffset, fragmentSize] = getFragmentLocation(lineOffsets,startLine,endLine);
722 //printf("%s: new file [%zu-%zu]->[%zu-%zu] size=%zu\n",
723 // qPrint(fileName),startLine,endLine,startLineOffset,endLineOffset,fragmentSize);
724 str.erase(0,startLineOffset);
725 str.resize(fragmentSize);
726 }
727
728 //! Reads the fragment start at byte offset \a startOffset of file \a fileName into buffer \a str.
729 //! Result will be a null terminated. If size==0 the whole file will be read and startOffset is ignored.
730 //! If size>0, size bytes will be read.
731 void readFragmentFromFile(std::string &str,const QCString &fileName,size_t startOffset,size_t size=0)
732 {
733 std::ifstream ifs = Portable::openInputStream(fileName,true,true);
734 if (size==0) { startOffset=0; size = static_cast<size_t>(ifs.tellg()); }
735 ifs.seekg(startOffset, std::ios::beg);
736 str.resize(size);
737 ifs.read(str.data(), size);
738 }
739
741 std::unordered_map<std::string,FilterCacheItem> m_cache;
742 std::unordered_map<std::string,LineOffsets> m_lineOffsets;
743 std::mutex m_mutex;
744 size_t m_endPos;
745};
746
748{
749 static FilterCache theInstance;
750 return theInstance;
751}
752
753//-----------------------------------------
754
755
756/*! Reads a fragment of code from file \a fileName starting at
757 * line \a startLine and ending at line \a endLine (inclusive). The fragment is
758 * stored in \a result. If FALSE is returned the code fragment could not be
759 * found.
760 *
761 * The file is scanned for a opening bracket ('{') from \a startLine onward
762 * The line actually containing the bracket is returned via startLine.
763 * The file is scanned for a closing bracket ('}') from \a endLine backward.
764 * The line actually containing the bracket is returned via endLine.
765 * Note that for VHDL code the bracket search is not done.
766 */
767bool readCodeFragment(const QCString &fileName,bool isMacro,
768 int &startLine,int &endLine,QCString &result)
769{
770 bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
771 QCString filter = getFileFilter(fileName,TRUE);
772 bool usePipe = !filter.isEmpty() && filterSourceFiles;
773 int tabSize = Config_getInt(TAB_SIZE);
774 SrcLangExt lang = getLanguageFromFileName(fileName);
775 const int blockSize = 4096;
776 std::string str;
778 static_cast<size_t>(std::max(1,startLine)),
779 static_cast<size_t>(std::max({1,startLine,endLine})),str);
780 //printf("readCodeFragment(%s,startLine=%d,endLine=%d)=\n[[[\n%s]]]\n",qPrint(fileName),startLine,endLine,qPrint(str));
781
782 bool found = lang==SrcLangExt::VHDL ||
783 lang==SrcLangExt::Python ||
784 lang==SrcLangExt::Fortran ||
785 isMacro;
786 // for VHDL, Python, and Fortran no bracket search is possible
787 char *p=str.data();
788 if (p && *p)
789 {
790 char c=0;
791 int col=0;
792 int lineNr=startLine;
793 // skip until the opening bracket or lonely : is found
794 char cn=0;
795 while (*p && !found)
796 {
797 int pc=0;
798 while ((c=*p++)!='{' && c!=':' && c!='=' && c!=0)
799 {
800 //printf("parsing char '%c'\n",c);
801 if (c=='\n')
802 {
803 lineNr++;
804 col = 0;
805 }
806 else if (c=='\t')
807 {
808 col+=tabSize - (col%tabSize);
809 }
810 else if (pc=='/' && c=='/') // skip single line comment
811 {
812 while ((c=*p++)!='\n' && c!=0);
813 if (c == '\n')
814 {
815 lineNr++;
816 col = 0;
817 }
818 }
819 else if (pc=='/' && c=='*') // skip C style comment
820 {
821 while (((c=*p++)!='/' || pc!='*') && c!=0)
822 {
823 if (c == '\n')
824 {
825 lineNr++;
826 col = 0;
827 }
828 pc=c;
829 }
830 }
831 else
832 {
833 col++;
834 }
835 pc = c;
836 }
837 if (c==':')
838 {
839 cn=*p++;
840 if (cn!=':') found=TRUE;
841 }
842 else if (c=='=')
843 {
844 cn=*p++;
845 if (cn=='>') // C# Expression body
846 {
847 found=TRUE;
848 }
849 }
850 else if (c=='{')
851 {
852 found=TRUE;
853 }
854 else if (c==0)
855 {
856 break;
857 }
858 }
859 //printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr);
860 if (found)
861 {
862 // For code with more than one line,
863 // fill the line with spaces until we are at the right column
864 // so that the opening brace lines up with the closing brace
865 if (endLine!=startLine)
866 {
867 QCString spaces;
868 spaces.fill(' ',col);
869 result+=spaces;
870 }
871 // copy until end of line
872 if (c) result+=c;
873 startLine=lineNr;
874 if (c==':' || c=='=')
875 {
876 result+=cn;
877 if (cn=='\n') lineNr++;
878 }
879 char lineStr[blockSize];
880 do
881 {
882 //printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine);
883 int size_read=0;
884 do
885 {
886 // read up to blockSize-1 non-zero characters
887 int i=0;
888 while ((c=*p) && i<blockSize-1)
889 {
890 lineStr[i++]=c;
891 p++;
892 if (c=='\n') break; // stop at end of the line
893 }
894 lineStr[i]=0;
895 size_read=i;
896 result+=lineStr; // append line to the output
897 } while (size_read == (blockSize-1)); // append more if line does not fit in buffer
898 lineNr++;
899 } while (*p);
900
901 // strip stuff after closing bracket
902 int newLineIndex = result.findRev('\n');
903 int braceIndex = result.findRev('}');
904 if (braceIndex > newLineIndex)
905 {
906 result.resize(static_cast<size_t>(braceIndex+1));
907 }
908 endLine=lineNr-1;
909 }
910 if (usePipe)
911 {
912 Debug::print(Debug::FilterOutput, 0, "Filter output\n");
913 Debug::print(Debug::FilterOutput,0,"-------------\n{}\n-------------\n",result);
914 }
915 }
916 QCString encoding = getEncoding(FileInfo(fileName.str()));
917 if (encoding!="UTF-8")
918 {
919 std::string encBuf = result.str();
920 bool ok = transcodeCharacterStringToUTF8(encBuf,encoding.data());
921 if (ok)
922 {
923 result = encBuf;
924 }
925 else
926 {
927 err("failed to transcode characters in code fragment in file {} lines {} to {}, from input encoding {} to UTF-8\n",
928 fileName,startLine,endLine,encoding);
929
930 }
931 }
932 if (!result.isEmpty() && result.at(result.length()-1)!='\n') result += "\n";
933 //printf("readCodeFragment(%d-%d)=%s\n",startLine,endLine,qPrint(result));
934 return found;
935}
936
938{
939 ASSERT(p->def->definitionType()!=Definition::TypeFile); // file overloads this method
940 QCString fn;
941 bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
942 if (sourceBrowser &&
943 p->body && p->body->startLine!=-1 && p->body->fileDef)
944 {
945 fn = p->body->fileDef->getSourceFileBase();
946 }
947 return fn;
948}
949
951{
952 const int maxAnchorStrLen = 20;
953 char anchorStr[maxAnchorStrLen];
954 anchorStr[0]='\0';
955 if (p->body && p->body->startLine!=-1)
956 {
957 if (Htags::useHtags)
958 {
959 qsnprintf(anchorStr,maxAnchorStrLen,"L%d",p->body->defLine);
960 }
961 else
962 {
963 qsnprintf(anchorStr,maxAnchorStrLen,"l%05d",p->body->defLine);
964 }
965 }
966 return anchorStr;
967}
968
969/*! Write a reference to the source code defining this definition */
971{
972 //printf("DefinitionImpl::writeSourceRef %d %p\n",bodyLine,bodyDef);
974 if (!fn.isEmpty())
975 {
976 QCString refText = theTranslator->trDefinedAtLineInSourceFile();
977 int lineMarkerPos = refText.find("@0");
978 int fileMarkerPos = refText.find("@1");
979 if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this.
980 {
981 QCString lineStr;
982 lineStr.sprintf("%d",p->body->defLine);
983 QCString anchorStr = getSourceAnchor();
984 ol.startParagraph("definition");
985 if (lineMarkerPos<fileMarkerPos) // line marker before file marker
986 {
987 // write text left from linePos marker
988 ol.parseText(refText.left(lineMarkerPos));
989 ol.writeObjectLink(QCString(),fn,anchorStr,lineStr);
990 // write text between markers
991 ol.parseText(refText.mid(lineMarkerPos+2,fileMarkerPos-lineMarkerPos-2));
992 // write file link
993 ol.writeObjectLink(QCString(),fn,QCString(),p->body->fileDef->name());
994 // write text right from file marker
995 ol.parseText(refText.right(refText.length()-static_cast<size_t>(fileMarkerPos)-2));
996 }
997 else // file marker before line marker
998 {
999 // write text left from file marker
1000 ol.parseText(refText.left(fileMarkerPos));
1001 // write file link
1002 ol.writeObjectLink(QCString(),fn,QCString(),p->body->fileDef->name());
1003 // write text between markers
1004 ol.parseText(refText.mid(fileMarkerPos+2,lineMarkerPos-fileMarkerPos-2));
1005 // write line link
1006 ol.writeObjectLink(QCString(),fn,anchorStr,lineStr);
1007 // write text right from linePos marker
1008 ol.parseText(refText.right(refText.length()-static_cast<size_t>(lineMarkerPos)-2));
1009 }
1010 ol.endParagraph();
1011 }
1012 else
1013 {
1014 err("translation error: invalid markers in trDefinedAtLineInSourceFile()\n");
1015 }
1016 }
1017}
1018
1019void DefinitionImpl::setBodySegment(int defLine, int bls,int ble)
1020{
1021 if (!p->body.has_value())
1022 {
1023 p->body = std::make_optional<BodyInfo>();
1024 }
1025 BodyInfo &body = p->body.value();
1026 body.defLine = defLine;
1027 body.startLine = bls;
1028 body.endLine = ble;
1029}
1030
1032{
1033 if (!p->body.has_value())
1034 {
1035 p->body = std::make_optional<BodyInfo>();
1036 }
1037 p->body.value().fileDef=fd;
1038}
1039
1041{
1042 return p->body && p->body->startLine!=-1 &&
1043 p->body->endLine>=p->body->startLine &&
1044 p->body->fileDef;
1045}
1046
1047/*! Write code of this definition into the documentation */
1049{
1050 const MemberDef *thisMd = nullptr;
1051 if (p->def->definitionType()==Definition::TypeMember)
1052 {
1053 thisMd = toMemberDef(p->def);
1054 }
1055 bool inlineSources = thisMd && thisMd->hasInlineSource();
1056 //printf("Source Fragment %s: %d-%d\n",qPrint(name()),
1057 // p->body->startLine,p->body->endLine);
1058 if (inlineSources && hasSources())
1059 {
1060 ol.pushGeneratorState();
1061 QCString codeFragment;
1062 bool isMacro = thisMd && thisMd->memberType()==MemberType::Define;
1063 int actualStart=p->body->startLine,actualEnd=p->body->endLine;
1064 if (readCodeFragment(p->body->fileDef->absFilePath(),isMacro,
1065 actualStart,actualEnd,codeFragment)
1066 )
1067 {
1068 //printf("Adding code fragment '%s' ext='%s' range=%d-%d\n",
1069 // qPrint(codeFragment),qPrint(p->defFileExt),actualStart,actualEnd);
1070 auto intf = Doxygen::parserManager->getCodeParser(p->defFileExt);
1071 intf->resetCodeParserState();
1072 //printf("Read:\n'%s'\n\n",qPrint(codeFragment));
1073
1074 auto &codeOL = ol.codeGenerators();
1075 codeOL.startCodeFragment("DoxyCode");
1076 size_t indent = 0;
1077 intf->parseCode(codeOL, // codeOutIntf
1078 scopeName, // scope
1079 detab(codeFragment,indent), // input
1080 p->lang, // lang
1081 Config_getBool(STRIP_CODE_COMMENTS),
1083 .setFileDef(p->body->fileDef)
1084 .setStartLine(actualStart)
1085 .setEndLine(actualEnd)
1086 .setInlineFragment(true)
1087 .setMemberDef(thisMd)
1088 );
1089 codeOL.endCodeFragment("DoxyCode");
1090 }
1091 ol.popGeneratorState();
1092 }
1093}
1094
1095static inline MemberVector refMapToVector(const std::unordered_map<std::string,MemberDef *> &map)
1096{
1097 // convert map to a vector of values
1098 MemberVector result;
1099 std::transform(map.begin(),map.end(), // iterate over map
1100 std::back_inserter(result), // add results to vector
1101 [](const auto &item)
1102 { return item.second; } // extract value to add from map Key,Value pair
1103 );
1104 // and sort it
1105 std::stable_sort(result.begin(),result.end(),
1106 [](const auto &m1,const auto &m2) { return genericCompareMembers(m1,m2)<0; });
1107 return result;
1108}
1109
1110/*! Write a reference to the source code fragments in which this
1111 * definition is used.
1112 */
1114 const QCString &text,const std::unordered_map<std::string,MemberDef *> &membersMap,
1115 bool /*funcOnly*/) const
1116{
1117 if (!membersMap.empty())
1118 {
1119 auto members = refMapToVector(membersMap);
1120
1121 auto replaceFunc = [this,&members,scopeName,&ol](size_t entryIndex)
1122 {
1123 bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1124 bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE);
1125 const MemberDef *md=members[entryIndex];
1126 if (md)
1127 {
1128 QCString scope=md->getScopeString();
1129 QCString name=md->name();
1130 //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),qPrint(scope),scopeName);
1131 if (!scope.isEmpty() && scope!=scopeName)
1132 {
1133 name.prepend(scope+getLanguageSpecificSeparator(p->lang));
1134 }
1135 if (!md->isObjCMethod() &&
1136 (md->isFunction() || md->isSlot() ||
1137 md->isPrototype() || md->isSignal()
1138 )
1139 )
1140 {
1141 name+="()";
1142 }
1143 if (sourceBrowser &&
1144 !(md->isLinkable() && !refLinkSource) &&
1145 md->getStartBodyLine()!=-1 &&
1146 md->getBodyDef()
1147 )
1148 {
1149 const int maxLineNrStr = 10;
1150 char anchorStr[maxLineNrStr];
1151 qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine());
1152 //printf("Write object link to %s\n",qPrint(md->getBodyDef()->getSourceFileBase()));
1153 ol.writeObjectLink(QCString(),md->getBodyDef()->getSourceFileBase(),anchorStr,name);
1154 }
1155 else if (md->isLinkable())
1156 {
1158 md->getOutputFileBase(),
1159 md->anchor(),name);
1160 }
1161 else
1162 {
1163 ol.docify(name);
1164 }
1165 }
1166 };
1167
1168 ol.startParagraph("reference");
1169 ol.parseText(text);
1170 ol.docify(" ");
1171 writeMarkerList(ol,
1172 theTranslator->trWriteList(static_cast<int>(members.size())).str(),
1173 members.size(),
1174 replaceFunc);
1175 ol.writeString(".");
1176 ol.endParagraph();
1177
1178 }
1179}
1180
1182{
1183 _writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),p->sourceRefByDict,FALSE);
1184}
1185
1187{
1188 _writeSourceRefList(ol,scopeName,theTranslator->trReferences(),p->sourceRefsDict,TRUE);
1189}
1190
1192{
1193 if (!Config_getBool(GENERATE_REQUIREMENTS)) return;
1194 auto writeRefsForType = [&ol](const RequirementRefs &refs,const char *parType,const QCString &text)
1195 {
1196 size_t num = refs.size();
1197 if (num>0)
1198 {
1199 ol.startParagraph(parType);
1200 ol.parseText(text);
1201 ol.docify(" ");
1202 writeMarkerList(ol,
1203 theTranslator->trWriteList(static_cast<int>(num)).str(), num,
1204 [&refs,&ol](size_t entryIndex) { RequirementManager::instance().writeRef(ol,refs[entryIndex]); }
1205 );
1206 ol.writeString(".");
1207 ol.endParagraph();
1208 }
1209 };
1210
1211 RequirementRefs satisfiesRefs;
1212 RequirementRefs verifiesRefs;
1213 splitRequirementRefs(p->requirementRefs,satisfiesRefs,verifiesRefs);
1214 writeRefsForType(satisfiesRefs,"satisfies",theTranslator->trSatisfies(satisfiesRefs.size()==1));
1215 writeRefsForType(verifiesRefs, "verifies", theTranslator->trVerifies(verifiesRefs.size()==1));
1216}
1217
1219{
1220 return !p->sourceRefByDict.empty();
1221}
1222
1224{
1225 return !p->sourceRefsDict.empty();
1226}
1227
1229{
1230 return !p->requirementRefs.empty();
1231}
1232
1234{
1235 bool extractAll = Config_getBool(EXTRACT_ALL);
1236 //bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1237 bool hasDocs =
1238 (p->details && !p->details->doc.isEmpty()) || // has detailed docs
1239 (p->brief && !p->brief->doc.isEmpty()) || // has brief description
1240 (p->inbodyDocs && !p->inbodyDocs->doc.isEmpty()) || // has inbody docs
1241 extractAll //|| // extract everything
1242 // (sourceBrowser && p->body &&
1243 // p->body->startLine!=-1 && p->body->fileDef)
1244 ; // link to definition
1245 return hasDocs;
1246}
1247
1249{
1250 bool hasDocs =
1251 (p->details && !p->details->doc.isEmpty()) ||
1252 (p->brief && !p->brief->doc.isEmpty()) ||
1253 (p->inbodyDocs && !p->inbodyDocs->doc.isEmpty());
1254 return hasDocs;
1255}
1256
1258{
1259 if (md)
1260 {
1261 p->sourceRefByDict.emplace(sourceRefName.str(),md);
1262 }
1263}
1264
1266{
1267 if (md)
1268 {
1269 p->sourceRefsDict.emplace(sourceRefName.str(),md);
1270 }
1271}
1272
1274{
1275 return nullptr;
1276}
1277
1279{
1280 err("DefinitionImpl::addInnerCompound() called\n");
1281}
1282
1284{
1285 std::call_once(p->qualifiedNameOnce.flag, [this]()
1286 {
1287 //printf("start %s::qualifiedName() localName=%s\n",qPrint(name()),qPrint(p->localName));
1288 if (p->outerScope==nullptr || p->outerScope->name()=="<globalScope>")
1289 {
1290 p->qualifiedName = (p->localName=="<globalScope>") ? QCString() : p->localName;
1291 }
1292 else
1293 {
1294 p->qualifiedName = p->outerScope->qualifiedName()+
1295 getLanguageSpecificSeparator(getLanguage())+
1296 p->localName;
1297 }
1298 //printf("end %s::qualifiedName()=%s\n",qPrint(name()),qPrint(p->qualifiedName));
1299 });
1300 return p->qualifiedName;
1301}
1302
1304{
1305 //printf("%s::setOuterScope(%s)\n",qPrint(name()),d?qPrint(d->name()):"<none>");
1306 Definition *outerScope = p->outerScope;
1307 bool found=false;
1308 // make sure that we are not creating a recursive scope relation.
1309 while (outerScope && !found)
1310 {
1311 found = (outerScope==d);
1312 outerScope = outerScope->getOuterScope();
1313 }
1314 if (!found)
1315 {
1316 p->qualifiedName.clear(); // flush cached scope name
1317 p->qualifiedNameOnce.reset();
1318 p->outerScope = d;
1319 }
1320 p->hidden = p->hidden || d->isHidden();
1321 assert(p->def!=p->outerScope);
1322}
1323
1325{
1326 return p->localName;
1327}
1328
1330{
1331 p->partOfGroups.push_back(gd);
1332}
1333
1335{
1336 p->xrefListItems.insert(p->xrefListItems.end(), sli.cbegin(), sli.cend());
1337}
1338
1340{
1341 p->requirementRefs.insert(p->requirementRefs.end(), rqli.cbegin(), rqli.cend());
1342}
1343
1345{
1346 auto otherXrefList = d->xrefListItems();
1347
1348 // append vectors
1349 p->xrefListItems.reserve(p->xrefListItems.size()+otherXrefList.size());
1350 p->xrefListItems.insert (p->xrefListItems.end(),
1351 otherXrefList.begin(),otherXrefList.end());
1352
1353 // sort results on itemId
1354 std::stable_sort(p->xrefListItems.begin(),p->xrefListItems.end(),
1355 [](RefItem *left,RefItem *right)
1356 { return left->id() <right->id() ||
1357 (left->id()==right->id() &&
1358 left->list()->listName() < right->list()->listName());
1359 });
1360
1361 // filter out duplicates
1362 auto last = std::unique(p->xrefListItems.begin(),p->xrefListItems.end(),
1363 [](const RefItem *left,const RefItem *right)
1364 { return left->id()==right->id() &&
1365 left->list()->listName()==right->list()->listName();
1366 });
1367 p->xrefListItems.erase(last, p->xrefListItems.end());
1368}
1369
1371{
1372 for (const RefItem *item : p->xrefListItems)
1373 {
1374 if (item->list()->listName()==listName)
1375 {
1376 return item->id();
1377 }
1378 }
1379 return -1;
1380}
1381
1383{
1384 return p->xrefListItems;
1385}
1386
1388{
1389 return p->requirementRefs;
1390}
1391
1393{
1394 QCString result;
1395 if (p->outerScope && p->outerScope!=Doxygen::globalScope)
1396 {
1397 result = p->outerScope->pathFragment();
1398 }
1399 if (p->def->isLinkable())
1400 {
1401 if (!result.isEmpty()) result+="/";
1402 if (p->def->definitionType()==Definition::TypeGroup &&
1403 !toGroupDef(p->def)->groupTitle().isEmpty())
1404 {
1405 result+=toGroupDef(p->def)->groupTitle();
1406 }
1407 else if (p->def->definitionType()==Definition::TypePage &&
1408 toPageDef(p->def)->hasTitle())
1409 {
1410 result+=toPageDef(p->def)->title();
1411 }
1412 else
1413 {
1414 result+=p->localName;
1415 }
1416 }
1417 else
1418 {
1419 result+=p->localName;
1420 }
1421 return result;
1422}
1423
1424//----------------------------------------------------------------------------------------
1425
1426// TODO: move to htmlgen
1427/*! Returns the string used in the footer for $navpath when
1428 * GENERATE_TREEVIEW is enabled
1429 */
1431{
1432 QCString result;
1433 Definition *outerScope = getOuterScope();
1434 QCString locName = localName();
1435 if (outerScope && outerScope!=Doxygen::globalScope)
1436 {
1437 result+=outerScope->navigationPathAsString();
1438 }
1439 else if (p->def->definitionType()==Definition::TypeFile &&
1440 toFileDef(p->def)->getDirDef())
1441 {
1442 result+=(toFileDef(p->def))->getDirDef()->navigationPathAsString();
1443 }
1444 result+="<li class=\"navelem\">";
1445 if (p->def->isLinkableInProject())
1446 {
1447 QCString fn = p->def->getOutputFileBase();
1449 if (p->def->definitionType()==Definition::TypeGroup &&
1450 !toGroupDef(p->def)->groupTitle().isEmpty())
1451 {
1452 QCString title = parseCommentAsHtml(p->def,nullptr,toGroupDef(p->def)->groupTitle(),
1453 p->def->getDefFileName(),p->def->getDefLine());
1454 result+="<a href=\"$relpath^"+fn+"\">"+title+"</a>";
1455 }
1456 else if (p->def->definitionType()==Definition::TypePage &&
1457 toPageDef(p->def)->hasTitle())
1458 {
1459 QCString title = parseCommentAsHtml(p->def,nullptr,toPageDef(p->def)->title(),
1460 p->def->getDefFileName(),p->def->getDefLine());
1461 result+="<a href=\"$relpath^"+fn+"\">"+title+"</a>";
1462 }
1463 else if (p->def->definitionType()==Definition::TypeClass)
1464 {
1465 QCString name = toClassDef(p->def)->className();
1466 if (name.endsWith("-p"))
1467 {
1468 name = name.left(name.length()-2);
1469 }
1470 result+="<a href=\"$relpath^"+fn;
1471 if (!p->def->anchor().isEmpty()) result+="#"+p->def->anchor();
1472 result+="\">"+convertToHtml(name)+"</a>";
1473 }
1474 else
1475 {
1476 result+="<a href=\"$relpath^"+fn+"\">"+
1477 convertToHtml(locName)+"</a>";
1478 }
1479 }
1480 else
1481 {
1482 result+="<b>"+convertToHtml(locName)+"</b>";
1483 }
1484 result+="</li>";
1485 return result;
1486}
1487
1488// TODO: move to htmlgen
1490{
1491 ol.pushGeneratorState();
1493
1494 QCString navPath;
1495 navPath += "<div id=\"nav-path\" class=\"navpath\">\n"
1496 " <ul>\n";
1497 navPath += navigationPathAsString();
1498 navPath += " </ul>\n"
1499 "</div>\n";
1500 ol.writeNavigationPath(navPath);
1501
1502 ol.popGeneratorState();
1503}
1504
1505void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const
1506{
1507 // first check if we have anything to show or if the outline is already shown on the outline panel
1508 if (p->sectionRefs.empty() || (Config_getBool(GENERATE_TREEVIEW) && Config_getBool(PAGE_OUTLINE_PANEL))) return;
1509 // generate the embedded toc
1510 //ol.writeLocalToc(p->sectionRefs,localToc);
1511
1512 auto generateTocEntries = [this,&ol]()
1513 {
1514 for (const SectionInfo *si : p->sectionRefs)
1515 {
1516 if (si->type().isSection())
1517 {
1518 ol.startTocEntry(si);
1519 const MemberDef *md = p->def->definitionType()==Definition::TypeMember ? toMemberDef(p->def) : nullptr;
1520 const Definition *scope = p->def->definitionType()==Definition::TypeMember ? p->def->getOuterScope() : p->def;
1521 QCString docTitle = si->title();
1522 if (docTitle.isEmpty()) docTitle = si->label();
1523 ol.generateDoc(docFile(),
1525 scope,
1526 md,
1527 docTitle,
1528 DocOptions()
1529 .setIndexWords(true)
1530 .setSingleLine(true)
1531 .setSectionLevel(si->type().level())
1532 );
1533 ol.endTocEntry(si);
1534 }
1535 }
1536 };
1537
1538 if (localToc.isHtmlEnabled())
1539 {
1540 ol.pushGeneratorState();
1542 ol.startLocalToc(localToc.htmlLevel());
1543 generateTocEntries();
1544 ol.endLocalToc();
1545 ol.popGeneratorState();
1546 }
1547 if (localToc.isDocbookEnabled())
1548 {
1549 ol.pushGeneratorState();
1551 ol.startLocalToc(localToc.docbookLevel());
1552 generateTocEntries();
1553 ol.endLocalToc();
1554 ol.popGeneratorState();
1555 }
1556 if (localToc.isLatexEnabled())
1557 {
1558 ol.pushGeneratorState();
1560 ol.startLocalToc(localToc.latexLevel());
1561 // no gneerateTocEntries() needed for LaTeX
1562 ol.endLocalToc();
1563 ol.popGeneratorState();
1564 }
1565}
1566
1567//----------------------------------------------------------------------------------------
1568
1570{
1571 return p->sectionRefs;
1572}
1573
1575{
1576 return p->symbolName;
1577}
1578
1579//----------------------
1580
1582{
1583 return p->details ? p->details->doc : QCString("");
1584}
1585
1587{
1588 return p->details ? p->details->line : p->brief ? p->brief->line : 1;
1589}
1590
1592{
1593 if (p->details && !p->details->file.isEmpty()) return p->details->file;
1594 else if (p->brief && !p->brief->file.isEmpty()) return p->brief->file;
1595 else return "<" + p->name + ">";
1596}
1597
1598//----------------------------------------------------------------------------
1599// strips w from s iff s starts with w
1600static bool stripWord(QCString &s,QCString w)
1601{
1602 bool success=FALSE;
1603 if (s.left(w.length())==w)
1604 {
1605 success=TRUE;
1606 s=s.right(s.length()-w.length());
1607 }
1608 return success;
1609}
1610
1611//----------------------------------------------------------------------------
1612// some quasi intelligent brief description abbreviator :^)
1613static QCString abbreviate(const QCString &s,const QCString &name)
1614{
1615 QCString scopelessName=name;
1616 int i=scopelessName.findRev("::");
1617 if (i!=-1) scopelessName=scopelessName.mid(i+2);
1618 QCString result=s;
1619 result=result.stripWhiteSpace();
1620 // strip trailing .
1621 if (!result.isEmpty() && result.at(result.length()-1)=='.')
1622 result=result.left(result.length()-1);
1623
1624 // strip any predefined prefix
1625 const StringVector &briefDescAbbrev = Config_getList(ABBREVIATE_BRIEF);
1626 for (const auto &p : briefDescAbbrev)
1627 {
1628 QCString str = substitute(p,"$name",scopelessName); // replace $name with entity name
1629 str += " ";
1630 stripWord(result,str);
1631 }
1632
1633 // capitalize first character
1634 if (!result.isEmpty())
1635 {
1636 char c = result[0];
1637 if (c >= 'a' && c <= 'z') result[0] += 'A' - 'a';
1638 }
1639
1640 return result;
1641}
1642
1643
1644//----------------------
1645
1647{
1648 //printf("%s::briefDescription(%d)='%s'\n",qPrint(name()),abbr,p->brief?qPrint(p->brief->doc):"<none>");
1649 return p->brief ?
1650 (abbr ? abbreviate(p->brief->doc,p->def->displayName()) : p->brief->doc) :
1651 QCString("");
1652}
1653
1655{
1656 if (p->brief && p->brief->tooltip.isEmpty() && !p->brief->doc.isEmpty())
1657 {
1658 const MemberDef *md = p->def->definitionType()==Definition::TypeMember ? toMemberDef(p->def) : nullptr;
1659 const Definition *scope = p->def->definitionType()==Definition::TypeMember ? p->def->getOuterScope() : p->def;
1660 p->brief->tooltip = parseCommentAsText(scope,md,
1661 p->brief->doc, p->brief->file, p->brief->line);
1662 }
1663}
1664
1666{
1667 return p->brief ? p->brief->tooltip : QCString();
1668}
1669
1671{
1672 return p->brief ? p->brief->line : 1;
1673}
1674
1676{
1677 return p->brief && !p->brief->file.isEmpty() ? p->brief->file : QCString("<"+p->name+">");
1678}
1679
1680//----------------------
1681
1683{
1684 return p->inbodyDocs ? p->inbodyDocs->doc : QCString("");
1685}
1686
1688{
1689 return p->inbodyDocs ? p->inbodyDocs->line : 1;
1690}
1691
1693{
1694 return p->inbodyDocs && !p->inbodyDocs->file.isEmpty() ? p->inbodyDocs->file : QCString("<"+p->name+">");
1695}
1696
1697
1698//----------------------
1699
1701{
1702 return p->defFileName;
1703}
1704
1706{
1707 return p->defFileExt;
1708}
1709
1711{
1712 return p->hidden;
1713}
1714
1716{
1717 return p->def->isLinkableInProject() && !p->hidden;
1718}
1719
1721{
1722 return p->def->isLinkable() && !p->hidden;
1723}
1724
1726{
1727 return p->isArtificial;
1728}
1729
1731{
1732 return p->isExported;
1733}
1734
1736{
1737 return p->ref;
1738}
1739
1741{
1742 return !p->ref.isEmpty();
1743}
1744
1746{
1747 return p->body ? p->body->defLine : -1;
1748}
1749
1751{
1752 return p->body ? p->body->startLine : -1;
1753}
1754
1756{
1757 return p->body ? p->body->endLine : -1;
1758}
1759
1761{
1762 return p->body ? p->body->fileDef : nullptr;
1763}
1764
1766{
1767 return p->partOfGroups;
1768}
1769
1771{
1772 for (const auto &gd : partOfGroups())
1773 {
1774 if (gd->isLinkable()) return true;
1775 }
1776 return false;
1777}
1778
1780{
1781 return p->outerScope;
1782}
1783
1784static std::mutex g_memberReferenceMutex;
1785
1787{
1788 std::lock_guard<std::mutex> lock(g_memberReferenceMutex);
1789 if (p->referencesMembers.empty() && !p->sourceRefsDict.empty())
1790 {
1791 p->referencesMembers = refMapToVector(p->sourceRefsDict);
1792 }
1793 return p->referencesMembers;
1794}
1795
1797{
1798 std::lock_guard<std::mutex> lock(g_memberReferenceMutex);
1799 if (p->referencedByMembers.empty() && !p->sourceRefByDict.empty())
1800 {
1801 p->referencedByMembers = refMapToVector(p->sourceRefByDict);
1802 }
1803 return p->referencedByMembers;
1804}
1805
1807{
1808 const DefinitionImpl *defImpl = other->toDefinitionImpl_();
1809 if (defImpl)
1810 {
1811 for (const auto &kv : defImpl->p->sourceRefsDict)
1812 {
1813 auto it = p->sourceRefsDict.find(kv.first);
1814 if (it != p->sourceRefsDict.end())
1815 {
1816 p->sourceRefsDict.insert(kv);
1817 }
1818 }
1819 }
1820}
1821
1823{
1824 const DefinitionImpl *defImpl = other->toDefinitionImpl_();
1825 if (defImpl)
1826 {
1827 for (const auto &kv : defImpl->p->sourceRefByDict)
1828 {
1829 auto it = p->sourceRefByDict.find(kv.first);
1830 if (it != p->sourceRefByDict.end())
1831 {
1832 p->sourceRefByDict.emplace(kv.first,kv.second);
1833 }
1834 }
1835 }
1836}
1837
1838
1840{
1841 p->ref=r;
1842}
1843
1845{
1846 return p->lang;
1847}
1848
1850{
1851 p->hidden = p->hidden || b;
1852}
1853
1855{
1856 p->isArtificial = b;
1857}
1858
1860{
1861 p->isExported = b;
1862}
1863
1865{
1866 p->localName=name;
1867}
1868
1870{
1871 p->lang=lang;
1872}
1873
1874
1876{
1877 p->symbolName=name;
1878}
1879
1881{
1882 return p->symbolName;
1883}
1884
1886{
1887 bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC);
1888 return !briefDescription().isEmpty() && briefMemberDesc;
1889}
1890
1892{
1893 QCString ref = getReference();
1894 if (!ref.isEmpty())
1895 {
1896 auto it = Doxygen::tagDestinationMap.find(ref.str());
1898 {
1899 QCString result(it->second);
1900 size_t l = result.length();
1901 if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
1902 { // relative path -> prepend relPath.
1903 result.prepend(relPath);
1904 l+=relPath.length();
1905 }
1906 if (l>0 && result.at(l-1)!='/') result+='/';
1907 return result;
1908 }
1909 }
1910 return relPath;
1911}
1912
1914{
1915 return p->name;
1916}
1917
1919{
1920 return p->isAnonymous;
1921}
1922
1924{
1925 return p->defLine;
1926}
1927
1929{
1930 return p->defColumn;
1931}
1932
1936
1940
1944
1945//---------------------------------------------------------------------------------
1946
1948 : m_def(def), m_scope(scope), m_symbolName(alias->_symbolName())
1949{
1950}
1951
1955
1957{
1958 //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name()));
1960 if (m_scope==nullptr)
1961 {
1962 m_qualifiedName = m_def->localName();
1963 }
1964 else
1965 {
1966 m_qualifiedName = m_scope->qualifiedName()+
1967 getLanguageSpecificSeparator(m_scope->getLanguage())+
1968 m_def->localName();
1969 }
1970}
1971
1976
1981
1983{
1984 return m_qualifiedName;
1985}
1986
1987//---------------------------------------------------------------------------------
1988
1990{
1991 return dm ? dm->toDefinition_() : nullptr;
1992}
1993
1995{
1996 return d ? d->toDefinitionMutable_() : nullptr;
1997}
1998
static AnchorGenerator & instance()
Returns the singleton instance.
Definition anchor.cpp:38
virtual QCString className() const =0
Returns the name of the class including outer classes, but not including namespaces.
@ FilterOutput
Definition debug.h:38
@ ExtCmd
Definition debug.h:36
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:76
DefinitionAliasImpl(Definition *def, const Definition *scope, const Definition *alias)
const Definition * m_scope
const QCString & name() const
QCString qualifiedName() const
virtual ~DefinitionAliasImpl()
The common base class of all entity definitions found in the sources.
Definition definition.h:77
virtual const RefItemVector & xrefListItems() const =0
virtual QCString navigationPathAsString() const =0
virtual bool isLinkable() const =0
virtual QCString anchor() const =0
virtual DefinitionMutable * toDefinitionMutable_()=0
virtual const FileDef * getBodyDef() const =0
virtual bool isHidden() const =0
virtual QCString getReference() const =0
virtual void _setSymbolName(const QCString &name)=0
virtual QCString getSourceFileBase() const =0
virtual QCString getOutputFileBase() const =0
virtual Definition * getOuterScope() const =0
virtual int getStartBodyLine() const =0
virtual const DefinitionImpl * toDefinitionImpl_() const =0
virtual const QCString & name() const =0
Private data associated with a Symbol DefinitionImpl object.
MemberVector referencesMembers
std::optional< BriefInfo > brief
std::optional< BodyInfo > body
RequirementRefs requirementRefs
void init(const QCString &df, const QCString &n)
ResettableOnce qualifiedNameOnce
std::optional< DocInfo > inbodyDocs
MemberVector referencedByMembers
std::unordered_map< std::string, MemberDef * > sourceRefByDict
std::unordered_map< std::string, MemberDef * > sourceRefsDict
RefItemVector xrefListItems
void setDefFileName(const QCString &df)
void setId(const QCString &name)
const RequirementRefs & requirementReferences() const
void setBodySegment(int defLine, int bls, int ble)
void setExported(bool b)
int getDefLine() const
bool isHidden() const
void mergeRefItems(Definition *d)
bool hasRequirementRefs() const
QCString documentation() const
void addSourceReferencedBy(MemberDef *d, const QCString &sourceRefName)
const RefItemVector & xrefListItems() const
void writeSummaryLinks(OutputList &) const
void setHidden(bool b)
QCString _symbolName() const
QCString getSourceFileBase() const
QCString externalReference(const QCString &relPath) const
bool isReference() const
bool isVisible() const
int briefLine() const
void addSectionsToDefinition(const std::vector< const SectionInfo * > &anchorList)
bool isAnonymous() const
bool isLinkableViaGroup() const
void setDefFile(const QCString &df, int defLine, int defColumn)
const Definition * findInnerCompound(const QCString &name) const
void setName(const QCString &name)
SrcLangExt getLanguage() const
void addInnerCompound(Definition *d)
void setArtificial(bool b)
bool hasSourceReffedBy() const
void _writeSourceRefList(OutputList &ol, const QCString &scopeName, const QCString &text, const std::unordered_map< std::string, MemberDef * > &members, bool) const
void writeNavigationPath(OutputList &ol) const
QCString getDefFileName() const
void writeSourceReffedBy(OutputList &ol, const QCString &scopeName) const
bool _docsAlreadyAdded(const QCString &doc, QCString &sigList)
void _setInbodyDocumentation(const QCString &d, const QCString &docFile, int docLine)
void setRefItems(const RefItemVector &sli)
int getStartBodyLine() const
void setLocalName(const QCString &name)
QCString symbolName() const
QCString id() const
void setOuterScope(Definition *d)
void _setBriefDescription(const QCString &b, const QCString &briefFile, int briefLine)
QCString qualifiedName() const
const MemberVector & getReferencesMembers() const
void setBodyDef(const FileDef *fd)
void writeInlineCode(OutputList &ol, const QCString &scopeName) const
int docLine() const
void setInbodyDocumentation(const QCString &d, const QCString &docFile, int docLine)
bool isArtificial() const
bool isExported() const
QCString briefDescriptionAsTooltip() const
int _getXRefListId(const QCString &listName) const
QCString inbodyDocumentation() const
QCString getSourceAnchor() const
QCString getDefFileExtension() const
void writeQuickMemberLinks(OutputList &, const MemberDef *) const
const GroupList & partOfGroups() const
void setBriefDescription(const QCString &b, const QCString &briefFile, int briefLine)
const QCString & name() const
QCString briefFile() const
bool hasUserDocumentation() const
int inbodyLine() const
QCString briefDescription(bool abbreviate=FALSE) const
bool hasBriefDescription() const
bool hasSources() const
const SectionRefs & getSectionRefs() const
DefinitionImpl & operator=(const DefinitionImpl &d)
bool isVisibleInProject() const
void writeSourceRefs(OutputList &ol, const QCString &scopeName) const
void makePartOfGroup(GroupDef *gd)
const QCString & localName() const
void mergeReferencedBy(const Definition *other)
int getStartDefLine() const
void setDocumentation(const QCString &d, const QCString &docFile, int docLine, bool stripWhiteSpace=TRUE)
void setReference(const QCString &r)
bool hasSourceRefs() const
void writeToc(OutputList &ol, const LocalToc &lt) const
QCString navigationPathAsString() const
void _setDocumentation(const QCString &d, const QCString &docFile, int docLine, bool stripWhiteSpace, bool atTop)
void writePageNavigation(OutputList &ol) const
const FileDef * getBodyDef() const
void writeSourceDef(OutputList &ol) const
void setLanguage(SrcLangExt lang)
void mergeReferences(const Definition *other)
QCString inbodyFile() const
std::unique_ptr< Private > p
bool hasSections() const
QCString docFile() const
void setRequirementReferences(const RequirementRefs &rqli)
bool hasDocumentation() const
Definition * getOuterScope() const
const MemberVector & getReferencedByMembers() const
QCString pathFragment() const
DefinitionImpl(Definition *def, const QCString &defFileName, int defLine, int defColumn, const QCString &name, const char *b=nullptr, const char *d=nullptr, bool isSymbol=TRUE)
int getDefColumn() const
int getEndBodyLine() const
void writeDocAnchorsToTagFile(TextStream &) const
void writeRequirementRefs(OutputList &ol) const
void _setSymbolName(const QCString &name)
QCString getReference() const
void addSourceReferences(MemberDef *d, const QCString &sourceRefName)
virtual Definition * toDefinition_()=0
static ParserManager * parserManager
Definition doxygen.h:128
static NamespaceDefMutable * globalScope
Definition doxygen.h:120
static StringMap tagDestinationMap
Definition doxygen.h:115
static QCString filterDBFileName
Definition doxygen.h:130
static SymbolMap< Definition > * symbolMap
Definition doxygen.h:124
static ClangUsrMap * clangUsrMap
Definition doxygen.h:125
A model of a file symbol.
Definition filedef.h:99
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
std::string extension(bool complete) const
Definition fileinfo.cpp:130
void shrinkBuffer(std::string &str, const QCString &fileName, size_t startLine, size_t endLine)
std::vector< size_t > LineOffsets
auto getFragmentLocation(const LineOffsets &lineOffsets, size_t startLine, size_t endLine) -> std::tuple< size_t, size_t >
std::unordered_map< std::string, LineOffsets > m_lineOffsets
bool getFileContentsDisk(const QCString &fileName, size_t startLine, size_t endLine, std::string &str)
static FilterCache & instance()
void readFragmentFromFile(std::string &str, const QCString &fileName, size_t startOffset, size_t size=0)
size_t m_endPos
void compileLineOffsets(const QCString &fileName, const std::string &str)
bool getFileContents(const QCString &fileName, size_t startLine, size_t endLine, std::string &str)
bool getFileContentsPipe(const QCString &fileName, const QCString &filter, size_t startLine, size_t endLine, std::string &str)
std::unordered_map< std::string, FilterCacheItem > m_cache
std::mutex m_mutex
A model of a group of symbols.
Definition groupdef.h:52
virtual QCString groupTitle() const =0
const T * find(const std::string &key) const
Definition linkedmap.h:47
constexpr int docbookLevel() const noexcept
Definition types.h:622
constexpr int latexLevel() const noexcept
Definition types.h:620
constexpr bool isDocbookEnabled() const noexcept
Definition types.h:617
constexpr bool isLatexEnabled() const noexcept
Definition types.h:615
constexpr int htmlLevel() const noexcept
Definition types.h:619
constexpr bool isHtmlEnabled() const noexcept
Definition types.h:614
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
virtual bool isSignal() const =0
virtual bool isObjCMethod() const =0
virtual bool isSlot() const =0
virtual bool isFunction() const =0
virtual QCString getScopeString() const =0
virtual bool hasInlineSource() const =0
virtual MemberType memberType() const =0
virtual bool isPrototype() const =0
A vector of MemberDef object.
Definition memberlist.h:35
iterator end() noexcept
Definition memberlist.h:56
iterator begin() noexcept
Definition memberlist.h:54
void startCodeFragment(const QCString &style)
Definition outputlist.h:279
Class representing a list of output generators that are written to in parallel.
Definition outputlist.h:315
void writeString(const QCString &text)
Definition outputlist.h:411
void startTocEntry(const SectionInfo *si)
Definition outputlist.h:748
const OutputCodeList & codeGenerators() const
Definition outputlist.h:358
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name)
Definition outputlist.h:439
void docify(const QCString &s)
Definition outputlist.h:437
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, const DocOptions &options)
void startParagraph(const QCString &classDef=QCString())
Definition outputlist.h:407
void endParagraph()
Definition outputlist.h:409
void pushGeneratorState()
void endLocalToc()
Definition outputlist.h:746
void disableAllBut(OutputType o)
void popGeneratorState()
void endTocEntry(const SectionInfo *si)
Definition outputlist.h:750
void writeNavigationPath(const QCString &s)
Definition outputlist.h:608
void parseText(const QCString &textStr)
void startLocalToc(int level)
Definition outputlist.h:744
virtual QCString title() const =0
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:422
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
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
void resize(size_t newlen)
Definition qcstring.h:180
QCString fill(char c, int len=-1)
Fills a string with a predefined character.
Definition qcstring.h:193
const std::string & str() const
Definition qcstring.h:552
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition qcstring.cpp:190
QCString right(size_t len) const
Definition qcstring.h:234
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:96
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
QCString left(size_t len) const
Definition qcstring.h:229
This struct represents an item in the list of references.
Definition reflist.h:32
int id() const
Definition reflist.h:52
RefList * list() const
Definition reflist.h:53
QCString listName() const
Definition reflist.h:101
class that provide information about a section.
Definition section.h:58
QCString label() const
Definition section.h:69
QCString ref() const
Definition section.h:72
void setDefinition(Definition *d)
Definition section.h:83
QCString fileName() const
Definition section.h:74
bool generated() const
Definition section.h:75
QCString title() const
Definition section.h:70
SectionType type() const
Definition section.h:71
singleton class that owns the list of all sections
Definition section.h:135
SectionInfo * add(const SectionInfo &si)
Definition section.h:139
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:179
class that represents a list of constant references to sections.
Definition section.h:103
constexpr bool isSection() const
Definition section.h:47
constexpr int level() const
Definition section.h:46
Text streaming class that buffers data.
Definition textstream.h:36
ClassDef * toClassDef(Definition *d)
Class representing a regular expression.
Definition regex.h:39
Object representing the matching results.
Definition regex.h:151
#define Config_getInt(name)
Definition config.h:34
#define Config_getList(name)
Definition config.h:38
#define Config_getBool(name)
Definition config.h:33
std::vector< std::string > StringVector
Definition containers.h:33
static std::mutex g_memberReferenceMutex
static void removeFromMap(const QCString &name, Definition *d)
bool readCodeFragment(const QCString &fileName, bool isMacro, int &startLine, int &endLine, QCString &result)
Reads a fragment from file fileName starting with line startLine and ending with line endLine.
static void addToMap(const QCString &name, Definition *d)
static bool matchExcludedSymbols(const QCString &name)
static QCString abbreviate(const QCString &s, const QCString &name)
Definition * toDefinition(DefinitionMutable *dm)
static MemberVector refMapToVector(const std::unordered_map< std::string, MemberDef * > &map)
static bool stripWord(QCString &s, QCString w)
DefinitionMutable * toDefinitionMutable(Definition *d)
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
FileDef * toFileDef(Definition *d)
Definition filedef.cpp:1966
GroupDef * toGroupDef(Definition *d)
Translator * theTranslator
Definition language.cpp:71
MemberDef * toMemberDef(Definition *d)
#define err(fmt,...)
Definition message.h:127
std::ifstream openInputStream(const QCString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:659
FILE * popen(const QCString &name, const QCString &type)
Definition portable.cpp:479
FILE * fopen(const QCString &fileName, const QCString &mode)
Definition portable.cpp:349
int pclose(FILE *stream)
Definition portable.cpp:488
bool search(std::string_view str, Match &match, const Ex &re, size_t pos)
Search in a given string str starting at position pos for a match against regular expression re.
Definition regex.cpp:844
PageDef * toPageDef(Definition *d)
Definition pagedef.cpp:502
Portable versions of functions that are platform dependent.
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:571
#define qsnprintf
Definition qcstring.h:49
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
std::vector< RefItem * > RefItemVector
Definition reflist.h:133
void splitRequirementRefs(const RequirementRefs &inputReqRefs, RequirementRefs &satisfiesRefs, RequirementRefs &verifiesRefs)
std::vector< RequirementRef > RequirementRefs
List of requirement references.
Definition requirement.h:56
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
Definition stringutil.h:72
Data associated with description found in the body.
Definition definition.h:64
int startLine
line number of the start of the definition's body
Definition definition.h:66
int endLine
line number of the end of the definition's body
Definition definition.h:67
int defLine
line number of the start of the definition
Definition definition.h:65
Data associated with a brief description.
Definition definition.h:55
QCString file
Definition definition.h:59
QCString doc
Definition definition.h:56
Options to configure the code parser.
Definition parserintf.h:78
CodeParserOptions & setStartLine(int lineNr)
Definition parserintf.h:101
CodeParserOptions & setInlineFragment(bool enable)
Definition parserintf.h:107
CodeParserOptions & setEndLine(int lineNr)
Definition parserintf.h:104
CodeParserOptions & setMemberDef(const MemberDef *md)
Definition parserintf.h:110
Data associated with a detailed description.
Definition definition.h:47
QCString doc
Definition definition.h:48
int line
Definition definition.h:49
QCString file
Definition definition.h:50
static bool useHtags
Definition htags.h:23
once_flag wrapper that is copyable (copy default-initializes the flag) and resettable.
ResettableOnce()=default
std::once_flag flag
ResettableOnce & operator=(const ResettableOnce &)
ResettableOnce(const ResettableOnce &)
SrcLangExt
Definition types.h:207
bool isUTF8CharUpperCase(const std::string &input, size_t pos)
Returns true iff the input string at byte position pos holds an upper case character.
Definition utf8.cpp:218
bool lastUTF8CharIsMultibyte(const std::string &input)
Returns true iff the last character in input is a multibyte character.
Definition utf8.cpp:212
Various UTF8 related helper functions.
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5214
QCString parseCommentAsHtml(const Definition *scope, const MemberDef *member, const QCString &doc, const QCString &fileName, int lineNr)
Definition util.cpp:5428
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:3967
QCString parseCommentAsText(const Definition *scope, const MemberDef *md, const QCString &doc, const QCString &fileName, int lineNr)
Definition util.cpp:5372
bool transcodeCharacterStringToUTF8(std::string &input, const char *inputEncoding)
Definition util.cpp:1456
QCString stripScope(const QCString &name)
Definition util.cpp:3783
int computeQualifiedIndex(const QCString &name)
Return the index of the last :: in the string name that is still before the first <.
Definition util.cpp:6847
QCString convertToXML(const QCString &s, bool keepEntities)
Definition util.cpp:3916
QCString detab(const QCString &s, size_t &refIndent)
Definition util.cpp:6743
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Returns the scope separator to use given the programming language lang.
Definition util.cpp:5920
QCString getEncoding(const FileInfo &fi)
Definition util.cpp:5714
QCString stripLeadingAndTrailingEmptyLines(const QCString &s, int &docLine)
Special version of QCString::stripWhiteSpace() that only strips completely blank lines.
Definition util.cpp:5033
QCString getFileFilter(const QCString &name, bool isSourceCode)
Definition util.cpp:1422
void writeMarkerList(OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
Definition util.cpp:1124
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:4925
A bunch of utility functions.
bool isId(int c)
Definition util.h:256