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