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

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: 5339
  • 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: 5339
  • 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: 5279
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: 5339
  • 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.