1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
From 8bf74c787af082102958de7498a9b4f4248788cc Mon Sep 17 00:00:00 2001
From: Elad Alfassa <elad@fedoraproject.org>
Date: Wed, 9 Aug 2017 17:39:07 +0300
Subject: [PATCH] jedi: adapt to jedi 0.10.0
https://bugzilla.gnome.org/show_bug.cgi?id=778708
---
diff --git a/plugins/jedi/jedi_plugin.py b/plugins/jedi/jedi_plugin.py
index 25ade14..8898b69 100644
--- a/plugins/jedi/jedi_plugin.py
+++ b/plugins/jedi/jedi_plugin.py
@@ -55,7 +55,6 @@ from gi.repository import GtkSource
from gi.repository import Ide
from gi.types import GObjectMeta
from gi.types import StructMeta
-
_ = Ide.gettext
gi_importer = DynamicImporter('gi.repository')
@@ -91,22 +90,31 @@ _ICONS = {
try:
import jedi
from jedi.evaluate.compiled import CompiledObject
+ from jedi.evaluate.compiled import get_special_object
from jedi.evaluate.compiled import _create_from_name
- from jedi.evaluate.compiled import builtin
+ from jedi.evaluate.context import Context
from jedi.evaluate.docstrings import _evaluate_for_statement_string
from jedi.evaluate.imports import Importer
class PatchedJediCompiledObject(CompiledObject):
"A modified version of Jedi CompiledObject to work with GObject Introspection modules"
+
+ def __init__(self, evaluator, obj, parent_context=None, faked_class=None):
+ # we have to override __init__ to change super(CompiledObject, self)
+ # to Context, in order to prevent an infinite recursion
+ Context.__init__(self, evaluator, parent_context)
+ self.obj = obj
+ self.tree_node = faked_class
+
def _cls(self):
if self.obj.__class__ == IntrospectionModule:
return self
else:
- return super()._cls()
+ return super()._cls(self)
@property
def py__call__(self):
- def actual(evaluator, params):
+ def actual(params):
# Parse the docstring to find the return type:
ret_type = ''
if '->' in self.obj.__doc__:
@@ -115,18 +123,21 @@ try:
if ret_type.startswith('iter:'):
ret_type = ret_type[len('iter:'):] # we don't care if it's an iterator
- if ret_type in __builtins__:
+ if hasattr(__builtins__, ret_type):
# The function we're inspecting returns a builtin python type, that's easy
- obj = _create_from_name(builtin, builtin, ret_type)
- return evaluator.execute(obj, params)
+ # (see test/test_evaluate/test_compiled.py in the jedi source code for usage)
+ builtins = get_special_object(self.evaluator, 'BUILTINS')
+ builtin_obj = builtins.py__getattribute__(ret_type)
+ obj = _create_from_name(self.evaluator, builtins, builtin_obj, "")
+ return self.evaluator.execute(obj, params)
else:
# The function we're inspecting returns a GObject type
- parent = self.parent.obj.__name__
+ parent = self.parent_context.obj.__name__
if parent.startswith('gi.repository'):
parent = parent[len('gi.repository.'):]
else:
# a module with overrides, such as Gtk, behaves differently
- parent_module = self.parent.obj.__module__
+ parent_module = self.parent_context.obj.__module__
if parent_module.startswith('gi.overrides'):
parent_module = parent_module[len('gi.overrides.'):]
parent = '%s.%s' % (parent_module, parent)
@@ -138,22 +149,28 @@ try:
# A pygobject type in a different module
return_type_parent = ret_type.split('.', 1)[0]
ret_type = 'from gi.repository import %s\n%s' % (return_type_parent, ret_type)
- result = _evaluate_for_statement_string(evaluator, ret_type, self.parent)
- return result
+ result = _evaluate_for_statement_string(self.parent_context, ret_type)
+ return set(result)
if type(self.obj) == FunctionInfo:
return actual
return super().py__call__
+ # we need to override CompiledBoundMethod without changing it much,
+ # just so it'll not get confused due to our overriden CompiledObject
+ class PatchedCompiledBoundMethod(PatchedJediCompiledObject):
+ def __init__(self, func):
+ super().__init__(func.evaluator, func.obj, func.parent_context, func.tree_node)
+
class PatchedJediImporter(Importer):
"A modified version of Jedi Importer to work with GObject Introspection modules"
def follow(self):
module_list = super().follow()
- if module_list == []:
+ if not module_list:
import_path = '.'.join([str(i) for i in self.import_path])
if import_path.startswith('gi.repository'):
try:
module = gi_importer.load_module(import_path)
- module_list = [PatchedJediCompiledObject(module)]
+ module_list = [PatchedJediCompiledObject(self._evaluator, module)]
except ImportError:
pass
return module_list
@@ -169,9 +186,9 @@ try:
return original_jedi_get_module('gi._gobject')
jedi.evaluate.compiled.fake.get_module = patched_jedi_get_module
-
- jedi.evaluate.imports.Importer = PatchedJediImporter
jedi.evaluate.compiled.CompiledObject = PatchedJediCompiledObject
+ jedi.evaluate.instance.CompiledBoundMethod = PatchedCompiledBoundMethod
+ jedi.evaluate.imports.Importer = PatchedJediImporter
HAS_JEDI = True
except ImportError:
print("jedi not found, python auto-completion not possible.")
@@ -331,7 +348,6 @@ def update_doc_db_on_startup():
update_doc_db_on_startup()
-
class JediCompletionProvider(Ide.Object, GtkSource.CompletionProvider, Ide.CompletionProvider):
context = None
current_word = None
@@ -600,6 +616,15 @@ class JediCompletionRequest:
script = jedi.Script(self.content, self.line + 1, self.column, self.filename)
db = DocumentationDB()
+
+ def get_gi_obj(info):
+ """ Get a GObject Introspection object from a jedi Completion, or None if the completion is not GObject Introspection related """
+ if (type(info._module) == PatchedJediCompiledObject and
+ info._module.obj.__class__ == IntrospectionModule):
+ return next(info._name.infer()).obj
+ else:
+ return None
+
for info in script.completions():
if self.cancelled:
return
@@ -608,10 +633,9 @@ class JediCompletionRequest:
# we have to use custom names here because .type and .params can't
# be overridden (they are properties)
- if type(info._definition) == PatchedJediCompiledObject and \
- type(info._definition.obj) == FunctionInfo:
+ obj = get_gi_obj(info)
+ if type(obj) == FunctionInfo:
info.real_type = 'function'
- obj = info._definition.obj
params = [arg_info.get_name() for arg_info in obj.get_arguments()]
else:
info.real_type = info.type
@@ -626,8 +650,8 @@ class JediCompletionRequest:
params.append(param.name)
doc = info.docstring()
- if hasattr(info._definition, 'obj'):
- obj = info._definition.obj
+ if obj is not None:
+ # get documentation for this GObject Introspection object
symbol = None
namespace = None
@@ -640,17 +664,7 @@ class JediCompletionRequest:
namespace = obj.get_namespace()
if symbol is not None:
- # we need to walk down the path to find the module so we can get the version
- parent = info._definition.parent
- found = False
- while not found:
- new_parent = parent.parent
- if new_parent is None:
- found = True
- else:
- parent = new_parent
- version = parent.obj._version
- result = db.query(symbol, version)
+ result = db.query(symbol, info._module.obj._version)
if result is not None:
doc = result
--
libgit2 0.26.0
|