Code::Blocks  SVN r11506
nativeparser_base.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 11304 $
6  * $Id: nativeparser_base.cpp 11304 2018-02-28 00:33:37Z ollydbg $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/plugins/codecompletion/nativeparser_base.cpp $
8  */
9 
10 #include <sdk.h>
11 
12 #ifndef CB_PRECOMP
13 #endif
14 
15 #include "nativeparser_base.h"
16 #include "parser/tokenizer.h"
17 
18 #include "parser/cclogger.h"
19 
20 #define CC_NATIVEPARSERBASE_DEBUG_OUTPUT 0
21 
22 #if defined(CC_GLOBAL_DEBUG_OUTPUT)
23  #if CC_GLOBAL_DEBUG_OUTPUT == 1
24  #undef CC_NATIVEPARSERBASE_DEBUG_OUTPUT
25  #define CC_NATIVEPARSERBASE_DEBUG_OUTPUT 1
26  #elif CC_GLOBAL_DEBUG_OUTPUT == 2
27  #undef CC_NATIVEPARSERBASE_DEBUG_OUTPUT
28  #define CC_NATIVEPARSERBASE_DEBUG_OUTPUT 2
29  #endif
30 #endif
31 
32 #ifdef CC_PARSER_TEST
33  #define ADDTOKEN(format, args...) \
34  CCLogger::Get()->AddToken(F(format, ##args))
35  #define TRACE(format, args...) \
36  CCLogger::Get()->DebugLog(F(format, ##args))
37  #define TRACE2(format, args...) \
38  CCLogger::Get()->DebugLog(F(format, ##args))
39 #else
40  #if CC_NATIVEPARSERBASE_DEBUG_OUTPUT == 1
41  #define ADDTOKEN(format, args...) \
42  CCLogger::Get()->AddToken(F(format, ##args))
43  #define TRACE(format, args...) \
44  CCLogger::Get()->DebugLog(F(format, ##args))
45  #define TRACE2(format, args...)
46  #elif CC_NATIVEPARSERBASE_DEBUG_OUTPUT == 2
47  #define ADDTOKEN(format, args...) \
48  CCLogger::Get()->AddToken(F(format, ##args))
49  #define TRACE(format, args...) \
50  do \
51  { \
52  if (g_EnableDebugTrace) \
53  CCLogger::Get()->DebugLog(F(format, ##args)); \
54  } \
55  while (false)
56  #define TRACE2(format, args...) \
57  CCLogger::Get()->DebugLog(F(format, ##args))
58  #else
59  #define ADDTOKEN(format, args...)
60  #define TRACE(format, args...)
61  #define TRACE2(format, args...)
62  #endif
63 #endif
64 
66 {
67 }
68 
70 {
71 }
72 
74 {
76 }
77 
78 // Here's the meat of code-completion :)
79 // This function decides most of what gets included in the auto-completion
80 // list presented to the user.
81 // It's called recursively for each component of the std::queue argument.
82 // for example: objA.objB.function()
83 // The queue is like: 'objA' 'objB' 'function'. We deal with objA first.
84 //
85 // No critical section needed in this recursive function!
86 // All functions that call this recursive function, should already entered a critical section.
88  std::queue<ParserComponent> components,
89  TokenIdxSet& result,
90  int parentTokenIdx,
91  bool isPrefix,
92  bool caseSensitive,
93  bool use_inheritance,
94  short int kindMask,
95  TokenIdxSet* search_scope)
96 {
97  if (components.empty())
98  return 0;
99 
100  if (s_DebugSmartSense)
101  CCLogger::Get()->DebugLog(_T("FindAIMatches() ----- FindAIMatches - enter -----"));
102 
103  TRACE(_T("NativeParser::FindAIMatches()"));
104 
105  // pop top component
106  ParserComponent parser_component = components.front();
107  components.pop();
108 
109  // handle the special keyword "this".
110  if ((parentTokenIdx != -1) && (parser_component.component == _T("this")))
111  {
112  // this will make the AI behave like it's the previous scope (or the current if no previous scope)
113 
114  // move on please, nothing to see here...
115  // All functions that call the recursive FindAIMatches should already entered a critical section.
116  return FindAIMatches(tree, components, result, parentTokenIdx,
117  isPrefix, caseSensitive, use_inheritance,
118  kindMask, search_scope);
119  }
120 
121  // we 'll only add tokens in the result set if we get matches for the last token
122  bool isLastComponent = components.empty();
123  wxString searchtext = parser_component.component;
124 
125  if (s_DebugSmartSense)
126  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() Search for %s, isLast = %d"),
127  searchtext.wx_str(), isLastComponent?1:0));
128 
129  // get a set of matches for the current token
130  TokenIdxSet local_result;
131  // All functions that call the recursive GenerateResultSet should already entered a critical section.
132  GenerateResultSet(tree, searchtext, parentTokenIdx, local_result,
133  (caseSensitive || !isLastComponent),
134  (isLastComponent && !isPrefix), kindMask);
135 
136  if (s_DebugSmartSense)
137  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() Looping %lu results"),
138  static_cast<unsigned long>(local_result.size())));
139 
140  // loop all matches, and recurse
141  for (TokenIdxSet::const_iterator it = local_result.begin(); it != local_result.end(); it++)
142  {
143  int id = *it;
144  const Token* token = tree->at(id);
145 
146  // sanity check
147  if (!token)
148  {
149  if (s_DebugSmartSense)
150  CCLogger::Get()->DebugLog(_T("FindAIMatches() Token is NULL?!"));
151  continue;
152  }
153 
154  // ignore operators
155  if (token->m_IsOperator)
156  continue;
157 
158  // enums children (enumerators), are added by default
159  if (token->m_TokenKind == tkEnum)
160  {
161  // insert enum type
162  result.insert(id);
163 
164  // insert enumerators
165  for (TokenIdxSet::const_iterator tis_it = token->m_Children.begin();
166  tis_it != token->m_Children.end();
167  tis_it++)
168  result.insert(*tis_it);
169 
170  continue; // done with this token
171  }
172 
173  if (s_DebugSmartSense)
174  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() Match: '%s' (ID='%d') : type='%s'"),
175  token->m_Name.wx_str(), id, token->m_BaseType.wx_str()));
176 
177 
178  // is the token a function or variable (i.e. is not a type)
179  if ( !searchtext.IsEmpty()
180  && (parser_component.tokenType != pttSearchText)
181  && !token->m_BaseType.IsEmpty() )
182  {
183  // the token is not a type
184  // find its type's ID and use this as parent instead of (*it)
185  TokenIdxSet type_result;
186  std::queue<ParserComponent> type_components;
187  wxString actual = token->m_BaseType;
188 
189  // TODO: ignore builtin types (void, int, etc)
190  BreakUpComponents(actual, type_components);
191  // the parent to search under is a bit troubling, because of namespaces
192  // what we 'll do is search under current parent and traverse up the parentship
193  // until we find a result, or reach -1...
194 
195  if (s_DebugSmartSense)
196  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() Looking for type: '%s' (%lu components)"),
197  actual.wx_str(),
198  static_cast<unsigned long>(type_components.size())));
199 
200  // search under all search-scope namespaces too
201  TokenIdxSet temp_search_scope;
202  if (search_scope)
203  temp_search_scope = *search_scope;
204 
205  // add grand-parent as search scope (if none defined)
206  // this helps with namespaces when the token's type doesn't contain
207  // namespace info. In that case (with the code here) we 're searching in
208  // the parent's namespace too
209  if (parentTokenIdx != -1)
210  {
211  const Token* parentToken = tree->at(parentTokenIdx);
212  if (parentToken)
213  {
214  const Token* parent = tree->at(parentToken->m_ParentIndex);
215  if (parent)
216  {
217  temp_search_scope.insert(parent->m_Index);
218  if (s_DebugSmartSense)
219  CCLogger::Get()->DebugLog(_T("FindAIMatches() Implicit search scope added:") + parent->m_Name);
220  }
221  }
222  }
223 
224  TokenIdxSet::const_iterator itsearch;
225  itsearch = temp_search_scope.begin();
226  while (!search_scope || itsearch != temp_search_scope.end())
227  {
228  const Token* parent = tree->at(*itsearch);
229 
230  if (s_DebugSmartSense)
231  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() Now looking under '%s'"),
232  parent ? parent->m_Name.wx_str() : wxString(_("Global namespace")).wx_str()));
233 
234  do
235  {
236  // types are searched as whole words, case sensitive and only classes/namespaces
237  // All functions that call the recursive FindAIMatches should already entered a critical section.
238  if (FindAIMatches(tree,
239  type_components,
240  type_result,
241  parent ? parent->m_Index : -1,
242  true,
243  false,
244  false,
246  &temp_search_scope) != 0)
247  break;
248  if (!parent)
249  break;
250  parent = tree->at(parent->m_ParentIndex);
251  } while (true);
252  ++itsearch;
253  }
254 
255  // we got all possible types (hopefully should be just one)
256  if (!type_result.empty())
257  {
258  // this is the first result
259  id = *(type_result.begin());
260  if (type_result.size() > 1)
261  {
262  // if we have more than one result, recurse for all of them
263  TokenIdxSet::const_iterator tis_it = type_result.begin();
264  ++tis_it;
265  while (tis_it != type_result.end())
266  {
267  std::queue<ParserComponent> lcomp = components;
268  // All functions that call the recursive FindAIMatches should already entered a critical section.
269  FindAIMatches(tree, lcomp, result, *tis_it, isPrefix,
270  caseSensitive, use_inheritance,
271  kindMask, search_scope);
272  ++tis_it;
273  }
274  }
275 
276  if (s_DebugSmartSense)
277  {
278  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() Type: '%s' (%d)"), tree->at(id)->m_Name.wx_str(), id));
279  if (type_result.size() > 1)
280  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() Multiple types matched for '%s': %lu results"),
281  token->m_BaseType.wx_str(),
282  static_cast<unsigned long>(type_result.size())));
283  }
284  }
285  else if (s_DebugSmartSense)
286  CCLogger::Get()->DebugLog(F(_T("FindAIMatches() No types matched '%s'."), token->m_BaseType.wx_str()));
287  }
288 
289  // if no more components, add to result set
290  if (isLastComponent)
291  result.insert(id);
292  // else recurse this function using id as a parent
293  else
294  // All functions that call the recursive FindAIMatches should already entered a critical section.
295  FindAIMatches(tree, components, result, id, isPrefix,
296  caseSensitive, use_inheritance, kindMask,
297  search_scope);
298  }
299 
300  if (s_DebugSmartSense)
301  CCLogger::Get()->DebugLog(_T("FindAIMatches() ----- FindAIMatches - leave -----"));
302 
303  return result.size();
304 }
305 
307  const TokenIdxSet& procResult,
308  TokenIdxSet& scopeResult)
309 {
311  // loop on the input parameter procResult, and only record some container tokens, such as
312  // class token, function token.
313  for (TokenIdxSet::const_iterator it = procResult.begin(); it != procResult.end(); ++it)
314  {
315  const Token* token = tree->at(*it);
316  if (!token)
317  continue;
318 
319  if (token->m_TokenKind == tkClass)
320  scopeResult.insert(*it);
321  else
322  {
323  if (token->m_TokenKind & tkAnyFunction && token->HasChildren()) // for local variable
324  scopeResult.insert(*it);
325  scopeResult.insert(token->m_ParentIndex);
326  }
327 
328  if (s_DebugSmartSense)
329  {
330  const Token* parent = tree->at(token->m_ParentIndex);
331  CCLogger::Get()->DebugLog(_T("AI() Adding search namespace: ") +
332  (parent ? parent->m_Name : _T("Global namespace")));
333  }
334  }
335 
337 }
338 
340  TokenIdxSet* searchScope)
341 {
343  // remove all the container tokens in the token index set
344  for (TokenIdxSet::const_iterator it = searchScope->begin(); it != searchScope->end();)
345  {
346  const Token* token = tree->at(*it);
347  if (!token || !(token->m_TokenKind & (tkNamespace | tkClass | tkTypedef | tkAnyFunction)))
348  searchScope->erase(it++);
349  else
350  ++it;
351  }
352 
354 
355  // ...but always search the global scope.
356  searchScope->insert(-1);
357 }
358 
359 // Set start and end for the calltip highlight region.
361  int* start,
362  int* end,
363  int typedCommas)
364 {
365  TRACE(_T("NativeParserBase::GetCallTipHighlight()"));
366 
367  int pos = 0;
368  int paramsCloseBracket = calltip.length() - 1;
369  int nest = 0;
370  int commas = 0;
371  *start = FindFunctionOpenParenthesis(calltip) + 1;
372  *end = 0;
373  while (true)
374  {
375  wxChar c = calltip.GetChar(pos++);
376  if (c == '\0')
377  break;
378  else if (c == '(')
379  ++nest;
380  else if (c == ')')
381  {
382  --nest;
383  if (nest == 0)
384  paramsCloseBracket = pos - 1;
385  }
386  else if (c == ',' && nest == 1)
387  {
388  ++commas;
389  if (commas == typedCommas + 1)
390  {
391  *end = pos - 1;
392  return;
393  }
394  *start = pos;
395  }
396  }
397  if (*end == 0)
398  *end = paramsCloseBracket;
399 }
400 
402 {
403  int nest = 0;
404  for (size_t i = calltip.length(); i > 0; --i)
405  {
406  wxChar c = calltip[i - 1];
407  if (c == wxT('('))
408  {
409  --nest;
410  if (nest == 0)
411  return i - 1;
412  }
413  else if (c == wxT(')'))
414  ++nest;
415  }
416  return -1;
417 }
418 
420  ParserTokenType& tokenType,
421  OperatorType& tokenOperatorType)
422 {
423  tokenType = pttSearchText;
424  tokenOperatorType = otOperatorUndefined;
425  if (line.IsEmpty())
426  return wxEmptyString;
427 
428  tokenOperatorType = otOperatorUndefined;
429  unsigned int startAt = FindCCTokenStart(line);
430  wxString res = GetNextCCToken(line, startAt, tokenOperatorType);
431 
432  TRACE(_T("GetCCToken() : FindCCTokenStart returned %u \"%s\""), startAt, line.wx_str());
433  TRACE(_T("GetCCToken() : GetNextCCToken returned %u \"%s\""), startAt, res.wx_str());
434 
435 
436  if (startAt == line.Len())
437  line.Clear();
438  else
439  {
440  // skip whitespace
441  startAt = AfterWhitespace(startAt, line);
442 
443  // Check for [Class]. ('.' pressed)
444  if (IsOperatorDot(startAt, line))
445  {
446  tokenType = pttClass;
447  line.Remove(0, startAt + 1);
448  }
449  // Check for
450  // (1) "AAA->" ('>' pressed)
451  // (2) "AAA::" (':' pressed)
452  // If (1) and tokenOperatorType == otOperatorSquare, then we have
453  // special case "AAA[]->" and should not change tokenOperatorType.
454  else if (IsOperatorEnd(startAt, line))
455  {
456  if ( IsOperatorPointer(startAt, line)
457  && !res.IsEmpty()
458  && tokenOperatorType != otOperatorSquare)
459  tokenOperatorType = otOperatorPointer;
460  if (line.GetChar(startAt) == ':')
461  tokenType = pttNamespace;
462  else
463  tokenType = pttClass;
464  line.Remove(0, startAt + 1);
465  }
466  else
467  line.Clear();
468  }
469 
470  TRACE(_T("GetCCToken() : Left \"%s\""), line.wx_str());
471 
472  if (tokenOperatorType == otOperatorParentheses)
473  tokenType = pttFunction;
474 
475  return res;
476 }
477 
478 // skip nest braces in the expression, e.g.
479 // SomeObject->SomeMethod(arg1, arg2)->Method2()
480 // ^end ^begin
481 // note we skip the nest brace (arg1, arg2).
483 {
484  // Careful: startAt can become negative, so it's defined as integer here!
485  int startAt = line.Len() - 1;
486  int nest = 0;
487 
488  bool repeat = true;
489  while (repeat)
490  {
491  repeat = false;
492  // Go back to the beginning of the function/variable (token)
493  startAt = BeginOfToken(startAt, line);
494 
495  // Check for [Class]. ('.' pressed)
496  if (IsOperatorDot(startAt, line))
497  {
498  --startAt;
499  repeat = true; // yes -> repeat.
500  }
501  // Check for [Class]-> ('>' pressed)
502  // Check for [Class]:: (':' pressed)
503  else if (IsOperatorEnd(startAt, line))
504  {
505  startAt -= 2;
506  repeat = true; // yes -> repeat.
507  }
508 
509  if (repeat)
510  {
511  // now we're just before the "." or "->" or "::"
512  // skip any whitespace
513  startAt = BeforeWhitespace(startAt, line);
514 
515  // check for function/array/cast ()
516  if (IsClosingBracket(startAt, line))
517  {
518  ++nest;
519  while ( (--startAt >= 0)
520  && (nest != 0) )
521  {
522  #if wxCHECK_VERSION(3, 0, 0)
523  switch (line.GetChar(startAt).GetValue())
524  #else
525  switch (line.GetChar(startAt))
526  #endif
527  {
528  case ']':
529  case ')': ++nest; --startAt; break;
530 
531  case '[':
532  case '(': --nest; --startAt; break;
533  default:
534  break;
535  }
536 
537  startAt = BeforeWhitespace(startAt, line);
538 
539  if (IsClosingBracket(startAt, line))
540  ++nest;
541  if (IsOpeningBracket(startAt, line))
542  --nest;
543  }
544 
545  startAt = BeforeToken(startAt, line);
546  }
547  }
548  }
549  ++startAt;
550 
551  startAt = AfterWhitespace(startAt, line);
552 
553  TRACE(_T("FindCCTokenStart() : Starting at %u \"%s\""), startAt, line.Mid(startAt).wx_str());
554 
555  return startAt;
556 }
557 
559  unsigned int& startAt,
560  OperatorType& tokenOperatorType)
561 {
562  wxString res;
563  int nest = 0;
564 
565  if ( (startAt < line.Len())
566  && (line.GetChar(startAt) == '(') )
567  {
568  while ( (startAt < line.Len())
569  && ( (line.GetChar(startAt) == '*')
570  || (line.GetChar(startAt) == '&')
571  || (line.GetChar(startAt) == '(') ) )
572  {
573  if (line.GetChar(startAt) == '(')
574  ++nest;
575  if (line.GetChar(startAt) == _T('*'))
576  tokenOperatorType = otOperatorStar;
577  ++startAt;
578  }
579  }
580 
581  TRACE(_T("GetNextCCToken() : at %u (%c): res=%s"), startAt, line.GetChar(startAt), res.wx_str());
582 
583  while (InsideToken(startAt, line))
584  {
585  res << line.GetChar(startAt);
586  ++startAt;
587  }
588  while ( (nest > 0)
589  && (startAt < line.Len()) )
590  {
591  // TODO: handle nested scope resolution (A::getC()).|
592  if (line.GetChar(startAt) == '(')
593  ++nest;
594  else if (line.GetChar(startAt) == ')')
595  --nest;
596  ++startAt;
597  }
598 
599  TRACE(_T("GetNextCCToken() : Done nest: at %u (%c): res=%s"), startAt, line.GetChar(startAt), res.wx_str());
600 
601  startAt = AfterWhitespace(startAt, line);
602  if (IsOpeningBracket(startAt, line))
603  {
604  if (line.GetChar(startAt) == _T('('))
605  tokenOperatorType = otOperatorParentheses;
606  else if (line.GetChar(startAt) == _T('['))
607  tokenOperatorType = otOperatorSquare;
608  ++nest;
609  while ( (startAt < line.Len()-1)
610  && (nest != 0) )
611  {
612  ++startAt;
613  #if wxCHECK_VERSION(3, 0, 0)
614  switch (line.GetChar(startAt).GetValue())
615  #else
616  switch (line.GetChar(startAt))
617  #endif
618  {
619  case ']':
620  case ')': --nest; ++startAt; break;
621 
622  case '[':tokenOperatorType = otOperatorSquare;
623  case '(': ++nest; ++startAt; break;
624  default:
625  break;
626  }
627 
628  startAt = AfterWhitespace(startAt, line);
629 
630  if (IsOpeningBracket(startAt, line))
631  ++nest;
632  //NOTE: do not skip successive closing brackets. Eg,
633  // "GetConfigManager(_T("code_completion"))->ReadBool"
634  // ^
635  if (IsClosingBracket(startAt, line))
636  {
637  --nest;
638  if (nest == 0)
639  ++startAt;
640  }
641  }
642  }
643  if (IsOperatorBegin(startAt, line))
644  ++startAt;
645 
646  TRACE(_T("GetNextCCToken() : Return at %u (%c): res=%s"), startAt, line.GetChar(startAt), res.wx_str());
647 
648  return res;
649 }
650 
652  int& lastFuncTokenIdx)
653 {
655 
656  Token* token = tree->at(lastFuncTokenIdx);
657  if (token)
658  {
659  lastFuncTokenIdx = -1;
660  if (token->m_TokenKind & tkAnyFunction)
661  token->DeleteAllChildren();
662  }
663 
665 }
666 
667 // Breaks up the phrase for code-completion.
668 // Suppose the user has invoked code-completion in this piece of code:
669 //
670 // Ogre::Root::getSingleton().|
671 //
672 // This function will break this up into an std::queue (FIFO) containing
673 // the following items (top is first-out):
674 //
675 // Ogre [pttNamespace]
676 // Root [pttClass]
677 // getSingleton [pttFunction]
678 // (empty space) [pttSearchText]
679 //
680 // It also classifies each component as a pttClass, pttNamespace, pttFunction, pttSearchText
682  std::queue<ParserComponent>& components)
683 {
684  ParserTokenType tokenType;
685  wxString statement = actual;
686  OperatorType tokenOperatorType;
687  // break up components of phrase
688  if (s_DebugSmartSense)
689  CCLogger::Get()->DebugLog(F(_T("BreakUpComponents() Breaking up '%s'"), statement.wx_str()));
690  TRACE(_T("NativeParserBase::BreakUpComponents()"));
691 
692  while (true)
693  {
694  wxString tok = GetCCToken(statement, tokenType, tokenOperatorType);
695 
696  ParserComponent pc;
697  pc.component = tok;
698  pc.tokenType = tokenType;
699  pc.tokenOperatorType = tokenOperatorType;
700  // Debug smart sense: output the component's name and type.
701  if (s_DebugSmartSense)
702  {
703  wxString tokenTypeString;
704  switch (tokenType)
705  {
706  case (pttFunction):
707  { tokenTypeString = _T("Function"); break; }
708  case (pttClass):
709  { tokenTypeString = _T("Class"); break; }
710  case (pttNamespace):
711  { tokenTypeString = _T("Namespace"); break; }
712  case (pttSearchText):
713  { tokenTypeString = _T("SearchText"); break; }
714  case (pttUndefined):
715  default:
716  { tokenTypeString = _T("Undefined"); }
717  }
718  CCLogger::Get()->DebugLog(F(_T("BreakUpComponents() Found component: '%s' (%s)"),
719  tok.wx_str(), tokenTypeString.wx_str()));
720  }
721 
722  // Support global namespace like ::MessageBoxA
723  // Break up into "", type is pttNameSpace and "MessageBoxA", type is pttSearchText.
724  // for pttNameSpace type, if its text (tok) is empty -> ignore this component.
725  // for pttSearchText type, don't do this because for ss:: we need this, too.
726  if (!tok.IsEmpty() || (tokenType == pttSearchText && !components.empty()))
727  {
728  if (s_DebugSmartSense)
729  CCLogger::Get()->DebugLog(F(_T("BreakUpComponents() Adding component: '%s'."), tok.wx_str()));
730  components.push(pc);
731  }
732 
733  if (tokenType == pttSearchText)
734  break;
735  }
736 
737  return 0;
738 }
739 
741  std::queue<ParserComponent> components,
742  const TokenIdxSet& searchScope,
743  TokenIdxSet& result,
744  bool caseSense,
745  bool isPrefix)
746 {
747  m_TemplateMap.clear();
748  if (components.empty())
749  return 0;
750 
751  TokenIdxSet initialScope;
752  if (!searchScope.empty())
753  initialScope = searchScope;
754  else
755  initialScope.insert(-1);
756 
757  while (!components.empty())
758  {
759  TokenIdxSet initialResult;
760  ParserComponent subComponent = components.front();
761  components.pop();
762  wxString searchText = subComponent.component;
763  if (searchText == _T("this"))
764  {
765  initialScope.erase(-1);
766  TokenIdxSet tempInitialScope = initialScope;
767 
769 
770  for (TokenIdxSet::const_iterator it = tempInitialScope.begin();
771  it != tempInitialScope.end(); ++it)
772  {
773  const Token* token = tree->at(*it);
774  if (token && (token->m_TokenKind != tkClass))
775  initialScope.erase(*it);
776  }
777 
779 
780  if (!initialScope.empty())
781  continue;
782  else
783  {
784  CCLogger::Get()->DebugLog(F(_T("ResolveExpression() Error to find initial search scope.")));
785  break; // error happened.
786  }
787  }
788 
789  if (s_DebugSmartSense)
790  {
791  CCLogger::Get()->DebugLog(F(_T("ResolveExpression() Search scope with %lu result:"),
792  static_cast<unsigned long>(initialScope.size())));
793  for (TokenIdxSet::const_iterator tt = initialScope.begin(); tt != initialScope.end(); ++tt)
794  CCLogger::Get()->DebugLog(F(_T("- Search scope: %d"), (*tt)));
795  }
796 
798 
799  // All functions that call the recursive GenerateResultSet should already entered a critical section.
800 
801  // e.g. A.BB.CCC.DDDD|
802  if (components.empty()) // is the last component (DDDD)
803  GenerateResultSet(tree, searchText, initialScope, initialResult, caseSense, isPrefix);
804  else // case sensitive and full-match always (A / BB / CCC)
805  GenerateResultSet(tree, searchText, initialScope, initialResult, true, false);
806 
808 
809  // now we should clear the initialScope.
810  initialScope.clear();
811 
812  //-------------------------------------
813 
814  if (s_DebugSmartSense)
815  CCLogger::Get()->DebugLog(F(_T("ResolveExpression() Looping %lu result."),
816  static_cast<unsigned long>(initialResult.size())));
817 
818  //------------------------------------
819  if (!initialResult.empty())
820  {
821  bool locked = false;
822 
823  // loop all matches.
824  for (TokenIdxSet::const_iterator it = initialResult.begin(); it != initialResult.end(); ++it)
825  {
826  const size_t id = (*it);
827  wxString actualTypeStr;
828  int parentIndex = -1;
829  bool isFuncOrVar = false;
830 
831  if (locked)
834  locked = true;
835 
836  const Token* token = tree->at(id);
837  if (!token)
838  {
839  if (s_DebugSmartSense)
840  CCLogger::Get()->DebugLog(F(_T("ResolveExpression() token is NULL?!")));
841  continue;
842  }
843 
844  // TODO: we should deal with operators carefully.
845  // it should work for class::/namespace::
847  continue;
848 
849  if (s_DebugSmartSense)
850  CCLogger::Get()->DebugLog(F(_T("ResolvExpression() Match:'%s(ID=%lu) : type='%s'"),
851  token->m_Name.wx_str(),
852  static_cast<unsigned long>(id),
853  token->m_BaseType.wx_str()));
854 
855  // recond the template map message here. hope it will work.
856  // wxString tkname = token->m_Name;
857  // wxArrayString tks = token->m_TemplateType;
858  if (!token->m_TemplateMap.empty())
859  m_TemplateMap = token->m_TemplateMap;
860 
861  // if the token is a function/variable(i.e. is not a type)
862  isFuncOrVar = !searchText.IsEmpty()
863  && (subComponent.tokenType != pttSearchText)
864  && !token->m_BaseType.IsEmpty();
865  if (isFuncOrVar)
866  {
867  actualTypeStr = token->m_BaseType;
868  parentIndex = token->m_Index;
869  }
870 
872  locked = false;
873 
874  // handle it if the token is a function/variable(i.e. is not a type)
875  if (isFuncOrVar)
876  {
877  TokenIdxSet actualTypeScope;
878  if (searchScope.empty())
879  actualTypeScope.insert(-1);
880  else
881  {
882  // now collect the search scope for actual type of function/variable.
883  CollectSearchScopes(searchScope, actualTypeScope, tree);
884 
886 
887  // now add the current token's parent scope;
888  const Token* currentTokenParent = tree->at(parentIndex);
889  while (true)
890  {
891  if (!currentTokenParent)
892  break;
893  actualTypeScope.insert(currentTokenParent->m_Index);
894  currentTokenParent = tree->at(currentTokenParent->m_ParentIndex);
895  }
896 
898  }
899 
900  // now get the tokens of variable/function.
901  TokenIdxSet actualTypeResult;
902  ResolveActualType(tree, actualTypeStr, actualTypeScope, actualTypeResult);
903  if (!actualTypeResult.empty())
904  {
905  for (TokenIdxSet::const_iterator it2 = actualTypeResult.begin();
906  it2 != actualTypeResult.end();
907  ++it2)
908  {
909  initialScope.insert(*it2);
910 
912 
913  const Token* typeToken = tree->at(*it2);
914  if (typeToken && !typeToken->m_TemplateMap.empty())
915  m_TemplateMap = typeToken->m_TemplateMap;
916 
918 
919  // and we need to add the template argument alias too.
920  AddTemplateAlias(tree, *it2, actualTypeScope, initialScope);
921  }
922  }
923  else // ok ,we search template container to check if type is template formal.
924  ResolveTemplateMap(tree, actualTypeStr, actualTypeScope, initialScope);
925 
926  continue;
927  }
928 
929  initialScope.insert(id);
930  }// for
931 
932  if (locked)
934  }
935  else
936  {
937  initialScope.clear();
938  break;
939  }
940 
941  if (subComponent.tokenOperatorType != otOperatorUndefined)
942  {
943  TokenIdxSet operatorResult;
944  ResolveOperator(tree, subComponent.tokenOperatorType, initialScope, searchScope, operatorResult);
945  if (!operatorResult.empty())
946  initialScope = operatorResult;
947  }
948  if (subComponent.tokenType != pttSearchText)
949  m_LastComponent = subComponent;
950  }// while
951 
952  // initialScope contains all the matching tokens after the cascade matching algorithm
953  if (!initialScope.empty())
954  {
955  // normally, tokens have hierarchies. E.g. a constructor token is a child of a class token.
956  // but here we promote (expose) the constructor tokens to the user. if a Token in initialScope
957  // is a class, we add all its public constructors to the results, this give us a chance to let
958  // CC jump to the declaration of a constructor, see
959  // http://forums.codeblocks.org/index.php/topic,13753.msg92654.html#msg92654
960  AddConstructors(tree, initialScope, result);
961  }
962 
963  return result.size();
964 }
965 
967 {
968  for (TokenIdxSet::iterator It = source.begin(); It != source.end(); ++It)
969  {
970  const Token* token = tree->at(*It);
971  if (!token)
972  continue;
973  dest.insert(*It);
974 
975  // add constructors of the class type token
976  if (token->m_TokenKind == tkClass)
977  {
978  // loop on its children, add its public constructors
979  for (TokenIdxSet::iterator chIt = token->m_Children.begin();
980  chIt != token->m_Children.end();
981  ++chIt)
982  {
983  const Token* tk = tree->at(*chIt);
984  if ( tk && ( tk->m_TokenKind == tkConstructor
985  || (tk->m_IsOperator && tk->m_Name.EndsWith(wxT("()"))) )
986  && (tk->m_Scope == tsPublic || tk->m_Scope == tsUndefined) )
987  {
988  dest.insert(*chIt);
989  }
990  }
991  }
992  }
993 }
994 
996  const OperatorType& tokenOperatorType,
997  const TokenIdxSet& tokens,
998  const TokenIdxSet& searchScope,
999  TokenIdxSet& result)
1000 {
1001  if (!tree || searchScope.empty())
1002  return;
1003 
1005 
1006  // first,we need to eliminate the tokens which are not tokens.
1007  TokenIdxSet opInitialScope;
1008  for (TokenIdxSet::const_iterator it=tokens.begin(); it!=tokens.end(); ++it)
1009  {
1010  int id = (*it);
1011  const Token* token = tree->at(id);
1012  if (token && (token->m_TokenKind == tkClass || token->m_TokenKind == tkTypedef))
1013  opInitialScope.insert(id);
1014  }
1015 
1017 
1018  // if we get nothing, just return.
1019  if (opInitialScope.empty())
1020  return;
1021 
1022  wxString operatorStr;
1023  switch(tokenOperatorType)
1024  {
1025  case otOperatorParentheses:
1026  operatorStr = _T("operator()"); break;
1027  case otOperatorSquare:
1028  operatorStr = _T("operator[]"); break;
1029  case otOperatorPointer:
1030  operatorStr = _T("operator->"); break;
1031  case otOperatorStar:
1032  operatorStr = _T("operator*"); break;
1033  case otOperatorUndefined:
1034  default:
1035  break;
1036  }
1037  if (operatorStr.IsEmpty())
1038  return;
1039 
1040  //s tart to parse the operator overload actual type.
1041  TokenIdxSet opInitialResult;
1042 
1044 
1045  // All functions that call the recursive GenerateResultSet should already entered a critical section.
1046  GenerateResultSet(tree, operatorStr, opInitialScope, opInitialResult);
1047 
1049 
1050  CollectSearchScopes(searchScope, opInitialScope, tree);
1051 
1052  if (opInitialResult.empty())
1053  return;
1054 
1055  for (TokenIdxSet::const_iterator it=opInitialResult.begin(); it!=opInitialResult.end(); ++it)
1056  {
1058 
1059  wxString type;
1060  const Token* token = tree->at((*it));
1061  if (token)
1062  type = token->m_BaseType;
1063 
1065 
1066  if (type.IsEmpty())
1067  continue;
1068 
1069  TokenIdxSet typeResult;
1070  ResolveActualType(tree, type, opInitialScope, typeResult);
1071  if (!typeResult.empty())
1072  {
1073  for (TokenIdxSet::const_iterator pTypeResult = typeResult.begin();
1074  pTypeResult!=typeResult.end();
1075  ++pTypeResult)
1076  {
1077  result.insert(*pTypeResult);
1078  AddTemplateAlias(tree, *pTypeResult, opInitialScope, result);
1079  }
1080  }
1081  else
1082  ResolveTemplateMap(tree, type, opInitialScope, result);
1083  }
1084 }
1085 
1087  wxString searchText,
1088  const TokenIdxSet& searchScope,
1089  TokenIdxSet& result)
1090 {
1091  // break up the search text for next analysis.
1092  std::queue<ParserComponent> typeComponents;
1093  BreakUpComponents(searchText, typeComponents);
1094  if (!typeComponents.empty())
1095  {
1096  TokenIdxSet initialScope;
1097  if (!searchScope.empty())
1098  initialScope = searchScope;
1099  else
1100  initialScope.insert(-1);
1101 
1103 
1104  while (!typeComponents.empty())
1105  {
1106  TokenIdxSet initialResult;
1107  ParserComponent component = typeComponents.front();
1108  typeComponents.pop();
1109  wxString actualTypeStr = component.component;
1110 
1111  // All functions that call the recursive GenerateResultSet should already entered a critical section.
1112  GenerateResultSet(tree, actualTypeStr, initialScope, initialResult, true, false, 0xFFFF);
1113 
1114  if (!initialResult.empty())
1115  {
1116  initialScope.clear();
1117  for (TokenIdxSet::const_iterator it = initialResult.begin(); it != initialResult.end(); ++it)
1118  // TODO (Morten#1#): eliminate the variable/function
1119  initialScope.insert(*it);
1120  }
1121  else
1122  {
1123  initialScope.clear();
1124  break;
1125  }
1126  }
1127 
1129 
1130  if (!initialScope.empty())
1131  result = initialScope;
1132  }
1133 
1134  return result.size();
1135 }
1136 
1138  const wxString& searchStr,
1139  const TokenIdxSet& actualTypeScope,
1140  TokenIdxSet& initialScope)
1141 {
1142  if (actualTypeScope.empty())
1143  return;
1144 
1145  wxString actualTypeStr = searchStr;
1146  std::map<wxString, wxString>::const_iterator it = m_TemplateMap.find(actualTypeStr);
1147  if (it != m_TemplateMap.end())
1148  {
1149  actualTypeStr = it->second;
1150  TokenIdxSet actualTypeResult;
1151  ResolveActualType(tree, actualTypeStr, actualTypeScope, actualTypeResult);
1152  if (!actualTypeResult.empty())
1153  {
1154  for (TokenIdxSet::const_iterator it2=actualTypeResult.begin(); it2!=actualTypeResult.end(); ++it2)
1155  initialScope.insert(*it2);
1156  }
1157  }
1158 }
1159 
1161  const int& id,
1162  const TokenIdxSet& actualTypeScope,
1163  TokenIdxSet& initialScope)
1164 {
1165  if (!tree || actualTypeScope.empty())
1166  return;
1167 
1168  // and we need to add the template argument alias too.
1169  wxString actualTypeStr;
1170 
1172 
1173  const Token* typeToken = tree->at(id);
1174  if (typeToken && typeToken->m_TokenKind == tkTypedef
1175  && !typeToken->m_TemplateAlias.IsEmpty() )
1176  actualTypeStr = typeToken->m_TemplateAlias;
1177 
1179 
1180  std::map<wxString, wxString>::const_iterator it = m_TemplateMap.find(actualTypeStr);
1181  if (it != m_TemplateMap.end())
1182  {
1183  actualTypeStr = it->second;
1184 
1185  if (actualTypeStr.Last() == _T('&') || actualTypeStr.Last() == _T('*'))
1186  actualTypeStr.RemoveLast();
1187 
1188  TokenIdxSet actualTypeResult;
1189  ResolveActualType(tree, actualTypeStr, actualTypeScope, actualTypeResult);
1190  if (!actualTypeResult.empty())
1191  {
1192  for (TokenIdxSet::const_iterator it2 = actualTypeResult.begin(); it2 != actualTypeResult.end(); ++it2)
1193  initialScope.insert(*it2);
1194  }
1195  }
1196 }
1197 
1198 // No critical section needed in this recursive function!
1199 // All functions that call this recursive function, should already entered a critical section.
1200 //
1201 // Here are sample algorithm, if we have code snippet
1202 //
1203 // class AAA { public: void f1(); int m_aaa;};
1204 // class BBB : public AAA {public: void f2(); int m_bbb;};
1205 // BBB obj;
1206 // obj.f|-------CC Here, we expect "f1" and "f2" be prompt
1207 //
1208 // Here, we do a search with the following states:
1209 // the search text target = "f", and isPrefix = true
1210 // parentIdx points to the class type Token "BBB"
1211 // caseSens could be true, kindMask could be to list any function kind tokens.
1212 //
1213 // First, we first list the children of BBB, there are two "f1", and "m_aaa", and text match should
1214 // only find one "f1".
1215 // Second, we try to calculate all the ancestors of BBB, which we see a class type Token "AAA"
1216 // list the children of AAA, and do a text match, we find "f2"
1217 // Last, we return a Token set which contains two elements ["f1", "f2"]
1218 //
1219 // Note that parentIdx could be the global namespace
1220 // Some kinds of Token types, such as Enum or Namespaces could be handled specially
1222  const wxString& target,
1223  int parentIdx,
1224  TokenIdxSet& result,
1225  bool caseSens,
1226  bool isPrefix,
1227  short int kindMask)
1228 {
1229  TRACE(_T("NativeParserBase::GenerateResultSet_1()"));
1230 
1231  Token* parent = tree->at(parentIdx);
1232  if (s_DebugSmartSense)
1233  CCLogger::Get()->DebugLog(F(_("GenerateResultSet() search '%s', parent='%s (id:%d, type:%s), isPrefix=%d'"),
1234  target.wx_str(),
1235  parent ? parent->m_Name.wx_str() : wxString(_T("Global namespace")).wx_str(),
1236  parent ? parent->m_Index : 0,
1237  parent ? parent->GetTokenKindString().wx_str() : 0,
1238  isPrefix ? 1 : 0));
1239 
1240  // parent == null means we are searching in the global scope
1241  if (parent)
1242  {
1243  // we got a parent; add its children
1244  for (TokenIdxSet::const_iterator it = parent->m_Children.begin(); it != parent->m_Children.end(); ++it)
1245  {
1246  const Token* token = tree->at(*it);
1247  if (token && MatchType(token->m_TokenKind, kindMask))
1248  {
1249  if (MatchText(token->m_Name, target, caseSens, isPrefix))
1250  result.insert(*it);
1251  else if (token && token->m_TokenKind == tkNamespace && token->m_Aliases.size()) // handle namespace aliases
1252  {
1253  for (size_t i = 0; i < token->m_Aliases.size(); ++i)
1254  {
1255  if (MatchText(token->m_Aliases[i], target, caseSens, isPrefix))
1256  {
1257  result.insert(*it);
1258  // break; ?
1259  }
1260  }
1261  }
1262  else if (token && token->m_TokenKind == tkEnum) // check enumerators for match too
1263  // All functions that call the recursive GenerateResultSet should already entered a critical section.
1264  GenerateResultSet(tree, target, *it, result, caseSens, isPrefix, kindMask);
1265  }
1266  }
1267  // now go up the inheritance chain and add all ancestors' children too
1268  tree->RecalcInheritanceChain(parent);
1269  for (TokenIdxSet::const_iterator it = parent->m_Ancestors.begin(); it != parent->m_Ancestors.end(); ++it)
1270  {
1271  const Token* ancestor = tree->at(*it);
1272  if (!ancestor)
1273  continue;
1274  for (TokenIdxSet::const_iterator it2 = ancestor->m_Children.begin(); it2 != ancestor->m_Children.end(); ++it2)
1275  {
1276  const Token* token = tree->at(*it2);
1277  if (token && MatchType(token->m_TokenKind, kindMask))
1278  {
1279  if (MatchText(token->m_Name, target, caseSens, isPrefix))
1280  result.insert(*it2);
1281  else if (token && token->m_TokenKind == tkNamespace && token->m_Aliases.size()) // handle namespace aliases
1282  {
1283  for (size_t i = 0; i < token->m_Aliases.size(); ++i)
1284  {
1285  if (MatchText(token->m_Aliases[i], target, caseSens, isPrefix))
1286  {
1287  result.insert(*it2);
1288  // break; ?
1289  }
1290  }
1291  }
1292  else if (token && token->m_TokenKind == tkEnum) // check enumerators for match too
1293  // All functions that call the recursive GenerateResultSet should already entered a critical section.
1294  GenerateResultSet(tree, target, *it2, result, caseSens, isPrefix, kindMask);
1295  }
1296  }
1297  }
1298  }
1299  else
1300  {
1301  // all global tokens
1302  const TokenList* tl = tree->GetTokens();
1303  for (TokenList::const_iterator it = tl->begin(); it != tl->end(); ++it)
1304  {
1305  const Token* token = *it;
1306  if (token && token->m_ParentIndex == -1)
1307  {
1308  if (token && MatchType(token->m_TokenKind, kindMask))
1309  {
1310  if (MatchText(token->m_Name, target, caseSens, isPrefix))
1311  result.insert(token->m_Index);
1312  else if (token && token->m_TokenKind == tkNamespace && token->m_Aliases.size()) // handle namespace aliases
1313  {
1314  for (size_t i = 0; i < token->m_Aliases.size(); ++i)
1315  {
1316  if (MatchText(token->m_Aliases[i], target, caseSens, isPrefix))
1317  {
1318  result.insert(token->m_Index);
1319  // break; ?
1320  }
1321  }
1322  }
1323  else if (token && token->m_TokenKind == tkEnum) // check enumerators for match too
1324  // All functions that call the recursive GenerateResultSet should already entered a critical section.
1325  GenerateResultSet(tree, target, token->m_Index, result, caseSens, isPrefix, kindMask);
1326  }
1327  }
1328  }
1329  }
1330 
1331  // done
1332  return result.size();
1333 }
1334 
1335 // No critical section needed in this recursive function!
1336 // All functions that call this recursive function, should already entered a critical section.
1401  const wxString& target,
1402  const TokenIdxSet& parentSet,
1403  TokenIdxSet& result,
1404  bool caseSens,
1405  bool isPrefix,
1406  cb_unused short int kindMask)
1407 {
1408  if (!tree) return 0;
1409 
1410  TRACE(_T("NativeParserBase::GenerateResultSet_2()"));
1411 
1412  if (target.IsEmpty())
1413  {
1414  for (TokenIdxSet::const_iterator ptr = parentSet.begin(); ptr != parentSet.end(); ++ptr)
1415  {
1416  size_t parentIdx = (*ptr);
1417  Token* parent = tree->at(parentIdx);
1418  if (!parent)
1419  continue;
1420 
1421  for (TokenIdxSet::const_iterator it = parent->m_Children.begin();
1422  it != parent->m_Children.end();
1423  ++it)
1424  {
1425  const Token* token = tree->at(*it);
1426  if (!token)
1427  continue;
1428  if ( !AddChildrenOfUnnamed(tree, token, result) )
1429  {
1430  result.insert(*it);
1431  AddChildrenOfEnum(tree, token, result);
1432  }
1433  }
1434 
1435  tree->RecalcInheritanceChain(parent);
1436 
1437  for (TokenIdxSet::const_iterator it = parent->m_Ancestors.begin();
1438  it != parent->m_Ancestors.end();
1439  ++it)
1440  {
1441  const Token* ancestor = tree->at(*it);
1442  if (!ancestor)
1443  continue;
1444  for (TokenIdxSet::const_iterator it2 = ancestor->m_Children.begin();
1445  it2 != ancestor->m_Children.end();
1446  ++it2)
1447  {
1448  const Token* token = tree->at(*it2);
1449  if (!token)
1450  continue;
1451  if ( !AddChildrenOfUnnamed(tree, token, result) )
1452  {
1453  result.insert(*it2);
1454  AddChildrenOfEnum(tree, token, result);
1455  }
1456  }
1457  }
1458  }
1459  }
1460  else
1461  {
1462  // we use FindMatches to get the items from tree directly and eliminate the
1463  // items which are not under the search scope.
1464  TokenIdxSet textMatchSet, tmpMatches;
1465  if (tree->FindMatches(target, tmpMatches, caseSens, isPrefix))
1466  {
1467  TokenIdxSet::const_iterator it;
1468  for (it = tmpMatches.begin(); it != tmpMatches.end(); ++it)
1469  {
1470  const Token* token = tree->at(*it);
1471  if (token)
1472  textMatchSet.insert(*it);
1473  }
1474  }
1475  // eliminate the tokens.
1476  if (!textMatchSet.empty())
1477  {
1478  TRACE(_T("Find %lu valid text matched tokens from the tree."),
1479  static_cast<unsigned long>(textMatchSet.size()));
1480 
1481  // get the tokens under the search scope. Note: tokens can have the same names, but we are
1482  // only interests those under the search scope, here the search scope is the parentSet,
1483  // So, the outer loop is the parentSet, which is the search scope
1484  for (TokenIdxSet::const_iterator parentIterator = parentSet.begin();
1485  parentIterator != parentSet.end();
1486  ++parentIterator)
1487  {
1488  // to make it clear, parentIdx stands for search scope. (Token Idx)
1489  // (*it) stand for matched item id.
1490  int parentIdx = (*parentIterator);
1491 
1492  // The inner loop is the textMatchSet
1493  for (TokenIdxSet::const_iterator it = textMatchSet.begin();
1494  it != textMatchSet.end();
1495  ++it)
1496  {
1497  const Token* token = tree->at(*it);
1498  // check whether its under the parentIdx
1499  // NOTE: check for unnamed or enum inside class.
1500  // eg, 'ParserCommon::ParserState::ptCreateParser' should be accessed as
1501  // 'ParserCommon::ptCreateParser'.
1502  // Here, token is ptCreateParser and parentIdx is ParserCommon, so
1503  // 'token->m_ParentIndex == parentIdx' is false. Now, we iterate over the
1504  // children of parentIdx and check if any of them is unnamed or enum
1505  // and match with token->m_ParentIndex. Thus if we confirm that 'token' is a
1506  // child of unnamed or enum(i.e., m_ParentIndex), we add the token to result.
1507  if (token && ((token->m_ParentIndex == parentIdx)
1508  || IsChildOfUnnamedOrEnum(tree, token->m_ParentIndex, parentIdx)))
1509  result.insert(*it);
1510 
1511  // "result" will become the search scope for the next loop, so
1512  // if the parentIdx has ancestors, we need to add them too.
1513  if (parentIdx != -1) //global namespace does not have ancestors
1514  {
1515  Token* tokenParent = tree->at(parentIdx);
1516  if (tokenParent)
1517  {
1518  // Here, we are going to calculate all tk's ancestors
1519  // Finally we will add them in the "result".
1520  tree->RecalcInheritanceChain(tokenParent);
1521 
1522  // This is somewhat tricky, for example, we have one tk, which has the
1523  // tk->m_AncestorsString == wxNavigationEnabled<wxWindow>
1524  // Normally, the wxNavigationEnabled will be added, but if we have:
1525  // template <class W>
1526  // class wxNavigationEnabled : public W
1527  // Shall we add the "W" as tk's ancestors? W is a formalTemplateArgument
1528 
1529  // Add tk's ancestors
1530  for ( TokenIdxSet::const_iterator ancestorIterator = tokenParent->m_Ancestors.begin();
1531  ancestorIterator != tokenParent->m_Ancestors.end();
1532  ++ancestorIterator )
1533  {
1534  // NOTE: check for unnamed or enum inside class (see note above).
1535  if (token && ((token->m_ParentIndex == (*ancestorIterator)) //matched
1536  || IsChildOfUnnamedOrEnum(tree, token->m_ParentIndex, (*ancestorIterator))))
1537  result.insert(*it);
1538  }
1539  }
1540  }
1541  else if (-1 == parentIdx)
1542  {
1543  //if the search scope is global,and the token's parent token kind is tkEnum ,we add them too.
1544  const Token* parentToken = tree->at(token->m_ParentIndex);
1545  if (parentToken && parentToken->m_TokenKind == tkEnum)
1546  result.insert(*it);
1547  }
1548 
1549  // Check if allocator class tokens should be added to the search scope.
1550  // allocator holds the typedefs that CC needs to handle STL containers.
1551  // An allocator token will be added if parentIdx is a child of an allocator dependent class.
1552  // Most STL containers are dependent on allocator.
1553  //
1554  // For example, suppose we are completing:
1555  // vector<string> AAA;
1556  // AAA.back().
1557  //
1558  // Here, parentIdx == "back()", which is a child of the allocator dependent class, vector.
1559  // So we add (*it) to the search scope if it is an allocator token.
1560  if (token && IsAllocator(tree, token->m_ParentIndex)
1561  && DependsOnAllocator(tree, parentIdx))
1562  result.insert(*it);
1563  }
1564  }
1565  }
1566  else
1567  {
1568  // We need to handle namespace aliases too. I hope we can find a good way to do this.
1569  // TODO: Handle template class here.
1570  if (parentSet.count(-1))
1571  {
1572  const TokenList* tl = tree->GetTokens();
1573  for (TokenList::const_iterator it = tl->begin(); it != tl->end(); ++it)
1574  {
1575  const Token* token = (*it);
1576  if (token && token->m_TokenKind == tkNamespace && token->m_Aliases.size())
1577  {
1578  for (size_t i = 0; i < token->m_Aliases.size(); ++i)
1579  {
1580  if (token->m_Aliases[i] == target)
1581  {
1582  result.insert(token->m_Index);
1583  // break; ?
1584  }
1585  }
1586  }
1587  }
1588  }
1589  }
1590  }
1591 
1592  return result.size();
1593 }
1594 
1595 // No critical section needed in this function!
1596 // All functions that call this function, should already entered a critical section.
1598  const int& id)
1599 {
1600  if (!tree)
1601  return false;
1602 
1603  const Token* token = tree->at(id);
1604  return (token && token->m_Name.IsSameAs(_T("allocator")));
1605 }
1606 
1607 // No critical section needed in this recursive function!
1608 // All functions that call this recursive function, should already entered a critical section.
1609 //
1610 // Currently, this function only identifies STL containers dependent on allocator.
1612  const int& id)
1613 {
1614  if (!tree)
1615  return false;
1616 
1617  const Token* token = tree->at(id);
1618  if (!token)
1619  return false;
1620 
1621  // If the STL class depends on allocator, it will have the form:
1622  // template <typename T, typename _Alloc = std::allocator<T> > class AAA { ... };
1623  if (token->m_TemplateArgument.Find(_T("_Alloc")) != wxNOT_FOUND)
1624  return true;
1625 
1626  // The STL class could also be a container adapter:
1627  // template <typename T, typename _Sequence = AAA<T> > class BBB { ... };
1628  // where AAA depends on allocator.
1629  if (token->m_TemplateArgument.Find(_T("_Sequence")) != wxNOT_FOUND)
1630  return true;
1631 
1632  return DependsOnAllocator(tree, token->m_ParentIndex);
1633 }
1634 
1636  TokenIdxSet& actualTypeScope,
1637  TokenTree* tree)
1638 {
1640 
1641  for (TokenIdxSet::const_iterator pScope=searchScope.begin(); pScope!=searchScope.end(); ++pScope)
1642  {
1643  actualTypeScope.insert(*pScope);
1644  // we need to pScope's parent scope too.
1645  if ((*pScope) != -1)
1646  {
1647  const Token* token = tree->at(*pScope);
1648  if (!token)
1649  continue;
1650  const Token* parent = tree->at(token->m_ParentIndex);
1651  while (true)
1652  {
1653  if (!parent)
1654  break;
1655  actualTypeScope.insert(parent->m_Index);
1656  parent = tree->at(parent->m_ParentIndex);
1657  }
1658  }
1659  }
1660 
1662 }
1663 
1664 // No critical section needed in this recursive function!
1665 // All functions that call this function, should already entered a critical section.
1667  const TokenIdxSet& tokens,
1668  size_t curLine,
1669  const wxString& file)
1670 {
1671  TRACE(_T("NativeParserBase::GetTokenFromCurrentLine()"));
1672 
1673  int result = -1;
1674  bool found = false;
1675  if (!tree)
1676  return result;
1677 
1678  const size_t fileIdx = tree->InsertFileOrGetIndex(file);
1679  const Token* classToken = nullptr;
1680  for (TokenIdxSet::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
1681  {
1682  const Token* token = tree->at(*it);
1683  if (!token)
1684  continue;
1685 
1686  TRACE(_T("GetTokenFromCurrentLine() Iterating: tN='%s', tF='%s', tStart=%u, tEnd=%u"),
1687  token->DisplayName().wx_str(), token->GetFilename().wx_str(),
1688  token->m_ImplLineStart, token->m_ImplLineEnd);
1689 
1690  if ( token->m_TokenKind & tkAnyFunction
1691  && token->m_ImplFileIdx == fileIdx
1692  && token->m_ImplLine <= curLine
1693  && token->m_ImplLineEnd >= curLine)
1694  {
1695  TRACE(_T("GetTokenFromCurrentLine() tkAnyFunction : tN='%s', tF='%s', tStart=%u, tEnd=%u"),
1696  token->DisplayName().wx_str(), token->GetFilename().wx_str(),
1697  token->m_ImplLineStart, token->m_ImplLineEnd);
1698  result = token->m_Index;
1699  found = true;
1700  }
1701  else if ( token->m_TokenKind == tkConstructor
1702  && token->m_ImplFileIdx == fileIdx
1703  && token->m_ImplLine <= curLine
1704  && token->m_ImplLineStart >= curLine)
1705  {
1706  TRACE(_T("GetTokenFromCurrentLine() tkConstructor : tN='%s', tF='%s', tStart=%u, tEnd=%u"),
1707  token->DisplayName().wx_str(), token->GetFilename().wx_str(),
1708  token->m_ImplLineStart, token->m_ImplLineEnd);
1709  result = token->m_Index;
1710  found = true;
1711  }
1712  else if ( token->m_TokenKind == tkClass
1713  && token->m_ImplLineStart <= curLine
1714  && token->m_ImplLineEnd >= curLine)
1715  {
1716  TRACE(_T("GetTokenFromCurrentLine() tkClass : tN='%s', tF='%s', tStart=%u, tEnd=%u"),
1717  token->DisplayName().wx_str(), token->GetFilename().wx_str(),
1718  token->m_ImplLineStart, token->m_ImplLineEnd);
1719  classToken = token;
1720  continue;
1721  }
1722 
1723  if (found) break; // exit for-loop
1724 
1725  TRACE(_T("GetTokenFromCurrentLine() Function out of bounds: tN='%s', tF='%s', tStart=%u, ")
1726  _T("tEnd=%u, line=%lu (size_t)line=%lu"), token->DisplayName().wx_str(),
1727  token->GetFilename().wx_str(), token->m_ImplLineStart, token->m_ImplLineEnd,
1728  static_cast<unsigned long>(curLine), static_cast<unsigned long>(curLine));
1729  }
1730 
1731  if (classToken)
1732  result = classToken->m_Index;
1733 
1734  return result;
1735 }
1736 
1738  const TokenIdxSet& tokens,
1739  wxArrayString& items)
1740 {
1742 
1743  for (TokenIdxSet::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
1744  {
1745  const Token* token = tree->at(*it);
1746  if (!token)
1747  continue;
1748 
1749  // support constructor call tips
1750  if (token->m_TokenKind == tkVariable)
1751  {
1752  TokenIdxSet classes;
1753  tree->FindMatches(token->m_BaseType, classes, true, false, tkClass);
1754  for (TokenIdxSet::const_iterator clIt = classes.begin(); clIt != classes.end(); ++clIt)
1755  {
1756  const Token* tk = tree->at(*clIt);
1757  if (tk)
1758  {
1759  token = tk;
1760  break;
1761  }
1762  }
1763  }
1764  if (token->m_TokenKind == tkClass)
1765  {
1766  for (TokenIdxSet::iterator chIt = token->m_Children.begin();
1767  chIt != token->m_Children.end();
1768  ++chIt)
1769  {
1770  const Token* tk = tree->at(*chIt);
1771  if ( tk && ( tk->m_TokenKind == tkConstructor
1772  || (tk->m_IsOperator && tk->m_Name.EndsWith(wxT("()"))) )
1773  && (tk->m_Scope == tsPublic || tk->m_Scope == tsUndefined) )
1774  {
1775  wxString tkTip;
1776  if (PrettyPrintToken(tree, tk, tkTip))
1777  items.Add(tkTip);
1778  }
1779  }
1780  continue;
1781  }
1782 
1783  // support macro call tips
1784  // NOTE: improved to support more advanced cases: preprocessor token mapped to
1785  // function / macro name or variable name (for typedef'd function ptr). Eg,
1786  // #define __MINGW_NAME_AW(func) func##A
1787  // #define MessageBox __MINGW_NAME_AW(MessageBox)
1788  // MessageBox( // --> Use calltip for MessageBoxA().
1789  // see details in
1790  // http://forums.codeblocks.org/index.php/topic,19278.msg133989.html#msg133989
1791 
1792  // only handle variable like macro definitions
1793  if (token->m_TokenKind == tkMacroDef && token->m_Args.empty())
1794  {
1795  // NOTE: we use m_FullType for our search so that we accept function / macro NAMES only,
1796  // any actual calls will be rejected (i.e., allow "#define MessageBox MessageBoxA", but
1797  // not "#define MessageBox MessageBoxA(...)"
1798  const Token* tk = tree->at(tree->TokenExists(token->m_FullType, -1,
1800 
1801  // either a function or a variable, but it is OK if a macro with not empty m_Args.
1802  if (tk && ((tk->m_TokenKind ^ tkMacroDef) || !tk->m_Args.empty()))
1803  token = tk; // tkVariable could be a typedef'd function ptr (checked in PrettyPrintToken())
1804  else
1805  {
1806  // a variable like macro, this token don't have m_Args(call tip information), but
1807  // if we try to expand the token, and finally find some one who do have m_Args, then
1808  // the expanded token's m_Args can used as call tips.
1809  Tokenizer smallTokenizer(tree);
1810  smallTokenizer.InitFromBuffer(token->m_FullType + _T('\n'));
1811  tk = tree->at(tree->TokenExists(smallTokenizer.GetToken(), -1, tkFunction|tkMacroDef|tkVariable));
1812  // only if the expanded result is a single token
1813  if (tk && smallTokenizer.PeekToken().empty())
1814  token = tk;
1815  }
1816  }
1817 
1818  wxString tkTip;
1819  if ( !PrettyPrintToken(tree, token, tkTip) )
1820  tkTip = wxT("Error while pretty printing token!");
1821  items.Add(tkTip);
1822 
1823  }// for
1824 
1826 }
1827 
1829  const Token* token,
1830  wxString& result,
1831  bool isRoot)
1832 {
1833  wxString name = token->m_Name;
1834  // a variable basically don't have call tips, but if it's type is a typedef'd function
1835  // pointer, we can still have call tips (which is the typedef function's arguments)
1836  if (token->m_TokenKind == tkVariable)
1837  {
1838  const Token* tk = tree->at(tree->TokenExists(token->m_BaseType, token->m_ParentIndex, tkTypedef));
1839  if (!tk && token->m_ParentIndex != -1)
1840  tk = tree->at(tree->TokenExists(token->m_BaseType, -1, tkTypedef));
1841  if (tk && !tk->m_Args.empty()) // typedef'd function pointer
1842  {
1843  name = token->m_Name;
1844  token = tk;
1845  }
1846  }
1847 
1848  // if the token has parents and the token is a container or a function,
1849  // then pretty print the parent of the token->
1850  if ( (token->m_ParentIndex != -1)
1851  && (token->m_TokenKind & (tkAnyContainer | tkAnyFunction)) )
1852  {
1853  const Token* parentToken = tree->at(token->m_ParentIndex);
1854  if (!parentToken || !PrettyPrintToken(tree, parentToken, result, false))
1855  return false;
1856  }
1857 
1858  switch (token->m_TokenKind)
1859  {
1860  case tkConstructor:
1861  result = result + token->m_Name + token->GetFormattedArgs();
1862  return true;
1863 
1864  case tkFunction:
1865  result = token->m_FullType + wxT(" ") + result + token->m_Name + token->GetFormattedArgs();
1866  if (token->m_IsConst)
1867  result += wxT(" const");
1868  if (token->m_IsNoExcept)
1869  result += wxT(" noexcept");
1870  return true;
1871 
1872  case tkClass:
1873  case tkNamespace:
1874  if (isRoot)
1875  result += token->m_Name;
1876  else
1877  result += token->m_Name + wxT("::");
1878  return true;
1879 
1880  case tkMacroDef:
1881  if (!token->GetFormattedArgs().IsEmpty())
1882  result = wxT("#define ") + token->m_Name + token->GetFormattedArgs();
1883  return true;
1884 
1885  case tkTypedef:
1886  result = token->m_BaseType + wxT(" ") + result + name + token->GetFormattedArgs();
1887  return true;
1888 
1889  case tkEnum:
1890  case tkDestructor:
1891  case tkVariable:
1892  case tkEnumerator:
1893  case tkMacroUse:
1894  case tkAnyContainer:
1895  case tkAnyFunction:
1896  case tkUndefined:
1897  default:
1898  break;
1899  }
1900  return true;
1901 }
std::vector< Token * > TokenList
Definition: tokentree.h:22
wxString F(const wxChar *msg,...)
sprintf-like function
Definition: logmanager.h:20
void ResolveTemplateMap(TokenTree *tree, const wxString &searchStr, const TokenIdxSet &actualTypeScope, TokenIdxSet &initialScope)
resolve template map [formal parameter] to [actual parameter]
size_t GenerateResultSet(TokenTree *tree, const wxString &target, int parentIdx, TokenIdxSet &result, bool caseSens=true, bool isPrefix=false, short int kindMask=0xFFFF)
Generate the matching results under the Parent Token index set.
std::map< wxString, wxString > m_TemplateMap
a string to string map from formal template argument to actual template argument
Definition: token.h:291
destructor class member function
Definition: token.h:51
int TokenExists(const wxString &name, int parent, short int kindMask)
query tokens by names
Definition: tokentree.cpp:141
static bool IsOperatorPointer(int startAt, const wxString &line)
static bool IsOperatorDot(int startAt, const wxString &line)
check whether line[startAt] is a dot character
wxMutex s_TokenTreeMutex
Definition: tokentree.cpp:49
variable
Definition: token.h:57
namespace
Definition: token.h:34
int m_ParentIndex
Parent Token index.
Definition: token.h:265
const_iterator begin() const
constructor class member function
Definition: token.h:48
size_t InsertFileOrGetIndex(const wxString &filename)
put the filename in the m_FilenameMap, and return the file index, if this file is already in the m_Fi...
Definition: tokentree.cpp:835
class or struct
Definition: token.h:37
size_t ResolveExpression(TokenTree *tree, std::queue< ParserComponent > components, const TokenIdxSet &searchScope, TokenIdxSet &result, bool caseSense=true, bool isPrefix=false)
A statement(expression) is expressed by a ParserComponent queue We do a match from the left of the qu...
virtual ~NativeParserBase()
Destructor.
wxString GetFormattedArgs() const
remove all &#39; &#39; in the original function argument string
Definition: token.cpp:199
Token * at(int idx)
Definition: tokentree.h:51
ParserComponent m_LastComponent
wxString m_BaseType
this is what the parser believes is the actual return value: e.g.
Definition: token.h:185
static CCLogger * Get()
Definition: cclogger.cpp:60
wxString m_Name
Token&#39;s name, it can be searched in the TokenTree.
Definition: token.h:188
unsigned int m_ImplLine
function implementation line index
Definition: token.h:219
typedef, note typedefs are stored as classes inheriting from the typedef&#39;d type, this takes advantage...
Definition: token.h:45
size_t length() const
bool AddChildrenOfEnum(TokenTree *tree, const Token *parent, TokenIdxSet &result)
wxString GetNextCCToken(const wxString &line, unsigned int &startAt, OperatorType &tokenOperatorType)
helper function to read the next CCToken, begin from the startAt, this point to a non-space character...
static bool IsOperatorBegin(int startAt, const wxString &line)
check if startAt point to "->" or "::" operator
container like tokens, those tokens can have children tokens
Definition: token.h:70
wxString GetFilename() const
get a full path of the file which contains the current Token
Definition: token.cpp:185
void CleanupSearchScope(TokenTree *tree, TokenIdxSet *searchScope)
remove all the container tokens in the token index set.
bool MatchText(const wxString &text, const wxString &target, bool caseSens, bool isPrefix)
void FindCurrentFunctionScope(TokenTree *tree, const TokenIdxSet &procResult, TokenIdxSet &scopeResult)
if the expression return the container tokens, which are the parent of the expression.
size_t BreakUpComponents(const wxString &actual, std::queue< ParserComponent > &components)
break a statement to several ParserComponents, and store them in a queue.
a container class to hold all the Tokens getting from parsing stage
Definition: tokentree.h:37
TokenIdxSet m_Children
if it is a class kind token, then it contains all the member tokens
Definition: token.h:268
unsigned int m_ImplLineStart
if token is impl, opening brace line
Definition: token.h:222
TokenIdxSet m_Ancestors
all the ancestors in the inheritance hierarchy
Definition: token.h:271
#define _T(string)
int m_Index
current Token index in the tree, it is index of the std::vector<Token*>, so use the index...
Definition: token.h:262
static bool IsOpeningBracket(int startAt, const wxString &line)
Test whether the current character is a &#39;(&#39; or &#39;[&#39;.
unsigned int m_ImplLineEnd
if token is impl, closing brace line
Definition: token.h:225
size_t FindAIMatches(TokenTree *tree, std::queue< ParserComponent > components, TokenIdxSet &result, int parentTokenIdx=-1, bool isPrefix=false, bool caseSensitive=false, bool use_inheritance=true, short int kindMask=0xFFFF, TokenIdxSet *search_scope=0)
Artificial Intelligence Matching.
wxString & Remove(size_t pos)
bool m_IsNoExcept
the member method is noexcept (yes/no)
Definition: token.h:251
bool MatchType(TokenKind kind, short int kindMask)
wxArrayString m_Aliases
used for namespace aliases
Definition: token.h:280
#define wxT(string)
This is just a simple lexer class.
Definition: tokenizer.h:64
int FindFunctionOpenParenthesis(const wxString &calltip)
Finds the position of the opening parenthesis marking the beginning of the params.
TokenScope m_Scope
public? private? protected?
Definition: token.h:231
#define wxNOT_FOUND
wxString DisplayName() const
a short simple string to show the token information, this usually generate for show the tip message w...
Definition: token.cpp:80
bool m_IsOperator
is operator overload function?
Definition: token.h:237
bool AddChildrenOfUnnamed(TokenTree *tree, const Token *parent, TokenIdxSet &result)
collect child tokens of the specified token, the specified token must be unnamed. ...
bool empty() const
void DebugLog(const wxString &msg)
Definition: cclogger.cpp:107
int GetTokenFromCurrentLine(TokenTree *tree, const TokenIdxSet &tokens, size_t curLine, const wxString &file)
used to get the correct token index in current line, e.g.
void Reset()
Init cc search member variables.
void RecalcInheritanceChain(Token *token)
convert the Token&#39;s ancestor string to it&#39;s IDs this contains recursive calls, for example in such co...
Definition: tokentree.cpp:643
bool empty()
check to see whether the TokenTree is empty
Definition: tokentree.h:63
wxUSE_UNICODE_dependent wxChar
void RemoveLastFunctionChildren(TokenTree *tree, int &lastFuncTokenIdx)
Remove the last function&#39;s children, when doing codecompletion in a function body, the function body up to the caret position was parsed, and the local variables defined in the function were recorded as the function&#39;s children.
bool PrettyPrintToken(TokenTree *tree, const Token *token, wxString &result, bool isRoot=true)
For ComputeCallTip() No critical section needed in this recursive function! All functions that call t...
wxString GetCCToken(wxString &line, ParserTokenType &tokenType, OperatorType &tokenOperatorType)
helper function to split the statement
value_type GetValue() const
a symbol found in the parsed files, it can be many kinds, such as a variable, a class and so on...
Definition: token.h:82
wxString & RemoveLast(size_t n=1)
std::set< int, std::less< int > > TokenIdxSet
Definition: token.h:16
wxString PeekToken()
Do a "look ahead", and return the next token string.
Definition: tokenizer.cpp:869
size_t ResolveActualType(TokenTree *tree, wxString searchText, const TokenIdxSet &searchScope, TokenIdxSet &result)
Get the Type information of the searchText string.
wxString m_TemplateAlias
alias for templates, e.g.
Definition: token.h:294
static int AfterWhitespace(int startAt, const wxString &line)
search from left to right, move the cursor to the first character after the space ...
bool IsSameAs(const wxString &s, bool caseSensitive=true) const
static bool IsClosingBracket(int startAt, const wxString &line)
check the current char (line[startAt]) is either &#39;)&#39; or &#39;]&#39;
std::map< wxString, wxString > m_TemplateMap
bool m_IsConst
the member method is const (yes/no)
Definition: token.h:248
OperatorType
the delimiter separating two Parser Component, See ParserComponent struct for more details ...
#define CC_LOCKER_TRACK_TT_MTX_UNLOCK(M)
Definition: cclogger.h:165
const wxStringCharType * wx_str() const
bool InitFromBuffer(const wxString &buffer, const wxString &fileOfBuffer=wxEmptyString, size_t initLineNumber=0)
Initialize the buffer by directly using a wxString&#39;s content.
Definition: tokenizer.cpp:174
const TokenList * GetTokens() const
Protected access to internal lists / maps.
Definition: tokentree.h:180
wxString wxEmptyString
bool s_DebugSmartSense
if this option is enabled, there will be many log messages when doing semantic match ...
bool HasChildren() const
check if the token has any child tokens.
Definition: token.h:113
bool DependsOnAllocator(TokenTree *tree, const int &id)
Test if token with this id depends on allocator class.
void ComputeCallTip(TokenTree *tree, const TokenIdxSet &tokens, wxArrayString &items)
call tips are tips when you are entering some functions, such as you have a class definition ...
const wxString & _(const wxString &string)
static bool IsOperatorEnd(int startAt, const wxString &line)
check startAt is at some character like:
wxString m_Args
If it is a function Token, then this value is function arguments, e.g.
Definition: token.h:194
unsigned int m_ImplFileIdx
function implementation file index
Definition: token.h:216
#define CC_LOCKER_TRACK_TT_MTX_LOCK(M)
Definition: cclogger.h:159
static int BeginOfToken(int startAt, const wxString &line)
go to the first character of the identifier, e.g
wxString m_TemplateArgument
template argument list, comma separated list string
Definition: token.h:283
static int BeforeToken(int startAt, const wxString &line)
undefined or just "all"
Definition: token.h:76
enum
Definition: token.h:40
wxString & erase(size_type pos=0, size_type n=npos)
bool IsEmpty() const
void Clear()
enumerator
Definition: token.h:60
size_t Len() const
any kind of functions
Definition: token.h:73
bool DeleteAllChildren()
delete all the child tokens of the current token, not only remove the relation, but also delete the T...
Definition: token.cpp:275
TokenKind m_TokenKind
See TokenKind class.
Definition: token.h:234
static bool InsideToken(int startAt, const wxString &line)
check whether the line[startAt] point to the identifier
const_iterator end() const
bool EndsWith(const wxString &suffix, wxString *rest=NULL) const
general function, not constructor nor destructor
Definition: token.h:54
unsigned int FindCCTokenStart(const wxString &line)
helper function to split the statement
ParserTokenType
divide a statement to several pieces(parser component), each component has a type member ...
a long statement can be divided to a ParserComponent chain.
size_t Add(const wxString &str, size_t copies=1)
const wxString ptr(_T("*"))
static int BeforeWhitespace(int startAt, const wxString &line)
move to the char before whitespace and tabs, e.g.
void AddConstructors(TokenTree *tree, const TokenIdxSet &source, TokenIdxSet &dest)
loop on the input Token index set (source), add all its public constructors to output Token index set...
size_t FindMatches(const wxString &query, TokenIdxSet &result, bool caseSensitive, bool is_prefix, TokenKind kindMask=tkUndefined)
find a collection of matched tokens
Definition: tokentree.cpp:266
void GetCallTipHighlight(const wxString &calltip, int *start, int *end, int typedCommas)
Returns the start and end of the call-tip highlight region.
int Find(wxUniChar ch, bool fromEnd=false) const
wxUniChar GetChar(size_t n) const
wxUniChar Last() const
macro definition, such as: #define AAA(x,y) f(x,y), where AAA is a token of tkMacroDef ...
Definition: token.h:63
void AddTemplateAlias(TokenTree *tree, const int &id, const TokenIdxSet &actualTypeScope, TokenIdxSet &initialScope)
add template parameter, get the actual parameter from the formal parameter list
bool IsAllocator(TokenTree *tree, const int &id)
Test if token with this id is allocator class.
bool IsChildOfUnnamedOrEnum(TokenTree *tree, const int targetIdx, const int parentIdx)
check to see if the token is an unnamed class or enum under the parent token
void ResolveOperator(TokenTree *tree, const OperatorType &tokenOperatorType, const TokenIdxSet &tokens, const TokenIdxSet &searchScope, TokenIdxSet &result)
used to solve the overloaded operator functions return type
Definition: token.h:26
wxString m_FullType
this is the full return value (if any): e.g.
Definition: token.h:182
wxString GetTokenKindString() const
the token kind string, e.g.
Definition: token.cpp:311
void CollectSearchScopes(const TokenIdxSet &searchScope, TokenIdxSet &actualTypeScope, TokenTree *tree)
Collect search scopes, add the searchScopes&#39;s parent scope.
NativeParserBase()
Constructor.
#define TRACE(format, args...)
wxString Mid(size_t first, size_t nCount=wxString::npos) const
wxString GetToken()
Consume and return the current token string.
Definition: tokenizer.cpp:839
the usage of the macro, for example: AAA(1,2)
Definition: token.h:66