Doxygen XLinks
by
V: 2511R0
Website: doxygen
Loading...
Searching...
No Matches
xlink.cpp
1//==================================================================================================
2// This implementation-file is part of DoxygenXLinks - A doxygen post-processor that allows to
3// define smarter <b>Doxygen</b>-links.
4//
5// \emoji :copyright: 2025-2026 A-Worx GmbH, Germany.
6// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#include "xlink.hpp"
9#include "target.hpp"
10#include "dxl.hpp"
12
13using namespace alib;
14using namespace std;
15
16namespace dxl {
17
18// todo: Add "?" to enable debug output: This just lists All entities found with that name.
19// Allow \? to escape the question mark.
20
22 Substring searchString= LinkString;
23
24 searchString.TrimEnd();
25 DisplayOriginalPos= searchString.Length();
26
27 // ------------------------------ consume prefixes ------------------------------
28 if (searchString.ConsumeChar<lang::Case::Sensitive, lang::Whitespaces::Trim>('^'))
30
31 char kindSpecChar= 0;
32 if ( searchString.Length() > 1 && searchString.CharAt<NC>(1) == ';') {
33 kindSpecChar= searchString.CharAt<NC>(0);
34 searchString.ConsumeChars<NC>(2);
35 }
36 if (searchString.ConsumeChar<lang::Case::Sensitive, lang::Whitespaces::Trim>('^'))
38
39 // interpret kind spec character
40 switch (tolower(kindSpecChar)) {
41 case'\0': KindSpec= Target::UNSPECIFIED; break;
42 case 'd': KindSpec= Target::Dir; break;
43 case 'f': KindSpec= Target::File; break;
44 case 'p': KindSpec= Target::Macro; break;
45 case 'n': KindSpec= Target::Namespace; break;
46 case 'o': KindSpec= Target::Concept; break;
47 case 't': KindSpec= Target::Typedef; break;
48 case 'r': KindSpec= Target::RECORD; break;
49 case 'c': KindSpec= Target::Class; break;
50 case 's': KindSpec= Target::Struct; break;
51 case 'u': KindSpec= Target::Union; break;
52 case 'e': KindSpec= Target::Enumeration; break;
53 case 'a': KindSpec= Target::EnumElement; break;
54 case 'm': KindSpec= Target::Function; break;
55 case 'v': KindSpec= Target::Variable; break;
56 default: Error= Errors::IllegalTargetKind; return;
57 }
58
59 // correct original Display position in search string (will be corrected once more)
60 DisplayOriginalPos-= searchString.Length();
61
62 // has display? If yes, cut that first from the end
63 integer displayStart= searchString.LastIndexOf(';');
64 if (displayStart>=0) {
65 DisplayOriginalPos+= displayStart + 1;
66 Substring display(searchString.Substring(displayStart + 1));
67 searchString.ConsumeCharsFromEnd(display.Length() + 1);
68 searchString.TrimEnd();
69 display.TrimEnd();
70 if (integer pos= display.IndexOf("\\\""); pos>=0) {
71 String256 tmpDisplay(display);
72 tmpDisplay.SearchAndReplace("\\\"", "\"", pos);
73 Display= String(MA, tmpDisplay);
74 }
75 else
76 Display= String(MA, display);
77 }
78 else
80
81 if (searchString.IsEmpty()) {
83 return;
84 }
85
86 // scan dir/file link
87 if (HasOneOf(KindSpec, Target::Dir|Target::File) ) {
88 String tmpScope[MAX_SCOPE_DEPTH];
89
91 scopeSize = 0;
92
93 // consume search string word by word (space separated)
94 while ( searchString.TrimStart().IsNotEmpty() ) {
95 if (scopeSize == MAX_SCOPE_DEPTH - 1) {
97 return;
98 }
99
100 //
101 String128 word;
102 if (searchString.ConsumeChar('\'')) {
103 while (searchString.IsNotEmpty()) {
104 if (searchString.ConsumeChar('\\')) {
105 if (searchString.IsNotEmpty())
106 word._<NC>(searchString.ConsumeChar());
107 continue;
108 }
109 if (searchString.ConsumeChar('\''))
110 break;
111 word._<NC>(searchString.ConsumeChar());
112 }
113 } else {
114 while (searchString.IsNotEmpty() && searchString.CharAtStart() != ' ') {
115 if (searchString.ConsumeChar('\\')) {
116 if (searchString.IsNotEmpty())
117 word._<NC>(searchString.ConsumeChar());
118 continue;
119 }
120 word._<NC>(searchString.ConsumeChar());
121 }
122 }
123
124 tmpScope[scopeSize++] = String(MA, word);
125 if (searchString.CharAtStart() == ' ')
127 }
128
130
131 // if the last component name ended with a space, we need to steal one hint and add it to the
132 // scope components.
135
136 // split the name into path components
137 ALIB_ASSERT(scopeSize == scopeHintsSize + 1, "DXL/PARSE")
138 for (;;) {
139 // find '/' or stupid windows backslash '\'
140 integer nextPos= tmpScope[scopeSize-1].IndexOfOrLength('/');
141 nextPos= std::min(nextPos, tmpScope[scopeSize-1].IndexOfOrLength('\\'));
142 if (nextPos== tmpScope[scopeSize-1].Length())
143 break;
144 tmpScope[scopeSize ]= tmpScope[scopeSize-1].Substring(nextPos + 1);
145 tmpScope[scopeSize-1]= tmpScope[scopeSize-1].Substring(0, nextPos);
146 ++scopeSize;
149 return;
150 }
151 }
152 // copy the local array to our member
153 scope= MA().NewArray<String>(scopeSize);
154 for (integer i= 0; i < scopeSize; ++i)
155 scope[i]= tmpScope[i];
156
157 return;
158 }
159
160 // ------------------------------ parse code-targets ------------------------------
161 // starts with keyword "template" ?
162 if ( searchString.StartsWith("template") ) {
163 if (searchString.CharAt(8) == ' ' ) {
164 searchString.ConsumeChars(9);
165 searchString.TrimStart();
166
167 // keyword "template " given, but no arguments -> create empty arguments
168 if (searchString.CharAtStart()!='<')
170
171 } else if (searchString.CharAt(8) == '<' ) {
172 searchString.ConsumeChars(8);
173 }
174 }
175
176 // starts with (or at least now after template keyword) template args?
177 if (searchString.CharAtStart() == '<' ) {
178 // todo: it hast to be tested
179 // - if the search string is rightfully cut
180 // - what happens if no closing '>' is given.
181 // (probably a crash. At least we got to set a parse error, which we never used, yet,
182 // an important todo. Parse errors have to be displayed in the output!)
183 // - do path hints still work? Does the XLink need to be "template<> str TString"?
185 }
186
187 // helper to read the next identifier including template params
188 auto getNextIdentiferWithTemplateArgs = [&](Substring& src, String& word) {
189 String orig= src;
190 int templateDepth= 0;
191
192 // read identifier up to template or sth different
193 if ( src.StartsWith("operator")) {
194 src.ConsumeChars(8);
195 src.TrimStart();
196 if ( !src.ConsumeString("()")
197 && !src.ConsumeString("bool") )
198 src.TrimStart("+-*/&%|~^=!<>[]");
199 } else {
200 while (isalnum(src.CharAtStart()) || src.CharAtStart() == '_')
201 src.ConsumeChar<NC>();
202
203 while (src.IsNotEmpty()) {
204 if (src.ConsumeChar('<')) {++templateDepth; continue;}
205 if (src.ConsumeChar('>') && --templateDepth == 0)
206 break;
207 if (templateDepth > 0 ) {
208 src.ConsumeChar();
209 continue;
210 }
211 break;
212 }
213 }
214
215 word= orig.Substring(0, orig.Length() - src.Length());
216 };
217
218 // read all identifiers (scope hints and scope)
219 {
220 String tmpScope[MAX_SCOPE_DEPTH];
222 scopeSize = 0;
223 IsLocal = searchString.TrimStart().ConsumeChar('.');
224if(LinkString.Equals("todo .fTreeSources;source-file tree"))
225 int todo=5;
226
227 for (;searchString.TrimStart().IsNotEmpty();) {
228 String word;
229 getNextIdentiferWithTemplateArgs(searchString, word);
230 if (word.IsEmpty()) {
231 if(searchString.CharAtStart()=='.') {
232 IsLocal= true; // this will lead to an error below: local with path hints
233 searchString.ConsumeChar();
234 continue;
235 }
236 break; // happens when non-alnum characters are given
237 }
238 if (scopeSize==MAX_SCOPE_DEPTH-1) {
240 return;
241 }
242 tmpScope[scopeSize++]= String(MA, word);
243 if (searchString.CharAtStart() == ' ')
245 else {
246 searchString.ConsumeChar('.');
247 searchString.ConsumeChar(':');
248 searchString.ConsumeChar(':');
249 }
250 }
251
252 // if the last component name ended with a space, we need to steal one hint and add it to the
253 // scope components.
256
257 // copy the local array to our member
258 if (scopeSize>0) {
259 scope= MA().NewArray<String>(scopeSize);
260 for (int i= 0; i < scopeSize; ++i)
261 scope[i]= tmpScope[i];
262 } else {
264 return;
265 }
266
267 // if a local link is given, no scope hints are accepted
268 if (IsLocal && scopeHintsSize > 0) {
270 return;
271 }
272 } // end of reading scope
273
274 // parse subscript
275 searchString.TrimStart();
276 if (searchString.ConsumeChar('[')) {
277 String128 subscript;
278 int depth= 0;
279 while ( depth > 0 || !searchString.ConsumeChar(']') ) {
280 if (searchString.ConsumeChar('[')) ++depth;
281 if (searchString.ConsumeChar(']')) --depth;
282 subscript._<NC>(searchString.ConsumeChar());
283 }
284 Subscript= String(MA, subscript);
285 searchString.TrimStart();
286 }
287
288 // parse template-specialization arguments (they come AFTER the identifier name)
289 integer templateStart= scope[scopeSize-1].IndexOf('<');
290 if (templateStart == 8 && scope[scopeSize-1].StartsWith("operator") ) {
291 if (scope[scopeSize-1].CharAt(9) == '<') // operator<<
292 templateStart= 9;
293 templateStart= scope[scopeSize-1].IndexOf('<', templateStart + 1);
294 }
295 if (templateStart>=0) {
296 Substring templateParams= scope[scopeSize-1].Substring(templateStart);
297 scope[scopeSize-1]= scope[scopeSize-1].Substring(0, templateStart);
298
300 }
301
302 // parse function arguments
303 if (searchString.CharAtStart() == '(')
305
306 // qualifiers?
307 if(searchString.Trim().IsNotEmpty())
308 Qualifiers= String( MA, searchString);
309}
310
312 // create only once
313 if ( linkToParentScope )
314 return linkToParentScope;
315
316 // create a dummy-XLink to search for possible parent nodes
317 linkToParentScope= MA().New<XLink>();
318 ALIB_DBG( linkToParentScope->MA.DbgCriticalSectionsPH->DCSLock= nullptr;)
319
320 // non-local links: create the parent scope
321 if(!IsLocal) {
322 linkToParentScope->scope= MA().NewArray<String>(scopeSize-1);
323 for (int i= 0; i < scopeSize-1; ++i)
324 linkToParentScope->scope[i]= scope[i];
325 linkToParentScope->scopeSize = scopeSize - 1;
326 linkToParentScope->scopeHintsSize= scopeHintsSize;
327
328 // search the XLink
329 for (auto* index : app::Get<DXLApp>().dxl->Indices )
330 index->Search(*linkToParentScope);
331 }
332 // local links: we can (almost) directly put the parent to the result-list of the dummy link
333 else {
334 Index* mainIndex= app::Get<DXLApp>().dxl->Indices.back();
335 Index::Node node= mainIndex->ImportNode(Index::CursorHandle{LocalLinkEntity.value});
336 bool scopeFound= true;
337 { ALIB_LOCK_SHARED_WITH(mainIndex->SLock)
338 for(int i= 0; i < scopeSize-1; ++i)
339 if(!node.AsCursor().GoToChild(Scope(i)) ) {
340 // if the child node does not exist, then we just do not add anything
341 // and no result is generated
342 scopeFound= false;
343 break;
344 }
345 }
346
347 if(scopeFound)
348 linkToParentScope->Targets.push_back({ node
349 , mainIndex->BaseURL
350 , node.HTMLFile()
352 ,false,false,false,false,false,false,false
353 });
354 }
355
356 // loop over all possible scope-parents
357 for ( Index::SearchResult& scopeParent : linkToParentScope->Targets ) {
358 // collect all parents from all possible records. This is done in a BFS per
359 // possible parent. This means, we go into the breadth, but per parent.
360 if ( auto* rec= Cast<TGTRecord>(scopeParent.Node); rec )
361 findInherited( rec->BaseTypes );
362
363 // if this scope-parent was a type definition, we follow those
364 else if ( scopeParent.Node.IsA(Target::Typedef)) {
365
366 // search final (!) target (could be chained type-defintions)
367 if ( Index::Node targetCursor= ResolveTypeDef(scopeParent.Node, LinkString);
368 !targetCursor.IsRoot() ) {
369 // great, we found the original component.
372 TypeDefinitionTargets->push_back(targetCursor);
373 }
374 }
375 } // loop over possible parents
376
377 // now we also have to add the base types of the type definition targets to the parents!
378 // (wow). But it seems like we do not need to do the opposite: Doxygen Tag files
379 // provide resolved type definitions in its list of base-types.
380 if ( TypeDefinitionTargets ) {
381 for (auto& typeDefTargetCursor : *TypeDefinitionTargets)
382 if ( auto* rec= Cast<TGTRecord>(typeDefTargetCursor); rec)
383 findInherited( rec->BaseTypes );
384 }
385
386 // logging base types found
387 if ( BaseTypes ) {
388 int cntLoggers; Lox_IsActive(cntLoggers, Verbosity::Info, "DXL/INDIRECT")
389 if (cntLoggers > 0) {
390 String1K parentLog;
391 for (auto& p : *BaseTypes)
392 parentLog << " " << p.Name() << NEW_LINE;
393 Lox_Info("DXL/INDIRECT", "Potential parents of XLink {!Q} are\n{}",
394 LinkString, parentLog)
395 }
396 }
397
398 return linkToParentScope;
399}
400
403 const alib::String& origSearchString ) {
404
405 // search final (!) target (could be chained type-defintions)
406 Index::Node typeDefCursor= startCursor;
407 for (;;) {
408 const TGTTypedef& typeDef= *Cast<TGTTypedef,NC>(typeDefCursor);
409 Lox_Info("DXL/INDIRECT", "Type definition for {} found: {}", origSearchString, typeDef.Type)
410
411 // search in indices
412 Index::Node typeDefTargetCursor;
413 for ( auto* index : app::Get<DXLApp>().dxl->Indices ) {
414 // create base type path
415 String512 typeDefPath(typeDef.Type);
416 typeDefPath.ShortenTo(typeDefPath.IndexOfOrLength('<'));
417 index->ReplaceToTreeSeparator(typeDefPath, Target::Typedef);
418 {ALIB_LOCK_SHARED_WITH(index->SLock)
419 if ( (typeDefTargetCursor= index->Root()).AsCursor().GoTo(typeDefPath).IsEmpty() )
420 break;
421 }
422 typeDefTargetCursor= index->Root();
423 }
424 // if not found, this probably is a namespace-local
425 if (typeDefTargetCursor.IsRoot()) {
426 Index::Node scopeParentCursor= typeDefCursor.Parent();
427 String512 typeDefPath(typeDef.Type);
428 typeDefPath.ShortenTo(typeDefPath.IndexOfOrLength('<'));
429 typeDefCursor.Index().ReplaceToTreeSeparator(typeDefPath, Target::Typedef);
430 {ALIB_LOCK_SHARED_WITH(typeDefCursor.Index().SLock)
431 while (!scopeParentCursor.IsRoot()) {
432 if((typeDefTargetCursor= scopeParentCursor).AsCursor().GoTo(typeDefPath).IsEmpty() )
433 break;
434 auto newScopeParentCursor= typeDefTargetCursor.Parent();
435 typeDefTargetCursor.AsCursor().GoToRoot();
436 if( newScopeParentCursor == scopeParentCursor )
437 break;
438 scopeParentCursor= newScopeParentCursor;
439 }
440 } }
441
442 if (typeDefTargetCursor.IsRoot()) {
443 Lox_Info("The type definition {!Q} was not found in the tag file {}:1. "
444 "While processing XLink {!Q}. This is probably an inherited type definition "
445 "to be resolved later",
446 typeDef.Type, typeDefCursor.Index().FilePath, origSearchString )
447 return typeDefTargetCursor;
448 }
449
450 // is again a type definition?
451 if (typeDefTargetCursor.IsA(Target::Typedef)) {
452 typeDefCursor= typeDefTargetCursor;
453 continue;
454 }
455
456 // great, we found the original component.
457 return typeDefTargetCursor;
458 } // endless loop
459}
460#include "ALib.Lang.CIMethods.H"
461
462void XLink::findInherited( const decltype(TGTRecord::BaseTypes)& bases) {
463
464 integer previousResultSize= BaseTypes ? BaseTypes->size() : 0;
465 // first add all base types (bfs approach)
466 for (auto& baseTypeName : bases) {
467
468 bool found= false;
469 for ( auto* index : app::Get<DXLApp>().dxl->Indices ) {
470 ALIB_LOCK_SHARED_WITH(index->SLock)
471
472 // create base type path
473 String512 baseTypePath(baseTypeName);
474 integer templatePos= baseTypePath.IndexOfOrLength('<');
475 baseTypePath.ShortenTo(templatePos);
476 index->ReplaceToTreeSeparator(baseTypePath, Target::RECORD);
477
478 // search
479 Index::Node baseType;
480 if ( (baseType= index->Root()).AsCursor().GoTo(baseTypePath).IsEmpty() ) {
481 if (!baseType.IsA(Target::RECORD | Target::Typedef)) {
482 Lox_Error("The specified base entity {!Q} is not a record or a type defintion, but a {}. "
483 "Detected in tag-file {!Q}",
484 baseTypePath, baseType.Kind(), index->FilePath )
485 continue;
486 }
487
488 found= true;
489 if (!BaseTypes)
491 BaseTypes->push_back(baseType);
492 }
493 }
494
495 // not found? Should not happen!
496 if (!found) {
497 Lox_Error("The specified base entity {!Q} does not exist in any tag-file.", baseTypeName)
498 }
499 }
500
501 // now search the grandparents of those that we have found (recursion)
502 if (BaseTypes) {
503 integer newResultSize= BaseTypes ? BaseTypes->size() : 0;
504 integer i= 0;
505 for ( auto& baseType : *BaseTypes ) {
506 if ( i>= previousResultSize && i < newResultSize )
508 ++i;
509 }
510 }
511}
512
514 const Index::SearchResult& result = Result();
515 Index::Node node = result.Node;
516 const Target* target = node.Target();
517
518 //-------------------- parse display ------------------
519 Substring display= Display;
520 bool starGiven = false;
521 bool addFArgs = false;
522 bool addTArgs = false;
523 bool addSubscript = false;
524 bool addType = false;
525 bool addQualifiers = false;
526 int addParents = 0;
527 for (;;) {
528 if ( display.ConsumeChar('/') ) break;
529 if ( display.ConsumeChar('<')
530 || display.ConsumeChar('>') ) { addTArgs = true; continue; }
531 if ( display.ConsumeChar('(')
532 || display.ConsumeChar(')') ) { addFArgs = true; continue; }
533 if ( display.ConsumeChar('[')
534 || display.ConsumeChar(']') ) { addSubscript = true; continue; }
535 if ( display.ConsumeChar('?') ) { addType = true; continue; }
536 if ( display.ConsumeChar('!') ) { addQualifiers = true; continue; }
537 if ( display.ConsumeChar('*') ) { starGiven = true; continue; }
538 if (isdigit(display.CharAtStart())) { addParents= display.ConsumeChar()-'0'; continue; }
539 break;
540 }
541
542 if (starGiven)
543 addFArgs= addTArgs= addSubscript= addType= addQualifiers= true;
544
545
546 //-------------------------------------- docs ----------------------------------------
547 if ( target->IsA(Target::DocAnchor | Target::Page | Target::Group) ) {
548 CSSClasses.Set(node, display.IsNotEmpty(), false );
549 const String& title= target->IsA(Target::DocAnchor) ? Cast<TGTDocAnchor, NC>(target)->Title
550 :target->IsA(Target::Page) ? Cast<TGTPage , NC>(target)->Title
551 : Cast<TGTGroup , NC>(target)->Title;
552 if (display.IsEmpty()) {
553 if ( title.IsNotEmpty() ) {
554 Display= title;
555 return;
556 }
557 if ( addParents == 0) Error= Errors::AnchorHasNoTitle;
558 else if ( addParents > 1) Error= Errors::InappropriateDisplayTweak;
559 Display= Name();
560 return;
561 }
562 if ( !display.Equals(Display))
563 Display= String(MA, display);
564 return;
565 }
566
567 //-------------------------------------- Dir/File ----------------------------------------
568 if ( target->IsA(Target::Dir | Target::File) ) {
569 if ( addFArgs | addTArgs | addSubscript | addType | addQualifiers )
571
572 CSSClasses.Set(node, display.IsNotEmpty(), false );
573 if ( display.IsNotEmpty()) {
574 if ( !display.Equals(Display))
575 Display= String(MA, display);
576 return;
577 }
578 }
579
580 //-------------------------------------- Types ----------------------------------------
581 else {
582 CSSClasses.Set( node, display.IsNotEmpty(), Result().IsIndirectByTypeDef
583 || Result().IsIndirectByInheritance
584 || Result().IsResolvedTypeDef );
585 ALIB_ASSERT(CSSClasses.Get(1).Equals("xl-entity"), "DXL/XLINK")
586
587 if ( display.IsNotEmpty() && !addFArgs && !addTArgs && !addType && addParents < 2 ) {
588 Display= display; // in case '/' was cut
589 return;
590 }
591 }
592
593 String256 newDisplay;
595
596 // add "template<...>" ? (done when * or keyword "template", or at least one
597 // template argument was given)
598 if ( auto* rec= Cast<TGTRecord>(target);
599 rec && rec->TemplateArgs) {
600 if(addTArgs || TemplateArgs ) {
601 newDisplay._("template ");
602 rec->TemplateArgs->Print(newDisplay);
603 newDisplay._<NC>(' ');
604 }
605 }
606
607 // add Type
608 if ( addType ) {
609 if ( auto* var= Cast<TGTVariable>(target); var)
610 newDisplay << var->Type << ' ';
611 if ( auto* func= Cast<TGTFunction>(target);
612 func && func->Type.IsNotEmpty()) // may be empty for constructor
613 newDisplay << func->Type << ' ';
614 }
615
616 // add parents?
617 if (addParents && !target->IsA(Target::Macro)) {
618 integer prevDisplayLength= newDisplay.Length();
619
620 // if inherited or a resolved type definition, then the originally given parent path has
621 // to be used.
623 for (int i= addParents-2 ; i>= 0; --i) {
624 int parentIdx= ScopeSize() - i -1;
625 if (parentIdx>=0){
626 newDisplay << Scope(parentIdx);
627 if (i>0)
628 newDisplay << "::";
629 }
630 else
632 }
633 } else {
634 // for some reason, the dir type in the tag file resides already in an according
635 // parent folder
636 auto n= node;
637 if(KindSpec == Target::Dir)
638 n= n.Parent();
639 auto parent= n;
640 int cntParentOverflow = 0;
641 for (; cntParentOverflow < addParents && !parent.IsRoot(); ++cntParentOverflow)
642 parent= parent.Parent();
643 if ( parent.IsRoot() && cntParentOverflow < addParents)
645 { ALIB_LOCK_SHARED_WITH(n.Index().SLock)
646 n.Parent().Path(newDisplay, parent); }
647 }
648 // parent path added? -> add a separator
649 if (prevDisplayLength != newDisplay.Length()){
650 if (HasOneOf(KindSpec, Target::Dir|Target::File))
651 newDisplay._<NC>(system::DIRECTORY_SEPARATOR);
652 else
653 newDisplay._<NC>("::");
654 }
655 }
656
657 // add name
658 newDisplay << Name();
659
660 // we add all parameters in case the user gave them 100% correct (not as hints)
661 // or qualifiers have been given.
662 // or display was set to "*"
663 if ( auto* func= Cast<TGTFunction>(target); func) {
664 if ( addFArgs
665 || addQualifiers
666 || result.FunctionArgumentMatch==4
667 || Qualifiers.IsNotEmpty() ) {
668 if ( func->Args ) func->Args->Print(newDisplay);
669 else newDisplay._("()");
670 }
671
672 // In case of qualifiers, all are added, even if just a hint was given.
673 if (addQualifiers || result.QualifiersHintMatch) {
674 newDisplay._<NC>(' ')._<NC>(func->Qualifiers);
675 // nevertheless, "noexcept" is removed. In V6501 this will be configurable :-)
676 if (newDisplay.EndsWith("noexcept") )
677 newDisplay.ShortenBy(8);
678 display.TrimEnd();
679 } }
680
681 // For prepro macros, we add all parameters in case the user just gave them
682 if ( target->IsA(Target::Macro)
683 && (Args || (addFArgs && Cast<TGTMacro,NC>(target)->Args) ) ) {
684 Cast<TGTMacro,NC>(target)->Args->Print(newDisplay);
685 }
686 // add template specialization? (done when <,>, *, or at least one specialization
687 // argument was given)
688 if ( target->IsA(Target::RECORD)
689 && Cast<TGTRecord,NC>(target)->SpecializationArgs
690 && (addTArgs || SpecializationArgs ) )
691 Cast<TGTRecord,NC>(target)->SpecializationArgs->Print(newDisplay);
692
693 // add variable subscript? (done when something matching was given)
694 if ( target->IsA(Target::Variable)
695 && (addSubscript || Subscript.IsNotNull()) )
696 newDisplay << Cast<TGTVariable,NC>(target)->Subscript;
697
698 // add file path to #define?
699 if (addParents && target->IsA(Target::Macro)) {
700 newDisplay._<NC>(" (");
701 auto parent= node;
702 int cntParentOverflow = 0;
703 for (; cntParentOverflow < addParents && !parent.IsRoot(); ++cntParentOverflow)
704 parent= parent.Parent();
705 if ( parent.IsRoot() && cntParentOverflow < addParents)
708 node.Parent().Path(newDisplay, parent);
709 newDisplay._<NC>(") ");
710 }
711
712 // finally, add what the user added to the display
713 if ( display.IsNotEmpty() )
714 newDisplay << display;
715 ConvertASCIItoHTMLEntities(newDisplay);
716 Display = String(MA, newDisplay);
717}
718
719
720#if defined(TODO_IS_NEEDED_AGAIN)
721namespace {
722//todo: Hier gehts weiter:
723//X erstmal alle fehler im ALib nun noch korrigieren
724//- dann die neuen Maps
725// - per filename
726// - per anchor aufbauen.
727//- dann das Resolving umstellen auf den echten parent, den man aus dem filenamen direkt nachschlägt
728//- Achso: Statt den filenamen zu speichern, kann man auch den Tree-node direkt im Tag-file ablegen.
729// - Das geht natĂĽrlich nur mit dem Haupt-Tagfile, also dem letzten in Indices.
730// - Dem Index also ein Flag "IsMainTagFile" geben und dem HTML-Base in den Targets eine union
731// machen: Entweder String oder exported File cursor.
732// - Dazu also als allererstes den HTML-Tree parsen, ohne notify und Job-Start. Dies trennen.
733// (oder war es da getrennt, naja, siehst du ja dann) und im Tag-file den Node suchen.
734// - Im Index::Search dann, bei ein local links sofort aufhören, wenn nicht IsMainTagFile.
735// - Dann im DXL ein feature einfügen, welches auf die Möglichkeit hinweist, dass ein Link
736// zum Local-Link gemacht werden kann. Leider kommen dann falsche source-locations heraus.
737// Da muss man am Anfang der Liste einen hübschen Erklärungstext hinzufügen.
738
739 // Converts a doxygen file name (mangled) back to the entity that the file documents
740 int parseFileScope( files::File htmlFile, String* fileScope,
741 MonoAllocator& ma, int MAX_SCOPE_DEPTH ) {
742 String256 fileName(htmlFile.Name());
743
744 // first parse the known entity types
745 integer scopeStart = fileName.StartsWith("struct") ? 6
746 : fileName.StartsWith("class") ? 5
747 : fileName.StartsWith("union") ? 5
748 : fileName.StartsWith("namespace") ? 9
749 : fileName.StartsWith("concept") ? 7
750 : -1;
751 if ( scopeStart < 0)
752 return 0;
753 fileName.ShortenTo( fileName.LastIndexOf('.') );
754
755 // replace mangled characters
756 fileName.DeleteStart(scopeStart);
757 fileName.SearchAndReplace( "_8" , "@" );
758 fileName.SearchAndReplace( "_1_1", "@" );
759 fileName.SearchAndReplace( "__" , "_" );
760
761 // parse the scope that the filename represents
762 Substring parser(fileName);
763 int scopeSize= 0;
764 while (parser.IsNotEmpty() && scopeSize < MAX_SCOPE_DEPTH )
765 fileScope[scopeSize++]= String( ma, parser.ConsumeToken('@') );
766 return scopeSize;
767 }
768}
769#endif //defined(TODO_IS_NEEDED_AGAIN)
770
771std::pair<XLink*,bool> XLink::GetLocalCopy(const File& htmlFile) {
772 // first check if a local link exists already for this file
773 auto htmlFileHandle= htmlFile.AsCursor().Export();
774 XLink* xl= this;
775 while (xl) {
776 if (xl->HTMLFileOfLocalLink == htmlFileHandle)
777 return std::make_pair(xl, false);
778 xl= xl->NextLocal;
779 }
780
781 // now either choose us (if we're still empty) or create a new one
782 if (HTMLFileOfLocalLink != 0) { //already used
783 auto* oldNext= NextLocal;
784 NextLocal= MA().New<XLink>(); ALIB_DBG(NextLocal->MA.DbgCriticalSectionsPH.Construct(nullptr));
785 NextLocal->LinkString= LinkString;
786 NextLocal->Parse();
787 NextLocal->NextLocal= oldNext;
788 xl= NextLocal;
789 } else
790 xl= this;
791
793 && xl->IsParsed()
795 && xl->scopeHintsSize == 0 , "DXL/XLINK")
796
797 // store the file.
798 xl->HTMLFileOfLocalLink= htmlFileHandle;
799 return std::make_pair(xl, true);
800}
801
802void XLink::PrintError(Paragraphs& out, const String& linkString, bool suppressHints) {
803
804 //---------------- lamda function that assembles the name of a target ----------------
805 auto printType= [&](const String& headLine, const Index::Node& targetNode, bool withPath) {
806 String512 np;
807 String32 kindName;
808 const Target* target= targetNode.Target();
809
810 // resolve kind name
811 if ( auto* rec= Cast<TGTRecord>(target);
812 rec && rec->TemplateArgs )
813 np._("template ");
814
815 bool isMember = targetNode.Parent()!=targetNode.Index().Root()
816 && !targetNode.Parent().IsA(Target::Namespace);
817 bool isConstructor= isMember
818 && targetNode.Parent().Name().Equals(Name());
819 if (target->IsA(Target::Function))
820 kindName= !isMember ? "namespace-function"
821 : isConstructor ? "constructor"
822 : "member-function";
823 else if (target->IsA(Target::Variable))
824 kindName= isMember ? "member-variable" : "namespace-variable";
825 else if ( auto* rec= Cast<TGTRecord>(target);
826 rec && rec->SpecializationArgs )
827 kindName= "specialization";
828 else if ( auto* macro= Cast<TGTMacro>(target); macro )
829 kindName= macro->Args ? "preprocessor macro"
830 : "preprocessor constant";
831 else kindName= target->Kind();
832
833 // Add type code
834 char typeCode= 0;
835 if (target->IsA(Target::Dir )) typeCode= 'D';
836 else if (target->IsA(Target::File )) typeCode= 'F';
837 else if (target->IsA(Target::Macro )) typeCode= 'P';
838 else if (target->IsA(Target::Namespace )) typeCode= 'N';
839 else if (target->IsA(Target::Concept )) typeCode= 'O';
840 else if (target->IsA(Target::Typedef )) typeCode= 'T';
841 else if (target->IsA(Target::Class )) typeCode= 'C';
842 else if (target->IsA(Target::Struct )) typeCode= 'S';
843 else if (target->IsA(Target::Union )) typeCode= 'U';
844 else if (target->IsA(Target::Enumeration )) typeCode= 'E';
845 else if (target->IsA(Target::EnumElement )) typeCode= 'A';
846 else if (target->IsA(Target::Function )) typeCode= 'M';
847 else if (target->IsA(Target::Variable )) typeCode= 'V';
848 if( typeCode) np._("(")._(typeCode)._(") ");
849
850 np._(kindName).InsertChars(' ', 10-np.Length())._<NC>(' ');
851
852 // resolve name
853 if (auto* rec= Cast<TGTRecord>(target);
854 rec && rec->TemplateArgs ) {
855 np._("template ");
856 rec->TemplateArgs->Print(np);
857 np._(' ');
858 }
859 if (withPath && !target->IsA(Target::Macro) && !targetNode.Parent().IsRoot()) {
860 String512 pathBuf;
861 {ALIB_LOCK_SHARED_WITH(targetNode.Index().SLock)
862 targetNode.Parent().Path(pathBuf); }
863 np._(pathBuf)._<NC>("::");
864 }
865
866 String name= targetNode.Name();
867 if ( target->IsA(Target::RECORD)) {
868 integer templatePos= name.IndexOfOrLength('<');
869 ALIB_DBG(assert(name.IndexOf('(')<0));
870 name= name.Substring(0, templatePos);
871 }
872 np._(name);
873
874 if (auto* rec= Cast<TGTRecord>(target); rec && rec->SpecializationArgs )
875 rec->SpecializationArgs->Print(np);
876
877 if (auto* var= Cast<TGTVariable>(target); var)
878 np << var->Subscript;
879
880 if (auto* macro= Cast<TGTMacro>(target); macro && macro->Args)
881 macro->Args->Print(np);
882
883 String256 link(targetNode.Index().BaseURL);
884 link << '/' << target->HTMLFile;
885 if (auto* mem= Cast<TGTMember>(target); mem)
886 link << '#' << mem->Anchor;
887
888 if (withPath && target->IsA(Target::Macro)) {
889 String512 pathBuf;
890 targetNode.Parent().Path(pathBuf);
891 np._<NC>(" in file: ")._<NC>(pathBuf);
892 }
893
894 //out.
895 integer oldLineWidth= out.LineWidth;
896 out.LineWidth= 0;
897 out.Add("{} {} {!ATab} {}:{} {!ATab} {} "
898 , headLine
899 , np
900 , "tag: "
901 , targetNode.Index().FilePath
902 , target->LineNo
903 , "->: "
904 , link
905 );
906 out.LineWidth= oldLineWidth;
907 }; // inner function 'printType'
908
909
910 //---------------- Error in XLink? ----------------
911 if ( Error != Errors::OK ) {
912 out.Add("XLink #{!Q} {}:", linkString, Error > Errors::WARNINGMARKER ? "is erroneous"
913 : "has a warning" );
914 out.PushIndent(2);
915 out.Add(APPCLI_CAMP.GetResource(String64("XL_ERR_")._(int(Error))) );
916 out.PopIndent();
917 return;
918 }
919
920
921 //---------------- indirection and not ^ and vice versa ----------------
922 if ( Targets.size() == 1 ) {
923
925 && !Result().IsIndirectByInheritance
926 && !Result().IsIndirectByTypeDef
927 && !Result().IsIndirectLinkToScannedHTMLSourceFile ) {
928 out.Add("Warning: XLink #{!Q} uses indirection prefix '^', while it targets a "
929 "direct member in the parent scope.\n"
930 " Hint: Remove the prefix from the XLink", linkString );
931 printType(" Target:", Result().Node, true);
932 return;
933 }
934
936 && ( Result().IsIndirectByInheritance
937 || Result().IsIndirectByTypeDef
938 || Result().IsIndirectLinkToScannedHTMLSourceFile ) ) {
939 out.Add("Warning: XLink #{!Q} has an indirect target but is not marked with the "
940 "indirection prefix '^'.",
941 linkString );
942 printType(" Target:", Result().Node, true);
943 return;
944 }
945
947 && Result().IsIndirectLinkToScannedHTMLSourceFile ) {
948 out.Add("Warning: XLink #{!Q} links to an HTML-file found in the output folder "
949 "(not the tag file)!\n"
950 "Mark this link with indirection prefix '^' (to silence this warning).",
951 linkString );
952 printType(" Target:", Result().Node, true);
953 return;
954 }
955
956 ALIB_ASSERT_WARNING(Error != Errors::OK, "DXL/XLINK",
957 "No error to print for this valid XLink \"{}\" in the sources", linkString )
958 return;
959 }
960
961 //---------------- remove from same-name-list if found in a more concrete list ----------------
962
963 std::erase_if(DidYouMeanSameName, [&](const auto& it) {
964 // remove if duplicate
965 for (auto& target : Targets)
966 if (target.Node == it)
967 return true;
968
969 // remove from other lists
970 if ( it == DidYouMeanTemplateType
971 || std::find( DidYouMeanFunctionOverload.begin(), DidYouMeanFunctionOverload.end(), it )
973 || std::find( DidYouMeanVariable .begin(), DidYouMeanVariable .end(), it )
974 != DidYouMeanVariable .end()
975 || std::find( DidYouMeanNotATemplate .begin(), DidYouMeanNotATemplate .end(), it )
976 != DidYouMeanNotATemplate .end()
977 || ( ScopeSize()
979 && linkToParentScope->BaseTypes
980 && std::find_if( linkToParentScope->Targets.begin(), linkToParentScope->Targets.end(),
981 [it]( Index::SearchResult& result) { return it==result.Node; })
982 != linkToParentScope->Targets.end() )
983 || ( ScopeSize()
985 && linkToParentScope->TypeDefinitionTargets
986 && std::find( linkToParentScope->TypeDefinitionTargets->begin(), linkToParentScope->TypeDefinitionTargets->end(), it )
987 != linkToParentScope->TypeDefinitionTargets->end() )
988 ) return true;
989
990 return false;
991 });
992
993
994 //---------------- ambiguous? ----------------
995 if ( Targets.size() > 1 ) {
996 out.Add("Ambiguous XLink #{!Q}.", linkString);
997 if (suppressHints)
998 return;
999 out.PushIndent(2);
1000 for (auto& target : Targets)
1001 printType("Could be", target.Node, true);
1002
1003 // Template type?
1004 if (DidYouMeanTemplateType.IsValid())
1005 printType("Could be", DidYouMeanTemplateType, true);
1006
1007 // Variable with different subscript
1008 for ( auto& variable : DidYouMeanVariable )
1009 printType("Could be", variable, true);
1010
1011 // Loop over list of nodes with the same name
1012 if (DidYouMeanSameName.size()) {
1013 out.Add("Further entities with the same name:");
1014 out.PushIndent(2);
1015 for (auto& node : DidYouMeanSameName )
1016 printType( "", node, true);
1017 out.PopIndent();
1018 }
1019 out.PopIndent();
1020 return;
1021 }
1022
1023 //---------------- not found! (Target.size()==0) ----------------
1024 out.Add("Unresolved XLink #{!Q}.", linkString);
1025 if (suppressHints)
1026 return;
1027
1028 out.PushIndent(2);
1031
1032
1033 // If a parent-path was given
1034 if (ScopeSize()>0) {
1035 ALIB_DBG(MA.DbgCriticalSectionsPH->DCSLock= nullptr;)
1036 if (!GetLinkToParent()->Targets.size()) {
1037 out.Buffer << (" Given parent scope \"");
1038 for ( int i= 0; i< HintsSize(); ++i)
1039 out.Buffer << Hint(i) << ' ';
1040 for ( int i= 0; i< ScopeSize(); ++i)
1041 out.Buffer << Scope(i) << (HasOneOf(KindSpec, Target::Dir | Target::File)
1043 out.Buffer << ("\" not found.\n");
1044 }
1045
1046 // If parent-path was found, list possible parents' children
1047 else {
1048 out.Add( "Collecting proposals of compound type(s) and base types: ");
1049 out.PushIndent(2);
1050
1051 // collect all nodes in one vector
1052 std::vector<Index::Node> parents;
1053 parents.reserve( linkToParentScope->Targets.size()
1054 + ( BaseTypes ? size_t(BaseTypes->size()) : 0 )
1055 + ( TypeDefinitionTargets? size_t(TypeDefinitionTargets->size()) : 0 ) );
1056
1057 for (auto& target : linkToParentScope->Targets)
1058 parents.push_back(target.Node);
1059 if (BaseTypes)
1060 for (auto& target : *BaseTypes)
1061 parents.push_back(target);
1063 for (auto& target : *TypeDefinitionTargets)
1064 parents.push_back(target);
1065
1066 bool foundSimilar= false;
1067 for (int phase=0 ; phase<5 ; ++phase) {
1068 for (auto& didYouMeanChildOf : parents) {
1069 if ( didYouMeanChildOf.IsA(Target::FILEPATH_COMPONENT) )
1070 continue;
1071 out.PushIndent(2);
1072
1073 // first search vice-versa start-strings
1074 if ( phase != 4) {
1075 String searchedName= Name();
1076 auto child= didYouMeanChildOf.AsCursor().FirstChild();
1077 while ( child.IsValid() ) {
1078 bool hits=
1079 ( phase == 0 // vice-versa start strings, case sensitive
1080 && ( child.Name().StartsWith<CHK,lang::Case::Sensitive>(searchedName)
1081 || searchedName.StartsWith<CHK,lang::Case::Sensitive>(child.Name()) ) )
1082 ||( phase == 1 // vice-versa start strings, case ignore
1083 && ( child.Name().StartsWith<CHK,lang::Case::Ignore >(searchedName)
1084 || searchedName.StartsWith<CHK,lang::Case::Ignore >(child.Name()) ) )
1085 ||( phase == 2 // vice-versa substrings, case sensitive
1086 && ( child.Name().IndexOf <NC,lang::Case::Sensitive>(searchedName) >=0
1087 || searchedName.IndexOf <NC,lang::Case::Sensitive>(child.Name()) >=0 ) )
1088 ||( phase == 3 // vice-versa substrings, case ignore
1089 && ( child.Name().IndexOf <NC,lang::Case::Ignore >(searchedName) >=0
1090 || searchedName.IndexOf <NC,lang::Case::Ignore >(child.Name()) >=0 ) )
1091 ;
1092
1093 if (hits && nodesListed.InsertIfNotExistent(child.Value()).second) {
1094 if (!foundSimilar) {
1095 printType("Did you mean an entity in", didYouMeanChildOf, true);
1096 foundSimilar= true;
1097 }
1098 printType(" ", child, false);
1099 }
1100 child.GoToNextSibling();
1101 }
1102 }
1103
1104 // finally, if still none was found, just dump some
1105 else if ( !foundSimilar) {
1106 auto child= didYouMeanChildOf.AsCursor().FirstChild();
1107 while (child.IsValid()) {
1108 if ( nodesListed.InsertIfNotExistent(child.Value()).second) {
1109 if (!foundSimilar) {
1110 printType("Did you mean an entity in", didYouMeanChildOf, true);
1111 foundSimilar= true;
1112 }
1113 printType(" ", child, false);
1114 }
1115 child.GoToNextSibling();
1116 }
1117 }
1118 out.PopIndent();
1119 }
1120 }
1121 out.PopIndent();
1122 } // possible parents found
1123 } // parent path was given
1124
1125 // Template type?
1126 if ( DidYouMeanTemplateType.IsValid()
1127 && nodesListed.InsertIfNotExistent(DidYouMeanTemplateType.Target()).second ) {
1128 printType("You probably meant:", DidYouMeanTemplateType, true);
1129 out.PushIndent(2);
1130 // Loop over the list of nodes with the same name (specializatios)
1131 for (auto& indexCursor : DidYouMeanSameName )
1132 printType("Or ", indexCursor, true);
1133 out.PopIndent();
1134 out.PopIndent();
1135 return;
1136 }
1137
1138 // Loop over the list of overloaded functions
1139 for (auto& indexCursor : DidYouMeanFunctionOverload ) {
1140 if ( nodesListed.InsertIfNotExistent(indexCursor.Target()).second )
1141 printType(indexCursor.IsA(Target::Macro) ? "Did you mean"
1142 : "Did you mean overloaded",
1143 indexCursor, true);
1144 }
1145
1146 // Loop over the list of overloaded functions
1147 for (auto& indexCursor : DidYouMeanVariable )
1148 if ( nodesListed.InsertIfNotExistent(indexCursor.Target()).second )
1149 printType("Subscript mismatch with: ", indexCursor, true);
1150
1151 // Loop over the list of nodes with the same name
1152 for (auto& indexCursor : DidYouMeanSameName )
1153 if ( nodesListed.InsertIfNotExistent(indexCursor.Target()).second )
1154 printType("Did you mean", indexCursor, true);
1155
1156
1157 out.PopIndent();
1158}
1159
1160} //namespace [dxl]
1161
#define ALIB_LOCK_SHARED_WITH(lock)
#define ALIB_ASSERT(cond, domain)
#define ALIB_ASSERT_WARNING(cond, domain,...)
#define ALIB_DBG(...)
#define Lox_Info(...)
#define Lox_Error(...)
#define Lox_IsActive(result,...)
std::pair< Iterator, bool > InsertIfNotExistent(const KeyType &key, const MappedType &mapped)
Cursor & AsCursor()
Paragraphs & PushIndent(const String &indentFirstLine, const String &indentOtherLines=nullptr)
void Add(boxing::TBoxes< TAllocatorArgs > &args)
Paragraphs & PopIndent()
TAString & InsertChars(TChar c, integer qty)
integer SearchAndReplace(const TString< TChar > &needle, const TString< TChar > &replacement, integer startIdx=0, integer maxReplacements=strings::MAX_LEN, lang::Case sensitivity=lang::Case::Sensitive, integer endIdx=strings::MAX_LEN)
TAString & ShortenTo(integer newLength)
TAString & ShortenBy(integer charsToRemove)
void DbgDisableBufferReplacementWarning()
constexpr integer Length() const
constexpr bool IsEmpty() const
bool EndsWith(const TString &needle) const
TChar CharAtStart() 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 Equals(const TString< TChar > &rhs) const
bool StartsWith(const TString &needle) const
integer IndexOfOrLength(TChar needle) const
bool ConsumeString(const TString< TChar > &consumable)
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
integer ConsumeChars(integer regionLength, TAString< TChar, TAllocator > &target, integer separatorWidth=0)
TSubstring & Trim(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
integer ConsumeCharsFromEnd(integer regionLength, TAString< TChar, TAllocator > &target, integer separatorWidth=0)
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
alib::system::PathString FilePath
The path to the doxygenTagFile.
Definition index.hpp:227
const alib::String & BaseURL
The URL of the HTML-output created with this tag-file.
Definition index.hpp:233
void ReplaceToTreeSeparator(alib::AString &buffer, Target::Kinds kind, alib::integer startPos=0)
Definition index.cpp:219
Node ImportNode(CursorHandle handle)
Definition index.hpp:490
alib::SharedLock SLock
Definition index.hpp:238
Target(Kinds pKind, const alib::String &htmlFile, int lineNo)
Definition target.hpp:226
bool IsA(Kinds aKind) const
Definition target.hpp:240
Kinds Kind() const
Definition target.hpp:235
alib::String HTMLFile
The HTML file that this target links to (or into).
Definition target.hpp:219
@ Struct
Denotes a struct.
Definition target.hpp:37
@ Function
Denotes a namespace- or member-function.
Definition target.hpp:46
@ Variable
Denotes a namespace- or member-variable.
Definition target.hpp:45
@ UNSPECIFIED
Used with the field #"XLink::KindSpec;2".
Definition target.hpp:56
@ Union
Denotes a union.
Definition target.hpp:39
@ Class
Denotes a class.
Definition target.hpp:38
@ Typedef
Denotes a type definition.
Definition target.hpp:44
@ File
Denotes a source file.
Definition target.hpp:31
@ EnumElement
Denotes an enumeration element.
Definition target.hpp:48
@ Concept
Denotes a C++20 concept.
Definition target.hpp:40
@ Macro
Denotes a preprocessor definition.
Definition target.hpp:43
@ Dir
Denotes a source folder.
Definition target.hpp:30
@ Page
Denotes a page.
Definition target.hpp:32
@ Group
Denotes a group.
Definition target.hpp:33
@ Enumeration
Denotes an enumeration.
Definition target.hpp:47
@ FILEPATH_COMPONENT
A node of a file path (not a doxygen kind).
Definition target.hpp:52
@ Namespace
Denotes a namespace.
Definition target.hpp:36
@ DocAnchor
Denotes a preprocessor definition.
Definition target.hpp:34
@ RECORD
Mask to identify records types.
Definition target.hpp:67
int LineNo
The line number in the Doxygen tag-file where this entity is defined.
Definition target.hpp:216
TApp & Get()
constexpr PathCharType DIRECTORY_SEPARATOR
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
containers::HashSet< TAllocator, T, THash, TEqual, THashCaching, TRecycling > HashSet
files::File File
containers::List< T, MonoAllocator, TRecycling > ListMA
LocalString< 64 > String64
LocalString< 8 > String8
constexpr CString NEW_LINE
constexpr const String EMPTY_STRING
lang::integer integer
monomem::TLocalAllocator< 2 > LocalAllocator2K
strings::TString< character > String
app::AppCliCamp APPCLI_CAMP
strings::TSubstring< character > Substring
LocalString< 1024 > String1K
LocalString< 128 > String128
LocalString< 256 > String256
format::Paragraphs Paragraphs
LocalString< 32 > String32
LocalString< 512 > String512
lox::Scope Scope
todox
Definition doxyfile.cpp:20
const TGT * Cast(const Index::Node &node)
Definition index.hpp:544
void ConvertASCIItoHTMLEntities(alib::AString &buffer)
Definition dxl.cpp:133
The cursor type of the #"StringTree".
Definition index.hpp:105
const alib::String & HTMLFile() const
Definition index.hpp:187
const Target * Target() const
Definition index.hpp:176
alib::strings::TAString< cmTree::CharacterType, alib::lang::HeapAllocator > & Path(alib::strings::TAString< cmTree::CharacterType > &targetString, alib::lang::CurrentData targetData=alib::lang::CurrentData::Clear) const
Definition index.hpp:146
Index & Index() const
Definition index.hpp:173
bool IsA(Target::Kinds kind) const
Definition index.hpp:197
Target::Kinds Kind() const
Definition index.hpp:192
Cursor & AsCursor()
Definition index.hpp:223
An entry in the vector of search results generated by the method Search.
Definition index.hpp:384
Node Node
The cursor pointing to the result.
Definition index.hpp:386
bool IsIndirectByInheritance
Set if a member was found in a base type and not in the originally given one.
Definition index.hpp:410
alib::ListMA< alib::String > BaseTypes
The base type of the record.
Definition target.hpp:352
XLink target information for type definitions.
Definition target.hpp:419
alib::String Type
The type of the definition.
Definition target.hpp:421
static FunctionArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
Definition target.cpp:28
static TemplateArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
Definition target.cpp:155