[gnome-builder/wip/tingping/jedi-symbols] jedi: Implement symbol resolver
- From: Patrick Griffis <pgriffis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/tingping/jedi-symbols] jedi: Implement symbol resolver
- Date: Thu, 14 Sep 2017 00:07:34 +0000 (UTC)
commit 0e2394cdc169b27b570c950c05c6fa6093da06ae
Author: Patrick Griffis <tingping tingping se>
Date: Wed Sep 13 20:06:42 2017 -0400
jedi: Implement symbol resolver
plugins/jedi/jedi.plugin | 3 +-
plugins/jedi/jedi_plugin.py | 159 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 161 insertions(+), 1 deletions(-)
---
diff --git a/plugins/jedi/jedi.plugin b/plugins/jedi/jedi.plugin
index b99fc59..7e1a585 100644
--- a/plugins/jedi/jedi.plugin
+++ b/plugins/jedi/jedi.plugin
@@ -3,7 +3,8 @@ Module=jedi_plugin
Loader=python3
Name=Python Auto-Completion (Jedi)
Description=Provides autocompletion features for the Python programming language.
-Authors=Christian Hergert <christian hergert me>
+Authors=Christian Hergert <christian hergert me> Patrick Griffis <tingping tingping se>
Copyright=Copyright © 2015 Christian Hergert
Builtin=true
X-Completion-Provider-Languages=python,python3
+X-Symbol-Resolver-Languages=python,python3
diff --git a/plugins/jedi/jedi_plugin.py b/plugins/jedi/jedi_plugin.py
index 8898b69..e5c04f4 100644
--- a/plugins/jedi/jedi_plugin.py
+++ b/plugins/jedi/jedi_plugin.py
@@ -679,6 +679,160 @@ class JediCompletionRequest:
self.cancelled = True
self.invocation.return_error_literal(Gio.io_error_quark(), Gio.IOErrorEnum.CANCELLED, "Operation
was cancelled")
+
+class JediSymbolNode(Ide.SymbolNode):
+ line = GObject.Property(type=int, flags=GObject.ParamFlags.CONSTRUCT_ONLY | GObject.ParamFlags.READWRITE)
+ col = GObject.Property(type=int, flags=GObject.ParamFlags.CONSTRUCT_ONLY | GObject.ParamFlags.READWRITE)
+
+ def __init__(self, children, **kwargs):
+ super().__init__(**kwargs)
+ self.children = children
+
+ def do_get_location_async(self, cancellable, callback, user_data=None):
+ task = Gio.Task.new(self, cancellable, callback)
+ task.return_boolean(True)
+
+ def do_get_location_finish(self, result):
+ if result.propagate_boolean():
+ return Ide.SourceLocation.new(self.file, self.line, self.col, 0)
+
+ def __len__(self):
+ return len(self.children)
+
+ def __bool__(self):
+ return True
+
+ def __getitem__(self, key):
+ return self.children[key]
+
+ def __iter__(self):
+ return iter(self.children)
+
+ def __repr__(self):
+ return '<JediSymbolNode {} ({})'.format(self.props.name, self.props.kind)
+
+
+class JediSymbolTree(GObject.Object, Ide.SymbolTree):
+ def __init__(self, variant):
+ super().__init__()
+ self.root_node = self._node_from_variant(variant)
+
+ @staticmethod
+ def _node_from_variant(variant):
+ children = []
+ for i in range(variant.n_children()):
+ name, kind, line, col = variant.get_child_value(i).unpack()
+ children.append(JediSymbolNode([], name=name, kind=kind,
+ line=line, col=col))
+ return JediSymbolNode(children)
+
+ def do_get_n_children(self, node):
+ return len(node) if node is not None else len(self.root_node)
+
+ def do_get_nth_child(self, node, nth):
+ return node[nth] if node is not None else self.root_node[nth]
+
+class JediSymbolProvider(Ide.Object, Ide.SymbolResolver):
+ def __init__(self):
+ super().__init__()
+ self.proxy = None
+ self.loading_proxy = False
+
+ def do_lookup_symbol_async(self, location, cancellable, callback, user_data=None):
+ task = Gio.Task.new(self, cancellable, callback)
+ task.return_boolean(False) # Not implemented
+
+ def do_lookup_symbol_finish(self, result):
+ result.propagate_boolean()
+ return None
+
+ def do_get_symbol_tree_async(self, file_, buffer_, cancellable, callback, user_data=None):
+ task = Gio.Task.new(self, cancellable, callback)
+
+ if not self.proxy and not self.loading_proxy:
+ def get_worker_cb(app, result):
+ self.loading_proxy = False
+ self.proxy = app.get_worker_finish(result)
+ self.loading_proxy = True
+ app = Gio.Application.get_default()
+ app.get_worker_async('jedi_plugin', None, get_worker_cb)
+
+ if not self.proxy:
+ task.return_boolean(False)
+ return
+
+
+ def async_handler(proxy, result, user_data):
+ (self, results, context) = user_data
+
+ try:
+ variant = proxy.call_finish(result)
+ variant = variant.get_child_value(0) # unwrap outer tuple
+ task.symbol_tree = JediSymbolTree(variant)
+ task.return_boolean(True)
+ except GLib.Error as e:
+ task.return_error(e)
+
+ context = self.get_context()
+ unsaved_file = context.get_unsaved_files().get_unsaved_file(file_)
+ if unsaved_file is not None:
+ contents = unsaved_file.get_content().get_data().decode('utf-8')
+ else:
+ contents = ''
+
+ self.proxy.call('GetSymbolTree',
+ GLib.Variant('(ss)', (file_.get_path(), contents)),
+ 0, 10000, cancellable, async_handler, (self, task, context))
+
+
+ def do_get_symbol_tree_finish(self, result):
+ if result.propagate_boolean():
+ return result.symbol_tree
+
+ def do_load(self):
+ pass
+
+ def do_find_references_async(self, location, cancellable, callback, user_data=None):
+ task = Gio.Task.new(self, cancellable, callback)
+ task.return_boolean(False) # Not implemented
+
+ def do_find_references_finish(self, result):
+ result.propagate_boolean()
+ return None
+
+ def do_find_nearest_scope_async(self, location, cancellable, callback, user_data=None):
+ task = Gio.Task.new(self, cancellable, callback)
+ task.return_boolean(False) # Not implemented
+
+ def do_find_nearest_scope_finish(self, result):
+ result.propagate_boolean()
+ return None
+
+
+class JediSymbolTreeRequest:
+ def __init__(self, invocation, filename, content):
+ self.invocation = invocation
+ self.filename = filename
+ self.content = content
+
+ @staticmethod
+ def _jeditype_to_idetype(t):
+ return {
+ 'function': Ide.SymbolKind.FUNCTION,
+ 'module': Ide.SymbolKind.MODULE,
+ 'class': Ide.SymbolKind.CLASS,
+ 'instance': Ide.SymbolKind.VARIABLE,
+ }.get(t, Ide.SymbolKind.NONE)
+
+ def run(self):
+ results = []
+ definitions = jedi.api.names(source=self.content, path=self.filename, all_scopes=True)
+ for definition in definitions:
+ results.append((definition.name, self._jeditype_to_idetype(definition.type),
+ definition.line, definition.column))
+ self.invocation.return_value(GLib.Variant('(a(siii))', (results,)))
+
+
class JediService(Ide.DBusService):
queue = None
handler_id = None
@@ -697,6 +851,11 @@ class JediService(Ide.DBusService):
if not self.handler_id:
self.handler_id = GLib.timeout_add(5, self.process)
+ @Ide.DBusMethod('org.gnome.builder.plugins.jedi', in_signature='ss', out_signature='a(siii)', async=True)
+ def GetSymbolTree(self, invocation, filename, content):
+ request = JediSymbolTreeRequest(invocation, filename, content)
+ request.run()
+
def process(self):
self.handler_id = 0
while self.queue:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]