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:
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:
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:
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??
@all
simple template codecompletion has been supported now.
test codes:
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)
Good news, blueshake and I was done on some template handling, see the test 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.....