diff options
Diffstat (limited to 'src/code.l')
-rw-r--r-- | src/code.l | 416 |
1 files changed, 126 insertions, 290 deletions
@@ -26,12 +26,14 @@ * includes */ +#include <utility> #include <memory> #include <algorithm> #include <unordered_map> #include <stack> #include <vector> #include <string> +#include <mutex> #include <stdio.h> #include <assert.h> @@ -55,6 +57,7 @@ #include "filename.h" #include "namespacedef.h" #include "tooltip.h" +#include "scopedtypevariant.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -68,10 +71,6 @@ #define USE_STATE2STRING 0 -/* ----------------------------------------------------------------- - * statics - */ - // context for an Objective-C method call struct ObjCCallCtx { @@ -87,116 +86,11 @@ struct ObjCCallCtx int braceCount; }; -/*! Represents a stack of variable to class mappings as found in the - * code. Each scope is enclosed in pushScope() and popScope() calls. - * Variables are added by calling addVariables() and one can search - * for variable using findVariable(). - */ -class VariableContext -{ - public: - static const ClassDef *dummyContext; - - using Scope = std::unordered_map<std::string,const ClassDef*>; - - void pushScope() - { - m_scopes.push_back(Scope()); - DBG_CTX((stderr,"** Push var context %zu\n",m_scopes.size())); - } - - void popScope() - { - if (!m_scopes.empty()) - { - DBG_CTX((stderr,"** Pop var context %zu\n",m_scopes.size())); - m_scopes.pop_back(); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop var context\n")); - } - } - - void clear() - { - m_scopes.clear(); - m_globalScope.clear(); - } - - void addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name); - const ClassDef *findVariable(const QCString &name); - - private: - Scope m_globalScope; - std::vector<Scope> m_scopes; -}; - -//------------------------------------------------------------------- - -class CallContext -{ - public: - struct Ctx - { - Ctx(QCString name_, QCString type_) : name(name_), type(type_) {} - QCString name; - QCString type; - const Definition *d = 0; - }; - - CallContext() - { - clear(); - } - - void setScope(const Definition *d) - { - Ctx &ctx = m_defList.back(); - DBG_CTX((stderr,"** Set call context %s (%p)\n",d==0 ? "<null>" : d->name().data(),d)); - ctx.d=d; - } - void pushScope(QCString name_, QCString type_) - { - m_defList.push_back(Ctx(name_,type_)); - DBG_CTX((stderr,"** Push call context %zu\n",m_defList.size())); - } - void popScope(QCString &name_, QCString &type_) - { - if (m_defList.size()>1) - { - DBG_CTX((stderr,"** Pop call context %zu\n",m_defList.size())); - const Ctx &ctx = m_defList.back(); - name_ = ctx.name; - type_ = ctx.type; - m_defList.pop_back(); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop call context\n")); - } - } - void clear() - { - DBG_CTX((stderr,"** Clear call context\n")); - m_defList.clear(); - m_defList.push_back(Ctx("","")); - } - const Definition *getScope() const - { - return m_defList.back().d; - } - - private: - std::vector<Ctx> m_defList; -}; - - struct codeYY_state { CodeOutputInterface * code = 0; - std::unordered_map< std::string, std::unique_ptr<ClassDef> > codeClassMap; + std::unordered_map< std::string, ScopedTypeVariant > codeClassMap; QCString curClassName; QStrList curClassBases; @@ -260,7 +154,7 @@ struct codeYY_state std::stack<int> classScopeLengthStack; - int prefixed_with_this_keyword = FALSE; + int isPrefixedWithThis = FALSE; const Definition *searchCtx = 0; bool collectXRefs = FALSE; @@ -312,7 +206,7 @@ static void addParmType(yyscan_t yyscanner); static void addUsingDirective(yyscan_t yyscanner,const char *name); static void setParameterList(yyscan_t yyscanner,const MemberDef *md); static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Definition *d); -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); static void updateCallContextForSmartPointer(yyscan_t yyscanner); static bool getLinkInScope(yyscan_t yyscanner,const QCString &c, // scope const QCString &m, // member @@ -342,7 +236,12 @@ static QCString escapeWord(yyscan_t yyscanner,const char *s); static QCString escapeComment(yyscan_t yyscanner,const char *s); static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const QCString &kw); static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void addVariable(yyscan_t yyscanner,QCString type,QCString name); +//------------------------------------------------------------------- + +static std::mutex g_searchIndexMutex; +static std::mutex g_tooltipMutex; /* ----------------------------------------------------------------- */ @@ -551,7 +450,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <ObjCParams>{ID} { yyextra->code->codify(yytext); yyextra->parmName=yytext; - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); yyextra->parmType.resize(0);yyextra->parmName.resize(0); } <ObjCMethod,ObjCParams,ObjCParamType>{ID} { @@ -827,7 +726,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->name = yytext; if (yyextra->insideBody) { - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); + addVariable(yyscanner,yyextra->type,yyextra->name); } generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); } @@ -860,8 +759,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} if (getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->curClassName)==0) { DBG_CTX((stderr,"Adding new class %s\n",yyextra->curClassName.data())); - std::unique_ptr<ClassDef> ncd { createClassDef("<code>",1,1, - yyextra->curClassName,ClassDef::Class,0,0,FALSE) }; + ScopedTypeVariant var(yyextra->curClassName); // insert base classes. char *s=yyextra->curClassBases.first(); while (s) @@ -870,16 +768,16 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} auto it = yyextra->codeClassMap.find(s); if (it!=yyextra->codeClassMap.end()) { - bcd=it->second.get(); + bcd = dynamic_cast<const ClassDef*>(it->second.globalDef()); } if (bcd==0) bcd=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,s); - if (bcd && bcd!=ncd.get()) + if (bcd && bcd->name()!=yyextra->curClassName) { - ncd->insertBaseClass(const_cast<ClassDef*>(bcd),s,Public,Normal); + var.localDef()->insertBaseClass(bcd->name()); } s=yyextra->curClassBases.next(); } - yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(ncd))); + yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var))); } //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count()); } @@ -1005,7 +903,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <UsingName>\n { codifyLines(yyscanner,yytext); BEGIN(Body); } <UsingName>. { codifyLines(yyscanner,yytext); BEGIN(Body); } <Body,FuncCall>"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C# - yyextra->prefixed_with_this_keyword = TRUE; + yyextra->isPrefixedWithThis = TRUE; } <Body>{KEYWORD}/([^a-z_A-Z0-9]) { if (yyextra->lang==SrcLangExt_Java && qstrcmp("internal",yytext) ==0) REJECT; @@ -1039,7 +937,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} endFontClass(yyscanner); // insert the variable in the parent scope, see bug 546158 yyextra->theVarContext.popScope(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); yyextra->theVarContext.pushScope(); yyextra->name.resize(0);yyextra->type.resize(0); } @@ -1359,9 +1257,9 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN( MemberCall ); } <MemberCall>{SCOPETNAME}/{BN}*"(" { - if (yyextra->theCallContext.getScope()) + if (yyextra->theCallContext.getScope().globalDef()) { - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) { yyextra->code->codify(yytext); addToSearchIndex(yyscanner,yytext); @@ -1385,10 +1283,10 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } } <MemberCall>{SCOPENAME}/{B}* { - if (yyextra->theCallContext.getScope()) + if (yyextra->theCallContext.getScope().globalDef()) { - DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope())); - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) + DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope().globalDef())); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) { yyextra->code->codify(yytext); addToSearchIndex(yyscanner,yytext); @@ -1435,7 +1333,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} { //printf("AddVariable: '%s' '%s' context=%d\n", // yyextra->type.data(),yyextra->name.data(),yyextra->theVarContext.count()); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); + addVariable(yyscanner,yyextra->type,yyextra->name); } yyextra->name.resize(0); } @@ -1665,7 +1563,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } <MemberCall2,FuncCall>, { yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); yyextra->parmType.resize(0);yyextra->parmName.resize(0); } <MemberCall2,FuncCall>"{" { @@ -1727,13 +1625,13 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->parmType=yyextra->parmName; yyextra->parmName.resize(0); } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } else { yyextra->parmType = yyextra->parmName; yyextra->parmName.resize(0); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } yyextra->theCallContext.popScope(yyextra->name, yyextra->type); yyextra->inForEachExpression = FALSE; @@ -1762,10 +1660,10 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} if (!yyextra->type.isEmpty()) { DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",yyextra->type.data(),yyextra->name.data())); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); + addVariable(yyscanner,yyextra->type,yyextra->name); } yyextra->parmType.resize(0);yyextra->parmName.resize(0); - yyextra->theCallContext.setScope(0); + yyextra->theCallContext.setScope(ScopedTypeVariant()); if (*yytext==';' || yyextra->insideBody) { if (!yyextra->insideBody) @@ -1791,7 +1689,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} { yyextra->theVarContext.pushScope(); } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); //yyextra->theCallContext.popScope(yyextra->name, yyextra->type); yyextra->parmType.resize(0);yyextra->parmName.resize(0); int index = yyextra->name.findRev("::"); @@ -1865,7 +1763,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } <OldStyleArgs>[,;] { yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); if (*yytext==';') yyextra->parmType.resize(0); yyextra->parmName.resize(0); } @@ -2290,7 +2188,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} /*@ ---------------------------------------------------------------------------- */ -void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name) +static void addVariable(yyscan_t yyscanner,QCString type,QCString name) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data()); @@ -2307,102 +2205,44 @@ void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const if (ltype.isEmpty() || lname.isEmpty()) return; DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' currentDefinition=%s\n", ltype.data(),lname.data(),yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>")); - Scope *scope = m_scopes.empty() ? &m_globalScope : &m_scopes.back(); - const ClassDef *varType = 0; auto it = yyextra->codeClassMap.find(ltype.str()); if (it!=yyextra->codeClassMap.end()) // look for class definitions inside the code block { - varType = it->second.get(); - } - if (varType==0) // look for global class definitions - { - varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); - } - int i=0; - if (varType) - { DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); - scope->emplace(std::make_pair(lname.str(),varType)); // add it to a list + yyextra->theVarContext.addVariable(lname,std::move(it->second)); // add it to a list } - else if ((i=ltype.find('<'))!=-1) + else { - // probably a template class - QCString typeName(ltype.left(i)); - const ClassDef* newDef = 0; - QCString templateArgs(ltype.right(ltype.length() - i)); - it = yyextra->codeClassMap.find(typeName.str()); - if (!typeName.isEmpty()) - { - if (it!=yyextra->codeClassMap.end()) // look for class definitions inside the code block - { - varType = it->second.get(); - } - else // otherwise look for global class definitions - { - varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,typeName,0,0,TRUE,TRUE); - } - } - if (varType && !varType->templateArguments().empty()) // and it must be a template - { - newDef = varType->getVariableInstance( templateArgs ); - } - if (newDef) + const ClassDef *varDef = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); + int i=0; + if (varDef) { - DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data())); - scope->emplace(std::make_pair(lname.str(), newDef)); + DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list } - else + else if ((i=ltype.find('<'))!=-1) { - // Doesn't seem to be a template. Try just the base name. + // probably a template class + QCString typeName(ltype.left(i)); addVariable(yyscanner,typeName,name); } - } - else - { - if (!m_scopes.empty()) // for local variables add a dummy entry so the name - // is hidden to avoid false links to global variables with the same name - // TODO: make this work for namespaces as well! - { - DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); - scope->emplace(std::make_pair(lname.str(),dummyContext)); - } else { - DBG_CTX((stderr,"** addVariable: not adding variable!\n")); - } - } -} - -const ClassDef *VariableContext::findVariable(const QCString &name) -{ - if (name.isEmpty()) return 0; - const ClassDef *result = 0; - - // search from inner to outer scope - auto it = std::rbegin(m_scopes); - while (it != std::rend(m_scopes)) - { - auto it2 = it->find(name.str()); - if (it2 != std::end(*it)) - { - result = it2->second; - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; + if (!yyextra->theVarContext.atGlobalScope()) // for local variables add a dummy entry so the name + // is hidden to avoid false links to global variables with the same name + // TODO: make this work for namespaces as well! + { + DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant()); + } + else + { + DBG_CTX((stderr,"** addVariable: not adding variable!\n")); + } } - ++it; } - // nothing found -> also try the global scope - auto it2 = m_globalScope.find(name.str()); - if (it2 != m_globalScope.end()) - { - result = it2->second; - } - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; } -const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8; - //------------------------------------------------------------------- /*! add class/namespace name s to the scope */ @@ -2445,6 +2285,7 @@ static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { + std::lock_guard<std::mutex> lock(g_searchIndexMutex); if (yyextra->searchCtx) { yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); @@ -2461,6 +2302,7 @@ static void addToSearchIndex(yyscan_t yyscanner,const char *text) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { + std::lock_guard<std::mutex> lock(g_searchIndexMutex); yyextra->code->addWord(text,FALSE); } } @@ -2620,8 +2462,11 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, const char *text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + { + std::lock_guard<std::mutex> lock(g_tooltipMutex); + TooltipManager::instance()->addTooltip(d); + } QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -2702,7 +2547,7 @@ static void setParameterList(yyscan_t yyscanner,const MemberDef *md) if (i!=-1) yyextra->parmType = yyextra->parmType.left(i); yyextra->parmType.stripPrefix("const "); yyextra->parmType=yyextra->parmType.stripWhiteSpace(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } } @@ -2735,7 +2580,7 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Def return 0; } -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) { if (name.isEmpty()) return 0; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -2754,7 +2599,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) if (md) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md; } } @@ -2767,7 +2612,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) if (md) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md; } } @@ -2775,32 +2620,32 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) } const MemberName *mn; - const ClassDef *mcd = yyextra->theVarContext.findVariable(name); - if (mcd) // local variable + const ScopedTypeVariant *mcv = yyextra->theVarContext.findVariable(name); + if (mcv) { DBG_CTX((stderr,"local variable?\n")); - if (mcd!=VariableContext::dummyContext) + if (mcv->type()!=ScopedTypeVariant::Dummy) // locally found variable { - DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(mcd); + DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcv.name().data())); + yyextra->theCallContext.setScope(*mcv); } } else { DBG_CTX((stderr,"class member? scope=%s\n",yyextra->classScope.data())); // look for a class member - mcd = getClass(yyextra->classScope); + const ClassDef *mcd = getClass(yyextra->classScope); if (mcd) { DBG_CTX((stderr,"Inside class %s\n",mcd->name().data())); - MemberDef *md=mcd->getMemberByName(name); + const MemberDef *md=mcd->getMemberByName(name); if (md) { DBG_CTX((stderr,"Found member %s\n",md->name().data())); if (yyextra->scopeStack.empty() || yyextra->scopeStack.top()!=CLASSBLOCK) { DBG_CTX((stderr,"class member '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); } return md; } @@ -2816,7 +2661,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) const std::unique_ptr<MemberDef> &md=mn->front(); if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md.get(); } return 0; @@ -2836,7 +2681,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) (yyextra->forceTagReference.isEmpty() || yyextra->forceTagReference==md->getReference()) ) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); //printf("returning member %s in source file %s\n",md->name().data(),yyextra->sourceFileDef->name().data()); return md.get(); } @@ -2850,7 +2695,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) static void updateCallContextForSmartPointer(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - const Definition *d = yyextra->theCallContext.getScope(); + const Definition *d = yyextra->theCallContext.getScope().globalDef(); //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>"); const MemberDef *md; if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<const ClassDef*>(d))->isSmartPointer())) @@ -2858,7 +2703,7 @@ static void updateCallContextForSmartPointer(yyscan_t yyscanner) const ClassDef *ncd = stripClassName(yyscanner,md->typeString(),md->getOuterScope()); if (ncd) { - yyextra->theCallContext.setScope(ncd); + yyextra->theCallContext.setScope(ScopedTypeVariant(ncd)); //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data()); } } @@ -2904,7 +2749,7 @@ static bool getLinkInScope(yyscan_t yyscanner, if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef(); if (d && d->isLinkable()) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p yyextra->insideBody=%d\n", // yyextra->currentDefinition,yyextra->currentMemberDef,yyextra->insideBody); @@ -2981,12 +2826,13 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { className = substitute(className,".","::"); // for PHP namespaces } - const ClassDef *cd=0,*lcd=0; + const ScopedTypeVariant *lcd=0; + const ClassDef *cd=0; const MemberDef *md=0; bool isLocal=FALSE; //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); - if (!yyextra->prefixed_with_this_keyword || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable + if (!yyextra->isPrefixedWithThis || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable { const Definition *d = yyextra->currentDefinition; //printf("d=%s yyextra->sourceFileDef=%s\n",d?d->name().data():"<none>",yyextra->sourceFileDef?yyextra->sourceFileDef->name().data():"<none>"); @@ -3006,7 +2852,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, const NamespaceDef *nd = getResolvedNamespace(className); if (nd && nd->isLinkable()) { - yyextra->theCallContext.setScope(nd); + yyextra->theCallContext.setScope(ScopedTypeVariant(nd)); addToSearchIndex(yyscanner,className); writeMultiLineCodeLink(yyscanner,*yyextra->code,nd,clName); return; @@ -3026,10 +2872,10 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, else { //printf("local variable!\n"); - if (lcd!=VariableContext::dummyContext) + if (lcd->type()!=ScopedTypeVariant::Dummy) { //printf("non-dummy context lcd=%s!\n",lcd->name().data()); - yyextra->theCallContext.setScope(lcd); + yyextra->theCallContext.setScope(*lcd); // to following is needed for links to a global variable, but is // no good for a link to a local variable that is also a global symbol. @@ -3042,7 +2888,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, isLocal=TRUE; DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); } - yyextra->prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls + yyextra->isPrefixedWithThis = FALSE; // discard the "this" prefix for the next calls if (cd && cd->isLinkable()) // is it a linkable class { @@ -3061,7 +2907,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, } writeMultiLineCodeLink(yyscanner,ol,cd,clName); addToSearchIndex(yyscanner,className); - yyextra->theCallContext.setScope(cd); + yyextra->theCallContext.setScope(ScopedTypeVariant(cd)); if (md) { const Definition *d = md->getOuterScope()==Doxygen::globalScope ? @@ -3081,18 +2927,19 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { if (md==0) // not found as a typedef { + AccessStack accessStack; md = setCallContextForVar(yyscanner,clName); //printf("setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition); if (md && yyextra->currentDefinition) { DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", md->name().data(),yyextra->currentDefinition->name().data(), - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md), + isAccessibleFrom(accessStack,yyextra->currentDefinition,yyextra->sourceFileDef,md), md->getOuterScope()->name().data())); } if (md && yyextra->currentDefinition && - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md)==-1) + isAccessibleFrom(accessStack,yyextra->currentDefinition,yyextra->sourceFileDef,md)==-1) { md=0; // variable not accessible } @@ -3165,7 +3012,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const ClassDef *typeClass = stripClassName(yyscanner,removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); - yyextra->theCallContext.setScope(typeClass); + yyextra->theCallContext.setScope(ScopedTypeVariant(typeClass)); const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? xmd->getFileDef() : xmd->getOuterScope(); @@ -3216,7 +3063,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const Definition *innerDef = cd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3230,7 +3077,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const Definition *innerDef = nd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3251,23 +3098,22 @@ static void generateMemberLink(yyscan_t yyscanner, if (varName.isEmpty()) return; // look for the variable in the current context - const ClassDef *vcd = yyextra->theVarContext.findVariable(varName); - if (vcd) + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(varName); + if (stv) { - if (vcd!=VariableContext::dummyContext) + if (stv->type()!=ScopedTypeVariant::Dummy) { //printf("Class found!\n"); - if (getLink(yyscanner,vcd->name(),memName,ol)) + if (getLink(yyscanner,stv->name(),memName,ol)) { //printf("Found result!\n"); return; } - if (vcd->baseClasses()) + if (stv->localDef() && !stv->localDef()->baseClasses().empty()) { - BaseClassListIterator bcli(*vcd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + for (const auto &bcName : stv->localDef()->baseClasses()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),memName,ol)) + if (getLink(yyscanner,bcName,memName,ol)) { //printf("Found result!\n"); return; @@ -3278,7 +3124,7 @@ static void generateMemberLink(yyscan_t yyscanner, } else // variable not in current context, maybe it is in a parent context { - vcd = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->classScope); + const ClassDef *vcd = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->classScope); if (vcd && vcd->isLinkable()) { //printf("Found class %s for variable '%s'\n",yyextra->classScope.data(),varName.data()); @@ -3350,7 +3196,6 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //CodeClassDef *ccd=0; - const ClassDef *ccd=0; QCString locScope=yyextra->classScope; QCString locFunc=removeRedundantWhiteSpace(funcName); if (yyextra->lang==SrcLangExt_PHP && locFunc.startsWith("self::")) locFunc=locFunc.mid(4); @@ -3416,37 +3261,31 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons auto it = yyextra->codeClassMap.find(fullScope.str()); if (it!=yyextra->codeClassMap.end()) { - ccd = it->second.get(); - } - if (ccd && ccd->baseClasses()) - { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),locFunc,ol,funcName)) + for (const auto &bcName : ccd.localDef()->baseClasses()) { - goto exit; + if (getLink(yyscanner,bcName,locFunc,ol,funcName)) + { + goto exit; + } } } } } - if (!locScope.isEmpty()) + if (!locScope.isEmpty() && fullScope!=locScope) { auto it = yyextra->codeClassMap.find(locScope.str()); if (it!=yyextra->codeClassMap.end()) { - ccd = it->second.get(); - } - if (fullScope!=locScope && ccd) - { - //printf("using classScope %s\n",yyextra->classScope.data()); - if (ccd->baseClasses()) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + for (const auto &bcName : ccd.localDef()->baseClasses()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),funcWithScope,ol,funcName)) + if (getLink(yyscanner,bcName,funcWithScope,ol,funcName)) { goto exit; } @@ -3519,8 +3358,8 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) { //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(), // ctx->methodName.data()); - const ClassDef *cd = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); - if (cd==0) // not a local variable + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); + if (stv==0) // not a local variable { if (ctx->objectTypeOrName=="self") { @@ -3569,9 +3408,13 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) else // local variable { //printf(" object is local variable\n"); - if (cd!=VariableContext::dummyContext && !ctx->methodName.isEmpty()) + if (stv->globalDef() && !ctx->methodName.isEmpty()) { - ctx->method = cd->getMemberByName(ctx->methodName); + const ClassDef *cd = dynamic_cast<const ClassDef *>(stv->globalDef()); + if (cd) + { + ctx->method = cd->getMemberByName(ctx->methodName); + } //printf(" class=%p method=%p\n",cd,ctx->method); } } @@ -3659,20 +3502,14 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) { cd = cd->categoryOf(); } - const BaseClassList *bcd = cd->baseClasses(); - if (bcd) // get direct base class (there should be only one) + for (const auto &bclass : cd->baseClasses()) { - BaseClassListIterator bli(*bcd); - BaseClassDef *bclass; - for (bli.toFirst();(bclass=bli.current());++bli) + if (bclass.classDef->compoundType()!=ClassDef::Protocol) { - if (bclass->classDef->compoundType()!=ClassDef::Protocol) + ctx->objectType = bclass.classDef; + if (ctx->objectType && !ctx->methodName.isEmpty()) { - ctx->objectType = bclass->classDef; - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); } } } @@ -3690,7 +3527,6 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) } } else if (ctx->objectType && - ctx->objectType!=VariableContext::dummyContext && ctx->objectType->isLinkable() ) // object is class name { |