summaryrefslogtreecommitdiffstats
path: root/src/code.l
diff options
context:
space:
mode:
authorDimitri van Heesch <doxygen@gmail.com>2020-10-10 18:08:23 (GMT)
committerDimitri van Heesch <doxygen@gmail.com>2020-10-10 18:08:23 (GMT)
commit0bf6993635a859867db545c89a0712ba94e6c217 (patch)
treefe07697eadec6ed84662815362ba827fdd25b12f /src/code.l
parent2c7b7cb90091ea43b42bf4abe886631e073f639b (diff)
downloadDoxygen-0bf6993635a859867db545c89a0712ba94e6c217.zip
Doxygen-0bf6993635a859867db545c89a0712ba94e6c217.tar.gz
Doxygen-0bf6993635a859867db545c89a0712ba94e6c217.tar.bz2
Refactoring: Introduce ScopedTypeVariant
- Avoid creating new symbol definitions while generating syntax highlighted code. - Add some locking around shared data collection (search index & tooltips) to support concurrent processing - Unify some code that was duplicated in code.l and pycode.l
Diffstat (limited to 'src/code.l')
-rw-r--r--src/code.l393
1 files changed, 117 insertions, 276 deletions
diff --git a/src/code.l b/src/code.l
index 9374b40..a614140 100644
--- a/src/code.l
+++ b/src/code.l
@@ -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);
}
}
@@ -2621,7 +2463,10 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol,
{
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
- TooltipManager::instance()->addTooltip(d);
+ {
+ 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 ?
@@ -3165,7 +3011,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 +3062,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 +3076,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 +3097,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 +3123,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 +3195,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 +3260,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 +3357,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 +3407,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);
}
}
@@ -3690,7 +3532,6 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx)
}
}
else if (ctx->objectType &&
- ctx->objectType!=VariableContext::dummyContext &&
ctx->objectType->isLinkable()
) // object is class name
{