Author Topic: Find implementation / declaration fails with namespaces  (Read 8654 times)

Offline Kalith

  • Multiple posting newcomer
  • *
  • Posts: 67
Find implementation / declaration fails with namespaces
« on: July 18, 2011, 12:40:06 pm »
Hi,

I've created a bug report for this issue in march, but it has received no comments since then.
The "Find implementation" and "Find declaration" methods (I guess it is the CodeCompletion plugin ?) fail in the following case :
Code
namespace Foo
{
    class Bar
    {
    public :

        Bar();

        void SomeFunction();
    };
}

using namespace Foo;

Bar::Bar()
{
}

void Bar::SomeFunction()
{
}

Try with "SomeFunction".
I'm using SVN 7282 on Ubuntu.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Find implementation / declaration fails with namespaces
« Reply #1 on: July 18, 2011, 03:19:33 pm »
I can confirm this is a bug. (I test with latest trunk)

currently I'm too busy, so I guess I can't have much time to debug this.
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: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Find implementation / declaration fails with namespaces
« Reply #2 on: July 20, 2011, 03:25:51 am »
The bug is related to the change of
rev 6823 by loaden
Quote
loaden  2010-11-4 8:19:39             
* special handle function overloading for 'Goto declaration' and 'Goto implementation'

on the code:
Code
    // special handle for function overloading
    if (result.size() > 1)
    {
        const size_t curLine = editor->GetControl()->GetCurrentLine() + 1;
        for (TokenIdxSet::iterator it = result.begin(); it != result.end(); ++it)
        {
            Token* tk = tokens->at(*it);
            if (tk)
            {
                if (tk->m_Line == curLine || tk->m_ImplLine == curLine)
                {
                    const int theOnlyOne = *it;
                    result.clear();
                    result.insert(theOnlyOne);
                    break;
                }
            }
        }
    }

In you test code, the parser find two declaration of "SomeFunction".
Note: the parser do not handle scope information, so even you use "using namespace Foo"; the second "SomeFunction" will be added as another Token.
Which means, there are two Tokens:
Code
Foo::Bar::SomeFunction
Bar::SomeFunction

But the code change in rev 6823 just delete the first Token in the result, and only add the later one.
So, we should refine the code snippet above.



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 Loaden

  • Lives here!
  • ****
  • Posts: 1014
Re: Find implementation / declaration fails with namespaces
« Reply #3 on: July 20, 2011, 06:51:12 am »
Code
namespace Foo
{
class Bar
{
public :
    Bar();
    void SomeFunction();
};
}

namespace Foo
{

Bar::Bar()
{
}

void Bar::SomeFunction()
{
}

}
Should works well.

So, the real question is how to solved "using namespace foo;" issue.
see: https://developer.berlios.de/bugs/?func=detailbug&group_id=5358&bug_id=17988

That's not easy.
I have not good idea about that.
« Last Edit: July 20, 2011, 06:58:25 am by Loaden »

Offline Kalith

  • Multiple posting newcomer
  • *
  • Posts: 67
Re: Find implementation / declaration fails with namespaces
« Reply #4 on: July 20, 2011, 10:37:59 am »
Indeed, Loaden's sample code works perfectly. That's the syntax I used in older files, but I've dropped it for the single line "using namespace".
I don't know how the CC parser works, but can't you do like a C++ compiler does ? When you read a "using namespace XX" directive, you temporarily bring to the current scope all the content of what has been previously parsed in this namespace/class.
Alternatively, you could check for each symbol found after a "using namespace XX" if is has any match both in the global scope and in namespace XX.
Depending on the size of the namespace and the file to parse, one or the other solution is better, but I guess the latter one would be the most efficient ("using namespace std", which is probably the most used one, sure contains a LOT of symbols...).

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Find implementation / declaration fails with namespaces
« Reply #5 on: July 20, 2011, 10:55:15 am »
Indeed, Loaden's sample code works perfectly. That's the syntax I used in older files, but I've dropped it for the single line "using namespace".
I don't know how the CC parser works, but can't you do like a C++ compiler does ? When you read a "using namespace XX" directive, you temporarily bring to the current scope all the content of what has been previously parsed in this namespace/class.
Alternatively, you could check for each symbol found after a "using namespace XX" if is has any match both in the global scope and in namespace XX.
Depending on the size of the namespace and the file to parse, one or the other solution is better, but I guess the latter one would be the most efficient ("using namespace std", which is probably the most used one, sure contains a LOT of symbols...).
CC's parser do much less job than a compiler.
Quote
you temporarily bring to the current scope all the content of what has been previously parsed in this namespace/class.
This sounds reasonable, but if the using directive is in a header file, also the header file was included in many cpp files, how can we deal with this? Currently, we just parse every file once, which means a header file will only be parsed once. This is much different with a C++ compiler. The compiler will do much dirty job, like preprocessing, which means a header file will be parsered several times in different translation unit. CC avoid doing that things to save time.

Quote
Alternatively, you could check for each symbol found after a "using namespace XX" if is has any match both in the global scope and in namespace XX.
This is the same thing as before, which means we should do at least "semantic checking". which means we should maintain an "Exposed namespace set" dynamically. see the code below:

Code
#include "SomeHeader.h"
using namespace A;
void f()
{
    using namespace B;

    XXX;

    {
          using namespace C;
          YYY;
    }
}

ZZZ;

When parsing the statement "YYY", we should the current exposed namespace set is
{A,B,C, namespace exposed in the "SomeHeader.h"}.

When parsing the statement "ZZZ", we only check the namespace
{A, namespace exposed in the "SomeHeader.h"}.

That's too complex for CC to remember all the exposed namespace scopes.

BTW: there are some code like:

Code
using B::b;
using A::a;
....
a;
b;
which only introduce some variables or types of a namespace, which will make the semantic check more harder.

Finally, I think that's to complex for use.... C++'s grammar is toooo complex to write a simple parser. :D
This is why I some days ago suggest using some compiler directly, such as GCCsense or Clang.
search our forum for more details.
 :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 Kalith

  • Multiple posting newcomer
  • *
  • Posts: 67
Re: Find implementation / declaration fails with namespaces
« Reply #6 on: July 20, 2011, 12:37:29 pm »
C++ is complex indeed... I understand that writing a real time parser is quite hard :shock:.
Dropping your current CC code for another library would be sad though. For all the hard work you've all put into it...
But it would surely release you of the burden.

Offline Kalith

  • Multiple posting newcomer
  • *
  • Posts: 67
Re: Find implementation / declaration fails with namespaces
« Reply #7 on: July 23, 2011, 04:02:34 pm »
I don't know if this is related, but I often get random crashes when typing, clinking on a function, or event exiting my compiled application.
There is a bug report attached, which seems to involve the CodeCompletion class.

Offline Kalith

  • Multiple posting newcomer
  • *
  • Posts: 67
Re: Find implementation / declaration fails with namespaces
« Reply #8 on: August 07, 2011, 11:39:47 pm »
The aforementioned crash still happens in the latest release from Jens' repository.
I'll fill in a bug report.
Any news on the original question though ?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Find implementation / declaration fails with namespaces
« Reply #9 on: August 09, 2011, 04:38:01 pm »
@kalith
Currently, the codecompletion was massively changed day by day in the trunk, so I would suggest you can try a more recent trunk version.(not sure which version in jens' repository).

from the crash, it seems the useful call stack is:
Code
<stack>
    <frame level="0" function="wxFatalSignalHandler" offset="00000026"/>
    <frame level="1"/>
    <frame level="2" function="wxChoice::GetCount() const" offset="00000053"/>
    <frame level="3" function="wxChoice::SetSelection(int)" offset="0000005c"/>
    <frame level="4" function="CodeCompletion::FindFunctionAndUpdate(int)" offset="00000155"/>
    <frame level="5" function="CodeCompletion::ParseFunctionsAndFillToolbar(bool)" offset="0000092d"/>
    <frame level="6" function="CodeCompletion::OnStartParsingFunctions(wxTimerEvent&amp;)" offset="0000002e"/>
    <frame level="7" function="wxAppConsole::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&amp;), wxEvent&amp;) const" offset="0000003f"/>
    <frame level="8" function="wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&amp;, wxEvtHandler*, wxEvent&amp;)" offset="00000079"/>
    <frame level="9" function="wxEventHashTable::HandleEvent(wxEvent&amp;, wxEvtHandler*)" offset="00000084"/>
    <frame level="10" function="wxEvtHandler::ProcessEvent(wxEvent&amp;)" offset="000000e7"/>
    <frame level="11" function="wxTimerBase::Notify()" offset="0000007d"/>
    <frame level="12"/>
    <frame level="13"/>
    <frame level="14" function="g_main_context_dispatch" offset="000001c8"/>
    <frame level="15"/>
    <frame level="16" function="g_main_loop_run" offset="0000017b"/>
    <frame level="17" function="gtk_main" offset="000000b9"/>
    <frame level="18" function="wxEventLoop::Run()" offset="00000048"/>
    <frame level="19" function="wxAppBase::MainLoop()" offset="0000004e"/>
    <frame level="20" function="wxAppBase::OnRun()" offset="00000021"/>
    <frame level="21"/>
  </stack>
But even from this, I can't tell something useful to the bug.

the original question? which one, you want to enable the "scopeā€œ or the "context" info when parsing?
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 Kalith

  • Multiple posting newcomer
  • *
  • Posts: 67
Re: Find implementation / declaration fails with namespaces
« Reply #10 on: August 10, 2011, 04:51:46 pm »
I'll try these versions as soon as they come out, thanks for pointing that out :)
If the crash still happens, I may try to run CB in debug mode to see where it actually comes from.
About the "original question", forgive me : I thought I was in another thread (this one)...