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