|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2008 - 2017 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the autocompletion interface to rope. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import os |
|
13 import sys |
|
14 |
|
15 from PyQt5.QtCore import pyqtSlot |
|
16 |
|
17 sys.path.insert(0, os.path.dirname(__file__)) |
|
18 ##if sys.version_info[0] >= 3: |
|
19 ## path = os.path.join(os.path.dirname(__file__), 'rope_py3') |
|
20 ##else: |
|
21 ## path = os.path.join(os.path.dirname(__file__), 'rope_py2') |
|
22 ## str = unicode # __IGNORE_WARNING__ |
|
23 ##sys.path.insert(0, path) |
|
24 ## |
|
25 ##import rope.base.libutils |
|
26 ##import rope.contrib.codeassist |
|
27 |
|
28 from QScintilla.Editor import Editor |
|
29 |
|
30 from JsonServer import JsonServer |
|
31 |
|
32 import Globals |
|
33 import Preferences |
|
34 |
|
35 |
|
36 class CodeAssistServer(JsonServer): |
|
37 """ |
|
38 Class implementing the autocompletion interface to rope. |
|
39 """ |
|
40 PictureIDs = { |
|
41 "class": "?{0}".format(Editor.ClassID), |
|
42 "instance": "?{0}".format(Editor.ClassID), |
|
43 "function": "?{0}".format(Editor.MethodID), |
|
44 "module": "?{0}".format(Editor.AttributeID), |
|
45 "None": "", |
|
46 } |
|
47 |
|
48 def __init__(self, plugin, parent=None): |
|
49 """ |
|
50 Constructor |
|
51 |
|
52 @param plugin reference to the plugin object |
|
53 @type RefactoringRopePlugin |
|
54 @param parent parent |
|
55 @type QObject |
|
56 """ |
|
57 super(CodeAssistServer, self).__init__(multiplex=True, parent=parent) |
|
58 |
|
59 self.__plugin = plugin |
|
60 self.__ui = parent |
|
61 |
|
62 self.__editorLanguageMapping = {} |
|
63 |
|
64 # Python 2 |
|
65 interpreter = Preferences.getDebugger("PythonInterpreter") |
|
66 self.__startCodeAssistClient(interpreter, "Python2") |
|
67 |
|
68 # Python 3 |
|
69 interpreter = Preferences.getDebugger("Python3Interpreter") |
|
70 self.__startCodeAssistClient(interpreter, "Python3") |
|
71 ## self.__project = rope.base.project.Project(Globals.getConfigDir()) |
|
72 ## self.__project.validate(self.__project.root) |
|
73 |
|
74 def __updateEditorLanguageMapping(self): |
|
75 """ |
|
76 Private method to update the editor language to connection mapping. |
|
77 """ |
|
78 self.__editorLanguageMapping = {} |
|
79 for name in self.connectionNames(): |
|
80 if name == "Python2": |
|
81 self.__editorLanguageMapping.update({ |
|
82 "Python": "Python2", |
|
83 "Python2": "Python2", |
|
84 "Pygments|Python": "Python2", |
|
85 }) |
|
86 elif name == "Python3": |
|
87 self.__editorLanguageMapping.update({ |
|
88 "Python3": "Python3", |
|
89 "Pygments|Python 3": "Python3", |
|
90 }) |
|
91 |
|
92 # TODO: port this to the distributed variant |
|
93 def getCompletions(self, editor): |
|
94 """ |
|
95 Public method to calculate the possible completions. |
|
96 |
|
97 @param editor reference to the editor object, that called this method |
|
98 QScintilla.Editor) |
|
99 @return list of proposals (QStringList) |
|
100 """ |
|
101 return [] |
|
102 ## filename = editor.getFileName() |
|
103 ## if filename: |
|
104 ## resource = rope.base.libutils.path_to_resource( |
|
105 ## self.__project, filename) |
|
106 ## else: |
|
107 ## resource = None |
|
108 ## line, index = editor.getCursorPosition() |
|
109 ## source = editor.text() |
|
110 ## offset = len("".join(source.splitlines(True)[:line])) + index |
|
111 ## maxfixes = self.__plugin.getPreferences("MaxFixes") |
|
112 ## try: |
|
113 ## proposals = rope.contrib.codeassist.code_assist( |
|
114 ## self.__project, source, offset, resource, maxfixes=maxfixes) |
|
115 ## proposals = rope.contrib.codeassist.sorted_proposals(proposals) |
|
116 ## names = [proposal.name + self.PictureIDs[proposal.type] |
|
117 ## for proposal in proposals] |
|
118 ## return names |
|
119 ## except Exception: |
|
120 ## return [] |
|
121 |
|
122 # TODO: port this to the distributed variant |
|
123 def getCallTips(self, pos, editor): |
|
124 """ |
|
125 Public method to calculate calltips. |
|
126 |
|
127 @param pos position in the text for the calltip (integer) |
|
128 @param editor reference to the editor object, that called this method |
|
129 QScintilla.Editor) |
|
130 @return list of possible calltips (list of strings) |
|
131 """ |
|
132 return [] |
|
133 ## filename = editor.getFileName() |
|
134 ## if filename: |
|
135 ## resource = rope.base.libutils.path_to_resource( |
|
136 ## self.__project, filename) |
|
137 ## else: |
|
138 ## resource = None |
|
139 ## source = editor.text() |
|
140 ## maxfixes = self.__plugin.getPreferences("CalltipsMaxFixes") |
|
141 ## try: |
|
142 ## line, index = editor.lineIndexFromPosition(pos) |
|
143 ## offset = len("".join(source.splitlines(True)[:line])) + index |
|
144 ## cts = rope.contrib.codeassist.get_calltip( |
|
145 ## self.__project, source, offset, resource, maxfixes=maxfixes, |
|
146 ## remove_self=True) |
|
147 ## if cts is not None: |
|
148 ## cts = [cts] |
|
149 ## else: |
|
150 ## cts = [] |
|
151 ## except Exception: |
|
152 ## cts = [] |
|
153 ## return cts |
|
154 |
|
155 # TODO: port this to the distributed variant |
|
156 def reportChanged(self, filename, oldSource): |
|
157 """ |
|
158 Public slot to report some changed sources. |
|
159 |
|
160 @param filename file name of the changed source (string) |
|
161 @param oldSource source code before the change (string) |
|
162 """ |
|
163 ## try: |
|
164 ## rope.base.libutils.report_change( |
|
165 ## self.__project, filename, oldSource) |
|
166 ## except RuntimeError: |
|
167 ## # this could come from trying to do PyQt4/PyQt5 mixed stuff |
|
168 ## # simply ignore it |
|
169 ## pass |
|
170 |
|
171 ####################################################################### |
|
172 ## Methods below handle the network connection |
|
173 ####################################################################### |
|
174 |
|
175 def __startCodeAssistClient(self, interpreter, idString): |
|
176 """ |
|
177 Private method to start the code assist client with the given |
|
178 interpreter. |
|
179 |
|
180 @param interpreter interpreter to be used for the code assist client |
|
181 @type str |
|
182 @param idString id of the client to be started |
|
183 @type str |
|
184 @return flag indicating a successful client start |
|
185 @rtype bool |
|
186 """ |
|
187 if interpreter: |
|
188 client = os.path.join(os.path.dirname(__file__), |
|
189 "CodeAssistClient.py") |
|
190 ok = self.startClient(interpreter, client, |
|
191 [Globals.getConfigDir()], |
|
192 idString=idString) |
|
193 if not ok: |
|
194 self.__ui.appendToStderr(self.tr( |
|
195 "'{0}' is not supported because the configured interpreter" |
|
196 " could not be started." |
|
197 ).format(idString)) |
|
198 else: |
|
199 self.__ui.appendToStderr(self.tr( |
|
200 "'{0}' is not supported because no suitable interpreter is" |
|
201 " configured." |
|
202 ).format(idString)) |
|
203 |
|
204 @pyqtSlot() |
|
205 def handleNewConnection(self): |
|
206 """ |
|
207 Public slot for new incoming connections from a client. |
|
208 """ |
|
209 super(CodeAssistServer, self).handleNewConnection() |
|
210 self.__updateEditorLanguageMapping() |