Major Assist++ refactoring

git-svn-id: svn://ultimatepp.org/upp/trunk@514 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2008-10-10 15:30:43 +00:00
parent 713e94f0b9
commit b1769a1d8d
11 changed files with 478 additions and 415 deletions

View file

@ -339,6 +339,7 @@ class Parser {
bool EatBody();
void Cv();
String TType();
String SimpleType(Decla& d);
void Qualifier();
void ParamList(Decl& d);
@ -346,6 +347,7 @@ class Parser {
void EatInitializers();
Decl Type();
void Vars(Array<Decl>& r, const char *p, bool type_def, bool more);
Array<Decl> Declaration0(bool l0 = false, bool more = false);
Array<Decl> Declaration(bool l0 = false, bool more = false);
bool IsParamList(int q);
void Elipsis(Decl& d);

View file

@ -403,13 +403,16 @@ String Parser::Constant()
return String(p, p1);
}
String Parser::TType()
{
int q = FindIndex(context.tparam, lex[0]);
if(q >= 0) return AsString(q);
return lex.Id();
}
String Parser::SimpleType(Decla& d)
{
if(Key(tk_struct) || Key(tk_class) || Key(tk_union) || Key(tk_enum) || Key(tk_typename)) {
if(lex.IsId() || lex == t_dblcolon) d.type = Name();
if(lex == '{') EatBody();
return Null;
}
Key(tk_typename) || Key(tk_struct) || Key(tk_class) || Key(tk_union) || Key(tk_enum);
if(Key(tk_bool) || Key(tk_float) || Key(tk_double) || Key(tk_void))
return Null;
bool sgn = Key(tk_signed) || Key(tk_unsigned);
@ -433,29 +436,21 @@ String Parser::SimpleType(Decla& d)
d.type << "::";
Check(lex.IsId(), "Name expected");
while(lex.IsId()) {
int q = FindIndex(context.tparam, lex[0]);
if(q >= 0) {
d.type << AsString(q);
++lex;
break;
}
else {
d.type << lex.Id();
if(cix.Find(lex) >= 0)
d.type << TType();
if(cix.Find(lex) >= 0)
cs = true;
else
cix.Add(lex);
++lex;
if(lex == '<')
d.type << TemplateParams();
if(Key(t_dblcolon)) {
d.type << "::";
if(Key('~'))
cs = true;
else
cix.Add(lex);
++lex;
if(lex == '<')
d.type << TemplateParams();
if(Key(t_dblcolon)) {
d.type << "::";
if(Key('~'))
cs = true;
}
else
break;
}
else
break;
}
return cs ? String(p, lex.Pos()) : String();
}
@ -628,19 +623,11 @@ bool Parser::IsParamList(int q)
return true;
}
Array<Parser::Decl> Parser::Declaration(bool l0, bool more)
Array<Parser::Decl> Parser::Declaration0(bool l0, bool more)
{
Array<Decl> r;
Decla d;
const char *p = lex.Pos();
if(Key(tk_typedef)) {
r = Declaration(false, true);
for(int i = 0; i < r.GetCount(); i++) {
r[i].type_def = true;
r[i].natural = "typedef " + r[i].natural;
}
return r;
}
if(Key(tk_friend))
d.isfriend = true;
for(;;) {
@ -721,6 +708,19 @@ Array<Parser::Decl> Parser::Declaration(bool l0, bool more)
return r;
}
Array<Parser::Decl> Parser::Declaration(bool l0, bool more)
{
if(Key(tk_typedef)) {
Array<Decl> r = Declaration(false, true);
for(int i = 0; i < r.GetCount(); i++) {
r[i].type_def = true;
r[i].natural = "typedef " + r[i].natural;
}
return r;
}
return Declaration0(l0, more);
}
void Parser::Locals(const String& type)
{
Array<Parser::Decl> d = Declaration(true, true);
@ -905,7 +905,10 @@ void Parser::Statement()
bool Parser::EatBody()
{
if(lex != '{') return false;
if(lex != '{') {
local.Clear();
return false;
}
lex.BeginBody();
maxScopeDepth = currentScopeDepth = dobody ? 0 : 1;
if(dobody) {
@ -1100,11 +1103,6 @@ bool Parser::Scope(const String& tp, const String& tn) {
String key = (t == tk_class ? "class" : t == tk_union ? "union" : "struct");
nn << key << ' ' << name;
CppItem& im = Item(context.scope, key, name, lex != ';');
if(Key(';')) {
context = cc;
SetScopeCurrent();
return true;
}
im.kind = tp.IsEmpty() ? STRUCT : STRUCTTEMPLATE;
im.type = name;
im.access = cc.access;
@ -1114,6 +1112,11 @@ bool Parser::Scope(const String& tp, const String& tn) {
im.ptype.Clear();
im.pname.Clear();
im.param.Clear();
if(Key(';')) {
context = cc;
SetScopeCurrent();
return true;
}
if(Key(':')) {
nn << " : ";
bool c = false;
@ -1169,6 +1172,8 @@ CppItem& Parser::Fn(const Decl& d, const String& templ, bool body,
String ptype;
for(int i = 0; i < d.param.GetCount(); i++) {
const Decla& p = d.param[i];
if(dobody)
local.Add(p.name, p.type);
ScAdd(param, p.natural);
if(i)
ptype << ';';
@ -1395,7 +1400,7 @@ void Parser::Do()
ScopeCat(scope, d.name);
CppItem& im = Item(scope, d.type_def ? "typedef" : d.name, d.name);
im.natural = Purify(h);
im.type = im.ptype = d.type;
im.type = d.type;
im.access = context.access;
im.kind = d.type_def ? TYPEDEF :
IsNull(scope) ? VARIABLE :

View file

@ -19,11 +19,19 @@ bool Qualify0(Scopefo& nf, const String& type, String& qt)
if(nf.GetScope() >= 0) {
int q = type.ReverseFind(':');
if(q > 0) {
// DDUMP(type);
LTIMING("Qualifying qualification");
Scopefo hnf(nf);
hnf.NoBases();
String qn;
if(DoQualify(hnf, type.Mid(0, q - 1), qn)) {
String qs = type.Mid(0, q - 1);
if(IsDigit(*qs)) {
qt = type;
return true;
}
// DDUMP(qs);
if(DoQualify(hnf, qs, qn)) {
// DDUMP(qn);
int scopei = nf.base.Find(qn);
if(scopei >= 0) {
String tp = type.Mid(q + 1);
@ -36,6 +44,8 @@ bool Qualify0(Scopefo& nf, const String& type, String& qt)
}
}
}
qt = type.Mid(q + 1);
return true;
}
else {
LTIMING("Bases");
@ -138,9 +148,9 @@ String QualifyIds(Scopefo& nf, const String& k, bool all, byte& qual)
else {
if(c == '(')
all = true;
r.Cat(c);
if(c != ' ')
r.Cat(c);
s++;
while(*s == ' ') s++;
}
}
return r;
@ -216,8 +226,6 @@ void QualifyPass2(CppBase& base)
bool sort = false;
for(int i = 0; i < n.GetCount(); i++) {
CppItem& m = n[i];
LLOG(base.GetKey(ni) << "::" << m.item << " " << GetCppFile(m.file)
<< " impl:" << m.impl << " kind:" << (int)m.kind << " IsType:" << m.IsType());
if(m.serial != base.serial && !m.IsType()) {
sort = true;
m.serial = base.serial;
@ -232,6 +240,9 @@ void QualifyPass2(CppBase& base)
: m.item;
}
}
LLOG(base.GetKey(ni) << "." << m.item << " " << GetCppFile(m.file)
<< " impl:" << m.impl << " kind:" << (int)m.kind << " IsType:" << m.IsType()
<< " qtype:" << m.qtype << " tparam:" << m.tparam);
}
if(sort)
Sort(n, CmpCppItem());

View file

@ -16,10 +16,11 @@ struct FileIconMaker : ImageMaker {
Color c = White();
Image m[2];
for(int i = 0; i < 2; i++) {
SHFILEINFO info;
SHGetFileInfo(file, dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL,
&info, sizeof(info),
SHGFI_ICON|SHGFI_SMALLICON|(exe ? 0 : SHGFI_USEFILEATTRIBUTES));
SHFILEINFOW info;
WString wfile = file.ToWString();
SHGetFileInfoW(~wfile, dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL,
&info, sizeof(info),
SHGFI_ICON|SHGFI_SMALLICON|(exe ? 0 : SHGFI_USEFILEATTRIBUTES));
HICON icon = info.hIcon;
ICONINFO iconinfo;
if(!icon || !GetIconInfo(icon, &iconinfo))

View file

@ -1,8 +1,8 @@
#include "ide.h"
#define LDUMP(x) // DDUMP(x)
#define LDUMPC(x) // DDUMPC(x)
#define LLOG(x) // DLOG(x)
#define LDUMP(x) //DDUMP(x)
#define LDUMPC(x) //DDUMPC(x)
#define LLOG(x) //DLOG(x)
class IndexSeparatorFrameCls : public CtrlFrame {
virtual void FrameLayout(Rect& r) { r.right -= 1; }
@ -55,7 +55,7 @@ AssistEditor::AssistEditor()
browser.item.NoWantFocus();
browser.item.WhenLeftClick = browser.item.WhenLeftDouble = THISBACK(BrowserGoto);
browser.NameStart();
navigator = NAV_BROWSER;
WhenAnnotationMove = THISBACK(SyncAnnotationPopup);
@ -65,295 +65,6 @@ AssistEditor::AssistEditor()
annotation_popup.Margins(6);
}
Vector<String> TemplatePars(const String& type)
{
Vector<String> r;
int q = type.Find('<');
if(q >= 0) {
const char *s = ~type + q + 1;
int lvl = 0;
String t;
while(*s && (lvl || *s != '>')) {
if(*s == '<')
lvl++;
if(*s == '>')
lvl--;
if(*s == ',') {
r.Add(t);
t.Clear();
s++;
}
else
t.Cat(*s++);
}
r.Add(t);
}
return r;
}
void SubstituteTpars(Vector<String>& type, const String& tname)
{
Vector<String> tp = TemplatePars(tname);
for(int i = 0; i < type.GetCount(); i++)
if(IsDigit(type[i][0])) {
int q = atoi(type[i]);
if(q >= 0 && q < tp.GetCount()) {
LLOG(type[i] << " -> " << tp[q]);
type[i] = tp[q];
}
}
}
bool AssistEditor::ScopeId(const Array<CppItem>& n, const String& id, Vector<String>& type, bool& code,
String& t)
{
String ntp = NoTemplatePars(id);
for(int i = 0; i < n.GetCount(); i++) {
const CppItem& m = n[i];
if(n[i].name == ntp) {
const String& qt = m.qtype;
if(!IsNull(qt) && FindIndex(type, qt) < 0 && (m.IsCode() || m.IsData())) {
type.Add(qt);
if(m.IsCode())
code = true;
}
}
}
if(type.GetCount())
return true;
int q = FindItem(n, "class");
if(q < 0)
q = FindItem(n, "struct");
if(q < 0)
q = FindItem(n, "typedef");
LDUMP(q);
if(q >= 0) {
Vector<String> base = Split(n[q].qptype, ';');
LDUMP(id);
LDUMPC(base);
LDUMPC(n[q].qptype);
SubstituteTpars(base, t);
for(int i = 0; i < base.GetCount(); i++) {
q = BrowserBase().Find(NoTemplatePars(base[i]));
String h = base[i];
if(q >= 0 && ScopeId(BrowserBase()[q], id, type, code, h)) {
t = h;
return true;
}
}
}
return false;
}
void AssistScanError(int line, const String& text)
{
#ifdef _DEBUG
PutVerbose(String().Cat() << "(" << line << "): " << text);
#endif
}
void AssistEditor::Context(Parser& parser, int pos)
{
theide->ScanFile();
String s = Get(0, pos);
StringStream ss(s);
parser.dobody = true;
parser.Do(ss, IgnoreList(), BrowserBase(), Null, callback(AssistScanError));
QualifyTypes(BrowserBase(), parser.current_scope, parser.current);
inbody = parser.IsInBody();
#ifdef _DEBUG
PutVerbose("body: " + AsString(inbody));
PutVerbose("scope: " + AsString(parser.current_scope));
#endif
}
void AssistEditor::TypeOf(const String& id, Vector<String>& r, bool& code)
{
Parser parser;
Context(parser, GetCursor());
code = false;
if(id == "this") {
r.Add(parser.current_scope);
return;
}
if(IsNull(id)) {
r.Add(parser.current_scope);
if(parser.current_scope.GetCount())
r.Add(Null);
return;
}
int q = parser.local.FindLast(id);
if(q >= 0) {
r.Add(parser.local[q]);
return;
}
Vector<String> p = Split(parser.current.pname, ';', false);
q = FindIndex(p, id);
if(q >= 0) {
p = Split(parser.current.qptype, ';');
if(q < p.GetCount())
r.Add(p[q]);
return;
}
String n = parser.current_scope;
for(;;) {
String type = n.GetCount() ? n + "::" + id : id;
if(BrowserBase().Find(type)) {
code = true;
r.Add(type);
}
int q = n.ReverseFind(':');
if(q < 1 || n[q - 1] != ':')
break;
n.Trim(q - 1);
}
q = BrowserBase().Find(parser.current_scope);
String dummy;
if(q >= 0 && ScopeId(BrowserBase()[q], id, r, code, dummy))
return;
q = BrowserBase().Find("");
if(q >= 0)
ScopeId(BrowserBase()[q], id, r, code, dummy);
}
Vector<String> AssistEditor::Operator(const char *oper, const Vector<String>& type)
{
Vector<String> nt;
bool d;
for(int i = 0; i < type.GetCount(); i++) {
String t = type[i];
int q = BrowserBase().Find(NoTemplatePars(t));
if(q < 0 || !ScopeId(BrowserBase()[q], oper, nt, d, t))
nt.Add(type[i]);
SubstituteTpars(nt, t);
}
return nt;
}
Vector<String> AssistEditor::TypeOf(const Vector<String>& xp, const String& tp)
{
Vector<String> type;
bool code;
if(!IsNull(tp)) {
Parser parser;
Context(parser, GetCursor());
type.Add(Qualify(BrowserBase(), parser.current_scope, tp));
}
else {
if(xp.GetCount() == 0 || !iscid(xp[0][0]))
return type;
TypeOf(xp[0], type, code);
}
LDUMPC(xp);
LDUMPC(type);
int q = 1;
if(code && xp.GetCount() > 1 && xp[1][0] == '(')
q++;
while(q < xp.GetCount() && type.GetCount()) {
int c = xp[q][0];
LDUMP(xp[q]);
if(iscid(c)) {
Vector<String> nt;
bool code = false;
for(int i = 0; i < type.GetCount(); i++) {
String t = type[i];
int j = BrowserBase().Find(NoTemplatePars(t));
if(j >= 0)
ScopeId(BrowserBase()[j], xp[q], nt, code, t);
LDUMPC(nt);
SubstituteTpars(nt, t);
}
if(code && q + 1 < xp.GetCount() && xp[q + 1][0] == '(')
q++;
type = nt;
}
if(c == '(')
type = Operator("operator()", type);
if(c == '[')
type = Operator("operator[]", type);
if(c == '-')
type = Operator("operator->", type);
q++;
}
LDUMPC(type);
return type;
}
int CharFilterT(int c)
{
return c >= '0' && c <= '9' ? "TUVWXYZMNO"[c - '0'] : c;
}
void AssistEditor::GatherItems(const String& type, bool nom, Index<String>& in_types, bool tp)
{
LLOG("GatherItems " << type);
if(in_types.Find(type) >= 0) {
LLOG("-> recursion, exiting");
return;
}
in_types.Add(type);
String ntp = NoTemplatePars(type);
int q = BrowserBase().Find(ntp);
LDUMP(q);
if(q < 0)
return;
if(tp) {
if(ntp != "")
ntp << "::";
int typei = assist_type.FindAdd("<types>");
for(int i = 0; i < BrowserBase().GetCount(); i++) {
String n = BrowserBase().GetKey(i);
if(n.GetLength() > ntp.GetLength() && memcmp(~ntp, ~n, ntp.GetLength()) == 0) {
LDUMP(n);
Array<CppItem>& m = BrowserBase()[i];
for(int i = 0; i < m.GetCount(); i++) {
const CppItem& im = m[i];
if(im.IsType()) {
CppItemInfo& f = assist_item.Add(im.name);
f.typei = typei;
(CppItem&)f = im;
break;
}
}
}
}
}
const Array<CppItem>& m = BrowserBase()[q];
String base;
int typei = assist_type.FindAdd(ntp);
for(int i = 0; i < m.GetCount(); i++) {
const CppItem& im = m[i];
if(im.IsType())
base = im.qptype;
LDUMP(im.name);
LDUMP(im.natural);
LDUMP(im.qitem);
LDUMP(base);
if((im.IsCode() || im.IsData() || im.IsMacro() && type == "")
&& (nom || im.access == PUBLIC)) {
if(im.IsCode()) {
int q = assist_item.Find(im.name);
while(q >= 0) {
if(assist_item[q].typei != typei)
assist_item[q].over = true;
q = assist_item.FindNext(q);
}
}
CppItemInfo& f = assist_item.Add(im.name);
f.typei = typei;
(CppItem&)f = im;
}
}
LDUMP(base);
Vector<String> b = Split(base, ';');
LDUMPC(b);
SubstituteTpars(b, type);
LDUMPC(b);
for(int i = 0; i < b.GetCount(); i++)
GatherItems(b[i], nom, in_types, tp);
in_types.Drop();
}
int CppItemInfoOrder(const Value& va, const Value& vb) {
const CppItemInfo& a = ValueTo<CppItemInfo>(va);
const CppItemInfo& b = ValueTo<CppItemInfo>(vb);
@ -415,16 +126,47 @@ String AssistEditor::IdBack(int& qq)
int q = qq;
while(iscid(Ch(q - 1)))
q--;
if(!iscib(Ch(q)))
return Null;
String r;
qq = q;
while(q < GetLength() && iscid(Ch(q)))
r.Cat(Ch(q++));
if(iscib(Ch(q))) {
qq = q;
while(q < GetLength() && iscid(Ch(q)))
r.Cat(Ch(q++));
}
return r;
}
Vector<String> AssistEditor::ReadBack(int q, String& type)
String AssistEditor::CompleteIdBack(int& q)
{
String id;
for(;;) {
SkipSpcBack(q);
if(Ch(q - 1) == '>') {
q--;
id = '>' + id;
}
else
if(Ch(q - 1) == '<') {
q--;
id = '<' + id;
}
else
if(Ch(q - 1) == ':') {
while(Ch(q - 1) == ':')
q--;
id = "::" + id;
}
else {
String nid = IdBack(q);
if(IsNull(nid))
break;
id = nid + id;
}
}
return id;
}
Vector<String> AssistEditor::ReadBack(int q)
{
Vector<String> r;
type.Clear();
@ -437,27 +179,27 @@ Vector<String> AssistEditor::ReadBack(int q, String& type)
}
SkipSpcBack(q);
int c = Ch(q - 1);
int c1 = Ch(q - 2);
if(c == ':' && c1 == ':') {
for(;;) {
q -= 2;
SkipSpcBack(q);
String id = IdBack(q);
if(IsNull(id))
break;
type = id + type;
SkipSpcBack(q);
if(Ch(q - 1) != ':' || Ch(q - 2) != ':')
break;
}
break;
if(c == '>' && !wasid) {
String id = ">";
q--;
r.Add() = id + CompleteIdBack(q);
wasid = true;
continue;
}
if(iscid(c)) {
if(wasid)
break;
String id = IdBack(q);
if(IsNull(id))
break;
String id;
for(;;) {
id = IdBack(q) + id;
SkipSpcBack(q);
if(Ch(q - 1) != ':')
break;
while(Ch(q - 1) == ':')
q--;
id = "::" + id;
SkipSpcBack(q);
}
r.Add() = id;
wasid = true;
continue;
@ -540,26 +282,36 @@ void AssistEditor::Assist()
if(!assist_active)
return;
CloseAssist();
Parser parser;
Context(parser, GetCursor());
int q = GetCursor();
assist_cursor = q;
while(iscid(Ch(q - 1)))
q--;
String tp;
Vector<String> h = ReadBack(q, tp);
Vector<String> type;
bool d;
if(h.GetCount() == 0 && IsNull(tp))
TypeOf(Null, type, d);
else {
type = TypeOf(h, tp);
if(type.GetCount() == 0)
return;
}
assist_type.Clear();
assist_item.Clear();
for(int i = 0; i < type.GetCount(); i++) {
Index<String> in_types;
GatherItems(type[i], h.GetCount() == 0, in_types, !IsNull(tp) || h.GetCount() == 0);
Index<String> in_types;
if(Ch(q - 1) == ':') {
while(Ch(q - 1) == ':')
q--;
Vector<String> tparam;
GatherItems(ParseTemplatedType(Qualify(parser.current_scope, CompleteIdBack(q)), tparam),
true, in_types, true);
}
else {
String tp;
Vector<String> xp = ReadBack(q);
if(xp.GetCount()) {
Index<String> typeset = ExpressionType(parser, xp);
for(int i = 0; i < typeset.GetCount(); i++)
if(typeset[i].GetCount())
GatherItems(typeset[i], xp.GetCount() == 0, in_types, xp.GetCount() == 0);
}
else {
GatherItems(parser.current_scope, true, in_types, true);
Index<String> in_types2;
GatherItems("", true, in_types2, true);
}
}
if(assist_item.GetCount() == 0)
return;
@ -721,17 +473,6 @@ bool AssistEditor::Key(dword key, int count)
return true;
}
}
#ifdef _DEBUG
if(key == K_ALT_F12) {
PutConsole("Type is");
String tp;
Vector<String> h = ReadBack(GetCursor(), tp);
Vector<String> r = TypeOf(h, tp);
PutConsole(tp);
for(int i = 0; i < r.GetCount(); i++)
PutConsole(r[i]);
}
#endif
int c = GetCursor();
int cc = GetChar(c);
int bcc = c > 0 ? GetChar(c - 1) : 0;
@ -912,7 +653,7 @@ void AssistEditor::DCopy()
parser.Do(ss, IgnoreList(), cpp, Null, CNULL, Split(cls, ':'));
for(int i = 0; i < cpp.GetCount(); i++) {
const Array<CppItem>& n = cpp[i];
for(int j = 0; j < n.GetCount(); j++) {
for(int j = 0; j < n.GetCount(); j = FindNext(n, j)) {
const CppItem& m = n[j];
if(m.IsCode())
if(decla)
@ -954,7 +695,8 @@ bool GetIdScope(String& os, const String& scope, const String& id, Index<String>
if(done.Find(scope) >= 0)
return Null;
done.Add(scope);
String n = NoTemplatePars(scope);
Vector<String> tparam;
String n = ParseTemplatedType(scope, tparam);
int q = BrowserBase().Find(n);
if(q < 0)
return Null;
@ -964,11 +706,11 @@ bool GetIdScope(String& os, const String& scope, const String& id, Index<String>
os = n;
return true;
}
for(int i = 0; i < m.GetCount(); i++) {
for(int i = 0; i < m.GetCount(); i = FindNext(m, i)) {
const CppItem& im = m[i];
if(im.IsType()) {
Vector<String> b = Split(im.qptype, ';');
SubstituteTpars(b, scope);
ResolveTParam(b, tparam);
for(int i = 0; i < b.GetCount(); i++) {
if(GetIdScope(os, b[i], id, done))
return true;
@ -1052,14 +794,14 @@ void Ide::JumpS()
while(iscid(editor.Ch(q - 1)))
q--;
String tp;
Vector<String> h = editor.ReadBack(q, tp);
Vector<String> type;
Vector<String> xp = editor.ReadBack(q);
Index<String> type;
Parser parser;
editor.Context(parser, editor.GetCursor());
if(h.GetCount() == 0 && IsNull(tp))
if(xp.GetCount() == 0 && IsNull(tp))
type.Add(parser.current_scope);
else {
type = editor.TypeOf(h, tp);
type = editor.ExpressionType(parser, xp);
if(type.GetCount() == 0)
return;
}

View file

@ -3,7 +3,7 @@
#define LTIMING(x) // RTIMING(x)
#define LLOG(x)
static const char s_dbver[] = "Assist++ 2.32";
static const char s_dbver[] = "CPP-BASE 2.34";
void GC_Cache()
{

291
uppsrc/ide/Cpp.cpp Normal file
View file

@ -0,0 +1,291 @@
#include "ide.h"
#define LDUMP(x) //DDUMP(x)
#define LDUMPC(x) //DDUMPC(x)
#define LLOG(x) //DLOG(x)
static Array<CppItem> sEmpty;
const Array<CppItem>& GetTypeItems(const String& type)
{
int q = BrowserBase().Find(type);
if(q < 0)
return sEmpty;
return BrowserBase()[q];
}
Vector<String> GetTypeBases(const String& type)
{
const Array<CppItem>& n = GetTypeItems(type);
for(int i = 0; i < n.GetCount(); i = FindNext(n, i)) {
const CppItem& im = n[i];
if(im.IsType())
return Split(im.qptype, ';');
}
Vector<String> empty;
return empty;
}
String ParseTemplatedType(const String& type, Vector<String>& tparam)
{
const char *s = type;
String r;
while(*s) {
if(*s == '<') {
s++;
int lvl = 0;
String t;
while(*s) {
int c = *s++;
if(c == ',') {
if(lvl == 0 && t.GetCount()) {
tparam.Add(t);
t.Clear();
}
}
else {
if(c == '>' && --lvl)
break;
if(c == '<')
lvl++;
t.Cat(c);
}
}
if(t.GetCount())
tparam.Add(t);
}
else
r.Cat(*s++);
}
LLOG("ParseTemplatedType " << type << " -> " << r);
LDUMPC(tparam);
return r;
}
String ResolveTParam(const String& type, const Vector<String>& tparam)
{
String r;
const char *s = type;
while(*s) {
if(IsDigit(*s)) {
int i = *s++ - '0';
if(i >= 0 && i < tparam.GetCount())
r.Cat(tparam[i]);
}
else
if(iscib(*s))
while(iscid(*s))
r.Cat(*s++);
else
r.Cat(*s++);
}
LLOG("Resolved " << type << " -> " << r);
const Array<CppItem>& x = GetTypeItems(r);
if(x.GetCount() && x[0].kind == TYPEDEF) {
LLOG("Is typedef " << x[0].qtype);
String h = x[0].qtype;
if(h != type && h != r)
return ResolveTParam(h, tparam);
return h;
}
return r;
}
void ResolveTParam(Vector<String>& type, const Vector<String>& tparam)
{
for(int i = 0; i < type.GetCount(); i++)
type[i] = ResolveTParam(type[i], tparam);
}
void AssistScanError(int line, const String& text)
{
#ifdef _DEBUG
PutVerbose(String().Cat() << "(" << line << "): " << text);
#endif
}
void AssistEditor::Context(Parser& parser, int pos)
{
theide->ScanFile();
String s = Get(0, pos);
StringStream ss(s);
parser.dobody = true;
parser.Do(ss, IgnoreList(), BrowserBase(), Null, callback(AssistScanError));
QualifyTypes(BrowserBase(), parser.current_scope, parser.current);
inbody = parser.IsInBody();
#ifdef _DEBUG
PutVerbose("body: " + AsString(inbody));
PutVerbose("scope: " + AsString(parser.current_scope));
#endif
}
String Qualify(const String& scope, const String& type)
{
return Qualify(BrowserBase(), scope, type);
}
void AssistEditor::ExpressionType(const String& type, const Vector<String>& xp, int ii,
Index<String>& typeset, const Vector<String>& tparam,
bool can_shortcut_operator, Index<String>& visited_bases)
{
if(ii >= xp.GetCount()) {
LLOG("Final type: " << type);
typeset.FindAdd(type);
return;
}
int c0 = typeset.GetCount();
const Array<CppItem>& n = GetTypeItems(type);
String id = xp[ii];
int q = id.ReverseFind(':');
if(q > 0 && id[q - 1] == ':') {
Vector<String> tparam;
String qtype = ParseTemplatedType(Qualify("", id.Mid(0, q - 1)), tparam);
id = id.Mid(q + 1);
ExpressionType(ResolveTParam(qtype, tparam), xp, ii + 1, typeset);
return;
}
LLOG("ExpressionType " << type << " ii: " << ii << " id:" << id);
if(*id == '.') {
ExpressionType(type, xp, ii + 1, typeset, tparam);
return;
}
bool shortcut_oper = false;
if(!iscid(*id)) {
shortcut_oper = can_shortcut_operator;
id = "operator" + id;
}
for(int i = 0; i < n.GetCount(); i = FindNext(n, i)) {
const CppItem& m = n[i];
if(m.name == id)
ExpressionType(ResolveTParam(m.qtype, tparam), xp, ii + 1, typeset);
}
if(typeset.GetCount() != c0 || IsNull(type))
return;
Vector<String> base = GetTypeBases(type);
ResolveTParam(base, tparam);
for(int i = 0; i < base.GetCount(); i++)
if(visited_bases.Find(base[i]) < 0) {
visited_bases.Add(base[i]);
Vector<String> tparam;
ExpressionType(ParseTemplatedType(base[i], tparam), xp, ii, typeset,
tparam, false, visited_bases);
if(typeset.GetCount() != c0)
return;
}
if(shortcut_oper)
ExpressionType(type, xp, ii + 1, typeset, tparam);
}
void AssistEditor::ExpressionType(const String& type, const Vector<String>& xp, int ii,
Index<String>& typeset, const Vector<String>& tparam)
{
Index<String> visited_bases;
ExpressionType(type, xp, ii, typeset, tparam, true, visited_bases);
}
void AssistEditor::ExpressionType(const String& type, const Vector<String>& xp, int ii,
Index<String>& typeset)
{
Vector<String> tparam;
ExpressionType(ParseTemplatedType(type, tparam), xp, ii, typeset, tparam);
}
Index<String> AssistEditor::ExpressionType(const Parser& parser, const Vector<String>& xp)
{
String type;
Index<String> typeset;
if(xp.GetCount() == 0)
return typeset;
if(xp[0] == "this") {
LLOG("this: " << type);
ExpressionType(parser.current_scope, xp, 1, typeset);
return typeset;
}
int q = parser.local.FindLast(xp[0]);
if(q >= 0) {
String type = Qualify(parser.current_scope, parser.local[q]);
LLOG("Found type local: " << type);
ExpressionType(type, xp, 1, typeset);
return typeset;
}
ExpressionType(parser.current_scope, xp, 0, typeset);
if(typeset.GetCount())
return typeset;
if(xp.GetCount() >= 2 && xp[1] == "()") {
Vector<String> tparam;
String qtype = ParseTemplatedType(Qualify(parser.current_scope, xp[0]), tparam);
if(BrowserBase().Find(qtype) >= 0) {
LLOG("Is constructor " << qtype);
ExpressionType(ResolveTParam(qtype, tparam), xp, 2, typeset);
return typeset;
}
}
ExpressionType("", xp, 0, typeset);
return typeset;
}
int CharFilterT(int c)
{
return c >= '0' && c <= '9' ? "TUVWXYZMNO"[c - '0'] : c;
}
void AssistEditor::GatherItems(const String& type, bool nom, Index<String>& in_types, bool tp)
{
LLOG("GatherItems " << type);
if(in_types.Find(type) >= 0) {
LLOG("-> recursion, exiting");
return;
}
in_types.Add(type);
Vector<String> tparam;
String ntp = ParseTemplatedType(type, tparam);
int q = BrowserBase().Find(ntp);
if(q >= 0) {
if(tp) {
if(ntp.GetCount())
ntp << "::";
int typei = assist_type.FindAdd("<types>");
for(int i = 0; i < BrowserBase().GetCount(); i++) {
String n = BrowserBase().GetKey(i);
if(n.GetLength() > ntp.GetLength() && memcmp(~ntp, ~n, ntp.GetLength()) == 0) {
Array<CppItem>& n = BrowserBase()[i];
for(int i = 0; i < n.GetCount(); i = FindNext(n, i)) {
const CppItem& m = n[i];
if(m.IsType()) {
CppItemInfo& f = assist_item.Add(m.name);
f.typei = typei;
(CppItem&)f = m;
break;
}
}
}
}
}
const Array<CppItem>& n = BrowserBase()[q];
String base;
int typei = assist_type.FindAdd(ntp);
for(int i = 0; i < n.GetCount(); i = FindNext(n, i)) {
const CppItem& im = n[i];
if(im.IsType())
base = im.qptype;
if((im.IsCode() || im.IsData() || im.IsMacro() && type == "")
&& (nom || im.access == PUBLIC)) {
int q = assist_item.Find(im.name);
while(q >= 0) {
if(assist_item[q].typei != typei)
assist_item[q].over = true;
q = assist_item.FindNext(q);
}
CppItemInfo& f = assist_item.Add(im.name);
f.typei = typei;
(CppItem&)f = im;
}
}
Vector<String> b = Split(base, ';');
ResolveTParam(b, tparam);
for(int i = 0; i < b.GetCount(); i++)
if(b[i].GetCount())
GatherItems(b[i], nom, in_types, tp);
}
in_types.Drop();
}

View file

@ -54,7 +54,7 @@ ThisbacksDlg::ThisbacksDlg(const String& scope)
if(q < 0)
return;
const Array<CppItem>& n = BrowserBase()[q];
for(int i = 0; i < n.GetCount(); i++)
for(int i = 0; i < n.GetCount(); i = FindNext(n, i))
nname.Add(n[i].name);
Index<String> done;
GatherCallbacks("", done, scope, PRIVATE);
@ -67,7 +67,8 @@ void ThisbacksDlg::GatherCallbacks(const String& pfx, Index<String>& done,
if(done.Find(h) >= 0)
return;
done.Add(h);
int q = BrowserBase().Find(NoTemplatePars(scope));
Vector<String> tparam;
int q = BrowserBase().Find(ParseTemplatedType(scope, tparam));
if(q < 0)
return;
const Array<CppItem>& n = BrowserBase()[q];
@ -104,7 +105,7 @@ void ThisbacksDlg::GatherCallbacks(const String& pfx, Index<String>& done,
const CppItem& m = n[i];
if(m.IsType() && m.access <= access) {
Vector<String> b = Split(m.qptype, ';');
SubstituteTpars(b, scope);
ResolveTParam(b, tparam);
for(int i = 0; i < b.GetCount(); i++)
GatherCallbacks(pfx, done, b[i], min(access, (int)PROTECTED));
}

View file

@ -12,15 +12,16 @@ void GatherVirtuals(ArrayMap<String, AssistItemInfo>& item, const String& scope,
if(done.Find(scope) >= 0)
return;
done.Add(scope);
int q = BrowserBase().Find(NoTemplatePars(scope));
Vector<String> tparam;
int q = BrowserBase().Find(ParseTemplatedType(scope, tparam));
if(q < 0)
return;
const Array<CppItem>& m = BrowserBase()[q];
for(int i = 0; i < m.GetCount(); i++) {
for(int i = 0; i < m.GetCount(); i = FindNext(m, i)) {
const CppItem& im = m[i];
if(im.IsType()) {
Vector<String> b = Split(im.qptype, ';');
SubstituteTpars(b, scope);
ResolveTParam(b, tparam);
for(int i = 0; i < b.GetCount(); i++)
GatherVirtuals(item, b[i], done);
}

View file

@ -354,9 +354,12 @@ public:
RightTabs();
};
int memcmp_i(const char *s, const char *t, int n);
void SubstituteTpars(Vector<String>& type, const String& tname);
int CharFilterMacro(int c);
int memcmp_i(const char *s, const char *t, int n);
String ParseTemplatedType(const String& type, Vector<String>& tparam);
String ResolveTParam(const String& type, const Vector<String>& tparam);
void ResolveTParam(Vector<String>& type, const Vector<String>& tparam);
String Qualify(const String& scope, const String& type);
int CharFilterMacro(int c);
struct AssistEditor : CodeEditor {
virtual bool Key(dword key, int count);
@ -409,10 +412,14 @@ struct AssistEditor : CodeEditor {
void Complete();
void Context(Parser& parser, int pos);
bool ScopeId(const Array<CppItem>& n, const String& id, Vector<String>& type, bool& code, String& t);
void TypeOf(const String& id, Vector<String>& r, bool& code);
Vector<String> Operator(const char *oper, const Vector<String>& type);
Vector<String> TypeOf(const Vector<String>& xp, const String& tp);
void ExpressionType(const String& type, const Vector<String>& xp, int ii,
Index<String>& typeset, const Vector<String>& tparam,
bool can_shortcut_operator, Index<String>& visited_bases);
void ExpressionType(const String& type, const Vector<String>& xp, int ii,Index<String>& typeset, const Vector<String>& tparam);
void ExpressionType(const String& type, const Vector<String>& xp, int ii,
Index<String>& typeset);
Index<String> ExpressionType(const Parser& parser, const Vector<String>& xp);
String RemoveDefPar(const char *s);
String MakeDefinition(const String& cls, const String& _n);
void DCopy();
@ -423,9 +430,10 @@ struct AssistEditor : CodeEditor {
void SelParam();
int Ch(int q);
int ParsBack(int q);
Vector<String> ReadBack(int q, String& type);
Vector<String> ReadBack(int q);
void SkipSpcBack(int& q);
String IdBack(int& qq);
String CompleteIdBack(int& q);
void SwapSContext(Parser& p);

View file

@ -36,6 +36,7 @@ file
QuickTabs.cpp,
Bottom.cpp,
t.cpp,
Cpp.cpp,
Assist.cpp,
Navigator.cpp,
Annotations.cpp,