@@ -179,7 +179,10 @@ struct codeYY_state
179
179
std::unordered_map< int , QCString> commentMap;
180
180
int braceCount=0 ;
181
181
182
+ using UsingContext = std::map<std::string,const NamespaceDef*>;
183
+
182
184
VariableContext theVarContext;
185
+ UsingContext theUsingContext;
183
186
CallContext theCallContext;
184
187
SymbolResolver symbolResolver;
185
188
TooltipManager tooltipManager;
@@ -258,7 +261,6 @@ static std::mutex g_searchIndexMutex;
258
261
static std::mutex g_docCrossReferenceMutex;
259
262
static std::mutex g_addExampleMutex;
260
263
static std::mutex g_countFlowKeywordsMutex;
261
- static std::mutex g_usingDirectiveMutex;
262
264
263
265
/* -----------------------------------------------------------------
264
266
*/
@@ -932,6 +934,12 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
932
934
endFontClass (yyscanner);
933
935
BEGIN (UsingName);
934
936
}
937
+ <Body>" using" {BN}+ {
938
+ startFontClass (yyscanner," keyword" );
939
+ codifyLines (yyscanner,yytext);
940
+ endFontClass (yyscanner);
941
+ BEGIN (UsingName);
942
+ }
935
943
<ConceptName>{ID}(" ::" {ID})* {
936
944
addUsingDirective (yyscanner,yytext);
937
945
generateClassOrGlobalLink (yyscanner,*yyextra->code ,yytext);
@@ -2208,20 +2216,34 @@ static void addVariable(yyscan_t yyscanner,QCString type,QCString name)
2208
2216
}
2209
2217
else
2210
2218
{
2211
- const ClassDef *varDef = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,ltype);
2212
- int i=0;
2213
- if (varDef)
2219
+ auto findVariableType = [&yyscanner,&yyg,<ype,&lname,&name](const Definition *d) -> const ClassDef *
2214
2220
{
2215
- DBG_CTX((stderr," ** addVariable type=' %s' name=' %s' \n" ,qPrint(ltype),qPrint(lname)));
2216
- yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list
2217
- }
2218
- else if ((i=ltype.find('<'))!=-1)
2221
+ const ClassDef *varDef = yyextra->symbolResolver.resolveClass(d,ltype);
2222
+ int i=0;
2223
+ if (varDef)
2224
+ {
2225
+ DBG_CTX((stderr," ** addVariable type=' %s' name=' %s' \n" ,qPrint(ltype),qPrint(lname)));
2226
+ yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list
2227
+ }
2228
+ else if ((i=ltype.find('<'))!=-1)
2229
+ {
2230
+ // probably a template class
2231
+ QCString typeName(ltype.left(i));
2232
+ addVariable(yyscanner,typeName,name);
2233
+ }
2234
+ return varDef;
2235
+ };
2236
+ const ClassDef *varDef = findVariableType(yyextra->currentDefinition);
2237
+ if (varDef==0)
2219
2238
{
2220
- // probably a template class
2221
- QCString typeName(ltype.left(i));
2222
- addVariable(yyscanner,typeName,name);
2239
+ // also check via using directive
2240
+ for (const auto &kv : yyextra->theUsingContext)
2241
+ {
2242
+ varDef = findVariableType(kv.second);
2243
+ if (varDef!=0) break;
2244
+ }
2223
2245
}
2224
- else
2246
+ if (varDef==0)
2225
2247
{
2226
2248
if (!yyextra->theVarContext.atGlobalScope()) // for local variables add a dummy entry so the name
2227
2249
// is hidden to avoid false links to global variables with the same name
@@ -2544,17 +2566,15 @@ static void addParmType(yyscan_t yyscanner)
2544
2566
yyextra->parmName .resize (0 ) ;
2545
2567
}
2546
2568
2547
- // TODO: make this have a scope only effect, at least not modifying the FileDef object.
2548
2569
static void addUsingDirective (yyscan_t yyscanner,const char *name)
2549
2570
{
2550
- std::lock_guard<std::mutex> lock (g_usingDirectiveMutex);
2551
2571
struct yyguts_t *yyg = (struct yyguts_t *)yyscanner;
2552
2572
if (yyextra->sourceFileDef && name)
2553
2573
{
2554
2574
const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find (name);
2555
2575
if (nd)
2556
2576
{
2557
- const_cast <FileDef*>( yyextra->sourceFileDef )-> addUsingDirective (nd );
2577
+ yyextra->theUsingContext . insert ( std::make_pair ( std::string (name),nd) );
2558
2578
}
2559
2579
}
2560
2580
}
@@ -2834,7 +2854,6 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
2834
2854
bool varOnly)
2835
2855
{
2836
2856
struct yyguts_t *yyg = (struct yyguts_t *)yyscanner;
2837
- int i=0 ;
2838
2857
QCString className=clName;
2839
2858
if (!className.isEmpty () && className[0 ]==' ~' ) // correct for matching negated values i.s.o. destructors.
2840
2859
{
@@ -2865,25 +2884,40 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
2865
2884
DBG_CTX ((stderr," generateClassOrGlobalLink(className=%s)\n " ,qPrint (className)));
2866
2885
if (!yyextra->isPrefixedWithThis || (lcd=yyextra->theVarContext .findVariable (className))==0 ) // not a local variable
2867
2886
{
2868
- const Definition *d = yyextra->currentDefinition ;
2869
- DBG_CTX ((stderr," d=%s yyextra->sourceFileDef=%s\n " ,d?qPrint (d->name ()):" <none>" ,yyextra->sourceFileDef ?qPrint (yyextra->sourceFileDef ->name ()):" <none>" ));
2870
- cd = yyextra->symbolResolver .resolveClass (d,className);
2871
- md = yyextra->symbolResolver .getTypedef ();
2872
- DBG_CTX ((stderr," non-local variable name=%s cd=%s md=%s!\n " ,
2873
- qPrint (className),cd?qPrint (cd->name ()):" <none>" ,
2874
- md?qPrint (md->name ()):" <none>" ));
2875
- i=className.find (' <' );
2887
+ int i=className.find (' <' );
2876
2888
QCString bareName = className;
2877
2889
if (i!=-1 ) bareName = bareName.left (i);
2878
- if (cd==0 && md==0 && i!=-1 )
2890
+
2891
+ auto checkForClass = [&yyg,&md,&cd,&bareName,&className](const Definition *d)
2892
+ {
2893
+ cd = yyextra->symbolResolver .resolveClass (d,className);
2894
+ md = yyextra->symbolResolver .getTypedef ();
2895
+ DBG_CTX ((stderr," non-local variable name=%s cd=%s md=%s!\n " ,
2896
+ qPrint (className),cd?qPrint (cd->name ()):" <none>" ,
2897
+ md?qPrint (md->name ()):" <none>" ));
2898
+ if (cd==0 && md==0 && !bareName.isEmpty ())
2899
+ {
2900
+ DBG_CTX ((stderr," bareName=%s\n " ,qPrint (bareName)));
2901
+ if (bareName!=className)
2902
+ {
2903
+ cd = yyextra->symbolResolver .resolveClass (d,bareName); // try unspecialized version
2904
+ md = yyextra->symbolResolver .getTypedef ();
2905
+ }
2906
+ }
2907
+ };
2908
+ const Definition *d = yyextra->currentDefinition ;
2909
+ DBG_CTX ((stderr," d=%s yyextra->sourceFileDef=%s\n " ,d?qPrint (d->name ()):" <none>" ,yyextra->sourceFileDef ?qPrint (yyextra->sourceFileDef ->name ()):" <none>" ));
2910
+ checkForClass (d);
2911
+ if (cd==0 && md==0 )
2879
2912
{
2880
- DBG_CTX ((stderr, " bareName=%s \n " , qPrint (bareName)));
2881
- if (bareName!=className )
2913
+ // also check via using directive
2914
+ for ( const auto &kv : yyextra-> theUsingContext )
2882
2915
{
2883
- cd = yyextra-> symbolResolver . resolveClass (d,bareName); // try unspecialized version
2884
- md = yyextra-> symbolResolver . getTypedef () ;
2916
+ checkForClass (kv. second );
2917
+ if (cd!= 0 || md!= 0 ) break ;
2885
2918
}
2886
2919
}
2920
+
2887
2921
const NamespaceDef *nd = getResolvedNamespace (className);
2888
2922
if (nd && nd->isLinkable ())
2889
2923
{
@@ -3902,7 +3936,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co
3902
3936
3903
3937
if (s.isEmpty ()) return ;
3904
3938
3905
- printlex (yy_flex_debug, TRUE , __FILE__, fd ? qPrint (fd->fileName ()): NULL );
3939
+ printlex (yy_flex_debug, TRUE , __FILE__, fd ? qPrint (fd->fileName ()): !exName. isEmpty () ? qPrint (exName) : NULL );
3906
3940
3907
3941
yyextra->code = &od;
3908
3942
yyextra->inputString = s.data ();
0 commit comments