Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => CodeCompletion redesign => Topic started by: ollydbg on July 06, 2010, 04:06:10 am

Title: I would like to read all the template arguments
Post by: ollydbg on July 06, 2010, 04:06:10 am
Currently, the CC doesn't support dealing with template.
So, what I want is (three steps):
Step One, read the information about template argument list
Step Two, store these information to each Token
Step Three, use them when doing codecompletion.


Here is what I would like to do in the first step:
There is a function named "SkipAngleBraces" in the Parserthread class. So, it can be used to read the template argument, I just change it to like:
Code
wxString ParserThread::SkipAngleBraces()
{
    // need to force the tokenizer _not_ skip anything
    // or else default values for template params would cause us to miss everything (because of the '=' symbol)
    TokenizerState oldState = m_Tokenizer.GetState();
    m_Tokenizer.SetState(tsSkipNone);
    wxString arg;

    int nestLvl = 0;
    // NOTE: only exit this loop with 'break' so the tokenizer's state can
    // be reset afterwards (i.e. don't use 'return')
    while (!TestDestroy())
    {
        wxString tmp = m_Tokenizer.GetToken();
        if (tmp==ParserConsts::lt)
        {
            arg<<tmp;
            ++nestLvl;
        }
        else if (tmp==ParserConsts::gt)
        {
            arg<<tmp;
            --nestLvl;
        }
        else if (tmp==ParserConsts::semicolon)
        {
            // unget token - leave ; on the stack
            m_Tokenizer.UngetToken();
            arg.Clear();
            break;
        }
        else if (tmp.IsEmpty())
            break;
        else
            arg<<tmp;


        if (nestLvl <= 0)
        {
            TRACE( _T("SkipAngleBraces() : file(%s) line(%d) %s"), m_Filename.wx_str(),m_Tokenizer.GetLineNumber(),arg.wx_str());
            break;
        }

    }

    // reset tokenizer's functionality
    m_Tokenizer.SetState(oldState);
    return arg;
}

So, you can see, if we find a match of "<" and ">", we can return the whole string of <xxxx yyyyy zzzz...>, this string seems to be the correct template arguments.

The next step is to read the class ancestor string list, for example, see the sample code:
Code
template <typename a, typename b>
class AAA
{
    a m_a;
    b m_b;
};

template <typename a, typename b>
ccc<x,y>  BBB(a in_a, b in_b)
{
    a m_a;
    b m_b;
};

class CCC: public AAA<int,float>
{
    ;
};

look at the class CCC, you can see, when we first find a "colon", we know that the next string are ancestor strings.

Currently, this is done in the void ParserThread::HandleClass(EClassType ct)

see:

Code
if (next==ParserConsts::colon) // has ancestor(s)
            {
                TRACE(_T("HandleClass() : Class '%s' has ancestors"), current.wx_str());
                m_Tokenizer.GetToken(); // eat ":"
                while (!TestDestroy())
                {
                    wxString tmp = GetClassFromMacro(m_Tokenizer.GetToken());
                    next = m_Tokenizer.PeekToken();
                    if (tmp==ParserConsts::kw_public ||
                        tmp==ParserConsts::kw_protected ||
                        tmp==ParserConsts::kw_private)
                    {
                        continue;
                    }
                    if (!(tmp==ParserConsts::comma || tmp==ParserConsts::gt))
                    {
                        // fix for namespace usage in ancestors
                        if (tmp==ParserConsts::dcolon || next==ParserConsts::dcolon)
                            ancestors << tmp;
                        else
                            ancestors << tmp << _T(',');
                        TRACE(_T("HandleClass() : Adding ancestor ") + tmp);
                    }

                    if (next.IsEmpty() ||
                        next==ParserConsts::opbrace ||
                        next==ParserConsts::semicolon)
                    {
                        break;
                    }
                    else if (next==ParserConsts::lt)
                    {
                        // template class
                        //m_Tokenizer.GetToken(); // reach "<"
                        // must not "eat" the token,
                        // SkipAngleBraces() will do it to see what it must match
                        wxString arg = SkipAngleBraces();
                        if(!arg.IsEmpty())
                        {
                            ancestors<<arg;
                        }
                        // also need to 'unget' the last token (>)
                        // so next iteration will see the { or ; in 'next'
                        m_Tokenizer.UngetToken();
                    }
                }
                TRACE(_T("HandleClass() : Ancestors: ") + ancestors);
            }

the code is try to read the whole ancestor strings, but is was not fully correct, so I need more time to fix.

I'm concerning another issue:

When all the "template arguments" was correctly parsed, How can we use this information in the Step Three??
Title: Re: I would like to read all the template arguments
Post by: blueshake on July 08, 2010, 04:55:18 am
@all
simple template codecompletion has been supported now.

test codes:
Code
template <typename T1>

class tm1
{
    T1 tm1_xx;
    T1 tm1_yy;
};
class cls1
{
    int cls1_xx;
    int cls1_yy;
};
/**class cls2
{
    int cls2_xx;
    int cls2_yy;
};*/
tm1<cls1> tt;
tt.tm1_xx.

see the picture.
(http://commondatastorage.googleapis.com/static.panoramio.com/photos/medium/37649120.jpg)
Title: Re: I would like to read all the template arguments
Post by: ollydbg on July 08, 2010, 05:10:34 am
Nice work!!!
Title: Re: I would like to read all the template arguments
Post by: ollydbg on July 30, 2010, 03:13:47 am
Good news, blueshake and I was done on some template handling, see the test code:

Code
class MyClass
{
public:
    int m_x;
    int m_y;
};

template <typename T1>
class MyTemplate
{
public:
    T1 m_xx;
    T1 m_yy;
    T1 Function(int aaa);
    T1* operator->() const throw()
    {
         return ;
    }
};

// a class object
MyTemplate<MyClass> a;

// a function
MyTemplate<MyClass> GlobalFunction(int bbb){};


// works here!!
GlobalFunction().Function().m_x;

a->

and the result, we are handling the overloaded operator -> function.  :D

(http://i683.photobucket.com/albums/vv194/ollydbg_cb/2010-07-30090822.png)

we are doing more testing.....