#include "ide.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) String ResolveTParam(const String& type, const Vector& tparam) { CodeBaseLock __; return ResolveTParam(CodeBase(), type, tparam); } void ResolveTParam(Vector& type, const Vector& tparam) { CodeBaseLock __; return ResolveTParam(CodeBase(), type, tparam); } String Qualify(const String& scope, const String& type, const String& usings) { CodeBaseLock __; return Qualify(CodeBase(), scope, type, usings); } void AssistScanError(int line, const String& text) { #ifdef _DEBUG PutVerbose(String().Cat() << "(" << line << "): " << text); #endif } void AssistEditor::Context(ParserContext& parser, int pos) { LTIMING("Context"); LLOG("---------- Context " << path); theide->ScanFile(true); parser = AssistParse(Get(0, pos), theide->editfile, AssistScanError, [&](String scope, String type, String usings) { CodeBaseLock __; String t = Qualify(CodeBase(), scope, type, usings); return CodeBase().Find(NoTemplatePars(t)) >= 0 ? t : Null; }); inbody = parser.IsInBody(); #ifdef _DEBUG PutVerbose("body: " + AsString(inbody)); PutVerbose("scope: " + AsString(parser.current_scope)); PutVerbose("using: " + AsString(parser.context.namespace_using)); for(int i = 0; i < parser.local.GetCount(); i++) PutVerbose(parser.local.GetKey(i) + ": " + parser.local[i].type); #endif } Index AssistEditor::EvaluateExpressionType(const ParserContext& parser, const Vector& xp) { CodeBaseLock __; return GetExpressionType(CodeBase(), parser, xp); } void AssistEditor::AssistItemAdd(const String& scope, const CppItem& m, int typei) { if(!iscib(*m.name) || m.name.GetCount() == 0) return; CppItemInfo& f = assist_item.Add(); f.typei = typei; f.scope = scope; (CppItem&)f = m; } void AssistEditor::GatherItems(const String& type, bool only_public, Index& in_types, bool types) { LTIMING("GatherItems"); LLOG("---- GatherItems " << type); CodeBaseLock __; if(in_types.Find(type) >= 0) { LLOG("-> recursion, exiting"); return; } in_types.Add(type); Vector tparam; String ntp = ParseTemplatedType(ResolveTParam(type, tparam), tparam); int q = CodeBase().Find(ntp); if(q < 0) { ntp.Replace("*", ""); // * can be part of type as result of template substitution q = CodeBase().Find(ntp); } if(q >= 0) { if(types) { if(ntp.GetCount()) ntp << "::"; int typei = assist_type.FindAdd(""); for(int i = 0; i < CodeBase().GetCount(); i++) { String nest = CodeBase().GetKey(i); if(nest.GetLength() > ntp.GetLength() && // Subscope of scope memcmp(~ntp, ~nest, ntp.GetLength()) == 0 && // e.g. Upp:: -> Upp::String nest.Find("::", ntp.GetLength()) < 0) { // but not Upp::String::Buffer Array& n = CodeBase()[i]; for(int i = 0; i < n.GetCount(); i++) { const CppItem& m = n[i]; if(m.IsType()) AssistItemAdd(nest, m, typei); } } } } const Array& n = CodeBase()[q]; String base; int typei = assist_type.FindAdd(ntp); bool op = only_public; for(int i = 0; i < n.GetCount(); i++) if(n[i].kind == FRIENDCLASS) op = false; for(int i = 0; i < n.GetCount(); i++) { const CppItem& im = n[i]; if(im.kind == STRUCT || im.kind == STRUCTTEMPLATE) base << im.qptype << ';'; if((im.IsCode() || !thisback && (im.IsData() || im.IsMacro() && IsNull(type))) && (!op || im.access == PUBLIC)) { AssistItemAdd(ntp, im, typei); } } if(!thisback) { Vector b = Split(base, ';'); Index h; for(int i = 0; i < b.GetCount(); i++) h.FindAdd(b[i]); b = h.PickKeys(); ResolveTParam(b, tparam); for(int i = 0; i < b.GetCount(); i++) if(b[i].GetCount()) GatherItems(b[i], only_public, in_types, types); } } in_types.Drop(); } bool OrderAssistItems(const CppItemInfo& a, const CppItemInfo& b) { return CombineCompare(a.uname, b.uname)(a.typei, b.typei)(a.qitem, b.qitem)(a.impl, b.impl)(a.filetype, b.filetype)(a.line, b.line) < 0; } void AssistEditor::RemoveDuplicates() { LTIMING("RemoveDuplicates"); { LTIMING("Sort"); Upp::Sort(assist_item, OrderAssistItems); } Vector remove; { LTIMING("Find duplicates"); int i = 0; while(i < assist_item.GetCount()) { // Remove identical items int ii = i; i++; while(i < assist_item.GetCount() && assist_item[ii].typei == assist_item[i].typei && assist_item[ii].qitem == assist_item[i].qitem && assist_item[ii].scope == assist_item[i].scope) remove.Add(i++); } } LTIMING("Final remove"); assist_item.Remove(remove); }