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??