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