summaryrefslogtreecommitdiff
path: root/src/code.l
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2022-12-27 12:33:07 +0900
committerJinWang An <jinwang.an@samsung.com>2022-12-27 12:33:07 +0900
commit9cf4982ab5fc6d964e1a024ff91a72d1fee5dc00 (patch)
treea19f0c024ea91acd7177f41fb5f066023f49027b /src/code.l
parent15e5c5601a13a41757e2a5e1a9105d1714d40215 (diff)
downloaddoxygen-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.l144
1 files changed, 102 insertions, 42 deletions
diff --git a/src/code.l b/src/code.l
index a0054ab..7f93d75 100644
--- a/src/code.l
+++ b/src/code.l
@@ -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,&ltype,&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;