--- a/RefactoringRope/CodeAssistServer.py Tue Sep 26 19:05:18 2017 +0200 +++ b/RefactoringRope/CodeAssistServer.py Wed Sep 27 18:25:08 2017 +0200 @@ -12,21 +12,10 @@ import os import sys -from PyQt5.QtCore import pyqtSlot +from PyQt5.QtCore import pyqtSlot, QCoreApplication, QTimer # TODO: eliminate this sys.path.insert(0, os.path.dirname(__file__)) -##if sys.version_info[0] >= 3: -## path = os.path.join(os.path.dirname(__file__), 'rope_py3') -##else: -## path = os.path.join(os.path.dirname(__file__), 'rope_py2') -## str = unicode # __IGNORE_WARNING__ -##sys.path.insert(0, path) -## -##import rope.base.libutils -##import rope.contrib.codeassist - -from QScintilla.Editor import Editor from JsonServer import JsonServer @@ -38,14 +27,6 @@ """ Class implementing the autocompletion interface to rope. """ - PictureIDs = { - "class": "?{0}".format(Editor.ClassID), - "instance": "?{0}".format(Editor.ClassID), - "function": "?{0}".format(Editor.MethodID), - "module": "?{0}".format(Editor.AttributeID), - "None": "", - } - def __init__(self, plugin, parent=None): """ Constructor @@ -63,6 +44,14 @@ self.__editorLanguageMapping = {} + # attributes to store the resuls of the client side + self.__completions = None + self.__calltips = None + + self.__methodMapping = { + "CompletionsResult": self.__processCompletionsResult, + } + # Python 2 interpreter = Preferences.getDebugger("PythonInterpreter") self.__startCodeAssistClient(interpreter, "Python2") @@ -70,8 +59,6 @@ # Python 3 interpreter = Preferences.getDebugger("Python3Interpreter") self.__startCodeAssistClient(interpreter, "Python3") -## self.__project = rope.base.project.Project(Globals.getConfigDir()) -## self.__project.validate(self.__project.root) def __updateEditorLanguageMapping(self): """ @@ -102,36 +89,56 @@ """ return language in self.__editorLanguageMapping - # TODO: port this to the distributed variant def getCompletions(self, editor): """ Public method to calculate the possible completions. @param editor reference to the editor object, that called this method - QScintilla.Editor) - @return list of proposals (QStringList) + @type QScintilla.Editor + @return list of proposals + @rtype list of str """ - print("rope: getCompletions") - return [] -## filename = editor.getFileName() -## if filename: -## resource = rope.base.libutils.path_to_resource( -## self.__project, filename) -## else: -## resource = None -## line, index = editor.getCursorPosition() -## source = editor.text() -## offset = len("".join(source.splitlines(True)[:line])) + index -## maxfixes = self.__plugin.getPreferences("MaxFixes") -## try: -## proposals = rope.contrib.codeassist.code_assist( -## self.__project, source, offset, resource, maxfixes=maxfixes) -## proposals = rope.contrib.codeassist.sorted_proposals(proposals) -## names = [proposal.name + self.PictureIDs[proposal.type] -## for proposal in proposals] -## return names -## except Exception: -## return [] + # reset the completions buffer + self.__completions = None + + language = editor.getLanguage() + if language not in self.__editorLanguageMapping: + return [] + idString = self.__editorLanguageMapping[language] + + filename = editor.getFileName() + line, index = editor.getCursorPosition() + source = editor.text() + offset = len("".join(source.splitlines(True)[:line])) + index + maxfixes = self.__plugin.getPreferences("MaxFixes") + + self.sendJson("getCompletions", { + "FileName": filename, + "Source": source, + "Offset": offset, + "MaxFixes": maxfixes, + }, idString=idString) + + # emulate the synchronous behaviour + timer = QTimer() + timer.setSingleShot(True) + timer.start(5000) # 5s timeout + while self.__completions is None and timer.isActive(): + QCoreApplication.processEvents() + + return [] if self.__completions is None else self.__completions + + def __processCompletionsResult(self, result): + """ + Private method to process the completions sent by the client. + + @param result dictionary containg the result sent by the client + @type dict + """ + if "Error" in result: + self.__completions = [] + else: + self.__completions = result["Completions"] # TODO: port this to the distributed variant def getCallTips(self, pos, editor): @@ -175,7 +182,7 @@ @param filename file name of the changed source (string) @param oldSource source code before the change (string) """ - print("rope: reportChanged") + print("code assist: reportChanged") ## try: ## rope.base.libutils.report_change( ## self.__project, filename, oldSource) @@ -188,6 +195,20 @@ ## Methods below handle the network connection ####################################################################### + def handleCall(self, method, params): + """ + Public method to handle a method call from the client. + + Note: This is an empty implementation that must be overridden in + derived classes. + + @param method requested method name + @type str + @param params dictionary with method specific parameters + @type dict + """ + self.__methodMapping[method](params) + def __startCodeAssistClient(self, interpreter, idString): """ Private method to start the code assist client with the given