You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
8.8 KiB
198 lines
8.8 KiB
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
|
|
|