RefactoringRope/CodeAssistServer.py

branch
eric7
changeset 365
f740b50380df
parent 360
2b35968f3d02
child 368
c206d08c28e7
equal deleted inserted replaced
364:a92b3272f4c1 365:f740b50380df
9 9
10 import os 10 import os
11 import sys 11 import sys
12 import contextlib 12 import contextlib
13 13
14 from PyQt5.QtCore import ( 14 from PyQt6.QtCore import (
15 pyqtSlot, QCoreApplication, QTimer 15 pyqtSlot, QCoreApplication, QTimer
16 ) 16 )
17 17
18 from E5Gui.E5Application import e5App 18 from EricWidgets.EricApplication import ericApp
19 from E5Gui import E5MessageBox 19 from EricWidgets import EricMessageBox
20
21 from EricNetwork.EricJsonServer import EricJsonServer
20 22
21 from QScintilla.Editor import Editor 23 from QScintilla.Editor import Editor
22
23 try:
24 from E5Network.E5JsonServer import E5JsonServer
25 except ImportError:
26 # TODO: delete JsonServer once ported to eric7
27 from .JsonServer import JsonServer as E5JsonServer
28 24
29 import Globals 25 import Globals
30 import Preferences 26 import Preferences
31 27
32 28
33 class CodeAssistServer(E5JsonServer): 29 class CodeAssistServer(EricJsonServer):
34 """ 30 """
35 Class implementing the autocompletion interface to rope. 31 Class implementing the autocompletion interface to rope.
36 """ 32 """
37 IdProject = "Project" 33 IdProject = "Project"
38 34
64 super().__init__( 60 super().__init__(
65 "CodeAssistServer", multiplex=True, parent=parent) 61 "CodeAssistServer", multiplex=True, parent=parent)
66 62
67 self.__plugin = plugin 63 self.__plugin = plugin
68 self.__ui = parent 64 self.__ui = parent
69 self.__vm = e5App().getObject("ViewManager") 65 self.__vm = ericApp().getObject("ViewManager")
70 self.__e5project = e5App().getObject("Project") 66 self.__e5project = ericApp().getObject("Project")
71 67
72 self.__editorLanguageMapping = {} 68 self.__editorLanguageMapping = {}
73 self.__clientConfigs = {} 69 self.__clientConfigs = {}
74 self.__editors = {} 70 self.__editors = {}
75
76 self.__asyncCompletions = False
77 71
78 self.__documentationViewer = None 72 self.__documentationViewer = None
79 73
80 # attributes to store the resuls of the client side 74 # attributes to store the resuls of the client side
81 self.__completions = None 75 self.__completions = None
104 } 98 }
105 99
106 # Python 3 100 # Python 3
107 self.__ensureActive("Python3") 101 self.__ensureActive("Python3")
108 102
109 def setAsyncCompletions(self, asynchronous):
110 """
111 Public method to set the asynchronous completions flag.
112
113 @param asynchronous flag indicating asynchronous completions
114 @type bool
115 """
116 self.__asyncCompletions = asynchronous
117
118 def __updateEditorLanguageMapping(self): 103 def __updateEditorLanguageMapping(self):
119 """ 104 """
120 Private method to update the editor language to connection mapping. 105 Private method to update the editor language to connection mapping.
121 """ 106 """
122 self.__editorLanguageMapping = {} 107 self.__editorLanguageMapping = {}
125 self.__editorLanguageMapping.update({ 110 self.__editorLanguageMapping.update({
126 "Python3": "Python3", 111 "Python3": "Python3",
127 "MicroPython": "Python3", 112 "MicroPython": "Python3",
128 "Pygments|Python": "Python3", 113 "Pygments|Python": "Python3",
129 "Pygments|Python 2.x": "Python3", 114 "Pygments|Python 2.x": "Python3",
115 "Cython": "Python3",
130 }) 116 })
131 117
132 def isSupportedLanguage(self, language): 118 def isSupportedLanguage(self, language):
133 """ 119 """
134 Public method to check, if the given language is supported. 120 Public method to check, if the given language is supported.
143 def __idString(self, editor): 129 def __idString(self, editor):
144 """ 130 """
145 Private method to determine the ID string for the back-end. 131 Private method to determine the ID string for the back-end.
146 132
147 @param editor reference to the editor to determine the ID string for 133 @param editor reference to the editor to determine the ID string for
148 @type QScintilla.Editor 134 @type Editor
149 @return ID string 135 @return ID string
150 @rtype str 136 @rtype str
151 """ 137 """
152 idString = "" 138 idString = ""
153 139
227 editor.editorSaved.connect( 213 editor.editorSaved.connect(
228 lambda: self.__configChanged(idString)) 214 lambda: self.__configChanged(idString))
229 self.__editors[idString] = editor 215 self.__editors[idString] = editor
230 return 216 return
231 else: 217 else:
232 E5MessageBox.critical( 218 EricMessageBox.critical(
233 self.__ui, 219 self.__ui,
234 self.tr("Configure Rope"), 220 self.tr("Configure Rope"),
235 self.tr("""The Rope configuration file '{0}' does""" 221 self.tr("""The Rope configuration file '{0}' does"""
236 """ not exist.""").format(configfile)) 222 """ not exist.""").format(configfile))
237 223
238 def getCompletions(self, editor, context): 224 def requestCompletions(self, editor, context, acText):
239 """ 225 """
240 Public method to calculate the possible completions. 226 Public method to request a list of possible completions.
241
242 Note: This is the synchronous variant for eric6 before 17.11.
243 227
244 @param editor reference to the editor object, that called this method 228 @param editor reference to the editor object, that called this method
245 @type QScintilla.Editor.Editor 229 @type Editor
246 @param context flag indicating to autocomplete a context
247 @type bool
248 @return list of possible completions
249 @rtype list of str
250 """
251 if not self.__plugin.getPreferences("CodeAssistEnabled"):
252 return []
253
254 # reset the completions buffer
255 self.__completions = None
256
257 if not self.__idString(editor):
258 return []
259
260 self.requestCompletions(editor, context, "")
261
262 # emulate the synchronous behaviour
263 timer = QTimer()
264 timer.setSingleShot(True)
265 timer.start(5000) # 5s timeout
266 while self.__completions is None and timer.isActive():
267 QCoreApplication.processEvents()
268
269 return [] if self.__completions is None else self.__completions
270
271 def requestCompletions(self, editor, context, acText):
272 """
273 Public method to request a list of possible completions.
274
275 Note: This is part of the asynchronous variant for eric6 17.11 and
276 later.
277
278 @param editor reference to the editor object, that called this method
279 @type QScintilla.Editor.Editor
280 @param context flag indicating to autocomplete a context 230 @param context flag indicating to autocomplete a context
281 @type bool 231 @type bool
282 @param acText text to be completed 232 @param acText text to be completed
283 @type str 233 @type str
284 """ 234 """
318 268
319 name += CodeAssistServer.PictureIDs.get( 269 name += CodeAssistServer.PictureIDs.get(
320 completion['CompletionType'], '') 270 completion['CompletionType'], '')
321 names.append(name) 271 names.append(name)
322 272
323 if self.__asyncCompletions: 273 if "Error" not in result:
324 # asynchronous variant for eric6 17.11 and later 274 editor = self.__vm.getOpenEditor(result["FileName"])
325 if "Error" not in result: 275 if editor is not None:
326 editor = self.__vm.getOpenEditor(result["FileName"]) 276 editor.completionsListReady(names,
327 if editor is not None: 277 result["CompletionText"])
328 editor.completionsListReady(names,
329 result["CompletionText"])
330 else:
331 # synchronous variant for eric6 before 17.11
332 if "Error" in result:
333 self.__completions = []
334 else:
335 self.__completions = result["Completions"]
336 278
337 def getCallTips(self, editor, pos, commas): 279 def getCallTips(self, editor, pos, commas):
338 """ 280 """
339 Public method to calculate calltips. 281 Public method to calculate calltips.
340 282
341 @param editor reference to the editor object, that called this method 283 @param editor reference to the editor object, that called this method
342 @type QScintilla.Editor.Editor 284 @type Editor
343 @param pos position in the text for the calltip 285 @param pos position in the text for the calltip
344 @type int 286 @type int
345 @param commas minimum number of commas contained in the calltip 287 @param commas minimum number of commas contained in the calltip
346 @type int 288 @type int
347 @return list of possible calltips 289 @return list of possible calltips
417 Public method to request source code documentation for the given 359 Public method to request source code documentation for the given
418 editor. 360 editor.
419 361
420 @param editor reference to the editor to get source code documentation 362 @param editor reference to the editor to get source code documentation
421 for 363 for
422 @type QScintilla.Editor.Editor 364 @type Editor
423 """ 365 """
424 if self.__documentationViewer is None: 366 if self.__documentationViewer is None:
425 return 367 return
426 368
427 idString = self.__idString(editor) 369 idString = self.__idString(editor)
511 and go to it. 453 and go to it.
512 454
513 Note: This is executed upon a mouse click sequence. 455 Note: This is executed upon a mouse click sequence.
514 456
515 @param editor reference to the calling editor 457 @param editor reference to the calling editor
516 @type QScintilla.Editor.Editor 458 @type Editor
517 """ 459 """
518 if not self.__plugin.getPreferences("MouseClickEnabled"): 460 if not self.__plugin.getPreferences("MouseClickEnabled"):
519 return 461 return
520 462
521 idString = self.__idString(editor) 463 idString = self.__idString(editor)
549 location = result["Location"] 491 location = result["Location"]
550 self.__vm.openSourceFile(location["ModulePath"], 492 self.__vm.openSourceFile(location["ModulePath"],
551 location["Line"], 493 location["Line"],
552 addNext=True) 494 addNext=True)
553 else: 495 else:
554 e5App().getObject("UserInterface").statusBar().showMessage( 496 ericApp().getObject("UserInterface").statusBar().showMessage(
555 self.tr('Code Assist: No definition found'), 5000) 497 self.tr('Code Assist: No definition found'), 5000)
556 498
557 ####################################################################### 499 #######################################################################
558 ## Methods below handle the network connection 500 ## Methods below handle the network connection
559 ####################################################################### 501 #######################################################################
626 568
627 client = os.path.join(os.path.dirname(__file__), 569 client = os.path.join(os.path.dirname(__file__),
628 "CodeAssistClient.py") 570 "CodeAssistClient.py")
629 ok, exitCode = self.startClient( 571 ok, exitCode = self.startClient(
630 interpreter, client, 572 interpreter, client,
631 clientArgs=[configDir, Globals.getPythonModulesDirectory()], 573 clientArgs=[configDir, Globals.getPythonLibraryDirectory()],
632 idString=idString, environment=clientEnv) 574 idString=idString, environment=clientEnv)
633 if not ok: 575 if not ok:
634 if exitCode == 42: 576 if exitCode == 42:
635 self.__ui.appendToStderr("CodeAssistServer: " + self.tr( 577 self.__ui.appendToStderr("CodeAssistServer: " + self.tr(
636 "The rope refactoring library is not installed.\n" 578 "The rope refactoring library is not installed.\n"
668 interpreter = "" 610 interpreter = ""
669 venvName = "" 611 venvName = ""
670 clientEnv = os.environ.copy() 612 clientEnv = os.environ.copy()
671 if "PATH" in clientEnv: 613 if "PATH" in clientEnv:
672 clientEnv["PATH"] = self.__ui.getOriginalPathString() 614 clientEnv["PATH"] = self.__ui.getOriginalPathString()
673 venvManager = e5App().getObject("VirtualEnvManager") 615 venvManager = ericApp().getObject("VirtualEnvManager")
674 if idString == "Python3": 616 if idString == "Python3":
675 venvName = Preferences.getDebugger("Python3VirtualEnv") 617 venvName = Preferences.getDebugger("Python3VirtualEnv")
676 if not venvName: 618 if not venvName:
677 venvName, _ = venvManager.getDefaultEnvironment() 619 venvName, _ = venvManager.getDefaultEnvironment()
678 if venvName: 620 if venvName:
709 clientEnv = os.environ.copy() 651 clientEnv = os.environ.copy()
710 if "PATH" in clientEnv: 652 if "PATH" in clientEnv:
711 clientEnv["PATH"] = self.__ui.getOriginalPathString() 653 clientEnv["PATH"] = self.__ui.getOriginalPathString()
712 654
713 if projectLanguage.startswith("Python"): 655 if projectLanguage.startswith("Python"):
714 venvManager = e5App().getObject("VirtualEnvManager") 656 venvManager = ericApp().getObject("VirtualEnvManager")
715 657
716 # get virtual environment from project first 658 # get virtual environment from project first
717 venvName = self.__e5project.getDebugProperty("VIRTUALENV") 659 venvName = self.__e5project.getDebugProperty("VIRTUALENV")
718 if not venvName: 660 if not venvName:
719 # get it from debugger settings next 661 # get it from debugger settings next

eric ide

mercurial