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('.');
224
225 for (;searchString.TrimStart().IsNotEmpty();) {
226 String word;
227 getNextIdentiferWithTemplateArgs(searchString, word);
228 if (word.IsEmpty()) {
229 if(searchString.CharAtStart()=='.') {
230 IsLocal= true; // this will lead to an error below: local with path hints
231 searchString.ConsumeChar();
232 continue;
233 }
234 break; // happens when non-alnum characters are given
235 }
236 if (scopeSize==MAX_SCOPE_DEPTH-1) {
238 return;
239 }
240 tmpScope[scopeSize++]= String(MA, word);
241 if (searchString.CharAtStart() == ' ')
243 else {
244 searchString.ConsumeChar('.');
245 searchString.ConsumeChar(':');
246 searchString.ConsumeChar(':');
247 }
248 }
249
250 // if the last component name ended with a space, we need to steal one hint and add it to the
251 // scope components.
254
255 // copy the local array to our member
256 if (scopeSize>0) {
257 scope= MA().NewArray<String>(scopeSize);
258 for (int i= 0; i < scopeSize; ++i)
259 scope[i]= tmpScope[i];
260 } else {
262 return;
263 }
264
265 // if a local link is given, no scope hints are accepted
266 if (IsLocal && scopeHintsSize > 0) {
268 return;
269 }
270 } // end of reading scope
271
272 // parse subscript
273 searchString.TrimStart();
274 if (searchString.ConsumeChar('[')) {
275 String128 subscript;
276 int depth= 0;
277 while ( depth > 0 || !searchString.ConsumeChar(']') ) {
278 if (searchString.ConsumeChar('[')) ++depth;
279 if (searchString.ConsumeChar(']')) --depth;
280 subscript._<NC>(searchString.ConsumeChar());
281 }
282 Subscript= String(MA, subscript);
283 searchString.TrimStart();
284 }
285
286 // parse template-specialization arguments (they come AFTER the identifier name)
287 integer templateStart= scope[scopeSize-1].IndexOf('<');
288 if (templateStart == 8 && scope[scopeSize-1].StartsWith("operator") ) {
289 if (scope[scopeSize-1].CharAt(9) == '<') // operator<<
290 templateStart= 9;
291 templateStart= scope[scopeSize-1].IndexOf('<', templateStart + 1);
292 }
293 if (templateStart>=0) {
294 Substring templateParams= scope[scopeSize-1].Substring(templateStart);
295 scope[scopeSize-1]= scope[scopeSize-1].Substring(0, templateStart);
296
298 }
299
300 // parse function arguments
301 if (searchString.CharAtStart() == '(')
303
304 // qualifiers?
305 if(searchString.Trim().IsNotEmpty())
306 Qualifiers= String( MA, searchString);
307}
308
310 // create only once
311 if ( linkToParentScope )
312 return linkToParentScope;
313
314 // create a dummy-XLink to search for possible parent nodes
315 linkToParentScope= MA().New<XLink>();
316 ALIB_DBG( linkToParentScope->MA.DbgCriticalSectionsPH->DCSLock= nullptr;)
317
318 // non-local links: create the parent scope
319 if(!IsLocal) {
320 linkToParentScope->scope= MA().NewArray<String>(scopeSize-1);
321 for (int i= 0; i < scopeSize-1; ++i)
322 linkToParentScope->scope[i]= scope[i];
323 linkToParentScope->scopeSize = scopeSize - 1;
324 linkToParentScope->scopeHintsSize= scopeHintsSize;
325
326 // search the XLink
327 for (auto* index : app::Get<DXLApp>().dxl->Indices )
328 index->Search(*linkToParentScope);
329 }
330 // local links: we can (almost) directly put the parent to the result-list of the dummy link
331 else {
332 Index* mainIndex= app::Get<DXLApp>().dxl->Indices.back();
333 Index::Node node= mainIndex->ImportNode(Index::CursorHandle{LocalLinkEntity.value});
334 bool scopeFound= true;
335 { ALIB_LOCK_SHARED_WITH(mainIndex->SLock)
336 for(int i= 0; i < scopeSize-1; ++i)
337 if(!node.AsCursor().GoToChild(Scope(i)) ) {
338 // if the child node does not exist, then we just do not add anything
339 // and no result is generated
340 scopeFound= false;
341 break;
342 }
343 }
344
345 if(scopeFound)
346 linkToParentScope->Targets.push_back({ node
347 , mainIndex->BaseURL
348 , node.HTMLFile()
350 ,false,false,false,false,false,false,false
351 });
352 }
353
354 // loop over all possible scope-parents
355 for ( Index::SearchResult& scopeParent : linkToParentScope->Targets ) {
356 // collect all parents from all possible records. This is done in a BFS per
357 // possible parent. This means, we go into the breadth, but per parent.
358 if ( auto* rec= Cast<TGTRecord>(scopeParent.Node); rec )
359 findInherited( rec->BaseTypes );
360
361 // if this scope-parent was a type definition, we follow those
362 else if ( scopeParent.Node.IsA(Target::Typedef)) {
363
364 // search final (!) target (could be chained type-defintions)
365 if ( Index::Node targetCursor= ResolveTypeDef(scopeParent.Node, LinkString);
366 !targetCursor.IsRoot() ) {
367 // great, we found the original component.
370 TypeDefinitionTargets->push_back(targetCursor);
371 }
372 }
373 } // loop over possible parents
374
375 // now we also have to add the base types of the type definition targets to the parents!
376 // (wow). But it seems like we do not need to do the opposite: Doxygen Tag files
377 // provide resolved type definitions in its list of base-types.
378 if ( TypeDefinitionTargets ) {
379 for (auto& typeDefTargetCursor : *TypeDefinitionTargets)
380 if ( auto* rec= Cast<TGTRecord>(typeDefTargetCursor); rec)
381 findInherited( rec->BaseTypes );
382 }
383
384 // logging base types found
385 if ( BaseTypes ) {
386 int cntLoggers; Lox_IsActive(cntLoggers, Verbosity::Info, "DXL/INDIRECT")
387 if (cntLoggers > 0) {
388 String1K parentLog;
389 for (auto& p : *BaseTypes)
390 parentLog << " " << p.Name() << NEW_LINE;
391 Lox_Info("DXL/INDIRECT", "Potential parents of XLink {!Q} are\n{}",
392 LinkString, parentLog)
393 }
394 }
395
396 return linkToParentScope;
397}
398
401 const alib::String& origSearchString ) {
402
403 // search final (!) target (could be chained type-defintions)
404 Index::Node typeDefCursor= startCursor;
405 for (;;) {
406 const TGTTypedef& typeDef= *Cast<TGTTypedef,NC>(typeDefCursor);
407 Lox_Info("DXL/INDIRECT", "Type definition for {} found: {}", origSearchString, typeDef.Type)
408
409 // search in indices
410 Index::Node typeDefTargetCursor;
411 for ( auto* index : app::Get<DXLApp>().dxl->Indices ) {
412 // create base type path
413 String512 typeDefPath(typeDef.Type);
414 typeDefPath.ShortenTo(typeDefPath.IndexOfOrLength('<'));
415 index->ReplaceToTreeSeparator(typeDefPath, Target::Typedef);
416 {ALIB_LOCK_SHARED_WITH(index->SLock)
417 if ( (typeDefTargetCursor= index->Root()).AsCursor().GoTo(typeDefPath).IsEmpty() )
418 break;
419 }
420 typeDefTargetCursor= index->Root();
421 }
422 // if not found, this probably is a namespace-local
423 if (typeDefTargetCursor.IsRoot()) {
424 Index::Node scopeParentCursor= typeDefCursor.Parent();
425 String512 typeDefPath(typeDef.Type);
426 typeDefPath.ShortenTo(typeDefPath.IndexOfOrLength('<'));
427 typeDefCursor.Index().ReplaceToTreeSeparator(typeDefPath, Target::Typedef);
428 {ALIB_LOCK_SHARED_WITH(typeDefCursor.Index().SLock)
429 while (!scopeParentCursor.IsRoot()) {
430 if((typeDefTargetCursor= scopeParentCursor).AsCursor().GoTo(typeDefPath).IsEmpty() )
431 break;
432 auto newScopeParentCursor= typeDefTargetCursor.Parent();
433 typeDefTargetCursor.AsCursor().GoToRoot();
434 if( newScopeParentCursor == scopeParentCursor )
435 break;
436 scopeParentCursor= newScopeParentCursor;
437 }
438 } }
439
440 if (typeDefTargetCursor.IsRoot()) {
441 Lox_Info("The type definition {!Q} was not found in the tag file {}:1. "
442 "While processing XLink {!Q}. This is probably an inherited type definition "
443 "to be resolved later",
444 typeDef.Type, typeDefCursor.Index().FilePath, origSearchString )
445 return typeDefTargetCursor;
446 }
447
448 // is again a type definition?
449 if (typeDefTargetCursor.IsA(Target::Typedef)) {
450 typeDefCursor= typeDefTargetCursor;
451 continue;
452 }
453
454 // great, we found the original component.
455 return typeDefTargetCursor;
456 } // endless loop
457}
458#include "ALib.Lang.CIMethods.H"
459
460void XLink::findInherited( const decltype(TGTRecord::BaseTypes)& bases) {
461
462 integer previousResultSize= BaseTypes ? BaseTypes->size() : 0;
463 // first add all base types (bfs approach)
464 for (auto& baseTypeName : bases) {
465
466 bool found= false;
467 for ( auto* index : app::Get<DXLApp>().dxl->Indices ) {
468 ALIB_LOCK_SHARED_WITH(index->SLock)
469
470 // create base type path
471 String512 baseTypePath(baseTypeName);
472 integer templatePos= baseTypePath.IndexOfOrLength('<');
473 baseTypePath.ShortenTo(templatePos);
474 index->ReplaceToTreeSeparator(baseTypePath, Target::RECORD);
475
476 // search
477 Index::Node baseType;
478 if ( (baseType= index->Root()).AsCursor().GoTo(baseTypePath).IsEmpty() ) {
479 if (!baseType.IsA(Target::RECORD | Target::Typedef)) {
480 Lox_Error("The specified base entity {!Q} is not a record or a type defintion, but a {}. "
481 "Detected in tag-file {!Q}",
482 baseTypePath, baseType.Kind(), index->FilePath )
483 continue;
484 }
485
486 found= true;
487 if (!BaseTypes)
489 BaseTypes->push_back(baseType);
490 }
491 }
492
493 // not found? Should not happen!
494 if (!found) {
495 Lox_Error("The specified base entity {!Q} does not exist in any tag-file.", baseTypeName)
496 }
497 }
498
499 // now search the grandparents of those that we have found (recursion)
500 if (BaseTypes) {
501 integer newResultSize= BaseTypes ? BaseTypes->size() : 0;
502 integer i= 0;
503 for ( auto& baseType : *BaseTypes ) {
504 if ( i>= previousResultSize && i < newResultSize )
506 ++i;
507 }
508 }
509}
510
512 const Index::SearchResult& result = Result();
513 Index::Node node = result.Node;
514 const Target* target = node.Target();
515
516 //-------------------- parse display ------------------
517 Substring display= Display;
518 bool starGiven = false;
519 bool addFArgs = false;
520 bool addTArgs = false;
521 bool addSubscript = false;
522 bool addType = false;
523 bool addQualifiers = false;
524 int addParents = 0;
525 for (;;) {
526 if ( display.ConsumeChar('/') ) break;
527 if ( display.ConsumeChar('<')
528 || display.ConsumeChar('>') ) { addTArgs = true; continue; }
529 if ( display.ConsumeChar('(')
530 || display.ConsumeChar(')') ) { addFArgs = true; continue; }
531 if ( display.ConsumeChar('[')
532 || display.ConsumeChar(']') ) { addSubscript = true; continue; }
533 if ( display.ConsumeChar('?') ) { addType = true; continue; }
534 if ( display.ConsumeChar('!') ) { addQualifiers = true; continue; }
535 if ( display.ConsumeChar('*') ) { starGiven = true; continue; }
536 if (isdigit(display.CharAtStart())) { addParents= display.ConsumeChar()-'0'; continue; }
537 break;
538 }
539
540 if (starGiven)
541 addFArgs= addTArgs= addSubscript= addType= addQualifiers= true;
542
543
544 //-------------------------------------- docs ----------------------------------------
545 if ( target->IsA(Target::DocAnchor | Target::Page | Target::Group) ) {
546 CSSClasses.Set(node, display.IsNotEmpty(), false );
547 const String& title= target->IsA(Target::DocAnchor) ? Cast<TGTDocAnchor, NC>(target)->Title
548 :target->IsA(Target::Page) ? Cast<TGTPage , NC>(target)->Title
549 : Cast<TGTGroup , NC>(target)->Title;
550 if (display.IsEmpty()) {
551 if ( title.IsNotEmpty() ) {
552 Display= title;
553 return;
554 }
555 if ( addParents == 0) Error= Errors::AnchorHasNoTitle;
556 else if ( addParents > 1) Error= Errors::InappropriateDisplayTweak;
557 Display= Name();
558 return;
559 }
560 if ( !display.Equals(Display))
561 Display= String(MA, display);
562 return;
563 }
564
565 //-------------------------------------- Dir/File ----------------------------------------
566 if ( target->IsA(Target::Dir | Target::File) ) {
567 if ( addFArgs | addTArgs | addSubscript | addType | addQualifiers )
569
570 CSSClasses.Set(node, display.IsNotEmpty(), false );
571 if ( display.IsNotEmpty()) {
572 if ( !display.Equals(Display))
573 Display= String(MA, display);
574 return;
575 }
576 }
577
578 //-------------------------------------- Types ----------------------------------------
579 else {
580 CSSClasses.Set( node, display.IsNotEmpty(), Result().IsIndirectByTypeDef
581 || Result().IsIndirectByInheritance
582 || Result().IsResolvedTypeDef );
583 ALIB_ASSERT(CSSClasses.Get(1).Equals("xl-entity"), "DXL/XLINK")
584
585 if ( display.IsNotEmpty() && !addFArgs && !addTArgs && !addType && addParents < 2 ) {
586 Display= display; // in case '/' was cut
587 return;
588 }
589 }
590
591 String256 newDisplay;
593
594 // add "template<...>" ? (done when * or keyword "template", or at least one
595 // template argument was given)
596 if ( auto* rec= Cast<TGTRecord>(target);
597 rec && rec->TemplateArgs) {
598 if(addTArgs || TemplateArgs ) {
599 newDisplay._("template ");
600 rec->TemplateArgs->Print(newDisplay);
601 newDisplay._<NC>(' ');
602 }
603 }
604
605 // add Type
606 if ( addType ) {
607 if ( auto* var= Cast<TGTVariable>(target); var)
608 newDisplay << var->Type << ' ';
609 if ( auto* func= Cast<TGTFunction>(target);
610 func && func->Type.IsNotEmpty()) // may be empty for constructor
611 newDisplay << func->Type << ' ';
612 }
613
614 // add parents?
615 if (addParents && !target->IsA(Target::Macro)) {
616 integer prevDisplayLength= newDisplay.Length();
617
618 // if inherited or a resolved type definition, then the originally given parent path has
619 // to be used.
621 for (int i= addParents-2 ; i>= 0; --i) {
622 int parentIdx= ScopeSize() - i -1;
623 if (parentIdx>=0){
624 newDisplay << Scope(parentIdx);
625 if (i>0)
626 newDisplay << "::";
627 }
628 else
630 }
631 } else {
632 // for some reason, the dir type in the tag file resides already in an according
633 // parent folder
634 auto n= node;
635 if(KindSpec == Target::Dir)
636 n= n.Parent();
637 auto parent= n;
638 int cntParentOverflow = 0;
639 for (; cntParentOverflow < addParents && !parent.IsRoot(); ++cntParentOverflow)
640 parent= parent.Parent();
641 if ( parent.IsRoot() && cntParentOverflow < addParents)
643 { ALIB_LOCK_SHARED_WITH(n.Index().SLock)
644 n.Parent().Path(newDisplay, parent); }
645 }
646 // parent path added? -> add a separator
647 if (prevDisplayLength != newDisplay.Length()){
648 if (HasOneOf(KindSpec, Target::Dir|Target::File))
649 newDisplay._<NC>(system::DIRECTORY_SEPARATOR);
650 else
651 newDisplay._<NC>("::");
652 }
653 }
654
655 // add name
656 newDisplay << Name();
657
658 // we add all parameters in case the user gave them 100% correct (not as hints)
659 // or qualifiers have been given.
660 // or display was set to "*"
661 if ( auto* func= Cast<TGTFunction>(target); func) {
662 if ( addFArgs
663 || addQualifiers
664 || result.FunctionArgumentMatch==4
665 || Qualifiers.IsNotEmpty() ) {
666 if ( func->Args ) func->Args->Print(newDisplay);
667 else newDisplay._("()");
668 }
669
670 // In case of qualifiers, all are added, even if just a hint was given.
671 if (addQualifiers || result.QualifiersHintMatch) {
672 newDisplay._<NC>(' ')._<NC>(func->Qualifiers);
673 // nevertheless, "noexcept" is removed. In V6501 this will be configurable :-)
674 if (newDisplay.EndsWith("noexcept") )
675 newDisplay.ShortenBy(8);
676 display.TrimEnd();
677 } }
678
679 // For prepro macros, we add all parameters in case the user just gave them
680 if ( target->IsA(Target::Macro)
681 && (Args || (addFArgs && Cast<TGTMacro,NC>(target)->Args) ) ) {
682 Cast<TGTMacro,NC>(target)->Args->Print(newDisplay);
683 }
684 // add template specialization? (done when <,>, *, or at least one specialization
685 // argument was given)
686 if ( target->IsA(Target::RECORD)
687 && Cast<TGTRecord,NC>(target)->SpecializationArgs
688 && (addTArgs || SpecializationArgs ) )
689 Cast<TGTRecord,NC>(target)->SpecializationArgs->Print(newDisplay);
690
691 // add variable subscript? (done when something matching was given)
692 if ( target->IsA(Target::Variable)
693 && (addSubscript || Subscript.IsNotNull()) )
694 newDisplay << Cast<TGTVariable,NC>(target)->Subscript;
695
696 // add file path to #define?
697 if (addParents && target->IsA(Target::Macro)) {
698 newDisplay._<NC>(" (");
699 auto parent= node;
700 int cntParentOverflow = 0;
701 for (; cntParentOverflow < addParents && !parent.IsRoot(); ++cntParentOverflow)
702 parent= parent.Parent();
703 if ( parent.IsRoot() && cntParentOverflow < addParents)
706 node.Parent().Path(newDisplay, parent);
707 newDisplay._<NC>(") ");
708 }
709
710 // finally, add what the user added to the display
711 if ( display.IsNotEmpty() )
712 newDisplay << display;
713 ConvertASCIItoHTMLEntities(newDisplay);
714 Display = String(MA, newDisplay);
715}
716
717
718#if defined(TODO_IS_NEEDED_AGAIN)
719namespace {
720//todo: Hier gehts weiter:
721//X erstmal alle fehler im ALib nun noch korrigieren
722//- dann die neuen Maps
723// - per filename
724// - per anchor aufbauen.
725//- dann das Resolving umstellen auf den echten parent, den man aus dem filenamen direkt nachschlägt
726//- Achso: Statt den filenamen zu speichern, kann man auch den Tree-node direkt im Tag-file ablegen.
727// - Das geht natĂĽrlich nur mit dem Haupt-Tagfile, also dem letzten in Indices.
728// - Dem Index also ein Flag "IsMainTagFile" geben und dem HTML-Base in den Targets eine union
729// machen: Entweder String oder exported File cursor.
730// - Dazu also als allererstes den HTML-Tree parsen, ohne notify und Job-Start. Dies trennen.
731// (oder war es da getrennt, naja, siehst du ja dann) und im Tag-file den Node suchen.
732// - Im Index::Search dann, bei ein local links sofort aufhören, wenn nicht IsMainTagFile.
733// - Dann im DXL ein feature einfügen, welches auf die Möglichkeit hinweist, dass ein Link
734// zum Local-Link gemacht werden kann. Leider kommen dann falsche source-locations heraus.
735// Da muss man am Anfang der Liste einen hübschen Erklärungstext hinzufügen.
736
737 // Converts a doxygen file name (mangled) back to the entity that the file documents
738 int parseFileScope( files::File htmlFile, String* fileScope,
739 MonoAllocator& ma, int MAX_SCOPE_DEPTH ) {
740 String256 fileName(htmlFile.Name());
741
742 // first parse the known entity types
743 integer scopeStart = fileName.StartsWith("struct") ? 6
744 : fileName.StartsWith("class") ? 5
745 : fileName.StartsWith("union") ? 5
746 : fileName.StartsWith("namespace") ? 9
747 : fileName.StartsWith("concept") ? 7
748 : -1;
749 if ( scopeStart < 0)
750 return 0;
751 fileName.ShortenTo( fileName.LastIndexOf('.') );
752
753 // replace mangled characters
754 fileName.DeleteStart(scopeStart);
755 fileName.SearchAndReplace( "_8" , "@" );
756 fileName.SearchAndReplace( "_1_1", "@" );
757 fileName.SearchAndReplace( "__" , "_" );
758
759 // parse the scope that the filename represents
760 Substring parser(fileName);
761 int scopeSize= 0;
762 while (parser.IsNotEmpty() && scopeSize < MAX_SCOPE_DEPTH )
763 fileScope[scopeSize++]= String( ma, parser.ConsumeToken('@') );
764 return scopeSize;
765 }
766}
767#endif //defined(TODO_IS_NEEDED_AGAIN)
768
769std::pair<XLink*,bool> XLink::GetLocalCopy(const File& htmlFile) {
770 // first check if a local link exists already for this file
771 auto htmlFileHandle= htmlFile.AsCursor().Export();
772 XLink* xl= this;
773 while (xl) {
774 if (xl->HTMLFileOfLocalLink == htmlFileHandle)
775 return std::make_pair(xl, false);
776 xl= xl->NextLocal;
777 }
778
779 // now either choose us (if we're still empty) or create a new one
780 if (HTMLFileOfLocalLink != 0) { //already used
781 auto* oldNext= NextLocal;
782 NextLocal= MA().New<XLink>(); ALIB_DBG(NextLocal->MA.DbgCriticalSectionsPH.Construct(nullptr));
783 NextLocal->LinkString= LinkString;
784 NextLocal->Parse();
785 NextLocal->NextLocal= oldNext;
786 xl= NextLocal;
787 } else
788 xl= this;
789
791 && xl->IsParsed()
793 && xl->scopeHintsSize == 0 , "DXL/XLINK")
794
795 // store the file.
796 xl->HTMLFileOfLocalLink= htmlFileHandle;
797 return std::make_pair(xl, true);
798}
799
800void XLink::PrintError(Paragraphs& out, const String& linkString, bool suppressHints) {
801
802 //---------------- lamda function that assembles the name of a target ----------------
803 auto printType= [&](const String& headLine, const Index::Node& targetNode, bool withPath) {
804 String512 np;
805 String32 kindName;
806 const Target* target= targetNode.Target();
807
808 // resolve kind name
809 if ( auto* rec= Cast<TGTRecord>(target);
810 rec && rec->TemplateArgs )
811 np._("template ");
812
813 bool isMember = targetNode.Parent()!=targetNode.Index().Root()
814 && !targetNode.Parent().IsA(Target::Namespace);
815 bool isConstructor= isMember
816 && targetNode.Parent().Name().Equals(Name());
817 if (target->IsA(Target::Function))
818 kindName= !isMember ? "namespace-function"
819 : isConstructor ? "constructor"
820 : "member-function";
821 else if (target->IsA(Target::Variable))
822 kindName= isMember ? "member-variable" : "namespace-variable";
823 else if ( auto* rec= Cast<TGTRecord>(target);
824 rec && rec->SpecializationArgs )
825 kindName= "specialization";
826 else if ( auto* macro= Cast<TGTMacro>(target); macro )
827 kindName= macro->Args ? "preprocessor macro"
828 : "preprocessor constant";
829 else kindName= target->Kind();
830
831 // Add type code
832 char typeCode= 0;
833 if (target->IsA(Target::Dir )) typeCode= 'D';
834 else if (target->IsA(Target::File )) typeCode= 'F';
835 else if (target->IsA(Target::Macro )) typeCode= 'P';
836 else if (target->IsA(Target::Namespace )) typeCode= 'N';
837 else if (target->IsA(Target::Concept )) typeCode= 'O';
838 else if (target->IsA(Target::Typedef )) typeCode= 'T';
839 else if (target->IsA(Target::Class )) typeCode= 'C';
840 else if (target->IsA(Target::Struct )) typeCode= 'S';
841 else if (target->IsA(Target::Union )) typeCode= 'U';
842 else if (target->IsA(Target::Enumeration )) typeCode= 'E';
843 else if (target->IsA(Target::EnumElement )) typeCode= 'A';
844 else if (target->IsA(Target::Function )) typeCode= 'M';
845 else if (target->IsA(Target::Variable )) typeCode= 'V';
846 if( typeCode) np._("(")._(typeCode)._(") ");
847
848 np._(kindName).InsertChars(' ', 10-np.Length())._<NC>(' ');
849
850 // resolve name
851 if (auto* rec= Cast<TGTRecord>(target);
852 rec && rec->TemplateArgs ) {
853 np._("template ");
854 rec->TemplateArgs->Print(np);
855 np._(' ');
856 }
857 if (withPath && !target->IsA(Target::Macro) && !targetNode.Parent().IsRoot()) {
858 String512 pathBuf;
859 {ALIB_LOCK_SHARED_WITH(targetNode.Index().SLock)
860 targetNode.Parent().Path(pathBuf); }
861 np._(pathBuf)._<NC>("::");
862 }
863
864 String name= targetNode.Name();
865 if ( target->IsA(Target::RECORD)) {
866 integer templatePos= name.IndexOfOrLength('<');
867 ALIB_DBG(assert(name.IndexOf('(')<0));
868 name= name.Substring(0, templatePos);
869 }
870 np._(name);
871
872 if (auto* rec= Cast<TGTRecord>(target); rec && rec->SpecializationArgs )
873 rec->SpecializationArgs->Print(np);
874
875 if (auto* var= Cast<TGTVariable>(target); var)
876 np << var->Subscript;
877
878 if (auto* macro= Cast<TGTMacro>(target); macro && macro->Args)
879 macro->Args->Print(np);
880
881 String256 link(targetNode.Index().BaseURL);
882 link << '/' << target->HTMLFile;
883 if (auto* mem= Cast<TGTMember>(target); mem)
884 link << '#' << mem->Anchor;
885
886 if (withPath && target->IsA(Target::Macro)) {
887 String512 pathBuf;
888 targetNode.Parent().Path(pathBuf);
889 np._<NC>(" in file: ")._<NC>(pathBuf);
890 }
891
892 //out.
893 integer oldLineWidth= out.LineWidth;
894 out.LineWidth= 0;
895 out.Add("{} {} {!ATab} {}:{} {!ATab} {} "
896 , headLine
897 , np
898 , "tag: "
899 , targetNode.Index().FilePath
900 , target->LineNo
901 , "->: "
902 , link
903 );
904 out.LineWidth= oldLineWidth;
905 }; // inner function 'printType'
906
907
908 //---------------- Error in XLink? ----------------
909 if ( Error != Errors::OK ) {
910 out.Add("XLink #{!Q} {}:", linkString, Error > Errors::WARNINGMARKER ? "is erroneous"
911 : "has a warning" );
912 out.PushIndent(2);
913 out.Add(APPCLI_CAMP.GetResource(String64("XL_ERR_")._(int(Error))) );
914 out.PopIndent();
915 return;
916 }
917
918
919 //---------------- indirection and not ^ and vice versa ----------------
920 if ( Targets.size() == 1 ) {
921
923 && !Result().IsIndirectByInheritance
924 && !Result().IsIndirectByTypeDef
925 && !Result().IsIndirectLinkToScannedHTMLSourceFile ) {
926 out.Add("Warning: XLink #{!Q} uses indirection prefix '^', while it targets a "
927 "direct member in the parent scope.\n"
928 " Hint: Remove the prefix from the XLink", linkString );
929 printType(" Target:", Result().Node, true);
930 return;
931 }
932
934 && ( Result().IsIndirectByInheritance
935 || Result().IsIndirectByTypeDef
936 || Result().IsIndirectLinkToScannedHTMLSourceFile ) ) {
937 out.Add("Warning: XLink #{!Q} has an indirect target but is not marked with the "
938 "indirection prefix '^'.",
939 linkString );
940 printType(" Target:", Result().Node, true);
941 return;
942 }
943
945 && Result().IsIndirectLinkToScannedHTMLSourceFile ) {
946 out.Add("Warning: XLink #{!Q} links to an HTML-file found in the output folder "
947 "(not the tag file)!\n"
948 "Mark this link with indirection prefix '^' (to silence this warning).",
949 linkString );
950 printType(" Target:", Result().Node, true);
951 return;
952 }
953
954 ALIB_ASSERT_WARNING(Error != Errors::OK, "DXL/XLINK",
955 "No error to print for this valid XLink \"{}\" in the sources", linkString )
956 return;
957 }
958
959 //---------------- remove from same-name-list if found in a more concrete list ----------------
960
961 std::erase_if(DidYouMeanSameName, [&](const auto& it) {
962 // remove if duplicate
963 for (auto& target : Targets)
964 if (target.Node == it)
965 return true;
966
967 // remove from other lists
968 if ( it == DidYouMeanTemplateType
969 || std::find( DidYouMeanFunctionOverload.begin(), DidYouMeanFunctionOverload.end(), it )
971 || std::find( DidYouMeanVariable .begin(), DidYouMeanVariable .end(), it )
972 != DidYouMeanVariable .end()
973 || std::find( DidYouMeanNotATemplate .begin(), DidYouMeanNotATemplate .end(), it )
974 != DidYouMeanNotATemplate .end()
975 || ( ScopeSize()
977 && linkToParentScope->BaseTypes
978 && std::find_if( linkToParentScope->Targets.begin(), linkToParentScope->Targets.end(),
979 [it]( Index::SearchResult& result) { return it==result.Node; })
980 != linkToParentScope->Targets.end() )
981 || ( ScopeSize()
983 && linkToParentScope->TypeDefinitionTargets
984 && std::find( linkToParentScope->TypeDefinitionTargets->begin(), linkToParentScope->TypeDefinitionTargets->end(), it )
985 != linkToParentScope->TypeDefinitionTargets->end() )
986 ) return true;
987
988 return false;
989 });
990
991
992 //---------------- ambiguous? ----------------
993 if ( Targets.size() > 1 ) {
994 out.Add("Ambiguous XLink #{!Q}.", linkString);
995 if (suppressHints)
996 return;
997 out.PushIndent(2);
998 for (auto& target : Targets)
999 printType("Could be", target.Node, true);
1000
1001 // Template type?
1002 if (DidYouMeanTemplateType.IsValid())
1003 printType("Could be", DidYouMeanTemplateType, true);
1004
1005 // Variable with different subscript
1006 for ( auto& variable : DidYouMeanVariable )
1007 printType("Could be", variable, true);
1008
1009 // Loop over list of nodes with the same name
1010 if (DidYouMeanSameName.size()) {
1011 out.Add("Further entities with the same name:");
1012 out.PushIndent(2);
1013 for (auto& node : DidYouMeanSameName )
1014 printType( "", node, true);
1015 out.PopIndent();
1016 }
1017 out.PopIndent();
1018 return;
1019 }
1020
1021 //---------------- not found! (Target.size()==0) ----------------
1022 out.Add("Unresolved XLink #{!Q}.", linkString);
1023 if (suppressHints)
1024 return;
1025
1026 out.PushIndent(2);
1029
1030
1031 // If a parent-path was given
1032 if (ScopeSize()>0) {
1033 ALIB_DBG(MA.DbgCriticalSectionsPH->DCSLock= nullptr;)
1034 if (!GetLinkToParent()->Targets.size()) {
1035 out.Buffer << (" Given parent scope \"");
1036 for ( int i= 0; i< HintsSize(); ++i)
1037 out.Buffer << Hint(i) << ' ';
1038 for ( int i= 0; i< ScopeSize(); ++i)
1039 out.Buffer << Scope(i) << (HasOneOf(KindSpec, Target::Dir | Target::File)
1041 out.Buffer << ("\" not found.\n");
1042 }
1043
1044 // If parent-path was found, list possible parents' children
1045 else {
1046 out.Add( "Collecting proposals of compound type(s) and base types: ");
1047 out.PushIndent(2);
1048
1049 // collect all nodes in one vector
1050 std::vector<Index::Node> parents;
1051 parents.reserve( linkToParentScope->Targets.size()
1052 + ( BaseTypes ? size_t(BaseTypes->size()) : 0 )
1053 + ( TypeDefinitionTargets? size_t(TypeDefinitionTargets->size()) : 0 ) );
1054
1055 for (auto& target : linkToParentScope->Targets)
1056 parents.push_back(target.Node);
1057 if (BaseTypes)
1058 for (auto& target : *BaseTypes)
1059 parents.push_back(target);
1061 for (auto& target : *TypeDefinitionTargets)
1062 parents.push_back(target);
1063
1064 bool foundSimilar= false;
1065 for (int phase=0 ; phase<5 ; ++phase) {
1066 for (auto& didYouMeanChildOf : parents) {
1067 if ( didYouMeanChildOf.IsA(Target::FILEPATH_COMPONENT) )
1068 continue;
1069 out.PushIndent(2);
1070
1071 // first search vice-versa start-strings
1072 if ( phase != 4) {
1073 String searchedName= Name();
1074 auto child= didYouMeanChildOf.AsCursor().FirstChild();
1075 while ( child.IsValid() ) {
1076 bool hits=
1077 ( phase == 0 // vice-versa start strings, case sensitive
1078 && ( child.Name().StartsWith<CHK,lang::Case::Sensitive>(searchedName)
1079 || searchedName.StartsWith<CHK,lang::Case::Sensitive>(child.Name()) ) )
1080 ||( phase == 1 // vice-versa start strings, case ignore
1081 && ( child.Name().StartsWith<CHK,lang::Case::Ignore >(searchedName)
1082 || searchedName.StartsWith<CHK,lang::Case::Ignore >(child.Name()) ) )
1083 ||( phase == 2 // vice-versa substrings, case sensitive
1084 && ( child.Name().IndexOf <NC,lang::Case::Sensitive>(searchedName) >=0
1085 || searchedName.IndexOf <NC,lang::Case::Sensitive>(child.Name()) >=0 ) )
1086 ||( phase == 3 // vice-versa substrings, case ignore
1087 && ( child.Name().IndexOf <NC,lang::Case::Ignore >(searchedName) >=0
1088 || searchedName.IndexOf <NC,lang::Case::Ignore >(child.Name()) >=0 ) )
1089 ;
1090
1091 if (hits && nodesListed.InsertIfNotExistent(child.Value()).second) {
1092 if (!foundSimilar) {
1093 printType("Did you mean an entity in", didYouMeanChildOf, true);
1094 foundSimilar= true;
1095 }
1096 printType(" ", child, false);
1097 }
1098 child.GoToNextSibling();
1099 }
1100 }
1101
1102 // finally, if still none was found, just dump some
1103 else if ( !foundSimilar) {
1104 auto child= didYouMeanChildOf.AsCursor().FirstChild();
1105 while (child.IsValid()) {
1106 if ( nodesListed.InsertIfNotExistent(child.Value()).second) {
1107 if (!foundSimilar) {
1108 printType("Did you mean an entity in", didYouMeanChildOf, true);
1109 foundSimilar= true;
1110 }
1111 printType(" ", child, false);
1112 }
1113 child.GoToNextSibling();
1114 }
1115 }
1116 out.PopIndent();
1117 }
1118 }
1119 out.PopIndent();
1120 } // possible parents found
1121 } // parent path was given
1122
1123 // Template type?
1124 if ( DidYouMeanTemplateType.IsValid()
1125 && nodesListed.InsertIfNotExistent(DidYouMeanTemplateType.Target()).second ) {
1126 printType("You probably meant:", DidYouMeanTemplateType, true);
1127 out.PushIndent(2);
1128 // Loop over the list of nodes with the same name (specializatios)
1129 for (auto& indexCursor : DidYouMeanSameName )
1130 printType("Or ", indexCursor, true);
1131 out.PopIndent();
1132 out.PopIndent();
1133 return;
1134 }
1135
1136 // Loop over the list of overloaded functions
1137 for (auto& indexCursor : DidYouMeanFunctionOverload ) {
1138 if ( nodesListed.InsertIfNotExistent(indexCursor.Target()).second )
1139 printType(indexCursor.IsA(Target::Macro) ? "Did you mean"
1140 : "Did you mean overloaded",
1141 indexCursor, true);
1142 }
1143
1144 // Loop over the list of overloaded functions
1145 for (auto& indexCursor : DidYouMeanVariable )
1146 if ( nodesListed.InsertIfNotExistent(indexCursor.Target()).second )
1147 printType("Subscript mismatch with: ", indexCursor, true);
1148
1149 // Loop over the list of nodes with the same name
1150 for (auto& indexCursor : DidYouMeanSameName )
1151 if ( nodesListed.InsertIfNotExistent(indexCursor.Target()).second )
1152 printType("Did you mean", indexCursor, true);
1153
1154
1155 out.PopIndent();
1156}
1157
1158} //namespace [dxl]
1159
#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