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 "md5hash.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 DString &df, const DString &n);
72 void setDefFileName(const DString &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 DString localName; // local (unqualified) name of the definition
93 // in the future m_name should become m_localName
96 DString ref; // reference to external documentation
97
98 bool hidden = false;
99 bool isArtificial = false;
100 bool isAnonymous = false;
101 bool isExported = false;
102
103 Definition *outerScope = nullptr; // not owner
104
105 // where the item was defined
108
109 SrcLangExt lang = SrcLangExt::Unknown;
110
111 DString id; // clang unique id
112
117 size_t defColumn;
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 DString ext = fi.extension(false);
129 if (!ext.empty()) 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;
155 isArtificial = false;
156 isExported = false;
157 lang = SrcLangExt::Unknown;
158}
159
160void DefinitionImpl::setDefFile(const DString &df,int defLine,size_t defCol)
161{
162 p->setDefFileName(df);
163 p->defLine = defLine;
164 p->defColumn = defCol;
165}
166
167//-----------------------------------------------------------------------------------------
168
170{
171 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 DString 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('*')!=DString::npos) // 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.empty()) // 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 DString &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.empty())
237 {
238 //printf("adding symbol %s\n",qPrint(symbolName));
240
242 }
243}
244
245static void removeFromMap(const DString &name,Definition *d)
246{
248}
249
251 const DString &df,int dl,size_t dc,
252 const DString &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);
264 _setDocumentation(d,df,dl,true,false);
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.empty()) return;
297 p->name = name;
298 p->isAnonymous = p->name.empty() ||
299 p->name.at(0)=='@' ||
300 p->name.find("::@")!=DString::npos;
301}
302
304{
305 if (id.empty()) 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().empty() && !AnchorGenerator::instance().isGenerated(si->label().str()))
363 {
364 //printf("write an entry!\n");
365 if (p->def->definitionType()==Definition::TypeMember) tagFile << " ";
366 DString fn = si->fileName();
368 tagFile << " <docanchor file=\"" << fn << "\"";
369 if (!si->title().empty())
370 {
371 tagFile << " title=\"" << convertToXML(si->title()) << "\"";
372 }
373 tagFile << ">" << si->label() << "</docanchor>\n";
374 }
375 }
376 }
377}
378
380{
381 // to avoid mismatches due to differences in indenting, we first remove
382 // double whitespaces...
383 DString docStr = doc.simplifyWhiteSpace();
384 DString sigStr = md5str(docStr.view());
385 //printf("%s:_docsAlreadyAdded doc='%s' sig='%s' docSigs='%s'\n",
386 // qPrint(name()),qPrint(doc),qPrint(sigStr),qPrint(sigList));
387 if (sigList.find(sigStr)==DString::npos) // new docs, add signature to prevent re-adding it
388 {
389 sigList+=DString(":")+sigStr;
390 return false;
391 }
392 else
393 {
394 return true;
396}
397
399 bool stripWhiteSpace,bool atTop)
400{
401 //printf("%s::setDocumentation(%s,%s,%d,%d)\n",qPrint(name()),d,docFile,docLine,stripWhiteSpace);
402 if (d.empty()) return;
403 DString doc = d;
404 if (stripWhiteSpace)
405 {
407 }
408 else // don't strip whitespace
409 {
410 doc=d;
411 }
412 if (!_docsAlreadyAdded(doc,p->docSignatures))
413 {
414 //printf("setting docs for %s: '%s'\n",qPrint(name()),qPrint(m_doc));
415 if (!p->details.has_value())
416 {
417 p->details = std::make_optional<DocInfo>();
418 }
419 DocInfo &details = p->details.value();
420 if (details.doc.empty()) // fresh detailed description
421 {
422 details.doc = doc;
423 }
424 else if (atTop) // another detailed description, append it to the start
425 {
426 details.doc = doc+"\n\n"+details.doc;
427 }
428 else // another detailed description, append it to the end
429 {
430 details.doc += "\n\n"+doc;
431 }
432 if (docLine!=-1) // store location if valid
433 {
434 details.file = docFile;
435 details.line = docLine;
436 }
437 else
438 {
439 details.file = docFile;
440 details.line = 1;
441 }
442 }
443}
444
446{
447 if (d.empty()) return;
449}
450
452{
453 DString brief = b;
454 brief = brief.stripWhiteSpace();
456 brief = brief.stripWhiteSpace();
457 if (brief.empty()) return;
458 size_t bl = brief.length();
459 if (bl>0)
460 {
461 if (!theTranslator || theTranslator->needsPunctuation()) // add punctuation if needed
462 {
463 int c = brief.at(bl-1);
464 switch(c)
465 {
466 case '.': case '!': case '?': case ':': break;
467 default:
468 if (isUTF8CharUpperCase(brief.str(),0) && !lastUTF8CharIsMultibyte(brief.str())) brief+='.';
469 break;
470 }
471 }
472 }
473
474 if (!_docsAlreadyAdded(brief,p->briefSignatures))
475 {
476 if (p->brief && !p->brief->doc.empty())
477 {
478 //printf("adding to details\n");
479 _setDocumentation(brief,briefFile,briefLine,false,true);
480 }
481 else
482 {
483 //fprintf(stderr,"DefinitionImpl::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine);
484 if (!p->brief.has_value())
485 {
486 p->brief = std::make_optional<BriefInfo>();
487 }
488 BriefInfo &briefInfo = p->brief.value();
489 briefInfo.doc=brief;
490 if (briefLine!=-1)
491 {
492 briefInfo.file = briefFile;
493 briefInfo.line = briefLine;
494 }
495 else
496 {
497 briefInfo.file = briefFile;
498 briefInfo.line = 1;
499 }
500 }
501 }
502 else
503 {
504 //printf("do nothing!\n");
505 }
506}
507
513
515{
516 if (!_docsAlreadyAdded(doc,p->docSignatures))
517 {
518 if (!p->inbodyDocs.has_value())
519 {
520 p->inbodyDocs = std::make_optional<DocInfo>();
521 }
522 DocInfo &inbodyDocs = p->inbodyDocs.value();
523 if (inbodyDocs.doc.empty()) // fresh inbody docs
524 {
525 inbodyDocs.doc = doc;
526 inbodyDocs.file = inbodyFile;
527 inbodyDocs.line = inbodyLine;
528 }
529 else // another inbody documentation fragment, append this to the end
530 {
531 inbodyDocs.doc += DString("\n\n")+doc;
532 }
533 }
534}
535
541
542//---------------------------------------
543
544/*! Cache for storing the result of filtering a file */
546{
547 private:
549 {
550 size_t filePos;
551 size_t fileSize;
552 };
553 using LineOffsets = std::vector<size_t>;
554
555 public:
556 static FilterCache &instance();
557
558 //! collects the part of file \a fileName starting at \a startLine and ending at \a endLine into
559 //! buffer \a str. Applies filtering if FILTER_SOURCE_FILES is enabled and the file extension
560 //! matches a filter. Caches file information so that subsequent extraction of blocks from
561 //! the same file can be performed efficiently
562 bool getFileContents(const DString &fileName,size_t startLine,size_t endLine, std::string &str)
563 {
564 bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
565 DString filter = getFileFilter(fileName,true);
566 bool usePipe = !filter.empty() && filterSourceFiles;
567 return usePipe ? getFileContentsPipe(fileName,filter,startLine,endLine,str)
568 : getFileContentsDisk(fileName,startLine,endLine,str);
569 }
570 private:
571 bool getFileContentsPipe(const DString &fileName,const DString &filter,
572 size_t startLine,size_t endLine,std::string &str)
573 {
574 std::unique_lock<std::mutex> lock(m_mutex);
575 auto it = m_cache.find(fileName.str());
576 if (it!=m_cache.end()) // cache hit: reuse stored result
577 {
578 lock.unlock();
579 auto item = it->second;
580 //printf("getFileContents(%s): cache hit\n",qPrint(fileName));
581 // file already processed, get the results after filtering from the tmp file
582 Debug::print(Debug::FilterOutput,0,"Reusing filter result for {} from {} at offset={} size={}\n",
583 fileName,Doxygen::filterDBFileName,item.filePos,item.fileSize);
584
585 auto it_off = m_lineOffsets.find(fileName.str());
586 assert(it_off!=m_lineOffsets.end());
587 auto [ startLineOffset, fragmentSize] = getFragmentLocation(it_off->second,startLine,endLine);
588 //printf("%s: existing file [%zu-%zu]->[%zu-%zu] size=%zu\n",
589 // qPrint(fileName),startLine,endLine,startLineOffset,endLineOffset,fragmentSize);
591 item.filePos+startLineOffset, fragmentSize);
592 return true;
593 }
594 else // cache miss: filter active but file not previously processed
595 {
596 //printf("getFileContents(%s): cache miss\n",qPrint(fileName));
597 // filter file
598 DString cmd=filter+" \""+fileName+"\"";
599 Debug::print(Debug::ExtCmd,0,"Executing popen(`{}`)\n",cmd);
600 FILE *f = Portable::popen(cmd,"r");
601 if (f==nullptr)
602 {
603 // handle error
604 err("Error opening filter pipe command '{}'\n",cmd);
605 return false;
606 }
608 FilterCacheItem item;
609 item.filePos = m_endPos;
610 if (bf==nullptr)
611 {
612 // handle error
613 err("Error opening filter database file {}\n",Doxygen::filterDBFileName);
615 return false;
616 }
617 // append the filtered output to the database file
618 size_t size=0;
619 while (!feof(f))
620 {
621 const int blockSize = 4096;
622 char buf[blockSize];
623 size_t bytesRead = fread(buf,1,blockSize,f);
624 size_t bytesWritten = fwrite(buf,1,bytesRead,bf);
625 if (bytesRead!=bytesWritten)
626 {
627 // handle error
628 err("Failed to write to filter database {}. Wrote {} out of {} bytes\n",
629 Doxygen::filterDBFileName,bytesWritten,bytesRead);
631 fclose(bf);
632 return false;
633 }
634 size+=bytesWritten;
635 str+=std::string_view(buf,bytesWritten);
636 }
637 item.fileSize = size;
638 // add location entry to the dictionary
639 m_cache.emplace(fileName.str(),item);
640 Debug::print(Debug::FilterOutput,0,"Storing new filter result for {} in {} at offset={} size={}\n",
641 fileName,Doxygen::filterDBFileName,item.filePos,item.fileSize);
642 // update end of file position
643 m_endPos += size;
645 fclose(bf);
646
647 // shrink buffer to [startLine..endLine] part
648 shrinkBuffer(str,fileName,startLine,endLine);
649 }
650 return true;
651 }
652
653 //! reads the fragment start at \a startLine and ending at \a endLine from file \a fileName
654 //! into buffer \a str
655 bool getFileContentsDisk(const DString &fileName,size_t startLine,size_t endLine,std::string &str)
656 {
657 std::unique_lock<std::mutex> lock(m_mutex);
658 // normal file
659 //printf("getFileContents(%s): no filter\n",qPrint(fileName));
660 auto it = m_lineOffsets.find(fileName.str());
661 if (it == m_lineOffsets.end()) // new file
662 {
663 // read file completely into str buffer
664 readFragmentFromFile(str,fileName,0);
665 // shrink buffer to [startLine..endLine] part
666 shrinkBuffer(str,fileName,startLine,endLine);
667 }
668 else // file already processed before
669 {
670 lock.unlock();
671 auto [ startLineOffset, fragmentSize] = getFragmentLocation(it->second,startLine,endLine);
672 //printf("%s: existing file [%zu-%zu] -> start=%zu size=%zu\n",
673 // qPrint(fileName),startLine,endLine,startLineOffset,fragmentSize);
674 readFragmentFromFile(str,fileName,startLineOffset,fragmentSize);
675 }
676 return true;
677 }
678
679 //! computes the starting offset for each line for file \a fileName, whose contents should
680 //! already be stored in buffer \a str.
681 void compileLineOffsets(const DString &fileName,const std::string &str)
682 {
683 // line 1 (index 0) is at offset 0
684 auto it = m_lineOffsets.emplace(fileName.data(),LineOffsets{0}).first;
685 const char *p=str.data();
686 while (*p)
687 {
688 char c=0;
689 while ((c=*p)!='\n' && c!=0) p++; // search until end of the line
690 if (c!=0) p++;
691 it->second.push_back(p-str.data());
692 }
693 }
694
695 //! Returns the byte offset and size within a file of a fragment given the array of
696 //! line offsets and the start and end line of the fragment.
697 auto getFragmentLocation(const LineOffsets &lineOffsets,
698 size_t startLine,size_t endLine) -> std::tuple<size_t,size_t>
699 {
700 assert(startLine > 0);
701 assert(startLine <= endLine);
702 const size_t startLineOffset = lineOffsets[std::min(startLine-1,lineOffsets.size()-1)];
703 const size_t endLineOffset = lineOffsets[std::min(endLine, lineOffsets.size()-1)];
704 assert(startLineOffset <= endLineOffset);
705 const size_t fragmentSize = endLineOffset-startLineOffset;
706 return std::tie(startLineOffset,fragmentSize);
707 }
708
709 //! Shrinks buffer \a str which should hold the contents of \a fileName to the
710 //! fragment starting a line \a startLine and ending at line \a endLine
711 void shrinkBuffer(std::string &str,const DString &fileName,size_t startLine,size_t endLine)
712 {
713 // compute offsets from start for each line
714 compileLineOffsets(fileName,str);
715 auto it = m_lineOffsets.find(fileName.str());
716 assert(it!=m_lineOffsets.end());
717 const LineOffsets &lineOffsets = it->second;
718 auto [ startLineOffset, fragmentSize] = getFragmentLocation(lineOffsets,startLine,endLine);
719 //printf("%s: new file [%zu-%zu]->[%zu-%zu] size=%zu\n",
720 // qPrint(fileName),startLine,endLine,startLineOffset,endLineOffset,fragmentSize);
721 str.erase(0,startLineOffset);
722 str.resize(fragmentSize);
723 }
724
725 //! Reads the fragment start at byte offset \a startOffset of file \a fileName into buffer \a str.
726 //! Result will be a null terminated. If size==0 the whole file will be read and startOffset is ignored.
727 //! If size>0, size bytes will be read.
728 void readFragmentFromFile(std::string &str,const DString &fileName,size_t startOffset,size_t size=0)
729 {
730 std::ifstream ifs = Portable::openInputStream(fileName,true,true);
731 if (size==0) { startOffset=0; size = static_cast<size_t>(ifs.tellg()); }
732 ifs.seekg(startOffset, std::ios::beg);
733 str.resize(size);
734 ifs.read(str.data(), size);
735 }
736
738 std::unordered_map<std::string,FilterCacheItem> m_cache;
739 std::unordered_map<std::string,LineOffsets> m_lineOffsets;
740 std::mutex m_mutex;
741 size_t m_endPos;
742};
743
745{
746 static FilterCache theInstance;
747 return theInstance;
748}
749
750//-----------------------------------------
751
752
753/*! Reads a fragment of code from file \a fileName starting at
754 * line \a startLine and ending at line \a endLine (inclusive). The fragment is
755 * stored in \a result. If false is returned the code fragment could not be
756 * found.
757 *
758 * The file is scanned for a opening bracket ('{') from \a startLine onward
759 * The line actually containing the bracket is returned via startLine.
760 * The file is scanned for a closing bracket ('}') from \a endLine backward.
761 * The line actually containing the bracket is returned via endLine.
762 * Note that for VHDL code the bracket search is not done.
763 */
764bool readCodeFragment(const DString &fileName,bool isMacro,
765 int &startLine,int &endLine,DString &result)
766{
767 bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
768 DString filter = getFileFilter(fileName,true);
769 bool usePipe = !filter.empty() && filterSourceFiles;
770 int tabSize = Config_getInt(TAB_SIZE);
771 SrcLangExt lang = getLanguageFromFileName(fileName);
772 const int blockSize = 4096;
773 std::string str;
775 static_cast<size_t>(std::max(1,startLine)),
776 static_cast<size_t>(std::max({1,startLine,endLine})),str);
777 //printf("readCodeFragment(%s,startLine=%d,endLine=%d)=\n[[[\n%s]]]\n",qPrint(fileName),startLine,endLine,qPrint(str));
778
779 bool found = lang==SrcLangExt::VHDL ||
780 lang==SrcLangExt::Python ||
781 lang==SrcLangExt::Fortran ||
782 isMacro;
783 // for VHDL, Python, and Fortran no bracket search is possible
784 char *p=str.data();
785 if (p && *p)
786 {
787 char c=0;
788 int col=0;
789 int lineNr=startLine;
790 // skip until the opening bracket or lonely : is found
791 char cn=0;
792 while (*p && !found)
793 {
794 int pc=0;
795 while ((c=*p++)!='{' && c!=':' && c!='=' && c!=0)
796 {
797 //printf("parsing char '%c'\n",c);
798 if (c=='\n')
799 {
800 lineNr++;
801 col = 0;
802 }
803 else if (c=='\t')
804 {
805 col+=tabSize - (col%tabSize);
806 }
807 else if (pc=='/' && c=='/') // skip single line comment
808 {
809 while ((c=*p++)!='\n' && c!=0);
810 if (c == '\n')
811 {
812 lineNr++;
813 col = 0;
814 }
815 }
816 else if (pc=='/' && c=='*') // skip C style comment
817 {
818 while (((c=*p++)!='/' || pc!='*') && c!=0)
819 {
820 if (c == '\n')
821 {
822 lineNr++;
823 col = 0;
824 }
825 pc=c;
826 }
827 }
828 else
829 {
830 col++;
831 }
832 pc = c;
833 }
834 if (c==':')
835 {
836 cn=*p++;
837 if (cn!=':') found=true;
838 }
839 else if (c=='=')
840 {
841 cn=*p++;
842 if (cn=='>') // C# Expression body
843 {
844 found=true;
845 }
846 }
847 else if (c=='{')
848 {
849 found=true;
850 }
851 else if (c==0)
852 {
853 break;
854 }
855 }
856 //printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr);
857 if (found)
858 {
859 // For code with more than one line,
860 // fill the line with spaces until we are at the right column
861 // so that the opening brace lines up with the closing brace
862 if (endLine!=startLine)
863 {
864 DString spaces;
865 spaces.fill(' ',col);
866 result+=spaces;
867 }
868 // copy until end of line
869 if (c) result+=c;
870 startLine=lineNr;
871 if (c==':' || c=='=')
872 {
873 result+=cn;
874 if (cn=='\n') lineNr++;
875 }
876 char lineStr[blockSize];
877 do
878 {
879 //printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine);
880 int size_read=0;
881 do
882 {
883 // read up to blockSize-1 non-zero characters
884 int i=0;
885 while ((c=*p) && i<blockSize-1)
886 {
887 lineStr[i++]=c;
888 p++;
889 if (c=='\n') break; // stop at end of the line
890 }
891 lineStr[i]=0;
892 size_read=i;
893 result+=lineStr; // append line to the output
894 } while (size_read == (blockSize-1)); // append more if line does not fit in buffer
895 lineNr++;
896 } while (*p);
897
898 // strip stuff after closing bracket
899 size_t newLineIndex = result.rfind('\n');
900 size_t braceIndex = result.rfind('}');
901 if (newLineIndex!=DString::npos && braceIndex!=DString::npos && braceIndex > newLineIndex)
902 {
903 result.resize(braceIndex+1);
904 }
905 endLine=lineNr-1;
906 }
907 if (usePipe)
908 {
909 Debug::print(Debug::FilterOutput, 0, "Filter output\n");
910 Debug::print(Debug::FilterOutput,0,"-------------\n{}\n-------------\n",result);
911 }
912 }
913 DString encoding = getEncoding(FileInfo(fileName.str()));
914 if (encoding!="UTF-8")
915 {
916 std::string encBuf = result.str();
917 bool ok = transcodeCharacterStringToUTF8(encBuf,encoding.data());
918 if (ok)
919 {
920 result = encBuf;
921 }
922 else
923 {
924 err("failed to transcode characters in code fragment in file {} lines {} to {}, from input encoding {} to UTF-8\n",
925 fileName,startLine,endLine,encoding);
926
927 }
928 }
929 if (!result.empty() && result.at(result.length()-1)!='\n') result += "\n";
930 //printf("readCodeFragment(%d-%d)=%s\n",startLine,endLine,qPrint(result));
931 return found;
932}
933
935{
936 ASSERT(p->def->definitionType()!=Definition::TypeFile); // file overloads this method
937 DString fn;
938 bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
939 if (sourceBrowser &&
940 p->body && p->body->startLine!=-1 && p->body->fileDef)
941 {
942 fn = p->body->fileDef->getSourceFileBase();
943 }
944 return fn;
945}
946
948{
949 const int maxAnchorStrLen = 20;
950 char anchorStr[maxAnchorStrLen];
951 anchorStr[0]='\0';
952 if (p->body && p->body->startLine!=-1)
953 {
954 if (Htags::useHtags)
955 {
956 snprintf(anchorStr,maxAnchorStrLen,"L%d",p->body->defLine);
957 }
958 else
959 {
960 snprintf(anchorStr,maxAnchorStrLen,"l%05d",p->body->defLine);
961 }
962 }
963 return anchorStr;
964}
965
966/*! Write a reference to the source code defining this definition */
968{
969 //printf("DefinitionImpl::writeSourceRef %d %p\n",bodyLine,bodyDef);
971 if (!fn.empty())
972 {
974 size_t lineMarkerPos = refText.find("@0");
975 size_t fileMarkerPos = refText.find("@1");
976 if (lineMarkerPos!=DString::npos && fileMarkerPos!=DString::npos) // should always pass this.
977 {
978 DString lineStr;
979 lineStr.sprintf("%d",p->body->defLine);
980 DString anchorStr = getSourceAnchor();
981 ol.startParagraph("definition");
982 if (lineMarkerPos<fileMarkerPos) // line marker before file marker
983 {
984 // write text left from linePos marker
985 ol.parseText(refText.left(lineMarkerPos));
986 ol.writeObjectLink(DString(),fn,anchorStr,lineStr);
987 // write text between markers
988 ol.parseText(refText.mid(lineMarkerPos+2,fileMarkerPos-lineMarkerPos-2));
989 // write file link
990 ol.writeObjectLink(DString(),fn,DString(),p->body->fileDef->name());
991 // write text right from file marker
992 ol.parseText(refText.mid(fileMarkerPos+2));
993 }
994 else // file marker before line marker
995 {
996 // write text left from file marker
997 ol.parseText(refText.left(fileMarkerPos));
998 // write file link
999 ol.writeObjectLink(DString(),fn,DString(),p->body->fileDef->name());
1000 // write text between markers
1001 ol.parseText(refText.mid(fileMarkerPos+2,lineMarkerPos-fileMarkerPos-2));
1002 // write line link
1003 ol.writeObjectLink(DString(),fn,anchorStr,lineStr);
1004 // write text right from linePos marker
1005 ol.parseText(refText.mid(lineMarkerPos+2));
1006 }
1007 ol.endParagraph();
1008 }
1009 else
1010 {
1011 err("translation error: invalid markers in trDefinedAtLineInSourceFile()\n");
1012 }
1013 }
1014}
1015
1016void DefinitionImpl::setBodySegment(int defLine, int bls,int ble)
1017{
1018 if (!p->body.has_value())
1019 {
1020 p->body = std::make_optional<BodyInfo>();
1021 }
1022 BodyInfo &body = p->body.value();
1023 body.defLine = defLine;
1024 body.startLine = bls;
1025 body.endLine = ble;
1026}
1027
1029{
1030 if (!p->body.has_value())
1031 {
1032 p->body = std::make_optional<BodyInfo>();
1033 }
1034 p->body.value().fileDef=fd;
1035}
1036
1038{
1039 return p->body && p->body->startLine!=-1 &&
1040 p->body->endLine>=p->body->startLine &&
1041 p->body->fileDef;
1042}
1043
1044/*! Write code of this definition into the documentation */
1046{
1047 const MemberDef *thisMd = nullptr;
1048 if (p->def->definitionType()==Definition::TypeMember)
1049 {
1050 thisMd = toMemberDef(p->def);
1051 }
1052 bool inlineSources = thisMd && thisMd->hasInlineSource() && thisMd->initializer().empty();
1053 //printf("Source Fragment %s: %d-%d\n",qPrint(name()),
1054 // p->body->startLine,p->body->endLine);
1055 if (inlineSources && hasSources())
1056 {
1057 ol.pushGeneratorState();
1058 DString codeFragment;
1059 bool isMacro = thisMd && thisMd->memberType()==MemberType::Define;
1060 int actualStart=p->body->startLine,actualEnd=p->body->endLine;
1061 if (readCodeFragment(p->body->fileDef->absFilePath(),isMacro,
1062 actualStart,actualEnd,codeFragment)
1063 )
1064 {
1065 //printf("Adding code fragment '%s' ext='%s' range=%d-%d\n",
1066 // qPrint(codeFragment),qPrint(p->defFileExt),actualStart,actualEnd);
1067 auto intf = Doxygen::parserManager->getCodeParser(p->defFileExt);
1068 intf->resetCodeParserState();
1069 //printf("Read:\n'%s'\n\n",qPrint(codeFragment));
1070
1071 auto &codeOL = ol.codeGenerators();
1072 codeOL.startCodeFragment("DoxyCode");
1073 size_t indent = 0;
1074 intf->parseCode(codeOL, // codeOutIntf
1075 scopeName, // scope
1076 detab(codeFragment,indent), // input
1077 p->lang, // lang
1078 Config_getBool(STRIP_CODE_COMMENTS),
1080 .setFileDef(p->body->fileDef)
1081 .setStartLine(actualStart)
1082 .setEndLine(actualEnd)
1083 .setInlineFragment(true)
1084 .setMemberDef(thisMd)
1085 );
1086 codeOL.endCodeFragment("DoxyCode");
1087 }
1088 ol.popGeneratorState();
1089 }
1090}
1091
1092static inline MemberVector refMapToVector(const std::unordered_map<std::string,MemberDef *> &map)
1093{
1094 // convert map to a vector of values
1095 MemberVector result;
1096 std::transform(map.begin(),map.end(), // iterate over map
1097 std::back_inserter(result), // add results to vector
1098 [](const auto &item)
1099 { return item.second; } // extract value to add from map Key,Value pair
1100 );
1101 // and sort it
1102 std::stable_sort(result.begin(),result.end(),
1103 [](const auto &m1,const auto &m2) { return genericCompareMembers(m1,m2)<0; });
1104 return result;
1105}
1106
1107/*! Write a reference to the source code fragments in which this
1108 * definition is used.
1109 */
1111 const DString &text,const std::unordered_map<std::string,MemberDef *> &membersMap,
1112 bool /*funcOnly*/) const
1113{
1114 if (!membersMap.empty())
1115 {
1116 auto members = refMapToVector(membersMap);
1117
1118 auto replaceFunc = [this,&members,scopeName,&ol](size_t entryIndex)
1119 {
1120 bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1121 bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE);
1122 const MemberDef *md=members[entryIndex];
1123 if (md)
1124 {
1125 DString scope=md->getScopeString();
1126 DString name=md->name();
1127 //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),qPrint(scope),scopeName);
1128 if (!scope.empty() && scope!=scopeName)
1129 {
1131 }
1132 if (!md->isObjCMethod() &&
1133 (md->isFunction() || md->isSlot() ||
1134 md->isPrototype() || md->isSignal()
1135 )
1136 )
1137 {
1138 name+="()";
1139 }
1140 if (sourceBrowser &&
1141 !(md->isLinkable() && !refLinkSource) &&
1142 md->getStartBodyLine()!=-1 &&
1143 md->getBodyDef()
1144 )
1145 {
1146 const int maxLineNrStr = 10;
1147 char anchorStr[maxLineNrStr];
1148 snprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine());
1149 //printf("Write object link to %s\n",qPrint(md->getBodyDef()->getSourceFileBase()));
1150 ol.writeObjectLink(DString(),md->getBodyDef()->getSourceFileBase(),anchorStr,name);
1151 }
1152 else if (md->isLinkable())
1153 {
1155 md->getOutputFileBase(),
1156 md->anchor(),name);
1157 }
1158 else
1159 {
1160 ol.docify(name);
1161 }
1162 }
1163 };
1164
1165 ol.startParagraph("reference");
1166 ol.parseText(text);
1167 ol.docify(" ");
1168 writeMarkerList(ol,
1169 theTranslator->trWriteList(static_cast<int>(members.size())).str(),
1170 members.size(),
1171 replaceFunc);
1172 ol.writeString(".");
1173 ol.endParagraph();
1174
1175 }
1176}
1177
1179{
1180 _writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),p->sourceRefByDict,false);
1181}
1182
1184{
1185 _writeSourceRefList(ol,scopeName,theTranslator->trReferences(),p->sourceRefsDict,true);
1186}
1187
1189{
1190 if (!Config_getBool(GENERATE_REQUIREMENTS)) return;
1191 auto writeRefsForType = [&ol](const RequirementRefs &refs,const char *parType,const DString &text)
1192 {
1193 size_t num = refs.size();
1194 if (num>0)
1195 {
1196 ol.startParagraph(parType);
1197 ol.parseText(text);
1198 ol.docify(" ");
1199 writeMarkerList(ol,
1200 theTranslator->trWriteList(static_cast<int>(num)).str(), num,
1201 [&refs,&ol](size_t entryIndex) { RequirementManager::instance().writeRef(ol,refs[entryIndex]); }
1202 );
1203 ol.writeString(".");
1204 ol.endParagraph();
1205 }
1206 };
1207
1208 RequirementRefs satisfiesRefs;
1209 RequirementRefs verifiesRefs;
1210 splitRequirementRefs(p->requirementRefs,satisfiesRefs,verifiesRefs);
1211 writeRefsForType(satisfiesRefs,"satisfies",theTranslator->trSatisfies(satisfiesRefs.size()==1));
1212 writeRefsForType(verifiesRefs, "verifies", theTranslator->trVerifies(verifiesRefs.size()==1));
1213}
1214
1216{
1217 return !p->sourceRefByDict.empty();
1218}
1219
1221{
1222 return !p->sourceRefsDict.empty();
1223}
1224
1226{
1227 return !p->requirementRefs.empty();
1228}
1229
1231{
1232 bool extractAll = Config_getBool(EXTRACT_ALL);
1233 //bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1234 bool hasDocs =
1235 (p->details && !p->details->doc.empty()) || // has detailed docs
1236 (p->brief && !p->brief->doc.empty()) || // has brief description
1237 (p->inbodyDocs && !p->inbodyDocs->doc.empty()) || // has inbody docs
1238 extractAll //|| // extract everything
1239 // (sourceBrowser && p->body &&
1240 // p->body->startLine!=-1 && p->body->fileDef)
1241 ; // link to definition
1242 return hasDocs;
1243}
1244
1246{
1247 bool hasDocs =
1248 (p->details && !p->details->doc.empty()) ||
1249 (p->brief && !p->brief->doc.empty()) ||
1250 (p->inbodyDocs && !p->inbodyDocs->doc.empty());
1251 return hasDocs;
1252}
1253
1255{
1256 if (md)
1257 {
1258 p->sourceRefByDict.emplace(sourceRefName.str(),md);
1259 }
1260}
1261
1263{
1264 if (md)
1265 {
1266 p->sourceRefsDict.emplace(sourceRefName.str(),md);
1267 }
1268}
1269
1271{
1272 return nullptr;
1273}
1274
1276{
1277 err("DefinitionImpl::addInnerCompound() called\n");
1278}
1279
1281{
1282 std::call_once(p->qualifiedNameOnce.flag, [this]()
1283 {
1284 //printf("start %s::qualifiedName() localName=%s\n",qPrint(name()),qPrint(p->localName));
1285 if (p->outerScope==nullptr || p->outerScope->name()=="<globalScope>")
1286 {
1287 p->qualifiedName = (p->localName=="<globalScope>") ? DString() : p->localName;
1288 }
1289 else
1290 {
1291 p->qualifiedName = p->outerScope->qualifiedName()+
1292 getLanguageSpecificSeparator(getLanguage())+
1293 p->localName;
1294 }
1295 //printf("end %s::qualifiedName()=%s\n",qPrint(name()),qPrint(p->qualifiedName));
1296 });
1297 return p->qualifiedName;
1298}
1299
1301{
1302 //printf("%s::setOuterScope(%s)\n",qPrint(name()),d?qPrint(d->name()):"<none>");
1303 Definition *outerScope = p->outerScope;
1304 bool found=false;
1305 // make sure that we are not creating a recursive scope relation.
1306 while (outerScope && !found)
1307 {
1308 found = (outerScope==d);
1309 outerScope = outerScope->getOuterScope();
1310 }
1311 if (!found)
1312 {
1313 p->qualifiedName.clear(); // flush cached scope name
1314 p->qualifiedNameOnce.reset();
1315 p->outerScope = d;
1316 }
1317 p->hidden = p->hidden || d->isHidden();
1318 assert(p->def!=p->outerScope);
1319}
1320
1322{
1323 return p->localName;
1324}
1325
1327{
1328 p->partOfGroups.push_back(gd);
1329}
1330
1332{
1333 p->xrefListItems.insert(p->xrefListItems.end(), sli.cbegin(), sli.cend());
1334}
1335
1337{
1338 p->requirementRefs.insert(p->requirementRefs.end(), rqli.cbegin(), rqli.cend());
1339}
1340
1342{
1343 auto otherXrefList = d->xrefListItems();
1344
1345 // append vectors
1346 p->xrefListItems.reserve(p->xrefListItems.size()+otherXrefList.size());
1347 p->xrefListItems.insert (p->xrefListItems.end(),
1348 otherXrefList.begin(),otherXrefList.end());
1349
1350 // sort results on itemId
1351 std::stable_sort(p->xrefListItems.begin(),p->xrefListItems.end(),
1352 [](RefItem *left,RefItem *right)
1353 { return left->id() <right->id() ||
1354 (left->id()==right->id() &&
1355 left->list()->listName() < right->list()->listName());
1356 });
1357
1358 // filter out duplicates
1359 auto last = std::unique(p->xrefListItems.begin(),p->xrefListItems.end(),
1360 [](const RefItem *left,const RefItem *right)
1361 { return left->id()==right->id() &&
1362 left->list()->listName()==right->list()->listName();
1363 });
1364 p->xrefListItems.erase(last, p->xrefListItems.end());
1365}
1366
1367int DefinitionImpl::_getXRefListId(const DString &listName) const
1368{
1369 for (const RefItem *item : p->xrefListItems)
1370 {
1371 if (item->list()->listName()==listName)
1372 {
1373 return item->id();
1374 }
1375 }
1376 return -1;
1377}
1378
1380{
1381 return p->xrefListItems;
1382}
1383
1385{
1386 return p->requirementRefs;
1387}
1388
1390{
1391 DString result;
1392 if (p->outerScope && p->outerScope!=Doxygen::globalScope)
1393 {
1394 result = p->outerScope->pathFragment();
1395 }
1396 if (p->def->isLinkable())
1397 {
1398 if (!result.empty()) result+="/";
1399 if (p->def->definitionType()==Definition::TypeGroup &&
1400 !toGroupDef(p->def)->groupTitle().empty())
1401 {
1402 result+=toGroupDef(p->def)->groupTitle();
1403 }
1404 else if (p->def->definitionType()==Definition::TypePage &&
1405 toPageDef(p->def)->hasTitle())
1406 {
1407 result+=toPageDef(p->def)->title();
1408 }
1409 else
1410 {
1411 result+=p->localName;
1412 }
1413 }
1414 else
1415 {
1416 result+=p->localName;
1417 }
1418 return result;
1419}
1420
1421//----------------------------------------------------------------------------------------
1422
1423// TODO: move to htmlgen
1424/*! Returns the string used in the footer for $navpath when
1425 * GENERATE_TREEVIEW is enabled
1426 */
1428{
1429 DString result;
1430 Definition *outerScope = getOuterScope();
1431 DString locName = localName();
1432 if (outerScope && outerScope!=Doxygen::globalScope)
1433 {
1434 result+=outerScope->navigationPathAsString();
1435 }
1436 else if (p->def->definitionType()==Definition::TypeFile &&
1437 toFileDef(p->def)->getDirDef())
1438 {
1439 result+=(toFileDef(p->def))->getDirDef()->navigationPathAsString();
1440 }
1441 result+="<li class=\"navelem\">";
1442 if (p->def->isLinkableInProject())
1443 {
1444 DString fn = p->def->getOutputFileBase();
1446 if (p->def->definitionType()==Definition::TypeGroup &&
1447 !toGroupDef(p->def)->groupTitle().empty())
1448 {
1449 DString title = parseCommentAsHtml(p->def,nullptr,toGroupDef(p->def)->groupTitle(),
1450 p->def->getDefFileName(),p->def->getDefLine());
1451 result+="<a href=\"$relpath^"+fn+"\">"+title+"</a>";
1452 }
1453 else if (p->def->definitionType()==Definition::TypePage &&
1454 toPageDef(p->def)->hasTitle())
1455 {
1456 DString title = parseCommentAsHtml(p->def,nullptr,toPageDef(p->def)->title(),
1457 p->def->getDefFileName(),p->def->getDefLine());
1458 result+="<a href=\"$relpath^"+fn+"\">"+title+"</a>";
1459 }
1460 else if (p->def->definitionType()==Definition::TypeClass)
1461 {
1462 DString name = toClassDef(p->def)->className();
1463 if (name.endsWith("-p"))
1464 {
1465 name = name.left(name.length()-2);
1466 }
1467 result+="<a href=\"$relpath^"+fn;
1468 if (!p->def->anchor().empty()) result+="#"+p->def->anchor();
1469 result+="\">"+convertToHtml(name)+"</a>";
1470 }
1471 else
1472 {
1473 result+="<a href=\"$relpath^"+fn+"\">"+
1474 convertToHtml(locName)+"</a>";
1475 }
1476 }
1477 else
1478 {
1479 result+="<b>"+convertToHtml(locName)+"</b>";
1480 }
1481 result+="</li>";
1482 return result;
1483}
1484
1485// TODO: move to htmlgen
1487{
1488 ol.pushGeneratorState();
1490
1491 DString navPath;
1492 navPath += "<div id=\"nav-path\" class=\"navpath\">\n"
1493 " <ul>\n";
1494 navPath += navigationPathAsString();
1495 navPath += " </ul>\n"
1496 "</div>\n";
1497 ol.writeNavigationPath(navPath);
1498
1499 ol.popGeneratorState();
1500}
1501
1502void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const
1503{
1504 // first check if we have anything to show or if the outline is already shown on the outline panel
1505 if (p->sectionRefs.empty() || (Config_getBool(GENERATE_TREEVIEW) && Config_getBool(PAGE_OUTLINE_PANEL))) return;
1506 // generate the embedded toc
1507 //ol.writeLocalToc(p->sectionRefs,localToc);
1508
1509 auto generateTocEntries = [this,&ol]()
1510 {
1511 for (const SectionInfo *si : p->sectionRefs)
1512 {
1513 if (si->type().isSection())
1514 {
1515 ol.startTocEntry(si);
1516 const MemberDef *md = p->def->definitionType()==Definition::TypeMember ? toMemberDef(p->def) : nullptr;
1517 const Definition *scope = p->def->definitionType()==Definition::TypeMember ? p->def->getOuterScope() : p->def;
1518 DString docTitle = si->title();
1519 if (docTitle.empty()) docTitle = si->label();
1520 ol.generateDoc(docFile(),
1522 scope,
1523 md,
1524 docTitle,
1525 DocOptions()
1526 .setIndexWords(true)
1527 .setSingleLine(true)
1528 .setSectionLevel(si->type().level())
1529 );
1530 ol.endTocEntry(si);
1531 }
1532 }
1533 };
1534
1535 if (localToc.isHtmlEnabled())
1536 {
1537 ol.pushGeneratorState();
1539 ol.startLocalToc(localToc.htmlLevel());
1540 generateTocEntries();
1541 ol.endLocalToc();
1542 ol.popGeneratorState();
1543 }
1544 if (localToc.isDocbookEnabled())
1545 {
1546 ol.pushGeneratorState();
1548 ol.startLocalToc(localToc.docbookLevel());
1549 generateTocEntries();
1550 ol.endLocalToc();
1551 ol.popGeneratorState();
1552 }
1553 if (localToc.isLatexEnabled())
1554 {
1555 ol.pushGeneratorState();
1557 ol.startLocalToc(localToc.latexLevel());
1558 // no gneerateTocEntries() needed for LaTeX
1559 ol.endLocalToc();
1560 ol.popGeneratorState();
1561 }
1562}
1563
1564//----------------------------------------------------------------------------------------
1565
1567{
1568 return p->sectionRefs;
1569}
1570
1572{
1573 return p->symbolName;
1574}
1575
1576//----------------------
1577
1579{
1580 return p->details ? p->details->doc : DString("");
1581}
1582
1584{
1585 return p->details ? p->details->line : p->brief ? p->brief->line : 1;
1586}
1587
1589{
1590 if (p->details && !p->details->file.empty()) return p->details->file;
1591 else if (p->brief && !p->brief->file.empty()) return p->brief->file;
1592 else return "<" + p->name + ">";
1593}
1594
1595//----------------------------------------------------------------------------
1596// strips w from s iff s starts with w
1597static bool stripWord(DString &s,DString w)
1598{
1599 bool success=false;
1600 if (s.left(w.length())==w)
1601 {
1602 success=true;
1603 s=s.mid(w.length());
1604 }
1605 return success;
1606}
1607
1608//----------------------------------------------------------------------------
1609// some quasi intelligent brief description abbreviator :^)
1610static DString abbreviate(const DString &s,const DString &name)
1611{
1612 DString scopelessName=name;
1613 if (size_t i=scopelessName.rfind("::"); i!=DString::npos) scopelessName=scopelessName.mid(i+2);
1614 DString result=s;
1615 result=result.stripWhiteSpace();
1616 // strip trailing .
1617 if (!result.empty() && result.at(result.length()-1)=='.')
1618 result=result.left(result.length()-1);
1619
1620 // strip any predefined prefix
1621 StringVector briefDescAbbrev = Config_getList(ABBREVIATE_BRIEF);
1622 for (const auto &p : briefDescAbbrev)
1623 {
1624 DString str = substitute(p,"$name",scopelessName); // replace $name with entity name
1625 str += " ";
1626 stripWord(result,str);
1627 }
1628
1629 // capitalize first character
1630 if (!result.empty())
1631 {
1632 char c = result[0];
1633 if (c >= 'a' && c <= 'z') result[0] += 'A' - 'a';
1634 }
1635
1636 return result;
1637}
1638
1639
1640//----------------------
1641
1643{
1644 //printf("%s::briefDescription(%d)='%s'\n",qPrint(name()),abbr,p->brief?qPrint(p->brief->doc):"<none>");
1645 return p->brief ?
1646 (abbr ? abbreviate(p->brief->doc,p->def->displayName()) : p->brief->doc) :
1647 DString("");
1648}
1649
1651{
1652 if (p->brief && p->brief->tooltip.empty() && !p->brief->doc.empty())
1653 {
1654 const MemberDef *md = p->def->definitionType()==Definition::TypeMember ? toMemberDef(p->def) : nullptr;
1655 const Definition *scope = p->def->definitionType()==Definition::TypeMember ? p->def->getOuterScope() : p->def;
1656 p->brief->tooltip = parseCommentAsText(scope,md,
1657 p->brief->doc, p->brief->file, p->brief->line);
1658 }
1659}
1660
1662{
1663 return p->brief ? p->brief->tooltip : DString();
1664}
1665
1667{
1668 return p->brief ? p->brief->line : 1;
1669}
1670
1672{
1673 return p->brief && !p->brief->file.empty() ? p->brief->file : DString("<"+p->name+">");
1674}
1675
1676//----------------------
1677
1679{
1680 return p->inbodyDocs ? p->inbodyDocs->doc : DString("");
1681}
1682
1684{
1685 return p->inbodyDocs ? p->inbodyDocs->line : 1;
1686}
1687
1689{
1690 return p->inbodyDocs && !p->inbodyDocs->file.empty() ? p->inbodyDocs->file : DString("<"+p->name+">");
1691}
1692
1693
1694//----------------------
1695
1697{
1698 return p->defFileName;
1699}
1700
1702{
1703 return p->defFileExt;
1704}
1705
1707{
1708 return p->hidden;
1709}
1710
1712{
1713 return p->def->isLinkableInProject() && !p->hidden;
1714}
1715
1717{
1718 return p->def->isLinkable() && !p->hidden;
1719}
1720
1722{
1723 return p->isArtificial;
1724}
1725
1727{
1728 return p->isExported;
1729}
1730
1732{
1733 return p->ref;
1734}
1735
1737{
1738 return !p->ref.empty();
1739}
1740
1742{
1743 return p->body ? p->body->defLine : -1;
1744}
1745
1747{
1748 return p->body ? p->body->startLine : -1;
1749}
1750
1752{
1753 return p->body ? p->body->endLine : -1;
1754}
1755
1757{
1758 return p->body ? p->body->fileDef : nullptr;
1759}
1760
1762{
1763 return p->partOfGroups;
1764}
1765
1767{
1768 for (const auto &gd : partOfGroups())
1769 {
1770 if (gd->isLinkable()) return true;
1771 }
1772 return false;
1773}
1774
1776{
1777 return p->outerScope;
1778}
1779
1780static std::mutex g_memberReferenceMutex;
1781
1783{
1784 std::lock_guard<std::mutex> lock(g_memberReferenceMutex);
1785 if (p->referencesMembers.empty() && !p->sourceRefsDict.empty())
1786 {
1787 p->referencesMembers = refMapToVector(p->sourceRefsDict);
1788 }
1789 return p->referencesMembers;
1790}
1791
1793{
1794 std::lock_guard<std::mutex> lock(g_memberReferenceMutex);
1795 if (p->referencedByMembers.empty() && !p->sourceRefByDict.empty())
1796 {
1797 p->referencedByMembers = refMapToVector(p->sourceRefByDict);
1798 }
1799 return p->referencedByMembers;
1800}
1801
1803{
1804 const DefinitionImpl *defImpl = other->toDefinitionImpl_();
1805 if (defImpl)
1806 {
1807 for (const auto &kv : defImpl->p->sourceRefsDict)
1808 {
1809 auto it = p->sourceRefsDict.find(kv.first);
1810 if (it != p->sourceRefsDict.end())
1811 {
1812 p->sourceRefsDict.insert(kv);
1813 }
1814 }
1815 }
1816}
1817
1819{
1820 const DefinitionImpl *defImpl = other->toDefinitionImpl_();
1821 if (defImpl)
1822 {
1823 for (const auto &kv : defImpl->p->sourceRefByDict)
1824 {
1825 auto it = p->sourceRefByDict.find(kv.first);
1826 if (it != p->sourceRefByDict.end())
1827 {
1828 p->sourceRefByDict.emplace(kv.first,kv.second);
1829 }
1830 }
1831 }
1832}
1833
1834
1836{
1837 p->ref=r;
1838}
1839
1841{
1842 return p->lang;
1843}
1844
1846{
1847 p->hidden = p->hidden || b;
1848}
1849
1851{
1852 p->isArtificial = b;
1853}
1854
1856{
1857 p->isExported = b;
1858}
1859
1861{
1862 p->localName=name;
1863}
1864
1866{
1867 p->lang=lang;
1868}
1869
1870
1872{
1873 p->symbolName=name;
1874}
1875
1877{
1878 return p->symbolName;
1879}
1880
1882{
1883 bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC);
1884 return !briefDescription().empty() && briefMemberDesc;
1885}
1886
1888{
1889 DString ref = getReference();
1890 if (!ref.empty())
1891 {
1892 auto it = Doxygen::tagDestinationMap.find(ref.str());
1894 {
1895 DString result(it->second);
1896 size_t l = result.length();
1897 if (!relPath.empty() && l>0 && result.at(0)=='.')
1898 { // relative path -> prepend relPath.
1899 result.prepend(relPath);
1900 l+=relPath.length();
1901 }
1902 if (l>0 && result.at(l-1)!='/') result+='/';
1903 return result;
1904 }
1905 }
1906 return relPath;
1907}
1908
1910{
1911 return p->name;
1912}
1913
1915{
1916 return p->isAnonymous;
1917}
1918
1920{
1921 return p->defLine;
1922}
1923
1925{
1926 return p->defColumn;
1927}
1928
1932
1936
1940
1941//---------------------------------------------------------------------------------
1942
1944 : m_def(def), m_scope(scope), m_symbolName(alias->_symbolName())
1945{
1946}
1947
1951
1953{
1954 //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name()));
1956 if (m_scope==nullptr)
1957 {
1959 }
1960 else
1961 {
1964 m_def->localName();
1965 }
1966}
1967
1972
1977
1979{
1980 return m_qualifiedName;
1981}
1982
1983//---------------------------------------------------------------------------------
1984
1986{
1987 return dm ? dm->toDefinition_() : nullptr;
1988}
1989
1991{
1992 return d ? d->toDefinitionMutable_() : nullptr;
1993}
1994
bool isGenerated(const std::string &anchor) const
Returns true iff anchor is one of the generated anchors.
Definition anchor.cpp:122
static AnchorGenerator & instance()
Returns the singleton instance.
Definition anchor.cpp:38
virtual DString className() const =0
Returns the name of the class including outer classes, but not including namespaces.
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:89
void resize(size_t newlen)
Definition dstring.h:214
DString()=default
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:249
DString fill(char c, size_t len)
Fills a string with a predefined character.
Definition dstring.h:283
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:323
DString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition dstring.cpp:122
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:153
std::string_view view() const
Definition dstring.h:167
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:183
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:675
DString & prepend(const char *s)
Definition dstring.h:504
size_t find(char c, size_t pos=0) const
Definition dstring.h:244
DString & sprintf(const char *format,...)
Definition dstring.cpp:29
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:342
DString left(size_t len) const
Definition dstring.h:311
const std::string & str() const
Definition dstring.h:634
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:162
bool endsWith(const char *s) const
Definition dstring.h:606
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:156
@ 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:77
DefinitionAliasImpl(Definition *def, const Definition *scope, const Definition *alias)
const Definition * m_scope
DString qualifiedName() const
virtual ~DefinitionAliasImpl()
const DString & name() const
The common base class of all entity definitions found in the sources.
Definition definition.h:77
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
virtual const RefItemVector & xrefListItems() const =0
virtual bool isLinkable() const =0
virtual const DString & name() const =0
virtual const DString & localName() const =0
virtual DefinitionMutable * toDefinitionMutable_()=0
virtual const FileDef * getBodyDef() const =0
virtual DString navigationPathAsString() const =0
virtual DString qualifiedName() const =0
virtual bool isHidden() const =0
virtual DString anchor() const =0
virtual DString getReference() const =0
virtual void _setSymbolName(const DString &name)=0
virtual Definition * getOuterScope() const =0
virtual DString getSourceFileBase() const =0
virtual int getStartBodyLine() const =0
virtual DString getOutputFileBase() const =0
virtual const DefinitionImpl * toDefinitionImpl_() const =0
friend DefinitionMutable * toDefinitionMutable(Definition *)
Private data associated with a Symbol DefinitionImpl object.
MemberVector referencesMembers
std::optional< BriefInfo > brief
void init(const DString &df, const DString &n)
void setDefFileName(const DString &df)
std::optional< BodyInfo > body
RequirementRefs requirementRefs
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 addSourceReferencedBy(MemberDef *d, const DString &sourceRefName)
const RequirementRefs & requirementReferences() const
void setBodySegment(int defLine, int bls, int ble)
void setExported(bool b)
DString pathFragment() const
int getDefLine() const
void setBriefDescription(const DString &b, const DString &briefFile, int briefLine)
bool isHidden() const
void writeSourceReffedBy(OutputList &ol, const DString &scopeName) const
void mergeRefItems(Definition *d)
bool hasRequirementRefs() const
DString navigationPathAsString() const
void writeInlineCode(OutputList &ol, const DString &scopeName) const
DefinitionImpl(Definition *def, const DString &defFileName, int defLine, size_t defColumn, const DString &name, const char *b=nullptr, const char *d=nullptr, bool isSymbol=true)
DString getSourceAnchor() const
const RefItemVector & xrefListItems() const
const Definition * findInnerCompound(const DString &name) const
void writeSummaryLinks(OutputList &) const
void setHidden(bool b)
bool isReference() const
bool isVisible() const
int briefLine() const
void _writeSourceRefList(OutputList &ol, const DString &scopeName, const DString &text, const std::unordered_map< std::string, MemberDef * > &members, bool) const
DString externalReference(const DString &relPath) const
void addSectionsToDefinition(const std::vector< const SectionInfo * > &anchorList)
bool isAnonymous() const
bool isLinkableViaGroup() const
void _setInbodyDocumentation(const DString &d, const DString &docFile, int docLine)
DString briefDescriptionAsTooltip() const
SrcLangExt getLanguage() const
DString inbodyFile() const
void addInnerCompound(Definition *d)
void setArtificial(bool b)
bool hasSourceReffedBy() const
void writeNavigationPath(OutputList &ol) const
void setRefItems(const RefItemVector &sli)
int getStartBodyLine() const
void writeSourceRefs(OutputList &ol, const DString &scopeName) const
void setOuterScope(Definition *d)
DString getDefFileName() const
DString _symbolName() const
const MemberVector & getReferencesMembers() const
void setBodyDef(const FileDef *fd)
DString symbolName() const
int docLine() const
void setDocumentation(const DString &d, const DString &docFile, int docLine, bool stripWhiteSpace=true)
DString getSourceFileBase() const
void _setBriefDescription(const DString &b, const DString &briefFile, int briefLine)
bool isArtificial() const
bool isExported() const
void setId(const DString &name)
DString id() const
void setLocalName(const DString &name)
int _getXRefListId(const DString &listName) const
void writeQuickMemberLinks(OutputList &, const MemberDef *) const
const GroupList & partOfGroups() const
bool hasUserDocumentation() const
void setReference(const DString &r)
DString docFile() const
const DString & localName() const
int inbodyLine() const
DString inbodyDocumentation() const
bool hasBriefDescription() const
bool hasSources() const
bool _docsAlreadyAdded(const DString &doc, DString &sigList)
const SectionRefs & getSectionRefs() const
DefinitionImpl & operator=(const DefinitionImpl &d)
bool isVisibleInProject() const
DString getDefFileExtension() const
DString qualifiedName() const
void _setSymbolName(const DString &name)
void makePartOfGroup(GroupDef *gd)
void setDefFile(const DString &df, int defLine, size_t defColumn)
void mergeReferencedBy(const Definition *other)
int getStartDefLine() const
DString documentation() const
void setName(const DString &name)
DString getReference() const
bool hasSourceRefs() const
void writeToc(OutputList &ol, const LocalToc &lt) const
void addSourceReferences(MemberDef *d, const DString &sourceRefName)
void writePageNavigation(OutputList &ol) const
const FileDef * getBodyDef() const
void writeSourceDef(OutputList &ol) const
void _setDocumentation(const DString &d, const DString &docFile, int docLine, bool stripWhiteSpace, bool atTop)
void setLanguage(SrcLangExt lang)
const DString & name() const
void mergeReferences(const Definition *other)
std::unique_ptr< Private > p
bool hasSections() const
size_t getDefColumn() const
void setRequirementReferences(const RequirementRefs &rqli)
bool hasDocumentation() const
void setInbodyDocumentation(const DString &d, const DString &docFile, int docLine)
DString briefDescription(bool abbreviate=false) const
Definition * getOuterScope() const
DString briefFile() const
const MemberVector & getReferencedByMembers() const
int getEndBodyLine() const
void writeDocAnchorsToTagFile(TextStream &) const
void writeRequirementRefs(OutputList &ol) const
virtual Definition * toDefinition_()=0
friend Definition * toDefinition(DefinitionMutable *)
static DString filterDBFileName
Definition doxygen.h:131
static ParserManager * parserManager
Definition doxygen.h:129
static NamespaceDefMutable * globalScope
Definition doxygen.h:121
static StringMap tagDestinationMap
Definition doxygen.h:116
static SymbolMap< Definition > * symbolMap
Definition doxygen.h:125
static ClangUsrMap * clangUsrMap
Definition doxygen.h:126
A model of a file symbol.
Definition filedef.h:99
virtual DirDef * getDirDef() const =0
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
FileInfo(const std::string &name)
Definition fileinfo.h:25
std::string extension(bool complete) const
Definition fileinfo.cpp:130
std::vector< size_t > LineOffsets
void shrinkBuffer(std::string &str, const DString &fileName, size_t startLine, size_t endLine)
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 getFileContents(const DString &fileName, size_t startLine, size_t endLine, std::string &str)
static FilterCache & instance()
size_t m_endPos
bool getFileContentsPipe(const DString &fileName, const DString &filter, size_t startLine, size_t endLine, std::string &str)
void compileLineOffsets(const DString &fileName, const std::string &str)
void readFragmentFromFile(std::string &str, const DString &fileName, size_t startOffset, size_t size=0)
std::unordered_map< std::string, FilterCacheItem > m_cache
bool getFileContentsDisk(const DString &fileName, size_t startLine, size_t endLine, std::string &str)
std::mutex m_mutex
A model of a group of symbols.
Definition groupdef.h:52
virtual DString groupTitle() const =0
const T * find(const std::string &key) const
Definition linkedmap.h:47
constexpr int docbookLevel() const noexcept
Definition types.h:662
constexpr int latexLevel() const noexcept
Definition types.h:660
constexpr bool isDocbookEnabled() const noexcept
Definition types.h:657
constexpr bool isLatexEnabled() const noexcept
Definition types.h:655
constexpr int htmlLevel() const noexcept
Definition types.h:659
constexpr bool isHtmlEnabled() const noexcept
Definition types.h:654
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
virtual bool isSignal() const =0
virtual bool isObjCMethod() const =0
virtual const DString & initializer() const =0
virtual bool isSlot() const =0
virtual bool isFunction() const =0
virtual bool hasInlineSource() const =0
virtual DString getScopeString() 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 DString &style)
Definition outputlist.h:280
Class representing a list of output generators that are written to in parallel.
Definition outputlist.h:315
void writeNavigationPath(const DString &s)
Definition outputlist.h:608
void parseText(const DString &textStr)
void startTocEntry(const SectionInfo *si)
Definition outputlist.h:748
void startParagraph(const DString &classDef=DString())
Definition outputlist.h:407
void writeObjectLink(const DString &ref, const DString &file, const DString &anchor, const DString &name)
Definition outputlist.h:439
const OutputCodeList & codeGenerators() const
Definition outputlist.h:358
void docify(const DString &s)
Definition outputlist.h:437
void writeString(const DString &text)
Definition outputlist.h:411
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 generateDoc(const DString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const DString &docStr, const DocOptions &options)
void startLocalToc(int level)
Definition outputlist.h:744
virtual bool hasTitle() const =0
virtual DString title() const =0
std::unique_ptr< CodeParserInterface > getCodeParser(const DString &extension)
Gets the interface to the parser associated with a given extension.
Definition parserintf.h:254
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
DString listName() const
Definition reflist.h:101
class that provide information about a section.
Definition section.h:58
DString fileName() const
Definition section.h:74
void setDefinition(Definition *d)
Definition section.h:83
bool generated() const
Definition section.h:75
SectionType type() const
Definition section.h:71
DString title() const
Definition section.h:70
DString ref() const
Definition section.h:72
DString label() const
Definition section.h:69
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
void remove(const DString &name, Ptr def)
Remove a symbol def from the map that was stored under key name.
Definition symbolmap.h:55
void add(const DString &name, Ptr def)
Add a symbol def into the map under key name.
Definition symbolmap.h:41
Text streaming class that buffers data.
Definition textstream.h:36
virtual DString trVerifies(bool singular)=0
virtual DString trReferences()=0
virtual DString trReferencedBy()=0
virtual DString trDefinedAtLineInSourceFile()=0
virtual bool needsPunctuation()
add punctuation at the end of a brief description when needed and supported by the language
Definition translator.h:154
virtual DString trWriteList(int numEntries)=0
virtual DString trSatisfies(bool singular)=0
ClassDef * toClassDef(Definition *d)
Class representing a regular expression.
Definition regex.h:39
Object representing the matching results.
Definition regex.h:154
#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 DString &name, Definition *d)
static bool matchExcludedSymbols(const DString &name)
static DString abbreviate(const DString &s, const DString &name)
static void addToMap(const DString &name, Definition *d)
bool readCodeFragment(const DString &fileName, bool isMacro, int &startLine, int &endLine, DString &result)
Reads a fragment from file fileName starting with line startLine and ending with line endLine.
static MemberVector refMapToVector(const std::unordered_map< std::string, MemberDef * > &map)
static bool stripWord(DString &s, DString w)
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:480
#define ASSERT(x)
Definition dstring.h:29
bool isId(int c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:884
FileDef * toFileDef(Definition *d)
Definition filedef.cpp:1966
GroupDef * toGroupDef(Definition *d)
Translator * theTranslator
Definition language.cpp:71
DString md5str(const std::string_view &str)
Definition md5hash.h:33
MemberDef * toMemberDef(Definition *d)
#define err(fmt,...)
Definition message.h:127
FILE * popen(const DString &name, const DString &type)
Definition portable.cpp:479
std::ifstream openInputStream(const DString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:659
int pclose(FILE *stream)
Definition portable.cpp:488
FILE * fopen(const DString &fileName, const DString &mode)
Definition portable.cpp:349
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:847
Definition dstring.h:902
PageDef * toPageDef(Definition *d)
Definition pagedef.cpp:519
Portable versions of functions that are platform dependent.
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:75
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
DString doc
Definition definition.h:56
DString file
Definition definition.h:59
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
DString doc
Definition definition.h:48
int line
Definition definition.h:49
DString file
Definition definition.h:50
Helper class to pass options when calling OutputList::generateDoc().
Definition docoptions.h:24
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.
DString parseCommentAsText(const Definition *scope, const MemberDef *md, const DString &doc, const DString &fileName, int lineNr)
Definition util.cpp:4561
DString stripLeadingAndTrailingEmptyLines(const DString &s, int &docLine)
Special version of DString::stripWhiteSpace() that only strips completely blank lines.
Definition util.cpp:4223
DString detab(const DString &s, size_t &refIndent)
Definition util.cpp:5796
int computeQualifiedIndex(const DString &name)
Return the index of the last :: in the string name that is still before the first <.
Definition util.cpp:5895
bool transcodeCharacterStringToUTF8(std::string &input, const char *inputEncoding)
Definition util.cpp:1086
DString stripScope(const DString &name)
Definition util.cpp:3176
DString convertToHtml(const DString &s, bool keepEntities)
Definition util.cpp:3358
DString parseCommentAsHtml(const Definition *scope, const MemberDef *member, const DString &doc, const DString &fileName, int lineNr)
Definition util.cpp:4617
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4404
DString getFileFilter(const DString &name, bool isSourceCode)
Definition util.cpp:1052
void addHtmlExtensionIfMissing(DString &fName)
Definition util.cpp:4128
DString convertToXML(const DString &s, bool keepEntities, const bool citeEntry)
Definition util.cpp:3299
DString getEncoding(const FileInfo &fi)
Definition util.cpp:4903
DString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Definition util.cpp:5080
void writeMarkerList(OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
Definition util.cpp:785
A bunch of utility functions.