Fix #8120 - more experiments with hover
[roobuilder] / src / Lsp.vala
index ec896ec..7b4b7da 100644 (file)
@@ -62,6 +62,12 @@ namespace Lsp {
     }
 
     public  class Position : Object, Gee.Comparable<Position> {
+        
+        public Position(uint line, uint chr)
+        {
+               this.line = line;
+               this.character = chr;
+        }
         /**
          * Line position in a document (zero-based).
          */
@@ -78,6 +84,7 @@ namespace Lsp {
         public uint character { get; set; default = -1; }
 
         public int compare_to (Position other) {
+             
             return line > other.line ? 1 :
                 (line == other.line ?
                  (character > other.character ? 1 :
@@ -101,20 +108,14 @@ namespace Lsp {
         }
 
         public Position translate (int dl = 0, int dc = 0) {
-            return new Position () {
-                line = this.line + dl,
-                character = this.character + dc
-            };
+            return new Position (this.character + dc, this.character + dc) ;
         }
     }
 
     public class Range : Object, Gee.Hashable<Range>, Gee.Comparable<Range> {
         
         public Range.simple(uint line, uint pos) {
-               var p =  new Position () {
-                line = line,
-                character = pos
-            };
+               var p =  new Position (line,pos);
                this.start = p;
                this.end = p;
                
@@ -151,7 +152,9 @@ namespace Lsp {
 
         public bool equal_to (Range other) { return this.to_string () == other.to_string (); }
                public bool equals (Range o) {
-                       return this.filename == o.filename && this.start.equals(o.start) && this.end.equals(o.end);
+                       return this.filename == o.filename && 
+                                       this.start.equals(o.start) && 
+                                       this.end.equals(o.end);
                }
 
         public int compare_to (Range other) {
@@ -172,7 +175,10 @@ namespace Lsp {
         }
 
         public bool contains (Position pos) {
-            return start.compare_to (pos) <= 0 && pos.compare_to (end) <= 0;
+               
+            var ret =  start.compare_to (pos) <= 0 && pos.compare_to (end) <= 0;
+           // GLib.debug( "range contains %d  (%d-%d) %s", (int)pos.line, (int)start.line, (int)end.line, ret ? "Y" : "N");
+            return ret;
         }
        
     }
@@ -335,7 +341,7 @@ namespace Lsp {
     }
 
     public class DocumentSymbol : Object, Json.Serializable {
-               private Vala.SourceReference? _source_reference;
+
                public string name { get; set; }
                public string detail { get; set; default = ""; }
                public SymbolKind kind { get; set; }
@@ -401,16 +407,16 @@ namespace Lsp {
 
         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) 
            {
-               GLib.debug("deserialise property %s" , property_name);
+               //GLib.debug("deserialise property %s" , property_name);
                if (property_name != "children") {
                    return default_deserialize_property (property_name, out value, pspec, property_node);
                }
             value = GLib.Value (typeof(GLib.ListStore));
                if (property_node.get_node_type () != Json.NodeType.ARRAY) {
-                   GLib.debug ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ());
+                  // GLib.debug ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ());
                    return false;
                }
-                       GLib.debug("got child length of %d", (int) property_node.get_array ().get_length());
+                       //GLib.debug("got child length of %d", (int) property_node.get_array ().get_length());
                var arguments = new GLib.ListStore(typeof(DocumentSymbol));
 
                property_node.get_array ().foreach_element ((array, index, element) => {
@@ -433,9 +439,10 @@ namespace Lsp {
                 
                public string tooltip {
                        owned get {
-                               GLib.debug("%s : %s", this.name, this.detail);
+                               //GLib.debug("%s : %s", this.name, this.detail);
                                //var detail = this.detail == "" ? (this.kind.to_string() + ": " + this.name) : this.detail;
-                                return GLib.Markup.escape_text(this.detail + "\nline: " + this.range.start.line.to_string());
+                                return "" + this.kind.to_string().replace( "LSP_SYMBOL_KIND_", "" ) + "\n" + 
+                                       GLib.Markup.escape_text(this.detail + "\nline: " + this.range.start.line.to_string());
                                
                        }
                }
@@ -444,6 +451,75 @@ namespace Lsp {
                                return this.kind.sort_key().to_string() + "=" + this.name;
                        }
                }
+               
+               public DocumentSymbol? containsLine(uint line, uint chr)
+               {
+                       if (!this.range.contains(new Position(line, chr))) {
+                               return null;
+                       }
+
+                       for(var i = 0; i < this.children.get_n_items();i++) {
+                               var el = (DocumentSymbol)this.children.get_item(i);
+                               var ret = el.containsLine(line,chr);
+                               if (ret != null) {
+                                       return ret;
+                               }
+                       }
+                       return this;
+                       
+               }
+               // does not compare children...
+               public bool equals(DocumentSymbol sym) {
+                       return this.name == sym.name && 
+                                       this.kind == sym.kind && 
+                                       this.detail == sym.detail &&
+                                       sym.range.equals(this.range);
+               }
+               
+               public static void copyList(GLib.ListStore source, GLib.ListStore target) 
+               {
+                       //GLib.debug("copyList source=%d target=%d", (int)source.get_n_items(), (int)target.get_n_items());
+                       var i = 0;
+                       while (i < source.get_n_items()) {
+                               //GLib.debug("copyList compare %d", i);
+                               if (i >= target.get_n_items()) {
+                                       //GLib.debug("copyList append");
+                                       target.append(source.get_item(i));
+                                       i++;
+                                       continue;
+                               }
+                               var sel = (Lsp.DocumentSymbol) source.get_item(i);
+                               var tel = (Lsp.DocumentSymbol) target.get_item(i);
+                               if (!sel.equals(tel)) {
+                                       //GLib.debug("copyList replace");
+                                       target.remove(i);
+                                       target.insert(i, sel);
+                                       i++;
+                                       continue;
+                               }
+
+                               if (sel.children.get_n_items() < 1 && tel.children.get_n_items() < 1) {
+                                       i++;
+                                       //GLib.debug("copyList same  noChlidren %s", sel.name);
+                                       continue;
+
+                               }
+                               //GLib.debug("copyList same = updateChildren %s", sel.name);
+                               //
+                                       // they are the same (ignoring children
+                               copyList(sel.children,tel.children);
+                               i++;
+                       
+                       }
+                       // remove target items, that dont exist anymore
+                       while (i < target.get_n_items()) {
+                               //GLib.debug("copyList remove");
+                               target.remove(i);
+                       }
+                       
+                       
+               
+               }
           
           
     }
@@ -492,40 +568,8 @@ namespace Lsp {
         TypeParameter = 26;
         
         public string icon () { 
-                               
-                       switch (this) {
-                               
-                               // case         SymbolKind.Text: return "completion-snippet-symbolic";
-                               case    SymbolKind.Method: return "lang-method-symbolic";
-                               case    SymbolKind.Function: return "lang-function-symbolic";
-                               case    SymbolKind.Constructor: return "lang-method-symbolic";
-                               case    SymbolKind.Field: return "lang-struct-field-symbolic";
-                               case    SymbolKind.Variable: return "lang-variable-symbolic";
-                               case    SymbolKind.Class: return "lang-class-symbolic";
-                               case    SymbolKind.Interface: return "lang-class-symbolic";
-                               case    SymbolKind.Module: return "lang-namespace-symbolic";
-                               case    SymbolKind.Property:return "lang-struct-field-symbolic";
-                               //case  SymbolKind.Unit: return "lang-variable-symbolic";
-                               //case  SymbolKind.Value: return "lang-variable-symbolic";
-                               case    SymbolKind.Enum: return "lang-enum-symbolic";
-                               //case  SymbolKind.Keyword: return "completion-word-symbolic";
-                               //case  SymbolKind.Snippet: return "completion-snippet-symbolic";
-
-                               //case  SymbolKind.Color: return "lang-typedef-symbolic";
-                               case    SymbolKind.File:return "lang-typedef-symbolic";
-                               //case  SymbolKind.Reference: return "lang-typedef-symbolic";
-                               //case  SymbolKind.Folder:return "lang-typedef-symbolic";
-                               case    SymbolKind.EnumMember: return "lang-typedef-symbolic";
-                               case    SymbolKind.Constant:return "lang-typedef-symbolic";
-                               case    SymbolKind.Struct: return "lang-struct-symbolic";
-                               case    SymbolKind.Event:return "lang-typedef-symbolic";
-                               case    SymbolKind.Operator:return "lang-typedef-symbolic";
-                               case    SymbolKind.TypeParameter:return "lang-typedef-symbolic";
-                       
-                               default: 
-                                return "completion-snippet-symbolic";
-                                               
-                       }
+                       return "lang-" + this.to_string().replace( "LSP_SYMBOL_KIND_", "" ).down() + "-symbolic"; 
+                        
                }
                public int sort_key() { 
                         
@@ -789,7 +833,7 @@ namespace Lsp {
        }
     }
 
-    public class MarkupContent : Object {
+    public class MarkupContent : Object , Json.Serializable {
         public string kind { get; set; }
         public string value { get; set; }
 
@@ -810,6 +854,11 @@ namespace Lsp {
             this.kind = "markdown";
             this.value = doc;
         }
+        public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) 
+        {
+            
+            return default_deserialize_property (property_name, out value, pspec, property_node);
+        }
     }
     
     [CCode (default_value = "LSP_COMPLETION_ITEM_KIND_Text")]
@@ -909,7 +958,28 @@ namespace Lsp {
         }
 
         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
-            error ("deserialization not supported");
+           //GLib.debug("deserialise property %s" , property_name);
+               if (property_name != "parameters") {
+                   return default_deserialize_property (property_name, out value, pspec, property_node);
+               }
+            value = GLib.Value (typeof(Gee.ArrayList));
+               if (property_node.get_node_type () != Json.NodeType.ARRAY) {
+                  // GLib.debug ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ());
+                   return false;
+               }
+                       //GLib.debug("got child length of %d", (int) property_node.get_array ().get_length());
+               var arguments = new Gee.ArrayList<ParameterInformation>();
+
+               property_node.get_array ().foreach_element ((array, index, element) => {
+                   
+                       var add= Json.gobject_deserialize ( typeof (ParameterInformation),  array.get_element(index)) as ParameterInformation;
+                               arguments.add( add);
+
+                  
+               });
+
+               value.set_object (arguments);
+               return true;
         }
     }
 
@@ -935,9 +1005,16 @@ namespace Lsp {
         }
     }
 
-    public class ParameterInformation : Object {
+    public class ParameterInformation : Object, Json.Serializable {
         public string label { get; set; }
         public MarkupContent documentation { get; set; }
+        
+        public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) 
+        {
+            
+            return default_deserialize_property (property_name, out value, pspec, property_node);
+        }
+        
     }
 
    public  class MarkedString : Object {
@@ -945,7 +1022,7 @@ namespace Lsp {
                {
                        this.language = language;
                        this.value = value;
-                       GLib.debug("new marked string %s : %s", language, value);
+                       //GLib.debug("new marked string %s : %s", language, value);
                }
         public string language { get; set; }
         public string value { get; set; }
@@ -953,6 +1030,7 @@ namespace Lsp {
 
     public class Hover : Object, Json.Serializable {
         public Gee.List<MarkedString> contents { get; set; default = new Gee.ArrayList<MarkedString> (); }
+
         public Range range { get; set; }
 
         public new void Json.Serializable.set_property (ParamSpec pspec, Value value) {
@@ -993,18 +1071,25 @@ namespace Lsp {
                            return false;
                        }
                                var contents = new Gee.ArrayList<MarkedString>();
-
                        property_node.get_array ().foreach_element ((array, index, element) => {
-                               try {
-                                               var add = new MarkedString(
-                                                       array.get_object_element(index).get_string_member("language"),
-                                                       array.get_object_element(index).get_string_member("value")
-                                               );
-                            
-                               contents.add ( add );
-                           } catch (Error e) {
-                               warning ("argument %u to command could not be deserialized: %s", index, e.message);
-                           }
+                               if (element.get_node_type() == Json.NodeType.VALUE) {
+                                       var str = element.get_string();
+                                       contents.add (  new MarkedString( "", str ));
+                                       
+                                       return;
+                               }
+                               if (element.get_node_type() != Json.NodeType.OBJECT) {
+                                       GLib.debug("got content: %s", element.get_node_type().to_string());
+                                       return;
+                               }
+                       
+                               var add = new MarkedString(
+                                               element.get_object().get_string_member("language"),
+                                               element.get_object().get_string_member("value")
+                                       );
+                    
+                       contents.add ( add );
+                    
                        });
                 value.set_object (contents);
                        return true;