summaryrefslogtreecommitdiffstats
path: root/src/pycode.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/pycode.l')
-rw-r--r--src/pycode.l215
1 files changed, 54 insertions, 161 deletions
diff --git a/src/pycode.l b/src/pycode.l
index 68ec265..ea314da 100644
--- a/src/pycode.l
+++ b/src/pycode.l
@@ -52,6 +52,7 @@
#include "filedef.h"
#include "namespacedef.h"
#include "tooltip.h"
+#include "scopedtypevariant.h"
// Toggle for some debugging info
//#define DBG_CTX(x) fprintf x
@@ -62,103 +63,10 @@
#define USE_STATE2STRING 0
-/*! 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 PyVariableContext
-{
- public:
- static const ClassDef *dummyContext;
-
- using Scope = std::unordered_map<std::string,const ClassDef *>;
-
- void pushScope()
- {
- m_scopes.push_back(Scope());
- }
-
- void popScope()
- {
- if (!m_scopes.empty())
- {
- m_scopes.pop_back();
- }
- }
-
- void clear()
- {
- m_scopes.clear();
- m_globalScope.clear();
- }
-
- void clearExceptGlobal()
- {
- m_scopes.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 PyCallContext
-{
- public:
- struct Ctx
- {
- Ctx(QCString name_,QCString type_) : name(name_), type(type_) {}
- QCString name;
- QCString type;
- const ClassDef *cd = 0;
- };
-
- PyCallContext()
- {
- clear();
- }
-
- void setClass(const ClassDef *cd)
- {
- Ctx &ctx = m_classList.back();
- ctx.cd=cd;
- }
- void pushScope(const QCString &name_,const QCString type_)
- {
- m_classList.push_back(Ctx(name_,type_));
- }
- void popScope(QCString &name_,QCString &type_)
- {
- if (m_classList.size()>1)
- {
- const Ctx &ctx = m_classList.back();
- name_ = ctx.name;
- type_ = ctx.type;
- m_classList.pop_back();
- }
- }
- void clear()
- {
- m_classList.clear();
- m_classList.push_back(Ctx("",""));
- }
- const ClassDef *getClass() const
- {
- return m_classList.back().cd;
- }
-
- private:
- std::vector<Ctx> m_classList;
-};
-
struct pycodeYY_state
{
- std::unordered_map< std::string, std::unique_ptr<ClassDef> > codeClassMap;
+ std::unordered_map< std::string, ScopedTypeVariant > codeClassMap;
QCString curClassName;
QStrList curClassBases;
@@ -196,8 +104,8 @@ struct pycodeYY_state
QCString docBlock; //!< contents of all lines of a documentation block
bool endComment = FALSE;
- PyVariableContext theVarContext;
- PyCallContext theCallContext;
+ VariableContext theVarContext;
+ CallContext theCallContext;
};
@@ -205,9 +113,6 @@ struct pycodeYY_state
static const char *stateToString(int state);
#endif
-const ClassDef *PyVariableContext::dummyContext = (ClassDef*)0x8;
-
-
static void startCodeLine(yyscan_t yyscanner);
static int countLines(yyscan_t yyscanner);
static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor);
@@ -235,6 +140,16 @@ static void findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol,
static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength);
static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
+#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l
+static void addVariable(yyscan_t yyscanner, QCString type, QCString name);
+#endif
+
+//-------------------------------------------------------------------
+
+static std::mutex g_searchIndexMutex;
+static std::mutex g_tooltipMutex;
+
+//-------------------------------------------------------------------
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
@@ -471,6 +386,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU
// Push a class scope
std::unique_ptr<ClassDef> classDefToAdd { createClassDef("<code>",1,1,yyextra->curClassName,ClassDef::Class,0,0,FALSE) };
+ ScopedTypeVariant var(yyextra->curClassName);
char *s=yyextra->curClassBases.first();
while (s)
{
@@ -479,7 +395,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU
auto it = yyextra->codeClassMap.find(s);
if (it != yyextra->codeClassMap.end())
{
- baseDefToAdd = it->second.get();
+ baseDefToAdd = dynamic_cast<const ClassDef*>(it->second.globalDef());
}
// Try to find class in global scope
if (baseDefToAdd==0)
@@ -487,14 +403,14 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU
baseDefToAdd=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,s);
}
- if (baseDefToAdd && baseDefToAdd!=classDefToAdd.get())
+ if (baseDefToAdd && baseDefToAdd->name()!=yyextra->curClassName)
{
- classDefToAdd->insertBaseClass(const_cast<ClassDef*>(baseDefToAdd),s,Public,Normal);
+ var.localDef()->insertBaseClass(baseDefToAdd->name());
}
s=yyextra->curClassBases.next();
}
- yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(classDefToAdd)));
+ yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var)));
// Reset class-parsing variables.
yyextra->curClassName.resize(0);
@@ -892,63 +808,36 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU
/*@ ----------------------------------------------------------------------------
*/
-void PyVariableContext::addVariable(yyscan_t yyscanner, const QCString &type,const QCString &name)
+#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l
+static void addVariable(yyscan_t yyscanner, QCString type, QCString name)
{
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
//printf("PyVariableContext::addVariable(%s,%s)\n",type.data(),name.data());
QCString ltype = type.simplifyWhiteSpace();
QCString lname = name.simplifyWhiteSpace();
- 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())
{
- varType = it->second.get();
- }
- if (varType==0)
- {
- varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); // look for global class definitions
- }
- if (varType)
- {
- scope->emplace(std::make_pair(lname.str(),varType)); // add it to a list
+ yyextra->theVarContext.addVariable(lname,std::move(it->second));
}
else
{
- if (!m_scopes.empty()) // for local variable add a dummy entry to avoid linking to a global that is
- // shadowed.
+ const ClassDef *varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); // look for global class definitions
+ if (varType)
{
- scope->emplace(std::make_pair(lname.str(),dummyContext));
+ yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varType));
}
- }
-}
-
-const ClassDef *PyVariableContext::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))
+ else
{
- result = it2->second;
- return result;
+ if (!yyextra->theVarContext.atGlobalScope()) // for local variable add a dummy entry to avoid linking to a global that is shadowed.
+ {
+ yyextra->theVarContext.addVariable(lname.str(),ScopedTypeVariant());
+ }
}
- ++it;
- }
- // nothing found -> also try the global scope
- auto it2 = m_globalScope.find(name.str());
- if (it2 != m_globalScope.end())
- {
- result = it2->second;
}
- return result;
}
+#endif
//-------------------------------------------------------------------------------
@@ -1031,6 +920,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);
@@ -1049,6 +939,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);
}
}
@@ -1189,7 +1080,10 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,
{
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
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();
@@ -1310,7 +1204,7 @@ static bool getLinkInScope(yyscan_t yyscanner,
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable())
{
- yyextra->theCallContext.setClass(stripClassName(yyscanner,md->typeString(),md->getOuterScope()));
+ yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
//printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n",
// yyextra->currentDefinition,yyextra->currentMemberDef);
@@ -1372,8 +1266,9 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data()));
- const ClassDef *cd=0,*lcd=0; /** Class def that we may find */
- const MemberDef *md=0; /** Member def that we may find */
+ const ScopedTypeVariant *lcd = 0;
+ const ClassDef *cd=0; // Class def that we may find
+ const MemberDef *md=0; // Member def that we may find
//bool isLocal=FALSE;
if ((lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable
@@ -1405,9 +1300,9 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
}
else
{
- if (lcd!=PyVariableContext::dummyContext)
+ if (lcd->type()!=ScopedTypeVariant::Dummy)
{
- yyextra->theCallContext.setClass(lcd);
+ yyextra->theCallContext.setScope(*lcd);
}
//isLocal=TRUE;
DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
@@ -1443,7 +1338,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
MemberDef *mmd = mcd->getMemberByName(locName);
if (mmd)
{
- yyextra->theCallContext.setClass(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()));
+ yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope())));
writeMultiLineCodeLink(yyscanner,ol,mmd,clName);
addToSearchIndex(yyscanner,className);
const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ?
@@ -1466,7 +1361,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
if (mmd)
{
//printf("name=%s scope=%s\n",locName.data(),scope.data());
- yyextra->theCallContext.setClass(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()));
+ yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope())));
writeMultiLineCodeLink(yyscanner,ol,mmd,clName);
addToSearchIndex(yyscanner,className);
const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ?
@@ -1503,8 +1398,7 @@ static void generateFunctionLink(yyscan_t yyscanner,
const char *funcName)
{
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
- const ClassDef *ccd=0;
- QCString locScope=yyextra->classScope.copy();
+ QCString locScope=yyextra->classScope;
QCString locFunc=removeRedundantWhiteSpace(funcName);
DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
int i=locFunc.findRev("::");
@@ -1519,17 +1413,16 @@ static void generateFunctionLink(yyscan_t yyscanner,
auto it = yyextra->codeClassMap.find(locScope.str());
if (it!=yyextra->codeClassMap.end())
{
- ccd = it->second.get();
- }
- //printf("using classScope %s\n",yyextra->classScope.data());
- if (ccd && ccd->baseClasses())
- {
- BaseClassListIterator bcli(*ccd->baseClasses());
- for ( ; bcli.current() ; ++bcli)
+ ScopedTypeVariant ccd = it->second;
+ //printf("using classScope %s\n",yyextra->classScope.data());
+ if (ccd.localDef() && !ccd.localDef()->baseClasses().empty())
{
- if (getLink(yyscanner,bcli.current()->classDef->name(),locFunc,ol,funcName))
+ for (const auto &bcName : ccd.localDef()->baseClasses())
{
- return;
+ if (getLink(yyscanner,bcName,locFunc,ol,funcName))
+ {
+ return;
+ }
}
}
}