mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
cpp: Expression refactored
git-svn-id: svn://ultimatepp.org/upp/trunk@8700 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
650b8be5ac
commit
4ec77506fb
9 changed files with 320 additions and 270 deletions
|
|
@ -617,6 +617,8 @@ public:
|
|||
|
||||
const SrcFile &getPreprocessedFile() { return file; }
|
||||
|
||||
Vector<String> GetNamespaces() const;
|
||||
|
||||
void Do(Stream& in, CppBase& _base, int file, int filetype,
|
||||
const String& title, Callback2<int, const String&> _err,
|
||||
const Vector<String>& typenames,
|
||||
|
|
@ -660,7 +662,12 @@ String QualifyKey(const CppBase& base, const String& scope, const String& type,
|
|||
|
||||
void Qualify(CppBase& base);
|
||||
|
||||
// void Parse(Stream& s, CppBase& base, int file, int filetype, const String& title, Callback2<int, const String&> err);
|
||||
const Array<CppItem>& GetTypeItems(const CppBase& codebase, const String& type);
|
||||
String ParseTemplatedType(const String& type, Vector<String>& tparam);
|
||||
String ResolveTParam(const CppBase& codebase, const String& type, const Vector<String>& tparam);
|
||||
void ResolveTParam(const CppBase& codebase, Vector<String>& type, const Vector<String>& tparam);
|
||||
|
||||
Index<String> GetExpressionType(const CppBase& codebase, const Parser& parser, const Vector<String>& xp);
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ file
|
|||
ScopeInfo.cpp,
|
||||
Qualify.cpp,
|
||||
CppItem.cpp,
|
||||
Expression.cpp,
|
||||
Info readonly separator,
|
||||
Copying;
|
||||
|
||||
|
|
|
|||
289
uppsrc/CppBase/Expression.cpp
Normal file
289
uppsrc/CppBase/Expression.cpp
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
#include "CppBase.h"
|
||||
|
||||
#if 0
|
||||
#define LDUMP(x) DDUMP(x)
|
||||
#define LDUMPC(x) DDUMPC(x)
|
||||
#define LLOG(x) DLOG(x)
|
||||
#else
|
||||
#define LDUMP(x)
|
||||
#define LDUMPC(x)
|
||||
#define LLOG(x)
|
||||
#endif
|
||||
|
||||
#define LTIMING(x) // DTIMING(x)
|
||||
|
||||
namespace Upp {
|
||||
|
||||
const Array<CppItem>& GetTypeItems(const CppBase& codebase, const String& type)
|
||||
{
|
||||
static Array<CppItem> sEmpty;
|
||||
int q = codebase.Find(type);
|
||||
if(q < 0)
|
||||
return sEmpty;
|
||||
return codebase[q];
|
||||
}
|
||||
|
||||
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 == ',' && lvl == 0) {
|
||||
tparam.Add(t);
|
||||
t.Clear();
|
||||
}
|
||||
else {
|
||||
if(c == '>') {
|
||||
if(lvl == 0)
|
||||
break;
|
||||
lvl--;
|
||||
}
|
||||
if(c == '<')
|
||||
lvl++;
|
||||
t.Cat(c);
|
||||
}
|
||||
}
|
||||
tparam.Add(t);
|
||||
break;
|
||||
}
|
||||
else
|
||||
r.Cat(*s++);
|
||||
}
|
||||
LLOG("ParseTemplatedType " << type << " -> " << r);
|
||||
LDUMPC(tparam);
|
||||
return r;
|
||||
}
|
||||
|
||||
String ResolveTParam(const CppBase& codebase, const String& type, const Vector<String>& tparam)
|
||||
{
|
||||
LLOG("ResolveTParam " << type << ' ' << 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(codebase, r);
|
||||
if(x.GetCount() && x[0].kind == TYPEDEF) {
|
||||
LLOG("Is typedef " << x[0].qtype << ';' << x[0].type << ';' << x[0].natural);
|
||||
String h = x[0].qtype;
|
||||
if(h != type && h != r)
|
||||
return ResolveTParam(codebase, h, tparam);
|
||||
return h;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void ResolveTParam(const CppBase& codebase, Vector<String>& type, const Vector<String>& tparam)
|
||||
{
|
||||
for(int i = 0; i < type.GetCount(); i++)
|
||||
type[i] = ResolveTParam(codebase, type[i], tparam);
|
||||
}
|
||||
|
||||
struct ExpressionTyper {
|
||||
const CppBase& codebase;
|
||||
int scan_counter; // limit permutations
|
||||
String context_type;
|
||||
String usings;
|
||||
const Vector<String>& xp;
|
||||
Index<String> typeset;
|
||||
const Parser& parser;
|
||||
|
||||
Vector<String> GetTypeBases(const String& type);
|
||||
String ResolveReturnType(const CppItem& m, const Vector<String>& tparam);
|
||||
|
||||
void ExpressionType(const String& ttype, int ii,
|
||||
bool variable, bool can_shortcut_operator,
|
||||
Index<String>& visited_bases, int lvl);
|
||||
void ExpressionType(const String& ttype, int ii, bool variable, int lvl);
|
||||
|
||||
Index<String> ExpressionType();
|
||||
|
||||
ExpressionTyper(const CppBase& codebase, const Parser& parser, const Vector<String>& xp);
|
||||
};
|
||||
|
||||
ExpressionTyper::ExpressionTyper(const CppBase& codebase, const Parser& parser, const Vector<String>& xp)
|
||||
: codebase(codebase), parser(parser), xp(xp)
|
||||
{
|
||||
scan_counter = 0;
|
||||
context_type = parser.current_scope;
|
||||
usings = parser.context.namespace_using;
|
||||
}
|
||||
|
||||
Vector<String> ExpressionTyper::GetTypeBases(const String& type)
|
||||
{
|
||||
const Array<CppItem>& n = GetTypeItems(codebase, type);
|
||||
String bases;
|
||||
for(int i = 0; i < n.GetCount(); i++) {
|
||||
const CppItem& im = n[i];
|
||||
if(im.IsType())
|
||||
bases << im.qptype << ';';
|
||||
}
|
||||
Index<String> r;
|
||||
Vector<String> h = Split(bases, ';');
|
||||
for(int i = 0; i < h.GetCount(); i++)
|
||||
r.FindAdd(h[i]);
|
||||
return r.PickKeys();
|
||||
}
|
||||
|
||||
String ExpressionTyper::ResolveReturnType(const CppItem& m, const Vector<String>& tparam)
|
||||
{
|
||||
if(m.tparam.GetCount()) {
|
||||
int q = InScListIndex(m.qtype, m.tname);
|
||||
if(q >= 0 && q < tparam.GetCount())
|
||||
return tparam[q];
|
||||
}
|
||||
return m.qtype;
|
||||
}
|
||||
|
||||
void ExpressionTyper::ExpressionType(const String& ttype, int ii,
|
||||
bool variable, bool can_shortcut_operator,
|
||||
Index<String>& visited_bases, int lvl)
|
||||
{
|
||||
LLOG("--- ExpressionType " << scan_counter << ", lvl " << lvl << ", ttype " << ttype);
|
||||
if(++scan_counter > 1000 || lvl > 100) // sort of ugly limitation of parsing permutations
|
||||
return;
|
||||
if(ii >= xp.GetCount()) {
|
||||
LLOG("--- Final type: " << ttype);
|
||||
typeset.FindAdd(ttype);
|
||||
return;
|
||||
}
|
||||
LDUMP(ii);
|
||||
LDUMP(xp[ii]);
|
||||
LDUMP(can_shortcut_operator);
|
||||
Vector<String> tparam;
|
||||
String type = ParseTemplatedType(ttype, tparam);
|
||||
int c0 = typeset.GetCount();
|
||||
const Array<CppItem>& n = GetTypeItems(codebase, type);
|
||||
LDUMP(type);
|
||||
LDUMP(tparam);
|
||||
if(codebase.namespaces.Find(ttype) < 0 && ttype.GetCount()) // do not search for namespace typedefs
|
||||
for(int i = 0; i < n.GetCount(); i++)
|
||||
if(n[i].kind == TYPEDEF) {
|
||||
LLOG("typedef -> " << n[i].qtype);
|
||||
ExpressionType(n[i].qtype, ii, variable, can_shortcut_operator, visited_bases, lvl + 1);
|
||||
return;
|
||||
}
|
||||
String id = xp[ii];
|
||||
int q = id.ReverseFind(':');
|
||||
if(q > 0 && id[q - 1] == ':') {
|
||||
type = ResolveTParam(codebase, Qualify(codebase, ttype, id.Mid(0, q - 1), usings), tparam);
|
||||
id = id.Mid(q + 1);
|
||||
}
|
||||
if(id.Find('<') >= 0) // as in Single<Display>
|
||||
id = ParseTemplatedType(id, tparam);
|
||||
LLOG("ExpressionType " << type << " ii: " << ii << " id:" << id << " variable:" << variable);
|
||||
|
||||
for(int i = 0; i < tparam.GetCount(); i++) // need to qualify template parameters
|
||||
tparam[i] = Qualify(codebase, context_type, tparam[i], usings);
|
||||
|
||||
bool shortcut_oper = false;
|
||||
if(!iscid(*id) && *id != '.') {
|
||||
shortcut_oper = can_shortcut_operator;
|
||||
id = "operator" + id;
|
||||
LLOG("id as: " << id);
|
||||
}
|
||||
if(*id == '.' || (!variable && !iscid(*id))) {
|
||||
LLOG(". " << ttype);
|
||||
ExpressionType(ttype, ii + 1, false, lvl + 1);
|
||||
return;
|
||||
}
|
||||
LDUMP(id);
|
||||
Index<String> done;
|
||||
for(int i = 0; i < n.GetCount(); i++) {
|
||||
const CppItem& m = n[i];
|
||||
if(m.name == id) {
|
||||
LLOG("Member " << m.qtype << " " << m.name);
|
||||
String t = ResolveReturnType(m, tparam);
|
||||
if(done.Find(t) < 0) {
|
||||
bool skipfnpars = m.IsCode() && ii + 1 < xp.GetCount() && xp[ii + 1] == "()";
|
||||
ExpressionType(ResolveTParam(codebase, t, tparam), ii + skipfnpars + 1,
|
||||
m.IsData() && !m.isptr, lvl + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(typeset.GetCount() != c0 || IsNull(type))
|
||||
return;
|
||||
Vector<String> base = GetTypeBases(type);
|
||||
LDUMPC(base);
|
||||
ResolveTParam(codebase, base, tparam);
|
||||
LDUMPC(base);
|
||||
for(int i = 0; i < base.GetCount(); i++)
|
||||
if(visited_bases.Find(base[i]) < 0) {
|
||||
visited_bases.Add(base[i]);
|
||||
ExpressionType(base[i], ii, variable, false, visited_bases, lvl + 1);
|
||||
if(typeset.GetCount() != c0)
|
||||
return;
|
||||
}
|
||||
|
||||
if(shortcut_oper) {
|
||||
LLOG("Shortcut " << xp[ii] << ", ttype " << ttype);
|
||||
ExpressionType(ttype, ii + 1, false, lvl + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionTyper::ExpressionType(const String& ttype, int ii, bool variable, int lvl)
|
||||
{
|
||||
Index<String> bases;
|
||||
ExpressionType(ttype, ii, false, true, bases, 0);
|
||||
}
|
||||
|
||||
Index<String> ExpressionTyper::ExpressionType()
|
||||
{
|
||||
LLOG("**** ExpressionType " << xp);
|
||||
String type;
|
||||
if(xp.GetCount() == 0)
|
||||
return typeset;
|
||||
if(xp[0] == "this") {
|
||||
LLOG("this: " << type);
|
||||
ExpressionType(context_type, 1, false, 0);
|
||||
return typeset;
|
||||
}
|
||||
int q = parser.local.FindLast(xp[0]);
|
||||
if(q >= 0) {
|
||||
String type = Qualify(codebase, context_type, parser.local[q].type, parser.context.namespace_using);
|
||||
LLOG("Found type local: " << type << " in scope: " << context_type);
|
||||
ExpressionType(type, 1, !parser.local[q].isptr, 0);
|
||||
return typeset;
|
||||
}
|
||||
ExpressionType(context_type, 0, false, 0);
|
||||
if(typeset.GetCount())
|
||||
return typeset;
|
||||
if(xp.GetCount() >= 2 && xp[1] == "()") {
|
||||
String qtype = Qualify(codebase, context_type, xp[0], parser.context.namespace_using);
|
||||
Vector<String> tparam;
|
||||
if(codebase.Find(ParseTemplatedType(qtype, tparam)) >= 0) {
|
||||
LLOG("Is constructor " << qtype);
|
||||
ExpressionType(qtype, 2, false, 0);
|
||||
return typeset;
|
||||
}
|
||||
}
|
||||
Vector<String> ns = parser.GetNamespaces();
|
||||
for(int i = 0; i < ns.GetCount(); i++)
|
||||
ExpressionType(ns[i], 0, false, 0);
|
||||
return typeset;
|
||||
}
|
||||
|
||||
Index<String> GetExpressionType(const CppBase& codebase, const Parser& parser, const Vector<String>& xp)
|
||||
{ // xp is a list of meaningful parts like "foo", "." , "Fn", "()", "->", "m", "[]"
|
||||
return ExpressionTyper(codebase, parser, xp).ExpressionType();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1798,13 +1798,17 @@ void Parser::Do(Stream& in, CppBase& _base, int filei_, int filetype_,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void Parse(Stream& s, CppBase& base, int file, int filetype, const String& title, Callback2<int, const String&> _err)
|
||||
Vector<String> Parser::GetNamespaces() const
|
||||
{
|
||||
LTIMING("Parse");
|
||||
Parser p;
|
||||
p.Do(s, base, file, filetype, title, _err);
|
||||
Vector<String> ns;
|
||||
Vector<String> h = Split(current_scope, ':');
|
||||
while(h.GetCount()) {
|
||||
ns.Add(Join(h, "::"));
|
||||
h.Drop();
|
||||
}
|
||||
ns.Append(Split(context.namespace_using, ';'));
|
||||
ns.Add(""); // Add global namespace too
|
||||
return ns;
|
||||
}
|
||||
*/
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -476,7 +476,7 @@ void AssistEditor::Assist()
|
|||
}
|
||||
else {
|
||||
GatherItems(parser.current_scope, false, in_types, true);
|
||||
Vector<String> ns = GetNamespaces(parser);
|
||||
Vector<String> ns = parser.GetNamespaces();
|
||||
for(int i = 0; i < ns.GetCount(); i++)
|
||||
if(parser.current_scope != ns[i]) // Do not scan namespace already scanned
|
||||
GatherItems(ns[i], false, in_types, true);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
Vector<String> GetNamespaces(const Parser& parser);
|
||||
|
||||
struct Navigator {
|
||||
virtual int GetCurrentLine() = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ void Ide::ContextGoto0(int pos)
|
|||
}
|
||||
}
|
||||
|
||||
Vector<String> ns = GetNamespaces(parser);
|
||||
Vector<String> ns = parser.GetNamespaces();
|
||||
|
||||
if(qual.GetCount()) { // Ctrl::MOUSELEFT, Vector<String>::Iterator
|
||||
Vector<String> todo;
|
||||
|
|
|
|||
|
|
@ -12,103 +12,19 @@
|
|||
|
||||
#define LTIMING(x) // DTIMING(x)
|
||||
|
||||
static Array<CppItem> sEmpty;
|
||||
|
||||
const Array<CppItem>& GetTypeItems(const String& type)
|
||||
{
|
||||
int q = CodeBase().Find(type);
|
||||
if(q < 0)
|
||||
return sEmpty;
|
||||
return CodeBase()[q];
|
||||
}
|
||||
|
||||
Vector<String> GetTypeBases(const String& type)
|
||||
{
|
||||
const Array<CppItem>& n = GetTypeItems(type);
|
||||
String bases;
|
||||
for(int i = 0; i < n.GetCount(); i++) {
|
||||
const CppItem& im = n[i];
|
||||
if(im.IsType())
|
||||
bases << im.qptype << ';';
|
||||
}
|
||||
Index<String> r;
|
||||
Vector<String> h = Split(bases, ';');
|
||||
for(int i = 0; i < h.GetCount(); i++)
|
||||
r.FindAdd(h[i]);
|
||||
return r.PickKeys();
|
||||
}
|
||||
|
||||
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 == ',' && lvl == 0) {
|
||||
tparam.Add(t);
|
||||
t.Clear();
|
||||
}
|
||||
else {
|
||||
if(c == '>') {
|
||||
if(lvl == 0)
|
||||
break;
|
||||
lvl--;
|
||||
}
|
||||
if(c == '<')
|
||||
lvl++;
|
||||
t.Cat(c);
|
||||
}
|
||||
}
|
||||
tparam.Add(t);
|
||||
break;
|
||||
}
|
||||
else
|
||||
r.Cat(*s++);
|
||||
}
|
||||
LLOG("ParseTemplatedType " << type << " -> " << r);
|
||||
LDUMPC(tparam);
|
||||
return r;
|
||||
}
|
||||
|
||||
String ResolveTParam(const String& type, const Vector<String>& tparam)
|
||||
{
|
||||
LLOG("ResolveTParam " << type << ' ' << 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 << ';' << x[0].type << ';' << x[0].natural);
|
||||
String h = x[0].qtype;
|
||||
if(h != type && h != r)
|
||||
return ResolveTParam(h, tparam);
|
||||
return h;
|
||||
}
|
||||
return r;
|
||||
return ResolveTParam(CodeBase(), type, tparam);
|
||||
}
|
||||
|
||||
void ResolveTParam(Vector<String>& type, const Vector<String>& tparam)
|
||||
{
|
||||
for(int i = 0; i < type.GetCount(); i++)
|
||||
type[i] = ResolveTParam(type[i], tparam);
|
||||
return ResolveTParam(CodeBase(), type, tparam);
|
||||
}
|
||||
|
||||
String Qualify(const String& scope, const String& type, const String& usings)
|
||||
{
|
||||
return Qualify(CodeBase(), scope, type, usings);
|
||||
}
|
||||
|
||||
void AssistScanError(int line, const String& text)
|
||||
|
|
@ -149,175 +65,9 @@ void AssistEditor::Context(Parser& parser, int pos)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
Vector<String> GetNamespaces(const Parser& parser)
|
||||
{
|
||||
Vector<String> ns;
|
||||
Vector<String> h = Split(parser.current_scope, ':');
|
||||
while(h.GetCount()) {
|
||||
ns.Add(Join(h, "::"));
|
||||
h.Drop();
|
||||
}
|
||||
ns.Append(Split(parser.context.namespace_using, ';'));
|
||||
ns.Add(""); // Add global namespace too
|
||||
return ns;
|
||||
}
|
||||
|
||||
String Qualify(const String& scope, const String& type, const String& usings)
|
||||
{
|
||||
return Qualify(CodeBase(), scope, type, usings);
|
||||
}
|
||||
|
||||
String ResolveReturnType(const CppItem& m, const Vector<String>& tparam)
|
||||
{
|
||||
if(m.tparam.GetCount()) {
|
||||
int q = InScListIndex(m.qtype, m.tname);
|
||||
if(q >= 0 && q < tparam.GetCount())
|
||||
return tparam[q];
|
||||
}
|
||||
return m.qtype;
|
||||
}
|
||||
|
||||
void AssistEditor::ExpressionType(const String& ttype,
|
||||
const String& context_type,
|
||||
const String& usings,
|
||||
const Vector<String>& xp, int ii,
|
||||
Index<String>& typeset, bool variable,
|
||||
bool can_shortcut_operator, Index<String>& visited_bases,
|
||||
int lvl)
|
||||
{
|
||||
LLOG("--- ExpressionType " << scan_counter << ", lvl " << lvl << ", ttype " << ttype);
|
||||
if(++scan_counter > 1000 || lvl > 100) // sort of ugly limitation of parsing permutations
|
||||
return;
|
||||
if(ii >= xp.GetCount()) {
|
||||
LLOG("--- Final type: " << ttype);
|
||||
typeset.FindAdd(ttype);
|
||||
return;
|
||||
}
|
||||
LDUMP(ii);
|
||||
LDUMP(xp[ii]);
|
||||
LDUMP(can_shortcut_operator);
|
||||
Vector<String> tparam;
|
||||
String type = ParseTemplatedType(ttype, tparam);
|
||||
int c0 = typeset.GetCount();
|
||||
const Array<CppItem>& n = GetTypeItems(type);
|
||||
LDUMP(type);
|
||||
LDUMP(tparam);
|
||||
if(CodeBase().namespaces.Find(ttype) < 0 && ttype.GetCount()) // do not search for namespace typedefs
|
||||
for(int i = 0; i < n.GetCount(); i++)
|
||||
if(n[i].kind == TYPEDEF) {
|
||||
LLOG("typedef -> " << n[i].qtype);
|
||||
ExpressionType(n[i].qtype, context_type, usings, xp, ii, typeset, variable, can_shortcut_operator, visited_bases, lvl + 1);
|
||||
return;
|
||||
}
|
||||
String id = xp[ii];
|
||||
int q = id.ReverseFind(':');
|
||||
if(q > 0 && id[q - 1] == ':') {
|
||||
type = ResolveTParam(Qualify(ttype, id.Mid(0, q - 1), usings), tparam);
|
||||
id = id.Mid(q + 1);
|
||||
}
|
||||
if(id.Find('<') >= 0) // as in Single<Display>
|
||||
id = ParseTemplatedType(id, tparam);
|
||||
LLOG("ExpressionType " << type << " ii: " << ii << " id:" << id << " variable:" << variable);
|
||||
|
||||
for(int i = 0; i < tparam.GetCount(); i++) // need to qualify template parameters
|
||||
tparam[i] = Qualify(context_type, tparam[i], usings);
|
||||
|
||||
bool shortcut_oper = false;
|
||||
if(!iscid(*id) && *id != '.') {
|
||||
shortcut_oper = can_shortcut_operator;
|
||||
id = "operator" + id;
|
||||
LLOG("id as: " << id);
|
||||
}
|
||||
if(*id == '.' || (!variable && !iscid(*id))) {
|
||||
LLOG(". " << ttype);
|
||||
ExpressionType(ttype, context_type, usings, xp, ii + 1, typeset, false, lvl + 1);
|
||||
return;
|
||||
}
|
||||
LDUMP(id);
|
||||
Index<String> done;
|
||||
for(int i = 0; i < n.GetCount(); i++) {
|
||||
const CppItem& m = n[i];
|
||||
if(m.name == id) {
|
||||
LLOG("Member " << m.qtype << " " << m.name);
|
||||
String t = ResolveReturnType(m, tparam);
|
||||
if(done.Find(t) < 0) {
|
||||
bool skipfnpars = m.IsCode() && ii + 1 < xp.GetCount() && xp[ii + 1] == "()";
|
||||
ExpressionType(ResolveTParam(t, tparam), context_type, usings, xp, ii + skipfnpars + 1,
|
||||
typeset, m.IsData() && !m.isptr, lvl + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(typeset.GetCount() != c0 || IsNull(type))
|
||||
return;
|
||||
Vector<String> base = GetTypeBases(type);
|
||||
LDUMPC(base);
|
||||
ResolveTParam(base, tparam);
|
||||
LDUMPC(base);
|
||||
for(int i = 0; i < base.GetCount(); i++)
|
||||
if(visited_bases.Find(base[i]) < 0) {
|
||||
visited_bases.Add(base[i]);
|
||||
ExpressionType(base[i], context_type, usings, xp, ii, typeset, variable, false, visited_bases, lvl + 1);
|
||||
if(typeset.GetCount() != c0)
|
||||
return;
|
||||
}
|
||||
|
||||
if(shortcut_oper) {
|
||||
LLOG("Shortcut " << xp[ii] << ", ttype " << ttype);
|
||||
ExpressionType(ttype, context_type, usings, xp, ii + 1, typeset, false, lvl + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AssistEditor::ExpressionType(const String& type, const String& context_type,
|
||||
const String& usings, const Vector<String>& xp, int ii,
|
||||
Index<String>& typeset, bool variable, int lvl)
|
||||
{
|
||||
Index<String> visited_bases;
|
||||
ExpressionType(type, context_type, usings, xp, ii, typeset, variable, true, visited_bases, lvl);
|
||||
}
|
||||
|
||||
Index<String> AssistEditor::ExpressionType(const Parser& parser, const Vector<String>& xp)
|
||||
{
|
||||
LLOG("**** ExpressionType " << xp);
|
||||
String type;
|
||||
Index<String> typeset;
|
||||
if(xp.GetCount() == 0)
|
||||
return typeset;
|
||||
if(xp[0] == "this") {
|
||||
LLOG("this: " << type);
|
||||
ExpressionType(parser.current_scope, parser.current_scope, parser.context.namespace_using, xp, 1, typeset, false, 0);
|
||||
return typeset;
|
||||
}
|
||||
int q = parser.local.FindLast(xp[0]);
|
||||
if(q >= 0) {
|
||||
String type = Qualify(parser.current_scope, parser.local[q].type, parser.context.namespace_using);
|
||||
LLOG("Found type local: " << type << " in scope: " << parser.current_scope);
|
||||
ExpressionType(type, parser.current_scope, parser.context.namespace_using, xp, 1, typeset, !parser.local[q].isptr, 0);
|
||||
return typeset;
|
||||
}
|
||||
ExpressionType(parser.current_scope, parser.current_scope, parser.context.namespace_using, xp, 0, typeset, false, 0);
|
||||
if(typeset.GetCount())
|
||||
return typeset;
|
||||
if(xp.GetCount() >= 2 && xp[1] == "()") {
|
||||
String qtype = Qualify(parser.current_scope, xp[0], parser.context.namespace_using);
|
||||
Vector<String> tparam;
|
||||
if(CodeBase().Find(ParseTemplatedType(qtype, tparam)) >= 0) {
|
||||
LLOG("Is constructor " << qtype);
|
||||
ExpressionType(qtype, parser.current_scope, parser.context.namespace_using, xp, 2, typeset, false, 0);
|
||||
return typeset;
|
||||
}
|
||||
}
|
||||
Vector<String> ns = GetNamespaces(parser);
|
||||
for(int i = 0; i < ns.GetCount(); i++)
|
||||
ExpressionType(ns[i], parser.current_scope, parser.context.namespace_using, xp, 0, typeset, false, 0);
|
||||
return typeset;
|
||||
}
|
||||
|
||||
Index<String> AssistEditor::EvaluateExpressionType(const Parser& parser, const Vector<String>& xp)
|
||||
{
|
||||
scan_counter = 0;
|
||||
return ExpressionType(parser, xp);
|
||||
return GetExpressionType(CodeBase(), parser, xp);
|
||||
}
|
||||
|
||||
void AssistEditor::AssistItemAdd(const String& scope, const CppItem& m, int typei)
|
||||
|
|
|
|||
|
|
@ -284,10 +284,11 @@ public:
|
|||
};
|
||||
|
||||
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, const String& usings);
|
||||
|
||||
int CharFilterMacro(int c);
|
||||
int CharFilterFileName(int c);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue