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 6 #ifndef NATIVEPARSERBASE_H 7 #define NATIVEPARSERBASE_H 8 9 #if wxCHECK_VERSION(3, 0, 0) 10 #include <wx/wxcrt.h> // wxIsalnum 11 #endif 12 #include <wx/string.h> 13 14 #include <map> 15 #include <queue> 16 17 #include "parser/token.h" 18 #include "parser/tokentree.h" 19 20 /** debug only variable, used to print the AI match related log message */ 21 extern bool s_DebugSmartSense; 22 23 class NativeParserBase 24 { 25 public: 26 /** divide a statement to several pieces(parser component), each component has a type member */ 27 enum ParserTokenType 28 { 29 pttUndefined = 0, 30 pttSearchText, 31 pttClass, 32 pttNamespace, 33 pttFunction 34 }; 35 36 /** the delimiter separating two Parser Component, See ParserComponent struct for more details */ 37 enum OperatorType 38 { 39 otOperatorUndefined = 0, 40 otOperatorSquare, 41 otOperatorParentheses, 42 otOperatorPointer, 43 otOperatorStar 44 }; 45 46 /** @brief a long statement can be divided to a ParserComponent chain. 47 * 48 * e.g. for a statement like below: 49 * @code 50 * Ogre::Root::getSingleton().| 51 * @endcode 52 * 53 * a chains of four ParserComponents will be generated and list below: 54 * @code 55 * Ogre [pttNamespace] 56 * Root [pttClass] 57 * getSingleton [pttFunction] 58 * (empty space) [pttSearchText] 59 * @endcode 60 * 61 * a ParserComponent is mainly an identifier, which we use this identifier name to query on the 62 * Symbol tree, and try to get the matched symbols. 63 * For this example, we first try to search the Symbol tree by the keyword "Ogre", this will 64 * match a symbol which has type "Namespace". 65 * The next step, we search the "Root" under the previous returned Symbols. 66 * In some special cases, such as "array[7]->b", we gives such result 67 * @code 68 * array [pttNamespace] (variable name?) 69 * [] [pttFunction, which is operator[]] 70 * b [pttSearchText] 71 * @endcode 72 */ 73 struct ParserComponent 74 { 75 wxString component; /// name 76 ParserTokenType tokenType; /// type 77 OperatorType tokenOperatorType; /// operator type 78 ParserComponentParserComponent79 ParserComponent() { Clear(); } ClearParserComponent80 void Clear() 81 { 82 component = wxEmptyString; 83 tokenType = pttUndefined; 84 tokenOperatorType = otOperatorUndefined; 85 } 86 }; 87 88 /** Constructor */ 89 NativeParserBase(); 90 91 /** Destructor */ 92 virtual ~NativeParserBase(); 93 94 protected: 95 96 /** Init cc search member variables */ 97 void Reset(); 98 99 /**@brief Artificial Intelligence Matching 100 * 101 * All functions that call this recursive function, should already entered a critical section or 102 * a mutex to protect the TokenTree. 103 * 104 * match (consume) the ParserComponent queue from left to right, 105 * the output result becomes the search scope of the next match. 106 * finally, give the results which match the last ParserComponent. 107 * @param components input ParserComponent queue 108 * @param parentTokenIdx, initial search scope of the left most component, this is the direct 109 * parent of the current statement(expression) 110 * @param fullMatch the result should be a full text match or prefix match 111 * @return matching token number, it is the size of result 112 */ 113 size_t FindAIMatches(TokenTree* tree, 114 std::queue<ParserComponent> components, 115 TokenIdxSet& result, 116 int parentTokenIdx = -1, 117 bool isPrefix = false, 118 bool caseSensitive = false, 119 bool use_inheritance = true, 120 short int kindMask = 0xFFFF, 121 TokenIdxSet* search_scope = 0); 122 123 /** if the expression return the container tokens, which are the 124 * parent of the expression. 125 * @param[in] procResult input function index collection 126 * @param[out] scopeResult filtered output function index collection 127 * For example, if we have such code 128 * @code 129 * class A 130 * { 131 * void f() 132 * { 133 * statement|<-----CC here 134 * }; 135 * } 136 * @endcode 137 * We try to locate the Tokens their scopes "Cover" the "statement" 138 */ 139 void FindCurrentFunctionScope(TokenTree* tree, 140 const TokenIdxSet& procResult, 141 TokenIdxSet& scopeResult); 142 143 /** remove all the container tokens in the token index set. 144 * @param searchScope The Tokens we need to remove from the tree 145 */ 146 void CleanupSearchScope(TokenTree* tree, 147 TokenIdxSet* searchScope); 148 149 /** Returns the start and end of the call-tip highlight region. 150 * For a function prototype "void MyNamespace::SomeClass::func(int a, float b)" 151 * if we have a function call statement "obj->f(x,y)", when we hover on the "y", we should 152 * high light the "float b" in the calltip 153 * @param[in] calltip is the calltip string 154 * @param[out] start the start index of the high light string 155 * @param[out] end the end index of the high light string 156 * @param[in] typedCommas e.g. "func(x, y)", in this case, we say we have typed one comma before 157 * the hovered "y", so we know we need to high light the second parameter, which is "float b" 158 */ 159 void GetCallTipHighlight(const wxString& calltip, 160 int* start, 161 int* end, 162 int typedCommas); 163 164 /** Finds the position of the opening parenthesis marking the beginning of the params. 165 * See GetCallTipHighlight() for more details 166 */ 167 int FindFunctionOpenParenthesis(const wxString& calltip); 168 169 /** helper function to split the statement 170 * 171 * @param line a statement string 172 * @param[out] tokenType the returned type of the string 173 * @param[out] tokenOperatorType if it is a function call token, specify which type of function call 174 * It contains a string on the following form: 175 * @code 176 * char* mychar = SomeNamespace::m_SomeVar.SomeMeth 177 * ^----start from here 178 * @endcode 179 * Usually, the caret is located at the end of the line. 180 * 181 * first we locate the first non-space char starting from the *end*: 182 * @code 183 * char* mychar = SomeNamespace::m_SomeVar.SomeMeth 184 * ^----stop here 185 * @endcode 186 * then we remove everything before it, so we get "SomeNamespace::m_SomeVar.SomeMeth" 187 * 188 * Now we cut the first component "SomeNamespace" and return it. 189 * The statement line becomes: 190 * @code 191 * m_SomeVar.SomeMeth 192 * @endcode 193 * so that if we call this function again with the (modified) line, 194 * we'll return "m_SomeVar" and modify line (again) to become: 195 * @code 196 * SomeMeth 197 * @endcode 198 * and so on and so forth until we return an empty string... 199 * NOTE: if we find () args or [] arrays in our way, we skip them (done in GetNextCCToken)... 200 * todo: it looks like [] is not skipped, because we have to handle the operator[] 201 * also, if we see a aaa(), we always think it is a function call 202 */ 203 wxString GetCCToken(wxString& line, 204 ParserTokenType& tokenType, 205 OperatorType& tokenOperatorType); 206 207 /** helper function to split the statement 208 * @code 209 * " SomeNameSpace::SomeClass.SomeMethod|" 210 * ^ should stop here <------------ ^ start from here, go backward(right to left) 211 * " f(SomeNameSpace::SomeClass.SomeMethod|" 212 * ^ should stop here 213 * @endcode 214 * so, brace level should be considered 215 */ 216 unsigned int FindCCTokenStart(const wxString& line); 217 218 /** helper function to read the next CCToken, begin from the startAt, this point to a non-space 219 * character, and fetch the beginning identifier 220 * @param startAt this will be updated to the char after the identifier 221 * @param tokenOperatorType the type of the operator 222 * E.g. 223 * @code 224 * SomeMethod()-> 225 * ^begin 226 * @endcode 227 * the returned wxString is "SomeMethod", the tokenOperatorType is pointer member access 228 */ 229 wxString GetNextCCToken(const wxString& line, 230 unsigned int& startAt, 231 OperatorType& tokenOperatorType); 232 233 /** Remove the last function's children, when doing codecompletion in a function body, the 234 * function body up to the caret position was parsed, and the local variables defined in 235 * the function were recorded as the function's children. 236 * Note that these tokens are marked as temporary tokens, so if the edit caret moves to another 237 * function body, these temporary tokens should be removed. 238 */ 239 void RemoveLastFunctionChildren(TokenTree* tree, int& lastFuncTokenIdx); 240 241 /** @brief break a statement to several ParserComponents, and store them in a queue. 242 * @param actual a statement string to be divided. 243 * @param components output variable containing the queue. 244 * @return number of ParserComponent 245 */ 246 size_t BreakUpComponents(const wxString& actual, 247 std::queue<ParserComponent>& components); 248 249 /** A statement(expression) is expressed by a ParserComponent queue 250 * We do a match from the left of the queue one by one. 251 * 252 * 253 * Here is a simple description about the algorithm, suppose we have such code snippet 254 * @code 255 * namespace AAA 256 * { 257 * class BBB 258 * { 259 * public: 260 * int m_aaa; 261 * } 262 * class CCC 263 * { 264 * public: 265 * BBB fun(); 266 * } 267 * } 268 * AAA::CCC obj; 269 * obj.fun().|-----we want to get code suggestion list here 270 * @endcode 271 * We first split the statement "obj.fun()." into 3 components: 272 * component name 273 * @code 274 * 1, obj 275 * 2, fun 276 * 3, empty 277 * @endcode 278 * We do three loops here, each loop, we consume one component. Also each loop's result will 279 * serve as the next loop's search scope. 280 * 281 * Loop 1 282 * We first search the tree by the text "obj", we find a matched variable token, which has the 283 * type string "AAA::CCC", then the text "AAA::CCC" is resolved to a class kind token "class CCC" 284 * Loop 2 285 * We search the tree by the text "fun". Here the search scope should be "CCC", it's the result 286 * from the previous loop, so we find that there is a function kind token under "class CCC", 287 * which is "function fun()" token. Then we need to see the return type of the fun() token, 288 * which is the name "BBB". Then we do another text search for "BBB" in the tree, and find a 289 * class kind token "class BBB" 290 * Loop 3 291 * Since the last search text is empty, we just return all the children of the "class BBB" token, 292 * so finally, we give the child variable kind token "m_aaa", then the code suggestion should 293 * prompt the string "m_aaa" 294 * 295 * @param tree the token tree pointer 296 * @param components expression structure expressed in std::queue<ParserComponent> 297 * @param searchScope search scope defined by TokenIdxSet 298 * @param[out] the final result token index 299 * @param caseSense case sensitive match 300 * @param isPrefix match type( full match or prefix match) 301 * @return result tokens count 302 */ 303 size_t ResolveExpression(TokenTree* tree, 304 std::queue<ParserComponent> components, 305 const TokenIdxSet& searchScope, 306 TokenIdxSet& result, 307 bool caseSense = true, 308 bool isPrefix = false); 309 310 /** used to solve the overloaded operator functions return type 311 * @param tokenOperatorType overloaded operator type, could be [], (), -> 312 * @param tokens input tokens set 313 * @param tree Token tree pointer 314 * @param searchScope search scope 315 * @param result output result 316 */ 317 void ResolveOperator(TokenTree* tree, 318 const OperatorType& tokenOperatorType, 319 const TokenIdxSet& tokens, 320 const TokenIdxSet& searchScope, 321 TokenIdxSet& result); 322 323 /** Get the Type information of the searchText string 324 * @param searchText input search text 325 * @param searchScope search scope defined in TokenIdxSet format 326 * @param result result token specify the Type of searchText 327 */ 328 size_t ResolveActualType(TokenTree* tree, 329 wxString searchText, 330 const TokenIdxSet& searchScope, 331 TokenIdxSet& result); 332 333 /** resolve template map [formal parameter] to [actual parameter] 334 * @param searchStr input Search String 335 * @param actualtypeScope Token type(actual parameter) 336 * @param initialScope search scope 337 */ 338 void ResolveTemplateMap(TokenTree* tree, 339 const wxString& searchStr, 340 const TokenIdxSet& actualTypeScope, 341 TokenIdxSet& initialScope); 342 343 /** add template parameter, get the actual parameter from the formal parameter list 344 * @param id template token id 345 * @param actualTypeScope search scope 346 * @param initialScope resolved result 347 * @param tree Token tree pointer. 348 */ 349 void AddTemplateAlias(TokenTree* tree, 350 const int& id, 351 const TokenIdxSet& actualTypeScope, 352 TokenIdxSet& initialScope); 353 354 /** Generate the matching results under the Parent Token index set 355 * 356 * All functions that call this recursive function, should already entered a critical section. 357 * 358 * @param tree TokenTree pointer 359 * @param target Scope (defined in TokenIdxSet) 360 * @param result result token index set 361 * @param isPrefix whether a full match is used or only do a prefix match 362 * @param kindMask define the result tokens filter, such as only class type is OK 363 * @return result token set number 364 */ 365 size_t GenerateResultSet(TokenTree* tree, 366 const wxString& target, 367 int parentIdx, 368 TokenIdxSet& result, 369 bool caseSens = true, 370 bool isPrefix = false, 371 short int kindMask = 0xFFFF); 372 373 /** This function is just like the one above, especially that it use a single parent Token id, 374 * not the parent id set in previous one. 375 * 376 * All functions that call this recursive function, should already entered a critical section. 377 * 378 */ 379 size_t GenerateResultSet(TokenTree* tree, 380 const wxString& target, 381 const TokenIdxSet& ptrParentID, 382 TokenIdxSet& result, 383 bool caseSens = true, 384 bool isPrefix = false, 385 short int kindMask = 0xFFFF); 386 387 /** Test if token with this id is allocator class. 388 * 389 * All functions that call this function, should already entered a critical section. 390 * 391 * @param tree TokenTree pointer 392 * @param id token idx 393 */ 394 bool IsAllocator(TokenTree* tree, 395 const int& id); 396 397 /** Test if token with this id depends on allocator class. 398 * Currently, this function only identifies STL containers dependent on allocator. 399 * 400 * All functions that call this recursive function, should already entered a critical section. 401 * 402 * @param tree TokenTree pointer 403 * @param id token idx 404 */ 405 bool DependsOnAllocator(TokenTree* tree, 406 const int& id); 407 408 /** Collect search scopes, add the searchScopes's parent scope 409 * @param searchScope input search scope 410 * @param actualTypeScope returned search scope 411 * @param tree TokenTree pointer 412 */ 413 void CollectSearchScopes(const TokenIdxSet& searchScope, 414 TokenIdxSet& actualTypeScope, 415 TokenTree* tree); 416 417 /** used to get the correct token index in current line, e.g. 418 * @code 419 * class A 420 * { 421 * void test() 422 * { // start of the function body 423 * | 424 * }; // end of the function body 425 * }; 426 * @endcode 427 * @param tokens all current file's function and class, which cover the current line 428 * @param curLine the line of the current caret position 429 * @param file editor file name 430 */ 431 int GetTokenFromCurrentLine(TokenTree* tree, 432 const TokenIdxSet& tokens, 433 size_t curLine, 434 const wxString& file); 435 436 /** call tips are tips when you are entering some functions, such as you have a class definition 437 * @code 438 * class A { 439 * public: 440 * void A() {}; 441 * void test() { }; 442 * }; 443 * when you are entering some text like 444 * A(| or objA.test(| 445 * @endcode 446 * then there will be a tip window show the function prototype of the function 447 * 448 */ 449 void ComputeCallTip(TokenTree* tree, 450 const TokenIdxSet& tokens, 451 wxArrayString& items); 452 453 /** For ComputeCallTip() 454 * No critical section needed in this recursive function! 455 * All functions that call this recursive function, should already entered a critical section. */ 456 bool PrettyPrintToken(TokenTree* tree, 457 const Token* token, 458 wxString& result, 459 bool isRoot = true); 460 461 // convenient static funcs for fast access and improved readability 462 463 // count commas in lineText (nesting parentheses) CountCommas(const wxString & lineText,int start)464 static int CountCommas(const wxString& lineText, int start) 465 { 466 int commas = 0; 467 int nest = 0; 468 while (true) 469 { 470 wxChar c = lineText.GetChar(start++); 471 if (c == '\0') 472 break; 473 else if (c == '(') 474 ++nest; 475 else if (c == ')') 476 --nest; 477 else if (c == ',' && nest == 1) 478 ++commas; 479 } 480 return commas; 481 } 482 483 /** check whether the line[startAt] point to the identifier 484 * @code 485 * SomeMethod(arg1, arg2)->Method2() 486 * ^^^^^^^^^^ those index will return true 487 * @endcode 488 */ InsideToken(int startAt,const wxString & line)489 static bool InsideToken(int startAt, const wxString& line) 490 { 491 return ( (startAt >= 0) 492 && ((size_t)startAt < line.Len()) 493 && ( (wxIsalnum(line.GetChar(startAt))) 494 || (line.GetChar(startAt) == '_') ) ); 495 } 496 497 /** go to the first character of the identifier, e.g 498 * @code 499 * " f(SomeNameSpace::SomeClass.SomeMethod" 500 * return value^ ^begin 501 * @endcode 502 * this is the index before the first character of the identifier 503 */ BeginOfToken(int startAt,const wxString & line)504 static int BeginOfToken(int startAt, const wxString& line) 505 { 506 while ( (startAt >= 0) 507 && ((size_t)startAt < line.Len()) 508 && ( (wxIsalnum(line.GetChar(startAt))) 509 || (line.GetChar(startAt) == '_') ) ) 510 --startAt; 511 return startAt; 512 } BeforeToken(int startAt,const wxString & line)513 static int BeforeToken(int startAt, const wxString& line) 514 { 515 if ( (startAt > 0) 516 && ((size_t)startAt < line.Len() + 1) 517 && ( (wxIsalnum(line.GetChar(startAt - 1))) 518 || (line.GetChar(startAt - 1) == '_') ) ) 519 --startAt; 520 return startAt; 521 } 522 523 /** check startAt is at some character like: 524 * @code 525 * SomeNameSpace::SomeClass 526 * ^ here is a double colon 527 * SomeObject->SomeMethod 528 * ^ here is a pointer member access operator 529 * @endcode 530 */ IsOperatorEnd(int startAt,const wxString & line)531 static bool IsOperatorEnd(int startAt, const wxString& line) 532 { 533 return ( (startAt > 0) 534 && ((size_t)startAt < line.Len()) 535 && ( ( (line.GetChar(startAt) == '>') 536 && (line.GetChar(startAt - 1) == '-') ) 537 || ( (line.GetChar(startAt) == ':') 538 && (line.GetChar(startAt - 1) == ':') ) ) ); 539 } IsOperatorPointer(int startAt,const wxString & line)540 static bool IsOperatorPointer(int startAt, const wxString& line) 541 { 542 return ( (startAt > 0) 543 && ((size_t)startAt < line.Len()) 544 && ( ( (line.GetChar(startAt) == '>') 545 && (line.GetChar(startAt - 1) == '-') ))); 546 } 547 548 /** check if startAt point to "->" or "::" operator */ 549 // FIXME (ollydbg#1#): should be startAt+1 < line.Len()? IsOperatorBegin(int startAt,const wxString & line)550 static bool IsOperatorBegin(int startAt, const wxString& line) 551 { 552 return ( (startAt >= 0) 553 && ((size_t)startAt < line.Len()) 554 && ( ( (line.GetChar(startAt ) == '-') 555 && (line.GetChar(startAt + 1) == '>') ) 556 || ( (line.GetChar(startAt) == ':') 557 && (line.GetChar(startAt + 1) == ':') ) ) ); 558 } 559 560 /** check whether line[startAt] is a dot character */ IsOperatorDot(int startAt,const wxString & line)561 static bool IsOperatorDot(int startAt, const wxString& line) 562 { 563 return ( (startAt >= 0) 564 && ((size_t)startAt < line.Len()) 565 && (line.GetChar(startAt) == '.') ); 566 } 567 568 /** move to the char before whitespace and tabs, e.g. 569 * @code 570 * SomeNameSpace :: SomeClass 571 * ^end ^begin 572 * note if there some spaces in the beginning like below 573 * " f::" 574 * ^end ^begin 575 * @endcode 576 * the returned index is -1. 577 * @return the cursor after the operation 578 */ BeforeWhitespace(int startAt,const wxString & line)579 static int BeforeWhitespace(int startAt, const wxString& line) 580 { 581 while ( (startAt >= 0) 582 && ((size_t)startAt < line.Len()) 583 && ( (line.GetChar(startAt) == ' ') 584 || (line.GetChar(startAt) == '\t') ) ) 585 --startAt; 586 return startAt; 587 } 588 589 /** search from left to right, move the cursor to the first character after the space 590 * @code 591 * " :: f" 592 * ^begin ^end 593 * @endcode 594 * @param[in] startAt the begin of the cursor 595 * @param[in] line the string buffer 596 * @return the location of the cursor 597 */ AfterWhitespace(int startAt,const wxString & line)598 static int AfterWhitespace(int startAt, const wxString& line) 599 { 600 if (startAt < 0) 601 startAt = 0; 602 while ( ((size_t)startAt < line.Len()) 603 && ( (line.GetChar(startAt) == ' ') 604 || (line.GetChar(startAt) == '\t') ) ) 605 ++startAt; 606 return startAt; 607 } 608 609 /** Test whether the current character is a '(' or '[' 610 * @param startAt the current cursor on the buffer 611 * @return true if test is OK 612 */ IsOpeningBracket(int startAt,const wxString & line)613 static bool IsOpeningBracket(int startAt, const wxString& line) 614 { 615 return ( ((size_t)startAt < line.Len()) 616 && ( (line.GetChar(startAt) == '(') 617 || (line.GetChar(startAt) == '[') ) ); 618 } 619 620 /** check the current char (line[startAt]) is either ')' or ']' */ IsClosingBracket(int startAt,const wxString & line)621 static bool IsClosingBracket(int startAt, const wxString& line) 622 { 623 return ( (startAt >= 0) 624 && ( (line.GetChar(startAt) == ')') 625 || (line.GetChar(startAt) == ']') ) ); 626 } 627 628 protected: 629 630 private: 631 // Helper utilities called only by GenerateResultSet! 632 // No critical section needed! All functions that call these functions, 633 // should already entered a critical section. 634 635 /** @brief collect child tokens of the specified token, the specified token must be unnamed. 636 * 637 * used for GenerateResultSet() function 638 * @param tree TokenTree pointer 639 * @param parent we need to collect the children of this token 640 * @param result collected tokens 641 * @return bool true if parent is an unnamed class or enum 642 */ AddChildrenOfUnnamed(TokenTree * tree,const Token * parent,TokenIdxSet & result)643 bool AddChildrenOfUnnamed(TokenTree* tree, const Token* parent, TokenIdxSet& result) 644 { 645 if ( ( (parent->m_TokenKind & (tkClass | tkEnum)) != 0 ) 646 && parent->m_IsAnonymous == true ) 647 { 648 // add all its children 649 for (TokenIdxSet::const_iterator it = parent->m_Children.begin(); 650 it != parent->m_Children.end(); ++it) 651 { 652 Token* tokenChild = tree->at(*it); 653 if ( tokenChild 654 && (parent->m_TokenKind == tkClass || tokenChild->m_Scope != tsPrivate) ) 655 { 656 // NOTE: recurse (eg: class A contains struct contains union or enum) 657 if ( !AddChildrenOfUnnamed(tree, tokenChild, result) ) 658 { 659 result.insert(*it); 660 AddChildrenOfEnum(tree, tokenChild, result); 661 } 662 } 663 } 664 return true; 665 } 666 return false; 667 } 668 AddChildrenOfEnum(TokenTree * tree,const Token * parent,TokenIdxSet & result)669 bool AddChildrenOfEnum(TokenTree* tree, const Token* parent, TokenIdxSet& result) 670 { 671 if (parent->m_TokenKind == tkEnum) 672 { 673 // add all its children 674 for (TokenIdxSet::const_iterator it = parent->m_Children.begin(); 675 it != parent->m_Children.end(); ++it) 676 { 677 Token* tokenChild = tree->at(*it); 678 if (tokenChild && tokenChild->m_Scope != tsPrivate) 679 result.insert(*it); 680 } 681 682 return true; 683 } 684 return false; 685 } 686 687 /** @brief check to see if the token is an unnamed class or enum under the parent token 688 * 689 * This function will internally recursive call itself. 690 * @param tree pointer to the TokenTree 691 * @param targetIdx the checked token index 692 * @param parentIdx the search scope 693 * @return bool true if success 694 */ IsChildOfUnnamedOrEnum(TokenTree * tree,const int targetIdx,const int parentIdx)695 bool IsChildOfUnnamedOrEnum(TokenTree* tree, const int targetIdx, const int parentIdx) 696 { 697 if (targetIdx == parentIdx) 698 return true; 699 if (parentIdx == -1) 700 return false; 701 702 Token* parent = tree->at(parentIdx); 703 if (parent && (parent->m_TokenKind & tkClass)) 704 { 705 // loop all children of the parent token 706 for (TokenIdxSet::const_iterator it = parent->m_Children.begin(); 707 it != parent->m_Children.end(); ++it) 708 { 709 Token* token = tree->at(*it); 710 // an unnamed class is much similar like the enum 711 if (token && (((token->m_TokenKind & tkClass) 712 && (token->m_IsAnonymous == true)) 713 || (token->m_TokenKind & tkEnum))) 714 { 715 // if target token matches on child, we can return success 716 // other wise, we try to see the target token matches child's child. 717 if ((targetIdx == (*it)) || IsChildOfUnnamedOrEnum(tree, targetIdx, (*it))) 718 return true; 719 } 720 } 721 } 722 return false; 723 } 724 725 726 /** loop on the input Token index set (source), add all its public constructors to output Token index set (dest) */ 727 void AddConstructors(TokenTree *tree, const TokenIdxSet& source, TokenIdxSet& dest); 728 729 // for GenerateResultSet() MatchText(const wxString & text,const wxString & target,bool caseSens,bool isPrefix)730 bool MatchText(const wxString& text, const wxString& target, bool caseSens, bool isPrefix) 731 { 732 if (isPrefix && target.IsEmpty()) 733 return true; 734 if (!isPrefix) 735 return text.CompareTo(target.wx_str(), caseSens ? wxString::exact : wxString::ignoreCase) == 0; 736 // isPrefix == true 737 if (caseSens) 738 return text.StartsWith(target); 739 return text.Upper().StartsWith(target.Upper()); 740 } 741 742 // for GenerateResultSet() MatchType(TokenKind kind,short int kindMask)743 bool MatchType(TokenKind kind, short int kindMask) 744 { 745 return kind & kindMask; 746 } 747 748 private: 749 ParserComponent m_LastComponent; 750 std::map<wxString, wxString> m_TemplateMap; 751 }; 752 753 #endif // NATIVEPARSERBASE_H 754