10 from __future__ import unicode_literals |
10 from __future__ import unicode_literals |
11 |
11 |
12 import os |
12 import os |
13 import sys |
13 import sys |
14 |
14 |
15 from PyQt5.QtCore import pyqtSlot |
15 from PyQt5.QtCore import pyqtSlot, QCoreApplication, QTimer |
16 |
16 |
17 # TODO: eliminate this |
17 # TODO: eliminate this |
18 sys.path.insert(0, os.path.dirname(__file__)) |
18 sys.path.insert(0, os.path.dirname(__file__)) |
19 ##if sys.version_info[0] >= 3: |
|
20 ## path = os.path.join(os.path.dirname(__file__), 'rope_py3') |
|
21 ##else: |
|
22 ## path = os.path.join(os.path.dirname(__file__), 'rope_py2') |
|
23 ## str = unicode # __IGNORE_WARNING__ |
|
24 ##sys.path.insert(0, path) |
|
25 ## |
|
26 ##import rope.base.libutils |
|
27 ##import rope.contrib.codeassist |
|
28 |
|
29 from QScintilla.Editor import Editor |
|
30 |
19 |
31 from JsonServer import JsonServer |
20 from JsonServer import JsonServer |
32 |
21 |
33 import Globals |
22 import Globals |
34 import Preferences |
23 import Preferences |
36 |
25 |
37 class CodeAssistServer(JsonServer): |
26 class CodeAssistServer(JsonServer): |
38 """ |
27 """ |
39 Class implementing the autocompletion interface to rope. |
28 Class implementing the autocompletion interface to rope. |
40 """ |
29 """ |
41 PictureIDs = { |
|
42 "class": "?{0}".format(Editor.ClassID), |
|
43 "instance": "?{0}".format(Editor.ClassID), |
|
44 "function": "?{0}".format(Editor.MethodID), |
|
45 "module": "?{0}".format(Editor.AttributeID), |
|
46 "None": "", |
|
47 } |
|
48 |
|
49 def __init__(self, plugin, parent=None): |
30 def __init__(self, plugin, parent=None): |
50 """ |
31 """ |
51 Constructor |
32 Constructor |
52 |
33 |
53 @param plugin reference to the plugin object |
34 @param plugin reference to the plugin object |
61 self.__plugin = plugin |
42 self.__plugin = plugin |
62 self.__ui = parent |
43 self.__ui = parent |
63 |
44 |
64 self.__editorLanguageMapping = {} |
45 self.__editorLanguageMapping = {} |
65 |
46 |
|
47 # attributes to store the resuls of the client side |
|
48 self.__completions = None |
|
49 self.__calltips = None |
|
50 |
|
51 self.__methodMapping = { |
|
52 "CompletionsResult": self.__processCompletionsResult, |
|
53 } |
|
54 |
66 # Python 2 |
55 # Python 2 |
67 interpreter = Preferences.getDebugger("PythonInterpreter") |
56 interpreter = Preferences.getDebugger("PythonInterpreter") |
68 self.__startCodeAssistClient(interpreter, "Python2") |
57 self.__startCodeAssistClient(interpreter, "Python2") |
69 |
58 |
70 # Python 3 |
59 # Python 3 |
71 interpreter = Preferences.getDebugger("Python3Interpreter") |
60 interpreter = Preferences.getDebugger("Python3Interpreter") |
72 self.__startCodeAssistClient(interpreter, "Python3") |
61 self.__startCodeAssistClient(interpreter, "Python3") |
73 ## self.__project = rope.base.project.Project(Globals.getConfigDir()) |
|
74 ## self.__project.validate(self.__project.root) |
|
75 |
62 |
76 def __updateEditorLanguageMapping(self): |
63 def __updateEditorLanguageMapping(self): |
77 """ |
64 """ |
78 Private method to update the editor language to connection mapping. |
65 Private method to update the editor language to connection mapping. |
79 """ |
66 """ |
100 @return flag indicating the support status |
87 @return flag indicating the support status |
101 @rtype bool |
88 @rtype bool |
102 """ |
89 """ |
103 return language in self.__editorLanguageMapping |
90 return language in self.__editorLanguageMapping |
104 |
91 |
105 # TODO: port this to the distributed variant |
|
106 def getCompletions(self, editor): |
92 def getCompletions(self, editor): |
107 """ |
93 """ |
108 Public method to calculate the possible completions. |
94 Public method to calculate the possible completions. |
109 |
95 |
110 @param editor reference to the editor object, that called this method |
96 @param editor reference to the editor object, that called this method |
111 QScintilla.Editor) |
97 @type QScintilla.Editor |
112 @return list of proposals (QStringList) |
98 @return list of proposals |
113 """ |
99 @rtype list of str |
114 print("rope: getCompletions") |
100 """ |
115 return [] |
101 # reset the completions buffer |
116 ## filename = editor.getFileName() |
102 self.__completions = None |
117 ## if filename: |
103 |
118 ## resource = rope.base.libutils.path_to_resource( |
104 language = editor.getLanguage() |
119 ## self.__project, filename) |
105 if language not in self.__editorLanguageMapping: |
120 ## else: |
106 return [] |
121 ## resource = None |
107 idString = self.__editorLanguageMapping[language] |
122 ## line, index = editor.getCursorPosition() |
108 |
123 ## source = editor.text() |
109 filename = editor.getFileName() |
124 ## offset = len("".join(source.splitlines(True)[:line])) + index |
110 line, index = editor.getCursorPosition() |
125 ## maxfixes = self.__plugin.getPreferences("MaxFixes") |
111 source = editor.text() |
126 ## try: |
112 offset = len("".join(source.splitlines(True)[:line])) + index |
127 ## proposals = rope.contrib.codeassist.code_assist( |
113 maxfixes = self.__plugin.getPreferences("MaxFixes") |
128 ## self.__project, source, offset, resource, maxfixes=maxfixes) |
114 |
129 ## proposals = rope.contrib.codeassist.sorted_proposals(proposals) |
115 self.sendJson("getCompletions", { |
130 ## names = [proposal.name + self.PictureIDs[proposal.type] |
116 "FileName": filename, |
131 ## for proposal in proposals] |
117 "Source": source, |
132 ## return names |
118 "Offset": offset, |
133 ## except Exception: |
119 "MaxFixes": maxfixes, |
134 ## return [] |
120 }, idString=idString) |
|
121 |
|
122 # emulate the synchronous behaviour |
|
123 timer = QTimer() |
|
124 timer.setSingleShot(True) |
|
125 timer.start(5000) # 5s timeout |
|
126 while self.__completions is None and timer.isActive(): |
|
127 QCoreApplication.processEvents() |
|
128 |
|
129 return [] if self.__completions is None else self.__completions |
|
130 |
|
131 def __processCompletionsResult(self, result): |
|
132 """ |
|
133 Private method to process the completions sent by the client. |
|
134 |
|
135 @param result dictionary containg the result sent by the client |
|
136 @type dict |
|
137 """ |
|
138 if "Error" in result: |
|
139 self.__completions = [] |
|
140 else: |
|
141 self.__completions = result["Completions"] |
135 |
142 |
136 # TODO: port this to the distributed variant |
143 # TODO: port this to the distributed variant |
137 def getCallTips(self, pos, editor): |
144 def getCallTips(self, pos, editor): |
138 """ |
145 """ |
139 Public method to calculate calltips. |
146 Public method to calculate calltips. |
173 Public slot to report some changed sources. |
180 Public slot to report some changed sources. |
174 |
181 |
175 @param filename file name of the changed source (string) |
182 @param filename file name of the changed source (string) |
176 @param oldSource source code before the change (string) |
183 @param oldSource source code before the change (string) |
177 """ |
184 """ |
178 print("rope: reportChanged") |
185 print("code assist: reportChanged") |
179 ## try: |
186 ## try: |
180 ## rope.base.libutils.report_change( |
187 ## rope.base.libutils.report_change( |
181 ## self.__project, filename, oldSource) |
188 ## self.__project, filename, oldSource) |
182 ## except RuntimeError: |
189 ## except RuntimeError: |
183 ## # this could come from trying to do PyQt4/PyQt5 mixed stuff |
190 ## # this could come from trying to do PyQt4/PyQt5 mixed stuff |
185 ## pass |
192 ## pass |
186 |
193 |
187 ####################################################################### |
194 ####################################################################### |
188 ## Methods below handle the network connection |
195 ## Methods below handle the network connection |
189 ####################################################################### |
196 ####################################################################### |
|
197 |
|
198 def handleCall(self, method, params): |
|
199 """ |
|
200 Public method to handle a method call from the client. |
|
201 |
|
202 Note: This is an empty implementation that must be overridden in |
|
203 derived classes. |
|
204 |
|
205 @param method requested method name |
|
206 @type str |
|
207 @param params dictionary with method specific parameters |
|
208 @type dict |
|
209 """ |
|
210 self.__methodMapping[method](params) |
190 |
211 |
191 def __startCodeAssistClient(self, interpreter, idString): |
212 def __startCodeAssistClient(self, interpreter, idString): |
192 """ |
213 """ |
193 Private method to start the code assist client with the given |
214 Private method to start the code assist client with the given |
194 interpreter. |
215 interpreter. |