48struct DLHTMLFileFilter : filetree::FFilter {
51 DLHTMLFileFilter(
String& ext) : extension(ext) {}
54 return file.Name().EndsWith<CHK, lang::Case::Ignore>(extension);
58struct DLSrcFileFilter : filetree::FFilter {
59 DoxygenINIFile &doxyfile;
61 DLSrcFileFilter(DoxygenINIFile &df) : doxyfile(df) {}
64 String64 extension(file.Name().Substring(file.Name().LastIndexOf(
'.')));
65 if (doxyfile.FilePatterns.IndexOf(extension) < 0)
75 if (lhs.CountChildren() == 0 && rhs.CountChildren() != 0)
return false;
76 if (lhs.CountChildren() != 0 && rhs.CountChildren() == 0)
return true;
79 return lhs->MDate() > rhs->MDate();
83String htmlConversionCodes[] = {
95constexpr String htmlConversionChars =
"<>&'[]@$ \"";
106 bool replacementFound=
false;
115 for (; codeIdx<
integer(
sizeof(htmlConversionCodes)/
sizeof(
String)) -1; ++codeIdx) {
116 if ( actBuf.
StartsWith(htmlConversionCodes[codeIdx]) ) {
117 replacement.
_(htmlConversionChars.CharAt(codeIdx));
118 idx+= htmlConversionCodes[codeIdx].
Length();
119 replacementFound=
true;
122 if ( codeIdx ==
sizeof(htmlConversionCodes)/
sizeof(
String) )
125 if (replacementFound)
126 buffer.
Reset(replacement);
131 for (
auto c : src ) {
132 integer idx= htmlConversionChars.IndexOf(c);
133 if ( idx < 0 ) dest.
_(c);
134 else dest.
_(
'&').
_<
NC>(htmlConversionCodes[idx]);
139 for (
auto c : asciiString )
140 if ( htmlConversionChars.IndexOf(c) >= 0 )
158 if (!
TPool.IsIdle()) {
159 Lox_Warning(
"Destructing DoxygenXLinks while not idle.")
162 Lox_Error(
"DoxygenXLinks not idle after 5s. destructing nevertheless now.")
172 const String& sourceHint ) {
176 for (
auto range= index->entityMap.EqualRange(anchorName)
177 ; range.first!=range.second
180 if (
auto* docAnchor=
static_cast<TGTDocAnchor*
>(index->ImportCursor(range.first->second).Value());
182 docAnchor->Title=
String(index->ma, anchorTitle);
183 Lox_Info(
"XTRA",
"Added title to anchor {!Q} of tag-file {!Q}\n"
184 " Anchor source: {}\n"
185 " Anchor title: {!Q}"
186 , anchorName, index->FileName, sourceHint, anchorTitle )
189 Lox_Info(
"XTRA",
"Title for anchor {!Q} hinted, but anchor not found in tag-files\n"
190 " Anchor source: {}\n"
191 " Anchor title: {!Q}"
192 , anchorName, sourceHint, anchorTitle )
201 Lox_Info(
"Scanning Doxygen's output folder and launching read jobs on HTML input files.\n"
202 " Maximum depth {}, File extension {!Q}, Doxygen output directory {!Q}"
208 ScanParameters::SymbolicLinks::RECURSIVE,
215 if ( scanResult == FTValue::ScanStates::NOT_EXISTENT
216 || resultPaths.empty()
217 || resultPaths.front().IsInvalid() ) {
226 Lox_Info(
"HTML file tree scanned.") {
229 if (cntLoggers > 0) {
237 rlogger->GetFormatMultiLine().Mode=3;)
240 Lox_Prune(rlogger->GetFormatMultiLine().Mode=2;)
245 Lox_Info(
"Scheduling HTMLReplacer jobs")
253 String32 omitSourceHTMLs(
"_source");
254 omitSourceHTMLs <<
Doxyfile.HtmlFileExtension;
257 if ( !treeIt.
Node()->IsDirectory()
258 && !treeIt.
Node().Name().EndsWith(omitSourceHTMLs) ) {
260 if (verbosity >= Verbosity::Info)
261 Lox_Info(
"Scheduling XLink replacement on HTML-file {!Q}",
TPool, treeIt.
Node().Name())
263 Stats.HTMLFiles.fetch_add(1);
269 auto qtyFiles =
Stats.HTMLFiles.load();
285 Lox_Info(
"Scanning Doxygen's input folders (sources).\n"
286 " Maximum depth {}, File extensions {!Q}"
296 for (
auto it:
Doxyfile.InputPaths) {
304 ScanParameters::SymbolicLinks::RECURSIVE,
312 Lox_Info(
"Source file tree scanned.") {
315 if (cntLoggers > 0) {
323 rlogger->GetFormatMultiLine().Mode=3;)
326 Lox_Prune(rlogger->GetFormatMultiLine().Mode=2;)
331 Lox_Info(
"Scheduling source scanner jobs")
342 if ( !treeIt.
Node()->IsDirectory() ) {
344 if (verbosity >= Verbosity::Info)
345 Lox_Info(
"Scheduling XLink search on source-file {!Q}", treeIt.
Node().Name())
347 Stats.SourceFiles.fetch_add(1);
353 auto qtyFiles =
Stats.SourceFiles.load();
368 Path scanPath(folder);
374 Lox_Info(
"Scanning source copies in directory {}", folder )
377 ScanParameters::SymbolicLinks::RECURSIVE,
385 Lox_Info(
"Source copies file tree scanned.") {
388 if (cntLoggers > 0) {
396 rlogger->GetFormatMultiLine().Mode=3;)
399 Lox_Prune(rlogger->GetFormatMultiLine().Mode=2;)
404 Lox_Info(
"Scheduling source replacer jobs")
415 if ( !treeIt.
Node()->IsDirectory() ) {
417 if (verbosity >= Verbosity::Info) {
419 Lox_Info(
"Scheduling XLink-replacement on source-copy {!Q}", p)
422 Stats.ReplSourceFiles.fetch_add(1);
428 auto qtyFiles =
Stats.ReplSourceFiles.load();
432 FormatString(), folder);
445 auto* rlogger =
app.GetRLogger();
456 Lox_Info(
"Number of hardware-threads (machine spec): ", std::thread::hardware_concurrency())
459 ->Actual(AutoSizes::Types::Tabstop, 25, 0);
460 app.printConfigFileInfo(*
app.cOut);
465 Path currentDir(SystemFolders::Current);
472 app.cOut->Add(
"Doxyfile: {!ATab}:1",
app.DoxyfilePath);
487 TPool.Strategy.Mode = ThreadPool::ResizeStrategy::Modes::Fixed;
488 TPool.Strategy.WorkersMax=10;
494 fTreeHTML .DbgCriticalSections(lang::Switch::Off);
499 app.stopWatch.Sample();
507 fTreeHTML .DbgCriticalSections(lang::Switch::On);
509 for (
auto tfInfoIt=
Doxyfile.TagFiles.begin() ; tfInfoIt !=
Doxyfile.TagFiles.end() ; ++tfInfoIt) {
510 Lox_Info(
"Creating index by loading Doxygen tagfile {!Q}. Target URL: {!Q}",
511 tfInfoIt->TagFilePath, tfInfoIt->BaseURL)
515 auto tfInfoNext= tfInfoIt;
517 isLast= tfInfoNext ==
Doxyfile.TagFiles.end();
521 index =
MA().New<
Index>( tfInfoIt->TagFilePath,
534 Stats.TimeIndexAndSourceLoading=
app.stopWatch.Sample();
540 Stats.TimeHTMLReplacements=
app.stopWatch.Sample();
546 index->DbgCriticalSectionCheck(alib::lang::Switch::Off);
574 (void) restoreSources.
Define();
581 xlinkIt.second->SourceLocations.clear();
586 index->DbgCriticalSectionCheck(alib::lang::Switch::On);
590 Stats.TimeSourceReplacements=
app.stopWatch.Sample();
595 index->DbgCriticalSectionCheck(alib::lang::Switch::Off);
603 #if !defined ENABLE_LIST_OPTION
606 (void) listExpression.
Define();
608 if (listFormat.
Define()) {
609 listFormat.
GetString().
Reset(
"#{LinkString@!Q} -> \\ref {path} {Display@!Q}");
631 auto it =
XLinkMap.Find(searchString);
635 Lox_Verbose(
"New Xlink registered with #\"{}\"", searchString)
636 Stats.UniqueXLinks.fetch_add(1);
649 XLink *xLink =
nullptr;
652 auto it =
XLinkMap.Find(searchString);
656 Lox_Info(
"XLink requested that was not registered, yet: #\"{}\"", searchString)
657 Stats.UniqueXLinks.fetch_add(1);
675 if( !htmlFile.
AsCursor().IsValid() ) {
683 auto localLinkEntity=
Indices.back()->GetHTMLFileEntity(htmlFile);
684 if( !localLinkEntity.IsValid() ) {
687 Lox_Warning(
"Local link {!Q} appeared in unrecogizable file {}", searchString, fileName)
694 if (!linkAndIsNew.second)
695 return linkAndIsNew.first;
696 xLink= linkAndIsNew.first;
701 Stats.XLinksWithErrors.fetch_add(1);
702 Lox_Info(
"Error {} parsing the XLink {!Q}: {}", xLink->
Error, searchString)
712 if( !htmlFile.
AsCursor().IsValid() ) {
716 auto localLinkEntity=
Indices.back()->GetHTMLFileEntity(htmlFile);
717 if( !localLinkEntity.IsValid() ) {
720 Lox_Warning(
"Local link {!Q} appeared in unrecogizable file {}", searchString, fileName)
727 xLink= linkAndIsNew.first;
729 Stats.XLinksWithErrors.fetch_add(1);
730 Lox_Info(
"Error {} parsing the XLink {!Q}: {}", xLink->
Error, searchString)
744 index->Search(*xLink);
746 Indices.back()->Search(*xLink);
753 if ( xLink->
Targets.size() > 1 ) {
758 bool hasIndirectMemberTargets=
false;
759 bool hasTypedefTargets =
false;
760 for (
auto& result : xLink->
Targets ) {
761 hasIndirectMemberTargets |= result.IsIndirectByInheritance
762 | result.IsIndirectByTypeDef;
765 if (hasTypedefTargets && !hasIndirectMemberTargets)
766 std::erase_if(xLink->
Targets, [&](
const auto& result) {
767 return !result.Node.IsA(Target::Typedef);
773 bool hasDirectMemberTargets =
false;
774 bool hasIndirectMemberTargets=
false;
775 for (
auto& result : xLink->
Targets )
776 if ( result.IsIndirectByInheritance | result.IsIndirectByTypeDef )
777 hasIndirectMemberTargets=
true;
779 hasDirectMemberTargets=
true;
781 if ( hasDirectMemberTargets && hasIndirectMemberTargets )
782 std::erase_if(xLink->
Targets, [&](
const auto& result) {
783 return result.IsIndirectByInheritance | result.IsIndirectByTypeDef;
789 bool hasNonSpecialized =
false;
790 bool hasSpecializations =
false;
791 for (
auto& result : xLink->
Targets )
792 if (
auto* rec= result.Cast<
TGTRecord>(); rec) {
793 if (rec->SpecializationArgs)
794 hasSpecializations=
true;
796 hasNonSpecialized=
true;
799 if ( hasNonSpecialized && hasSpecializations )
800 std::erase_if(xLink->
Targets, [&](
const auto& result) {
801 auto* rec= result.template Cast<TGTRecord>();
802 return rec && rec->SpecializationArgs;
808 for (
auto& result : xLink->
Targets )
811 std::erase_if(xLink->
Targets, [&](
const auto& toDelete) {
812 auto* f= toDelete.template Cast<TGTFunction>();
813 return f && f->Qualifiers.IndexOf(
"const") >= 0;
839 else if (xLink->
Targets.empty()) {
840 Stats.UnresolvedXLinks.fetch_add(1);
841 Lox_Info(
"Search for {!Q} gave no result", searchString)
847 Stats.AmbiguousXLinks.fetch_add(1);
848 Lox_Info(
"Search for {!Q} gave {} results", searchString, xLink->
Targets.size())
851bool WARNINGS_IGNORE_INDIRECTS=
false;
854 Stats.XLinksWithWarnings.fetch_add(1);
855 Lox_Info(
"XLink {!Q} has warnings", searchString)
867 int lineNo,
int colNo ) {
876 Substring fName= targetFilename.
IsEmpty() ? elLocation.Name() : targetFilename;
905 if (targetFilename.
IsEmpty()) {
909 auto it=
Indices.back()->fileMap.Find(elLocation.Name());
910 if ( it ==
Indices.back()->fileMap.end() ) {
911 if (!isELREFAnchor)
Stats.ELReplacementsUnresolved .fetch_add(1);
912 else Stats.ELREFReplacementsUnresolved.fetch_add(1);
913 Lox_Warning(
"ELDECO",
"File {!Q} not found in main index.", elLocation.Name())
919 Lox_Info(
"ELDECO",
"Found file {!Q} in main index.", elLocation.Name())
920 node=
Indices.back()->ImportCursor(it->second);
925 auto it=
Indices.back()->anchorMap.Find({elLocation.Name(), targetAnchor});
926 if ( it ==
Indices.back()->anchorMap.end() ) {
928 Lox_Warning(
"ELDECO",
"EL-Anchor of HTML file main index. Target: {}/{}#{} "
929 "HTML-Location: {0}/{}:{}:{}",
930 Indices.back()->BaseURL, elLocation.Name(), targetAnchor,
931 elLocation.Name(), lineNo, colNo )
932 if (!isELREFAnchor)
Stats.ELReplacementsUnresolved .fetch_add(1);
933 else Stats.ELREFReplacementsUnresolved.fetch_add(1);
937 node=
Indices.back()->ImportCursor(it->second);
943 size_t indexIdx= size_t(-1);
944 for (
size_t idx= 0 ; idx <
Indices.size() - (isELREFAnchor? 1 : 0) ; ++idx) {
946 if ( targetFilename.
StartsWith(index->BaseURL) ) {
948 targetFilename= targetFilename.
Substring(index->BaseURL.Length());
950 targetFilename= targetFilename.
Substring(1);
955 if ( targetAnchor.
IsEmpty() ) {
957 for (
size_t idx= 0 ; idx <
Indices.size() - (isELREFAnchor? 1 : 0) ; ++idx) {
958 if (indexIdx !=
size_t(-1) && idx != indexIdx)
962 auto it= index->fileMap.Find(targetFilename);
963 if ( it != index->fileMap.end() ) {
964 node= index->ImportCursor(it->second);
978 Lox_Warning(
"ELDECO",
"File {!Q} not found in any index.", targetFilename)
979 if (!isELREFAnchor)
Stats.ELReplacementsUnresolved .fetch_add(1);
980 else Stats.ELREFReplacementsUnresolved.fetch_add(1);
985 Lox_Info(
"ELDECO",
"Found file {!Q} in index {}:{}.", targetFilename,
991 for (
size_t idx= 0 ; idx <
Indices.size() ; ++idx) {
992 if (indexIdx !=
size_t(-1) && idx != indexIdx)
996 auto it= index->anchorMap.Find({targetFilename, targetAnchor});
997 if ( it != index->anchorMap.end() ) {
998 node= index->ImportCursor(it->second);
1005 "EL-Anchor of HTML file not found in any index. Target: {} # {} "
1006 "HTML-Location: {}/{}:{}:{}",
1007 targetFilename, targetAnchor,
1008 Indices.back()->BaseURL, elLocation.Name(), lineNo, colNo )
1009 if (!isELREFAnchor)
Stats.ELReplacementsUnresolved .fetch_add(1);
1010 else Stats.ELREFReplacementsUnresolved.fetch_add(1);
1016 Lox_Info(
"ELDECO",
"Found file/anchor {}/{}#{} in index. HTML-Location {0}/{}:{}.",
1018 elLocation.Name(), lineNo, colNo)
1022 styles.
Set( node,
false,
false );
1029 Lox_Info(
"Writing non-resolved or ambiguous XLinks. (The main output)")
1035 xLinkIt.second->WasPrinted=
false;
1040 RecentlyModifiedFirst sorter;
1045 int cntLocations = 0;
1053 Lox_Verbose(
"No unresolved XLinks found with file {}:1", treeIt.
Path())
1059 Lox_Info(
"Found {} (unique) XLinks with file {}:1",
1060 linksInSrc.size(), treeIt.
Path())
1062 bool SUPPRESS_WARNINGS=
false;
1065 for (
auto &linkInSrc: linksInSrc) {
1066 if ( !linkInSrc.XL->IsParsed() ) {
1067 Lox_Info(
"Found {} XLink #{!Q} in sources which was not evaluated yet, "
1068 "hence not found in HTML files." , linkInSrc.XL->LinkString)
1069 linkInSrc.XL->NotFoundInHTML=
true;
1072 if (linkInSrc.XL->NotFoundInHTML)
1076 XLink* xlOrCopy= linkInSrc.XL;
1084 if ( xlOrCopy->
IsGood( SUPPRESS_WARNINGS ) ) {
1085 while ((xlOrCopy= xlOrCopy->
NextLocal) !=
nullptr )
1091 Lox_Info(
"{} XLink {!ATab!Q} @ {}:{}:{}",
1092 xlOrCopy->
Targets.size() > 1 ?
"Ambiguous"
1093 : xlOrCopy->
Targets.size() == 0 ?
"Unresolved"
1096 xlOrCopy->
LinkString, treeIt.
Path(), linkInSrc.Line, linkInSrc.Column)
1103 app.cErr->PushIndent(2);
1115 for (
auto &srcLoc: linkInSrc.XL->SourceLocations)
1116 if (innerTrIt.
Node() == srcLoc.File.AsCursor()) {
1119 Lox_Info(
" @ {}:{}:{}", locationPath, srcLoc.Line, srcLoc.Column)
1120 app.cErr->Add(
"@ {}:{}:{}", locationPath, srcLoc.Line, srcLoc.Column);
1128 app.cErr->Add(
"This local XLink's HTML file: {}",
1133 app.cErr->PopIndent();
1135 while ((xlOrCopy= xlOrCopy->
NextLocal) !=
nullptr )
1147 auto cntErrs=
Stats.UnresolvedXLinks.load()
1148 +
Stats.AmbiguousXLinks.load()
1149 +
Stats.XLinksWithErrors;
1151 app.cErr->Add(
"Error summary: {} erroneous XLinks @ {} locations.", cntErrs, cntLocations
1155 if (
Stats.XLinksWithWarnings.load() > 0) {
1156 app.cErr->Add(
"Warning summary: {} XLinks with warnings."
1157 ,
Stats.XLinksWithWarnings.load() +
Stats.AmbiguousXLinks.load()
1163 if ( expressionString.
IsEmpty())
1168 app.stopWatch.Sample();
1176 app.cErr->Add(
"{}-Expressions need to evaluate to boolean or integer values.\n"
1177 " Given expression string: {!Q}\n"
1178 " Normalized expression string: {!Q}\n"
1188 Lox_Info(
"Expression sucessfully compiled:\n"
1189 " Given expression string: {!Q}\n"
1190 " Normalized expression string: {!Q}\n"
1198 app.cOut->Add(
"Attention: The given expression is constant:\n"
1199 " Given expression string: {!Q}\n"
1200 " Normalized expression string: {!Q}\n"
1201 " Optimized expression string: {!Q}"
1202 ,
app.GetName(), expressionString
1207 xLink.second->WasPrinted =
false;
1212 RecentlyModifiedFirst sorter;
1218 int cntLocations = 0;
1236 for (
auto &linkInSrc: linksInSrc) {
1238 if (linkInSrc.XL->WasPrinted)
1240 linkInSrc.XL->WasPrinted =
true;
1243 if ( !expr.
Includes(linkInSrc.XL) )
1251 dxlScope.
Xlink = linkInSrc.XL;
1254 exprFormatter.
Format(
app.cOut->Buffer, dxlScope ); }
1256 app.cOut->PushIndent(2);
1257 app.cOut->Add(
"@ {}:{}:{}",
1258 path, linkInSrc.Line, linkInSrc.Column);
1261 for (
auto &srcInLink: linkInSrc.XL->SourceLocations) {
1264 if ( srcInLink.File.AsCursor() == treeIt.
Node()
1265 && srcInLink.Line == linkInSrc.Line
1266 && srcInLink.Column == linkInSrc.Column)
1269 srcInLink.File.AssembleSymbolicPath(furtherPath, lang::Inclusion::Include);
1270 app.cOut->Add(
"@ {}:{}:{}", furtherPath, srcInLink.Line, srcInLink.Column);
1272 app.cOut->PopIndent();
1281 app.cOut->Add(
"List summery: Found {} XLinks @ {} locations that match expression {}.\n"
1282 "Query generation time: {}"
1287 ,
app.stopWatch.Sample()
1293 app.cErr->Add(
"Error parsing expression {!Q}:", expressionString);
1296 e.
Format(exceptionMsg); }
1298 app.cErr->Add(exceptionMsg);
1305 int cntSrcOnlyLinks= 0;
1307 if ( it.second->HTMLLocations.empty()
1308 || (it.second->IsLocal && !it.second->HTMLFileOfLocalLink.IsValid()) )
1311 if ( cntSrcOnlyLinks == 0)
1315 app.cErr->Add(
"Found {} unique XLinks in sources, which are not in HTML files.\n"
1316 " Note: This usually happens if the DoxygenXLinks was run twice. In other\n"
1317 " words, when doxygen was not run before running the DoxygenXLinks.\n"
1318 " Another option is that XLinks appeared in code that was not\n"
1319 " used by doxygen to write output. For example, due to preprocessor \n"
1320 " switches or because the XLink was (accidentially) located in a standard\n"
1323 " Printing the first 5:\n",
1326 app.cErr->PushIndent(2);
1328 if ( !it.second->HTMLLocations.empty()
1329 && !(it.second->IsLocal && !it.second->HTMLFileOfLocalLink.IsValid()) )
1333 app.cErr->Add(
"XLink #{!Q}", it.first );
1334 app.cErr->PushIndent(2);
1335 for (
auto& loc : it.second->SourceLocations ) {
1338 loc.File.AssembleSymbolicPath(path, lang::Inclusion::Include); }
1339 app.cErr->Add(
"@ {}:{}:{}", path, loc.Line, loc.Column );
1341 app.cErr->PopIndent();
1343 app.cErr->PopIndent();
1349 int cntHTMLOnlyLinks= 0;
1351 if ( it.second->SourceLocations.empty() )
1354 if ( cntHTMLOnlyLinks == 0)
1358 app.cErr->Add(
"Found {} unique XLinks in HTML files, which were not found in the sources.\n"
1359 " Note: This should not happen. It might indicate that {} does not read\n"
1360 " the sources rightfully. Maybe it misinterprets the doxygen INI-file.\n"
1361 " It is not allowed to create XLinks using Doxygen macros. Use the \\\\ref syntax there!\n"
1362 " In case you cannot find the reason, please report it as a bug.\n"
1363 " (If so, please include a short sample. Thank you!)\n"
1365 "Printing the first 5:\n"
1366 ,cntHTMLOnlyLinks,
app.GetName() );
1369 app.cErr->PushIndent(2);
1371 if ( !it.second->SourceLocations.empty() )
1375 app.cErr->Add(
"XLink #{!Q}" ,it.first );
1376 app.cErr->PushIndent(2);
1377 for (
auto& loc : it.second->HTMLLocations ) {
1380 loc.File.AssembleSymbolicPath(path, lang::Inclusion::Include); }
1381 app.cErr->Add(
"@ {}:{}:{}", path ,loc.Line ,loc.Column );
1383 app.cErr->PopIndent();
1385 app.cErr->PopIndent();
1393 int srcLocationsGood = 0;
1394 int htmlLocationsGood = 0;
1395 int srcLocationsWithErrors = 0;
1396 int htmlLocationsWithErrors = 0;
1397 int srcLocationsUnresolved = 0;
1398 int htmlLocationsUnresolved = 0;
1399 int srcLocationsAmbiguous = 0;
1400 int htmlLocationsAmbiguous = 0;
1401 int srcLocationsWithWarnings = 0;
1402 int htmlLocationsWithWarnings= 0;
1405 XLink& xLink= *it.second;
1406 Lox_Info(
"Dump",
"XLink found: {} {!ATab}", it.first, it.second->IsResolved())
1420 if( getStatistics.
Define() )
1421 getStatistics=
false;
1424 app.stopWatch.Sample();
1426 if (!getStatistics.
GetBool()) {
1427 app.cOut->Add(
"{} finished: {!ATab:,} XLinks replaced in {:,} html files. "
1428 "Identified {:,} locations in {:,} source files.\n"
1429 "Execution time: {}"
1432 ,
Stats.HTMLFiles.load()
1435 ,
Stats.SourceFiles.load()
1437 ,
app.stopWatch.GetCumulated()
1445 for (
int i= 1; i <
ARG_C; ++i )
1446 parameters <<
ARG_VN[i] <<
' ';
1447 app.cOut->AddMarked(
"\nStatistics of command: {} {}\n@HL= ",
app.GetName(), parameters );
1451 app.cOut->Add(
"Tag-files:\n============");
1452 app.cOut->PushIndent(2);
1453 unsigned ctdTagFiles= 0;
1456 app.cOut->Add(
"No {}: {:,6} lines read, file {!Q}, URL: {}, load time {}",
1458 index->StatCtdLines, index->FilePath, index->BaseURL, index->LoadTime);
1459 maxTagFileNameLen= std::max(maxTagFileNameLen, index->FileName.Length());
1462 std::vector<int> kindSums;
1463 kindSums.reserve(ctdTagFiles);
1466 auto& fmt=
app.cOut->Formatter;
1467 auto& buf=
app.cOut->Buffer;
1471 for (
unsigned i= 0; i< ctdTagFiles ; ++i)
1472 fmt->Format(buf,
String64(
"|{:>")._(maxTagFileNameLen)._(
"} "),
Indices.at(i)->FileName);
1474 buf <<
" ----------------";
1475 for (
unsigned tf= 0; tf< ctdTagFiles ; ++tf) {
1476 fmt->Format(buf,
"|-{!FillC-}", maxTagFileNameLen);
1477 kindSums.push_back(0);
1486 fmt->Format(buf,
" {:14} ", kind);
1487 for (
unsigned tf= 0; tf< ctdTagFiles ; ++tf) {
1488 fmt->Format(buf,
String64(
"|{:,")._(maxTagFileNameLen)._(
"} ")
1489 ,
Indices[tf]->KindStats.GetByIdx(kindIdx) );
1490 kindSums[tf]+=
Indices[tf]->KindStats.GetByIdx(kindIdx);
1495 buf <<
" ----------------";
1496 for (
unsigned tf= 0; tf< ctdTagFiles ; ++tf)
1497 fmt->Format(buf,
"|-{!FillC-}", maxTagFileNameLen);
1500 for (
unsigned i= 0; i< ctdTagFiles ; ++i)
1501 fmt->Format(buf,
String64(
"|{:,")._(maxTagFileNameLen)._(
"} "), kindSums[i]);
1504 app.cOut->PopIndent();
1508 app.cOut->Add(
"XLinks:\n============");
1509 app.cOut->PushIndent(2);
1510 app.cOut->Add(
" | Sources | HTML | Unique/Total \n"
1511 "---------------|----------|----------|--------------" );
1512 app.cOut->Add(
"XLinks |{:9,} |{:9,} |{:9,}\n"
1513 , srcLocationsGood + srcLocationsUnresolved + srcLocationsAmbiguous
1514 + srcLocationsWithErrors + srcLocationsWithWarnings
1515 , htmlLocationsGood + htmlLocationsUnresolved + htmlLocationsAmbiguous
1516 + htmlLocationsWithErrors + htmlLocationsWithWarnings
1517 ,
Stats.UniqueXLinks.load() );
1519 app.cOut->Add(
" Unresolved |{:9,} |{:9,} |{:9,}\n" , srcLocationsUnresolved,
1520 htmlLocationsUnresolved,
Stats.UnresolvedXLinks.load() );
1522 app.cOut->Add(
" Ambiguous |{:9,} |{:9,} |{:9,}\n" , srcLocationsAmbiguous,
1523 htmlLocationsAmbiguous,
Stats.AmbiguousXLinks.load() );
1525 app.cOut->Add(
" Erroneous |{:9,} |{:9,} |{:9,}\n", srcLocationsWithErrors,
1526 htmlLocationsWithErrors,
Stats.XLinksWithErrors.load() );
1528 app.cOut->Add(
" Warnings |{:9,} |{:9,} |{:9,}\n", srcLocationsWithWarnings,
1529 htmlLocationsWithWarnings,
Stats.XLinksWithWarnings.load() );
1531 app.cOut->Add(
"EL-Anchors | -/- |{:9,} |{0:9,}\n",
Stats.ELReplacements.load() );
1532 app.cOut->Add(
" Unresolved | -/- |{:9,} |{0:9,}\n",
Stats.ELReplacementsUnresolved.load());
1533 app.cOut->Add(
"ELREF-Anchors | -/- |{:9,} |{0:9,}\n",
Stats.ELREFReplacements.load() );
1534 app.cOut->Add(
" Unresolved | -/- |{:9,} |{0:9,}\n",
Stats.ELREFReplacementsUnresolved.load());
1535 app.cOut->Add(
"---------------|----------|----------|--------------\n");
1536 app.cOut->Add(
" Files |{:9,} |{:9,} |{:9,}\n",
Stats.SourceFiles.load(),
1537 Stats.HTMLFiles.load(),
Stats.SourceFiles.load() +
Stats.HTMLFiles.load() );
1538 app.cOut->Add(
" Lines |{:9,} |{:9,} |{:9,}\n",
Stats.SourceFileLines.load()
1539 ,
Stats.HTMLFileLines.load(),
Stats.SourceFileLines.load() +
Stats.HTMLFileLines.load() );
1540 app.cOut->Add(
" Size |{:>9} |{:>9} |{:>9}\n"
1545 app.cOut->Add(
" Time |{:>9} |{:>9} |{:>9}\n",
Stats.TimeIndexAndSourceLoading
1546 ,
Stats.TimeHTMLReplacements,
Stats.TimeIndexAndSourceLoading +
Stats.TimeHTMLReplacements );
1548 app.cOut->PopIndent();
1552 app.cOut->Add(
"Total Time: {}",
app.stopWatch.GetCumulated());
1558 "XLink must be of kind 'File' to be resolved from HTML file")
1560 "This method must only be called if on unresolved links")
1569 for(
auto c : name )
switch(c) {
1570 case '_': dxNameNormal <<
"__";
break;
1571 case '-': dxNameNormal <<
"_0";
break;
1572 case '.': dxNameNormal <<
"_8";
break;
1573 case ':': dxNameNormal <<
"_1";
break;
1574 case '/': dxNameNormal <<
"_2";
break;
1575 case '<': dxNameNormal <<
"_3";
break;
1576 case '>': dxNameNormal <<
"_4";
break;
1577 case '*': dxNameNormal <<
"_5";
break;
1578 case '&': dxNameNormal <<
"_6";
break;
1579 case '|': dxNameNormal <<
"_7";
break;
1580 case '!': dxNameNormal <<
"_9";
break;
1581 case ',': dxNameNormal <<
"_a";
break;
1582 default: dxNameNormal << c;
break;
1584 dxNameSource << dxNameNormal <<
"_source";
1585 dxNameNormal <<
Doxyfile.HtmlFileExtension;
1586 dxNameSource <<
Doxyfile.HtmlFileExtension;
1597 foundNormal= treeIt.
Node();
1599 foundSource= treeIt.
Node();
1604 if ( foundNormal.
AsCursor().IsInvalid() && foundSource.
AsCursor().IsInvalid() )
1614 for (
int i= 0; i < xLink.
ScopeSize(); ++i)
1616 path << xLink.
Name();
1617 if ( foundSource.
AsCursor().IsValid() )
1623 bool created= node.
AsCursor().GoToCreatedPathIfNotExistent(path, &filePathComponentTag) != 0;
1626 (foundNormal.
AsCursor().IsValid() ? foundNormal
1627 : foundSource).Name()
1632 xLink.
Targets.push_back({ node
1636 ,0,
false,
false,
false,false
#define ALIB_LOCK_SHARED_WITH(lock)
#define ALIB_CALLER_NULLED
#define ALIB_ASSERT(cond, domain)
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_ASSERT_ERROR(cond, domain,...)
#define ALIB_LOCK_WITH(lock)
#define Lox_Exception(...)
#define Lox_SetVerbosity(...)
#define Lox_SetDomain(...)
#define Lox_GetVerbosity(result,...)
#define Lox_IsActive(result,...)
void Initialize(CursorType startNode, lang::Inclusion includeStartNode)
void SetSorting(Sorter *sorter)
const TStringTree::NameType Path() const
void SetPathGeneration(lang::Switch pathGeneration)
constexpr CharacterType Separator() const noexcept
TCursor< true > ConstCursor
TCustom & GetCustomData()
bool HasCustomData() const
strings::TAString< PathCharType > & AssembleSymbolicPath(strings::TAString< PathCharType > &target, lang::Inclusion includeFilename) const
TAString & InsertAt(const TString< TChar > &src, integer pos)
void DbgDisableBufferReplacementWarning()
constexpr integer Length() const
constexpr bool IsEmpty() const
bool EndsWith(const TString &needle) const
TChar CharAt(integer idx) const
constexpr bool IsNotEmpty() const
integer IndexOf(const TString &needle, integer startIdx=0, integer endIdx=strings::MAX_LEN) const
integer LastIndexOf(TChar needle, integer startIndex=MAX_LEN) const
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
bool StartsWith(const TString &needle) const
static bool IsAbsolute(const PathString &path)
bool Define(Priority requestedPriority=Priority::Standard)
alib::String GetExpressionString()
bool Includes(XLink *xLink)
alib::String GetOptimizedString()
XLink * GetXLink(alib::String &searchString, const alib::filetree::FTFile &htmlFile)
Statistics Stats
Statistics collected during the execution and printed when verbose output is requested.
alib::FTree & GetHTMLTree()
alib::SharedFTree fTreeSources
The file tree used for reading the source files.
void scanHTMLFiles()
Scans the HTML input file tree.
ExclamationFile Exclamations
void scanReplSrcFiles(const alib::String &folder)
alib::SharedFTree fTreeHTML
The file tree used for reading the html files.
void Run()
The main method of this main class of project DoxygenXLinks.
void listLinks(const alib::String &expressionString, const alib::String &format)
void AddAnchorTitle(const alib::String &anchorName, const alib::String &anchorTitle, const alib::String &sourceHint)
alib::CString ExclamationsPath
The path to this file. Todo: make configurable and auto-generated from app-name.
alib::SharedLock & GetHTMLTreeLock()
void writeXLinksInHTMLNotInSource()
void scheduleSrcScanners()
Launches the #"SourceLocationFinder" jobs on the #".fTreeSources;source-file tree".
void writeErrors()
Writes the non-resolved and ambiguous src links in an ordered fashion.
void schduleHTMLReplacers()
Launches the #"HTMLReplacer" jobs on the #".fTreeHTML;HTML-file tree".
alib::Verbosity verbosityGetELDecoration
Used to optimize logging speed in critical code section.
void GetELDecoration(Styles &styles, bool isELREFAnchor, alib::FTFile &elLocation, alib::String targetFilename, alib::String targetAnchor, int lineNo, int colNo)
alib::StdVectorMA< Index * > Indices
~DoxygenXLinks()
Virtual destructor.
void tryResolveHTMLTargetFile(XLink &xLink)
DoxygenXLinks()
Constructor.
alib::MonoAllocator MA
Our mono allocator.
alib::HashMap< alib::MonoAllocator, alib::String, XLink *, std::hash< alib::String >, std::equal_to< alib::String >, alib::lang::Caching::Enabled, alib::Recycling::None > XLinkMap
The set of unique XLinks found in the source and HTML files.
DoxygenINIFile Doxyfile
The Doxyfile to process.
DXLThreadPool TPool
The thread pool used to load and search the HMTL files.
alib::SharedLock & GetSourceTreeLock()
XLink * RegisterXLink(alib::String &searchString)
void writeXLinksInSourceNotInHTML()
void schduleSourceReplacers(const alib::String &folder)
alib::MonoAllocator ma
The allocator used for the parent #"StringTree" and for the hashtable in the field map.
const alib::String & BaseURL
The URL of the HTML-output created with this tag-file.
alib::PathString FilePath
The path to the doxygenTagFile.
void Load()
Loads the tag-file and creates the index.
static constexpr alib::String EL
CSS class name. See user manual chapter #"dxl_styling".
static constexpr alib::String SrcFileLine
CSS class name. See user manual chapter #"dxl_styling".
bool isFile
This set when a file is targeted by the XLink.
static constexpr alib::String Dir
CSS class name. See user manual chapter #"dxl_styling".
static constexpr alib::String SrcFile
todo: only set with EL/ELRef today.
static constexpr alib::String Module
CSS class name. See user manual chapter #"dxl_styling".
static constexpr alib::String FileOrDir
CSS class name. See user manual chapter #"dxl_styling".
bool isDir
This set when a dir is targeted by the XLink.
static constexpr alib::String ELUnknown
CSS class name. See user manual chapter #"dxl_styling".
static constexpr alib::String XLEL
CSS class name. See user manual chapter #"dxl_styling".
void Set(const Index::Node &node, bool hasDisplayText, bool isIndirect)
void Add(const alib::String &style)
Kinds
Enumerates the kinds of compounds found in a the Doxygen tagfile.
@ MAX_KIND
The highest bit defining a kind.
@ Typedef
Denotes a type definition.
@ File
Denotes a source file.
@ FILEPATH_COMPONENT
A node of a file path (not a doxygen kind).
@ RECORD
Mask to identify records types.
alib::String LinkString
The original source string.
alib::Lock Lock
The lock protecting the creation phase and as well allocator access.
alib::String & Name() const
alib::filetree::FTree::ConstCursorHandle HTMLFileOfLocalLink
The tree node of the HTML file that created this copy of the originally given local XLink.
Index::SearchResult & Result()
bool IsGood(bool ignoreIndirects)
void Parse()
Parses the given searchString and allocates the fields in the MA.
alib::StdVectorMA< Location > HTMLLocations
const alib::String & Scope(int n) const
void PrintError(alib::Paragraphs &out, const alib::String &linkString, bool suppressHints=false)
alib::StdVectorMA< Index::SearchResult > Targets
@ RestoringUnusedLocalLink
@ LocalLinkCopiedToUnrecognizableFile
@ RestoringAmbiguousLocalLink
static Index::Node ResolveTypeDef(const Index::Node &startCursor, const alib::String &origSearchString)
std::pair< XLink *, bool > GetLocalCopy(const alib::filetree::FTFile &htmlFile)
Index::ConstCursorHandle LocalLinkEntity
alib::StdVectorMA< Location > SourceLocations
Errors Error
Possible errors that occured during parsing the search string given by the user.
Target::Kinds KindSpec
Function arguments provided with the source XLink.
alib::String Qualifiers
Function qualifiers like const, or nothrow provided with the source XLink.
Target::TemplateArguments * SpecializationArgs
bool NoIndirectionWarning
int Compare(const TChar *lhs, const TChar *rhs, integer cmpLength)
FTValue::ScanStates ScanFiles(FTree &tree, ScanParameters ¶meters, CanonicalPathList *resultPaths=nullptr, Path *remainingStart=nullptr)
AString & DbgDump(AString &target, FTree &tree, EnumBitSet< FileStatus::Types > includedTypes=EnumBitSet< FileStatus::Types >(true), FTree::Cursor startNode=FTree::Cursor(), unsigned depth=(std::numeric_limits< unsigned int >::max)())
variables::Variable CampVariable(camp::Camp &camp)
lox::textlogger::TextLogger TextLogger
variables::Variable Variable
LocalString< 64 > String64
constexpr CString NEW_LINE
constexpr const String EMPTY_STRING
LocalString< 4096 > String4K
strings::TString< character > String
strings::TSubstring< character > Substring
strings::TString< PathCharType > PathString
exceptions::Exception Exception
filetree::SPFileFilter SPFileFilter
LocalString< 256 > String256
LocalString< 2048 > String2K
strings::TAString< character, lang::HeapAllocator > AString
containers::StringTreeIterator< TTree > StringTreeIterator
LocalString< 32 > String32
LocalString< 512 > String512
void ConvertASCIItoHTMLEntities(const alib::String &src, alib::AString &dest)
bool NeedsHTMLConversion(const String &asciiString)
alib::StdVectorMA< ResolvedLocation > XLinkList
void ConvertHTMLEntitiesToAscii(alib::AString &buffer)
@ NoSourceCopiesFound
No sources found with the specification given in the Doxyfile.
@ NoSourceFilesFound
No sources found with the specification given in the Doxyfile.
@ NoHTMLFilesFound
HTML files to process not found.
static constexpr unsigned InfiniteRecursion
XLink * Xlink
The link to evaluate.
The cursor type of the #"StringTree".
const alib::String & HTMLFile() const
void ReplaceTarget(class Target *newTarget)
bool IsA(Target::Kinds kind) const
Node Node
The cursor pointing to the result.
bool IsResolvedTypeDef
Set the XLink targets a type-definition and requested to resolve that.
alib::String HTMLAnchor
The HTML anchor hash. Set only with members.
XLink target information for pages.
alib::String Title
The title of the group.
XLink target information for source files.
XLink target information for C++ namespace- and member-functions.
alib::String Qualifiers
Additional qualifiers like const or nothrow.
XLink target information for C++ structs, classes and unions.