1 /*
2  * This file is part of the FortranProject plugin for Code::Blocks IDE
3  * and licensed under the GNU General Public License, version 3
4  * http://www.gnu.org/licenses/gpl-3.0.html
5  */
6 
7 #include "parserf.h"
8 
9 #include <sdk.h>
10 #ifndef CB_PRECOMP
11     #include <wx/tokenzr.h>
12     #include <wx/string.h>
13     #include <wx/thread.h>
14     #include <wx/arrstr.h>
15     #include <wx/regex.h>
16 
17     #include <cbstyledtextctrl.h>
18     #include <configmanager.h>
19     #include <editormanager.h>
20     #include <globals.h>
21     #include <logmanager.h>
22 #endif
23 #include <vector>
24 
25 #include "workspaceparserthread.h"
26 #include "parserthreadf.h"
27 #include "adddirparserthread.h"
28 #include "ccsmartfilter.h"
29 
30 FortranFileExt g_FortranFileExt;
31 
32 static wxCriticalSection s_CurrentBTokensCritSect;
33 
ParserF(bool withIntrinsicModules)34 ParserF::ParserF(bool withIntrinsicModules)
35 {
36     m_pTokens = new TokensArrayF();
37     m_pIntrinsicModuleTokens = NULL;
38     m_pIncludeDB = new IncludeDB();
39     m_pAdditionalDirTokens = NULL;
40     m_pIncludeDBADir = NULL;
41     m_Done = false;
42 
43     m_RecursiveDeep = 0;
44     m_UseRenameArrays = false;
45     m_RenameDeep = 0;
46     m_IncludeDeep = 0;
47     m_SubmodDeep = 0;
48 
49     m_pTokensNew = NULL;
50     m_pIncludeDBNew = NULL;
51     m_pTokensADirNew = NULL;
52     m_pIncludeDBADirNew = NULL;
53     m_pBufferTokens = new TokensArrayF();
54     m_pCurrentBufferTokensNew = NULL;
55 
56     if (withIntrinsicModules)
57     {
58         m_pIntrinsicModuleTokens = new TokensArrayF();
59         ParseIntrinsicModules();
60     }
61 }
62 
~ParserF()63 ParserF::~ParserF()
64 {
65     //dtor
66     Clear();
67     delete m_pTokens;
68     if (m_pIntrinsicModuleTokens)
69         delete m_pIntrinsicModuleTokens;
70     delete m_pIncludeDB;
71     if (m_pAdditionalDirTokens)
72         delete m_pAdditionalDirTokens;
73     if (m_pIncludeDBADir)
74         delete m_pIncludeDBADir;
75 
76     if (m_pTokensNew)
77         delete m_pTokensNew;
78     if (m_pIncludeDBNew)
79         delete m_pIncludeDBNew;
80     if (m_pTokensADirNew)
81         delete m_pTokensADirNew;
82     if (m_pIncludeDBADirNew)
83         delete m_pIncludeDBADirNew;
84     if (m_pBufferTokens)
85         delete m_pBufferTokens;
86     if (m_pCurrentBufferTokensNew)
87         delete m_pCurrentBufferTokensNew;
88 }
89 
Parse(const wxString & projectFilename,const wxString & filename,FortranSourceForm fsForm)90 bool ParserF::Parse(const wxString& projectFilename, const wxString& filename, FortranSourceForm fsForm)
91 {
92     wxCriticalSectionLocker locker(s_CritSect);
93     wxString fn = UnixFilename(filename);
94     ParserThreadF* thread = new ParserThreadF(projectFilename, fn, m_pTokens, fsForm, false, m_pIncludeDB);
95     bool res = thread->Parse();
96     delete thread;
97 
98     return res;
99 }
100 
Reparse(const wxString & projectFilename,const wxString & filename,FortranSourceForm fsForm)101 bool ParserF::Reparse(const wxString& projectFilename, const wxString& filename, FortranSourceForm fsForm)
102 {
103     m_Done = false;
104     RemoveFile(filename);
105     bool res = Parse(projectFilename, filename, fsForm);
106     m_Done = true;
107     return res;
108 }
109 
BatchParse(const wxArrayString & projectFilenames,const wxArrayString & filenames,ArrayOfFortranSourceForm & fileForms)110 bool ParserF::BatchParse(const wxArrayString& projectFilenames, const wxArrayString& filenames, ArrayOfFortranSourceForm& fileForms)
111 {
112     m_Done = false;
113     bool res = true;
114     if (filenames.size() != fileForms.size())
115         return false;
116     for (size_t i=0; i<filenames.size(); i++)
117     {
118         if(!Parse(projectFilenames[i], filenames[i], fileForms[i]))
119         {
120             res = false;
121             //break;
122         }
123     }
124     m_Done = true;
125     return res;
126 }
127 
RemoveFile(const wxString & filename)128 bool ParserF::RemoveFile(const wxString& filename)
129 {
130 	wxString file = UnixFilename(filename);
131     m_Done = false;
132     wxCriticalSectionLocker locker(s_CritSect);
133 
134     RemoveBuffer(filename);
135 
136     size_t i = 0;
137     while (i < m_pTokens->size())
138     {
139         if (m_pTokens->Item(i)->m_Filename.IsSameAs(file))
140         {
141             m_pTokens->Item(i)->Clear();
142             delete m_pTokens->Item(i);
143             m_pTokens->RemoveAt(i);
144         }
145         else
146             ++i;
147     }
148     wxFileName fn(filename);
149     m_pIncludeDB->RemoveFile(fn.GetFullName());
150     m_Done = true;
151 	return true;
152 }
153 
RemoveBuffer(const wxString & filename)154 void ParserF::RemoveBuffer(const wxString& filename)
155 {
156     wxString file = UnixFilename(filename);
157 
158     if (m_pBufferTokens &&
159         (m_pBufferTokens->size() > 0))
160     {
161         size_t i = 0;
162         while (i < m_pBufferTokens->size())
163         {
164             if (m_pBufferTokens->Item(i)->m_Filename.IsSameAs(file))
165             {
166                 m_pBufferTokens->Item(i)->Clear();
167                 delete m_pBufferTokens->Item(i);
168                 m_pBufferTokens->RemoveAt(i);
169                 break;
170             }
171             else
172                 ++i;
173         }
174     }
175 }
176 
FindTypeBoundProcedures(const TokenFlat & interToken,const wxArrayString & searchArr,TokensArrayFlat & resTokenArr)177 bool ParserF::FindTypeBoundProcedures(const TokenFlat& interToken, const wxArrayString& searchArr, TokensArrayFlat& resTokenArr)
178 {
179     wxCriticalSectionLocker locker(s_CritSect);
180     bool foundType = false;
181 
182     TokensArrayF* fileChildren = FindFileTokens(interToken.m_Filename);
183 
184     // find module
185     TokenF* module;
186     for (size_t j=0; j<fileChildren->GetCount(); j++)
187     {
188         if (fileChildren->Item(j)->m_TokenKind == tkModule)
189         {
190             module = fileChildren->Item(j);
191             for (size_t k=0; k < module->m_Children.GetCount(); k++)
192             {
193                 if (interToken.m_ParentName.IsSameAs(module->m_Children.Item(k)->m_Name) &&
194                      interToken.m_ParentTokenKind == module->m_Children.Item(k)->m_TokenKind)
195                 {
196                     // type was found
197                     TokenF* typeTok = module->m_Children.Item(k);
198                     for (size_t m=0; m < typeTok->m_Children.GetCount(); m++)
199                     {
200                         for (size_t l=0; l < searchArr.GetCount(); l++)
201                         {
202                             if (typeTok->m_Children.Item(m)->m_TokenKind == tkProcedure &&
203                                 typeTok->m_Children.Item(m)->m_Name.IsSameAs(searchArr.Item(l)) )
204                             {
205                                 resTokenArr.Add(new TokenFlat(typeTok->m_Children.Item(m)));
206                             }
207                         }
208                     }
209                     foundType = true;
210                     break;
211                 }
212             }
213             if (foundType)
214                 break;
215         }
216     }
217     return foundType;
218 }
219 
FindMatchTokenInSameModule(const TokenFlat & procedureToken,const wxString & search,TokensArrayFlat & result,int tokenKindMask,int noChildrenOf)220 bool ParserF::FindMatchTokenInSameModule(const TokenFlat& procedureToken, const wxString& search, TokensArrayFlat& result, int tokenKindMask, int noChildrenOf)
221 {
222     wxCriticalSectionLocker locker(s_CritSect);
223 
224     // find module
225     TokensArrayF* fileChildren = FindFileTokens(procedureToken.m_Filename);
226     TokenF* module;
227     bool foundModule = false;
228     for (size_t j=0; j<fileChildren->GetCount(); j++)
229     {
230         if (fileChildren->Item(j)->m_TokenKind == tkModule)
231         {
232             module = fileChildren->Item(j);
233             for (size_t k=0; k < module->m_Children.GetCount(); k++)
234             {
235                 if (procedureToken.m_ParentName.IsSameAs(module->m_Children.Item(k)->m_Name) &&
236                      procedureToken.m_ParentTokenKind == module->m_Children.Item(k)->m_TokenKind)
237                 {
238                     foundModule = true;
239                     break;
240                 }
241             }
242         }
243         if (foundModule)
244             break;
245     }
246     if (foundModule)
247     {
248         // find match token
249         size_t rCount = result.GetCount();
250         FindMatchChildrenDeclared(module->m_Children, search, result, tokenKindMask, false, noChildrenOf);
251         if (rCount < result.GetCount())
252         {
253             return true;
254         }
255     }
256     return false;
257 }
258 
FindMatchTokensDeclared(const wxString & search,TokensArrayFlat & result,int tokenKindMask,bool partialMatch,int noChildrenOf,bool onlyPublicNames,bool noIncludeFiles)259 size_t ParserF::FindMatchTokensDeclared(const wxString& search, TokensArrayFlat& result, int tokenKindMask, bool partialMatch, int noChildrenOf,
260                                         bool onlyPublicNames, bool noIncludeFiles)
261 {
262     wxString searchLw = search.Lower();
263     wxChar sep = wxFileName::GetPathSeparator();
264 
265     wxCriticalSectionLocker locker(s_CritSect);
266 
267     for (size_t i=0; i<m_pTokens->GetCount(); i++)
268     {
269         if (noIncludeFiles)
270         {
271             wxString fn = m_pTokens->Item(i)->m_Filename.AfterLast(sep);
272             if (m_pIncludeDB->IsIncludeFile(fn))
273                 continue;
274         }
275         TokensArrayF* fileChildren = FindFileTokens(m_pTokens->Item(i)->m_Filename);
276         if (fileChildren && fileChildren->GetCount() > 0)
277         {
278             FindMatchChildrenDeclared(*fileChildren, searchLw, result, tokenKindMask, partialMatch, noChildrenOf, onlyPublicNames);
279         }
280     }
281 
282     if (m_pIntrinsicModuleTokens)
283     {
284         for (size_t i=0; i<m_pIntrinsicModuleTokens->GetCount(); i++)
285         {
286             if (m_pIntrinsicModuleTokens->Item(i)->m_Children.GetCount() > 0)
287             {
288                 FindMatchChildrenDeclared(m_pIntrinsicModuleTokens->Item(i)->m_Children, searchLw, result, tokenKindMask,
289                                           partialMatch, noChildrenOf, onlyPublicNames);
290             }
291         }
292     }
293 
294     if (m_pAdditionalDirTokens)
295     {
296         for (size_t i=0; i<m_pAdditionalDirTokens->GetCount(); i++)
297         {
298             wxString fn = m_pAdditionalDirTokens->Item(i)->m_Filename.AfterLast(sep);
299             if (m_pIncludeDBADir && m_pIncludeDBADir->IsIncludeFile(fn))
300                 continue;
301 
302             if (m_pAdditionalDirTokens->Item(i)->m_Children.GetCount() > 0)
303             {
304                 FindMatchChildrenDeclared(m_pAdditionalDirTokens->Item(i)->m_Children, searchLw, result, tokenKindMask,
305                                           partialMatch, noChildrenOf, onlyPublicNames);
306             }
307         }
308     }
309     return result.GetCount();
310 }
311 
FindMatchChildrenDeclared(TokensArrayF & children,const wxString search,TokensArrayFlat & result,int tokenKindMask,bool partialMatch,int noChildrenOf,bool onlyPublicNames)312 void ParserF::FindMatchChildrenDeclared(TokensArrayF& children, const wxString search, TokensArrayFlat& result, int tokenKindMask,
313                                         bool partialMatch, int noChildrenOf, bool onlyPublicNames)
314 {
315     size_t nChil = children.GetCount();
316     for (size_t i=0; i<nChil; ++i)
317     {
318         TokenF* tok = children.Item(i);
319         if ((partialMatch && (tok->m_TokenKind & tokenKindMask) && tok->m_Name.StartsWith(search)) ||
320             (!partialMatch && (tok->m_TokenKind & tokenKindMask) && tok->m_Name.IsSameAs(search)))
321         {
322             if (!onlyPublicNames || (tok->m_TokenAccess != taPrivate) )
323             {
324                 result.Add(new TokenFlat(tok));
325             }
326         }
327         else if (tok->m_TokenKind == tkInclude && !(tkInclude & noChildrenOf))
328         {
329             if (m_IncludeDeep > 5)
330                 continue;
331             TokensArrayF includedTokens;
332             AddIncludeFileChildren(tok, includedTokens);
333             if (includedTokens.GetCount() > 0)
334             {
335                 m_IncludeDeep++;
336                 FindMatchChildrenDeclared(includedTokens, search, result, tokenKindMask, partialMatch, noChildrenOf, onlyPublicNames);
337                 m_IncludeDeep--;
338             }
339         }
340         else if ((tok->m_TokenKind == tkSubmodule) && (tokenKindMask & tkSubmodule))
341         {
342             wxString sname = tok->m_Name.AfterLast(':');
343             if ((partialMatch && sname.StartsWith(search)) ||
344                 (!partialMatch && sname.IsSameAs(search)))
345             {
346                 result.Add(new TokenFlat(tok));
347             }
348         }
349 
350         if (tok->m_Children.GetCount() > 0 && !(tok->m_TokenKind & noChildrenOf))
351         {
352             FindMatchChildrenDeclared(tok->m_Children, search, result, tokenKindMask, partialMatch, noChildrenOf, onlyPublicNames);
353         }
354     }
355 }
356 
FindMatchVariablesInModules(const wxString & search,TokensArrayFlat & result,bool partialMatch)357 void ParserF::FindMatchVariablesInModules(const wxString& search, TokensArrayFlat& result, bool partialMatch)
358 {
359     wxString searchLw = search.Lower();
360 
361     wxCriticalSectionLocker locker(s_CritSect);
362 
363     for (size_t i=0; i<m_pTokens->GetCount(); i++)
364     {
365         TokensArrayF* children = FindFileTokens(m_pTokens->Item(i)->m_Filename);
366         if (!children)
367             continue;
368         for (size_t j=0; j<children->GetCount(); j++)
369         {
370             if ( children->Item(j)->m_TokenKind == tkModule )
371             {
372                 TokensArrayF* modChildren = &children->Item(j)->m_Children;
373                 for (size_t k=0; k<modChildren->GetCount(); k++)
374                 {
375                     if ( (modChildren->Item(k)->m_TokenKind == tkVariable)
376                         && ( ( partialMatch && modChildren->Item(k)->m_Name.StartsWith(searchLw) ) ||
377                              ( !partialMatch && modChildren->Item(k)->m_Name.IsSameAs(searchLw) ) ) )
378                     {
379                         result.Add(new TokenFlat(modChildren->Item(k)));
380                     }
381                 }
382             }
383         }
384     }
385 }
386 
FindMatchTypeComponents(TokenFlat & parentTok,const wxString & lineStr,TokensArrayFlat & result)387 bool ParserF::FindMatchTypeComponents(TokenFlat& parentTok, const wxString& lineStr, TokensArrayFlat& result)
388 {
389     bool isAfterPercent;
390     wxArrayString parts;
391     if (!CutLineIntoParts(lineStr, isAfterPercent, parts))
392         return false;
393     if (parts.Count() == 0)
394         return true;
395 
396     wxString name = parts.Item(0);
397 
398     TokensArrayFlatClass childrenTmp;
399     TokensArrayFlat* childTFTmp = childrenTmp.GetTokens();
400     GetChildren(&parentTok, tkVariable, *childTFTmp);
401     size_t i=0;
402     while(true)
403     {
404         if(i >= childTFTmp->Count())
405             break;
406 
407         if(!childTFTmp->Item(i)->m_Name.IsSameAs(name))
408         {
409             delete childTFTmp->Item(i);
410             childTFTmp->RemoveAt(i);
411         }
412         else
413             i++;
414     }
415 
416     wxString myFilename = parentTok.m_Filename;
417     unsigned int myScopeLine = 0;
418     if (childTFTmp->Count() > 0)
419         myScopeLine = childTFTmp->Item(0)->m_LineStart;
420     else // (childTFTmp->Count() == 0)
421         FindUseAssociatedTokens(true, &parentTok, name, false, *childTFTmp, tkVariable, false);
422 
423     if (childTFTmp->Count() == 0)
424         return false; //Type was not found.
425 
426     bool found = FindMatchTypeComponents2(childTFTmp, myScopeLine, myFilename, parts, result, false, true, true);
427     return found;
428 }
429 
FindMatchTypeComponents(cbEditor * ed,const wxString & lineCur,TokensArrayFlat & result,bool partialMatch,bool onlyPublicNames,bool & isAfterPercent,bool getAsProcedure)430 bool ParserF::FindMatchTypeComponents(cbEditor* ed, const wxString& lineCur, TokensArrayFlat& result, bool partialMatch,
431                                       bool onlyPublicNames, bool& isAfterPercent, bool getAsProcedure)
432 {
433     wxArrayString parts;
434     if (!CutLineIntoParts(lineCur, isAfterPercent, parts))
435         return false;
436     if (parts.Count() == 0)
437         return true;
438 
439     wxString name = parts.Item(0);
440 
441     TokensArrayFlatClass tokensTmp;
442     TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
443     int tmpEndPos = -1;
444     int nLineCurScope = -1;
445     FindMatchDeclarationsInCurrentScope(name, ed, *resultTmp, false, tmpEndPos, &nLineCurScope);
446 
447     if (nLineCurScope == -1)
448         return false; // something wrong with finding current scope
449 
450     wxString myFilename = UnixFilename(ed->GetFilename());
451     unsigned int myScopeLine = 0;
452     if (resultTmp->Count() > 0)
453         myScopeLine = resultTmp->Item(0)->m_LineStart;
454     else // (resultTmp->Count() == 0)
455         FindUseAssociatedTokens(onlyPublicNames, ed, name, false, *resultTmp, tkVariable, false);
456 
457     if (resultTmp->Count() == 0)
458         return false; //Type was not found.
459 
460     bool found = FindMatchTypeComponents2(resultTmp, myScopeLine, myFilename, parts, result, partialMatch, onlyPublicNames, getAsProcedure);
461     return found;
462 }
463 
FindMatchTypeComponents2(TokensArrayFlat * foundVariables,unsigned int myScopeLine,wxString & myFilename,wxArrayString & parts,TokensArrayFlat & result,bool partialMatch,bool onlyPublicNames,bool getAsProcedure)464 bool ParserF::FindMatchTypeComponents2(TokensArrayFlat* foundVariables, unsigned int myScopeLine, wxString& myFilename, wxArrayString& parts,
465                                         TokensArrayFlat& result, bool partialMatch, bool onlyPublicNames, bool getAsProcedure)
466 {
467     wxArrayString address;
468     wxString nameType;
469     bool nameType_found = false;
470     for (size_t i=0; i<foundVariables->Count(); i++)
471     {
472         TokenFlat* tok = foundVariables->Item(i);
473         if ( tok->m_TokenKind == tkVariable )
474         {
475             wxString tDefLow = tok->m_TypeDefinition.Lower();
476             if ( tDefLow.StartsWith(_T("type")) || tDefLow.StartsWith(_T("class")) )
477             {
478                 nameType = tDefLow;
479                 int idx_a = nameType.Find(_T(")"));
480                 int idx_b = nameType.Find(_T("("));
481                 if (idx_a != wxNOT_FOUND && idx_b != wxNOT_FOUND && idx_a > idx_b+1)
482                 {
483                     nameType = nameType.Mid(idx_b+1,idx_a-idx_b-1);
484                     idx_a = nameType.Find(_T("("));
485                     if (idx_a != wxNOT_FOUND) // parametrized type
486                         nameType = nameType.Mid(0,idx_a).Trim();
487                     FindAddress(tok, address);
488                     nameType_found = true;
489                     break;
490                 }
491             }
492         }
493     }
494     if (!nameType_found)
495         return false; // something is wrong
496 
497     int nTypes = parts.Count() - 1;
498     wxString searchName = parts.Item(parts.Count()-1);
499     wxString nameTypeCom = nameType;
500     TokenF* typeToken = NULL;
501     bool isHostAssociated = false;
502     for (int i=1; i<=nTypes; i++)
503     {
504         TokensArrayFlatClass typesTmp;
505         TokensArrayFlat* resultTypesTmp = typesTmp.GetTokens();
506         FindUseAssociatedTokens(onlyPublicNames, address, nameType, false, *resultTypesTmp, tkType, false);
507 
508         if (resultTypesTmp->Count() == 0)
509             return false; // type was not found
510 
511         {
512             wxCriticalSectionLocker locker(s_CritSect);
513             typeToken = GetTypeInFile(resultTypesTmp->Item(0)->m_Filename, resultTypesTmp->Item(0)->m_LineStart,
514                                       resultTypesTmp->Item(0)->m_Name);
515             if (i == nTypes)
516             {
517                 isHostAssociated = resultTypesTmp->Item(0)->m_HostAssociated;
518                 break;
519             }
520 
521             if (!GetTypeOfComponent(&typeToken, parts.Item(i), nameTypeCom))
522                 return false; // something is wrong
523             address.Clear();
524             GetAddressOfToken(typeToken, address);
525             address.Add(parts.Item(i));
526         }
527         nameType = nameTypeCom;
528     }
529 
530     if (!typeToken)
531         return false;
532 
533     for (int icyc=0; icyc < 30; icyc++)  // if icyc >= 30, definitely something is wrong
534     {
535         bool inSameModule = false;
536         if ( typeToken->m_Filename.IsSameAs(myFilename) &&
537             (myScopeLine > typeToken->m_pParent->m_LineStart) && (myScopeLine <= typeToken->m_pParent->m_LineEnd) )
538             inSameModule = true;
539 
540         for (size_t i=0; i<typeToken->m_Children.GetCount(); i++)
541         {
542             TokenF* tokenCh = typeToken->m_Children.Item(i);
543             if ( (partialMatch && (tokenCh->m_Name.StartsWith(searchName))) ||
544                  (!partialMatch && (tokenCh->m_Name.IsSameAs(searchName))) )
545             {
546                 TokenFlat* tokTmp=0;
547                 if (tokenCh->m_TokenKind == tkVariable)
548                 {
549                     tokTmp = new TokenFlat(tokenCh);
550                 }
551                 else if (tokenCh->m_TokenKind == tkProcedure)
552                 {
553                     tokTmp = new TokenFlat(tokenCh);
554                     if (!getAsProcedure)
555                     {
556                         wxString tokName;
557                         if (!tokenCh->m_PartLast.IsEmpty())
558                             tokName = tokenCh->m_PartLast;
559                         else
560                             tokName = tokenCh->m_Name;
561 
562                         // what is kind of procedure ?
563                         TokensArrayFlatClass tokensProc;
564                         TokensArrayFlat* resultProc = tokensProc.GetTokens();
565                         int kindMask = tkFunction | tkSubroutine;
566 
567                         int noInChildren = tkInterface | tkFunction | tkSubroutine;
568                         bool found = FindMatchTokenInSameModule(tokenCh, tokName, *resultProc, kindMask, noInChildren);
569                         if (!found)
570                             FindMatchTokensDeclared(tokName, *resultProc, kindMask, false, noInChildren);
571                         if (resultProc->GetCount() > 0)
572                         {
573                             tokTmp->m_TokenKind = resultProc->Item(0)->m_TokenKind;
574                             ChangeArgumentsTypeBoundProc(*tokTmp, *(resultProc->Item(0)));
575                             tokTmp->m_PartLast.Empty();
576                         }
577                     }
578                 }
579                 else if (tokenCh->m_TokenKind == tkInterface)
580                 {
581                     tokTmp = new TokenFlat(tokenCh);
582                 }
583 
584                 if (tokTmp)
585                 {
586                     if ( !onlyPublicNames ||
587                          tokenCh->m_TokenAccess != taPrivate ||
588                          isHostAssociated ||
589                          inSameModule )
590                     {
591                         result.Add(tokTmp);
592                     }
593                 }
594             }
595         }
596         if ( (partialMatch && !typeToken->m_ExtendsType.IsEmpty() && typeToken->m_ExtendsType.Lower().StartsWith(searchName)) ||
597             (!partialMatch && !typeToken->m_ExtendsType.IsEmpty() && typeToken->m_ExtendsType.Lower().IsSameAs(searchName)) )
598         {
599             TokenF* newToken = new TokenF;
600             newToken->m_Name = typeToken->m_ExtendsType.Lower();
601             newToken->m_DisplayName = typeToken->m_ExtendsType;
602             newToken->m_TokenKind = tkType;
603             newToken->m_pParent = typeToken;
604             result.Add(new TokenFlat(newToken));
605         }
606         if (!typeToken->m_ExtendsType.IsEmpty())
607         {
608             typeToken = GetType(typeToken->m_ExtendsType.Lower());
609             if(!typeToken)
610                 break; // type was not found
611         }
612         else
613         {
614             break;
615         }
616     }
617 
618     return true;
619 }
620 
621 
CutLineIntoParts(const wxString & lineCur,bool & isAfterPercent,wxArrayString & parts)622 bool ParserF::CutLineIntoParts(const wxString& lineCur, bool& isAfterPercent, wxArrayString& parts)
623 {
624     wxString line = lineCur.Lower();
625     isAfterPercent = false;
626     line = line.AfterLast(';');
627     int idx = line.Find(_T("%"));
628     if (idx == wxNOT_FOUND)
629         return true;
630     if (line.EndsWith(_T(" ")))
631     {
632         wxString tmpString = line.Trim();
633         if (!tmpString.EndsWith(_T("%")))
634             return true;
635     }
636     else if (line.EndsWith(_T(")")) || line.EndsWith(_T("(")) || line.EndsWith(_T(","))
637              || line.EndsWith(_T("[")) || line.EndsWith(_T("]")))
638         return true;
639     int idx_a = line.Find('(', true);
640     int idx_b = line.Find(')', true);
641     if ((idx_a != wxNOT_FOUND && idx_b == wxNOT_FOUND) || (idx_a > idx_b))
642         line = line.Mid(idx_a+1);
643 
644     idx_a = line.Find('[', true);
645     idx_b = line.Find(']', true);
646     if ((idx_a != wxNOT_FOUND && idx_b == wxNOT_FOUND) || (idx_a > idx_b))
647         line = line.Mid(idx_a+1);
648 
649     CutBlocks('(', line);
650     CutBlocks('[', line);
651 
652     idx_a = line.Find(',', true);
653     if (idx_a != wxNOT_FOUND)
654         line = line.Mid(idx_a+1);
655     idx = line.Find('=',true);
656     if (idx != wxNOT_FOUND)
657         line = line.Mid(idx+1);
658     idx = line.Find('>',true);
659     if (idx != wxNOT_FOUND)
660         line = line.Mid(idx+1);
661     idx = line.Find('<',true);
662     if (idx != wxNOT_FOUND)
663         line = line.Mid(idx+1);
664     idx = line.Find('.',true);
665     if (idx != wxNOT_FOUND)
666         line = line.Mid(idx+1);
667     idx = line.Find('/',true);
668     if (idx != wxNOT_FOUND)
669         line = line.Mid(idx+1);
670     idx = line.Find('*',true);
671     if (idx != wxNOT_FOUND)
672         line = line.Mid(idx+1);
673     idx = line.Find('-',true);
674     if (idx != wxNOT_FOUND)
675         line = line.Mid(idx+1);
676     idx = line.Find('+',true);
677     if (idx != wxNOT_FOUND)
678         line = line.Mid(idx+1);
679     idx = line.Find(':',true);
680     if (idx != wxNOT_FOUND)
681         line = line.Mid(idx+1);
682     idx = line.Find('(',true);
683     if (idx != wxNOT_FOUND)
684         line = line.Mid(idx+1);
685     idx = line.Find('%');
686     if (idx == wxNOT_FOUND)
687         return true;
688 
689     isAfterPercent = true;
690 
691     wxStringTokenizer tkz(line, _T("%"), wxTOKEN_RET_EMPTY_ALL);
692     while ( tkz.HasMoreTokens() )
693     {
694         wxString str = tkz.GetNextToken();
695         wxStringTokenizer tkz2(str, _T(" \t\r\n"), wxTOKEN_STRTOK);
696         if (tkz2.CountTokens() > 1)
697         {
698             // something is wrong. Try further
699             while ( tkz2.HasMoreTokens() )
700             {
701                 str = tkz2.GetNextToken();
702             }
703             parts.Empty();
704         }
705         parts.Add(str.Trim(false).Trim());
706     }
707     if (parts.Count() == 1)
708         return false; // something wrong
709     for (size_t i=0; i<parts.Count()-1; i++)
710     {
711         if (parts.Item(i).IsEmpty())
712             return false; // something wrong
713     }
714     return true;
715 }
716 
717 
FindMatchDeclarationsInCurrentScope(const wxString & search,cbEditor * ed,TokensArrayFlat & result,bool partialMatch,int endPos,int * nLineStart)718 void ParserF::FindMatchDeclarationsInCurrentScope(const wxString& search, cbEditor* ed, TokensArrayFlat& result, bool partialMatch, int endPos, int* nLineStart)
719 {
720     int lineStart = -1;
721     TokenFlat* tokFl = NULL;
722     FindLineScopeLN(ed, lineStart, tokFl, endPos);
723 
724     wxString searchLw = search.Lower();
725 
726     if (tokFl)
727     {
728         if ((tokFl->m_TokenKind == tkAssociateConstruct) ||
729             (tokFl->m_TokenKind == tkSelectTypeChild) ||
730             (tokFl->m_TokenKind == tkSelectTypeDefault))
731         {
732             wxString args = tokFl->m_Args;
733             std::map<wxString,wxString> assocMap;
734             ParserThreadF::SplitAssociateConstruct(args, assocMap);
735 
736             std::map<wxString,wxString>::iterator it;
737             for ( it=assocMap.begin(); it != assocMap.end(); ++it )
738             {
739                 if ((partialMatch && (*it).first.Lower().StartsWith(searchLw)) ||
740                     (!partialMatch && (*it).first.Lower().IsSameAs(searchLw)))
741                 {
742                     TokenFlat* newToken = new TokenFlat();
743                     newToken->m_Name = (*it).first.Lower();
744 
745                     newToken->m_TokenKind = tkVariable;
746                     newToken->m_pParent = NULL;
747                     newToken->m_Filename = ed->GetFilename();
748                     newToken->m_LineStart = lineStart;
749                     newToken->m_DisplayName = (*it).first;
750                     newToken->m_Args << _T(" => ") << (*it).second;
751                     if (tokFl->m_TokenKind == tkAssociateConstruct)
752                         newToken->m_TypeDefinition = _T("AssociateConstruct");
753                     else if (tokFl->m_TokenKind == tkSelectTypeDefault)
754                         newToken->m_TypeDefinition = _T("SelectTypeConstruct");
755                     else // tkSelectTypeChild
756                         newToken->m_TypeDefinition = tokFl->m_TypeDefinition;
757                     newToken->m_DefinitionLength = 1;
758 
759                     result.Add(newToken);
760                 }
761             }
762             if (nLineStart)
763                 *nLineStart = lineStart;
764             delete tokFl;
765             return;
766         }
767         delete tokFl;
768     }
769 
770     if (nLineStart)
771         *nLineStart = lineStart;
772 
773     if (lineStart == -1)
774         return;
775 
776     {
777         cbStyledTextCtrl* control = ed->GetControl();
778         if (!control)
779             return;
780 
781         int curPos = control->GetCurrentPos();
782         unsigned int curLine = control->LineFromPosition(curPos) + 1;
783         int tokenKindMask = tkFunction | tkProgram | tkSubroutine | tkModule | tkBlockConstruct |
784                         tkAssociateConstruct | tkSubmodule | tkSelectTypeChild | tkSelectTypeDefault |
785                         tkType | tkProcedure;
786 
787         wxCriticalSectionLocker locker(s_CritSect);
788         TokensArrayF* fileChildren = FindFileTokens(ed->GetFilename());
789         if (!fileChildren)
790             return;
791 
792         TokenF* pToken = NULL;
793         if (!FindLineScope(curLine, lineStart, tokenKindMask, *fileChildren, pToken))
794             return;
795         if(!pToken)
796             return;
797         int filterMask = tkVariable;
798         TokensArrayF* pChildren = &pToken->m_Children;
799         //Add results
800         for (size_t i=0; i<pChildren->GetCount(); i++)
801         {
802             if ((partialMatch && pChildren->Item(i)->m_Name.StartsWith(searchLw)) ||
803                 (!partialMatch && pChildren->Item(i)->m_Name.IsSameAs(searchLw)))
804             {
805                 if (pChildren->Item(i)->m_TokenKind & filterMask)
806                 {
807                     result.Add(new TokenFlat(pChildren->Item(i)));
808                 }
809             }
810         }
811         if (pToken->m_TokenKind == tkType && pToken->m_pParent && (pToken->m_pParent->m_TokenKind & tokenKindMask))
812         {
813             pChildren = &pToken->m_pParent->m_Children;
814             for (size_t i=0; i<pChildren->GetCount(); i++)
815             {
816                 if ((partialMatch && pChildren->Item(i)->m_Name.StartsWith(searchLw)) ||
817                     (!partialMatch && pChildren->Item(i)->m_Name.IsSameAs(searchLw)))
818                 {
819                     if (pChildren->Item(i)->m_TokenKind & filterMask)
820                     {
821                         result.Add(new TokenFlat(pChildren->Item(i)));
822                     }
823                 }
824             }
825         }
826         if (pToken->m_TokenKind == tkFunction && pToken->m_ResultVariable.IsEmpty())
827         {
828             // Take function name as variable if 'result(var_name)' was not given
829             if ((partialMatch && pToken->m_Name.StartsWith(searchLw)) ||
830                 (!partialMatch && pToken->m_Name.IsSameAs(searchLw)))
831             {
832                 // Check if name was not added already as a local variable
833                 bool alreadyHave = false;
834                 for (size_t i=0; i<result.GetCount(); i++)
835                 {
836                     if (result.Item(i)->m_Name.IsSameAs(pToken->m_Name))
837                     {
838                         alreadyHave = true;
839                         break;
840                     }
841                 }
842                 if (!alreadyHave)
843                     result.Add(new TokenFlat(pToken));
844             }
845         }
846     }
847     return;
848 }
849 
FindLineScope(unsigned int line,int & lineStart,int tokenKindMask,TokensArrayF & children,TokenF * & pToken)850 bool ParserF::FindLineScope(unsigned int line, int& lineStart, int tokenKindMask, TokensArrayF& children, TokenF* &pToken)
851 {
852     bool found = false;
853     for (size_t i=0; i<children.GetCount(); i++)
854     {
855         if ((children.Item(i)->m_LineStart <= line) && (children.Item(i)->m_LineEnd >= line) && (children.Item(i)->m_TokenKind & tokenKindMask))
856         {
857             lineStart = children.Item(i)->m_LineStart;
858             pToken = children.Item(i);
859             FindLineScope(line, lineStart, tokenKindMask, children.Item(i)->m_Children, pToken);
860             found = true;
861             break;
862         }
863         else if (children.Item(i)->m_LineStart > line)
864         {
865             found = true;
866             break;
867         }
868     }
869     return found;
870 }
871 
FindLineScopeLN(cbEditor * ed,int & lineStart,TokenFlat * & token,int endPos)872 void ParserF::FindLineScopeLN(cbEditor* ed, int& lineStart, TokenFlat* &token, int endPos)
873 {
874     lineStart = -1;
875 
876     wxString filename = ed->GetFilename();
877     FortranSourceForm fsForm;
878     if (!IsFileFortran(filename, fsForm))
879         return;
880 
881     cbStyledTextCtrl* control = ed->GetControl();
882     if (!control)
883         return;
884 
885     int curPos;
886     if (endPos == -1)
887         curPos = control->GetCurrentPos();
888     else
889         curPos = endPos;
890 
891     unsigned int curLine = control->LineFromPosition(curPos) + 1;
892     int tokenKindMask = tkFunction | tkProgram | tkSubroutine | tkModule | tkBlockConstruct |
893                         tkAssociateConstruct | tkSubmodule | tkSelectTypeChild | tkSelectTypeDefault |
894                         tkInterfaceExplicit | tkInterface | tkProcedure; // | tkType;
895 
896     //Parse to find a scope
897     unsigned int parseStartLine;
898     if (curLine <= 100)
899         parseStartLine = 1;
900     else
901         parseStartLine = curLine - 100;
902 
903     wxString strRange;
904     int linesUntil;
905     if (parseStartLine == 1)
906     {
907         strRange = control->GetTextRange(0,curPos);
908         linesUntil = 0;
909     }
910     else
911     {
912         linesUntil = parseStartLine - 2;
913         strRange = control->GetTextRange(control->GetLineEndPosition(linesUntil),curPos);
914     }
915     curLine -= linesUntil;
916 
917     TokenF* pToken = NULL;
918     int chUntil = 0;
919     TokensArrayClass tTemp;
920     TokensArrayF* pRes = tTemp.GetTokens();
921     ParserThreadF parsTh = ParserThreadF(wxEmptyString, strRange, pRes, fsForm, true);
922     bool res = parsTh.Parse();
923     if (res)
924     {
925         FindLineScope(curLine, lineStart, tokenKindMask, *pRes, pToken);
926 
927         if (pToken && pToken->m_Name.IsEmpty() && (pToken->m_TokenKind != tkBlockConstruct) &&
928             (pToken->m_TokenKind != tkAssociateConstruct) &&
929             (pToken->m_TokenKind != tkSelectTypeChild) && (pToken->m_TokenKind != tkSelectTypeDefault))
930         {
931             if (pToken->m_pParent && (pToken->m_pParent->m_TokenKind & tokenKindMask))
932             {
933                 pToken = pToken->m_pParent;
934                 lineStart = pToken->m_LineStart;
935             }
936             else
937             {
938                 lineStart = -1;
939             }
940         }
941 
942         if (pToken)
943             pToken->m_Filename = UnixFilename(filename);
944     }
945 
946     if (lineStart == -1)
947     {
948         //Find scope between file tokens
949         wxCriticalSectionLocker locker(s_CritSect);
950         TokensArrayF* children = FindFileTokens(filename);
951         if (!children)
952             return;
953 
954         for (size_t i=0; i<children->GetCount(); i++)
955         {
956             if ((children->Item(i)->m_LineStart <= parseStartLine) && (children->Item(i)->m_TokenKind & tokenKindMask))
957             {
958                 lineStart = children->Item(i)->m_LineStart;
959                 pToken = children->Item(i);
960                 if (FindLineScope(parseStartLine, lineStart, tokenKindMask, children->Item(i)->m_Children, pToken))
961                 {
962                     break;
963                 }
964             }
965             else if (children->Item(i)->m_LineStart > parseStartLine)
966             {
967                 break;
968             }
969         }
970     }
971     else
972     {
973         lineStart += linesUntil;
974         chUntil = linesUntil;
975     }
976 
977     if (lineStart == -1)
978         return;
979 
980     if (pToken)
981     {
982         token = new TokenFlat(pToken);
983         token->m_LineStart += chUntil;
984     }
985 }
986 
FindFileTokens(const wxString & filename)987 TokensArrayF* ParserF::FindFileTokens(const wxString& filename)
988 {
989     TokensArrayF* children=NULL;
990     if (m_pBufferTokens)
991     {
992         for (size_t i=0; i<m_pBufferTokens->GetCount(); i++)
993         {
994             if (m_pBufferTokens->Item(i)->m_Filename.IsSameAs(filename))
995             {
996                 children = &m_pBufferTokens->Item(i)->m_Children;
997                 break;
998             }
999         }
1000     }
1001     if (!children)
1002     {
1003         size_t nTok = m_pTokens->GetCount();
1004         for (size_t i=0; i<nTok; ++i)
1005         {
1006             TokenF* tok = m_pTokens->Item(i);
1007             if (tok->m_TokenKind == tkFile && (tok->m_Filename.IsSameAs(filename)))
1008             {
1009                 children = &tok->m_Children;
1010                 break;
1011             }
1012         }
1013     }
1014     if (!children && m_pIntrinsicModuleTokens)
1015     {
1016         for (size_t i=0; i<m_pIntrinsicModuleTokens->GetCount(); ++i)
1017         {
1018             if ((m_pIntrinsicModuleTokens->Item(i)->m_TokenKind == tkFile) && (m_pIntrinsicModuleTokens->Item(i)->m_Filename.IsSameAs(filename)))
1019             {
1020                 children = &m_pIntrinsicModuleTokens->Item(i)->m_Children;
1021                 break;
1022             }
1023         }
1024     }
1025     if (!children && m_pAdditionalDirTokens)
1026     {
1027         for (size_t i=0; i<m_pAdditionalDirTokens->GetCount(); ++i)
1028         {
1029             if ((m_pAdditionalDirTokens->Item(i)->m_TokenKind == tkFile) && (m_pAdditionalDirTokens->Item(i)->m_Filename.IsSameAs(filename)))
1030             {
1031                 children = &m_pAdditionalDirTokens->Item(i)->m_Children;
1032                 break;
1033             }
1034         }
1035     }
1036     return children;
1037 }
1038 
FindFile(const wxString & filename)1039 TokenF* ParserF::FindFile(const wxString& filename)
1040 {
1041     wxString fn = UnixFilename(filename);
1042     TokenF* fileToken=0;
1043     size_t nTok = m_pTokens->GetCount();
1044     for (size_t i=0; i<nTok; ++i)
1045     {
1046         TokenF* tok = m_pTokens->Item(i);
1047         if (tok->m_TokenKind == tkFile && (tok->m_Filename.IsSameAs(fn)))
1048         {
1049             fileToken = m_pTokens->Item(i);
1050             break;
1051         }
1052     }
1053     return fileToken;
1054 }
1055 
FindFile(const wxString & filename,TokensArrayFlat & result)1056 void ParserF::FindFile(const wxString& filename, TokensArrayFlat& result)
1057 {
1058     wxCriticalSectionLocker locker(s_CritSect);
1059 
1060     for (size_t i=0; i<m_pTokens->GetCount(); i++)
1061     {
1062         if (m_pTokens->Item(i)->m_TokenKind == tkFile &&
1063             m_pTokens->Item(i)->m_Name.IsSameAs(filename))
1064         {
1065             result.Add(new TokenFlat(m_pTokens->Item(i)));
1066         }
1067     }
1068 }
1069 
FindFileTokenWithName(const wxString & filename)1070 TokenF* ParserF::FindFileTokenWithName(const wxString& filename)
1071 {
1072     wxString fn = UnixFilename(filename);
1073     TokenF* fileToken=0;
1074     for (size_t i=0; i<m_pTokens->GetCount(); i++)
1075     {
1076         if (m_pTokens->Item(i)->m_TokenKind == tkFile)
1077         {
1078             wxFileName tfn(m_pTokens->Item(i)->m_Filename);
1079             if (tfn.GetFullName().IsSameAs(filename))
1080             {
1081                 fileToken = m_pTokens->Item(i);
1082                 break;
1083             }
1084         }
1085     }
1086     return fileToken;
1087 }
1088 
FindModuleSubmoduleToken(const wxString & moduleName)1089 TokenF* ParserF::FindModuleSubmoduleToken(const wxString& moduleName)
1090 {
1091     wxString moduleNameLw = moduleName.Lower();
1092     TokenF* module = 0;
1093     if (m_pBufferTokens)
1094     {
1095         size_t nTok = m_pBufferTokens->GetCount();
1096         for (size_t i=0; i<nTok; ++i)
1097         {
1098             TokenF* tok = m_pBufferTokens->Item(i);
1099             if (tok->m_TokenKind == tkFile)
1100             {
1101                 TokensArrayF* children = &tok->m_Children;
1102                 size_t nChil = children->GetCount();
1103                 for (size_t j=0; j<nChil; ++j)
1104                 {
1105                     TokenF* chil = children->Item(j);
1106                     if ((chil->m_TokenKind == tkModule || chil->m_TokenKind == tkSubmodule) &&
1107                          chil->m_Name.IsSameAs(moduleNameLw))
1108                     {
1109                         module = chil;
1110                         break;
1111                     }
1112                 }
1113                 if (module)
1114                     break;
1115             }
1116         }
1117     }
1118 
1119     if (!module)
1120     {
1121         size_t nTok = m_pTokens->GetCount();
1122         for (size_t i=0; i<nTok; ++i)
1123         {
1124             TokenF* tok = m_pTokens->Item(i);
1125             if (tok->m_TokenKind == tkFile)
1126             {
1127                 TokensArrayF* children = &tok->m_Children;
1128                 size_t nChil = children->GetCount();
1129                 for (size_t j=0; j<nChil; ++j)
1130                 {
1131                     TokenF* chil = children->Item(j);
1132                     if ((chil->m_TokenKind == tkModule || chil->m_TokenKind == tkSubmodule) &&
1133                          chil->m_Name.IsSameAs(moduleNameLw))
1134                     {
1135                         module = chil;
1136                         break;
1137                     }
1138                 }
1139                 if (module)
1140                     break;
1141             }
1142         }
1143     }
1144 
1145     if (!module && m_pIntrinsicModuleTokens)
1146     {
1147         for (size_t i=0; i<m_pIntrinsicModuleTokens->GetCount(); ++i)
1148         {
1149             if (m_pIntrinsicModuleTokens->Item(i)->m_TokenKind == tkFile)
1150             {
1151                 TokensArrayF* children = &m_pIntrinsicModuleTokens->Item(i)->m_Children;
1152                 for (size_t j=0; j<children->GetCount(); ++j)
1153                 {
1154                     if (children->Item(j)->m_TokenKind == tkModule && children->Item(j)->m_Name.IsSameAs(moduleNameLw))
1155                     {
1156                         module = children->Item(j);
1157                         break;
1158                     }
1159                 }
1160                 if (module)
1161                     break;
1162             }
1163         }
1164     }
1165 
1166     if (!module && m_pAdditionalDirTokens)
1167     {
1168         for (size_t i=0; i<m_pAdditionalDirTokens->GetCount(); i++)
1169         {
1170             if (m_pAdditionalDirTokens->Item(i)->m_TokenKind == tkFile)
1171             {
1172                 TokensArrayF* children = &m_pAdditionalDirTokens->Item(i)->m_Children;
1173                 for (size_t j=0; j<children->GetCount(); j++)
1174                 {
1175                     if (children->Item(j)->m_TokenKind == tkModule && children->Item(j)->m_Name.IsSameAs(moduleNameLw))
1176                     {
1177                         module = children->Item(j);
1178                         break;
1179                     }
1180                 }
1181                 if (module)
1182                     break;
1183             }
1184         }
1185     }
1186     return module;
1187 }
1188 
1189 
FindMatchTokens(wxString filename,wxString search,TokensArrayF & result)1190 size_t ParserF::FindMatchTokens(wxString filename, wxString search, TokensArrayF& result)
1191 {
1192     filename = UnixFilename(filename);
1193     search = search.Lower();
1194 
1195     TokensArrayF* filechildren = FindFileTokens(filename);
1196     if (filechildren)
1197         FindMatchChildren(*filechildren, search, result);
1198     else
1199         Manager::Get()->GetLogManager()->DebugLog(_T("Can not find file # tokens:")+filename);
1200 
1201     return result.GetCount();
1202 }
1203 
FindMatchChildren(TokensArrayF & children,wxString search,TokensArrayF & result,bool exact)1204 void ParserF::FindMatchChildren(TokensArrayF &children, wxString search, TokensArrayF& result, bool exact)
1205 {
1206     for (size_t i=0; i<children.GetCount(); i++)
1207     {
1208         if (exact)
1209         {
1210             if (children.Item(i)->m_Name.IsSameAs(search))
1211                 result.Add(children.Item(i));
1212         }
1213         else
1214         {
1215             if (!(children.Item(i)->m_Name.Find(search) == wxNOT_FOUND))
1216                 result.Add(children.Item(i));
1217         }
1218         if (children.Item(i)->m_Children.GetCount() > 0)
1219             FindMatchChildren(children.Item(i)->m_Children, search, result, exact);
1220     }
1221 }
1222 
Clear()1223 void ParserF::Clear()
1224 {
1225     m_Done = false;
1226     wxCriticalSectionLocker locker(s_CritSect);
1227 
1228     if (m_pTokens)
1229         ClearTokens(m_pTokens);
1230 
1231     if (m_pIntrinsicModuleTokens)
1232         ClearTokens(m_pIntrinsicModuleTokens);
1233 
1234     m_VisitedModules.Clear();
1235     ClearPassedTokensArray2D(m_PassedTokensVisited);
1236     ClearArrOfSizeT2D(m_ChildrenIdxVisited);
1237     ClearBoolArray3D(m_CanBeSeenVisited);
1238 
1239     if (m_pIncludeDB)
1240         m_pIncludeDB->Clear();
1241 
1242     if (m_pTokensNew)
1243         ClearTokens(m_pTokensNew);
1244     if (m_pIncludeDBNew)
1245         m_pIncludeDBNew->Clear();
1246 
1247     if (m_pBufferTokens)
1248         ClearTokens(m_pBufferTokens);
1249 
1250     if (m_pCurrentBufferTokensNew)
1251         ClearTokens(m_pCurrentBufferTokensNew);
1252 
1253     if (m_pAdditionalDirTokens)
1254         ClearTokens(m_pAdditionalDirTokens);
1255     if (m_pIncludeDBADir)
1256         m_pIncludeDBADir->Clear();
1257 
1258     if (m_pTokensADirNew)
1259         ClearTokens(m_pTokensADirNew);
1260     if (m_pIncludeDBADirNew)
1261         m_pIncludeDBADirNew->Clear();
1262 
1263     m_Done = true;
1264 }
1265 
ObtainUsedDeclaredModules(const wxString & fileName,StringSet * fileUseModules,StringSet * fileDeclaredModules,StringSet * fileExtendsSModules,StringSet * fileDeclaredSubmodules,StringSet * fileIncludes)1266 void ParserF::ObtainUsedDeclaredModules(const wxString& fileName, StringSet* fileUseModules, StringSet* fileDeclaredModules,
1267                                         StringSet* fileExtendsSModules, StringSet* fileDeclaredSubmodules, StringSet* fileIncludes)
1268 {
1269     wxCriticalSectionLocker locker(s_CritSect);
1270 
1271     int idx = GetFileIndex(fileName);
1272     if (idx == -1)
1273         return;
1274     TokenF* tok = m_pTokens->Item(idx);
1275 
1276     ObtainUDModulesToken(tok, fileUseModules, fileDeclaredModules, fileExtendsSModules, fileDeclaredSubmodules, fileIncludes);
1277 }
1278 
ObtainUDModulesToken(TokenF * token,StringSet * fileUseModules,StringSet * fileDeclaredModules,StringSet * fileExtendsSModules,StringSet * fileDeclaredSubmodules,StringSet * fileIncludes)1279 void ParserF::ObtainUDModulesToken(TokenF* token, StringSet* fileUseModules, StringSet* fileDeclaredModules,
1280                                    StringSet* fileExtendsSModules, StringSet* fileDeclaredSubmodules, StringSet* fileIncludes)
1281 {
1282     for (size_t i=0; i < token->m_Children.GetCount(); i++)
1283     {
1284         if (token->m_Children.Item(i)->m_TokenKind == tkUse)
1285         {
1286             fileUseModules->insert(token->m_Children.Item(i)->m_Name);
1287         }
1288         else if (token->m_Children.Item(i)->m_TokenKind == tkModule)
1289         {
1290             fileDeclaredModules->insert(token->m_Children.Item(i)->m_Name);
1291         }
1292         else if (token->m_Children.Item(i)->m_TokenKind == tkSubmodule)
1293         {
1294             wxString smodName = token->m_Children.Item(i)->m_Name;
1295             SubmoduleTokenF* submod = static_cast<SubmoduleTokenF*>(token->m_Children.Item(i));
1296             wxString parentModName = submod->m_AncestorModuleName;
1297             smodName << _T("(") << parentModName << _T(")");
1298             fileDeclaredSubmodules->insert(smodName);
1299 
1300             wxString extName;
1301             if (!submod->m_ParentSubmoduleName.IsEmpty())
1302                 extName = submod->m_ParentSubmoduleName + _T("(") + parentModName + _T(")");
1303             else
1304                 extName = parentModName;
1305             fileExtendsSModules->insert(extName);
1306         }
1307         else if (token->m_Children.Item(i)->m_TokenKind == tkInclude)
1308         {
1309             fileIncludes->insert(token->m_Children.Item(i)->m_Name);
1310         }
1311 
1312         if (token->m_Children.Item(i)->m_Children.GetCount() > 0)
1313             ObtainUDModulesToken(token->m_Children.Item(i), fileUseModules, fileDeclaredModules,
1314                                  fileExtendsSModules, fileDeclaredSubmodules, fileIncludes);
1315     }
1316 }
1317 
GetFileIndex(const wxString & filename)1318 size_t ParserF::GetFileIndex(const wxString& filename)
1319 {
1320     wxString fn = UnixFilename(filename);
1321     for (size_t i=0; i<m_pTokens->GetCount(); i++)
1322     {
1323         if (m_pTokens->Item(i)->m_Filename.IsSameAs(fn))
1324         {
1325             return i;
1326         }
1327     }
1328     return -1;
1329 }
1330 
IsFileFortran(const wxString & filename,FortranSourceForm & fsForm)1331 bool ParserF::IsFileFortran(const wxString& filename, FortranSourceForm& fsForm)
1332 {
1333     return g_FortranFileExt.IsFileFortran(filename, fsForm);
1334 }
1335 
RereadOptions()1336 void ParserF::RereadOptions()
1337 {
1338     g_FortranFileExt.RereadOptions();
1339 }
1340 
FindMatchTokensForToolTip(const wxString & nameUnder,int posEndOfWord,cbEditor * ed,bool onlyUseAssoc,bool onlyPublicNames,TokensArrayFlat & result,bool & isAfterPercent)1341 void ParserF::FindMatchTokensForToolTip(const wxString& nameUnder, int posEndOfWord, cbEditor* ed,
1342                                         bool onlyUseAssoc, bool onlyPublicNames, TokensArrayFlat& result, bool& isAfterPercent)
1343 {
1344     isAfterPercent = false;
1345     if (!ed)
1346         return;
1347     cbStyledTextCtrl* control = ed->GetControl();
1348     if (!control)
1349         return;
1350     int lineStartPos = control->GetLineEndPosition(control->LineFromPosition(posEndOfWord) - 1) + 1;
1351     wxString curLine = control->GetTextRange(lineStartPos,posEndOfWord);
1352 
1353     TokensArrayFlatClass tokensTemp;
1354     TokensArrayFlat* resultTemp = tokensTemp.GetTokens();
1355     if (!FindMatchTypeComponents(ed, curLine, *resultTemp, false, onlyPublicNames, isAfterPercent, true))
1356         return;
1357     if (resultTemp->GetCount() > 0)
1358     {
1359         TokenFlat* token = resultTemp->Item(0); // we take only first added item
1360         result.Add( new TokenFlat(token) );
1361         if (token->m_TokenKind == tkProcedure)
1362         {
1363             wxString tokName;
1364             if (!token->m_PartLast.IsEmpty())
1365                 tokName = token->m_PartLast;
1366             else
1367                 tokName = token->m_Name;
1368 
1369             TokensArrayFlatClass tokensTmp;
1370             TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
1371             int kindMask = tkFunction | tkSubroutine;
1372             int noInChildren = tkInterface | tkFunction | tkSubroutine;
1373             bool found = FindMatchTokenInSameModule(token, tokName, *resultTmp, kindMask, noInChildren);
1374             if (!found)
1375                 FindMatchTokensDeclared(tokName, *resultTmp, kindMask, false, noInChildren);
1376             if (resultTmp->GetCount() > 0)
1377                 result.Add( new TokenFlat(resultTmp->Item(0)) );
1378         }
1379         else if (token->m_TokenKind == tkInterface)
1380         {
1381             FindGenericTypeBoudComponents(token, result);
1382             for (size_t i=1; i<resultTemp->GetCount(); i++)
1383             {
1384                 if (resultTemp->Item(i)->m_TokenKind == tkInterface)
1385                 {
1386                     result.Add( new TokenFlat(resultTemp->Item(i)));
1387                     FindGenericTypeBoudComponents(resultTemp->Item(i), result);
1388                 }
1389             }
1390         }
1391     }
1392 
1393     if (!isAfterPercent)
1394     {
1395         int tokKind = tkModule | tkFunction | tkProgram | tkSubroutine | tkPreprocessor | tkInterface | tkBlockData | tkType;
1396         if (onlyUseAssoc)
1397         {
1398             int noChildrenOf = tkInterface | tkModule | tkSubmodule | tkFunction | tkSubroutine | tkProgram;
1399             tokKind = tokKind | tkVariable;
1400             FindUseAssociatedTokens(onlyPublicNames, ed, nameUnder, false, result, tokKind, false);
1401             FindMatchTokensDeclared(nameUnder, result, tokKind, false, noChildrenOf, false, true); // take global procedures only
1402         }
1403         else
1404         {
1405             int noChildrenOf = tkInterface | tkFunction | tkSubroutine | tkProgram;
1406             FindMatchTokensDeclared(nameUnder, result, tokKind, false, noChildrenOf, onlyPublicNames);
1407             FindMatchVariablesInModules(nameUnder, result, false);
1408         }
1409         FindMatchDeclarationsInCurrentScope(nameUnder, ed, result, false, posEndOfWord);
1410     }
1411 }
1412 
FindGenericTypeBoudComponents(TokenFlat * token,TokensArrayFlat & result)1413 void ParserF::FindGenericTypeBoudComponents(TokenFlat* token, TokensArrayFlat& result)
1414 {
1415     if (token->m_TokenKind != tkInterface)
1416         return;
1417 
1418     if (token->m_PartLast.IsEmpty())
1419         return;
1420 
1421     wxArrayString specNames;
1422     wxStringTokenizer tkz(token->m_PartLast, _T(" \t\r\n"), wxTOKEN_STRTOK);
1423     while ( tkz.HasMoreTokens() )
1424     {
1425         specNames.Add(tkz.GetNextToken().Lower());
1426     }
1427     TokensArrayFlatClass procTokenArrTmp;
1428     TokensArrayFlat* procTokenArr = procTokenArrTmp.GetTokens();
1429     if (!FindTypeBoundProcedures(token, specNames, *procTokenArr))
1430         return;
1431     int kindMask = tkFunction | tkSubroutine;
1432     int noInChildren = tkInterface | tkFunction | tkSubroutine;
1433     for (size_t i=0; i<procTokenArr->Count(); i++)
1434     {
1435         wxString tokName;
1436         if (!procTokenArr->Item(i)->m_PartLast.IsEmpty())
1437             tokName = procTokenArr->Item(i)->m_PartLast;
1438         else
1439             tokName = procTokenArr->Item(i)->m_Name;
1440 
1441         TokensArrayFlatClass tokensTmp;
1442         TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
1443         bool found = FindMatchTokenInSameModule(procTokenArr->Item(i), tokName, *resultTmp, kindMask, noInChildren);
1444         if (!found)
1445             FindMatchTokensDeclared(tokName, *resultTmp, kindMask, false, noInChildren);
1446         if (resultTmp->GetCount() > 0)
1447         {
1448             result.Add( new TokenFlat(procTokenArr->Item(i)) );
1449             result.Add( new TokenFlat(resultTmp->Item(0)) );
1450         }
1451     }
1452 }
1453 
1454 
FindMatchOperatorTokensForJump(wxString & nameOperator,TokensArrayFlat & result)1455 void ParserF::FindMatchOperatorTokensForJump(wxString& nameOperator, TokensArrayFlat& result)
1456 {
1457     wxString nameFind;
1458     if (nameOperator.IsSameAs(_T("=")))
1459         nameFind = _T("%%assignment");
1460     else
1461         nameFind = _T("%%operator");
1462 
1463     int noChildrenOf = tkFunction | tkSubroutine | tkProgram;
1464     int tokKind = tkInterface;
1465     TokensArrayFlatClass tokensTmp;
1466     TokensArrayFlat* tokensTmpFl = tokensTmp.GetTokens();
1467     FindMatchTokensDeclared(nameFind, *tokensTmpFl, tokKind, true, noChildrenOf);
1468 
1469     wxString regExStr = _T("^") + nameFind + _T("[\\s\\t]*\\([\\s\\t]*\\") + nameOperator + _T("[\\s\\t]*\\).*");
1470     int opt = wxRE_ADVANCED | wxRE_ICASE | wxRE_NOSUB;
1471     wxRegEx opRegEx;
1472     if(!opRegEx.Compile(regExStr, opt))
1473         return;
1474 
1475     for (size_t i=0; i<tokensTmpFl->size(); i++)
1476     {
1477         if (opRegEx.Matches(tokensTmpFl->Item(i)->m_Name))
1478         {
1479             TokenFlat* newTok = new TokenFlat(tokensTmpFl->Item(i));
1480             newTok->m_DisplayName = newTok->m_DisplayName.Mid(2);
1481             newTok->m_Name = newTok->m_Name.Mid(2);
1482             result.Add(newTok);
1483         }
1484     }
1485 }
1486 
1487 
FindMatchTokensForJump(cbEditor * ed,bool onlyUseAssoc,bool onlyPublicNames,TokensArrayFlat & result)1488 void ParserF::FindMatchTokensForJump(cbEditor* ed, bool onlyUseAssoc, bool onlyPublicNames, TokensArrayFlat& result)
1489 {
1490     bool isAfterPercent = false;
1491     if (!ed)
1492         return;
1493     cbStyledTextCtrl* control = ed->GetControl();
1494     if (!control)
1495         return;
1496     int pos = control->GetCurrentPos();
1497     int posEndOfWord = control->WordEndPosition(pos, true);
1498     int posStartOfWord = control->WordStartPosition(pos, true);
1499     wxString nameUnder = control->GetTextRange(posStartOfWord, posEndOfWord);
1500     if (nameUnder.IsEmpty())
1501         return;
1502     int lineStartPos = control->GetLineEndPosition(control->LineFromPosition(posEndOfWord) - 1) + 1;
1503     wxString curLine = control->GetTextRange(lineStartPos,posEndOfWord);
1504 
1505     ChangeLineIfRequired(ed, curLine);
1506 
1507     if (!FindMatchTypeComponents(ed, curLine, result, false, onlyPublicNames, isAfterPercent, true))
1508         return;
1509 
1510     if (isAfterPercent)
1511         return;
1512 
1513     int tokKind = tkModule | tkSubmodule | tkFunction | tkProgram | tkSubroutine | tkPreprocessor | tkInterface |
1514                   tkBlockData | tkType | tkVariable | tkProcedure;
1515     if (onlyUseAssoc)
1516     {
1517         TokensArrayFlatClass tokensTmp;
1518         TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
1519         TokensArrayFlatClass tokensTmpU;
1520         TokensArrayFlat* resultTmpU = tokensTmpU.GetTokens();
1521         FindUseAssociatedTokens(onlyPublicNames, ed, nameUnder, false, *resultTmp, tokKind, false, resultTmpU);
1522         FindImplementedProcInMySubmodules(ed, nameUnder, *resultTmp);
1523         for (size_t i=0; i<resultTmpU->GetCount(); i++)
1524         {
1525             AddUniqueResult(result, resultTmpU->Item(i));
1526         }
1527         for (size_t i=0; i<resultTmp->GetCount(); i++)
1528         {
1529             result.Add(new TokenFlat(resultTmp->Item(i)));
1530         }
1531         int noChildrenOf = tkInterface | tkModule | tkSubmodule | tkFunction | tkSubroutine | tkProgram;
1532         FindMatchTokensDeclared(nameUnder, result, tokKind, false, noChildrenOf, false, true); // take global procedures only
1533     }
1534     else
1535     {
1536         int noChildrenOf = tkFunction | tkSubroutine | tkProgram;
1537         FindMatchTokensDeclared(nameUnder, result, tokKind, false, noChildrenOf);
1538         FindMatchVariablesInModules(nameUnder, result, false);
1539     }
1540     FindMatchDeclarationsInCurrentScope(nameUnder, ed, result, false, posEndOfWord);
1541 
1542     if (result.GetCount() == 0 && IsIncludeFile(ed->GetFilename()))
1543     {
1544         FindMatchTokensAtInclude(ed, nameUnder, onlyPublicNames, false, result);
1545     }
1546 }
1547 
1548 
FindMatchTokensForCodeCompletion(bool useSmartCC,bool onlyUseAssoc,bool onlyPublicNames,const wxString & nameUnderCursor,cbEditor * ed,TokensArrayFlat & result,bool & isAfterPercent,int & tokKind,wxArrayString & firstWords)1549 bool ParserF::FindMatchTokensForCodeCompletion(bool useSmartCC, bool onlyUseAssoc, bool onlyPublicNames, const wxString& nameUnderCursor, cbEditor* ed,
1550                                                TokensArrayFlat& result, bool& isAfterPercent, int& tokKind, wxArrayString& firstWords)
1551 {
1552     wxString curLine;
1553     if (!FindWordsBefore(ed, 100, curLine, firstWords))  //get words on the line
1554         return false;
1555 
1556     ChangeLineIfRequired(ed, curLine);
1557 
1558     isAfterPercent = false;
1559     if (!FindMatchTypeComponents(ed, curLine, result, true, onlyPublicNames, isAfterPercent, false))
1560         return true;
1561 
1562     if (isAfterPercent)
1563         return true;
1564 
1565     bool allowVariables;
1566     kindOfCCList kindCC = kccOther;
1567     if (!useSmartCC)
1568     {
1569         tokKind = tkFunction | tkProgram | tkSubroutine | tkPreprocessor | tkInterface | tkBlockData | tkType;
1570         allowVariables = true;
1571     }
1572     else
1573     {
1574         CCSmartFilter::GetTokenKind(firstWords, tokKind, allowVariables, kindCC);
1575     }
1576 
1577     if (kindCC == kccUseAssocTokens)
1578     {
1579         // if we are after "use" statement
1580         wxString nameUnderCursorLw = nameUnderCursor.Lower();
1581         FindTokensForUse(nameUnderCursorLw, firstWords, result, onlyPublicNames); // we are on line with: use mod_name subr_name...
1582         tokKind = 0; // no keywords
1583     }
1584     else if (kindCC == kccAccessList)
1585     {
1586         // if we are after "private" or "public" or "protected" statement
1587         FindUseAssociatedTokens(onlyPublicNames, ed, nameUnderCursor, true, result, tokKind, true);
1588         FindMatchDeclarationsInCurrentScope(nameUnderCursor, ed, result, true);
1589         tokKind = 0; // no keywords
1590     }
1591     else if (onlyUseAssoc)
1592     {
1593         bool classVar = false;
1594         if (allowVariables)
1595         {
1596             tokKind = tokKind | tkVariable;
1597         }
1598         else if (firstWords.GetCount() > 0 && firstWords.Item(0).IsSameAs(_T("call")))
1599         {
1600             tokKind = tokKind | tkVariable;
1601             classVar = true;
1602         }
1603 
1604         bool wasTkOtherRemoved = false;
1605         if (tokKind & tkOther)
1606         {
1607             tokKind = tokKind ^ tkOther;
1608             wasTkOtherRemoved = true;
1609         }
1610         FindUseAssociatedTokens(onlyPublicNames, ed, nameUnderCursor, true, result, tokKind, true);
1611 
1612         int noChildrenOf = tkInterface | tkModule | tkSubmodule | tkFunction | tkSubroutine | tkProgram;
1613         FindMatchTokensDeclared(nameUnderCursor, result, tokKind, true, noChildrenOf, false, true); // take global procedures only
1614 
1615         if (allowVariables || classVar)
1616         {
1617             FindMatchDeclarationsInCurrentScope(nameUnderCursor, ed, result, true);
1618         }
1619 
1620         if (classVar)
1621         {
1622             int i = 0;
1623             while (true)
1624             {
1625                 if (i >= int(result.GetCount()))
1626                     break;
1627                 TokenF* tok = result.Item(i);
1628                 if ( tok->m_TokenKind == tkVariable )
1629                 {
1630                     wxString tDefLow = tok->m_TypeDefinition.Lower();
1631                     if ( !tDefLow.StartsWith(_T("type")) && !tDefLow.StartsWith(_T("class")) )
1632                     {
1633                         result.Item(i)->Clear();
1634                         delete result.Item(i);
1635                         result.RemoveAt(i);
1636                         i--;
1637                     }
1638                 }
1639                 i++;
1640             }
1641         }
1642 
1643         if (wasTkOtherRemoved)
1644             tokKind = tokKind | tkOther;
1645     }
1646     else
1647     {
1648         int noChildrenOf = tkInterface | tkFunction | tkSubroutine | tkProgram;
1649         FindMatchTokensDeclared(nameUnderCursor, result, tokKind, true, noChildrenOf, onlyPublicNames);
1650 
1651         if (allowVariables)
1652         {
1653             FindMatchVariablesInModules(nameUnderCursor, result, true);
1654             FindMatchDeclarationsInCurrentScope(nameUnderCursor, ed, result, true);
1655         }
1656 
1657         if (tokKind & tkSubroutine)
1658         {
1659             if (firstWords.GetCount() > 0 && firstWords.Item(0).IsSameAs(_T("call")))
1660             {
1661                 TokensArrayFlatClass tokensTmp;
1662                 TokensArrayFlat* resTmp = tokensTmp.GetTokens();
1663 
1664                 FindMatchVariablesInModules(nameUnderCursor, *resTmp, true);
1665                 FindMatchDeclarationsInCurrentScope(nameUnderCursor, ed, *resTmp, true);
1666 
1667                 for (size_t i=0; i<resTmp->Count(); i++)
1668                 {
1669                     TokenF* tok = resTmp->Item(i);
1670                     if ( tok->m_TokenKind == tkVariable )
1671                     {
1672                         wxString tDefLow = tok->m_TypeDefinition.Lower();
1673                         if ( tDefLow.StartsWith(_T("type")) || tDefLow.StartsWith(_T("class")) )
1674                         {
1675                             result.Add(new TokenFlat(tok));
1676                         }
1677                     }
1678                 }
1679             }
1680         }
1681     }
1682 
1683     if (result.Count() == 0 && IsIncludeFile(ed->GetFilename()))
1684     {
1685         FindMatchTokensAtInclude(ed, nameUnderCursor, onlyPublicNames, true, result);
1686     }
1687 
1688     if (tokKind & tkSubmodule)
1689     {
1690         for (size_t i=0; i<result.Count(); i++)
1691         {
1692             TokenFlat* tok = result.Item(i);
1693             if (tok->m_TokenKind == tkSubmodule)
1694             {
1695                 wxString name = tok->m_DisplayName.BeforeFirst('(');
1696                 tok->m_DisplayName = name.Trim();
1697             }
1698         }
1699     }
1700     return true;
1701 }
1702 
FindWordsBefore(cbEditor * ed,int numberOfWordsMax,wxString & curLine,wxArrayString & firstWords)1703 bool ParserF::FindWordsBefore(cbEditor* ed, int numberOfWordsMax, wxString &curLine, wxArrayString &firstWords)
1704 {
1705     /* Finds word before current word (first word).
1706     */
1707     if (!ed)
1708         return false;
1709     cbStyledTextCtrl* control = ed->GetControl();
1710     if (!control)
1711         return false;
1712     int pos   = control->GetCurrentPos();
1713     int lineCur = control->LineFromPosition(pos);
1714     int lineStartPos = control->PositionFromLine(lineCur);
1715     curLine = control->GetTextRange(lineStartPos,pos);
1716 //    if (curLine.Find('!') != wxNOT_FOUND)
1717 //        return false; // we are in comments
1718     wxString line = curLine;
1719 
1720     for (int i=lineCur-1; i>=0; i--)
1721     {
1722         wxString tmpLine = control->GetLine(i).BeforeFirst('!').Trim();
1723         if (tmpLine.EndsWith(_T("&")))
1724         {
1725             // current line is continuation line
1726             tmpLine = tmpLine.BeforeLast('&').Trim();
1727             if (!tmpLine.IsEmpty())
1728             {
1729                 line.Prepend(_T(" "));
1730                 line.Prepend(tmpLine);
1731             }
1732         }
1733         else if (!tmpLine.IsEmpty())
1734         {
1735             break;
1736         }
1737     }
1738 
1739     // end of current word
1740     bool found = false;
1741     int idx;
1742     for (int i=line.Len()-1; i>=0; i--)
1743     {
1744         if (!isalnum(line.GetChar(i)) && (line.GetChar(i) != '_'))
1745         {
1746             found = true;
1747             idx = i;
1748             break;
1749         }
1750     }
1751     if (!found)
1752     {
1753         firstWords.Add(wxEmptyString);
1754         return true;
1755     }
1756 
1757     for (int nword=0; nword<numberOfWordsMax; nword++)
1758     {
1759         // end of first word
1760         int idx_end = -1;
1761         for (int i=idx; i>=0; i--)
1762         {
1763             if (!isspace(line.GetChar(i)))
1764             {
1765                 idx_end = i;
1766                 break;
1767             }
1768         }
1769         if (idx_end == -1)
1770         {
1771             if (firstWords.Count() == 0)
1772                 firstWords.Add(wxEmptyString);
1773             break;
1774         }
1775         else if (!isalnum(line.GetChar(idx_end)) && (line.GetChar(idx_end) != '_'))
1776         {
1777             firstWords.Add(line.GetChar(idx_end));
1778             idx = idx_end - 1;
1779         }
1780         else
1781         {
1782             // start of first word
1783             int idx_start = 0;
1784             for (int i=idx_end-1; i>=0; i--)
1785             {
1786                 if (!isalnum(line.GetChar(i)) && (line.GetChar(i) != '_'))
1787                 {
1788                     idx_start = i + 1;
1789                     break;
1790                 }
1791             }
1792             firstWords.Add(line.Mid(idx_start, idx_end-idx_start+1).Lower());
1793             idx = idx_start - 1;
1794         }
1795     }
1796     return true;
1797 }
1798 
CutBlocks(const wxChar & ch,wxString & line)1799 bool ParserF::CutBlocks(const wxChar& ch, wxString& line)
1800 {
1801 	// cut blocks () [] {} <>
1802 	wxChar match;
1803 	switch (ch)
1804 	{
1805 		case '(': match = ')'; break;
1806 		case '[': match = ']'; break;
1807 		case '{': match = '}'; break;
1808 		case '<': match = '>'; break;
1809 		default : return false;
1810 	}
1811 
1812     std::vector<int> startAll;
1813     startAll.reserve(10);
1814 	int count = 0; // counter for nested blocks (xxx())
1815 	int i = 0;
1816 	int end;
1817 	while (i < (int)line.length())
1818 	{
1819 	    while (i < (int)line.length())
1820 	    {
1821             if (line.GetChar(i) == '"' || line.GetChar(i) == '\'')
1822             {
1823                 // this is the case that match is inside a string!
1824                 char cha = line.GetChar(i);
1825                 i++;
1826                 while (i < (int)line.length())
1827                 {
1828                     if (line.GetChar(i) == cha)
1829                         break;
1830                     else
1831                         i++;
1832                 }
1833                 i++;
1834             }
1835             else
1836                 break;
1837         }
1838 		if (line.GetChar(i) == ch)
1839 		{
1840             startAll.push_back(i);
1841 			count++;
1842 		}
1843 		else if (line.GetChar(i) == match)
1844 		{
1845 		    if (count > 0)
1846 		    {
1847                 end = i;
1848                 wxString line_new = line.Mid(0,startAll[count-1]);
1849                 if (end+1 < (int)line.length())
1850                     line_new.Append(line.Mid(end+1));
1851                 line = line_new;
1852                 i = startAll[count-1] - 1;
1853                 startAll.pop_back();
1854                 count--;
1855 		    }
1856 		}
1857 		i++;
1858 	}
1859 	return true;
1860 }
1861 
GetTypeOfComponent(const wxString & nameType,const wxString & nameComponent,wxString & nameTypeComponent)1862 bool ParserF::GetTypeOfComponent(const wxString& nameType, const wxString& nameComponent, wxString& nameTypeComponent)
1863 {
1864     for (size_t i=0; i<m_pTokens->GetCount(); i++)
1865     {
1866         TokenF* pfToken = m_pTokens->Item(i);
1867         for (size_t j=0; j<pfToken->m_Children.GetCount(); j++)
1868         {
1869             TokenF* pToken = pfToken->m_Children.Item(j);
1870             if (pToken->m_TokenKind == tkModule)
1871             {
1872                 for (size_t k=0; k<pToken->m_Children.GetCount(); k++)
1873                 {
1874                     if (pToken->m_Children.Item(k)->m_TokenKind == tkType)
1875                     {
1876                         TokenF* pT = pToken->m_Children.Item(k);
1877                         if (pT->m_Name.IsSameAs(nameType))
1878                         {
1879                             if (GetTypeOfComponent(&pT, nameComponent, nameTypeComponent))
1880                                 return true;
1881                         }
1882                     }
1883                 }
1884             }
1885         }
1886     }
1887     return false;
1888 }
1889 
GetTypeOfComponent(TokenF ** ppT,const wxString & nameComponent,wxString & nameTypeComponent)1890 bool ParserF::GetTypeOfComponent(TokenF** ppT, const wxString& nameComponent, wxString& nameTypeComponent)
1891 {
1892     TokenF* pT = *ppT;
1893     if (GetTypeOfChild(pT, nameComponent, nameTypeComponent))
1894         return true;
1895 
1896     //Maybe nameComponent is parent type?
1897     if (!pT->m_ExtendsType.IsEmpty() && pT->m_ExtendsType.Lower().IsSameAs(nameComponent))
1898     {
1899         nameTypeComponent = pT->m_ExtendsType.Lower();
1900         return true;
1901     }
1902     else if (!pT->m_ExtendsType.IsEmpty())
1903     {
1904         for (size_t l=0; l<30; l++)
1905         {
1906             TokenF* typeToken = GetType(pT->m_ExtendsType.Lower());
1907             if(!typeToken)
1908                 break; // type was not found
1909             if (GetTypeOfChild(typeToken, nameComponent, nameTypeComponent))
1910             {
1911                 *ppT = typeToken;
1912                 return true;
1913             }
1914             else if (!typeToken->m_ExtendsType.IsEmpty() && typeToken->m_ExtendsType.Lower().IsSameAs(nameComponent))
1915             {
1916                 nameTypeComponent = typeToken->m_ExtendsType.Lower();
1917                 return true;
1918             }
1919             else if(!typeToken->m_ExtendsType.IsEmpty())
1920             {
1921                 pT = typeToken;
1922             }
1923             else
1924             {
1925                 break;
1926             }
1927         }
1928     }
1929     return false;
1930 }
1931 
1932 
GetTypeOfChild(TokenF * pT,const wxString & nameComponent,wxString & nameTypeComponent)1933 bool ParserF::GetTypeOfChild(TokenF* pT, const wxString& nameComponent, wxString& nameTypeComponent)
1934 {
1935     for (size_t l=0; l<pT->m_Children.GetCount(); l++)
1936     {
1937         if ((pT->m_Children.Item(l)->m_Name.IsSameAs(nameComponent)) && (pT->m_Children.Item(l)->m_TokenKind == tkVariable))
1938         {
1939             wxString tdef = pT->m_Children.Item(l)->m_TypeDefinition.Lower();
1940             if (tdef.StartsWith(_T("type")) || tdef.StartsWith(_T("class")))
1941             {
1942                 int idx_a = tdef.Find(_T(")"));
1943                 int idx_b = tdef.Find(_T("("));
1944                 if (idx_a != wxNOT_FOUND && idx_b != wxNOT_FOUND && idx_a > idx_b)
1945                 {
1946                     nameTypeComponent = tdef.Mid(idx_b+1,idx_a-idx_b-1);
1947                     return true;
1948                 }
1949             }
1950             else
1951             {
1952                 nameTypeComponent = tdef;
1953                 return true;
1954             }
1955         }
1956     }
1957     return false;
1958 }
1959 
GetType(const wxString & nameType)1960 TokenF* ParserF::GetType(const wxString& nameType)
1961 {
1962     for (size_t i=0; i<m_pTokens->GetCount(); i++)
1963     {
1964         TokenF* pfToken = m_pTokens->Item(i);
1965         for (size_t j=0; j<pfToken->m_Children.GetCount(); j++)
1966         {
1967             TokenF* pToken = pfToken->m_Children.Item(j);
1968             if (pToken->m_TokenKind == tkModule)
1969             {
1970                 for (size_t k=0; k<pToken->m_Children.GetCount(); k++)
1971                 {
1972                     if (pToken->m_Children.Item(k)->m_TokenKind == tkType)
1973                     {
1974                         TokenF* pT = pToken->m_Children.Item(k);
1975                         if (pT->m_Name.IsSameAs(nameType))
1976                         {
1977                             return pT;
1978                         }
1979                     }
1980                 }
1981             }
1982         }
1983     }
1984     return NULL;
1985 }
1986 
GetTypeInFile(const wxString & fileName,const unsigned int line,const wxString & nameType)1987 TokenF* ParserF::GetTypeInFile(const wxString& fileName, const unsigned int line, const wxString& nameType)
1988 {
1989     TokensArrayF tokens;
1990     FindMatchTokens(fileName, nameType, tokens);
1991     for (size_t i=0; i<tokens.GetCount(); i++)
1992     {
1993         if (tokens.Item(i)->m_TokenKind == tkType && tokens.Item(i)->m_LineStart == line
1994             && tokens.Item(i)->m_Name.IsSameAs(nameType))
1995         {
1996             return tokens.Item(i);
1997         }
1998     }
1999     return NULL;
2000 }
2001 
GetTypeComponentsInFile(const wxString & fileName,const unsigned int line,const wxString & nameType,TokensArrayFlat * result)2002 void ParserF::GetTypeComponentsInFile(const wxString& fileName, const unsigned int line, const wxString& nameType, TokensArrayFlat* result)
2003 {
2004     wxCriticalSectionLocker locker(s_CritSect);
2005 
2006     TokenF* typeToken = GetTypeInFile(fileName, line, nameType);
2007     if (!typeToken)
2008         return;
2009 
2010     for (size_t i=0; i<typeToken->m_Children.GetCount(); i++)
2011     {
2012         TokenF* tokenCh = typeToken->m_Children.Item(i);
2013         result->Add(new TokenFlat(tokenCh));
2014     }
2015 }
2016 
FindTokenDeclaration(TokenFlat & token,const wxString & argName,wxString & argDecl,wxString & argDescription)2017 bool ParserF::FindTokenDeclaration(TokenFlat& token, const wxString& argName, wxString& argDecl, wxString& argDescription)
2018 {
2019     TokenF * pTok = FindToken(token);
2020     if (!pTok)
2021         return false;
2022     TokensArrayF* pChildren = &pTok->m_Children;
2023 
2024     bool found = false;
2025     wxString argNameLw = argName.Lower();
2026     for (size_t i=0; i<pChildren->GetCount(); i++)
2027     {
2028         if (pChildren->Item(i)->m_Name.IsSameAs(argNameLw))
2029         {
2030             if (pChildren->Item(i)->m_TokenKind == tkProcedure)
2031             {
2032                 argDecl << _T("procedure(") << pChildren->Item(i)->m_PartLast << _T(") :: ")
2033                         << pChildren->Item(i)->m_DisplayName;
2034             }
2035             else
2036             {
2037                 argDecl << pChildren->Item(i)->m_TypeDefinition << _T(" :: ")
2038                         << pChildren->Item(i)->m_DisplayName << pChildren->Item(i)->m_Args;
2039                 argDescription << HtmlDoc::GetDocShort(pChildren->Item(i)->m_DocString);
2040             }
2041             found = true;
2042             break;
2043         }
2044     }
2045     return found;
2046 }
2047 
FindTokenRange(TokenFlat & token,wxString & txtRange)2048 bool ParserF::FindTokenRange(TokenFlat& token, wxString& txtRange)
2049 {
2050     wxString buff;
2051     std::vector<int> lineStarts;
2052     return FindTokenRange(token, txtRange, buff, lineStarts);
2053 }
2054 
FindTokenRange(TokenFlat & token,wxString & txtRange,wxString & buff,std::vector<int> & lineStarts,bool withDefinition,bool readFile)2055 bool ParserF::FindTokenRange(TokenFlat& token, wxString& txtRange, wxString& buff, std::vector<int> &lineStarts, bool withDefinition, bool readFile)
2056 {
2057     if (!wxFileExists(token.m_Filename))
2058         return false;
2059 
2060     if (readFile)
2061     {
2062         lineStarts.clear();
2063         buff.Empty();
2064 
2065         if (!Manager::Get()->GetEditorManager())
2066             return false;
2067 
2068         cbEditor* ed = Manager::Get()->GetEditorManager()->IsBuiltinOpen(token.m_Filename);
2069         if (ed) // File is opened
2070         {
2071             cbStyledTextCtrl* control = ed->GetControl();
2072             if (!control)
2073                 return false;
2074             buff = control->GetText();
2075         }
2076         else
2077         {
2078             wxFile file(token.m_Filename);
2079             if (!ReadFileToString(file,buff))
2080                 return false;
2081         }
2082         lineStarts.push_back(0);
2083     }
2084     else
2085     {
2086         //use buff content
2087     }
2088 
2089     //get range of token
2090     size_t pos_start=0;
2091     size_t pos_end=0;
2092     size_t line = 1;
2093     unsigned int lStart = token.m_LineStart;
2094     if (!withDefinition)
2095         lStart += token.m_DefinitionLength;
2096 
2097 
2098     bool startFound = false;
2099     bool endFound = false;
2100     for (size_t i=0; i<buff.Length(); i++)
2101     {
2102         if (!startFound && lStart <= line)
2103         {
2104             pos_start = i;
2105             startFound = true;
2106         }
2107         else if (!endFound && token.m_LineEnd < line)
2108         {
2109             pos_end = i;
2110             endFound = true;
2111             if (!readFile)
2112                 break;
2113         }
2114 
2115         if (buff.GetChar(i) == '\n')
2116         {
2117             line++;
2118             if (readFile)
2119                 lineStarts.push_back(i+1);
2120         }
2121     }
2122     if (!startFound)
2123         return false;
2124 
2125     if (pos_start > pos_end)
2126     {
2127         pos_end = buff.Length();
2128     }
2129     txtRange = buff.Mid(pos_start, pos_end - pos_start);
2130     return true;
2131 }
2132 
FindInfoLog(TokenFlat & token,bool logComAbove,bool logComBelow,bool logDeclar,bool logComVariab,wxString & msg)2133 bool ParserF::FindInfoLog(TokenFlat& token, bool logComAbove, bool logComBelow, bool logDeclar, bool logComVariab, wxString& msg)
2134 {
2135     wxString argsNew = wxEmptyString;
2136     bool readFile = true;
2137     return FindInfoLog(token, logComAbove, logComBelow, logDeclar, logComVariab, msg, argsNew, readFile);
2138 }
2139 
FindInfoLog(TokenFlat & token,bool logComAbove,bool logComBelow,bool logDeclar,bool logComVariab,wxString & msg,bool readFile)2140 bool ParserF::FindInfoLog(TokenFlat& token, bool logComAbove, bool logComBelow, bool logDeclar, bool logComVariab, wxString& msg,
2141                           bool readFile)
2142 {
2143     wxString argsNew = wxEmptyString;
2144     return FindInfoLog(token, logComAbove, logComBelow, logDeclar, logComVariab, msg, argsNew, readFile);
2145 }
2146 
FindInfoLog(TokenFlat & token,bool logComAbove,bool logComBelow,bool logDeclar,bool logComVariab,wxString & msg,wxString & argsNew)2147 bool ParserF::FindInfoLog(TokenFlat& token, bool logComAbove, bool logComBelow, bool logDeclar, bool logComVariab, wxString& msg,
2148                           wxString& argsNew)
2149 {
2150     bool readFile = true;
2151     return FindInfoLog(token, logComAbove, logComBelow, logDeclar, logComVariab, msg, argsNew, readFile);
2152 }
2153 
2154 
FindInfoLog(TokenFlat & token,bool logComAbove,bool logComBelow,bool logDeclar,bool logComVariab,wxString & msg,const wxString & argsNew,bool readFile)2155 bool ParserF::FindInfoLog(TokenFlat& token, bool logComAbove, bool logComBelow, bool logDeclar, bool logComVariab, wxString& msg,
2156                           const wxString& argsNew, bool readFile)
2157 {
2158     wxString txtRange;
2159     if (!FindTokenRange(token, txtRange, m_Buff, m_LineStarts, false, readFile))
2160         return false;
2161 
2162     FortranSourceForm fsForm;
2163     if (!IsFileFortran(token.m_Filename, fsForm))
2164         return false;
2165 
2166     //Parse
2167     TokensArrayClass tokensTmp;
2168     TokensArrayF* parsResult = tokensTmp.GetTokens();
2169     ParserThreadF thread = ParserThreadF(wxEmptyString, txtRange, parsResult, fsForm, true);
2170 
2171     if (logComAbove)
2172     {
2173         // insert comments above
2174         wxArrayString comAbove;
2175         bool startDoxy = false;
2176         bool allowSimple = true;
2177         int endFor = std::max(int(token.m_LineStart)-100, 0);
2178         for (int i=token.m_LineStart-1; i>endFor; i--)
2179         {
2180             wxString str1 = m_Buff.Mid(m_LineStarts[i-1], m_LineStarts[i]-m_LineStarts[i-1]).Trim(false);
2181             if ( str1.IsEmpty() && startDoxy )
2182             {
2183                 break;
2184             }
2185             else if ( str1.StartsWith(_T("!>")) || str1.StartsWith(_T("!<")) || str1.StartsWith(_T("!!")) )
2186             {
2187                 comAbove.Add(str1);
2188                 startDoxy = true;
2189             }
2190             else if ( allowSimple && str1.StartsWith(_T("!")) )
2191             {
2192                 comAbove.Add(str1);
2193             }
2194             else if ( str1.IsEmpty() )
2195             {
2196                 allowSimple = false;
2197             }
2198             else
2199             {
2200                 break;
2201             }
2202         }
2203 
2204         for (int i=comAbove.GetCount()-1; i>=0; i--)
2205         {
2206             msg << comAbove.Item(i);
2207         }
2208     }
2209 
2210     if (token.m_TokenKind != tkType)
2211         thread.ParseDeclarations();
2212 
2213     if (token.m_TokenKind == tkSubroutine)
2214     {
2215         if (token.m_Name.IsSameAs(_T("__fortran_statement_open")))
2216             msg << _T("OPEN");
2217         else
2218             msg << _T("subroutine ") << token.m_DisplayName;
2219         if (argsNew.IsEmpty())
2220             msg << token.m_Args << _T("\n");
2221         else
2222             msg << argsNew << _T("\n");
2223     }
2224     else if (token.m_TokenKind == tkFunction)
2225     {
2226         if (!token.m_PartFirst.IsEmpty())
2227         {
2228             msg << token.m_PartFirst << _T(" ");
2229         }
2230         msg << _T("function ") << token.m_DisplayName;
2231         if (argsNew.IsEmpty())
2232             msg << token.m_Args;
2233         else
2234             msg << argsNew;
2235         if (!token.m_PartLast.IsEmpty())
2236         {
2237             msg << _T(" ") << token.m_PartLast;
2238         }
2239         msg << _T("\n");
2240     }
2241     else if (token.m_TokenKind == tkType)
2242     {
2243         for (size_t i=token.m_LineStart-1; i<token.m_LineEnd; i++)
2244         {
2245             size_t slen;
2246             if (i+1 < m_LineStarts.size())
2247                 slen = m_LineStarts[i+1] - m_LineStarts[i];
2248             else
2249                 slen = m_Buff.Length() - m_LineStarts[i];
2250             wxString str1 = m_Buff.Mid(m_LineStarts[i], slen).Trim(false).Trim();
2251             if (i+1 == token.m_LineStart || i+1 == token.m_LineEnd)
2252                 msg << str1 << _T("\n");
2253             else if (str1.BeforeFirst('!').Trim().Lower().IsSameAs(_T("contains")))
2254                 msg << str1 << _T("\n");
2255             else
2256                 msg << _T("    ") << str1 << _T("\n");
2257         }
2258     }
2259 
2260     if (logComBelow)
2261     {
2262         // insert comments below
2263         unsigned int lStart = token.m_LineStart + token.m_DefinitionLength;
2264         for (unsigned int i=lStart; i<token.m_LineEnd; i++)
2265         {
2266             wxString str1 = m_Buff.Mid(m_LineStarts[i-1], m_LineStarts[i]-m_LineStarts[i-1]).Trim(false);
2267             if (str1.StartsWith(_T("!")))
2268             {
2269                 msg << _T("    ") << str1;
2270             }
2271             else
2272             {
2273                 break;
2274             }
2275         }
2276     }
2277 
2278     wxArrayString argMsgArr;
2279     int maxLenArg = 0;
2280     std::vector<size_t> idxOrder;
2281 
2282     if (logDeclar && token.m_TokenKind != tkType)
2283     {
2284         wxArrayString argArr;
2285         wxStringTokenizer tkz(token.m_Args, _T("(),[] \t\r\n"), wxTOKEN_STRTOK );
2286         while ( tkz.HasMoreTokens() )
2287         {
2288             argArr.Add(tkz.GetNextToken());
2289         }
2290 
2291         if (token.m_TokenKind == tkFunction)
2292         {
2293             wxString arg1;
2294             if (!token.m_ResultVariable.IsEmpty())
2295             {
2296                 arg1 = token.m_ResultVariable.Lower();
2297             }
2298             else
2299             {
2300                 arg1 = token.m_Name.Lower();
2301             }
2302             for (size_t i=0; i<parsResult->GetCount(); i++)
2303             {
2304                 if (parsResult->Item(i)->m_Name.IsSameAs(arg1))
2305                 {
2306                     msg << _T("    ") << parsResult->Item(i)->m_TypeDefinition << _T(" :: ")
2307                         << parsResult->Item(i)->m_DisplayName << parsResult->Item(i)->m_Args;
2308                     if (parsResult->Item(i)->m_DocString.length() > 0)
2309                         msg << _T(" ! ") << parsResult->Item(i)->m_DocString;
2310                     msg << _T("\n");
2311                     break;
2312                 }
2313             }
2314         }
2315 
2316         for (size_t j=0; j<argArr.Count(); j++)
2317         {
2318             wxString msg1;
2319             wxString arg1 = argArr.Item(j).Lower();
2320             for (size_t i=0; i<parsResult->GetCount(); i++)
2321             {
2322                 if (parsResult->Item(i)->m_Name.IsSameAs(arg1))
2323                 {
2324                     if (parsResult->Item(i)->m_TokenKind == tkProcedure)
2325                     {
2326                         msg1 << _T("    ") << parsResult->Item(i)->m_TypeDefinition
2327                              << _T(" :: ") << parsResult->Item(i)->m_DisplayName;
2328                         if (parsResult->Item(i)->m_DocString.length() > 0)
2329                              msg1 << _T(" ! ") << parsResult->Item(i)->m_DocString;
2330                     }
2331                     else
2332                     {
2333                         msg1 << _T("    ") << parsResult->Item(i)->m_TypeDefinition << _T(" :: ")
2334                              << parsResult->Item(i)->m_DisplayName << parsResult->Item(i)->m_Args;
2335                         if (parsResult->Item(i)->m_DocString.length() > 0)
2336                              msg1 << _T(" ! ") << parsResult->Item(i)->m_DocString;
2337                     }
2338                     idxOrder.push_back(i);
2339                     argMsgArr.Add(msg1);
2340                     int ln = msg1.Len();
2341                     if (ln > maxLenArg)
2342                         maxLenArg = ln;
2343                     break;
2344                 }
2345             }
2346         }
2347     }
2348 
2349     if (token.m_TokenKind != tkType)
2350     {
2351         if (maxLenArg >= 60)
2352             maxLenArg = 60;
2353 
2354         for (size_t j=0; j<argMsgArr.Count(); j++)
2355         {
2356             msg << argMsgArr.Item(j);
2357             if (logComVariab &&
2358                 parsResult->Item(idxOrder[j])->m_TokenKind != tkProcedure)
2359             {
2360                 wxString spaces;
2361                 int nspaces = maxLenArg - argMsgArr.Item(j).Len() + 1;
2362                 if (nspaces < 1)
2363                     nspaces = 1;
2364                 spaces.Append(' ',nspaces);
2365                 msg << spaces << parsResult->Item(idxOrder[j])->m_PartLast << _T("\n");
2366             }
2367             else
2368             {
2369                 msg << _T("\n");
2370             }
2371         }
2372     }
2373 
2374     if (token.m_ParentTokenKind == tkModule)
2375     {
2376         msg << _("!Module: ") << token.m_ParentDisplayName << _(". File: ");
2377     }
2378     else
2379     {
2380         msg << _("!File: ");
2381     }
2382     msg << token.m_Filename.AfterLast(wxFILE_SEP_PATH) << _T(":") << token.m_LineStart;
2383     return true;
2384 }
2385 
FindTooltipForTypeBoundProc(wxString & msg,TokenFlat * token1,TokenFlat * token2)2386 bool ParserF::FindTooltipForTypeBoundProc(wxString& msg, TokenFlat* token1, TokenFlat* token2)
2387 {
2388     if (!token1 || token1->m_TokenKind != tkProcedure)
2389         return false;
2390     wxString txtRange;
2391     wxString buff;
2392     std::vector<int> lineStarts;
2393     if (!FindTokenRange(*token1, txtRange, buff, lineStarts, true))
2394         return false;
2395     int ic = txtRange.Find(_T("::"));
2396     if (ic == wxNOT_FOUND)
2397     {
2398         msg << _T("procedure ") << token1->m_DisplayName;
2399         if (!token1->m_Args.IsEmpty())
2400         {
2401             msg << _T("(") << token1->m_Args << _T(")");
2402         }
2403     }
2404     else
2405     {
2406         msg << txtRange.Mid(0,ic+2).Trim(false) << _T(" ") << token1->m_DisplayName;
2407     }
2408     if (!token1->m_PartLast.IsEmpty())
2409     {
2410         msg << _T(" => ") << token1->m_PartLast;
2411     }
2412     msg << _T("\n");
2413 
2414     if (token2)
2415     {
2416         if (token2->m_TokenKind == tkSubroutine || token2->m_TokenKind == tkFunction)
2417         {
2418             wxString pass_arg = token1->m_Args;
2419             int start = 0;
2420             int end = 0;
2421             if (token1->m_Pass && !pass_arg.IsEmpty())
2422             {
2423                 GetPossitionOfDummyArgument(token2->m_Args, pass_arg, start, end);
2424             }
2425             else if (token1->m_Pass)
2426             {
2427                 GetCallTipHighlight(token2->m_Args, 0, start, end);
2428             }
2429             wxString argNew;
2430             if (end > start)
2431             {
2432                 argNew << token2->m_Args.Mid(0,start) << _T("[");
2433                 wxString secPart = token2->m_Args.Mid(start);
2434                 int icom = secPart.Find(_T(","));
2435                 if (icom != wxNOT_FOUND)
2436                 {
2437                     argNew << secPart.Mid(0,icom+1) << _T("]") << secPart.Mid(icom+1);
2438                 }
2439                 else
2440                 {
2441                     argNew << token2->m_Args.Mid(start,end-start) << _T("]") << token2->m_Args.Mid(end);
2442                 }
2443             }
2444             else
2445             {
2446                 argNew = token2->m_Args;
2447             }
2448             if (token2->m_TokenKind == tkSubroutine)
2449             {
2450                 msg << _T("subroutine ") << token2->m_DisplayName << argNew << _T("\n");
2451             }
2452             else if (token2->m_TokenKind == tkFunction)
2453             {
2454                 if (!token2->m_PartFirst.IsEmpty())
2455                 {
2456                     msg << token2->m_PartFirst << _T(" ");
2457                 }
2458                 msg << _T("function ") << token2->m_DisplayName << argNew << _T("\n");
2459             }
2460         }
2461     }
2462     if (!token1->m_Filename.IsEmpty())
2463     {
2464         msg << token1->m_Filename.AfterLast(wxFILE_SEP_PATH) << _T(":") << token1->m_LineStart;
2465     }
2466     return true;
2467 }
2468 
FindInfoLogForTypeBoundProc(TokensArrayFlat & tokenPair,bool logComAbove,bool logComBelow,bool logDeclar,bool logComVariab,wxString & msg,wxString * buff,std::vector<int> * lineStarts)2469 bool ParserF::FindInfoLogForTypeBoundProc(TokensArrayFlat& tokenPair, bool logComAbove, bool logComBelow, bool logDeclar, bool logComVariab, wxString& msg,
2470                                           wxString* buff, std::vector<int>* lineStarts)
2471 {
2472     if (tokenPair.GetCount() == 0)
2473     {
2474         return false;
2475     }
2476 
2477     TokenFlat* token1 = tokenPair.Item(0);
2478     if (token1->m_TokenKind != tkProcedure)
2479         return false;
2480     wxString txtRange;
2481     if (!buff)
2482     {
2483         buff= new wxString();
2484         lineStarts = new std::vector<int>;
2485         if (!FindTokenRange(*token1, txtRange, *buff, *lineStarts, true))
2486             return false;
2487         delete buff;
2488         delete lineStarts;
2489     }
2490     else
2491     {
2492         if (!FindTokenRange(*token1, txtRange, *buff, *lineStarts, true, false))
2493             return false;
2494     }
2495     int ic = txtRange.Find(_T("::"));
2496     if (ic == wxNOT_FOUND)
2497     {
2498         msg << _T("procedure ") << token1->m_DisplayName;
2499         if (token1->m_IsAbstract)
2500             msg << _T("(") << token1->m_PartLast << _T(")");
2501     }
2502     else
2503     {
2504         msg << txtRange.Mid(0,ic+2).Trim(false) << _T(" ") << token1->m_DisplayName;
2505     }
2506 
2507     if (!token1->m_PartLast.IsEmpty() && !token1->m_IsAbstract)
2508     {
2509         msg << _T(" => ") << token1->m_PartLast;
2510     }
2511     msg << _T("\n!File: ") << token1->m_Filename.AfterLast(wxFILE_SEP_PATH) << _T(":") << token1->m_LineStart << _T("\n");
2512 
2513     if (tokenPair.GetCount() > 1)
2514     {
2515         TokenFlat* token = tokenPair.Item(1);
2516         if (token->m_TokenKind == tkSubroutine || token->m_TokenKind == tkFunction)
2517         {
2518             wxString pass_arg = token1->m_Args;
2519             int start = 0;
2520             int end = 0;
2521             if (token1->m_Pass && !pass_arg.IsEmpty())
2522             {
2523                 GetPossitionOfDummyArgument(token->m_Args, pass_arg, start, end);
2524             }
2525             else if (token1->m_Pass)
2526             {
2527                 GetCallTipHighlight(token->m_Args, 0, start, end);
2528             }
2529             if (end > start)
2530             {
2531                 wxString argNew;
2532                 argNew << token->m_Args.Mid(0,start) << _T("[");
2533                 wxString secPart = token->m_Args.Mid(start);
2534                 int icom = secPart.Find(_T(","));
2535                 if (icom != wxNOT_FOUND)
2536                 {
2537                     argNew << secPart.Mid(0,icom+1) << _T("]") << secPart.Mid(icom+1);
2538                 }
2539                 else
2540                 {
2541                     argNew << token->m_Args.Mid(start,end-start) << _T("]") << token->m_Args.Mid(end);
2542                 }
2543                 FindInfoLog(*token, logComAbove, logComBelow, logDeclar, logComVariab, msg, argNew);
2544             }
2545             else
2546             {
2547                 FindInfoLog(*token, logComAbove, logComBelow, logDeclar, logComVariab, msg);
2548             }
2549         }
2550     }
2551     return true;
2552 }
2553 
FindInfoLogForGenericTBProc(TokensArrayFlat & tokens,bool logComAbove,bool logComBelow,bool logDeclar,bool logComVariab,wxString & msg)2554 bool ParserF::FindInfoLogForGenericTBProc(TokensArrayFlat& tokens, bool logComAbove, bool logComBelow, bool logDeclar, bool logComVariab, wxString& msg)
2555 {
2556     if (tokens.GetCount() == 0 || tokens.Item(0)->m_TokenKind != tkInterface)
2557     {
2558         return false;
2559     }
2560 
2561     wxString buff;
2562     std::vector<int> lineStarts;
2563     size_t iInt = 0;
2564     wxString filName;
2565     wxString msgProc;
2566 
2567     while ( iInt < tokens.GetCount() )
2568     {
2569         TokenFlat* token = tokens.Item(iInt);
2570         if (token->m_TokenKind != tkInterface)
2571             break;
2572         wxString tokRan;
2573         if (iInt == 0 || !filName.IsSameAs(token->m_Filename))
2574         {
2575             if (!FindTokenRange(*token, tokRan, buff, lineStarts, true))
2576                 return false;
2577             filName = token->m_Filename;
2578         }
2579         else
2580         {
2581             if (!FindTokenRange(*token, tokRan, buff, lineStarts, true, false))
2582                 return false;
2583         }
2584         msg.Append(_T("\n"));
2585         msg.Append( tokRan.Trim().Trim(false) );
2586 
2587         if (token->m_ParentTokenKind == tkType)
2588         {
2589             msg << _("\n!Type: ") << token->m_ParentDisplayName << _(". File: ");
2590         }
2591         msg << token->m_Filename.AfterLast(wxFILE_SEP_PATH) << _T(":") << token->m_LineStart;
2592 
2593         size_t i = iInt + 1;
2594         while ( i < tokens.GetCount()-1 )
2595         {
2596             if ( tokens.Item(i)->m_TokenKind == tkInterface )
2597                 break;
2598             msgProc << _T("\n!---------------------\n");
2599             TokensArrayFlatClass tokensTmpCl;
2600             TokensArrayFlat* tokensTmp = tokensTmpCl.GetTokens();
2601             tokensTmp->Add(new TokenFlat(tokens.Item(i)));
2602             tokensTmp->Add(new TokenFlat(tokens.Item(i+1)));
2603             FindInfoLogForTypeBoundProc(*tokensTmp, logComAbove, logComBelow, logDeclar, logComVariab, msgProc, &buff, &lineStarts);
2604             i += 2;
2605         }
2606         iInt = i;
2607     }
2608     msg.Trim(false).Append(msgProc);
2609 
2610     return true;
2611 }
2612 
GetTokenStr(TokenFlat & token,wxString & msg)2613 bool ParserF::GetTokenStr(TokenFlat& token, wxString& msg)
2614 {
2615     wxString buff;
2616     std::vector<int> lineStarts;
2617     if (!FindTokenRange(token, msg, buff, lineStarts, true))
2618         return false;
2619 
2620     if (token.m_ParentTokenKind == tkModule)
2621     {
2622         msg << _("\n!Module: ") << token.m_ParentDisplayName << _(". File: ");
2623     }
2624     else
2625     {
2626         msg << _("\n!File: ");
2627     }
2628     msg << token.m_Filename.AfterLast(wxFILE_SEP_PATH) << _T(":") << token.m_LineStart;
2629     return true;
2630 }
2631 
FindChildrenOfInterface(TokenFlat * token,TokensArrayFlat & result)2632 void ParserF::FindChildrenOfInterface(TokenFlat* token, TokensArrayFlat& result)
2633 {
2634     if (token->m_ParentTokenKind != tkModule)
2635         return;
2636 
2637     TokensArrayF* pFileChildren = FindFileTokens(token->m_Filename);
2638 
2639     for (size_t j=0; j < pFileChildren->GetCount(); j++)
2640     {
2641         if (pFileChildren->Item(j)->m_TokenKind == tkModule && pFileChildren->Item(j)->m_Name.IsSameAs(token->m_ParentName))
2642         {
2643             TokensArrayF* pModChildren = &pFileChildren->Item(j)->m_Children;
2644             for (size_t k=0; k < pModChildren->GetCount(); k++)
2645             {
2646                 if (pModChildren->Item(k)->m_Name.IsSameAs(token->m_Name) && pModChildren->Item(k)->m_TokenKind == tkInterface)
2647                 {
2648                     wxArrayString address;
2649                     address.Add(pFileChildren->Item(j)->m_Filename);
2650                     address.Add(pFileChildren->Item(j)->m_Name);
2651                     int tokenKindMask = tkSubroutine | tkFunction;
2652                     TokensArrayF* pIntChildren = &pModChildren->Item(k)->m_Children;
2653                     for (size_t l=0; l < pIntChildren->GetCount(); l++)
2654                     {
2655                         if (pIntChildren->Item(l)->m_TokenKind & tokenKindMask)
2656                         {
2657                             result.Add(new TokenFlat(pIntChildren->Item(l)));
2658                         }
2659                         else
2660                         {
2661                             wxString name = pIntChildren->Item(l)->m_Name;
2662                             FindUseAssociatedTokens(true, address, name, false, result, tokenKindMask | tkInterface, false);
2663                         }
2664                     }
2665                     break;
2666                 }
2667             }
2668             break;
2669         }
2670     }
2671 }
2672 
GetPossitionOfDummyArgument(const wxString & args,const wxString & arg,int & start,int & end)2673 void ParserF::GetPossitionOfDummyArgument(const wxString& args, const wxString& arg, int& start, int& end)
2674 {
2675     wxStringTokenizer tkz(args, _T(" ,\t\r\n()"), wxTOKEN_STRTOK);
2676     while ( tkz.HasMoreTokens() )
2677     {
2678         wxString token = tkz.GetNextToken();
2679         if (token.IsSameAs(arg))
2680         {
2681             end = tkz.GetPosition() - 1;
2682             start = end - token.Length();
2683             break;
2684         }
2685     }
2686 }
2687 
GetCallTipHighlight(const wxString & calltip,int commasWas,int & start,int & end)2688 void ParserF::GetCallTipHighlight(const wxString& calltip, int commasWas, int& start, int& end)
2689 {
2690     int pos = 1; // skip opening parenthesis
2691     int nest = 0;
2692     int commas = 0;
2693     start = 1;
2694     end = 0;
2695     while (true)
2696     {
2697         wxChar c = calltip.GetChar(pos++);
2698         if (c == '\0')
2699             break;
2700         else if (c == '(')
2701             ++nest;
2702         else if (c == ')')
2703             --nest;
2704         else if (c == ',' && nest <= 0)
2705         {
2706             ++commas;
2707             if (commas == commasWas)
2708             {
2709                 start = pos;
2710             }
2711             else if (commas == commasWas + 1)
2712             {
2713                 end = pos; // already incremented
2714                 break;
2715             }
2716         }
2717     }
2718     if (end == 0)
2719         end = calltip.Length() - 1;
2720     if (commas < commasWas)
2721     {
2722         start = end; //no highlight
2723     }
2724 }
2725 
FindUseAssociatedTokens(bool onlyPublicNames,TokenFlat * tok,const wxString & search,bool partialMatch,TokensArrayFlat & result,int tokenKindMask,bool changeDisplayName,TokensArrayFlat * useWithRenameTok)2726 void ParserF::FindUseAssociatedTokens(bool onlyPublicNames, TokenFlat* tok, const wxString& search, bool partialMatch, TokensArrayFlat& result, int tokenKindMask,
2727                                       bool changeDisplayName, TokensArrayFlat* useWithRenameTok)
2728 {
2729     wxArrayString address; // [file_name, module_name, function_name, etc.]
2730     FindAddress(tok, address);
2731     if (address.Count() < 2)
2732         return; // file only
2733 
2734     FindUseAssociatedTokens(onlyPublicNames, address, search, partialMatch, result, tokenKindMask, changeDisplayName, useWithRenameTok);
2735 }
2736 
FindUseAssociatedTokens(bool onlyPublicNames,cbEditor * ed,const wxString & search,bool partialMatch,TokensArrayFlat & result,int tokenKindMask,bool changeDisplayName,TokensArrayFlat * useWithRenameTok)2737 void ParserF::FindUseAssociatedTokens(bool onlyPublicNames, cbEditor* ed, const wxString& search, bool partialMatch, TokensArrayFlat& result, int tokenKindMask,
2738                                       bool changeDisplayName, TokensArrayFlat* useWithRenameTok)
2739 {
2740     wxArrayString address; // [file_name, module_name, function_name, etc.]
2741     FindAddress(ed, address);
2742     if (address.Count() < 2)
2743         return; // file only
2744 
2745     FindUseAssociatedTokens(onlyPublicNames, address, search, partialMatch, result, tokenKindMask, changeDisplayName, useWithRenameTok);
2746 }
2747 
FindUseAssociatedTokens(bool onlyPublicNames,wxArrayString & address,const wxString & search,bool partialMatch,TokensArrayFlat & result,int tokenKindMask,bool changeDisplayName,TokensArrayFlat * useWithRenameTok)2748 void ParserF::FindUseAssociatedTokens(bool onlyPublicNames, wxArrayString& address, const wxString& search, bool partialMatch, TokensArrayFlat& result, int tokenKindMask,
2749                                       bool changeDisplayName, TokensArrayFlat* useWithRenameTok)
2750 {
2751     wxString searchLw = search.Lower();
2752     wxCriticalSectionLocker locker(s_CritSect);
2753     if (address.Count() == 0)
2754         return;
2755     TokensArrayF* children = FindFileTokens(address.Item(0));
2756     if (!children)
2757         return;
2758 
2759     int callMask = tkCallFunction | tkCallSubroutine;
2760     std::vector<TokensArrayF*> vpChildren;
2761     TokensArrayF  useTokens;
2762     bool found = false;
2763     TokenF* subModToken = NULL;
2764     TokenF* procedureToken = NULL;
2765     for (size_t j=1; j<address.Count(); j++)
2766     {
2767         if (address.Item(j).IsEmpty())
2768             break;
2769 
2770         bool isInterfaceExp = address.Item(j).IsSameAs(_T("%%tkInterfaceExplicit"));
2771         found = false;
2772         for (size_t i=0; i<children->GetCount(); i++)
2773         {
2774             if (children->Item(i)->m_Name.IsSameAs(address.Item(j)) && !(children->Item(i)->m_TokenKind & callMask))
2775             {
2776                 vpChildren.push_back(&children->Item(i)->m_Children);
2777                 found = true;
2778                 if (children->Item(i)->m_TokenKind == tkSubmodule)
2779                     subModToken = children->Item(i);
2780                 else if (children->Item(i)->m_TokenKind == tkProcedure)
2781                     procedureToken = children->Item(i);
2782                 children = &children->Item(i)->m_Children;
2783                 break;
2784             }
2785             else if (isInterfaceExp && children->Item(i)->m_TokenKind == tkInterfaceExplicit
2786                      && children->Item(i)->m_Children.GetCount() > 0
2787                      && j+1 < address.Count())
2788             {
2789                 TokensArrayF* childrenIntExp = &children->Item(i)->m_Children;
2790                 for (size_t k=0; k<childrenIntExp->GetCount(); k++)
2791                 {
2792                     if (childrenIntExp->Item(k)->m_Name.IsSameAs(address.Item(j+1)))
2793                     {
2794                         vpChildren.push_back(&children->Item(i)->m_Children);
2795                         found = true;
2796                         children = childrenIntExp;
2797                         break;
2798                     }
2799                 }
2800             }
2801         }
2802         if (!found)
2803             break;
2804     }
2805 
2806     bool found_full_adress = (vpChildren.size() == address.size()-1);
2807     size_t sizeChildren = vpChildren.size();
2808 
2809     if (subModToken)
2810     {
2811         m_SubmodDeep = 0;
2812         size_t oldCountCh = vpChildren.size();
2813         GetSubmoduleHostTokens(subModToken, vpChildren);
2814 
2815         if (procedureToken)
2816         {
2817             found = false;
2818             int prTMask = tkFunction | tkSubroutine;
2819             for (size_t ichil=oldCountCh; ichil<vpChildren.size(); ichil++)
2820             {
2821                 TokensArrayF* pParChildren = vpChildren[ichil];
2822                 for (size_t i=0; i<pParChildren->GetCount(); i++)
2823                 {
2824                     if ((pParChildren->Item(i)->m_TokenKind == tkInterfaceExplicit) ||
2825                         (pParChildren->Item(i)->m_TokenKind == tkInterface))
2826                     {
2827                         TokensArrayF* pIntCh = &pParChildren->Item(i)->m_Children;
2828                         for (size_t k=0; k<pIntCh->GetCount(); k++)
2829                         {
2830                             if ((pIntCh->Item(k)->m_TokenKind & prTMask) &&
2831                                 pIntCh->Item(k)->m_Name.IsSameAs(procedureToken->m_Name) &&
2832                                 pIntCh->Item(k)->m_Children.GetCount())
2833                             {
2834                                 vpChildren.push_back(&pIntCh->Item(k)->m_Children);
2835                                 found = true;
2836                                 break;
2837                             }
2838                         }
2839                         if (found)
2840                             break;
2841                     }
2842                 }
2843                 if (found)
2844                     break;
2845             }
2846         }
2847     }
2848 
2849     int numInclude = 0;
2850     for (size_t ichil=0; ichil<vpChildren.size(); ichil++)
2851     {
2852         TokensArrayF* pParChildren = vpChildren[ichil];
2853         for (size_t i=0; i<pParChildren->GetCount(); i++)
2854         {
2855             if (pParChildren->Item(i)->m_TokenKind == tkUse)
2856             {
2857                 useTokens.Add(pParChildren->Item(i));
2858             }
2859             else if (pParChildren->Item(i)->m_TokenKind == tkInclude)
2860             {
2861                 TokensArrayF* includedTokens = new TokensArrayF();
2862                 AddIncludeFileChildren(pParChildren->Item(i), *includedTokens);
2863                 vpChildren.push_back(includedTokens);
2864                 numInclude++;
2865             }
2866             else if ((ichil == sizeChildren-1) && found_full_adress &&
2867                      pParChildren->Item(i)->m_TokenKind == tkVariable)
2868             {
2869                 //don't take locally declared variables
2870             }
2871             else if (pParChildren->Item(i)->m_TokenKind & tokenKindMask)
2872             {
2873                 if ((partialMatch && pParChildren->Item(i)->m_Name.StartsWith(searchLw)) ||
2874                     (!partialMatch && pParChildren->Item(i)->m_Name.IsSameAs(searchLw)))
2875                 {
2876                     AddUniqueResult(result, pParChildren->Item(i), true);
2877                 }
2878             }
2879 
2880             if (pParChildren->Item(i)->m_TokenKind == tkInterfaceExplicit ||
2881                      pParChildren->Item(i)->m_TokenKind == tkInterface)
2882             {
2883                 TokensArrayF* pEICh = &pParChildren->Item(i)->m_Children;
2884                 for (size_t ie=0; ie<pEICh->GetCount(); ie++)
2885                 {
2886                     if (pEICh->Item(ie)->m_TokenKind & tokenKindMask)
2887                     {
2888                         if ((partialMatch && pEICh->Item(ie)->m_Name.StartsWith(searchLw)) ||
2889                             (!partialMatch && pEICh->Item(ie)->m_Name.IsSameAs(searchLw)))
2890                         {
2891                             AddUniqueResult(result, pEICh->Item(ie), true);
2892                         }
2893                     }
2894                 }
2895             }
2896         }
2897     }
2898     if (numInclude > 0)
2899     {
2900         size_t origSize = vpChildren.size() - numInclude;
2901         for (size_t ichil=origSize; ichil<vpChildren.size(); ichil++)
2902         {
2903             delete vpChildren[ichil];
2904         }
2905     }
2906 
2907     m_RecursiveDeep = 0;
2908     m_UseRenameArrays = false;
2909     m_RenameDeep = 0;
2910     m_IncludeDeep = 0;
2911 
2912     for (size_t i=0; i<useTokens.Count(); i++)
2913     {
2914         ArrOfSizeT resChildrenIdx;
2915         BoolArray2D resCanBeSeen2D;
2916         TokensArrayFlatClass renTokCl;
2917         TokensArrayFlat* renamedTokens = renTokCl.GetTokens();
2918 
2919         FindUseAssociatedTokens2(useTokens.Item(i), searchLw, resChildrenIdx, resCanBeSeen2D, tokenKindMask, partialMatch,
2920                                   changeDisplayName, onlyPublicNames, *renamedTokens, useWithRenameTok);
2921 
2922         for (size_t ia=0; ia<resChildrenIdx.GetCount(); ia++)
2923         {
2924             TokensArrayFlat* pasTokens = m_PassedTokensVisited[resChildrenIdx.Item(ia)];
2925             BoolArray1D* canSee = resCanBeSeen2D[ia];
2926             for (size_t j=0; j<canSee->size(); j++)
2927             {
2928                 if ((*canSee)[j])
2929                 {
2930                     AddUniqueResult(result, pasTokens->Item(j));
2931                 }
2932             }
2933         }
2934         for (size_t ia=0; ia<renamedTokens->GetCount(); ia++)
2935         {
2936             AddUniqueResult(result, renamedTokens->Item(ia));
2937         }
2938         ClearBoolArray2D(resCanBeSeen2D);
2939     }
2940     m_VisitedModules.Clear();
2941     ClearPassedTokensArray2D(m_PassedTokensVisited);
2942     ClearArrOfSizeT2D(m_ChildrenIdxVisited);
2943     ClearBoolArray3D(m_CanBeSeenVisited);
2944 }
2945 
2946 //void ParserF::GetAddress(TokenF* token, wxArrayString& address)
2947 //{
2948 ////    if (token->m_TokenKind == tkFile)
2949 ////        address.Insert(token->m_Filename, 0);
2950 ////    else
2951 ////    {
2952 ////        address.Insert(token->m_Name,0);
2953 ////        GetAddress(token->m_pParent, address);
2954 ////    }
2955 //
2956 //    GetAddressOfToken(token, address);
2957 //}
2958 
FindAddress(cbEditor * ed,wxArrayString & address)2959 void ParserF::FindAddress(cbEditor* ed, wxArrayString& address)
2960 {
2961     // Address is: fileName, module_name, sub_name and etc.
2962     int lineStart;
2963     TokenFlat* tokFl=NULL;
2964     FindLineScopeLN(ed, lineStart, tokFl, -1);
2965     if (!tokFl)
2966     {
2967         address.Add(UnixFilename(ed->GetFilename()));
2968         return;
2969     }
2970 
2971     FindAddress(tokFl, address);
2972     if (tokFl)
2973         delete tokFl;
2974 }
2975 
FindAddress(TokenFlat * tokFl,wxArrayString & address)2976 void ParserF::FindAddress(TokenFlat* tokFl, wxArrayString& address)
2977 {
2978     if (!tokFl)
2979         return;
2980 
2981     // Address is: fileName, module_name, sub_name and etc.
2982     address.Add(tokFl->m_Filename);
2983     if (tokFl->m_TokenKind == tkModule || tokFl->m_TokenKind == tkSubmodule)
2984     {
2985         address.Add(tokFl->m_Name);
2986     }
2987     else if (!tokFl->m_ParentName.IsEmpty() && tokFl->m_ParentTokenKind == tkFile)
2988     {
2989         address.Add(tokFl->m_Name);
2990     }
2991     else if (!tokFl->m_ParentName.IsEmpty() && (tokFl->m_ParentTokenKind == tkModule || tokFl->m_ParentTokenKind == tkSubmodule))
2992     {
2993         address.Add(tokFl->m_ParentName);
2994         address.Add(tokFl->m_Name);
2995     }
2996     else if (!tokFl->m_ParentName.IsEmpty())
2997     {
2998         wxArrayString guess;
2999         TokensArrayF* fileChildren = FindFileTokens(tokFl->m_Filename);
3000         if (fileChildren)
3001         {
3002             TokenF* token = FindToken(*tokFl, fileChildren);
3003             guess.Clear();
3004             while (token)
3005             {
3006                 if (token->m_TokenKind != tkFile)
3007                     guess.Add(token->m_Name);
3008                 token = token->m_pParent;
3009             }
3010         }
3011 
3012         if (guess.Count() > 0)
3013         {
3014             for (int i=guess.GetCount()-1; i>=0; i--)
3015             {
3016                 address.Add(guess.Item(size_t(i)));
3017             }
3018         }
3019     }
3020     else // no parent name
3021     {
3022         bool found = false;
3023         wxArrayString guess;
3024         int lineDifStart = 0;
3025         bool foundGuess = false;
3026         wxString tokFlname = tokFl->m_Name;
3027         bool operIntf = tokFlname.StartsWith(_T("%%operator ("));
3028         if (operIntf)
3029             tokFlname = tokFlname.BeforeFirst('#').Trim();
3030         int tokenKindMask = tkFunction | tkProgram | tkSubroutine | tkModule | tkSubmodule |
3031                             tkInterfaceExplicit | tkProcedure;
3032         TokensArrayF* fileChildren = FindFileTokens(tokFl->m_Filename);
3033         if (fileChildren)
3034         {
3035             for (size_t i=0; i<fileChildren->GetCount(); i++)
3036             {
3037                 if (fileChildren->Item(i)->m_TokenKind == tokFl->m_TokenKind && fileChildren->Item(i)->m_Name.IsSameAs(tokFlname))
3038                 {
3039                     if (fileChildren->Item(i)->m_LineStart == tokFl->m_LineStart)
3040                     {
3041                         guess.Clear();
3042                         guess.Add(tokFlname);
3043                         found = true;
3044                         break;
3045                     }
3046                     else
3047                     {
3048                         int lds = abs(int(fileChildren->Item(i)->m_LineStart) - int(tokFl->m_LineStart));
3049                         if ((foundGuess && lineDifStart > lds) || !foundGuess)
3050                         {
3051                             guess.Clear();
3052                             guess.Add(tokFlname);
3053                             lineDifStart = lds;
3054                             foundGuess = true;
3055                         }
3056                     }
3057                 }
3058                 else if (fileChildren->Item(i)->m_TokenKind & tokenKindMask)
3059                 {
3060                     TokensArrayF* childL1 = &(fileChildren->Item(i)->m_Children);
3061                     for (size_t j=0; j<childL1->GetCount(); j++)
3062                     {
3063                         bool isInterfaceExp = childL1->Item(j)->m_TokenKind == tkInterfaceExplicit;
3064                         wxString childL1name;
3065                         if (operIntf && childL1->Item(j)->m_TokenKind == tkInterface &&
3066                             childL1->Item(j)->m_Name.StartsWith(_T("%%operator (")))
3067                         {
3068                             childL1name = childL1->Item(j)->m_Name.BeforeFirst('#').Trim();
3069                         }
3070                         else
3071                         {
3072                             childL1name = childL1->Item(j)->m_Name;
3073                         }
3074                         if (childL1->Item(j)->m_TokenKind == tokFl->m_TokenKind && childL1name.IsSameAs(tokFlname))
3075                         {
3076                             if (childL1->Item(j)->m_LineStart == tokFl->m_LineStart)
3077                             {
3078                                 guess.Clear();
3079                                 guess.Add(fileChildren->Item(i)->m_Name);
3080                                 guess.Add(tokFlname);
3081                                 found =  true;
3082                                 break;
3083                             }
3084                             else
3085                             {
3086                                 int lds = abs(int(childL1->Item(j)->m_LineStart) - int(tokFl->m_LineStart));
3087                                 if ((foundGuess && lineDifStart > lds) || !foundGuess)
3088                                 {
3089                                     guess.Clear();
3090                                     guess.Add(fileChildren->Item(i)->m_Name);
3091                                     guess.Add(tokFlname);
3092                                     lineDifStart = lds;
3093                                     foundGuess = true;
3094                                 }
3095                             }
3096                         }
3097                         else if (childL1->Item(j)->m_TokenKind & tokenKindMask)
3098                         {
3099                             TokensArrayF* childL2 = &(childL1->Item(j)->m_Children);
3100                             for (size_t k=0; k<childL2->Count(); k++)
3101                             {
3102                                 if (childL2->Item(k)->m_TokenKind == tokFl->m_TokenKind && childL2->Item(k)->m_Name.IsSameAs(tokFlname))
3103                                 {
3104                                     if (childL2->Item(k)->m_LineStart == tokFl->m_LineStart)
3105                                     {
3106                                         guess.Clear();
3107                                         guess.Add(fileChildren->Item(i)->m_Name);
3108                                         if (isInterfaceExp && childL1->Item(j)->m_Name.IsEmpty())
3109                                             guess.Add(_T("%%tkInterfaceExplicit"));
3110                                         else
3111                                             guess.Add(childL1->Item(j)->m_Name);
3112                                         guess.Add(tokFlname);
3113                                         found = true;
3114                                         break;
3115                                     }
3116                                     else
3117                                     {
3118                                         int lds = abs(int(childL2->Item(k)->m_LineStart) - int(tokFl->m_LineStart));
3119                                         if ((foundGuess && lineDifStart > lds) || !foundGuess)
3120                                         {
3121                                             guess.Clear();
3122                                             guess.Add(fileChildren->Item(i)->m_Name);
3123                                             guess.Add(childL1->Item(j)->m_Name);
3124                                             guess.Add(tokFlname);
3125                                             lineDifStart = lds;
3126                                             foundGuess = true;
3127                                         }
3128                                     }
3129                                 }
3130                             }
3131                             if (found)
3132                                 break;
3133                         }
3134                     }
3135                     if (found)
3136                         break;
3137                 }
3138             }
3139         }
3140         for (size_t i=0; i<guess.GetCount(); i++)
3141         {
3142             address.Add(guess.Item(i));
3143         }
3144     }
3145 }
3146 
FindTokensForUse(const wxString & search,wxArrayString & firstWords,TokensArrayFlat & result,bool onlyPublicNames)3147 void ParserF::FindTokensForUse(const wxString& search, wxArrayString& firstWords, TokensArrayFlat& result, bool onlyPublicNames)
3148 {
3149     int woCount = firstWords.GetCount();
3150     if (woCount < 2 || !firstWords.Item(woCount-1).IsSameAs(_T("use")))
3151         return;
3152 
3153     bool hasColon2 = false;
3154     int idx;
3155     bool firstC = false;
3156 
3157     for (size_t i=0; i<firstWords.GetCount()-1; i++)
3158     {
3159         if (firstWords.Item(i).IsSameAs(_T(":")))
3160         {
3161             if (firstC)
3162             {
3163                 hasColon2 = true;
3164                 idx = i - 2;
3165                 break;
3166             }
3167             else
3168             {
3169                 firstC = true;
3170             }
3171         }
3172         else if (firstC)
3173         {
3174             firstC = false;
3175         }
3176     }
3177 
3178     wxString modName;
3179     if (hasColon2 && idx >= 0)
3180     {
3181         modName = firstWords.Item(idx);
3182     }
3183     else if (!hasColon2)
3184     {
3185         modName = firstWords.Item(woCount-2);
3186     }
3187     else
3188     {
3189         return;
3190     }
3191 
3192     int tokenKindMask = tkSubroutine | tkFunction | tkInterface | tkOther | tkVariable | tkType;
3193     int noChildrenOf = tokenKindMask;
3194     TokensArrayFlat* useWithRenameTok = NULL;
3195     m_RecursiveDeep = 0;
3196     m_UseRenameArrays = false;
3197     m_RenameDeep = 0;
3198     m_IncludeDeep = 0;
3199 
3200     ArrOfSizeT* resChildrenIdx = NULL;
3201     BoolArray2D* resCanBeSeen2D = NULL;
3202     FindMatchTokensInModuleAndUse2(modName, search, resChildrenIdx, resCanBeSeen2D, tokenKindMask, noChildrenOf, true,
3203                                   onlyPublicNames, true, useWithRenameTok);
3204 
3205     if (resChildrenIdx && resCanBeSeen2D)
3206     {
3207         for (size_t ia=0; ia<resChildrenIdx->GetCount(); ia++)
3208         {
3209             TokensArrayFlat* pasTokens = m_PassedTokensVisited[resChildrenIdx->Item(ia)];
3210             BoolArray1D* canSee = (*resCanBeSeen2D)[ia];
3211             for (size_t j=0; j<canSee->size(); j++)
3212             {
3213                 if ((*canSee)[j])
3214                 {
3215                     AddUniqueResult(result, pasTokens->Item(j));
3216                 }
3217             }
3218         }
3219     }
3220 
3221     m_VisitedModules.Clear();
3222     ClearPassedTokensArray2D(m_PassedTokensVisited);
3223     ClearArrOfSizeT2D(m_ChildrenIdxVisited);
3224     ClearBoolArray3D(m_CanBeSeenVisited);
3225 }
3226 
3227 
AddUniqueResult(TokensArrayFlat & result,const TokenF * token,bool isHostAssociated)3228 void ParserF::AddUniqueResult(TokensArrayFlat& result, const TokenF* token, bool isHostAssociated)
3229 {
3230     bool have = false;
3231     for (size_t i=0; i<result.GetCount(); i++)
3232     {
3233         if (result.Item(i)->m_LineStart == token->m_LineStart &&
3234             result.Item(i)->m_DisplayName.IsSameAs(token->m_DisplayName) &&
3235             result.Item(i)->m_Filename.IsSameAs(token->m_Filename))
3236         {
3237             have = true;
3238             break;
3239         }
3240     }
3241     if (!have)
3242     {
3243         result.Add(new TokenFlat(token));
3244         result.Item(result.size()-1)->m_HostAssociated = isHostAssociated;
3245     }
3246 }
3247 
AddUniqueResult(TokensArrayFlat & result,const TokenFlat * token)3248 void ParserF::AddUniqueResult(TokensArrayFlat& result, const TokenFlat* token)
3249 {
3250     bool have = false;
3251     for (size_t i=0; i<result.GetCount(); i++)
3252     {
3253         if (result.Item(i)->m_LineStart == token->m_LineStart &&
3254             result.Item(i)->m_DisplayName.IsSameAs(token->m_DisplayName) &&
3255             result.Item(i)->m_Filename.IsSameAs(token->m_Filename))
3256         {
3257             have = true;
3258             break;
3259         }
3260     }
3261     if (!have)
3262         result.Add(new TokenFlat(token));
3263 }
3264 
3265 
FindUseAssociatedTokens2(TokenF * useToken,const wxString & searchLw,ArrOfSizeT & resChildrenIdx,BoolArray2D & resCanBeSeen2D,int tokenKindMask,bool partialMatch,bool changeDisplayName,bool onlyPublicNames,TokensArrayFlat & renamedTokens,TokensArrayFlat * useWithRenameTok)3266 void ParserF::FindUseAssociatedTokens2(TokenF* useToken, const wxString &searchLw, ArrOfSizeT &resChildrenIdx, BoolArray2D &resCanBeSeen2D, int tokenKindMask, bool partialMatch,
3267                                       bool changeDisplayName, bool onlyPublicNames, TokensArrayFlat &renamedTokens, TokensArrayFlat* useWithRenameTok)
3268 {
3269     if (m_RecursiveDeep > 20)
3270         return;  // deep limit was reached
3271 
3272     if (!useToken)
3273         return;
3274     if (useToken->m_TokenKind != tkUse)
3275         return;
3276 
3277     int noChildrenOf = tkInterface | tkFunction | tkSubroutine | tkType;
3278     UseTokenF* uTok = static_cast<UseTokenF*>(useToken);
3279 //    if (uTok->GetModuleNature() == mnIntrinsic)
3280 //        return;
3281 
3282     m_RecursiveDeep++;
3283 
3284     ArrOfSizeT* childrenIdx = NULL;
3285     BoolArray2D* canBeSeen2D = NULL;
3286     int midx;
3287     if (!m_UseRenameArrays)
3288         midx = m_VisitedModules.Index(useToken->m_Name);
3289     else
3290         midx = m_VisitedModulesRen.Index(useToken->m_Name);
3291     if (midx != wxNOT_FOUND)
3292     {
3293         if (!m_UseRenameArrays)
3294         {
3295             childrenIdx = m_ChildrenIdxVisited[midx];
3296             canBeSeen2D = m_CanBeSeenVisited[midx];
3297         }
3298         else
3299         {
3300             childrenIdx = m_ChildrenIdxVisitedRen[midx];
3301             canBeSeen2D = m_CanBeSeenVisitedRen[midx];
3302         }
3303     }
3304     else
3305     {
3306         FindMatchTokensInModuleAndUse2(uTok->m_Name, searchLw, childrenIdx, canBeSeen2D, tokenKindMask, noChildrenOf, partialMatch,
3307                                        onlyPublicNames, changeDisplayName, useWithRenameTok);
3308     }
3309     if (!childrenIdx || !canBeSeen2D)
3310     {
3311         m_RecursiveDeep--;
3312         return;
3313     }
3314 
3315     std::list<wxArrayString> *renameList = uTok->GetRenameList();
3316     std::set<wxString> *namesList = uTok->GetNamesList();
3317     if (uTok->HasOnly())
3318     {
3319         //with ONLY: keyword
3320         if (!namesList->empty())
3321         {
3322             // has names without rename
3323             for (size_t i=0; i<childrenIdx->GetCount(); i++)
3324             {
3325                 TokensArrayFlat* pT;
3326                 if (!m_UseRenameArrays)
3327                     pT = m_PassedTokensVisited[childrenIdx->Item(i)];
3328                 else
3329                     pT = m_PassedTokensVisitedRen[childrenIdx->Item(i)];
3330                 BoolArray1D* canSee = (*canBeSeen2D)[i];
3331                 bool has = false;
3332                 BoolArray1D* canSeeTmp = NULL;
3333                 for (size_t j=0; j<pT->GetCount(); j++)
3334                 {
3335                     //if ((*canSee)[j] && namesList->count(pT->Item(j)->m_Name) > 0)
3336                     if ((*canSee)[j] &&
3337                         ((pT->Item(j)->m_Rename.IsEmpty() && namesList->count(pT->Item(j)->m_Name) > 0) ||
3338                          (!pT->Item(j)->m_Rename.IsEmpty() && namesList->count(pT->Item(j)->m_Rename.Lower()) > 0)))
3339                     {
3340                         if (!has)
3341                         {
3342                             canSeeTmp = new BoolArray1D(canSee->size(),false);
3343                             has = true;
3344                         }
3345                         (*canSeeTmp)[j] = true;
3346                     }
3347                 }
3348                 if (has)
3349                 {
3350                     resChildrenIdx.Add(childrenIdx->Item(i));
3351                     resCanBeSeen2D.push_back(canSeeTmp);
3352                 }
3353             }
3354         }
3355 
3356         for(std::list<wxArrayString>::iterator pos=renameList->begin(); pos != renameList->end(); ++pos)
3357         {
3358             // through rename
3359             // pos->Item(0) -local name
3360             // pos->Item(1) -external name
3361             wxString locNamLw = pos->Item(0).Lower();
3362             if ( (partialMatch && locNamLw.StartsWith(searchLw)) ||
3363                  (!partialMatch && locNamLw.IsSameAs(searchLw)) )
3364             {
3365                 wxString impNamLw = pos->Item(1).Lower();
3366 
3367                 if ( (partialMatch && impNamLw.StartsWith(searchLw)) ||
3368                  (!partialMatch && impNamLw.IsSameAs(searchLw)) )
3369                 {
3370                     for (size_t i=0; i<childrenIdx->GetCount(); i++)
3371                     {
3372                         TokensArrayFlat* pT;
3373                         if (!m_UseRenameArrays)
3374                             pT = m_PassedTokensVisited[childrenIdx->Item(i)];
3375                         else
3376                             pT = m_PassedTokensVisitedRen[childrenIdx->Item(i)];
3377                         BoolArray1D* canSee = (*canBeSeen2D)[i];
3378                         for (size_t j=0; j<pT->GetCount(); j++)
3379                         {
3380                             if ((*canSee)[j] && pT->Item(j)->m_Name.IsSameAs(impNamLw))
3381                             {
3382                                 TokenFlat* tf = new TokenFlat(pT->Item(j));
3383                                 if (changeDisplayName)
3384                                 {
3385                                     tf->Rename(pos->Item(0));
3386                                 }
3387                                 tf->m_Rename << pos->Item(0);
3388                                 renamedTokens.Add(tf);
3389 
3390                                 if (useWithRenameTok)
3391                                 {
3392                                     TokenFlat* tfu = new TokenFlat(useToken);
3393                                     tfu->m_Rename = pos->Item(0) + _T(" => ") + pos->Item(1);
3394                                     useWithRenameTok->Add(tfu);
3395                                 }
3396                             }
3397                         }
3398                     }
3399                 }
3400                 else if (m_RenameDeep == 0)
3401                 {
3402                     ArrOfSizeT* renChIdx = NULL;
3403                     BoolArray2D* renCBS2D = NULL;
3404                     m_UseRenameArrays = true;
3405                     m_RenameDeep++;
3406                     FindMatchTokensInModuleAndUse2(uTok->m_Name, impNamLw, renChIdx, renCBS2D, tokenKindMask, noChildrenOf, false,
3407                                                   onlyPublicNames, changeDisplayName, useWithRenameTok);
3408                     m_UseRenameArrays = false;
3409                     m_RenameDeep--;
3410                     if (renChIdx && renCBS2D)
3411                     {
3412                         bool have = false;
3413                         for (size_t ia=0; ia<renChIdx->GetCount(); ia++)
3414                         {
3415                             TokensArrayFlat* pasTokens = m_PassedTokensVisitedRen[renChIdx->Item(ia)];
3416                             BoolArray1D* canSee = (*renCBS2D)[ia];
3417                             for (size_t j=0; j<canSee->size(); j++)
3418                             {
3419                                 if ((*canSee)[j])
3420                                 {
3421                                     TokenFlat* tf = new TokenFlat(pasTokens->Item(j));
3422                                     if (changeDisplayName)
3423                                     {
3424                                         tf->Rename(pos->Item(0));
3425                                     }
3426                                     tf->m_Rename << pos->Item(0);
3427                                     renamedTokens.Add(tf);
3428                                     if (!have)
3429                                         have = true;
3430                                 }
3431                             }
3432                         }
3433                         if (have && useWithRenameTok)
3434                         {
3435                             TokenFlat* tfu = new TokenFlat(useToken);
3436                             tfu->m_Rename = pos->Item(0) + _T(" => ") + pos->Item(1);
3437                             useWithRenameTok->Add(tfu);
3438                         }
3439                     }
3440                     if (m_RenameDeep == 0)
3441                     {
3442                         m_VisitedModulesRen.Clear();
3443                         ClearPassedTokensArray2D(m_PassedTokensVisitedRen);
3444                         ClearArrOfSizeT2D(m_ChildrenIdxVisitedRen);
3445                         ClearBoolArray3D(m_CanBeSeenVisitedRen);
3446                     }
3447                 }
3448             }
3449         }
3450     }
3451     else if (!renameList->empty())
3452     {
3453         //no ONLY keyword. Has rename list.
3454         size_t oldCount = resChildrenIdx.GetCount();
3455         for (size_t i=0; i<childrenIdx->GetCount(); i++)
3456         {
3457             resChildrenIdx.Add(childrenIdx->Item(i));
3458             BoolArray1D* canSee = (*canBeSeen2D)[i];
3459             BoolArray1D* canSeeTmp = new BoolArray1D(*canSee);
3460             resCanBeSeen2D.push_back(canSeeTmp);
3461         }
3462 
3463         for (std::list<wxArrayString>::iterator pos=renameList->begin(); pos != renameList->end(); ++pos)
3464         {
3465             if (pos->Item(0).IsEmpty() || pos->Item(1).IsEmpty())
3466                 continue; //some mistake
3467 
3468             wxString locNamLw = pos->Item(0).Lower();
3469             if ( (partialMatch && locNamLw.StartsWith(searchLw)) ||
3470                  (!partialMatch && locNamLw.IsSameAs(searchLw)) )
3471             {
3472                 wxString impNamLw = pos->Item(1).Lower();
3473 
3474                 if ( (partialMatch && impNamLw.StartsWith(searchLw)) ||
3475                  (!partialMatch && impNamLw.IsSameAs(searchLw)) )
3476                 {
3477                     for (size_t i=oldCount; i<resChildrenIdx.GetCount(); i++)
3478                     {
3479                         TokensArrayFlat* pT;
3480                         if (!m_UseRenameArrays)
3481                             pT = m_PassedTokensVisited[resChildrenIdx.Item(i)];
3482                         else
3483                             pT = m_PassedTokensVisitedRen[resChildrenIdx.Item(i)];
3484                         BoolArray1D* canSeeTmp = resCanBeSeen2D[i];
3485                         for (size_t j=0; j<pT->GetCount(); j++)
3486                         {
3487                             if ((*canSeeTmp)[j] && pT->Item(j)->m_Name.IsSameAs(impNamLw))
3488                             {
3489                                 TokenFlat* tf = new TokenFlat(pT->Item(j));
3490                                 if (changeDisplayName)
3491                                 {
3492                                     tf->Rename(pos->Item(0));
3493                                 }
3494                                 tf->m_Rename << pos->Item(0);
3495                                 renamedTokens.Add(tf);
3496 
3497                                 if (useWithRenameTok)
3498                                 {
3499                                     TokenFlat* tfu = new TokenFlat(useToken);
3500                                     tfu->m_Rename = pos->Item(0) + _T(" => ") + pos->Item(1);
3501                                     useWithRenameTok->Add(tfu);
3502                                 }
3503                                 (*canSeeTmp)[j] = false;
3504                             }
3505                         }
3506                     }
3507                 }
3508                 else if (m_RenameDeep == 0)
3509                 {
3510                     ArrOfSizeT* renChIdx = NULL;
3511                     BoolArray2D* renCBS2D = NULL;
3512                     m_UseRenameArrays = true;
3513                     FindMatchTokensInModuleAndUse2(uTok->m_Name, impNamLw, renChIdx, renCBS2D, tokenKindMask, noChildrenOf, false,
3514                                                   onlyPublicNames, changeDisplayName, useWithRenameTok);
3515                     m_UseRenameArrays = false;
3516                     if (renChIdx && renCBS2D)
3517                     {
3518                         bool have = false;
3519                         for (size_t ia=0; ia<renChIdx->GetCount(); ia++)
3520                         {
3521                             TokensArrayFlat* pasTokens = m_PassedTokensVisitedRen[renChIdx->Item(ia)];
3522                             BoolArray1D* canSee = (*renCBS2D)[ia];
3523                             for (size_t j=0; j<canSee->size(); j++)
3524                             {
3525                                 if ((*canSee)[j])
3526                                 {
3527                                     TokenFlat* tf = new TokenFlat(pasTokens->Item(j));
3528                                     if (changeDisplayName)
3529                                     {
3530                                         tf->Rename(pos->Item(0));
3531                                     }
3532                                     tf->m_Rename << pos->Item(0);
3533                                     renamedTokens.Add(tf);
3534                                     if (!have)
3535                                         have = true;
3536                                 }
3537                             }
3538                         }
3539                         if (have && useWithRenameTok)
3540                         {
3541                             TokenFlat* tfu = new TokenFlat(useToken);
3542                             tfu->m_Rename = pos->Item(0) + _T(" => ") + pos->Item(1);
3543                             useWithRenameTok->Add(tfu);
3544                         }
3545                     }
3546                     if (m_RenameDeep == 0)
3547                     {
3548                         m_VisitedModulesRen.Clear();
3549                         ClearPassedTokensArray2D(m_PassedTokensVisitedRen);
3550                         ClearArrOfSizeT2D(m_ChildrenIdxVisitedRen);
3551                         ClearBoolArray3D(m_CanBeSeenVisitedRen);
3552                     }
3553                 }
3554             }
3555             else
3556             {
3557                 wxString impNamLw = pos->Item(1).Lower();
3558                 if ( (partialMatch && impNamLw.StartsWith(searchLw)) ||
3559                      (!partialMatch && impNamLw.IsSameAs(searchLw)) )
3560                 {
3561                     for (size_t i=oldCount; i<resChildrenIdx.GetCount(); i++)
3562                     {
3563                         TokensArrayFlat* pT;
3564                         if (!m_UseRenameArrays)
3565                             pT = m_PassedTokensVisited[resChildrenIdx.Item(i)];
3566                         else
3567                             pT = m_PassedTokensVisitedRen[resChildrenIdx.Item(i)];
3568                         BoolArray1D* canSeeTmp = resCanBeSeen2D[i];
3569                         for (size_t j=0; j<pT->GetCount(); j++)
3570                         {
3571                             if ((*canSeeTmp)[j] && pT->Item(j)->m_Name.IsSameAs(impNamLw))
3572                             {
3573                                 (*canSeeTmp)[j] = false;
3574                             }
3575                         }
3576                     }
3577                 }
3578             }
3579         }
3580 
3581     }
3582     else // no ONLY or rename list
3583     {
3584         for (size_t i=0; i<childrenIdx->GetCount(); i++)
3585         {
3586             resChildrenIdx.Add(childrenIdx->Item(i));
3587             BoolArray1D* canSee = (*canBeSeen2D)[i];
3588             BoolArray1D* canSeeTmp = new BoolArray1D(*canSee);
3589             resCanBeSeen2D.push_back(canSeeTmp);
3590         }
3591     }
3592     m_RecursiveDeep--;
3593 }
3594 
3595 
FindMatchTokensInModuleAndUse2(const wxString & modName,const wxString & searchLw,ArrOfSizeT * & childrenIdx,BoolArray2D * & canBeSeen2D,int tokenKindMask,int noChildrenOf,bool partialMatch,bool onlyPublicNames,bool changeDisplayName,TokensArrayFlat * useWithRenameTok)3596 void ParserF::FindMatchTokensInModuleAndUse2(const wxString& modName, const wxString& searchLw, ArrOfSizeT* &childrenIdx, BoolArray2D* &canBeSeen2D, int tokenKindMask,
3597                                              int noChildrenOf, bool partialMatch, bool onlyPublicNames, bool changeDisplayName, TokensArrayFlat* useWithRenameTok)
3598 {
3599     TokenF* modTok = FindModuleSubmoduleToken(modName);
3600 
3601     if (!modTok || modTok->m_TokenKind != tkModule)
3602         return;
3603     ModuleTokenF* mToken = static_cast<ModuleTokenF*>(modTok);
3604     TokensArrayF* children = &modTok->m_Children;
3605     if (!children)
3606         return;
3607 
3608     TokensArrayF useTokens;
3609 
3610     std::vector<TokensArrayF*> vpChildren;
3611     vpChildren.push_back(children);
3612     int numInclude = 0;
3613     for (size_t ichil=0; ichil<vpChildren.size(); ++ichil)
3614     {
3615         TokensArrayF* pParChildren = vpChildren[ichil];
3616         size_t npch = pParChildren->GetCount();
3617 
3618         for (size_t i=0; i<npch; ++i)
3619         {
3620             TokenF* chtok = pParChildren->Item(i);
3621             if (chtok->m_TokenKind == tkUse)
3622             {
3623                 useTokens.Add(chtok);
3624             }
3625             else if (chtok->m_TokenKind == tkInclude)
3626             {
3627                 TokensArrayF* includedTokens = new TokensArrayF();
3628                 AddIncludeFileChildren(chtok, *includedTokens);
3629                 vpChildren.push_back(includedTokens);
3630                 numInclude++;
3631             }
3632             else if (chtok->m_TokenKind == tkSubroutine || chtok->m_TokenKind == tkFunction)
3633             {
3634                 break; // 'use' statments must be located above procedures
3635             }
3636         }
3637     }
3638     if (numInclude > 0)
3639     {
3640         size_t origSize = vpChildren.size() - numInclude;
3641         for (size_t ichil=origSize; ichil<vpChildren.size(); ichil++)
3642         {
3643             delete vpChildren[ichil];
3644         }
3645     }
3646 
3647     childrenIdx = new ArrOfSizeT; // indexes of associated modules and this module
3648     canBeSeen2D = new BoolArray2D;
3649 
3650     TokensArrayFlat* passedTokens = new TokensArrayFlat;
3651     FindMatchChildrenDeclared(*children, searchLw, *passedTokens, tokenKindMask, partialMatch, noChildrenOf, onlyPublicNames);
3652 
3653     BoolArray1D* canSeeLocal = new BoolArray1D;
3654 
3655     if (onlyPublicNames)
3656     {
3657         wxString nameT;
3658         for (size_t i=0; i<useTokens.Count(); i++)
3659         {
3660             ArrOfSizeT childrenIdxTmp;
3661             BoolArray2D canBeSeen2DTmp;
3662             TokensArrayFlat renamedTokensTmp;
3663             FindUseAssociatedTokens2(useTokens.Item(i), searchLw, childrenIdxTmp, canBeSeen2DTmp, tokenKindMask, partialMatch,
3664                                       changeDisplayName, onlyPublicNames, renamedTokensTmp, useWithRenameTok);
3665             bool defPub = (useTokens.Item(i)->m_TokenAccess == taPublic);
3666             size_t nChIdx = childrenIdxTmp.GetCount();
3667             for (size_t j=0; j<nChIdx; ++j)
3668             {
3669                 size_t chIdx = childrenIdxTmp.Item(j);
3670                 TokensArrayFlat* passTokTmp;
3671                 if (!m_UseRenameArrays)
3672                     passTokTmp = m_PassedTokensVisited[chIdx];
3673                 else
3674                     passTokTmp = m_PassedTokensVisitedRen[chIdx];
3675                 BoolArray1D* canSeeTmp = canBeSeen2DTmp[j];
3676                 int ind = childrenIdx->Index(chIdx);
3677 
3678                 if (ind == wxNOT_FOUND)
3679                 {
3680                     bool hasPub = false;
3681                     size_t cSs = canSeeTmp->size();
3682                     for (size_t k=0; k<cSs; k++)
3683                     {
3684                         if ((*canSeeTmp)[k])
3685                         {
3686                             TokenFlat* passTokIt = passTokTmp->Item(k);
3687                             if (!changeDisplayName)
3688                             {
3689                                 if (passTokIt->m_Rename.IsEmpty())
3690                                     nameT = passTokIt->m_Name;
3691                                 else
3692                                     nameT = passTokIt->m_Rename.Lower();
3693                             }
3694 
3695                             if ( (changeDisplayName && ((defPub && !mToken->HasNameInPrivateList(passTokIt->m_Name)) ||
3696                                                         (!defPub && mToken->HasNameInPublicList(passTokIt->m_Name)))) ||
3697                                  (!changeDisplayName && ((defPub && !mToken->HasNameInPrivateList(nameT)) ||
3698                                                         (!defPub && mToken->HasNameInPublicList(nameT)))) )
3699                             {
3700                                 hasPub = true;
3701                             }
3702                             else
3703                             {
3704                                 (*canSeeTmp)[k] = false;
3705                             }
3706                         }
3707                     }
3708                     if (hasPub)
3709                     {
3710                         childrenIdx->Add(chIdx);
3711                         canBeSeen2D->push_back(canSeeTmp);
3712                     }
3713                 }
3714                 else
3715                 {
3716                     BoolArray1D* canSee = (*canBeSeen2D)[ind];
3717                     for (size_t k=0; k<canSeeTmp->size(); k++)
3718                     {
3719                         if (!(*canSee)[k] && (*canSeeTmp)[k])
3720                         {
3721                             TokenFlat* passTokIt = passTokTmp->Item(k);
3722                             if (!changeDisplayName)
3723                             {
3724                                 if (passTokIt->m_Rename.IsEmpty())
3725                                     nameT = passTokIt->m_Name;
3726                                 else
3727                                     nameT = passTokIt->m_Rename.Lower();
3728                             }
3729                             if ( (changeDisplayName && ((defPub && !mToken->HasNameInPrivateList(passTokIt->m_Name)) ||
3730                                                         (!defPub && mToken->HasNameInPublicList(passTokIt->m_Name)))) ||
3731                                  (!changeDisplayName && ((defPub && !mToken->HasNameInPrivateList(nameT)) ||
3732                                                         (!defPub && mToken->HasNameInPublicList(nameT)))) )
3733                             {
3734                                 (*canSee)[k] = true;
3735                             }
3736                             else
3737                             {
3738                                 //canSee->Item(k) = false;
3739                             }
3740                         }
3741                     }
3742                     delete canSeeTmp;
3743                 }
3744             }
3745 
3746             for (size_t j=0; j<renamedTokensTmp.GetCount(); j++)
3747             {
3748                 if (!changeDisplayName)
3749                 {
3750                     if (renamedTokensTmp.Item(j)->m_Rename.IsEmpty())
3751                         nameT = renamedTokensTmp.Item(j)->m_Name;
3752                     else
3753                         nameT = renamedTokensTmp.Item(j)->m_Rename.Lower();
3754                 }
3755 
3756                 if ( (changeDisplayName && ((defPub && !mToken->HasNameInPrivateList(renamedTokensTmp.Item(j)->m_Name)) ||
3757                                             (!defPub && mToken->HasNameInPublicList(renamedTokensTmp.Item(j)->m_Name)))) ||
3758                      (!changeDisplayName && ((defPub && !mToken->HasNameInPrivateList(nameT)) ||
3759                                             (!defPub && mToken->HasNameInPublicList(nameT)))) )
3760                 {
3761                     passedTokens->Add(renamedTokensTmp.Item(j));
3762                 }
3763                 else
3764                 {
3765                     renamedTokensTmp.Item(j)->Clear();
3766                     delete renamedTokensTmp.Item(j);
3767                 }
3768             }
3769         }
3770     }
3771     else // !onlyPublicNames
3772     {
3773         for (size_t i=0; i<useTokens.Count(); i++)
3774         {
3775             ArrOfSizeT childrenIdxTmp;
3776             BoolArray2D canBeSeen2DTmp;
3777             TokensArrayFlat renamedTokensTmp;
3778             FindUseAssociatedTokens2(useTokens.Item(i), searchLw, childrenIdxTmp, canBeSeen2DTmp, tokenKindMask, partialMatch,
3779                                       changeDisplayName, onlyPublicNames, renamedTokensTmp, useWithRenameTok);
3780 
3781             for (size_t j=0; j<childrenIdxTmp.GetCount(); j++)
3782             {
3783                 BoolArray1D* canSeeTmp = canBeSeen2DTmp[j];
3784                 int ind = childrenIdx->Index(childrenIdxTmp.Item(j));
3785                 if (ind == wxNOT_FOUND)
3786                 {
3787                     childrenIdx->Add(childrenIdxTmp.Item(j));
3788                     canBeSeen2D->push_back(canSeeTmp);
3789                 }
3790                 else
3791                 {
3792                     BoolArray1D* canSee = (*canBeSeen2D)[ind];
3793                     for (size_t k=0; k<canSeeTmp->size(); k++)
3794                     {
3795                         if (!(*canSee)[k] && (*canSeeTmp)[k])
3796                             (*canSee)[k] = true;
3797                     }
3798                     delete canSeeTmp;
3799                 }
3800             }
3801 
3802             for (size_t j=0; j<renamedTokensTmp.GetCount(); j++)
3803             {
3804                 passedTokens->Add(renamedTokensTmp.Item(j));
3805             }
3806         }
3807     }
3808 
3809     canSeeLocal->resize(passedTokens->GetCount(),true);
3810     canBeSeen2D->push_back(canSeeLocal);
3811     if (!m_UseRenameArrays)
3812     {
3813         m_CanBeSeenVisited.push_back(canBeSeen2D);
3814         m_VisitedModules.Add(modName);
3815         m_PassedTokensVisited.push_back(passedTokens);
3816         childrenIdx->Add(m_VisitedModules.GetCount()-1);
3817         m_ChildrenIdxVisited.push_back(childrenIdx);
3818     }
3819     else
3820     {
3821         m_CanBeSeenVisitedRen.push_back(canBeSeen2D);
3822         m_VisitedModulesRen.Add(modName);
3823         m_PassedTokensVisitedRen.push_back(passedTokens);
3824         childrenIdx->Add(m_VisitedModulesRen.GetCount()-1);
3825         m_ChildrenIdxVisitedRen.push_back(childrenIdx);
3826     }
3827 }
3828 
3829 
ChangeAssociatedName(wxString & line,TokenFlat * token)3830 void ParserF::ChangeAssociatedName(wxString& line, TokenFlat* token)
3831 {
3832     if (!token)
3833         return;
3834     if ((token->m_TokenKind != tkAssociateConstruct) && (token->m_TokenKind != tkSelectTypeDefault))
3835         return;
3836 
3837     wxString args = token->m_Args.Lower();
3838     std::map<wxString,wxString> assocMap;
3839     ParserThreadF::SplitAssociateConstruct(args, assocMap);
3840 
3841     //change names in the line
3842     wxString lineLw = line.Lower();
3843     line.Empty();
3844     const wxString delim = _T(" ()[]{}&;,*./+-><=%\t\r\n");
3845     size_t idx1 = 0;
3846     wxString block;
3847     bool wasDeli = false;
3848     for(size_t i=0; i<lineLw.Len(); i++)
3849     {
3850         if (!wasDeli && delim.Find(lineLw.GetChar(i)) != wxNOT_FOUND)
3851         {
3852             block = lineLw.Mid(idx1,i-idx1);
3853             wasDeli = true;
3854             idx1 = i;
3855             std::map<wxString,wxString>::iterator it = assocMap.find(block);
3856             if (it != assocMap.end())
3857                 line << it->second;
3858             else
3859                 line << block;
3860         }
3861         else if (wasDeli && delim.Find(lineLw.GetChar(i)) == wxNOT_FOUND)
3862         {
3863             line << lineLw.Mid(idx1,i-idx1);
3864             wasDeli = false;
3865             idx1 = i;
3866         }
3867     }
3868     line << lineLw.Mid(idx1);
3869 }
3870 
3871 
AddIncludeFileChildren(const TokenF * include,TokensArrayF & tokens)3872 void ParserF::AddIncludeFileChildren(const TokenF* include, TokensArrayF& tokens)
3873 {
3874     if (include->m_TokenKind != tkInclude)
3875         return;
3876 
3877     bool withExt = (include->m_Name.Find('.',true) != wxNOT_FOUND);
3878     #ifdef __WXMSW__
3879         wxString iname = include->m_Name;
3880     #else
3881         wxString iname = include->m_DisplayName;
3882     #endif
3883 
3884     for (size_t i=0; i<m_pTokens->GetCount(); i++)
3885     {
3886         if (m_pTokens->Item(i)->m_TokenKind != tkFile)
3887             continue;
3888 
3889         #ifdef __WXMSW__
3890             wxString ffname = m_pTokens->Item(i)->m_Filename.AfterLast('\\');
3891             ffname.MakeLower();
3892         #else
3893             wxString ffname = m_pTokens->Item(i)->m_Filename.AfterLast('/');
3894         #endif
3895 
3896         if ( (withExt && ffname.IsSameAs(iname)) ||
3897              (!withExt && ffname.BeforeFirst('.').IsSameAs(iname)) )
3898         {
3899             tokens.Alloc(tokens.GetCount() + m_pTokens->Item(i)->m_Children.GetCount());
3900             for (size_t j=0; j<m_pTokens->Item(i)->m_Children.GetCount(); j++)
3901             {
3902                 tokens.Add(m_pTokens->Item(i)->m_Children.Item(j));
3903             }
3904             break;
3905         }
3906     }
3907 }
3908 
IsIncludeFile(wxString fileName)3909 bool ParserF::IsIncludeFile(wxString fileName)
3910 {
3911     bool isInclude = false;
3912     wxChar sep = wxFileName::GetPathSeparator();
3913     if (m_pIncludeDB->IsIncludeFile(fileName.AfterLast(sep)))
3914         isInclude = true;
3915     return isInclude;
3916 }
3917 
HasIncludeFiles()3918 bool ParserF::HasIncludeFiles()
3919 {
3920     return !m_pIncludeDB->IsEmpty();
3921 }
3922 
GetSubmoduleHostTokens(TokenF * subModToken,std::vector<TokensArrayF * > & vpChildren)3923 void ParserF::GetSubmoduleHostTokens(TokenF* subModToken, std::vector<TokensArrayF*> &vpChildren)
3924 {
3925     m_SubmodDeep++;
3926     if (!subModToken || subModToken->m_TokenKind != tkSubmodule)
3927         return;
3928     if (m_SubmodDeep > 10)  // the limit of recursive call. Should be more than enough.
3929         return;
3930 
3931     SubmoduleTokenF* submod = static_cast<SubmoduleTokenF*>(subModToken);
3932     wxString parentName = submod->m_AncestorModuleName;
3933     if (!submod->m_ParentSubmoduleName.IsEmpty())
3934         parentName << _T(":") << submod->m_ParentSubmoduleName;
3935 
3936     TokenF* modTok = FindModuleSubmoduleToken(parentName);
3937     if (!modTok)
3938         return;
3939 
3940     if (modTok->m_Children.Count() > 0)
3941         vpChildren.push_back(&modTok->m_Children);
3942 
3943     if (modTok->m_TokenKind == tkSubmodule)
3944         GetSubmoduleHostTokens(modTok, vpChildren);
3945 }
3946 
SetNewTokens(TokensArrayF * pTokens)3947 void ParserF::SetNewTokens(TokensArrayF* pTokens)
3948 {
3949     if (m_pTokensNew)
3950     {
3951         ClearTokens(m_pTokensNew);
3952         delete m_pTokensNew;
3953     }
3954     m_pTokensNew = pTokens;
3955 }
3956 
SetNewIncludeDB(IncludeDB * pIncludeDB)3957 void ParserF::SetNewIncludeDB(IncludeDB* pIncludeDB)
3958 {
3959     if (m_pIncludeDBNew)
3960     {
3961         m_pIncludeDBNew->Clear();
3962         delete m_pIncludeDBNew;
3963     }
3964     m_pIncludeDBNew = pIncludeDB;
3965 }
3966 
SetNewADirTokens(TokensArrayF * pTokens)3967 void ParserF::SetNewADirTokens(TokensArrayF* pTokens)
3968 {
3969     if (m_pTokensADirNew)
3970     {
3971         ClearTokens(m_pTokensADirNew);
3972         delete m_pTokensADirNew;
3973     }
3974     m_pTokensADirNew = pTokens;
3975 }
3976 
SetNewADirIncludeDB(IncludeDB * pIncludeDB)3977 void ParserF::SetNewADirIncludeDB(IncludeDB* pIncludeDB)
3978 {
3979     if (m_pIncludeDBADirNew)
3980     {
3981         m_pIncludeDBADirNew->Clear();
3982         delete m_pIncludeDBADirNew;
3983     }
3984     m_pIncludeDBADirNew = pIncludeDB;
3985 }
3986 
ClearTokens(TokensArrayF * pTokens)3987 void ParserF::ClearTokens(TokensArrayF* pTokens)
3988 {
3989     if (!pTokens)
3990         return;
3991 
3992     for (size_t i=0; i<pTokens->GetCount(); i++)
3993     {
3994         pTokens->Item(i)->Clear();
3995         delete pTokens->Item(i);
3996     }
3997     pTokens->Clear();
3998 }
3999 
ConnectToNewTokens()4000 void ParserF::ConnectToNewTokens()
4001 {
4002     wxCriticalSectionLocker cslocker(s_CritSect);
4003     wxMutexLocker mlocker(s_NewTokensMutex);
4004     if (m_pBufferTokens)
4005     {
4006         ClearTokens(m_pBufferTokens);
4007     }
4008     if (m_pTokens)
4009     {
4010         ClearTokens(m_pTokens);
4011         delete m_pTokens;
4012     }
4013     m_pTokens = m_pTokensNew;
4014     m_pTokensNew = NULL;
4015     if (m_pIncludeDB)
4016     {
4017         m_pIncludeDB->Clear();
4018         delete m_pIncludeDB;
4019     }
4020     m_pIncludeDB = m_pIncludeDBNew;
4021     m_pIncludeDBNew = NULL;
4022 }
4023 
ConnectToNewADirTokens()4024 void ParserF::ConnectToNewADirTokens()
4025 {
4026     wxCriticalSectionLocker cslocker(s_CritSect);
4027     wxMutexLocker mlocker(s_AdditionalDirNewTokensMutex);
4028     if (m_pAdditionalDirTokens)
4029     {
4030         ClearTokens(m_pAdditionalDirTokens);
4031         delete m_pAdditionalDirTokens;
4032     }
4033     m_pAdditionalDirTokens = m_pTokensADirNew;
4034     m_pTokensADirNew = NULL;
4035 
4036     if (m_pIncludeDBADir)
4037     {
4038         m_pIncludeDBADir->Clear();
4039         delete m_pIncludeDBADir;
4040     }
4041     m_pIncludeDBADir = m_pIncludeDBADirNew;
4042     m_pIncludeDBADirNew = NULL;
4043 }
4044 
SetNewCurrentTokens(TokensArrayF * pTokens)4045 void ParserF::SetNewCurrentTokens(TokensArrayF* pTokens)
4046 {
4047     // function called from secondary thread (bufferparserthread)
4048     wxCriticalSectionLocker locker(s_CurrentBTokensCritSect);
4049     if (m_pCurrentBufferTokensNew)
4050     {
4051         ClearTokens(m_pCurrentBufferTokensNew);
4052         delete m_pCurrentBufferTokensNew;
4053     }
4054     m_pCurrentBufferTokensNew = pTokens;
4055 }
4056 
ConnectToNewCurrentTokens()4057 void ParserF::ConnectToNewCurrentTokens()
4058 {
4059     wxCriticalSectionLocker locker(s_CurrentBTokensCritSect);
4060     if (m_pBufferTokens && m_pCurrentBufferTokensNew && m_pCurrentBufferTokensNew->size() > 0)
4061     {
4062         for (size_t i=0; i<m_pBufferTokens->size(); i++)
4063         {
4064             if (m_pBufferTokens->Item(i)->m_Filename.IsSameAs(m_pCurrentBufferTokensNew->Item(0)->m_Filename))
4065             {
4066                 m_pBufferTokens->Item(i)->Clear();
4067                 delete m_pBufferTokens->Item(i);
4068                 m_pBufferTokens->RemoveAt(i);
4069                 break;
4070             }
4071         }
4072         m_pBufferTokens->Add(m_pCurrentBufferTokensNew->Item(0));
4073     }
4074     if (m_pCurrentBufferTokensNew)
4075         delete m_pCurrentBufferTokensNew;
4076     m_pCurrentBufferTokensNew = NULL;
4077 }
4078 
ParseIntrinsicModules()4079 void ParserF::ParseIntrinsicModules()
4080 {
4081     if (!m_pIntrinsicModuleTokens)
4082         return;
4083     int dispCase = 0;
4084     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
4085     if (cfg)
4086         dispCase = cfg->ReadInt(_T("/keywords_case"), 0);
4087 
4088     wxString filename = ConfigManager::GetDataFolder() + _T("/images/fortranproject/fortran_intrinsic_modules.f90");
4089     if (!wxFileExists(filename))
4090     {
4091         Manager::Get()->GetLogManager()->Log(_T("FortranProject plugin error: file ")+filename+_T(" was not found."));
4092         return;
4093     }
4094     wxString fn = UnixFilename(filename);
4095     ParserThreadF* thread = new ParserThreadF(fn, fn, m_pIntrinsicModuleTokens, fsfFree);
4096     thread->Parse();
4097     delete thread;
4098 
4099     ChangeCaseChildren(m_pIntrinsicModuleTokens->Item(0)->m_Children, dispCase);
4100 }
4101 
ChangeCaseChildren(TokensArrayF & children,int dispCase)4102 void ParserF::ChangeCaseChildren(TokensArrayF &children, int dispCase)
4103 {
4104     for (size_t i=0; i<children.GetCount(); i++)
4105     {
4106         wxString* dn = &children.Item(i)->m_DisplayName;
4107         switch (dispCase)
4108         {
4109             case 0:
4110             {
4111                 break;
4112             }
4113             case 1:
4114             {
4115                 *dn = dn->MakeUpper();
4116                 break;
4117             }
4118             case 2:
4119             {
4120                 *dn = dn->Mid(0,1).MakeUpper() + dn->Mid(1).MakeLower();
4121                 break;
4122             }
4123             default :
4124             {
4125                 *dn = dn->MakeLower();
4126                 break;
4127             }
4128         }
4129         if (children.Item(i)->m_Children.GetCount() > 0)
4130         {
4131             ChangeCaseChildren(children.Item(i)->m_Children, dispCase);
4132         }
4133     }
4134 }
4135 
4136 
FindToken(const TokenFlat & token,TokensArrayF * children)4137 TokenF* ParserF::FindToken(const TokenFlat &token, TokensArrayF* children)
4138 {
4139     if (!children)
4140         children = FindFileTokens(token.m_Filename);
4141     if (!children)
4142         return NULL;
4143 
4144     TokenF* pFoundToken = NULL;
4145 
4146     for (size_t i=0; i<children->GetCount(); i++)
4147     {
4148 		if (children->Item(i)->m_LineStart == token.m_LineStart && children->Item(i)->m_Name == token.m_Name)
4149         {
4150             pFoundToken = children->Item(i);
4151             break;
4152         }
4153         else if ( children->Item(i)->m_LineStart <= token.m_LineStart &&
4154                   children->Item(i)->m_LineEnd >= token.m_LineStart &&
4155                   children->Item(i)->m_Children.GetCount() > 0)
4156         {
4157             pFoundToken = FindToken(token, &children->Item(i)->m_Children);
4158             if (pFoundToken)
4159                 break;
4160         }
4161         else if (children->Item(i)->m_LineStart > token.m_LineStart)
4162             break;
4163     }
4164     return pFoundToken;
4165 }
4166 
ChangeLineIfRequired(cbEditor * ed,wxString & curLine)4167 void ParserF::ChangeLineIfRequired(cbEditor* ed, wxString& curLine)
4168 {
4169     int lineStart = -1;
4170     TokenFlat* tokFl = NULL;
4171     FindLineScopeLN(ed, lineStart, tokFl, -1);
4172     if (tokFl)
4173     {
4174         if (tokFl->m_TokenKind == tkAssociateConstruct || tokFl->m_TokenKind == tkSelectTypeDefault)
4175         {
4176             ChangeAssociatedName(curLine, tokFl);
4177         }
4178         delete tokFl;
4179     }
4180 }
4181 
GetAddressOfToken(TokenF * token,wxArrayString & address)4182 void ParserF::GetAddressOfToken(TokenF* token, wxArrayString& address)
4183 {
4184     if (token->m_TokenKind != tkFile && token->m_pParent)
4185         GetAddressOfToken(token->m_pParent, address);
4186 
4187     if (token->m_TokenKind == tkFile)
4188         address.Add(token->m_Filename);
4189     else
4190         address.Add(token->m_Name);
4191 }
4192 
FindTokenBetweenChildren(TokenF * pToken,const wxString & name)4193 TokenF* ParserF::FindTokenBetweenChildren(TokenF* pToken, const wxString& name)
4194 {
4195     TokensArrayF* pChildren = &pToken->m_Children;
4196 
4197     wxString nameLw = name.Lower();
4198     for (size_t i=0; i<pChildren->GetCount(); i++)
4199     {
4200         if (pChildren->Item(i)->m_Name.IsSameAs(nameLw))
4201             return pChildren->Item(i);
4202     }
4203     return NULL;
4204 }
4205 
FindImplementedProcInMySubmodules(TokenFlat * tok,const wxString & search,TokensArrayFlat & result)4206 void ParserF::FindImplementedProcInMySubmodules(TokenFlat* tok, const wxString& search, TokensArrayFlat& result)
4207 {
4208     wxArrayString address; // [file_name, module_name, function_name, etc.]
4209     FindAddress(tok, address);
4210     if (address.Count() < 3)
4211         return; // not in an interface
4212 
4213     FindImplementedProcInMySubmodules(address, search, result);
4214 }
4215 
FindImplementedProcInMySubmodules(cbEditor * ed,const wxString & search,TokensArrayFlat & result)4216 void ParserF::FindImplementedProcInMySubmodules(cbEditor* ed, const wxString& search, TokensArrayFlat& result)
4217 {
4218     wxArrayString address; // [file_name, module_name, function_name, etc.]
4219     FindAddress(ed, address);
4220     if (address.Count() < 3)
4221         return; // not in an interface
4222 
4223     FindImplementedProcInMySubmodules(address, search, result);
4224 }
4225 
FindImplementedProcInMySubmodules(wxArrayString & address,const wxString & search,TokensArrayFlat & result)4226 void ParserF::FindImplementedProcInMySubmodules(wxArrayString& address, const wxString& search, TokensArrayFlat& result)
4227 {
4228     wxString searchLw = search.Lower();
4229     wxCriticalSectionLocker locker(s_CritSect);
4230     TokensArrayF* fileChildren = FindFileTokens(address.Item(0));
4231     if (!fileChildren)
4232         return;
4233 
4234     std::vector<TokensArrayF*> vpChildren;
4235     TokenF* subModToken = NULL;
4236     TokensArrayF* subModTokenCh = NULL;
4237 
4238     for (size_t i=0; i<fileChildren->GetCount(); i++)
4239     {
4240         if ((fileChildren->Item(i)->m_TokenKind == tkModule || fileChildren->Item(i)->m_TokenKind == tkSubmodule) &&
4241              fileChildren->Item(i)->m_Name.IsSameAs(address.Item(1)))
4242         {
4243             subModToken = fileChildren->Item(i);
4244             subModTokenCh = &fileChildren->Item(i)->m_Children;
4245             break;
4246         }
4247     }
4248     if (!subModTokenCh)
4249         return;
4250 
4251     bool inInterface = false;
4252     bool isInterfaceExp = address.Item(2).IsSameAs(_T("%%tkInterfaceExplicit"));
4253     for (size_t i=0; i<subModTokenCh->GetCount(); i++)
4254     {
4255         if ((subModTokenCh->Item(i)->m_TokenKind == tkInterface || subModTokenCh->Item(i)->m_TokenKind == tkInterfaceExplicit) &&
4256             (subModTokenCh->Item(i)->m_Name.IsSameAs(address.Item(2)) || isInterfaceExp))
4257         {
4258             inInterface = true;
4259             break;
4260         }
4261     }
4262     if (!inInterface)
4263         return;
4264 
4265     wxString modName;
4266     if (subModToken->m_TokenKind == tkModule)
4267         modName = subModToken->m_Name;
4268     else
4269     {
4270         SubmoduleTokenF* submod = static_cast<SubmoduleTokenF*>(subModToken);
4271         modName = submod->m_AncestorModuleName;
4272     }
4273 
4274     TokensArrayF* submodTokens = new TokensArrayF();
4275     FindSubmodulesWhichExtends(modName, submodTokens);
4276     int mask = tkFunction | tkSubroutine | tkProcedure;
4277 
4278     for (size_t j=0; j<submodTokens->GetCount(); j++)
4279     {
4280         TokensArrayF* smCh = &submodTokens->Item(j)->m_Children;
4281         for (size_t i=0; i<smCh->GetCount(); i++)
4282         {
4283             if ((smCh->Item(i)->m_TokenKind & mask) &&
4284                 smCh->Item(i)->m_Name.IsSameAs(searchLw))
4285             {
4286                 result.Add(new TokenFlat(smCh->Item(i)));
4287             }
4288         }
4289     }
4290 }
4291 
FindSubmodulesWhichExtends(const wxString & moduleName,TokensArrayF * result)4292 void ParserF::FindSubmodulesWhichExtends(const wxString& moduleName, TokensArrayF* result)
4293 {
4294     for (size_t i=0; i<m_pTokens->GetCount(); i++)
4295     {
4296         if (m_pTokens->Item(i)->m_TokenKind == tkFile)
4297         {
4298             TokensArrayF* children = &m_pTokens->Item(i)->m_Children;
4299             for (size_t j=0; j<children->GetCount(); j++)
4300             {
4301                 if (children->Item(j)->m_TokenKind == tkSubmodule)
4302                 {
4303                     SubmoduleTokenF* submod = static_cast<SubmoduleTokenF*>(children->Item(j));
4304                     if (submod->m_AncestorModuleName.IsSameAs(moduleName))
4305                         result->Add(children->Item(j));
4306                 }
4307             }
4308         }
4309     }
4310 }
4311 
ChangeArgumentsTypeBoundProc(TokenFlat & tbProcTok,const TokenFlat & procTok)4312 void ParserF::ChangeArgumentsTypeBoundProc(TokenFlat& tbProcTok, const TokenFlat& procTok)
4313 {
4314     if (tbProcTok.m_Pass)
4315     {
4316         wxString pass_arg = tbProcTok.m_Args;
4317         wxString args = procTok.m_Args;
4318         int start = 0;
4319         int end = 0;
4320         if (!pass_arg.IsEmpty())
4321             GetPossitionOfDummyArgument(args, pass_arg, start, end);
4322         else
4323             GetCallTipHighlight(args, 0, start, end);
4324         if (end <= start)
4325         {
4326             tbProcTok.m_Args = args; // was not found?
4327             return;
4328         }
4329 
4330         wxString fpart = args.Mid(0,start);
4331         int compos = fpart.Find(',',true);
4332         if (compos != wxNOT_FOUND)
4333             fpart = fpart.Mid(0,compos+1);
4334 
4335         wxString spart = args.Mid(start);
4336         compos = spart.Find(',');
4337         if (compos != wxNOT_FOUND)
4338             spart = spart.Mid(compos+1).Trim(false);
4339         else
4340             spart = args.Mid(end).Trim(false);
4341 
4342         tbProcTok.m_Args = fpart.Append(spart);
4343     }
4344     else
4345     {
4346         tbProcTok.m_Args = procTok.m_Args;
4347     }
4348 }
4349 
GetChildren(TokenFlat * token,int tokenKindMask,TokensArrayFlat & result,int levelMax)4350 void ParserF::GetChildren(TokenFlat* token, int tokenKindMask, TokensArrayFlat& result, int levelMax)
4351 {
4352     TokenF* pToken = NULL;
4353     TokensArrayF* pChildren = FindFileTokens(token->m_Filename);
4354 
4355     for (size_t i=0; i<8; i++)
4356     {
4357         bool newChildren = false;
4358         for (size_t j=0; j < pChildren->GetCount(); j++)
4359         {
4360             if (pChildren->Item(j)->m_LineStart == token->m_LineStart && pChildren->Item(j)->m_Name.IsSameAs(token->m_Name))
4361             {
4362                 pToken = pChildren->Item(j);
4363                 break;
4364             }
4365             else if (pChildren->Item(j)->m_LineStart <= token->m_LineStart && pChildren->Item(j)->m_LineEnd >= token->m_LineEnd)
4366             {
4367                 pChildren = &pChildren->Item(j)->m_Children;
4368                 newChildren = true;
4369                 break;
4370             }
4371             else if (pChildren->Item(j)->m_LineStart > token->m_LineStart)
4372             {
4373                 break;
4374             }
4375         }
4376         if (!newChildren)
4377             break;
4378     }
4379 
4380     if (!pToken)
4381         return;
4382 
4383     GetChildren(pToken, tokenKindMask, result, 1, levelMax);
4384 }
4385 
GetChildren(TokenF * pToken,int tokenKindMask,TokensArrayFlat & result,int level,int levelMax)4386 void ParserF::GetChildren(TokenF* pToken, int tokenKindMask, TokensArrayFlat& result, int level, int levelMax)
4387 {
4388     if (!pToken)
4389         return;
4390 
4391     TokensArrayF* pChildren = &pToken->m_Children;
4392     size_t nChild = pChildren->GetCount();
4393     for (size_t i=0; i<nChild; i++)
4394     {
4395         if (pChildren->Item(i)->m_TokenKind & tokenKindMask)
4396         {
4397             result.Add(new TokenFlat(pChildren->Item(i)));
4398         }
4399         else if (pChildren->Item(i)->m_TokenKind == tkAssociateConstruct)
4400         {
4401             GetChildrenAssociateConstruct(pChildren->Item(i), tokenKindMask, result);
4402         }
4403         if (level < levelMax)
4404             GetChildren(pChildren->Item(i), tokenKindMask, result, level+1, levelMax);
4405     }
4406 }
4407 
GetChildrenAssociateConstruct(TokenF * token,int tokenKindMask,TokensArrayFlat & result)4408 void ParserF::GetChildrenAssociateConstruct(TokenF* token, int tokenKindMask, TokensArrayFlat& result)
4409 {
4410     TokensArrayF* pACCh = &token->m_Children;
4411     for (size_t j=0; j<pACCh->GetCount(); j++)
4412     {
4413         if (pACCh->Item(j)->m_TokenKind & tokenKindMask)
4414         {
4415             result.Add(new TokenFlat(pACCh->Item(j)));
4416         }
4417         else if (pACCh->Item(j)->m_TokenKind == tkAssociateConstruct)
4418         {
4419             GetChildrenAssociateConstruct(pACCh->Item(j), tokenKindMask, result);
4420         }
4421     }
4422 }
4423 
4424 
FindMatchTokensAtInclude(cbEditor * ed,const wxString & findName,bool onlyPublicNames,bool partialMach,TokensArrayFlat & result)4425 void ParserF::FindMatchTokensAtInclude(cbEditor* ed, const wxString& findName, bool onlyPublicNames, bool partialMach, TokensArrayFlat& result)
4426 {
4427     wxChar sep = wxFileName::GetPathSeparator();
4428     wxString fname = ed->GetFilename().AfterLast(sep);
4429     wxString parFName = m_pIncludeDB->GetOneParentFile(fname);
4430 
4431     if (parFName.IsEmpty())
4432         return;
4433 
4434     TokenF* pFileToken = FindFileTokenWithName(parFName);
4435     if (!pFileToken)
4436         return;
4437 
4438     TokensArrayFlatClass includeTmp;
4439     TokensArrayFlat* includeToks = includeTmp.GetTokens();
4440     int mask = tkInclude;
4441 
4442     FindMatchChildrenDeclared(pFileToken->m_Children, fname.Lower(), *includeToks, mask, false, mask, onlyPublicNames);
4443 
4444     if (includeToks->Count() == 0)
4445         return;
4446 
4447     int tokKind = tkModule | tkFunction | tkProgram | tkSubroutine | tkPreprocessor | tkInterface |
4448                   tkBlockData | tkType | tkVariable | tkProcedure;
4449     TokensArrayFlatClass tokensTmp;
4450     TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
4451     TokensArrayFlatClass tokensTmpU;
4452     TokensArrayFlat* resultTmpU = tokensTmpU.GetTokens();
4453     FindUseAssociatedTokens(onlyPublicNames, includeToks->Item(0), findName, partialMach, *resultTmp, tokKind, false, resultTmpU);
4454     FindImplementedProcInMySubmodules(ed, findName, *resultTmp);
4455     for (size_t i=0; i<resultTmpU->GetCount(); i++)
4456     {
4457         AddUniqueResult(result, resultTmpU->Item(i));
4458     }
4459     for (size_t i=0; i<resultTmp->GetCount(); i++)
4460     {
4461         result.Add(new TokenFlat(resultTmp->Item(i)));
4462     }
4463 }
4464 
BuildCalledByDict(CalledByDict & cByDict)4465 void ParserF::BuildCalledByDict(CalledByDict& cByDict)
4466 {
4467     cByDict.Build(m_pTokens);
4468 }
4469 
4470 
4471