From b1769a1d8d8104d18784dade11f6929528d380d1 Mon Sep 17 00:00:00 2001 From: cxl Date: Fri, 10 Oct 2008 15:30:43 +0000 Subject: [PATCH] Major Assist++ refactoring git-svn-id: svn://ultimatepp.org/upp/trunk@514 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/CppBase/CppBase.h | 2 + uppsrc/CppBase/Parser.cpp | 89 ++++---- uppsrc/CppBase/Qualify.cpp | 21 +- uppsrc/CtrlLib/FileSel.cpp | 9 +- uppsrc/ide/Assist.cpp | 440 ++++++++---------------------------- uppsrc/ide/Browser/Base.cpp | 2 +- uppsrc/ide/Cpp.cpp | 291 ++++++++++++++++++++++++ uppsrc/ide/Thisbacks.cpp | 7 +- uppsrc/ide/Virtuals.cpp | 7 +- uppsrc/ide/ide.h | 24 +- uppsrc/ide/ide.upp | 1 + 11 files changed, 478 insertions(+), 415 deletions(-) create mode 100644 uppsrc/ide/Cpp.cpp diff --git a/uppsrc/CppBase/CppBase.h b/uppsrc/CppBase/CppBase.h index 42173adb9..de413e40d 100644 --- a/uppsrc/CppBase/CppBase.h +++ b/uppsrc/CppBase/CppBase.h @@ -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& r, const char *p, bool type_def, bool more); + Array Declaration0(bool l0 = false, bool more = false); Array Declaration(bool l0 = false, bool more = false); bool IsParamList(int q); void Elipsis(Decl& d); diff --git a/uppsrc/CppBase/Parser.cpp b/uppsrc/CppBase/Parser.cpp index bf03aad97..9c0fe396f 100644 --- a/uppsrc/CppBase/Parser.cpp +++ b/uppsrc/CppBase/Parser.cpp @@ -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::Declaration(bool l0, bool more) +Array Parser::Declaration0(bool l0, bool more) { Array 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::Declaration(bool l0, bool more) return r; } +Array Parser::Declaration(bool l0, bool more) +{ + if(Key(tk_typedef)) { + Array 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 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 : diff --git a/uppsrc/CppBase/Qualify.cpp b/uppsrc/CppBase/Qualify.cpp index 4de352cd4..495bf5c3c 100644 --- a/uppsrc/CppBase/Qualify.cpp +++ b/uppsrc/CppBase/Qualify.cpp @@ -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()); diff --git a/uppsrc/CtrlLib/FileSel.cpp b/uppsrc/CtrlLib/FileSel.cpp index e3732b175..4d3cd8f73 100644 --- a/uppsrc/CtrlLib/FileSel.cpp +++ b/uppsrc/CtrlLib/FileSel.cpp @@ -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)) diff --git a/uppsrc/ide/Assist.cpp b/uppsrc/ide/Assist.cpp index 6d25d4c28..516d0156d 100644 --- a/uppsrc/ide/Assist.cpp +++ b/uppsrc/ide/Assist.cpp @@ -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 TemplatePars(const String& type) -{ - Vector 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& type, const String& tname) -{ - Vector 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& n, const String& id, Vector& 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 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& 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 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 AssistEditor::Operator(const char *oper, const Vector& type) -{ - Vector 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 AssistEditor::TypeOf(const Vector& xp, const String& tp) -{ - Vector 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 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& 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(""); - 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& 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& 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 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(va); const CppItemInfo& b = ValueTo(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 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 AssistEditor::ReadBack(int q) { Vector r; type.Clear(); @@ -437,27 +179,27 @@ Vector 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 h = ReadBack(q, tp); - Vector 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 in_types; - GatherItems(type[i], h.GetCount() == 0, in_types, !IsNull(tp) || h.GetCount() == 0); + Index in_types; + if(Ch(q - 1) == ':') { + while(Ch(q - 1) == ':') + q--; + Vector tparam; + GatherItems(ParseTemplatedType(Qualify(parser.current_scope, CompleteIdBack(q)), tparam), + true, in_types, true); + } + else { + String tp; + Vector xp = ReadBack(q); + if(xp.GetCount()) { + Index 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 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 h = ReadBack(GetCursor(), tp); - Vector 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& 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 if(done.Find(scope) >= 0) return Null; done.Add(scope); - String n = NoTemplatePars(scope); + Vector 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 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 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 h = editor.ReadBack(q, tp); - Vector type; + Vector xp = editor.ReadBack(q); + Index 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; } diff --git a/uppsrc/ide/Browser/Base.cpp b/uppsrc/ide/Browser/Base.cpp index 8babc073e..3ab67773d 100644 --- a/uppsrc/ide/Browser/Base.cpp +++ b/uppsrc/ide/Browser/Base.cpp @@ -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() { diff --git a/uppsrc/ide/Cpp.cpp b/uppsrc/ide/Cpp.cpp new file mode 100644 index 000000000..3ce23cb3c --- /dev/null +++ b/uppsrc/ide/Cpp.cpp @@ -0,0 +1,291 @@ +#include "ide.h" + +#define LDUMP(x) //DDUMP(x) +#define LDUMPC(x) //DDUMPC(x) +#define LLOG(x) //DLOG(x) + +static Array sEmpty; + +const Array& GetTypeItems(const String& type) +{ + int q = BrowserBase().Find(type); + if(q < 0) + return sEmpty; + return BrowserBase()[q]; +} + +Vector GetTypeBases(const String& type) +{ + const Array& 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 empty; + return empty; +} + +String ParseTemplatedType(const String& type, Vector& 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& 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& 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& type, const Vector& 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& xp, int ii, + Index& typeset, const Vector& tparam, + bool can_shortcut_operator, Index& visited_bases) +{ + if(ii >= xp.GetCount()) { + LLOG("Final type: " << type); + typeset.FindAdd(type); + return; + } + int c0 = typeset.GetCount(); + const Array& n = GetTypeItems(type); + String id = xp[ii]; + int q = id.ReverseFind(':'); + if(q > 0 && id[q - 1] == ':') { + Vector 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 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 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& xp, int ii, + Index& typeset, const Vector& tparam) +{ + Index visited_bases; + ExpressionType(type, xp, ii, typeset, tparam, true, visited_bases); +} + +void AssistEditor::ExpressionType(const String& type, const Vector& xp, int ii, + Index& typeset) +{ + Vector tparam; + ExpressionType(ParseTemplatedType(type, tparam), xp, ii, typeset, tparam); +} + +Index AssistEditor::ExpressionType(const Parser& parser, const Vector& xp) +{ + String type; + Index 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 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& in_types, bool tp) +{ + LLOG("GatherItems " << type); + if(in_types.Find(type) >= 0) { + LLOG("-> recursion, exiting"); + return; + } + in_types.Add(type); + Vector 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(""); + 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& 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& 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 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(); +} diff --git a/uppsrc/ide/Thisbacks.cpp b/uppsrc/ide/Thisbacks.cpp index d06274543..e7b83f864 100644 --- a/uppsrc/ide/Thisbacks.cpp +++ b/uppsrc/ide/Thisbacks.cpp @@ -54,7 +54,7 @@ ThisbacksDlg::ThisbacksDlg(const String& scope) if(q < 0) return; const Array& 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 done; GatherCallbacks("", done, scope, PRIVATE); @@ -67,7 +67,8 @@ void ThisbacksDlg::GatherCallbacks(const String& pfx, Index& done, if(done.Find(h) >= 0) return; done.Add(h); - int q = BrowserBase().Find(NoTemplatePars(scope)); + Vector tparam; + int q = BrowserBase().Find(ParseTemplatedType(scope, tparam)); if(q < 0) return; const Array& n = BrowserBase()[q]; @@ -104,7 +105,7 @@ void ThisbacksDlg::GatherCallbacks(const String& pfx, Index& done, const CppItem& m = n[i]; if(m.IsType() && m.access <= access) { Vector 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)); } diff --git a/uppsrc/ide/Virtuals.cpp b/uppsrc/ide/Virtuals.cpp index 07d512dd8..d7770c2a8 100644 --- a/uppsrc/ide/Virtuals.cpp +++ b/uppsrc/ide/Virtuals.cpp @@ -12,15 +12,16 @@ void GatherVirtuals(ArrayMap& item, const String& scope, if(done.Find(scope) >= 0) return; done.Add(scope); - int q = BrowserBase().Find(NoTemplatePars(scope)); + Vector tparam; + int q = BrowserBase().Find(ParseTemplatedType(scope, tparam)); if(q < 0) return; const Array& 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 b = Split(im.qptype, ';'); - SubstituteTpars(b, scope); + ResolveTParam(b, tparam); for(int i = 0; i < b.GetCount(); i++) GatherVirtuals(item, b[i], done); } diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index 4298cc3d8..de8c1752f 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -354,9 +354,12 @@ public: RightTabs(); }; -int memcmp_i(const char *s, const char *t, int n); -void SubstituteTpars(Vector& 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& tparam); +String ResolveTParam(const String& type, const Vector& tparam); +void ResolveTParam(Vector& type, const Vector& 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& n, const String& id, Vector& type, bool& code, String& t); - void TypeOf(const String& id, Vector& r, bool& code); - Vector Operator(const char *oper, const Vector& type); - Vector TypeOf(const Vector& xp, const String& tp); + void ExpressionType(const String& type, const Vector& xp, int ii, + Index& typeset, const Vector& tparam, + bool can_shortcut_operator, Index& visited_bases); + void ExpressionType(const String& type, const Vector& xp, int ii,Index& typeset, const Vector& tparam); + void ExpressionType(const String& type, const Vector& xp, int ii, + Index& typeset); + Index ExpressionType(const Parser& parser, const Vector& 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 ReadBack(int q, String& type); + Vector ReadBack(int q); void SkipSpcBack(int& q); String IdBack(int& qq); + String CompleteIdBack(int& q); void SwapSContext(Parser& p); diff --git a/uppsrc/ide/ide.upp b/uppsrc/ide/ide.upp index 72ef84933..beffc16e3 100644 --- a/uppsrc/ide/ide.upp +++ b/uppsrc/ide/ide.upp @@ -36,6 +36,7 @@ file QuickTabs.cpp, Bottom.cpp, t.cpp, + Cpp.cpp, Assist.cpp, Navigator.cpp, Annotations.cpp,