1 #include "ide.h"
2
3 #if 0
4 #define LDUMP(x) DDUMP(x)
5 #define LDUMPC(x) DDUMPC(x)
6 #define LLOG(x) DLOG(x)
7 #else
8 #define LDUMP(x)
9 #define LDUMPC(x)
10 #define LLOG(x)
11 #endif
12
13 #define LTIMING(x) // DTIMING(x)
14
ResolveTParam(const String & type,const Vector<String> & tparam)15 String ResolveTParam(const String& type, const Vector<String>& tparam)
16 {
17 CodeBaseLock __;
18 return ResolveTParam(CodeBase(), type, tparam);
19 }
20
ResolveTParam(Vector<String> & type,const Vector<String> & tparam)21 void ResolveTParam(Vector<String>& type, const Vector<String>& tparam)
22 {
23 CodeBaseLock __;
24 return ResolveTParam(CodeBase(), type, tparam);
25 }
26
Qualify(const String & scope,const String & type,const String & usings)27 String Qualify(const String& scope, const String& type, const String& usings)
28 {
29 CodeBaseLock __;
30 return Qualify(CodeBase(), scope, type, usings);
31 }
32
AssistScanError(int line,const String & text)33 void AssistScanError(int line, const String& text)
34 {
35 #ifdef _DEBUG
36 PutVerbose(String().Cat() << "(" << line << "): " << text);
37 #endif
38 }
39
Context(ParserContext & parser,int pos)40 void AssistEditor::Context(ParserContext& parser, int pos)
41 {
42 LTIMING("Context");
43 LLOG("---------- Context " << path);
44
45 theide->ScanFile(true);
46
47 parser = AssistParse(Get(0, pos), theide->editfile, AssistScanError,
48 [&](String scope, String type, String usings) {
49 CodeBaseLock __;
50 String t = Qualify(CodeBase(), scope, type, usings);
51 return CodeBase().Find(NoTemplatePars(t)) >= 0 ? t : Null;
52 });
53 inbody = parser.IsInBody();
54 #ifdef _DEBUG
55 PutVerbose("body: " + AsString(inbody));
56 PutVerbose("scope: " + AsString(parser.current_scope));
57 PutVerbose("using: " + AsString(parser.context.namespace_using));
58 for(int i = 0; i < parser.local.GetCount(); i++)
59 PutVerbose(parser.local.GetKey(i) + ": " + parser.local[i].type);
60 #endif
61 }
62
EvaluateExpressionType(const ParserContext & parser,const Vector<String> & xp)63 Index<String> AssistEditor::EvaluateExpressionType(const ParserContext& parser, const Vector<String>& xp)
64 {
65 CodeBaseLock __;
66 return GetExpressionType(CodeBase(), parser, xp);
67 }
68
AssistItemAdd(const String & scope,const CppItem & m,int typei)69 void AssistEditor::AssistItemAdd(const String& scope, const CppItem& m, int typei)
70 {
71 if(!iscib(*m.name) || m.name.GetCount() == 0)
72 return;
73 CppItemInfo& f = assist_item.Add();
74 f.typei = typei;
75 f.scope = scope;
76 (CppItem&)f = m;
77 }
78
GatherItems(const String & type,bool only_public,Index<String> & in_types,bool types)79 void AssistEditor::GatherItems(const String& type, bool only_public, Index<String>& in_types, bool types)
80 {
81 LTIMING("GatherItems");
82 LLOG("---- GatherItems " << type);
83 CodeBaseLock __;
84 if(in_types.Find(type) >= 0) {
85 LLOG("-> recursion, exiting");
86 return;
87 }
88 in_types.Add(type);
89 Vector<String> tparam;
90 String ntp = ParseTemplatedType(ResolveTParam(type, tparam), tparam);
91 int q = CodeBase().Find(ntp);
92 if(q < 0) {
93 ntp.Replace("*", ""); // * can be part of type as result of template substitution
94 q = CodeBase().Find(ntp);
95 }
96 if(q >= 0) {
97 if(types) {
98 if(ntp.GetCount())
99 ntp << "::";
100 int typei = assist_type.FindAdd("<types>");
101 for(int i = 0; i < CodeBase().GetCount(); i++) {
102 String nest = CodeBase().GetKey(i);
103 if(nest.GetLength() > ntp.GetLength() && // Subscope of scope
104 memcmp(~ntp, ~nest, ntp.GetLength()) == 0 && // e.g. Upp:: -> Upp::String
105 nest.Find("::", ntp.GetLength()) < 0) { // but not Upp::String::Buffer
106 Array<CppItem>& n = CodeBase()[i];
107 for(int i = 0; i < n.GetCount(); i++) {
108 const CppItem& m = n[i];
109 if(m.IsType())
110 AssistItemAdd(nest, m, typei);
111 }
112 }
113 }
114 }
115 const Array<CppItem>& n = CodeBase()[q];
116 String base;
117 int typei = assist_type.FindAdd(ntp);
118 bool op = only_public;
119 for(int i = 0; i < n.GetCount(); i++)
120 if(n[i].kind == FRIENDCLASS)
121 op = false;
122 for(int i = 0; i < n.GetCount(); i++) {
123 const CppItem& im = n[i];
124 if(im.kind == STRUCT || im.kind == STRUCTTEMPLATE)
125 base << im.qptype << ';';
126 if((im.IsCode() || !thisback && (im.IsData() || im.IsMacro() && IsNull(type)))
127 && (!op || im.access == PUBLIC)) {
128 AssistItemAdd(ntp, im, typei);
129 }
130 }
131 if(!thisback) {
132 Vector<String> b = Split(base, ';');
133 Index<String> h;
134 for(int i = 0; i < b.GetCount(); i++)
135 h.FindAdd(b[i]);
136 b = h.PickKeys();
137 ResolveTParam(b, tparam);
138 for(int i = 0; i < b.GetCount(); i++)
139 if(b[i].GetCount())
140 GatherItems(b[i], only_public, in_types, types);
141 }
142 }
143 in_types.Drop();
144 }
145
OrderAssistItems(const CppItemInfo & a,const CppItemInfo & b)146 bool OrderAssistItems(const CppItemInfo& a, const CppItemInfo& b)
147 {
148 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;
149 }
150
RemoveDuplicates()151 void AssistEditor::RemoveDuplicates()
152 {
153 LTIMING("RemoveDuplicates");
154 { LTIMING("Sort");
155 Upp::Sort(assist_item, OrderAssistItems);
156 }
157 Vector<int> remove;
158 {
159 LTIMING("Find duplicates");
160 int i = 0;
161 while(i < assist_item.GetCount()) { // Remove identical items
162 int ii = i;
163 i++;
164 while(i < assist_item.GetCount()
165 && assist_item[ii].typei == assist_item[i].typei
166 && assist_item[ii].qitem == assist_item[i].qitem
167 && assist_item[ii].scope == assist_item[i].scope)
168 remove.Add(i++);
169 }
170 }
171 LTIMING("Final remove");
172 assist_item.Remove(remove);
173 }
174