Skip to content

Commit c91a8c8

Browse files
committed
issue #11260 Inherited attribute is repeated twice in python
1 parent 29ca2e5 commit c91a8c8

6 files changed

Lines changed: 128 additions & 72 deletions

File tree

src/classdef.cpp

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable>
403403
void writeTemplateSpec(OutputList &ol,const Definition *d,
404404
const QCString &type,SrcLangExt lang) const;
405405
void mergeMembersFromBaseClasses(bool mergeVirtualBaseClass);
406+
void hideDerivedVariablesInPython(ClassDefMutable *cls);
406407

407408
// PIMPL idiom
408409
class IMPL;
@@ -3739,7 +3740,7 @@ void ClassDefImpl::mergeMembersFromBaseClasses(bool mergeVirtualBaseClass)
37393740
found=matchArguments2(
37403741
srcMd->getOuterScope(),srcMd->getFileDef(),&srcAl,
37413742
dstMd->getOuterScope(),dstMd->getFileDef(),&dstAl,
3742-
TRUE,getLanguage()
3743+
TRUE,lang
37433744
);
37443745
//printf(" Yes, matching (%s<->%s): %d\n",
37453746
// qPrint(argListToString(srcMd->argumentList())),
@@ -3805,7 +3806,8 @@ void ClassDefImpl::mergeMembersFromBaseClasses(bool mergeVirtualBaseClass)
38053806
// it seems that the member is not reachable by prefixing a
38063807
// scope name either (according to my compiler). Currently,
38073808
// this case is shown anyway.
3808-
if (!found && srcMd->protection()!=Protection::Private && !srcMd->isFriend() && srcMi->virtualBaseClass()==mergeVirtualBaseClass)
3809+
if (!found && srcMd->protection()!=Protection::Private && !srcMd->isFriend() &&
3810+
srcMi->virtualBaseClass()==mergeVirtualBaseClass && lang!=SrcLangExt::Python)
38093811
{
38103812
Protection prot = srcMd->protection();
38113813
if (bcd.prot==Protection::Protected && prot==Protection::Public)
@@ -3830,7 +3832,7 @@ void ClassDefImpl::mergeMembersFromBaseClasses(bool mergeVirtualBaseClass)
38303832
if (virt==Specifier::Normal && bcd.virt!=Specifier::Normal) virt=bcd.virt;
38313833
bool virtualBaseClass = bcd.virt!=Specifier::Normal;
38323834

3833-
std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(srcMd,prot,virt,TRUE,virtualBaseClass);
3835+
auto newMi = std::make_unique<MemberInfo>(srcMd,prot,virt,TRUE,virtualBaseClass);
38343836
newMi->setScopePath(bClass->name()+sep+srcMi->scopePath());
38353837
if (ambiguous)
38363838
{
@@ -3919,6 +3921,56 @@ void ClassDefImpl::mergeMembersFromBaseClasses(bool mergeVirtualBaseClass)
39193921
}
39203922
}
39213923

3924+
// See issue11260, referring to a variable in a base class will make doxygen
3925+
// add it as a member to the derived class, but this is not correct for non-private variables
3926+
// so we correct this here, now we know the inheritance hierarchy
3927+
void ClassDefImpl::hideDerivedVariablesInPython(ClassDefMutable *bClass)
3928+
{
3929+
//printf("hideDerivedVariableInPython()\n");
3930+
if (bClass)
3931+
{
3932+
const MemberNameInfoLinkedMap &srcMnd = bClass->memberNameInfoLinkedMap();
3933+
MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap;
3934+
3935+
// recurse up the inheritance hierarchy
3936+
for (const auto &bcd : bClass->baseClasses())
3937+
{
3938+
hideDerivedVariablesInPython(toClassDefMutable(bcd.classDef));
3939+
}
3940+
3941+
for (auto &srcMni : srcMnd) // for each member in a base class
3942+
{
3943+
//printf(" candidate(%s)\n",qPrint(srcMni->memberName()));
3944+
MemberNameInfo *dstMni=dstMnd.find(srcMni->memberName());
3945+
if (dstMni) // that is also in this class
3946+
{
3947+
MemberNameInfo::iterator it;
3948+
//printf("%s member in %s and %s\n",qPrint(name()),qPrint(bClass->name()),qPrint(name()));
3949+
for (it=dstMni->begin();it!=dstMni->end();)
3950+
{
3951+
MemberDefMutable *dstMd = toMemberDefMutable((*it)->memberDef());
3952+
if (dstMd && dstMd->isVariable() && !dstMd->name().startsWith("__"))
3953+
{
3954+
//printf(" hiding member %s\n",qPrint(dstMd->name()));
3955+
// hide a member variable if it is already defined in a base class, unless
3956+
// it is a __private variable
3957+
removeMemberFromLists(dstMd);
3958+
it = dstMni->erase(it);
3959+
}
3960+
else
3961+
{
3962+
++it;
3963+
}
3964+
}
3965+
if (dstMni->empty()) // if the list has become empty, remove the entry from the dictionary
3966+
{
3967+
dstMnd.del(srcMni->memberName());
3968+
}
3969+
}
3970+
}
3971+
}
3972+
}
3973+
39223974
/*!
39233975
* recursively merges the 'all members' lists of a class base
39243976
* with that of this class. Must only be called for classes without
@@ -3927,7 +3979,14 @@ void ClassDefImpl::mergeMembersFromBaseClasses(bool mergeVirtualBaseClass)
39273979
void ClassDefImpl::mergeMembers()
39283980
{
39293981
if (m_impl->membersMerged) return;
3930-
if (getLanguage()==SrcLangExt::Python) return; // python does not have member overloading, see issue 8480
3982+
if (getLanguage()==SrcLangExt::Python)
3983+
{
3984+
for (const auto &bcd : baseClasses())
3985+
{
3986+
ClassDefMutable *bClass=toClassDefMutable(bcd.classDef);
3987+
hideDerivedVariablesInPython(bClass);
3988+
}
3989+
}
39313990

39323991
//printf("> %s::mergeMembers()\n",qPrint(name()));
39333992

@@ -4519,20 +4578,20 @@ void ClassDefImpl::sortMemberLists()
45194578
int ClassDefImpl::countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
45204579
MemberListType lt2,bool invert,bool showAlways,ClassDefSet &visitedClasses) const
45214580
{
4522-
//printf("%s: countMemberDeclarations for %d and %d\n",qPrint(name()),lt.to_int(),lt2.to_int());
4581+
//printf("%s: countMemberDeclarations for %s and %s\n",qPrint(name()),lt.to_string(),lt2.to_string());
45234582
int count=0;
45244583
MemberList * ml = getMemberList(lt);
45254584
MemberList * ml2 = getMemberList(lt2);
45264585
if (getLanguage()!=SrcLangExt::VHDL) // use specific declarations function
45274586
{
45284587
if (ml)
45294588
{
4530-
count+=ml->numDecMembers();
4589+
count+=ml->numDecMembers(inheritedFrom);
45314590
//printf("-> ml=%d\n",ml->numDecMembers());
45324591
}
45334592
if (ml2)
45344593
{
4535-
count+=ml2->numDecMembers();
4594+
count+=ml2->numDecMembers(inheritedFrom);
45364595
//printf("-> ml2=%d\n",ml2->numDecMembers());
45374596
}
45384597
// also include grouped members that have their own section in the class (see bug 722759)
@@ -4601,8 +4660,8 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt,
46014660
int inhCount = 0;
46024661
int count = countMembersIncludingGrouped(lt,inheritedFrom,FALSE);
46034662
bool process = count>0;
4604-
//printf("%s: countInheritedDecMembers: lt=%d process=%d count=%d invert=%d\n",
4605-
// qPrint(name()),lt.to_int(),process,count,invert);
4663+
//printf("%s: countInheritedDecMembers: lt=%s process=%d count=%d invert=%d\n",
4664+
// qPrint(name()),lt.to_string(),process,count,invert);
46064665
if ((process^invert) || showAlways)
46074666
{
46084667
for (const auto &ibcd : m_impl->inherits)
@@ -4613,8 +4672,8 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt,
46134672
if (icd && icd->isLinkable())
46144673
{
46154674
convertProtectionLevel(lt,ibcd.prot,&lt1,&lt2);
4616-
//printf("%s: convert %d->(%d,%d) prot=%d\n",
4617-
// qPrint(icd->name()),lt.to_int(),lt1.to_int(),lt2.to_int(),ibcd.prot);
4675+
//printf("%s: convert %s->(%s,%s) prot=%d\n",
4676+
// qPrint(icd->name()),lt.to_string(),lt1.to_string(),lt2.to_string(),ibcd.prot);
46184677
if (visitedClasses.find(icd)==visitedClasses.end())
46194678
{
46204679
visitedClasses.insert(icd); // guard for multiple virtual inheritance
@@ -4626,6 +4685,7 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt,
46264685
}
46274686
}
46284687
}
4688+
//printf("%s: count=%d\n",qPrint(name()),inhCount);
46294689
return inhCount;
46304690
}
46314691

@@ -4706,7 +4766,7 @@ int ClassDefImpl::countMembersIncludingGrouped(MemberListType lt,
47064766
}
47074767
}
47084768
//printf("%s:countMembersIncludingGrouped(lt=%s,%s)=%d\n",
4709-
// qPrint(name()),qPrint(lt.to_string()),ml?qPrint(ml->listType().toLabel()):"<none>",count);
4769+
// qPrint(name()),qPrint(lt.to_string()),ml?qPrint(ml->listType().to_string()):"<none>",count);
47104770
return count;
47114771
}
47124772

@@ -4777,18 +4837,18 @@ void ClassDefImpl::writeMemberDeclarations(OutputList &ol,ClassDefSet &visitedCl
47774837
}
47784838
else
47794839
{
4780-
//printf("%s::writeMemberDeclarations(%s) ml=%p ml2=%p\n",qPrint(name()),qPrint(title),ml,ml2);
4840+
//printf("%s::writeMemberDeclarations(%s) ml=%p ml2=%p\n",qPrint(name()),qPrint(title),(void*)ml,(void*)ml2);
47814841
QCString tt = title, st = subTitle;
47824842
if (ml)
47834843
{
4784-
//printf(" writeDeclarations type=%s count=%d\n",qPrint(lt.to_string()),ml->numDecMembers());
4844+
//printf(" writeDeclarations ml type=%s count=%d\n",qPrint(lt.to_string()),ml->numDecMembers(inheritedFrom));
47854845
ml->writeDeclarations(ol,this,nullptr,nullptr,nullptr,nullptr,tt,st,FALSE,showInline,inheritedFrom,lt,true);
47864846
tt.clear();
47874847
st.clear();
47884848
}
47894849
if (ml2)
47904850
{
4791-
//printf(" writeDeclarations type=%s count=%d\n",qPrint(lt2.to_string()),ml2->numDecMembers());
4851+
//printf(" writeDeclarations ml2 type=%s count=%d\n",qPrint(lt2.to_string()),ml2->numDecMembers(inheritedFrom));
47924852
ml2->writeDeclarations(ol,this,nullptr,nullptr,nullptr,nullptr,tt,st,FALSE,showInline,inheritedFrom,lt,ml==nullptr);
47934853
}
47944854
bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);

src/doxygen.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8304,12 +8304,14 @@ static void computeMemberRelationsForBaseClass(const ClassDef *cd,const BaseClas
83048304
MemberDefMutable *bmd = toMemberDefMutable(ibmd->memberDef());
83058305
if (bmd) // not part of an inline namespace
83068306
{
8307-
if (bmd->virtualness()!=Specifier::Normal ||
8308-
bmd->getLanguage()==SrcLangExt::Python ||
8309-
bmd->getLanguage()==SrcLangExt::Java ||
8310-
bmd->getLanguage()==SrcLangExt::PHP ||
8311-
mbcd->compoundType()==ClassDef::Interface ||
8312-
mbcd->compoundType()==ClassDef::Protocol)
8307+
auto lang = bmd->getLanguage();
8308+
auto compType = mbcd->compoundType();
8309+
if (bmd->virtualness()!=Specifier::Normal ||
8310+
lang==SrcLangExt::Python ||
8311+
lang==SrcLangExt::Java ||
8312+
lang==SrcLangExt::PHP ||
8313+
compType==ClassDef::Interface ||
8314+
compType==ClassDef::Protocol)
83138315
{
83148316
const ArgumentList &bmdAl = bmd->argumentList();
83158317
const ArgumentList &mdAl = md->argumentList();
@@ -8318,13 +8320,14 @@ static void computeMemberRelationsForBaseClass(const ClassDef *cd,const BaseClas
83188320
// qPrint(argListToString(mdAl))
83198321
// );
83208322
if (
8321-
bmd->getLanguage()==SrcLangExt::Python ||
8323+
lang==SrcLangExt::Python ||
83228324
matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),&bmdAl,
83238325
md->getOuterScope(), md->getFileDef(), &mdAl,
8324-
TRUE,bmd->getLanguage()
8326+
TRUE,lang
83258327
)
83268328
)
83278329
{
8330+
if (lang==SrcLangExt::Python && md->name().startsWith("__")) continue; // private members do not reimplement
83288331
//printf("match!\n");
83298332
const MemberDef *rmd = md->reimplements();
83308333
if (rmd==nullptr) // not already assigned

src/memberlist.cpp

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -119,62 +119,51 @@ int MemberList::countInheritableMembers(const ClassDef *inheritedFrom) const
119119
/*! Count the number of members in this list that are visible in
120120
* the declaration part of a compound's documentation page.
121121
*/
122-
void MemberList::countDecMembers()
122+
std::pair<int,int> MemberList::countDecMembers(const ClassDef *inheritedFrom) const
123123
{
124-
if (m_numDecMembers!=-1) return;
125-
126124
//printf("----- countDecMembers count=%d ----\n",count());
127-
/*
128-
m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0;
129-
m_typeCnt=m_seqCnt=m_dictCnt=m_protoCnt=m_defCnt=m_friendCnt=0;
130-
*/
131-
m_numDecMembers=0;
125+
int numDecMembers=0;
126+
int numDecEnumValues=0;
132127
for (const auto &md : m_members)
133128
{
134129
//printf("MemberList::countDecMembers(md=%s,%d)\n",qPrint(md->name()),md->isBriefSectionVisible());
135-
if (md->isBriefSectionVisible())
130+
if ((inheritedFrom==nullptr || !md->isReimplementedBy(inheritedFrom)) &&
131+
md->isBriefSectionVisible())
136132
{
137133
switch(md->memberType())
138134
{
139135
case MemberType::Variable: // fall through
140136
case MemberType::Event: // fall through
141-
case MemberType::Property: /*m_varCnt++,*/
142-
m_numDecMembers++;
137+
case MemberType::Property: numDecMembers++;
143138
break;
144139
// apparently necessary to get this to show up in declarations section?
145140
case MemberType::Interface: // fall through
146141
case MemberType::Service: // fall through
147142
case MemberType::Function: // fall through
148143
case MemberType::Signal: // fall through
149144
case MemberType::DCOP: // fall through
150-
case MemberType::Slot: if (!md->isRelated() || md->getClassDef())
151-
/*m_funcCnt++,*/
152-
m_numDecMembers++;
145+
case MemberType::Slot: if (!md->isRelated() || md->getClassDef())
146+
numDecMembers++;
153147
break;
154-
case MemberType::Enumeration: /*m_enumCnt++,*/
155-
m_numDecMembers++;
148+
case MemberType::Enumeration:
149+
numDecMembers++;
156150
break;
157-
case MemberType::EnumValue: m_numDecEnumValues++;
158-
m_numDecMembers++;
151+
case MemberType::EnumValue: numDecEnumValues++;
152+
numDecMembers++;
159153
break;
160-
case MemberType::Typedef: /*m_typeCnt++,*/
161-
m_numDecMembers++;
154+
case MemberType::Typedef: numDecMembers++;
162155
break;
163-
case MemberType::Sequence: /*m_seqCnt++,*/
164-
m_numDecMembers++;
156+
case MemberType::Sequence: numDecMembers++;
165157
break;
166-
case MemberType::Dictionary: /*m_dictCnt++,*/
167-
m_numDecMembers++;
158+
case MemberType::Dictionary: numDecMembers++;
168159
break;
169-
//case MemberType::Prototype: m_protoCnt++,m_numDecMembers++; break;
170160
case MemberType::Define: if (Config_getBool(EXTRACT_ALL) ||
171161
!md->argsString().isEmpty() ||
172162
!md->initializer().isEmpty() ||
173163
md->hasDocumentation()
174-
) /*m_defCnt++,*/ m_numDecMembers++;
164+
) numDecMembers++;
175165
break;
176-
case MemberType::Friend: /*m_friendCnt++,*/
177-
m_numDecMembers++;
166+
case MemberType::Friend: numDecMembers++;
178167
break;
179168
default:
180169
err("Unknown member type found for member '%s'!\n",qPrint(md->name()));
@@ -184,24 +173,18 @@ void MemberList::countDecMembers()
184173
for (const auto &mg : m_memberGroupRefList)
185174
{
186175
mg->countDecMembers();
187-
/*
188-
m_varCnt+=mg->varCount();
189-
m_funcCnt+=mg->funcCount();
190-
m_enumCnt+=mg->enumCount();
191-
m_enumValCnt+=mg->enumValueCount();
192-
m_typeCnt+=mg->typedefCount();
193-
m_seqCnt+=mg->sequenceCount();
194-
m_dictCnt+=mg->dictionaryCount();
195-
m_protoCnt+=mg->protoCount();
196-
m_defCnt+=mg->defineCount();
197-
m_friendCnt+=mg->friendCount();
198-
*/
199-
m_numDecMembers+=mg->numDecMembers();
200-
m_numDecEnumValues+=mg->numDecEnumValues();
176+
numDecMembers+=mg->numDecMembers();
177+
numDecEnumValues+=mg->numDecEnumValues();
201178
}
202179
//printf("----- end countDecMembers ----\n");
203180

204-
//printf("MemberList::countDecMembers()=%d\n",m_numDecMembers);
181+
return std::make_pair(numDecMembers,numDecEnumValues);
182+
}
183+
184+
void MemberList::countDecMembers() const
185+
{
186+
if (m_numDecMembers!=-1) return; // already cached
187+
std::tie(m_numDecMembers, m_numDecEnumValues) = countDecMembers(nullptr); // cache new values
205188
}
206189

207190
void MemberList::countDocMembers()
@@ -528,9 +511,9 @@ void MemberList::writeDeclarations(OutputList &ol,
528511
//printf("%p: MemberList::writeDeclaration(title='%s',subtitle='%s')=%d inheritedFrom=%p\n",
529512
// (void*)this,qPrint(title),qPrint(subtitle),numDecMembers(),(void*)inheritedFrom);
530513

531-
int num = numDecMembers();
514+
int num = numDecMembers(inheritedFrom);
532515
int numEnumValues = numDecEnumValues();
533-
if (inheritedFrom)
516+
if (inheritedFrom && num>0)
534517
{
535518
if (cd && !optimizeVhdl)
536519
{

src/memberlist.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <vector>
2020
#include <algorithm>
21+
#include <utility>
2122

2223
#include "memberdef.h"
2324
#include "linkedmap.h"
@@ -113,12 +114,16 @@ class MemberList : public MemberVector
113114
MemberListType listType() const { return m_listType; }
114115
MemberListContainer container() const { return m_container; }
115116

116-
int numDecMembers() const { ASSERT(m_numDecMembers!=-1); return m_numDecMembers; }
117+
int numDecMembers(const ClassDef *inheritedFrom) const
118+
{ return countDecMembers(inheritedFrom).first; }
119+
int numDecMembers() const
120+
{ ASSERT(m_numDecMembers!=-1); return m_numDecMembers; }
117121
int numDecEnumValues() const { return m_numDecEnumValues; }
118122
int numDocMembers() const { ASSERT(m_numDocMembers!=-1); return m_numDocMembers; }
119123
int numDocEnumValues() const { return m_numDocEnumValues; }
120124
bool needsSorting() const { return m_needsSorting; }
121-
void countDecMembers();
125+
void countDecMembers() const;
126+
std::pair<int,int> countDecMembers(const ClassDef *inheritedFrom) const;
122127
void countDocMembers();
123128
int countInheritableMembers(const ClassDef *inheritedFrom) const;
124129
void writePlainDeclarations(OutputList &ol,bool inGroup,
@@ -147,8 +152,8 @@ class MemberList : public MemberVector
147152

148153
private:
149154
int countEnumValues(const MemberDef *md) const;
150-
int m_numDecMembers; // number of members in the brief part of the memberlist
151-
int m_numDecEnumValues;
155+
mutable int m_numDecMembers; // number of members in the brief part of the memberlist
156+
mutable int m_numDecEnumValues;
152157
int m_numDocMembers; // number of members in the detailed part of the memberlist
153158
int m_numDocEnumValues;
154159
MemberGroupRefList m_memberGroupRefList;

0 commit comments

Comments
 (0)