diff options
author | JinWang An <jinwang.an@samsung.com> | 2022-12-27 12:33:07 +0900 |
---|---|---|
committer | JinWang An <jinwang.an@samsung.com> | 2022-12-27 12:33:07 +0900 |
commit | 9cf4982ab5fc6d964e1a024ff91a72d1fee5dc00 (patch) | |
tree | a19f0c024ea91acd7177f41fb5f066023f49027b /src/code.l | |
parent | 15e5c5601a13a41757e2a5e1a9105d1714d40215 (diff) | |
download | doxygen-9cf4982ab5fc6d964e1a024ff91a72d1fee5dc00.tar.gz doxygen-9cf4982ab5fc6d964e1a024ff91a72d1fee5dc00.tar.bz2 doxygen-9cf4982ab5fc6d964e1a024ff91a72d1fee5dc00.zip |
Imported Upstream version 1.9.4upstream/1.9.4
Diffstat (limited to 'src/code.l')
-rw-r--r-- | src/code.l | 144 |
1 files changed, 102 insertions, 42 deletions
@@ -179,7 +179,10 @@ struct codeYY_state std::unordered_map< int, QCString> commentMap; int braceCount=0; + using UsingContext = std::map<std::string,const NamespaceDef*>; + VariableContext theVarContext; + UsingContext theUsingContext; CallContext theCallContext; SymbolResolver symbolResolver; TooltipManager tooltipManager; @@ -213,7 +216,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, const QCString &text); static void addType(yyscan_t yyscanner); static void addParmType(yyscan_t yyscanner); -static void addUsingDirective(yyscan_t yyscanner,const char *name); +static void addUsingDirective(yyscan_t yyscanner,const QCString &name); static void setParameterList(yyscan_t yyscanner,const MemberDef *md); static const ClassDef *stripClassName(yyscan_t yyscanner,const QCString &s,const Definition *d); static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); @@ -258,7 +261,6 @@ static std::mutex g_searchIndexMutex; static std::mutex g_docCrossReferenceMutex; static std::mutex g_addExampleMutex; static std::mutex g_countFlowKeywordsMutex; -static std::mutex g_usingDirectiveMutex; /* ----------------------------------------------------------------- */ @@ -932,13 +934,18 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale endFontClass(yyscanner); BEGIN(UsingName); } +<Body>"using"{BN}+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(UsingName); + } <ConceptName>{ID}("::"{ID})* { - addUsingDirective(yyscanner,yytext); generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); } <ConceptName>"=" { codifyLines(yyscanner,yytext); BEGIN(Body); } -<UsingName>{ID}("::"{ID})* { - addUsingDirective(yyscanner,yytext); +<UsingName>{ID}(("::"|"."){ID})* { + addUsingDirective(yyscanner,substitute(yytext,".","::")); generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); BEGIN(Body); } @@ -1147,6 +1154,18 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale generateFunctionLink(yyscanner,*yyextra->code,yytext); yyextra->name+=yytext; } +<Body>{ID}("."{ID})+/{BN}+ { // CSharp/Java scope + if (yyextra->lang==SrcLangExt_CSharp || yyextra->lang==SrcLangExt_Java) + { + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; + } + else + { + REJECT; + } + } <Body>{SCOPENAME}/{B}* { // p->func() if (startsWithKeyword(yytext,"typedef")) REJECT; addType(yyscanner); @@ -2198,6 +2217,7 @@ static void addVariable(yyscan_t yyscanner,QCString type,QCString name) ltype = ltype.right(ltype.length()-6); } if (ltype.isEmpty() || lname.isEmpty()) return; + ltype = substitute(ltype,".","::"); DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' currentDefinition=%s\n", qPrint(ltype),qPrint(lname),yyextra->currentDefinition?qPrint(yyextra->currentDefinition->name()):"<none>")); auto it = yyextra->codeClassMap.find(ltype.str()); @@ -2208,20 +2228,33 @@ static void addVariable(yyscan_t yyscanner,QCString type,QCString name) } else { - const ClassDef *varDef = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,ltype); - int i=0; - if (varDef) + auto findVariableType = [&yyscanner,&yyg,<ype,&lname,&name](const Definition *d) -> const ClassDef * { - DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",qPrint(ltype),qPrint(lname))); - yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list - } - else if ((i=ltype.find('<'))!=-1) + const ClassDef *varDef = yyextra->symbolResolver.resolveClass(d,ltype); + int i=0; + if (varDef) + { + DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",qPrint(ltype),qPrint(lname))); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list + } + else if ((i=ltype.find('<'))!=-1) + { + // probably a template class + QCString typeName(ltype.left(i)); + addVariable(yyscanner,typeName,name); + } + return varDef; + }; + const ClassDef *varDef = findVariableType(yyextra->currentDefinition); + if (varDef==0) // also check via using directive { - // probably a template class - QCString typeName(ltype.left(i)); - addVariable(yyscanner,typeName,name); + for (const auto &kv : yyextra->theUsingContext) + { + varDef = findVariableType(kv.second); + if (varDef!=0) break; + } } - else + if (varDef==0) { 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 @@ -2544,17 +2577,16 @@ static void addParmType(yyscan_t yyscanner) yyextra->parmName.resize(0) ; } -// TODO: make this have a scope only effect, at least not modifying the FileDef object. -static void addUsingDirective(yyscan_t yyscanner,const char *name) +static void addUsingDirective(yyscan_t yyscanner,const QCString &name) { - std::lock_guard<std::mutex> lock(g_usingDirectiveMutex); + //printf("AddUsingDirective(%s)\n",qPrint(name)); struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->sourceFileDef && name) + if (yyextra->sourceFileDef && !name.isEmpty()) { const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(name); if (nd) { - const_cast<FileDef*>(yyextra->sourceFileDef)->addUsingDirective(nd); + yyextra->theUsingContext.insert(std::make_pair(name.str(),nd)); } } } @@ -2834,7 +2866,6 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, bool varOnly) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - int i=0; QCString className=clName; if (!className.isEmpty() && className[0]=='~') // correct for matching negated values i.s.o. destructors. { @@ -2855,7 +2886,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, } else if (yyextra->lang==SrcLangExt_CSharp || yyextra->lang==SrcLangExt_Java) { - className = substitute(className,".","::"); // for PHP namespaces + className = substitute(className,".","::"); // for C#/Java namespaces } const ScopedTypeVariant *lcd=0; const ClassDef *cd=0; @@ -2865,25 +2896,54 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",qPrint(className))); if (!yyextra->isPrefixedWithThis || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable { - const Definition *d = yyextra->currentDefinition; - DBG_CTX((stderr,"d=%s yyextra->sourceFileDef=%s\n",d?qPrint(d->name()):"<none>",yyextra->sourceFileDef?qPrint(yyextra->sourceFileDef->name()):"<none>")); - cd = yyextra->symbolResolver.resolveClass(d,className); - md = yyextra->symbolResolver.getTypedef(); - DBG_CTX((stderr,"non-local variable name=%s cd=%s md=%s!\n", - qPrint(className),cd?qPrint(cd->name()):"<none>", - md?qPrint(md->name()):"<none>")); - i=className.find('<'); + int i=className.find('<'); QCString bareName = className; if (i!=-1) bareName = bareName.left(i); - if (cd==0 && md==0 && i!=-1) + + auto checkForClass = [&yyg,&bareName,&className](const Definition *d, + const ClassDef *&cd_,const MemberDef *&md_) + { + cd_ = yyextra->symbolResolver.resolveClass(d,className); + md_ = yyextra->symbolResolver.getTypedef(); + DBG_CTX((stderr,"non-local variable name=%s cd=%s md=%s!\n", + qPrint(className),cd_?qPrint(cd_->name()):"<none>", + md_?qPrint(md_->name()):"<none>")); + if (cd_==0 && md_==0 && !bareName.isEmpty()) + { + DBG_CTX((stderr,"bareName=%s\n",qPrint(bareName))); + if (bareName!=className) + { + cd_ = yyextra->symbolResolver.resolveClass(d,bareName); // try unspecialized version + md_ = yyextra->symbolResolver.getTypedef(); + } + } + }; + const Definition *d = yyextra->currentDefinition; + DBG_CTX((stderr,"d=%s yyextra->sourceFileDef=%s\n",d?qPrint(d->name()):"<none>",yyextra->sourceFileDef?qPrint(yyextra->sourceFileDef->name()):"<none>")); + checkForClass(d,cd,md); + if (cd==0 && md==0 && d && d->definitionType()==Definition::TypeClass) + { + const FileDef *fd = toClassDef(d)->getFileDef(); + if (fd) + { + // also check for using directive in the file that defines this class + for (const auto &nd : fd->getUsedNamespaces()) + { + checkForClass(nd,cd,md); + if (cd!=0 || md!=0) break; + } + } + } + if (cd==0 && md==0) { - DBG_CTX((stderr,"bareName=%s\n",qPrint(bareName))); - if (bareName!=className) + // also check via using directive + for (const auto &kv : yyextra->theUsingContext) { - cd = yyextra->symbolResolver.resolveClass(d,bareName); // try unspecialized version - md = yyextra->symbolResolver.getTypedef(); + checkForClass(kv.second,cd,md); + if (cd!=0 || md!=0) break; } } + const NamespaceDef *nd = getResolvedNamespace(className); if (nd && nd->isLinkable()) { @@ -2974,7 +3034,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, if (md==0) // not found as a typedef { md = setCallContextForVar(yyscanner,clName); - DBG_CTX((stderr,"setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",qPrint(clName),(void*)md,(void*)yyextra->currentDefinition)); + DBG_CTX((stderr,"setCallContextForVar(%s) md=%p yyextra->currentDefinition=%s\n",qPrint(clName),(void*)md,yyextra->currentDefinition ? qPrint(yyextra->currentDefinition->name()) : "<none>")); if (md && yyextra->currentDefinition) { DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", @@ -3242,7 +3302,7 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons QCString funcWithScope=locFunc; QCString funcWithFullScope=locFunc; QCString fullScope=locScope; - DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",qPrint(locScope),qPrint(locFunc))); + DBG_CTX((stderr,"*** locScope=%s locFunc=%s\n",qPrint(locScope),qPrint(locFunc))); int len=2; int i=locFunc.findRev("::"); if (yyextra->currentMemberDef && yyextra->currentMemberDef->resolveAlias()->getClassDef() && @@ -3734,12 +3794,12 @@ static QCString escapeComment(yyscan_t yyscanner,const char *s) static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const char *keyword) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - static std::unordered_set<std::string> non_cpp_keywords = { + static const std::unordered_set<std::string> non_cpp_keywords = { "__assume", "__super", "abstract", "function", "gcnew", "gcroot", "generic", "get", "internal", "null", "pin_ptr", "raise", "remove", "self", "set", "transient"}; - static std::unordered_set<std::string> non_java_keywords = { + static const std::unordered_set<std::string> non_java_keywords = { "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", "char8_t", "char16_t", "char32_t", @@ -3902,7 +3962,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? qPrint(fd->fileName()): NULL); + printlex(yy_flex_debug, TRUE, __FILE__, fd ? qPrint(fd->fileName()): !exName.isEmpty() ? qPrint(exName) : NULL); yyextra->code = &od; yyextra->inputString = s.data(); @@ -3951,7 +4011,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co { setCurrentDoc(yyscanner,"l00001"); } - yyextra->currentDefinition = getResolvedNamespace(className); + yyextra->currentDefinition = searchCtx ? searchCtx : getResolvedNamespace(className); yyextra->currentMemberDef = 0; yyextra->searchingForBody = exBlock; yyextra->insideBody = FALSE; |