@@ -1002,6 +1002,16 @@ class TagFileParser
1002
1002
};
1003
1003
private:
1004
1004
1005
+ struct ClassNode
1006
+ {
1007
+ ClassNode (const std::string &n) : name(n) {}
1008
+ std::string name;
1009
+ const TagClassInfo *tci = nullptr ;
1010
+ std::unordered_map<std::string,std::unique_ptr<ClassNode>> children;
1011
+ };
1012
+
1013
+ void buildClassEntry (const std::shared_ptr<Entry> &root, const TagClassInfo *tci);
1014
+ void buildClassTree (const std::shared_ptr<Entry> &root, const ClassNode &node);
1005
1015
// ------------------------------------
1006
1016
1007
1017
std::vector< TagCompoundVariant > m_tagFileCompounds;
@@ -1485,70 +1495,109 @@ void TagFileParser::buildMemberList(const std::shared_ptr<Entry> &ce,const std::
1485
1495
}
1486
1496
}
1487
1497
1498
+ void TagFileParser::buildClassEntry (const std::shared_ptr<Entry> &root, const TagClassInfo *tci)
1499
+ {
1500
+ std::shared_ptr<Entry> ce = std::make_shared<Entry>();
1501
+ ce->section = EntryType::makeClass ();
1502
+ switch (tci->kind )
1503
+ {
1504
+ case TagClassInfo::Kind::Class: break ;
1505
+ case TagClassInfo::Kind::Struct: ce->spec = TypeSpecifier ().setStruct (true ); break ;
1506
+ case TagClassInfo::Kind::Union: ce->spec = TypeSpecifier ().setUnion (true ); break ;
1507
+ case TagClassInfo::Kind::Interface: ce->spec = TypeSpecifier ().setInterface (true ); break ;
1508
+ case TagClassInfo::Kind::Enum: ce->spec = TypeSpecifier ().setEnum (true ); break ;
1509
+ case TagClassInfo::Kind::Exception: ce->spec = TypeSpecifier ().setException (true ); break ;
1510
+ case TagClassInfo::Kind::Protocol: ce->spec = TypeSpecifier ().setProtocol (true ); break ;
1511
+ case TagClassInfo::Kind::Category: ce->spec = TypeSpecifier ().setCategory (true ); break ;
1512
+ case TagClassInfo::Kind::Service: ce->spec = TypeSpecifier ().setService (true ); break ;
1513
+ case TagClassInfo::Kind::Singleton: ce->spec = TypeSpecifier ().setSingleton (true ); break ;
1514
+ case TagClassInfo::Kind::None: // should never happen, means not properly initialized
1515
+ assert (tci->kind != TagClassInfo::Kind::None);
1516
+ break ;
1517
+ }
1518
+ ce->name = tci->name ;
1519
+ if (tci->kind ==TagClassInfo::Kind::Protocol)
1520
+ {
1521
+ ce->name +=" -p" ;
1522
+ }
1523
+ addDocAnchors (ce,tci->docAnchors );
1524
+ ce->tagInfoData .tagName = m_tagName;
1525
+ ce->tagInfoData .anchor = tci->anchor ;
1526
+ ce->tagInfoData .fileName = tci->filename ;
1527
+ ce->startLine = tci->lineNr ;
1528
+ ce->fileName = m_tagName;
1529
+ ce->hasTagInfo = TRUE ;
1530
+ ce->id = tci->clangId ;
1531
+ ce->lang = tci->isObjC ? SrcLangExt::ObjC : SrcLangExt::Unknown;
1532
+ // transfer base class list
1533
+ ce->extends = tci->bases ;
1534
+ if (!tci->templateArguments .empty ())
1535
+ {
1536
+ ArgumentList al;
1537
+ for (const auto &argName : tci->templateArguments )
1538
+ {
1539
+ Argument a;
1540
+ a.type = " class" ;
1541
+ a.name = argName.c_str ();
1542
+ al.push_back (a);
1543
+ }
1544
+ ce->tArgLists .push_back (al);
1545
+ }
1546
+
1547
+ buildMemberList (ce,tci->members );
1548
+ root->moveToSubEntryAndKeep (ce);
1549
+ }
1550
+
1551
+ void TagFileParser::buildClassTree (const std::shared_ptr<Entry> &root,const ClassNode &node)
1552
+ {
1553
+ if (node.tci )
1554
+ {
1555
+ buildClassEntry (root,node.tci );
1556
+ }
1557
+ for (const auto &child : node.children )
1558
+ {
1559
+ buildClassTree (root,*child.second );
1560
+ }
1561
+ }
1562
+
1488
1563
/* ! Injects the info gathered by the XML parser into the Entry tree.
1489
1564
* This tree contains the information extracted from the input in a
1490
1565
* "unrelated" form.
1491
1566
*/
1492
1567
void TagFileParser::buildLists (const std::shared_ptr<Entry> &root)
1493
1568
{
1494
- // build class list
1569
+ // First reorganize the entries in m_tagFileCompounds such that
1570
+ // outer scope is processed before the nested class scope.
1571
+ // To solve issue #11569, where a class nested in a specialization is
1572
+ // processed first, which later causes the wrong class to be used
1573
+ ClassNode classRoot (" " );
1495
1574
for (const auto &comp : m_tagFileCompounds)
1496
1575
{
1497
1576
const TagClassInfo *tci = comp.getClassInfo ();
1498
1577
if (tci)
1499
1578
{
1500
- std::shared_ptr<Entry> ce = std::make_shared<Entry>();
1501
- ce->section = EntryType::makeClass ();
1502
- switch (tci->kind )
1503
- {
1504
- case TagClassInfo::Kind::Class: break ;
1505
- case TagClassInfo::Kind::Struct: ce->spec = TypeSpecifier ().setStruct (true ); break ;
1506
- case TagClassInfo::Kind::Union: ce->spec = TypeSpecifier ().setUnion (true ); break ;
1507
- case TagClassInfo::Kind::Interface: ce->spec = TypeSpecifier ().setInterface (true ); break ;
1508
- case TagClassInfo::Kind::Enum: ce->spec = TypeSpecifier ().setEnum (true ); break ;
1509
- case TagClassInfo::Kind::Exception: ce->spec = TypeSpecifier ().setException (true ); break ;
1510
- case TagClassInfo::Kind::Protocol: ce->spec = TypeSpecifier ().setProtocol (true ); break ;
1511
- case TagClassInfo::Kind::Category: ce->spec = TypeSpecifier ().setCategory (true ); break ;
1512
- case TagClassInfo::Kind::Service: ce->spec = TypeSpecifier ().setService (true ); break ;
1513
- case TagClassInfo::Kind::Singleton: ce->spec = TypeSpecifier ().setSingleton (true ); break ;
1514
- case TagClassInfo::Kind::None: // should never happen, means not properly initialized
1515
- assert (tci->kind != TagClassInfo::Kind::None);
1516
- break ;
1517
- }
1518
- ce->name = tci->name ;
1519
- if (tci->kind ==TagClassInfo::Kind::Protocol)
1579
+ ClassNode *current = &classRoot;
1580
+ auto parts = split (tci->name .str ()," ::" );
1581
+ for (size_t i=0 ; i<parts.size (); ++i)
1520
1582
{
1521
- ce->name +=" -p" ;
1522
- }
1523
- addDocAnchors (ce,tci->docAnchors );
1524
- ce->tagInfoData .tagName = m_tagName;
1525
- ce->tagInfoData .anchor = tci->anchor ;
1526
- ce->tagInfoData .fileName = tci->filename ;
1527
- ce->startLine = tci->lineNr ;
1528
- ce->fileName = m_tagName;
1529
- ce->hasTagInfo = TRUE ;
1530
- ce->id = tci->clangId ;
1531
- ce->lang = tci->isObjC ? SrcLangExt::ObjC : SrcLangExt::Unknown;
1532
- // transfer base class list
1533
- ce->extends = tci->bases ;
1534
- if (!tci->templateArguments .empty ())
1535
- {
1536
- ArgumentList al;
1537
- for (const auto &argName : tci->templateArguments )
1583
+ const auto &part = parts[i];
1584
+ if (current->children .find (part)==current->children .end ()) // new child node
1585
+ {
1586
+ current->children [part] = std::make_unique<ClassNode>(part);
1587
+ }
1588
+ current = current->children [part].get ();
1589
+ if (i==parts.size ()-1 )
1538
1590
{
1539
- Argument a;
1540
- a.type = " class" ;
1541
- a.name = argName.c_str ();
1542
- al.push_back (a);
1591
+ current->tci = tci;
1543
1592
}
1544
- ce->tArgLists .push_back (al);
1545
1593
}
1546
-
1547
- buildMemberList (ce,tci->members );
1548
- root->moveToSubEntryAndKeep (ce);
1549
1594
}
1550
1595
}
1551
1596
1597
+ // now process the classes following the tree structure
1598
+ buildClassTree (root,classRoot);
1599
+
1600
+
1552
1601
// build file list
1553
1602
for (const auto &comp : m_tagFileCompounds)
1554
1603
{
0 commit comments