55 "getDocumentation": self.__getDocumentation, |
56 "getDocumentation": self.__getDocumentation, |
56 "gotoDefinition": self.__gotoDefinition, |
57 "gotoDefinition": self.__gotoDefinition, |
57 "gotoReferences": self.__getReferences, |
58 "gotoReferences": self.__getReferences, |
58 "reportChanged": self.__reportChanged, |
59 "reportChanged": self.__reportChanged, |
59 } |
60 } |
60 |
61 |
61 from FileSystemCommands import RefactoringClientFileSystemCommands |
62 from FileSystemCommands import RefactoringClientFileSystemCommands |
|
63 |
62 self.__fsCommands = RefactoringClientFileSystemCommands(self) |
64 self.__fsCommands = RefactoringClientFileSystemCommands(self) |
63 |
65 |
64 self.__projectpath = projectPath |
66 self.__projectpath = projectPath |
65 self.__project = rope.base.project.Project( |
67 self.__project = rope.base.project.Project( |
66 self.__projectpath, fscommands=self.__fsCommands) |
68 self.__projectpath, fscommands=self.__fsCommands |
|
69 ) |
67 self.__project.validate(self.__project.root) |
70 self.__project.validate(self.__project.root) |
68 |
71 |
69 self.__id = idString |
72 self.__id = idString |
70 |
73 |
71 def handleCall(self, method, params): |
74 def handleCall(self, method, params): |
72 """ |
75 """ |
73 Public method to handle a method call from the server. |
76 Public method to handle a method call from the server. |
74 |
77 |
75 @param method requested method name |
78 @param method requested method name |
76 @type str |
79 @type str |
77 @param params dictionary with method specific parameters |
80 @param params dictionary with method specific parameters |
78 @type dict |
81 @type dict |
79 """ |
82 """ |
80 self.__methodMapping[method](params) |
83 self.__methodMapping[method](params) |
81 |
84 |
82 def __handleRopeError(self, err): |
85 def __handleRopeError(self, err): |
83 """ |
86 """ |
84 Private method to process a rope error. |
87 Private method to process a rope error. |
85 |
88 |
86 @param err rope exception object |
89 @param err rope exception object |
87 @type Exception |
90 @type Exception |
88 @return dictionary containing the error information |
91 @return dictionary containing the error information |
89 @rtype dict |
92 @rtype dict |
90 """ |
93 """ |
91 ropeError = str(type(err)).split()[-1] |
94 ropeError = str(type(err)).split()[-1] |
92 ropeError = ropeError[1:-2].split('.')[-1] |
95 ropeError = ropeError[1:-2].split(".")[-1] |
93 errorDict = { |
96 errorDict = { |
94 "Error": ropeError, |
97 "Error": ropeError, |
95 "ErrorString": str(err), |
98 "ErrorString": str(err), |
96 } |
99 } |
97 if ropeError == 'ModuleSyntaxError': |
100 if ropeError == "ModuleSyntaxError": |
98 errorDict["ErrorFile"] = err.filename |
101 errorDict["ErrorFile"] = err.filename |
99 errorDict["ErrorLine"] = err.lineno |
102 errorDict["ErrorLine"] = err.lineno |
100 |
103 |
101 return errorDict |
104 return errorDict |
102 |
105 |
103 def __getConfig(self, params): |
106 def __getConfig(self, params): |
104 """ |
107 """ |
105 Private method to send some configuration data to the server. |
108 Private method to send some configuration data to the server. |
106 |
109 |
107 @param params dictionary containing the method parameters sent by |
110 @param params dictionary containing the method parameters sent by |
108 the server |
111 the server |
109 @type dict |
112 @type dict |
110 """ |
113 """ |
111 result = { |
114 result = { |
112 "RopeFolderName": self.__project.ropefolder.real_path, |
115 "RopeFolderName": self.__project.ropefolder.real_path, |
113 "Id": self.__id, |
116 "Id": self.__id, |
114 } |
117 } |
115 |
118 |
116 self.sendJson("Config", result) |
119 self.sendJson("Config", result) |
117 |
120 |
118 def __configChanged(self, params): |
121 def __configChanged(self, params): |
119 """ |
122 """ |
120 Private method to handle a change of the configuration file. |
123 Private method to handle a change of the configuration file. |
121 |
124 |
122 @param params dictionary containing the method parameters sent by |
125 @param params dictionary containing the method parameters sent by |
123 the server |
126 the server |
124 @type dict |
127 @type dict |
125 """ |
128 """ |
126 self.__project.close() |
129 self.__project.close() |
127 self.__project = rope.base.project.Project( |
130 self.__project = rope.base.project.Project( |
128 self.__projectpath, fscommands=self.__fsCommands) |
131 self.__projectpath, fscommands=self.__fsCommands |
|
132 ) |
129 self.__project.validate(self.__project.root) |
133 self.__project.validate(self.__project.root) |
130 |
134 |
131 def __closeProject(self, params): |
135 def __closeProject(self, params): |
132 """ |
136 """ |
133 Private slot to validate the project. |
137 Private slot to validate the project. |
134 |
138 |
135 @param params dictionary containing the method parameters sent by |
139 @param params dictionary containing the method parameters sent by |
136 the server |
140 the server |
137 @type dict |
141 @type dict |
138 """ |
142 """ |
139 self.__project.close() |
143 self.__project.close() |
140 |
144 |
141 def __getCompletions(self, params): |
145 def __getCompletions(self, params): |
142 """ |
146 """ |
143 Private method to calculate possible completions. |
147 Private method to calculate possible completions. |
144 |
148 |
145 @param params dictionary containing the method parameters |
149 @param params dictionary containing the method parameters |
146 @type dict |
150 @type dict |
147 """ |
151 """ |
148 filename = params["FileName"] |
152 filename = params["FileName"] |
149 source = params["Source"] |
153 source = params["Source"] |
150 offset = params["Offset"] |
154 offset = params["Offset"] |
151 maxfixes = params["MaxFixes"] |
155 maxfixes = params["MaxFixes"] |
152 |
156 |
153 self.__project.prefs.set("python_path", params["SysPath"]) |
157 self.__project.prefs.set("python_path", params["SysPath"]) |
154 resource = ( |
158 resource = ( |
155 rope.base.libutils.path_to_resource(self.__project, filename) |
159 rope.base.libutils.path_to_resource(self.__project, filename) |
156 if filename else |
160 if filename |
157 None |
161 else None |
158 ) |
162 ) |
159 |
163 |
160 errorDict = {} |
164 errorDict = {} |
161 completions = [] |
165 completions = [] |
162 |
166 |
163 try: |
167 try: |
164 proposals = rope.contrib.codeassist.code_assist( |
168 proposals = rope.contrib.codeassist.code_assist( |
165 self.__project, source, offset, resource, maxfixes=maxfixes) |
169 self.__project, source, offset, resource, maxfixes=maxfixes |
|
170 ) |
166 for proposal in proposals: |
171 for proposal in proposals: |
167 proposalType = proposal.type |
172 proposalType = proposal.type |
168 if proposal.name.startswith("__"): |
173 if proposal.name.startswith("__"): |
169 proposalType = "__" + proposalType |
174 proposalType = "__" + proposalType |
170 elif proposal.name.startswith("_"): |
175 elif proposal.name.startswith("_"): |
171 proposalType = "_" + proposalType |
176 proposalType = "_" + proposalType |
172 completions.append({ |
177 completions.append( |
173 "Name": proposal.name, |
178 { |
174 "CompletionType": proposalType, |
179 "Name": proposal.name, |
175 }) |
180 "CompletionType": proposalType, |
|
181 } |
|
182 ) |
176 except Exception as err: |
183 except Exception as err: |
177 errorDict = self.__handleRopeError(err) |
184 errorDict = self.__handleRopeError(err) |
178 |
185 |
179 result = { |
186 result = { |
180 "Completions": completions, |
187 "Completions": completions, |
181 "CompletionText": params["CompletionText"], |
188 "CompletionText": params["CompletionText"], |
182 "FileName": filename, |
189 "FileName": filename, |
183 } |
190 } |
184 result.update(errorDict) |
191 result.update(errorDict) |
185 |
192 |
186 self.sendJson("CompletionsResult", result) |
193 self.sendJson("CompletionsResult", result) |
187 |
194 |
188 def __getCallTips(self, params): |
195 def __getCallTips(self, params): |
189 """ |
196 """ |
190 Private method to calculate possible calltips. |
197 Private method to calculate possible calltips. |
191 |
198 |
192 @param params dictionary containing the method parameters |
199 @param params dictionary containing the method parameters |
193 @type dict |
200 @type dict |
194 """ |
201 """ |
195 filename = params["FileName"] |
202 filename = params["FileName"] |
196 source = params["Source"] |
203 source = params["Source"] |
197 offset = params["Offset"] |
204 offset = params["Offset"] |
198 maxfixes = params["MaxFixes"] |
205 maxfixes = params["MaxFixes"] |
199 |
206 |
200 self.__project.prefs.set("python_path", params["SysPath"]) |
207 self.__project.prefs.set("python_path", params["SysPath"]) |
201 resource = ( |
208 resource = ( |
202 rope.base.libutils.path_to_resource(self.__project, filename) |
209 rope.base.libutils.path_to_resource(self.__project, filename) |
203 if filename else |
210 if filename |
204 None |
211 else None |
205 ) |
212 ) |
206 |
213 |
207 errorDict = {} |
214 errorDict = {} |
208 calltips = [] |
215 calltips = [] |
209 |
216 |
210 try: |
217 try: |
211 cts = rope.contrib.codeassist.get_calltip( |
218 cts = rope.contrib.codeassist.get_calltip( |
212 self.__project, source, offset, resource, maxfixes=maxfixes, |
219 self.__project, |
213 remove_self=True) |
220 source, |
|
221 offset, |
|
222 resource, |
|
223 maxfixes=maxfixes, |
|
224 remove_self=True, |
|
225 ) |
214 if cts is not None: |
226 if cts is not None: |
215 calltips = [cts] |
227 calltips = [cts] |
216 except Exception as err: |
228 except Exception as err: |
217 errorDict = self.__handleRopeError(err) |
229 errorDict = self.__handleRopeError(err) |
218 |
230 |
219 result = { |
231 result = { |
220 "CallTips": calltips, |
232 "CallTips": calltips, |
221 } |
233 } |
222 result.update(errorDict) |
234 result.update(errorDict) |
223 |
235 |
224 self.sendJson("CallTipsResult", result) |
236 self.sendJson("CallTipsResult", result) |
225 |
237 |
226 def __getDocumentation(self, params): |
238 def __getDocumentation(self, params): |
227 """ |
239 """ |
228 Private method to get some source code documentation. |
240 Private method to get some source code documentation. |
229 |
241 |
230 @param params dictionary containing the method parameters |
242 @param params dictionary containing the method parameters |
231 @type dict |
243 @type dict |
232 """ |
244 """ |
233 filename = params["FileName"] |
245 filename = params["FileName"] |
234 source = params["Source"] |
246 source = params["Source"] |
235 offset = params["Offset"] |
247 offset = params["Offset"] |
236 maxfixes = params["MaxFixes"] |
248 maxfixes = params["MaxFixes"] |
237 |
249 |
238 if self.__id != CodeAssistClient.IdProject: |
250 if self.__id != CodeAssistClient.IdProject: |
239 self.__project.prefs.set("python_path", params["SysPath"]) |
251 self.__project.prefs.set("python_path", params["SysPath"]) |
240 resource = ( |
252 resource = ( |
241 rope.base.libutils.path_to_resource(self.__project, filename) |
253 rope.base.libutils.path_to_resource(self.__project, filename) |
242 if filename else |
254 if filename |
243 None |
255 else None |
244 ) |
256 ) |
245 |
257 |
246 errorDict = {} |
258 errorDict = {} |
247 documentation = "" |
259 documentation = "" |
248 cts = None |
260 cts = None |
249 |
261 |
250 with contextlib.suppress(Exception): |
262 with contextlib.suppress(Exception): |
251 cts = rope.contrib.codeassist.get_calltip( |
263 cts = rope.contrib.codeassist.get_calltip( |
252 self.__project, source, offset, resource, maxfixes=maxfixes, |
264 self.__project, |
253 remove_self=True) |
265 source, |
254 |
266 offset, |
|
267 resource, |
|
268 maxfixes=maxfixes, |
|
269 remove_self=True, |
|
270 ) |
|
271 |
255 if cts is not None: |
272 if cts is not None: |
256 while '..' in cts: |
273 while ".." in cts: |
257 cts = cts.replace('..', '.') |
274 cts = cts.replace("..", ".") |
258 if '(.)' in cts: |
275 if "(.)" in cts: |
259 cts = cts.replace('(.)', '(...)') |
276 cts = cts.replace("(.)", "(...)") |
260 |
277 |
261 try: |
278 try: |
262 documentation = rope.contrib.codeassist.get_doc( |
279 documentation = rope.contrib.codeassist.get_doc( |
263 self.__project, source, offset, resource, maxfixes=maxfixes) |
280 self.__project, source, offset, resource, maxfixes=maxfixes |
|
281 ) |
264 except Exception as err: |
282 except Exception as err: |
265 errorDict = self.__handleRopeError(err) |
283 errorDict = self.__handleRopeError(err) |
266 |
284 |
267 typeName = self.__getObjectTypeAndName( |
285 typeName = self.__getObjectTypeAndName( |
268 self.__project, source, offset, resource, maxfixes=maxfixes) |
286 self.__project, source, offset, resource, maxfixes=maxfixes |
269 |
287 ) |
270 documentationDict = self.__processDocumentation(cts, documentation, |
288 |
271 typeName) |
289 documentationDict = self.__processDocumentation(cts, documentation, typeName) |
272 result = { |
290 result = { |
273 "DocumentationDict": documentationDict, |
291 "DocumentationDict": documentationDict, |
274 } |
292 } |
275 result.update(errorDict) |
293 result.update(errorDict) |
276 |
294 |
277 self.sendJson("DocumentationResult", result) |
295 self.sendJson("DocumentationResult", result) |
278 |
296 |
279 def __processDocumentation(self, cts, documentation, typeName): |
297 def __processDocumentation(self, cts, documentation, typeName): |
280 """ |
298 """ |
281 Private method to process the call-tips and documentation. |
299 Private method to process the call-tips and documentation. |
282 |
300 |
283 @param cts call-tips |
301 @param cts call-tips |
284 @type str |
302 @type str |
285 @param documentation extracted source code documentation |
303 @param documentation extracted source code documentation |
286 @type str |
304 @type str |
287 @param typeName type and name of the object |
305 @param typeName type and name of the object |
380 typ = "object" |
398 typ = "object" |
381 name = "" |
399 name = "" |
382 else: |
400 else: |
383 typ = "" |
401 typ = "" |
384 name = "" |
402 name = "" |
385 |
403 |
386 return typ, name |
404 return typ, name |
387 |
405 |
388 def __gotoDefinition(self, params): |
406 def __gotoDefinition(self, params): |
389 """ |
407 """ |
390 Private method to handle the Goto Definition action. |
408 Private method to handle the Goto Definition action. |
391 |
409 |
392 @param params dictionary containing the method parameters sent by |
410 @param params dictionary containing the method parameters sent by |
393 the server |
411 the server |
394 @type dict |
412 @type dict |
395 """ |
413 """ |
396 import rope.base.libutils |
414 import rope.base.libutils |
397 |
415 |
398 filename = params["FileName"] |
416 filename = params["FileName"] |
399 offset = params["Offset"] |
417 offset = params["Offset"] |
400 source = params["Source"] |
418 source = params["Source"] |
401 uid = params["Uuid"] |
419 uid = params["Uuid"] |
402 |
420 |
403 self.__project.prefs.set("python_path", params["SysPath"]) |
421 self.__project.prefs.set("python_path", params["SysPath"]) |
404 resource = ( |
422 resource = ( |
405 rope.base.libutils.path_to_resource(self.__project, filename) |
423 rope.base.libutils.path_to_resource(self.__project, filename) |
406 if filename else |
424 if filename |
407 None |
425 else None |
408 ) |
426 ) |
409 |
427 |
410 errorDict = {} |
428 errorDict = {} |
411 result = {} |
429 result = {} |
412 |
430 |
413 import rope.contrib.findit |
431 import rope.contrib.findit |
|
432 |
414 try: |
433 try: |
415 location = rope.contrib.findit.find_definition( |
434 location = rope.contrib.findit.find_definition( |
416 self.__project, source, offset, resource) |
435 self.__project, source, offset, resource |
|
436 ) |
417 except Exception as err: |
437 except Exception as err: |
418 location = None |
438 location = None |
419 errorDict = self.__handleRopeError(err) |
439 errorDict = self.__handleRopeError(err) |
420 |
440 |
421 if location is not None: |
441 if location is not None: |
422 result["Location"] = { |
442 result["Location"] = { |
423 "ModulePath": location.resource.real_path, |
443 "ModulePath": location.resource.real_path, |
424 "Line": location.lineno, |
444 "Line": location.lineno, |
425 } |
445 } |
426 result["Uuid"] = uid |
446 result["Uuid"] = uid |
427 result.update(errorDict) |
447 result.update(errorDict) |
428 |
448 |
429 self.sendJson("GotoDefinitionResult", result) |
449 self.sendJson("GotoDefinitionResult", result) |
430 |
450 |
431 def __getReferences(self, params): |
451 def __getReferences(self, params): |
432 """ |
452 """ |
433 Private method to get the places a parameter is referenced. |
453 Private method to get the places a parameter is referenced. |
434 |
454 |
435 @param params dictionary containing the method parameters sent by |
455 @param params dictionary containing the method parameters sent by |
436 the server |
456 the server |
437 @type dict |
457 @type dict |
438 """ |
458 """ |
439 import rope.base.libutils |
459 import rope.base.libutils |
440 |
460 |
441 filename = params["FileName"] |
461 filename = params["FileName"] |
442 offset = params["Offset"] |
462 offset = params["Offset"] |
443 line = params["Line"] |
463 line = params["Line"] |
444 uid = params["Uuid"] |
464 uid = params["Uuid"] |
445 |
465 |
446 self.__project.prefs.set("python_path", params["SysPath"]) |
466 self.__project.prefs.set("python_path", params["SysPath"]) |
447 resource = ( |
467 resource = ( |
448 rope.base.libutils.path_to_resource(self.__project, filename) |
468 rope.base.libutils.path_to_resource(self.__project, filename) |
449 if filename else |
469 if filename |
450 None |
470 else None |
451 ) |
471 ) |
452 |
472 |
453 errorDict = {} |
473 errorDict = {} |
454 gotoReferences = [] |
474 gotoReferences = [] |
455 |
475 |
456 import rope.contrib.findit |
476 import rope.contrib.findit |
|
477 |
457 try: |
478 try: |
458 occurrences = rope.contrib.findit.find_occurrences( |
479 occurrences = rope.contrib.findit.find_occurrences( |
459 self.__project, resource, offset, in_hierarchy=True) |
480 self.__project, resource, offset, in_hierarchy=True |
|
481 ) |
460 for occurrence in occurrences: |
482 for occurrence in occurrences: |
461 if ( |
483 if ( |
462 occurrence.lineno == line and |
484 occurrence.lineno == line |
463 occurrence.resource.real_path == filename |
485 and occurrence.resource.real_path == filename |
464 ): |
486 ): |
465 continue |
487 continue |
466 gotoReferences.append({ |
488 gotoReferences.append( |
467 'ModulePath': occurrence.resource.real_path, |
489 { |
468 'Line': occurrence.lineno, |
490 "ModulePath": occurrence.resource.real_path, |
469 'Code': occurrence.resource.read().splitlines()[ |
491 "Line": occurrence.lineno, |
470 occurrence.lineno - 1], |
492 "Code": occurrence.resource.read().splitlines()[ |
471 }) |
493 occurrence.lineno - 1 |
|
494 ], |
|
495 } |
|
496 ) |
472 except Exception as err: |
497 except Exception as err: |
473 errorDict = self.__handleRopeError(err) |
498 errorDict = self.__handleRopeError(err) |
474 |
499 |
475 result = { |
500 result = { |
476 "GotoReferencesList": gotoReferences, |
501 "GotoReferencesList": gotoReferences, |
477 "Uuid": uid, |
502 "Uuid": uid, |
478 } |
503 } |
479 result.update(errorDict) |
504 result.update(errorDict) |
480 |
505 |
481 self.sendJson("GotoReferencesResult", result) |
506 self.sendJson("GotoReferencesResult", result) |
482 |
507 |
483 def __reportChanged(self, params): |
508 def __reportChanged(self, params): |
484 """ |
509 """ |
485 Private method to register some changed sources. |
510 Private method to register some changed sources. |
486 |
511 |
487 @param params dictionary containing the method parameters sent by |
512 @param params dictionary containing the method parameters sent by |
488 the server |
513 the server |
489 @type dict |
514 @type dict |
490 """ |
515 """ |
491 filename = params["FileName"] |
516 filename = params["FileName"] |
492 oldSource = params["OldSource"] |
517 oldSource = params["OldSource"] |
493 |
518 |
494 with contextlib.suppress(Exception): |
519 with contextlib.suppress(Exception): |
495 rope.base.libutils.report_change( |
520 rope.base.libutils.report_change(self.__project, filename, oldSource) |
496 self.__project, filename, oldSource) |
521 |
497 |
522 |
498 |
523 if __name__ == "__main__": |
499 if __name__ == '__main__': |
|
500 if len(sys.argv) != 6: |
524 if len(sys.argv) != 6: |
501 print('Host, port, id, project path and module path parameters are' |
525 print( |
502 ' missing. Abort.') |
526 "Host, port, id, project path and module path parameters are" |
|
527 " missing. Abort." |
|
528 ) |
503 sys.exit(1) |
529 sys.exit(1) |
504 |
530 |
505 host, port, idString, projectPath = sys.argv[1:-1] |
531 host, port, idString, projectPath = sys.argv[1:-1] |
506 |
532 |
507 # Create a Qt6 application object in order to allow the processing of |
533 # Create a Qt6 application object in order to allow the processing of |
508 # modules containing Qt stuff. |
534 # modules containing Qt stuff. |
509 try: |
535 try: |
510 from PyQt6.QtCore import QCoreApplication |
536 from PyQt6.QtCore import QCoreApplication |
511 except (ImportError, RuntimeError): |
537 except (ImportError, RuntimeError): |
512 QCoreApplication = None |
538 QCoreApplication = None |
513 if QCoreApplication is not None: |
539 if QCoreApplication is not None: |
514 app = QCoreApplication([]) |
540 app = QCoreApplication([]) |
515 |
541 |
516 client = CodeAssistClient(host, int(port), idString, projectPath) |
542 client = CodeAssistClient(host, int(port), idString, projectPath) |
517 # Start the main loop |
543 # Start the main loop |
518 client.run() |
544 client.run() |
519 |
545 |
520 sys.exit(0) |
546 sys.exit(0) |
521 |
547 |
522 # |
548 # |
523 # eflag: noqa = M801 |
549 # eflag: noqa = M801 |