Author Topic: Is this something we can solve with the improved CC  (Read 22723 times)

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5490
Is this something we can solve with the improved CC
« on: February 11, 2010, 06:18:56 pm »
Hi,

This code has had, and still has some problems with CC, more specifically with the 'find declaration' :

Code
#include <iostream>

class ITest
{
public:
virtual int Method1(int Arg) = 0;
};


class Test : public ITest
{
public:
int Method1(int Arg);
};


int Test::Method1(int Arg)
{
return Arg;
}

int main()
{
Test Hello;
std::cout << Hello.Method1(5);
return 0;
}

Scenario :

1) right click Method1 in the call 'Hello.Method1(5)' and choose "find implementation' --> works nicely :-)

2) right click Method1 in the call 'Hello.Method1(5)' and choose "find declaration' --> gives me a choice :
Quote
* the ITest declaration
* the Test declaration
I think since the parser should now that Hello is a Test variable, it should not allow me any choice, and automatically select the Test declaration one.

Is this something that can be fixed with the improved CC, or are we still missing something in our parsing/tokens list ?

Offline blueshake

  • Regular
  • ***
  • Posts: 459
Re: Is this something we can solve with the improved CC
« Reply #1 on: February 15, 2010, 03:03:41 am »
Dear killerbot:

I dont think it is easy to do this.

For current parser.It will parse your test codes as this.

Quote
ITest
  |- Method1

Test
  |-Method1

And for a faster seach,the parser just get the matched items from the tokenstree.so you can two items from your test codes.


It make no sense if you try to solve the expression,since Test is inherited from ITest.you still will get two items.One in ITest,the other in Test.


killerbot:if you get any idea about this.share it here,please. :D


I think it will be more harder for parse these codes:

Code
ITest* pHello = new Test();


Even the codecompletion can not work correctly,not mention to others.


BTW:it is amazing that I can write so much English now. :lol: :lol: :lol:

« Last Edit: February 15, 2010, 04:10:46 am by blueshake »
Keep low and hear the sadness of little dog.
I fall in love with a girl,but I don't dare to tell her.What should I do?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #2 on: April 13, 2010, 05:22:45 pm »
@killerbot

As blueshake said, the parsing tree (simply we can say the token tree, or AST) can be like:

Quote
ITest
  |- Method1

Test
  |-Method1

Once using the find declaration on the statement: Hello.Method1(5).

In the current CC, I think there are some steps:
1, get the word under the caret, so, we return the "Method1"
2, then we do a search on the TokenTree( it is a trie structure, which store all the token names)
3, then we get all the tokens named "Method1", also, we filter the non-function tokens.
4, Then, we show "two result".

So, the more clever way is analysis the whole expression of "Hello.Method1()", and as you said, the parser knows that this is a function of the "Hello", and the parser also knows that "Hello" is type of class "Test", so, the member methods of "Test" should be searched first, then if the result is 0, we should search following the class inheritance hierarchy, in this case, the ITest class should be searched.

So, I think this bug can be fixed.  :D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline daniloz

  • Regular
  • ***
  • Posts: 268
Re: Is this something we can solve with the improved CC
« Reply #3 on: April 14, 2010, 09:16:42 am »
If I understand right what ollydbg says and if this is changed somehow in the CC to do what  killerbot suggests, does it means that "find implementation" and "find declaration" would also be also to go directly to the relevant class function member in case of functions with same name in different classes?

For example, I have a Reset() function in several classes (more than 20, actually) and each time I do a "find declaration/implementation" I have to chose from a list which class I want.

So, if  the whole expression of "Object.Reset()" is analyzed (as suggested by ollydbg), then the CC can go directly to the relevant Reset() function, right?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #4 on: April 14, 2010, 09:19:31 am »

For example, I have a Reset() function in several classes (more than 20, actually) and each time I do a "find declaration/implementation" I have to chose from a list which class I want.

So, if  the whole expression of "Object.Reset()" is analyzed (as suggested by ollydbg), then the CC can go directly to the relevant Reset() function, right?

Yes, 100% correct!!!
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline daniloz

  • Regular
  • ***
  • Posts: 268
Re: Is this something we can solve with the improved CC
« Reply #5 on: April 14, 2010, 09:25:35 am »
Cool!!! That's something I was waiting for a while now...  :D

The other thing is to parse #ifdef statements and parse only the relevant code, but this one I know is a though one... ;-)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #6 on: April 14, 2010, 09:34:31 am »
Cool!!! That's something I was waiting for a while now...  :D

The other thing is to parse #ifdef statements and parse only the relevant code, but this one I know is a though one... ;-)
Ok, I will help if I have time.

By the way, these days, Loaden has implementing a mechanism to handle #if #ifdef like statement. He has release his code in

http://topic.csdn.net/u/20100412/21/b39c50b9-caeb-406f-a12e-023e088c78c9.html  It is a Chinese programming site.

He has not finished it yet, because he has failed parsing the statement like below:

Code
#if (2 - 1) + !((3 - 2) ^ 1)

Resolving the expression is not quite easy.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Ceniza

  • Developer
  • Lives here!
  • *****
  • Posts: 1441
    • CenizaSOFT
Re: Is this something we can solve with the improved CC
« Reply #7 on: April 14, 2010, 04:17:23 pm »
Code
#if (2 - 1) + !((3 - 2) ^ 1)

Resolving the expression is not quite easy.

If you need to make replacements, then it is not easy. If it is just parentheses, numbers and operators, then it is quite easy once you convert everything into tokens after the #if and skip all whitespace.

The code that evaluates constant expressions is in constexprevaluator.h of CCPP, but no one liked that code because of all template stuff. Re-using the productions would give you the desired result. It is just a matter of replacing all template stuff into specific types.

Anyway...

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #8 on: April 14, 2010, 04:27:32 pm »
@Ceniza
I know you CCPP project, and I have tried that several months ago, but as you said, it is hard to understand...

If your CCPP project can used to replace the current Tokenizer class. ( All I want is " macro replacement, and #if XXXX evaluation), it will make CC more powerful.

But I'm sorry I can't fully understand these source code structure. Can you give a more description about your CCPP? Thanks.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5490
Re: Is this something we can solve with the improved CC
« Reply #9 on: April 14, 2010, 11:50:26 pm »
If I understand right what ollydbg says and if this is changed somehow in the CC to do what  killerbot suggests, does it means that "find implementation" and "find declaration" would also be also to go directly to the relevant class function member in case of functions with same name in different classes?

For example, I have a Reset() function in several classes (more than 20, actually) and each time I do a "find declaration/implementation" I have to chose from a list which class I want.

So, if  the whole expression of "Object.Reset()" is analyzed (as suggested by ollydbg), then the CC can go directly to the relevant Reset() function, right?


I can fully confirm this. That is indeed the idea behind my suggestion, to have these kind of things fixed. I think this would be an big improvement in our CC.

Let's hope our CC specialists can come up with a solution.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #10 on: April 15, 2010, 02:38:26 am »
Doing "find implementation" is some thing much like to the autoCompletion.

For example:

When
Code
Object.Reset()
, you would like to find the implementation of Reset().

This is just like doing the autoCompletion when you are entering, the vertical slash stands for the caret position.
Code
Object.Reset|

The only difference is: Doing autoCompletion will list all the members with the prefix string "Reset", so there will be a list like:
Code
Reset()
ResetXXX
ResetYYYY
.....
But doing "find implementation" will only do a full match of the "Reset", and only the function members will be matched.

 
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Is this something we can solve with the improved CC
« Reply #11 on: April 15, 2010, 07:10:26 am »
I can fully confirm this. That is indeed the idea behind my suggestion, to have these kind of things fixed. I think this would be an big improvement in our CC.
I would do it slightly different: Consider you have base classes and you do want to see the base method which your derived class may have overwritten. So I still would show all methods, but maybe kind of sorted by it's relevance. So like first the one of the very class I am directly targeting, then the onces of base classes etc. Searching for the whole object as suggested makes this impossible. I can live very well with being presented a lot of "Reset" functions (it's the same for me with methods called "Init" and "ReInit"). I benefit from seeing all matches and would disagree if I see only one or less in the end.

...just don't over-do it!
« Last Edit: April 15, 2010, 07:12:13 am by MortenMacFly »
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline daniloz

  • Regular
  • ***
  • Posts: 268
Re: Is this something we can solve with the improved CC
« Reply #12 on: April 15, 2010, 09:03:41 am »
I benefit from seeing all matches and would disagree if I see only one or less in the end.
...just don't over-do it!

My case is not related with derived classes, in which case I agree with MortenMacFly. I was think of different classes (not related to each other) with methods called "Reset", in which case I don't see the advantage of seeing the other classes in the list, since they're not related to the object in question.

What do you think??

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #13 on: April 15, 2010, 11:06:41 am »
@mac
Code
Searching for the whole object as suggested makes this impossible. I can live very well with being presented a lot of "Reset" functions (it's the same for me with methods called "Init" and "ReInit"). I benefit from seeing all matches and would disagree if I see only one or less in the end.
Not fully understand these sentence.  Does it means all the function in the class inheritance hierarchy should be displayed. I just agree with daniloz that all the other functions should be removed from the list.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Ceniza

  • Developer
  • Lives here!
  • *****
  • Posts: 1441
    • CenizaSOFT
Re: Is this something we can solve with the improved CC
« Reply #14 on: April 15, 2010, 07:03:28 pm »
@Ceniza
I know you CCPP project, and I have tried that several months ago, but as you said, it is hard to understand...

If your CCPP project can used to replace the current Tokenizer class. ( All I want is " macro replacement, and #if XXXX evaluation), it will make CC more powerful.

But I'm sorry I can't fully understand these source code structure. Can you give a more description about your CCPP? Thanks.

At least the constexprevaluator:

WSSkipper is a class that returns the next non-whitespace token given an iterator. It actually works as a wrapper around the iterator.
TokenContainer is just a... er... container (like a vector, deque, list, ...) that has all tokens after #if up to the end of the expression. The last token must be a ttEOT (Token Type End-Of-Tokens).
All you have to do is to give this sequence of tokens to ConstExprEvaluator::eval() and it will tell you if the expression evaluates to true or false.

I attach the file just in case. What is important from it are the rules.

[attachment deleted by admin]

Offline Loaden

  • Lives here!
  • ****
  • Posts: 1014
Re: Is this something we can solve with the improved CC
« Reply #15 on: April 16, 2010, 07:27:56 am »
Cool!!! That's something I was waiting for a while now...  :D

The other thing is to parse #ifdef statements and parse only the relevant code, but this one I know is a though one... ;-)
Ok, I will help if I have time.

By the way, these days, Loaden has implementing a mechanism to handle #if #ifdef like statement. He has release his code in

http://topic.csdn.net/u/20100412/21/b39c50b9-caeb-406f-a12e-023e088c78c9.html  It is a Chinese programming site.

He has not finished it yet, because he has failed parsing the statement like below:

Code
#if (2 - 1) + !((3 - 2) ^ 1)

Resolving the expression is not quite easy.
I have solved this problem, after repeated tests, and now it works well.


[attachment deleted by admin]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #16 on: July 04, 2010, 03:27:32 pm »
@Ceniza
firstly, thanks for the hint, the calculation of expression value in your CCPP code is still a bit hard for me, so you can see, in CC_BRANCH, we still use another way. (CC_branch has a way to calculate the #if XXX  kind of conditional preprocessor value now).

I have some time to test your CCPP project. I'm using it under MinGW.
To build the lib, we need to do a modification in the file:

include\stdstring.h

Under Windows, the function sprintf is not under std namespace, instead, you need to add the #include <cstdio>

Code
        /**
            \brief Creates a new STDString from an \c int value.
            \param value Value to convert.
            \return New STDString containing the string representation of
                \p value.
        */
        static STDString fromInt(int value) { char buffer[24]; std::sprintf(buffer, "%d", value); return STDString(buffer); }

Also, I have find a bug, When I'm running your test-debug target, I set the argument like this:

../../tests/file_line.cpp

So, the file_line.cpp will be parsed.

Here is the log output:

Code
const char * fGetFILE ( ) {

return "bwehehe.h" ;
}
int fGetLINE ( ) {

return 58 ;
}
            # define getLINE ( ) 201 int main ( ) {

int line0 = 206 ;
int line1 = getLINE ( ) ;
const char * file1 = "src/test/../../tests/file_line.cpp" ;
int line2 = fGetLINE ( ) ;
const char * file2 = fGetFILE ( ) ;
const char * today = "Jul 04 2010" ;
const char * now = "20:52:31" ;
int cpp = 199711L ;
}

Process returned 0 (0x0)   execution time : 0.047 s
Press any key to continue.

See the log :

Code
int line1 = getLINE ( ) ;

But in the file_line.cpp, the getLine() is defined by a macro.

file_line.cpp
Code
#line 200
#include "file_line.h"
#define getLINE() __LINE__

int main()
{
#if __LINE__ == 205
    int line0 = __LINE__;
#endif
    int line1 = getLINE();
    const char *file1 = getFILE();
    int line2 = fGetLINE();
    const char *file2 = fGetFILE();
    const char *today = __DATE__;
    const char *now = __TIME__;
    int cpp = __cplusplus;
}


So, it should output the current line number instead of getLINE().

BTW: it seems the CCPP project was currently develop freeze, would like to improve it or you just abandon it?

Thanks.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #17 on: July 25, 2010, 04:03:02 pm »
@killerbot and all.
See this function:
Code
void CodeCompletion::OnValueTooltip(CodeBlocksEvent& event)
{
    event.Skip();

    if (IsAttached() && m_InitDone)
    {
        if (!Manager::Get()->GetConfigManager(_T("code_completion"))->ReadBool(_T("eval_tooltip"), true))
            return;

        EditorBase* base = event.GetEditor();
        cbEditor* ed = base && base->IsBuiltinEditor() ? static_cast<cbEditor*>(base) : 0;
        if (!ed || ed->IsContextMenuOpened())
            return;

        if (ed->GetControl()->CallTipActive())
            ed->GetControl()->CallTipCancel();
//        Manager::Get()->GetLogManager()->DebugLog(F(_T("CodeCompletion::OnValueTooltip: %p"), ed));
        /* NOTE: The following 2 lines of codes can fix [Bug #11785].
        *       The solution may not the best one and it requires the editor
        *       to have the focus (even if C::B has the focus) in order to pop-up the tooltip. */
        if (wxWindow::FindFocus() != static_cast<wxWindow*>(ed->GetControl()))
            return;

        // ignore comments, strings, preprocesor, etc
        int style = event.GetInt();
        if (   (style != wxSCI_C_DEFAULT)
            && (style != wxSCI_C_OPERATOR)
            && (style != wxSCI_C_IDENTIFIER) )
            return;

        int pos = ed->GetControl()->PositionFromPointClose(event.GetX(), event.GetY());
        if (pos < 0 || pos >= ed->GetControl()->GetLength())
            return;

        Parser* parser = m_NativeParser.GetParserPtr();
        if (parser)
        {
            TokenIdxSet result;
            int endOfWord = ed->GetControl()->WordEndPosition(pos, true);
            if (m_NativeParser.MarkItemsByAI(result, true, true, true, endOfWord))
            {
                wxString msg;
                int count = 0;
                for (TokenIdxSet::iterator it = result.begin(); it != result.end(); ++it)
                {
                    Token* token = parser->GetTokens()->at(*it);
                    if (token)
                    {
                        msg << token->DisplayName() << _T("\n");
                        ++count;
                        if (count > 32) // allow max 32 matches (else something is definitely wrong)
                        {
                            msg.Clear();
                            break;
                        }
                    }
                }
                if (!msg.IsEmpty())
                {
                    msg.RemoveLast(); // last \n
                    ed->GetControl()->CallTipShow(pos, msg);
//                    Manager::Get()->GetLogManager()->DebugLog(F(msg));
                }
            }
        }
    }
}

and the function call:

Code
m_NativeParser.MarkItemsByAI(result, true, true, true, endOfWord)

after this function call, the result will contains the "Token" you suggests.  :D, because MarkItemsByAI do consider the "scopes" of the current word.

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5490
Re: Is this something we can solve with the improved CC
« Reply #18 on: July 25, 2010, 04:42:38 pm »
so it looks we are ably to solve the problem, are you taking this change into account in your CC refactorings ?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Is this something we can solve with the improved CC
« Reply #19 on: July 26, 2010, 01:53:28 am »
so it looks we are ably to solve the problem, are you taking this change into account in your CC refactorings ?
partially Yes.
Your problem about "virtual function" still has some bug. But I have create another sample code, and can show how it works:

Code
int Method1(int arg);

class Other
{
    public:
int Method1(int Arg);
};


class ITest
{
public:
virtual int Method1(int Arg) = 0;
};


class Test : public ITest
{
public:
int Method1(int Arg);
};


int Test::Method1(int Arg)
{
return Arg;
}

int main()
{
Test Hello;
std::cout << Hello.Method1(5);
return 0;
}

In this example, I add Two "function" named "Method1". Now, if I right click on the "Hello.Method1(5)", and select "goto declaration", you will still show the:
Code
* the ITest declaration
* the Test declaration
But pay attention:
We don't have the "global function Method1" and the "Other::Method1" included.

Here is the modified code:

Code
void CodeCompletion::OnGotoDeclaration(wxCommandEvent& event)
{
    EditorManager* edMan = Manager::Get()->GetEditorManager();
    // killerbot : the menu and right click pop up menu ensured there is a name under the cursor
    // BUT it seems the shortcut keys are not disabled although there menu counter part is
    // ---> so check is needed and gracefully shut up when the Name under the cursor is empty
    bool MoveOn = false;
    wxString NameUnderCursor;
    bool IsInclude = false;
    if (EditorHasNameUnderCursor(NameUnderCursor, IsInclude))
    {
        if (!IsInclude)
        {   // alright move on
            MoveOn = true;
        }
    }
    if (!MoveOn)
        return;

    Parser* parser = m_NativeParser.GetParserPtr();
    if (!parser)
        return;

    // prepare a boolean filter for declaration/implementation
    bool isDecl = event.GetId() == idGotoDeclaration || event.GetId() == idMenuGotoDeclaration;
    bool isImpl = event.GetId() == idGotoImplementation || event.GetId() == idMenuGotoImplementation;

    // get the matching set
    Token* token = 0;
    TokenIdxSet result;
    //parser->GetTokens()->FindMatches(NameUnderCursor, result, true, false);
    //Added by Asmwarrior

    // ignore comments, strings, preprocesor, etc
    int style = event.GetInt();
    if (   (style != wxSCI_C_DEFAULT)
        && (style != wxSCI_C_OPERATOR)
        && (style != wxSCI_C_IDENTIFIER) )
        return;


    cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
    if (!ed)
        return;

    const int pos = ed->GetControl()->GetCurrentPos();
    int endOfWord = ed->GetControl()->WordEndPosition(pos, true);
    m_NativeParser.MarkItemsByAI(result, true, true, true, endOfWord);


//cbMessageBox(wxString::Format(_("TEST: %s %d"), NameUnderCursor.c_str(), result.size()), _("Warning"), wxICON_WARNING);
    // one match
    if (result.size() == 1)
    {
        Token* sel = parser->GetTokens()->at(*(result.begin()));
        if ((isImpl && !sel->GetImplFilename().IsEmpty()) ||
            (isDecl && !sel->GetFilename().IsEmpty()))
        {
            token = sel;
        }
    }
    // if more than one match, display a selection dialog
    else if (result.size() > 1)
    {
        // TODO: we could parse the line containing the text so
        // if namespaces were included, we could limit the results (and be more accurate)
        wxArrayString selections;
        wxArrayInt int_selections;
        for (TokenIdxSet::iterator it = result.begin(); it != result.end(); ++it)
        {
            Token* sel = parser->GetTokens()->at(*it);
            if (sel)
            {
                // only match tokens that have filename info
                if (   (isImpl && !sel->GetImplFilename().IsEmpty())
                    || (isDecl && !sel->GetFilename().IsEmpty()) )
                {
                    selections.Add(sel->DisplayName());
                    int_selections.Add(*it);
                }
            }
        }
        if (selections.GetCount() > 1)
        {
            int sel = wxGetSingleChoiceIndex(_("Please make a selection:"), _("Multiple matches"), selections);
            if (sel == wxNOT_FOUND)
                return;
            token = parser->GetTokens()->at(int_selections[sel]);
        }
        else if (selections.GetCount() == 1)
        {    // number of selections can be < result.size() due to the if tests, so in case we fall
            // back on 1 entry no need to show a selection
            token = parser->GetTokens()->at(int_selections[0]);
        }
    }

    // do we have a token?
    if (token)
    {
        if (isImpl)
        {
            if (cbEditor* ed = edMan->Open(token->GetImplFilename()))
            {
                ed->GotoLine(token->m_ImplLine - 1);
            }
            else
            {
                cbMessageBox(wxString::Format(_("Implementation not found: %s"), NameUnderCursor.c_str()), _("Warning"), wxICON_WARNING);
            }
        }
        else
        {
            if (cbEditor* ed = edMan->Open(token->GetFilename()))
            {
                ed->GotoLine(token->m_Line - 1);
            }
            else
            {
                cbMessageBox(wxString::Format(_("Declaration not found: %s"), NameUnderCursor.c_str()), _("Warning"), wxICON_WARNING);
            }
        }
    }
    else
    {
        cbMessageBox(wxString::Format(_("Not found: %s"), NameUnderCursor.c_str()), _("Warning"), wxICON_WARNING);
    }
}

To your problem:
We should loop of the result TokenIdxSet, then strip out the redundant virtual function declarations, but sometimes as Morten said, this is not a good idea. :D
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.