55
66#include < model/file.h>
77#include < model/file-odb.hxx>
8+ #include < model/position.h>
89
910using namespace cc ;
1011using namespace cc ::service::language;
@@ -22,42 +23,324 @@ class PythonServiceTest : public ::testing::Test
2223 webserver::ServerContext (std::string(), boost::program_options::variables_map()))
2324 )
2425 {
25- }
26-
27- model::File queryFile (const std::string& filename)
28- {
29- return _transaction ([&, this ]() {
30- return _db->query_value <model::File>(odb::query<model::File>::filename == filename);
31- });
26+ loadFile (" functions.py" );
27+ loadFile (" classes.py" );
28+ loadFile (" imports.py" );
3229 }
3330
3431 AstNodeInfo getAstNodeInfoByPosition (const std::string& filename, int32_t line, int32_t column)
3532 {
36- model::File file = queryFile (filename);
33+ AstNodeInfo nodeInfo;
34+
35+ if (m_files.count (filename) == 0 )
36+ {
37+ return nodeInfo;
38+ }
39+
40+ model::FileId file_id = m_files[filename];
3741
3842 service::core::FilePosition filePos;
39- filePos.file = std::to_string (file. id );
43+ filePos.file = std::to_string (file_id );
4044 filePos.pos .line = line;
4145 filePos.pos .column = column;
4246
43- AstNodeInfo nodeInfo;
4447 _pythonservice->getAstNodeInfoByPosition (nodeInfo, filePos);
4548 return nodeInfo;
4649 }
4750
51+ size_t referenceFinder (const std::vector<AstNodeInfo>& references,
52+ const std::vector<model::Position>& positions)
53+ {
54+ size_t c = 0 ;
55+ for (const AstNodeInfo& info : references)
56+ {
57+ size_t line = info.range .range .startpos .line ;
58+ size_t column = info.range .range .startpos .column ;
59+
60+ for (const model::Position& pos : positions)
61+ {
62+ if (pos.line == line && pos.column == column) c++;
63+ }
64+ }
65+
66+ return c;
67+ }
68+
4869private:
4970 std::shared_ptr<odb::database> _db;
5071 util::OdbTransaction _transaction;
72+ std::unordered_map<std::string, std::uint64_t > m_files;
73+ void loadFile (const std::string& filename)
74+ {
75+ _transaction ([&, this ]() {
76+ model::File file = _db->query_value <model::File>(odb::query<model::File>::filename == filename);
77+ m_files.emplace (filename, file.id );
78+ });
79+ }
5180
5281protected:
5382 std::shared_ptr<PythonServiceHandler> _pythonservice;
5483};
5584
5685TEST_F (PythonServiceTest, AstNodeInfoByPosition)
5786{
87+ AstNodeInfo nodeInfo;
88+
5889 // Simulating click on line 1 column 5
59- AstNodeInfo nodeInfo = getAstNodeInfoByPosition (" functions.py" , 1 , 5 );
90+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 1 , 5 );
6091
6192 EXPECT_EQ (nodeInfo.astNodeValue , " def hello_world()" );
6293 EXPECT_EQ (nodeInfo.symbolType , " function" );
94+
95+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 14 , 12 );
96+
97+ EXPECT_EQ (nodeInfo.astNodeValue , " mul" );
98+ EXPECT_EQ (nodeInfo.symbolType , " statement" );
99+
100+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 24 , 10 );
101+
102+ EXPECT_EQ (nodeInfo.astNodeValue , " MyLib" );
103+ EXPECT_EQ (nodeInfo.symbolType , " statement" );
104+ }
105+
106+ TEST_F (PythonServiceTest, NodeProperties)
107+ {
108+ AstNodeInfo nodeInfo;
109+
110+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 7 , 5 );
111+ std::map<std::string, std::string> map;
112+
113+ _pythonservice->getProperties (map, nodeInfo.id );
114+ EXPECT_EQ (nodeInfo.astNodeValue , " def mul(a, b)" );
115+
116+ EXPECT_EQ (map.count (" Full name" ), 1 );
117+ EXPECT_EQ (map[" Full name" ], " functions.mul" );
118+ EXPECT_EQ (map.count (" Builtin" ), 1 );
119+ EXPECT_EQ (map[" Builtin" ], " false" );
120+ EXPECT_EQ (map.count (" Function call" ), 1 );
121+ EXPECT_EQ (map[" Function call" ], " false" );
122+ }
123+
124+ TEST_F (PythonServiceTest, NodePropertiesBuiltinCall)
125+ {
126+ AstNodeInfo nodeInfo;
127+
128+ nodeInfo = getAstNodeInfoByPosition (" imports.py" , 12 , 17 );
129+ EXPECT_EQ (nodeInfo.astNodeValue , " getpid" );
130+
131+ std::map<std::string, std::string> map;
132+
133+ _pythonservice->getProperties (map, nodeInfo.id );
134+ EXPECT_EQ (map.count (" Full name" ), 1 );
135+ EXPECT_EQ (map[" Full name" ], " imports.getpid" );
136+ EXPECT_EQ (map.count (" Builtin" ), 1 );
137+ EXPECT_EQ (map[" Builtin" ], " true" );
138+ EXPECT_EQ (map.count (" Function call" ), 1 );
139+ EXPECT_EQ (map[" Function call" ], " true" );
140+ }
141+
142+ TEST_F (PythonServiceTest, NodeDefinition)
143+ {
144+ AstNodeInfo nodeInfo;
145+ std::vector<AstNodeInfo> references;
146+
147+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 11 , 12 );
148+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::DEFINITION, {});
149+
150+ EXPECT_EQ (references.size (), 1 );
151+ EXPECT_EQ (references[0 ].symbolType , " function" );
152+ EXPECT_EQ (references[0 ].astNodeValue , " def mul(a, b)" );
153+
154+ references = {};
155+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 29 , 6 );
156+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::DEFINITION, {});
157+
158+ EXPECT_EQ (references.size (), 1 );
159+ EXPECT_EQ (references[0 ].symbolType , " statement" );
160+ EXPECT_EQ (references[0 ].astNodeValue , " mylib = {\n " );
161+
162+ references = {};
163+ nodeInfo = getAstNodeInfoByPosition (" classes.py" , 27 , 8 );
164+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::DEFINITION, {});
165+
166+ EXPECT_EQ (references.size (), 1 );
167+ EXPECT_EQ (references[0 ].symbolType , " class" );
168+ EXPECT_EQ (references[0 ].astNodeValue , " class Base:\n " );
169+ }
170+
171+ TEST_F (PythonServiceTest, NodeUsage)
172+ {
173+ AstNodeInfo nodeInfo;
174+ std::vector<AstNodeInfo> references;
175+
176+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 16 , 1 );
177+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::USAGE, {});
178+
179+ EXPECT_EQ (nodeInfo.astNodeValue , " mylib = {\n " );
180+ EXPECT_EQ (references.size (), 2 );
181+
182+ size_t found = referenceFinder (references, {{29 , 6 }, {46 , 11 }});
183+ EXPECT_EQ (found, references.size ());
184+ }
185+
186+ TEST_F (PythonServiceTest, NodeDataMembers)
187+ {
188+ AstNodeInfo nodeInfo;
189+ std::vector<AstNodeInfo> references;
190+
191+ nodeInfo = getAstNodeInfoByPosition (" classes.py" , 1 , 1 );
192+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::DATA_MEMBER, {});
193+
194+ EXPECT_EQ (nodeInfo.astNodeValue , " class Base:\n " );
195+ EXPECT_EQ (references.size (), 2 );
196+
197+ size_t found = referenceFinder (references, {{2 , 5 }, {3 , 5 }});
198+ EXPECT_EQ (found, references.size ());
199+ }
200+
201+ TEST_F (PythonServiceTest, NodeLocalVariables)
202+ {
203+ AstNodeInfo nodeInfo;
204+ std::vector<AstNodeInfo> references;
205+
206+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 96 , 1 );
207+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::LOCAL_VAR, {});
208+
209+ EXPECT_EQ (nodeInfo.astNodeValue , " def local_var()" );
210+ EXPECT_EQ (references.size (), 3 );
211+
212+ size_t found = referenceFinder (references, {{97 , 5 }, {98 , 5 }, {99 , 9 }});
213+ EXPECT_EQ (found, references.size ());
214+ }
215+
216+ TEST_F (PythonServiceTest, NodeParent)
217+ {
218+ AstNodeInfo nodeInfo;
219+ std::vector<AstNodeInfo> references;
220+
221+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 97 , 5 );
222+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::PARENT, {});
223+
224+ EXPECT_EQ (nodeInfo.astNodeValue , " a = 2" );
225+ EXPECT_EQ (references.size (), 1 );
226+
227+ size_t found = referenceFinder (references, {{96 , 1 }});
228+ EXPECT_EQ (found, references.size ());
229+ }
230+
231+ TEST_F (PythonServiceTest, NodeParentFunction)
232+ {
233+ AstNodeInfo nodeInfo;
234+ std::vector<AstNodeInfo> references;
235+
236+ nodeInfo = getAstNodeInfoByPosition (" classes.py" , 31 , 9 );
237+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::PARENT_FUNCTION, {});
238+
239+ EXPECT_EQ (nodeInfo.astNodeValue , " z = 2" );
240+ EXPECT_EQ (references.size (), 1 );
241+
242+ size_t found = referenceFinder (references, {{29 , 1 }});
243+ EXPECT_EQ (found, references.size ());
244+ }
245+
246+ TEST_F (PythonServiceTest, NodeCaller)
247+ {
248+ AstNodeInfo nodeInfo;
249+ std::vector<AstNodeInfo> references;
250+
251+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 13 , 1 );
252+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::CALLER, {});
253+
254+ EXPECT_EQ (nodeInfo.astNodeValue , " def mul3()" );
255+ EXPECT_EQ (references.size (), 2 );
256+
257+ size_t found = referenceFinder (references, {{28 , 6 }, {45 , 11 }});
258+ EXPECT_EQ (found, references.size ());
259+ }
260+
261+ TEST_F (PythonServiceTest, NodeThisCalls)
262+ {
263+ AstNodeInfo nodeInfo;
264+ std::vector<AstNodeInfo> references;
265+
266+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 10 , 1 );
267+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::THIS_CALLS, {});
268+
269+ EXPECT_EQ (nodeInfo.astNodeValue , " def mul2(a, b)" );
270+ EXPECT_EQ (references.size (), 1 );
271+
272+ size_t found = referenceFinder (references, {{11 , 12 }});
273+ EXPECT_EQ (found, references.size ());
274+ }
275+
276+ TEST_F (PythonServiceTest, NodeMethod)
277+ {
278+ AstNodeInfo nodeInfo;
279+ std::vector<AstNodeInfo> references;
280+
281+ nodeInfo = getAstNodeInfoByPosition (" classes.py" , 1 , 1 );
282+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::METHOD, {});
283+
284+ EXPECT_EQ (nodeInfo.astNodeValue , " class Base:\n " );
285+ EXPECT_EQ (references.size (), 3 );
286+
287+ size_t found = referenceFinder (references, {{5 , 5 }, {8 , 5 }, {11 , 5 }});
288+ EXPECT_EQ (found, references.size ());
289+ }
290+
291+ TEST_F (PythonServiceTest, NodeBaseClass)
292+ {
293+ AstNodeInfo nodeInfo;
294+ std::vector<AstNodeInfo> references;
295+
296+ nodeInfo = getAstNodeInfoByPosition (" classes.py" , 19 , 1 );
297+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::BASE_CLASS, {});
298+
299+ EXPECT_EQ (nodeInfo.astNodeValue , " class Derived(Base):\n " );
300+ EXPECT_EQ (references.size (), 1 );
301+
302+ size_t found = referenceFinder (references, {{1 , 1 }});
303+ EXPECT_EQ (found, references.size ());
304+
305+ // ----------
306+
307+ references = {};
308+ nodeInfo = getAstNodeInfoByPosition (" classes.py" , 23 , 1 );
309+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::BASE_CLASS, {});
310+
311+ EXPECT_EQ (nodeInfo.astNodeValue , " class Derived2(Derived, Base):\n " );
312+ EXPECT_EQ (references.size (), 2 );
313+
314+ found = referenceFinder (references, {{1 , 1 }, {19 , 1 }});
315+ EXPECT_EQ (found, references.size ());
316+ }
317+
318+ TEST_F (PythonServiceTest, NodeFunctionParam)
319+ {
320+ AstNodeInfo nodeInfo;
321+ std::vector<AstNodeInfo> references;
322+
323+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 4 , 1 );
324+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::PARAMETER, {});
325+
326+ EXPECT_EQ (nodeInfo.astNodeValue , " def runner(func, param1, param2)" );
327+ EXPECT_EQ (references.size (), 3 );
328+
329+ size_t found = referenceFinder (references, {{4 , 12 }, {4 , 18 }, {4 , 26 }});
330+ EXPECT_EQ (found, references.size ());
331+ }
332+
333+ TEST_F (PythonServiceTest, NodeAnnotation)
334+ {
335+ AstNodeInfo nodeInfo;
336+ std::vector<AstNodeInfo> references;
337+
338+ nodeInfo = getAstNodeInfoByPosition (" functions.py" , 69 , 1 );
339+ _pythonservice->getReferences (references, nodeInfo.id , PythonServiceHandler::ANNOTATION, {});
340+
341+ EXPECT_EQ (nodeInfo.astNodeValue , " def annotation(a, b) -> None" );
342+ EXPECT_EQ (references.size (), 1 );
343+
344+ size_t found = referenceFinder (references, {{69 , 24 }});
345+ EXPECT_EQ (found, references.size ());
63346}
0 commit comments