[gnome-builder] vala: add a simple symbol tree for vala



commit 34107505f2e733e9d998c53dde796c48738f2ecf
Author: Christian Hergert <christian hergert me>
Date:   Sat Sep 26 04:36:38 2015 -0700

    vala: add a simple symbol tree for vala
    
    Not very optimized, and I noticed that libvala is leaking like crazy.
    We have a lot to do here.
    
    Also, it seems the symbol tree is broke for searching non-toplevels.

 plugins/vala-pack/Makefile.am                   |    1 +
 plugins/vala-pack/ide-vala-index.vala           |   35 +++++
 plugins/vala-pack/ide-vala-source-file.vala     |    2 +-
 plugins/vala-pack/ide-vala-symbol-resolver.vala |    9 +-
 plugins/vala-pack/ide-vala-symbol-tree.vala     |  154 +++++++++++++++++++++++
 5 files changed, 198 insertions(+), 3 deletions(-)
---
diff --git a/plugins/vala-pack/Makefile.am b/plugins/vala-pack/Makefile.am
index f83fccc..a7caeaa 100644
--- a/plugins/vala-pack/Makefile.am
+++ b/plugins/vala-pack/Makefile.am
@@ -18,6 +18,7 @@ libvala_pack_plugin_la_SOURCES = \
        ide-vala-locator.vala \
        ide-vala-source-file.vala \
        ide-vala-symbol-resolver.vala \
+       ide-vala-symbol-tree.vala \
        vala-pack-plugin.vala \
        $(NULL)
 
diff --git a/plugins/vala-pack/ide-vala-index.vala b/plugins/vala-pack/ide-vala-index.vala
index a90b1ad..76fedf6 100644
--- a/plugins/vala-pack/ide-vala-index.vala
+++ b/plugins/vala-pack/ide-vala-index.vala
@@ -326,6 +326,41 @@ namespace Ide
 
                        return symbol;
                }
+
+               public async Ide.SymbolTree? get_symbol_tree (GLib.File file,
+                                                             GLib.Cancellable? cancellable)
+                       throws GLib.Error
+               {
+                       Ide.SymbolTree? ret = null;
+
+                       Ide.ThreadPool.push (Ide.ThreadPoolKind.COMPILER, () => {
+                               lock (this.code_context) {
+                                       Vala.CodeContext.push (this.code_context);
+
+                                       if (!this.source_files.contains (file)) {
+                                               this.add_file (file);
+                                               this.reparse ();
+                                       }
+
+                                       var source_file = this.source_files [file];
+                                       if (source_file.dirty) {
+                                               this.reparse ();
+                                       }
+
+                                       var tree_builder = new Ide.ValaSymbolTreeVisitor ();
+                                       source_file.accept_children (tree_builder);
+                                       ret = tree_builder.build_tree ();
+
+                                       Vala.CodeContext.pop ();
+
+                                       GLib.Idle.add (this.get_symbol_tree.callback);
+                               }
+                       });
+
+                       yield;
+
+                       return ret;
+               }
        }
 }
 
diff --git a/plugins/vala-pack/ide-vala-source-file.vala b/plugins/vala-pack/ide-vala-source-file.vala
index f0eff3e..2a62294 100644
--- a/plugins/vala-pack/ide-vala-source-file.vala
+++ b/plugins/vala-pack/ide-vala-source-file.vala
@@ -45,7 +45,7 @@ namespace Ide
        public class ValaSourceFile: Vala.SourceFile
        {
                ArrayList<Ide.Diagnostic> diagnostics;
-               Ide.File file;
+               internal Ide.File file;
 
                public ValaSourceFile (Vala.CodeContext context,
                                       Vala.SourceFileType type,
diff --git a/plugins/vala-pack/ide-vala-symbol-resolver.vala b/plugins/vala-pack/ide-vala-symbol-resolver.vala
index 8c740ef..f498a0a 100644
--- a/plugins/vala-pack/ide-vala-symbol-resolver.vala
+++ b/plugins/vala-pack/ide-vala-symbol-resolver.vala
@@ -28,7 +28,12 @@ namespace Ide
                                                                    GLib.Cancellable? cancellable)
                        throws GLib.Error
                {
-                       return null;
+                       var context = this.get_context ();
+                       var service = (Ide.ValaService)context.get_service_typed (typeof (Ide.ValaService));
+                       var index = service.index;
+                       var symbol_tree = yield index.get_symbol_tree (file, cancellable);
+
+                       return symbol_tree;
                }
 
                public async Ide.Symbol? lookup_symbol_async (Ide.SourceLocation location,
@@ -48,7 +53,7 @@ namespace Ide
 
                        if (symbol != null) {
                                var kind = Ide.SymbolKind.FUNCTION;
-                               var flags = Ide.SymbolFlags.SYMBOL_FLAGS_NONE;
+                               var flags = Ide.SymbolFlags.NONE;
                                var source_reference = symbol.source_reference;
 
                                if (source_reference != null) {
diff --git a/plugins/vala-pack/ide-vala-symbol-tree.vala b/plugins/vala-pack/ide-vala-symbol-tree.vala
new file mode 100644
index 0000000..0f68ced
--- /dev/null
+++ b/plugins/vala-pack/ide-vala-symbol-tree.vala
@@ -0,0 +1,154 @@
+/* ide-vala-symbol-tree.vala
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+using Ide;
+using Vala;
+
+namespace Ide
+{
+       public class ValaSymbolTreeVisitor: Vala.CodeVisitor
+       {
+               HashMap<Vala.CodeNode?,ArrayList<Vala.CodeNode>> table;
+               GLib.Queue<ArrayList<Vala.CodeNode>> queue;
+
+               public ValaSymbolTreeVisitor ()
+               {
+                       this.table = new HashMap<Vala.CodeNode?,ArrayList<Vala.CodeNode>> ();
+                       this.queue = new GLib.Queue<ArrayList<Vala.CodeNode>> ();
+
+                       var root = new ArrayList<Vala.CodeNode> ();
+                       this.table [null] = root;
+                       this.queue.push_head (root);
+               }
+
+               public Ide.SymbolTree? build_tree ()
+               {
+                       return new Ide.ValaSymbolTree (this.table);
+               }
+
+               void visit_generic (Vala.CodeNode node)
+               {
+                       var current = this.queue.peek_head ();
+                       current.add (node);
+
+                       var list = new ArrayList<Vala.CodeNode> ();
+                       this.queue.push_head (list);
+
+                       this.table [node] = list;
+
+                       node.accept_children (this);
+
+                       this.queue.pop_head ();
+               }
+
+               public override void visit_class (Vala.Class node) { this.visit_generic (node); }
+               public override void visit_method (Vala.Method node) { this.visit_generic (node); }
+               public override void visit_local_variable (Vala.LocalVariable node) { this.visit_generic 
(node); }
+               public override void visit_interface (Vala.Interface node) { this.visit_generic (node); }
+               public override void visit_struct (Vala.Struct node) { this.visit_generic (node); }
+               public override void visit_creation_method (Vala.CreationMethod node) { this.visit_generic 
(node); }
+               public override void visit_property (Vala.Property node) { this.visit_generic (node); }
+               public override void visit_property_accessor (Vala.PropertyAccessor node) { 
this.visit_generic (node); }
+               public override void visit_constructor (Vala.Constructor node) { this.visit_generic (node); }
+               public override void visit_destructor (Vala.Destructor node) { this.visit_generic (node); }
+
+               public override void visit_block (Vala.Block node) { node.accept_children (this); }
+               public override void visit_source_file (Vala.SourceFile source_file) { 
source_file.accept_children (this); }
+       }
+
+       public class ValaSymbolTree : GLib.Object, Ide.SymbolTree
+       {
+               HashMap<Vala.CodeNode?,ArrayList<Vala.CodeNode>> table;
+
+               public ValaSymbolTree (HashMap<Vala.CodeNode?,ArrayList<Vala.CodeNode>> table)
+               {
+                       this.table = table;
+
+                       debug ("Tree created with %u rows", table.size);
+               }
+
+               ArrayList<Vala.CodeNode>? find (Ide.SymbolNode? node)
+               {
+                       Ide.ValaSymbolNode? symbol_node = (Ide.ValaSymbolNode)node;
+                       Vala.CodeNode? key = null;
+
+                       if (symbol_node != null) {
+                               if  (!this.table.contains (symbol_node.node))
+                                       return null;
+                               key = symbol_node.node;
+                       }
+
+                       return this.table [key];
+               }
+
+               public uint get_n_children (Ide.SymbolNode? node)
+               {
+                       var list = find (node);
+
+                       if (list == null)
+                               debug ("Failed to find child! %p", node);
+                       else
+                               debug ("node has %u children.", list.size);
+
+                       return list != null ? list.size : 0;
+               }
+
+               public Ide.SymbolNode? get_nth_child (Ide.SymbolNode? node, uint nth)
+               {
+                       var list = find (node);
+
+                       if (list != null && list.size > nth)
+                               return new Ide.ValaSymbolNode (list [(int)nth]);
+
+                       return null;
+               }
+       }
+
+       public class ValaSymbolNode : Ide.SymbolNode
+       {
+               public Vala.CodeNode? node;
+
+               public ValaSymbolNode (Vala.CodeNode node)
+               {
+                       this.node = node;
+
+                       this.name = (node as Vala.Symbol).name;
+                       this.kind = Ide.SymbolKind.NONE;
+                       this.flags = Ide.SymbolFlags.NONE;
+
+                       if (node is Vala.Method)
+                               this.kind = Ide.SymbolKind.FUNCTION;
+                       else if (node is Vala.Class)
+                               this.kind = Ide.SymbolKind.CLASS;
+                       else if (node is Vala.Struct)
+                               this.kind = Ide.SymbolKind.STRUCT;
+               }
+
+               public override Ide.SourceLocation? get_location ()
+               {
+                       var source_reference = this.node.source_reference;
+                       var file = (source_reference.file as Ide.ValaSourceFile).file;
+
+                       return new Ide.SourceLocation (file,
+                                                      source_reference.begin.line - 1,
+                                                      source_reference.begin.column - 1,
+                                                      0);
+               }
+       }
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]