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