src/Lsp.vala
[roobuilder] / src / Lsp.vala
1 /* protocol.vala
2  *
3  * Copyright 2017-2019 Ben Iofel <ben@iofel.me>
4  * Copyright 2017-2020 Princeton Ferro <princetonferro@gmail.com>
5  * Copyright 2020 Sergii Fesenko <s.fesenko@outlook.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation, either version 2.1 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 namespace Lsp {
22     /**
23      * Defines how the host (editor) should sync document changes to the language server.
24      */
25     [CCode (default_value = "LSP_TEXT_DOCUMENT_SYNC_KIND_Unset")]
26     public enum TextDocumentSyncKind {
27         Unset = -1,
28         /**
29          * Documents should not be synced at all.
30          */
31         None = 0,
32         /**
33          * Documents are synced by always sending the full content of the document.
34          */
35         Full = 1,
36         /**
37          * Documents are synced by sending the full content on open. After that only incremental
38          * updates to the document are sent.
39          */
40         Incremental = 2
41     }
42
43     public  enum DiagnosticSeverity {
44         Unset = 0,
45         /**
46          * Reports an error.
47          */
48         Error = 1,
49         /**
50          * Reports a warning.
51          */
52         Warning = 2,
53         /**
54          * Reports an information.
55          */
56         Information = 3,
57         /**
58          * Reports a hint.
59          */
60         Hint = 4
61         
62     }
63
64     public  class Position : Object, Gee.Comparable<Position> {
65         /**
66          * Line position in a document (zero-based).
67          */
68         public uint line { get; set; default = -1; }
69
70         /**
71          * Character offset on a line in a document (zero-based). Assuming that the line is
72          * represented as a string, the `character` value represents the gap between the
73          * `character` and `character + 1`.
74          *
75          * If the character value is greater than the line length it defaults back to the
76          * line length.
77          */
78         public uint character { get; set; default = -1; }
79
80         public int compare_to (Position other) {
81             return line > other.line ? 1 :
82                 (line == other.line ?
83                  (character > other.character ? 1 :
84                   (character == other.character ? 0 : -1)) : -1);
85         }
86
87         public string to_string () {
88             return @"$line:$character";
89         }
90
91         public Position.from_libvala (Vala.SourceLocation sloc) {
92             line = sloc.line - 1;
93             character = sloc.column;
94         }
95
96         public Position dup () {
97             return this.translate ();
98         }
99
100         public Position translate (int dl = 0, int dc = 0) {
101             return new Position () {
102                 line = this.line + dl,
103                 character = this.character + dc
104             };
105         }
106     }
107
108     public class Range : Object, Gee.Hashable<Range>, Gee.Comparable<Range> {
109         /**
110          * The range's start position.
111          */
112         public Position start { get; set; }
113
114         /**
115          * The range's end position.
116          */
117         public Position end { get; set; }
118
119         private string? filename;
120
121         public string to_string () { return (filename != null ? @"$filename:" : "") + @"$start -> $end"; }
122
123         public Range.from_pos (Position pos) {
124             this.start = pos;
125             this.end = pos.dup ();
126         }
127
128         public Range.from_sourceref (Vala.SourceReference sref) {
129             this.start = new Position.from_libvala (sref.begin);
130             this.end = new Position.from_libvala (sref.end);
131             this.start.character -= 1;
132             this.filename = sref.file.filename;
133         }
134
135         public uint hash () {
136             return this.to_string ().hash ();
137         }
138
139         public bool equal_to (Range other) { return this.to_string () == other.to_string (); }
140                 public bool equals (Range o) {
141                         return this.filename == o.filename && this.start == o.start && this.end == o.end;
142                 }
143
144         public int compare_to (Range other) {
145             return start.compare_to (other.start);
146         }
147
148         /**
149          * Return a new range that includes `this` and `other`.
150          */
151         public Range union (Range other) {
152             var range = new Range () {
153                 start = start.compare_to (other.start) < 0 ? start : other.start,
154                 end = end.compare_to (other.end) < 0 ? other.end : end,
155             };
156             if (filename == other.filename)
157                 range.filename = filename;
158             return range;
159         }
160
161         public bool contains (Position pos) {
162             return start.compare_to (pos) <= 0 && pos.compare_to (end) <= 0;
163         }
164        
165     }
166
167     public class Diagnostic : Object {
168         /**
169          * The range at which the message applies.
170          */
171         public Range range { get; set; }
172
173         /**
174          * The diagnostic's severity. Can be omitted. If omitted it is up to the
175          * client to interpret diagnostics as error, warning, info or hint.
176          */
177         public DiagnosticSeverity severity { get; set; }
178
179         /**
180          * The diagnostic's code. Can be omitted.
181          */
182         public string? code { get; set; }
183
184         /**
185          * A human-readable string describing the source of this
186          * diagnostic, e.g. 'typescript' or 'super lint'.
187          */
188         public string? source { get; set; }
189
190         /**
191          * The diagnostic's message.
192          */
193         public string message { get; set; }
194         
195         
196         public string category {
197                 get { 
198                         switch(this.severity) {
199
200                                 case DiagnosticSeverity.Error : 
201                                         return "ERR";
202                                 case DiagnosticSeverity.Warning : 
203                                         return this.message.contains("deprecated") ? "DEPR" : "WARN";
204                                 default : 
205                                         return "WARN";
206                         }
207                 }
208                 private set {}
209                 
210         }
211         public bool equals(Lsp.Diagnostic o) {
212                 return this.range.equals(o.range) && this.severity == o.severity && this.message == o.message;
213  
214         }
215     }
216
217     /**
218      * An event describing a change to a text document. If range and rangeLength are omitted
219      * the new text is considered to be the full content of the document.
220      */
221     public class TextDocumentContentChangeEvent : Object {
222         public Range? range    { get; set; }
223         public int rangeLength { get; set; }
224         public string text     { get; set; }
225     }
226
227     public enum MessageType {
228         /**
229          * An error message.
230          */
231         Error = 1,
232         /**
233          * A warning message.
234          */
235         Warning = 2,
236         /**
237          * An information message.
238          */
239         Info = 3,
240         /**
241          * A log message.
242          */
243         Log = 4
244     }
245
246     public class TextDocumentIdentifier : Object {
247         public string uri { get; set; }
248     }
249
250     public class VersionedTextDocumentIdentifier : TextDocumentIdentifier {
251         /**
252          * The version number of this document. If a versioned text document identifier
253          * is sent from the server to the client and the file is not open in the editor
254          * (the server has not received an open notification before) the server can send
255          * `null` to indicate that the version is known and the content on disk is the
256          * master (as speced with document content ownership).
257          *
258          * The version number of a document will increase after each change, including
259          * undo/redo. The number doesn't need to be consecutive.
260          */
261         public int version { get; set; default = -1; }
262     }
263
264     public class TextDocumentPositionParams : Object {
265         public TextDocumentIdentifier textDocument { get; set; }
266         public Position position { get; set; }
267     }
268
269     public class ReferenceParams : TextDocumentPositionParams {
270         public class ReferenceContext : Object {
271             public bool includeDeclaration { get; set; }
272         }
273         public ReferenceContext? context { get; set; }
274     }
275
276     public class Location : Object {
277         public string uri { get; set; }
278         public Range range { get; set; }
279
280         public Location.from_sourceref (Vala.SourceReference sref) {
281             this (sref.file.filename, new Range.from_sourceref (sref));
282         }
283
284         public Location (string filename, Range range) {
285             this.uri = File.new_for_commandline_arg (filename).get_uri ();
286             this.range = range;
287         }
288     }
289
290     [CCode (default_value = "LSP_DOCUMENT_HIGHLIGHT_KIND_Text")]
291     public enum DocumentHighlightKind {
292         Text = 1,
293         Read = 2,
294         Write = 3
295     }
296
297     public class DocumentHighlight : Object {
298         public Range range { get; set; }
299         public DocumentHighlightKind kind { get; set; }
300     }
301
302     public class DocumentSymbolParams: Object {
303         public TextDocumentIdentifier textDocument { get; set; }
304     }
305
306     public class DocumentSymbol : Object, Json.Serializable {
307         private Vala.SourceReference? _source_reference;
308         public string name { get; set; }
309         public string? detail { get; set; }
310         public SymbolKind kind { get; set; }
311         public bool deprecated { get; set; }
312         private Range? _initial_range;
313         public Range range {
314             owned get {
315                 if (_initial_range == null)
316                     _initial_range = new Range.from_sourceref (children.first ()._source_reference);
317                 
318                 return children.fold<Range> ((child, current_range) => current_range.union (child.range), _initial_range);
319             }
320         }
321         public Range selectionRange { get; set; }
322         public Gee.List<DocumentSymbol> children { get; private set; default = new Gee.LinkedList<DocumentSymbol> (); }
323         public string? parent_name;
324
325         private DocumentSymbol () {}
326
327         /**
328          * @param type the data type containing this symbol, if there was one (not available for Namespaces, for example)
329          * @param sym the symbol
330          */
331          /*
332         public DocumentSymbol.from_vala_symbol (Vala.DataType? type, Vala.Symbol sym, SymbolKind kind) {
333             this.parent_name = sym.parent_symbol != null ? sym.parent_symbol.name : null;
334             this._initial_range = new Range.from_sourceref (sym.source_reference);
335             if (sym is Vala.Subroutine) {
336                 var sub = (Vala.Subroutine) sym;
337                 var body_sref = sub.body != null ? sub.body.source_reference : null;
338                 // debug ("subroutine %s found (body @ %s)", sym.get_full_name (),
339                 //         body_sref != null ? body_sref.to_string () : null);
340                 if (body_sref != null && (body_sref.begin.line < body_sref.end.line ||
341                                           body_sref.begin.line == body_sref.end.line && body_sref.begin.pos <= body_sref.end.pos)) {
342                     this._initial_range = this._initial_range.union (new Range.from_sourceref (body_sref));
343                 }
344             }
345             this.name = sym.name;
346             this.detail = Vls.CodeHelp.get_symbol_representation (type, sym, null, false);
347             this.kind = kind;
348             this.selectionRange = new Range.from_sourceref (sym.source_reference);
349             this.deprecated = sym.version.deprecated;
350         }
351         */
352         public new void Json.Serializable.set_property (ParamSpec pspec, Value value) {
353             base.set_property (pspec.get_name (), value);
354         }
355
356         public new Value Json.Serializable.get_property (ParamSpec pspec) {
357             Value val = Value (pspec.value_type);
358             base.get_property (pspec.get_name (), ref val);
359             return val;
360         }
361
362         public unowned ParamSpec? find_property (string name) {
363             return this.get_class ().find_property (name);
364         }
365
366         public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) {
367             if (property_name != "children")
368                 return default_serialize_property (property_name, value, pspec);
369             var node = new Json.Node (Json.NodeType.ARRAY);
370             node.init_array (new Json.Array ());
371             var array = node.get_array ();
372             foreach (var child in children)
373                 array.add_element (Json.gobject_serialize (child));
374             return node;
375         }
376
377         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) 
378             {
379                 
380                 if (property_name != "children") {
381                     return default_deserialize_property (property_name, out value, pspec, property_node);
382                 }
383                 value = GLib.Value (GLib.Type.BOXED);
384                 if (property_node.get_node_type () != Json.NodeType.ARRAY) {
385                     warning ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ());
386                     return false;
387                 }
388                          
389                 var arguments = new Gee.ArrayList<DocumentSymbol>();
390
391                 property_node.get_array ().foreach_element ((array, index, element) => {
392                     
393                         var add= Json.gobject_deserialize ( typeof (DocumentSymbol),  array.get_element(index)) as DocumentSymbol;
394                                 arguments.add( add);
395
396                    
397                 });
398
399                 value.set_boxed (arguments);
400                 return true;
401            }
402     }
403
404     public class SymbolInformation : Object {
405         public string name { get; set; }
406         public SymbolKind kind { get; set; }
407         public Location location { get; set; }
408         public string? containerName { get; set; }
409
410         public SymbolInformation.from_document_symbol (DocumentSymbol dsym, string uri) {
411             this.name = dsym.name;
412             this.kind = dsym.kind;
413             this.location = new Location (uri, dsym.range);
414             this.containerName = dsym.parent_name;
415         }
416     }
417
418     [CCode (default_value = "LSP_SYMBOL_KIND_Variable")]
419     public enum SymbolKind {
420         File = 1,
421         Module = 2,
422         Namespace = 3,
423         Package = 4,
424         Class = 5,
425         Method = 6,
426         Property = 7,
427         Field = 8,
428         Constructor = 9,
429         Enum = 10,
430         Interface = 11,
431         Function = 12,
432         Variable = 13,
433         Constant = 14,
434         String = 15,
435         Number = 16,
436         Boolean = 17,
437         Array = 18,
438         Object = 19,
439         Key = 20,
440         Null = 21,
441         EnumMember = 22,
442         Struct = 23,
443         Event = 24,
444         Operator = 25,
445         TypeParameter = 26
446     }
447
448         public class CompletionList : Object, Json.Serializable {
449         public bool isIncomplete { get; set; }
450         public Gee.List<CompletionItem> items { get; private set; default = new Gee.LinkedList<CompletionItem> (); }
451
452         public new void Json.Serializable.set_property (ParamSpec pspec, Value value) {
453             base.set_property (pspec.get_name (), value);
454         }
455
456         public new Value Json.Serializable.get_property (ParamSpec pspec) {
457             Value val = Value(pspec.value_type);
458             base.get_property (pspec.get_name (), ref val);
459             return val;
460         }
461
462         public unowned ParamSpec? find_property (string name) {
463             return this.get_class ().find_property (name);
464         }
465
466         public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) {
467             if (property_name != "items")
468                 return default_serialize_property (property_name, value, pspec);
469             var node = new Json.Node (Json.NodeType.ARRAY);
470             node.init_array (new Json.Array ());
471             var array = node.get_array ();
472             foreach (var child in items)
473                 array.add_element (Json.gobject_serialize (child));
474             return node;
475         }
476
477         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
478             error ("deserialization not supported");
479         }
480     }
481
482     [CCode (default_value = "LSP_COMPLETION_TRIGGER_KIND_Invoked")]
483     public enum CompletionTriggerKind {
484         /**
485              * Completion was triggered by typing an identifier (24x7 code
486              * complete), manual invocation (e.g Ctrl+Space) or via API.
487              */
488         Invoked = 1,
489
490         /**
491              * Completion was triggered by a trigger character specified by
492              * the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
493              */
494         TriggerCharacter = 2,
495
496         /**
497              * Completion was re-triggered as the current completion list is incomplete.
498              */
499         TriggerForIncompleteCompletions = 3
500     }
501
502     public class CompletionContext : Object {
503         public CompletionTriggerKind triggerKind { get; set;}
504         public string? triggerCharacter { get; set; }
505     }
506
507     public class CompletionParams : TextDocumentPositionParams {
508         /**
509          * The completion context. This is only available if the client specifies
510          * to send this using `ClientCapabilities.textDocument.completion.contextSupport === true`
511          */
512         public CompletionContext? context { get; set; }
513     }
514
515     public enum CompletionItemTag {
516         // Render a completion as obsolete, usually using a strike-out.
517         Deprecated = 1,
518     }
519
520     [CCode (default_value = "LSP_INSERT_TEXT_FORMAT_PlainText")]
521     public enum InsertTextFormat {
522         /**
523          * The primary text to be inserted is treated as a plain string.
524          */
525         PlainText = 1,
526
527         /**
528          * The primary text to be inserted is treated as a snippet.
529          *
530          * A snippet can define tab stops and placeholders with `$1`, `$2`
531          * and `${3:foo}`. `$0` defines the final tab stop, it defaults to
532          * the end of the snippet. Placeholders with equal identifiers are linked,
533          * that is typing in one will update others too.
534          */
535         Snippet = 2,
536     }
537
538     public class CompletionItem : Object, Gee.Hashable<CompletionItem>, Json.Serializable {
539         public string label { get; set; }
540         public CompletionItemKind kind { get; set; }
541         public string detail { get; set; }
542         public MarkupContent? documentation { get; set; }
543         public bool deprecated { get; set; }
544         public Gee.List<CompletionItemTag> tags { get; private set; default = new Gee.ArrayList<CompletionItemTag> (); }
545         public string? insertText { get; set; }
546         public InsertTextFormat insertTextFormat { get; set; default = InsertTextFormat.PlainText; }
547         private uint _hash;
548
549         private CompletionItem () {}
550
551         public CompletionItem.keyword (string keyword, string? insert_text = null, string? documentation = null) {
552             this.label = keyword;
553             this.kind = CompletionItemKind.Keyword;
554             this.insertText = insert_text;
555             if (insert_text != null && (insert_text.contains ("$0") || insert_text.contains ("${0")))
556                 this.insertTextFormat = InsertTextFormat.Snippet;
557             if (documentation != null)
558                 this.documentation = new MarkupContent.from_plaintext (documentation);
559             this._hash = @"$label $kind".hash ();
560         }
561
562         /**
563          * A completion suggestion from an existing Vala symbol.
564          * 
565          * @param instance_type the parent data type of data type of the expression where this symbol appears, or null
566          * @param sym the symbol itself
567          * @param scope the scope to display this in
568          * @param kind the kind of completion to display
569          * @param documentation the documentation to display
570          * @param label_override if non-null, override the displayed symbol name with this
571          */
572          /*
573         public CompletionItem.from_symbol (Vala.DataType? instance_type, Vala.Symbol sym, Vala.Scope? scope,
574             CompletionItemKind kind,
575             Vls.DocComment? documentation, string? label_override = null) {
576             this.label = label_override ?? sym.name;
577             this.kind = kind;
578             this.detail = Vls.CodeHelp.get_symbol_representation (instance_type, sym, scope, true, null, label_override, false);
579             this._hash = @"$label $kind".hash ();
580
581             if (documentation != null)
582                 this.documentation = new MarkupContent.from_markdown (documentation.body);
583
584             var version = sym.get_attribute ("Version");
585             if (version != null && (version.get_bool ("deprecated") || version.get_string ("deprecated_since") != null)) {
586                 this.tags.add (CompletionItemTag.Deprecated);
587                 this.deprecated = true;
588             }public
589         }
590                 */
591         /**
592          * A completion suggestion from a data type and a synthetic symbol name.
593          *
594          * @param symbol_type       the data type of the symbol
595          * @param symbol_name       the name of the synthetic symbol
596          * @param scope             the scope that this completion item is displayed in, or null
597          * @param kind              the type of completion to display
598          * @param documentation     the documentation for this symbol, or null
599          */
600          /*
601         public CompletionItem.from_synthetic_symbol (Vala.DataType symbol_type, string symbol_name, Vala.Scope? scope,
602                                                      CompletionItemKind kind, Vls.DocComment? documentation) {
603             this.label = symbol_name;
604             this.kind = kind;
605             this.detail = @"$(Vls.CodeHelp.get_symbol_representation (symbol_type, null, scope, true, null, null, false)) $symbol_name";
606             this._hash = @"$label $kind".hash ();
607
608             if (documentation != null)
609                 this.documentation = new MarkupContent.from_markdown (documentation.body);
610         }
611         */
612                 /*
613         public CompletionItem.from_unimplemented_symbol (Vala.Symbol sym, 
614                                                          string label, CompletionItemKind kind,
615                                                          string insert_text,
616                                                          Vls.DocComment? documentation) {
617             this.label = label;
618             this.kind = kind;
619             this.insertText = insert_text;
620             if (insert_text.contains ("$0") || insert_text.contains ("${0"))
621                 this.insertTextFormat = InsertTextFormat.Snippet;
622             this._hash = @"$label $kind".hash ();
623             if (documentation != null)
624                 this.documentation = new MarkupContent.from_markdown (documentation.body);
625         }
626         */
627
628         public uint hash () {
629             return this._hash;
630         }
631
632         public bool equal_to (CompletionItem other) {
633             return other.label == this.label && other.kind == this.kind;
634         }
635
636         public new void Json.Serializable.set_property (ParamSpec pspec, Value value) {
637             base.set_property (pspec.get_name (), value);
638         }
639
640         public new Value Json.Serializable.get_property (ParamSpec pspec) {
641             Value val = Value(pspec.value_type);
642             base.get_property (pspec.get_name (), ref val);
643             return val;
644         }
645
646         public unowned ParamSpec? find_property (string name) {
647             return this.get_class ().find_property (name);
648         }
649
650         public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) {
651             if (property_name != "tags")
652                 return default_serialize_property (property_name, value, pspec);
653
654             var node = new Json.Node (Json.NodeType.ARRAY);
655             node.init_array (new Json.Array ());
656             var array = node.get_array ();
657             foreach (var tag in this.tags) {
658                 array.add_int_element (tag);
659             }
660
661             return node;
662         }
663         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) 
664         {
665                 if (property_name != "tags") {
666                 return default_deserialize_property (property_name, out value, pspec, property_node);
667             }
668             value = GLib.Value (GLib.Type.BOXED);
669             if (property_node.get_node_type () != Json.NodeType.ARRAY) {
670                 warning ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ());
671                 return false;
672             }
673
674             var arguments = new Gee.ArrayList<CompletionItemTag>();
675
676             property_node.get_array ().foreach_element ((array, index, element) => {
677                 try {
678                     arguments.add ((CompletionItemTag) Json.gvariant_deserialize (element, null).get_int32() );
679                 } catch (Error e) {
680                     warning ("argument %u to command could not be deserialized: %s", index, e.message);
681                 }
682             });
683
684             value.set_boxed (arguments);
685             return true;
686        }
687     }
688
689     public class MarkupContent : Object {
690         public string kind { get; set; }
691         public string value { get; set; }
692
693         private MarkupContent () {}
694
695         /**
696          * Create a MarkupContent with plain text.
697          */
698         public MarkupContent.from_plaintext (string doc) {
699             this.kind = "plaintext";
700             this.value = doc;
701         }
702
703         /**
704          * Create a MarkupContent with markdown text.
705          */
706         public MarkupContent.from_markdown (string doc) {
707             this.kind = "markdown";
708             this.value = doc;
709         }
710     }
711     
712     [CCode (default_value = "LSP_COMPLETION_ITEM_KIND_Text")]
713     public enum CompletionItemKind {
714         Text = 1,
715         Method = 2,
716         Function = 3,
717         Constructor = 4,
718         Field = 5,
719         Variable = 6,
720         Class = 7,
721         Interface = 8,
722         Module = 9,
723         Property = 10,
724         Unit = 11,
725         Value = 12,
726         Enum = 13,
727         Keyword = 14,
728         Snippet = 15,
729         Color = 16,
730         File = 17,
731         Reference = 18,
732         Folder = 19,
733         EnumMember = 20,
734         Constant = 21,
735         Struct = 22,
736         Event = 23,
737         Operator = 24,
738         TypeParameter = 25
739     }
740     
741     /**
742      * Capabilities of the client/editor for `textDocument/documentSymbol`
743      */
744     public class DocumentSymbolCapabilities : Object {
745         public bool hierarchicalDocumentSymbolSupport { get; set; }
746     }
747
748     /**
749      * Capabilities of the client/editor for `textDocument/rename`
750      */
751     public class RenameClientCapabilities : Object {
752         public bool prepareSupport { get; set; }
753     }
754
755     /**
756      * Capabilities of the client/editor pertaining to language features.
757      */
758     public class TextDocumentClientCapabilities : Object {
759         public DocumentSymbolCapabilities documentSymbol { get; set; default = new DocumentSymbolCapabilities ();}
760         public RenameClientCapabilities rename { get; set; default = new RenameClientCapabilities (); }
761     }
762
763     /**
764      * Capabilities of the client/editor.
765      */
766     public class ClientCapabilities : Object {
767         public TextDocumentClientCapabilities textDocument { get; set; default = new TextDocumentClientCapabilities (); }
768     }
769
770     public class InitializeParams : Object {
771         public int processId { get; set; }
772         public string? rootPath { get; set; }
773         public string? rootUri { get; set; }
774         public ClientCapabilities capabilities { get; set; default = new ClientCapabilities (); }
775     }
776
777     public class SignatureInformation : Object, Json.Serializable {
778         public string label { get; set; }
779         public MarkupContent documentation { get; set; }
780
781         public Gee.List<ParameterInformation> parameters { get; private set; default = new Gee.LinkedList<ParameterInformation> (); }
782
783         public new void Json.Serializable.set_property (ParamSpec pspec, Value value) {
784             base.set_property (pspec.get_name (), value);
785         }
786
787         public new Value Json.Serializable.get_property (ParamSpec pspec) {
788             Value val = Value(pspec.value_type);
789             base.get_property (pspec.get_name (), ref val);
790             return val;
791         }
792
793         public unowned ParamSpec? find_property (string name) {
794             return this.get_class ().find_property (name);
795         }
796
797         public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) {
798             if (property_name != "parameters")
799                 return default_serialize_property (property_name, value, pspec);
800             var node = new Json.Node (Json.NodeType.ARRAY);
801             node.init_array (new Json.Array ());
802             var array = node.get_array ();
803             foreach (var child in parameters)
804                 array.add_element (Json.gobject_serialize (child));
805             return node;
806         }
807
808         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
809             error ("deserialization not supported");
810         }
811     }
812
813     public class SignatureHelp : Object, Json.Serializable {
814         public Gee.Collection<SignatureInformation> signatures { get; set; default = new Gee.ArrayList<SignatureInformation> (); }
815         public int activeSignature { get; set; }
816         public int activeParameter { get; set; }
817
818         public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) {
819             if (property_name != "signatures")
820                 return default_serialize_property (property_name, value, pspec);
821
822             var node = new Json.Node (Json.NodeType.ARRAY);
823             node.init_array (new Json.Array ());
824             var array = node.get_array ();
825             foreach (var child in signatures)
826                 array.add_element (Json.gobject_serialize (child));
827             return node;
828         }
829
830         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
831             error ("deserialization not supported");
832         }
833     }
834
835     public class ParameterInformation : Object {
836         public string label { get; set; }
837         public MarkupContent documentation { get; set; }
838     }
839
840    public  class MarkedString : Object {
841         public string language { get; set; }
842         public string value { get; set; }
843     }
844
845     public class Hover : Object, Json.Serializable {
846         public Gee.List<MarkedString> contents { get; set; default = new Gee.ArrayList<MarkedString> (); }
847         public Range range { get; set; }
848
849         public new void Json.Serializable.set_property (ParamSpec pspec, Value value) {
850             base.set_property (pspec.get_name (), value);
851         }
852
853         public new Value Json.Serializable.get_property (ParamSpec pspec) {
854             Value val = Value(pspec.value_type);
855             base.get_property (pspec.get_name (), ref val);
856             return val;
857         }
858
859         public unowned ParamSpec? find_property (string name) {
860             return this.get_class ().find_property (name);
861         }
862
863         public Json.Node serialize_property (string property_name, Value value, ParamSpec pspec) {
864             if (property_name != "contents")
865                 return default_serialize_property (property_name, value, pspec);
866             var node = new Json.Node (Json.NodeType.ARRAY);
867             node.init_array (new Json.Array ());
868             var array = node.get_array ();
869             foreach (var child in contents) {
870                 if (child.language != null)
871                     array.add_element (Json.gobject_serialize (child));
872                 else
873                     array.add_element (new Json.Node (Json.NodeType.VALUE).init_string (child.value));
874             }
875             return node;
876         }
877
878         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
879             error ("deserialization not supported");
880         }
881     }
882
883     /**
884      * A textual edit applicable to a text document.
885      */
886     public class TextEdit : Object {
887         /**
888          * The range of the text document to be manipulated. To insert
889          * text into a document create a range where ``start === end``.
890          */
891         public Range range { get; set; }
892
893         /**
894          * The string to be inserted. For delete operations use an
895          * empty string.
896          */
897         public string newText { get; set; }
898
899         public TextEdit (Range range, string new_text = "") {
900             this.range = range;
901             this.newText = new_text;
902         }
903     }
904
905     /** 
906      * Describes textual changes on a single text document. The text document is
907      * referred to as a {@link VersionedTextDocumentIdentifier} to allow clients to
908      * check the text document version before an edit is applied. A
909      * {@link TextDocumentEdit} describes all changes on a version ``Si`` and after they are
910      * applied move the document to version ``Si+1``. So the creator of a
911      * {@link TextDocumentEdit} doesn’t need to sort the array of edits or do any kind
912      * of ordering. However the edits must be non overlapping.
913      */
914     public class TextDocumentEdit : Object, Json.Serializable {
915         /**
916          * The text document to change.
917          */
918         public VersionedTextDocumentIdentifier textDocument { get; set; }
919
920         /**
921          * The edits to be applied.
922          */
923         public Gee.ArrayList<TextEdit> edits { get; set; default = new Gee.ArrayList<TextEdit> (); }
924
925         public TextDocumentEdit (VersionedTextDocumentIdentifier text_document) {
926             this.textDocument = text_document;
927         }
928
929         public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
930             if (property_name != "edits")
931                 return default_serialize_property (property_name, value, pspec);
932             
933             var node = new Json.Node (Json.NodeType.ARRAY);
934             node.init_array (new Json.Array ());
935             var array = node.get_array ();
936             foreach (var text_edit in edits) {
937                 array.add_element (Json.gobject_serialize (text_edit));
938             }
939             return node;
940         }
941
942         public bool deserialize_property (string property_name, out GLib.Value value, GLib.ParamSpec pspec, Json.Node property_node) {
943             error ("deserialization not supported");
944         }
945     }
946
947     public abstract class CommandLike : Object, Json.Serializable {
948         /**
949          * The identifier of the actual command handler.
950          */
951         public string command { get; set; }
952
953         /**
954          * Arguments that the command handler should be invoked with.
955          */
956         public Array<Variant>? arguments { get; set; }
957
958         public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
959             if (property_name != "arguments" || arguments == null)
960                 return default_serialize_property (property_name, value, pspec);
961
962             var array = new Json.Array ();
963             for (int i = 0; i < arguments.length; i++)
964                 array.add_element (Json.gvariant_serialize (arguments.index (i)));
965
966             var node = new Json.Node (Json.NodeType.ARRAY);
967             node.set_array (array);
968             return node;
969         }
970
971         public bool deserialize_property (string property_name, out GLib.Value value, GLib.ParamSpec pspec, Json.Node property_node) 
972         {
973             if (property_name == "arguments") {
974                 value = GLib.Value (GLib.Type.BOXED);
975                 if (property_node.get_node_type () != Json.NodeType.ARRAY) {
976                     warning ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ());
977                     return false;
978                 }
979
980                 var arguments = new Array<Variant> ();
981
982                 property_node.get_array ().foreach_element ((array, index, element) => {
983                     try {
984                         arguments.append_val (Json.gvariant_deserialize (element, null));
985                     } catch (Error e) {
986                         warning ("argument %u to command could not be deserialized: %s", index, e.message);
987                     }
988                 });
989
990                 value.set_boxed (arguments);
991                 return true;
992             } else if (property_name == "command") {
993                 // workaround for json-glib < 1.5.2 (Ubuntu 20.04 / eOS 6)
994                 if (property_node.get_value_type () != typeof (string)) {
995                     value = "";
996                     warning ("unexpected property node type for 'commands' %s", property_node.get_node_type ().to_string ());
997                     return false;
998                 }
999
1000                 value = property_node.get_string ();
1001                 return true;
1002             } else {
1003                 return default_deserialize_property (property_name, out value, pspec, property_node);
1004             }
1005         }
1006     }
1007
1008     public class ExecuteCommandParams : CommandLike {
1009     }
1010
1011     /**
1012      * Represents a reference to a command. Provides a title which will be used
1013      * to represent a command in the UI. Commands are identified by a string
1014      * identifier. The recommended way to handle commands is to implement their
1015      * execution on the server side if the client and server provides the
1016      * corresponding capabilities. Alternatively the tool extension code could
1017      * handle the command. The protocol currently doesn’t specify a set of
1018      * well-known commands.
1019      */
1020     public class Command : CommandLike {
1021         /**
1022          * The title of the command, like `save`.
1023          */
1024         public string title { get; set; }
1025     }
1026
1027     /**
1028      * A code lens represents a command that should be shown along with
1029      * source text, like the number of references, a way to run tests, etc.
1030      *
1031      * A code lens is _unresolved_ when no command is associated to it. For
1032      * performance reasons the creation of a code lens and resolving should be done
1033      * in two stages.
1034      */
1035     public class CodeLens : Object {
1036         /**
1037          * The range in which this code lens is valid. Should only span a single
1038          * line.
1039          */
1040         public Range range { get; set; }
1041
1042         /**
1043          * The command this code lens represents.
1044          */
1045         public Command? command { get; set; }
1046     }
1047     
1048     public class DocumentRangeFormattingParams : Object {
1049         public TextDocumentIdentifier textDocument { get; set; }
1050         public Range? range { get; set; }
1051         public FormattingOptions options { get; set; }
1052     }
1053
1054     public class FormattingOptions : Object {
1055         public uint tabSize { get; set; }
1056         public bool insertSpaces { get; set; }
1057         public bool trimTrailingWhitespace { get; set; }
1058         public bool insertFinalNewline { get; set; }
1059         public bool trimFinalNewlines { get; set; }
1060     }
1061
1062     public class CodeActionParams : Object {
1063         public TextDocumentIdentifier textDocument { get; set; }
1064         public Range range { get; set; }
1065         public CodeActionContext context { get; set; }
1066     }
1067
1068
1069     public class CodeActionContext : Object, Json.Serializable {
1070         public Gee.List<Diagnostic> diagnostics { get; set; default = new Gee.ArrayList<Diagnostic> (); }
1071         public string[]? only { get; set; }
1072 /*
1073         public bool deserialize_property (string property_name, out Value value, ParamSpec pspec, Json.Node property_node) {
1074             if (property_name != "diagnostics")
1075                 return default_deserialize_property (property_name, out value, pspec, property_node);
1076             var diags = new Gee.ArrayList<Diagnostic> ();
1077             property_node.get_array ().foreach_element ((array, index, element) => {
1078                 try {
1079                     diags.add (Vls.Util.parse_variant<Diagnostic> (Json.gvariant_deserialize (element, null)));
1080                 } catch (Error e) {
1081                     warning ("argument %u could not be deserialized: %s", index, e.message);
1082                 }
1083             });
1084             value = diags;
1085             return true;
1086         }
1087         */
1088     }
1089
1090
1091         public class Diagnostics : Object, Json.Serializable 
1092         {
1093                 public string uri { get; set; }
1094
1095                 public int version  { get; set; default = 0; }
1096         public Gee.ArrayList<Diagnostic>? diagnostics { get; set; }
1097                  
1098                 public string filename { 
1099                         owned get {
1100                                 return File.new_for_uri (this.uri).get_path();
1101                         }
1102                         private set {}
1103                 }
1104                 
1105                 public bool deserialize_property (string property_name, out GLib.Value val, GLib.ParamSpec pspec, Json.Node property_node) {
1106                         if (property_name == "diagnostics") {
1107                                 var diags =  new Gee.ArrayList<Diagnostic> ();
1108                                 if (property_node.get_node_type () != Json.NodeType.ARRAY) {
1109                                         val = diags;
1110                                         warning ("unexpected property node type for 'arguments' %s", property_node.get_node_type ().to_string ());
1111                                         return false;
1112                                 }
1113
1114                                 
1115
1116                                 property_node.get_array ().foreach_element ((array, index, element) => {
1117                                          
1118                                                 diags.add (Json.gobject_deserialize (typeof (Lsp.Diagnostic), element) as Diagnostic );
1119                                          
1120                                                 //warning ("argument %u to command could not be deserialized: %s", index, e.message);
1121                                          
1122                                 });
1123                                 val = diags;
1124                                  
1125                                 return true;
1126                         }   
1127                          
1128                         return default_deserialize_property (property_name, out val, pspec, property_node);
1129                          
1130                 }
1131
1132                 
1133         }
1134
1135
1136    public  class CodeAction : Object, Json.Serializable {
1137         public string title { get; set; }
1138         public string? kind { get; set; }
1139         public Gee.Collection<Diagnostic>? diagnostics { get; set; }
1140         public bool isPreferred { get; set; }
1141         public WorkspaceEdit? edit { get; set; }
1142         public Command? command { get; set; }
1143         public Object? data { get; set; }
1144
1145         protected void add_diagnostic (Diagnostic diag) {
1146             if (diagnostics == null)
1147                 diagnostics = new Gee.ArrayList<Diagnostic> ();
1148             diagnostics.add (diag);
1149         }
1150
1151         public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
1152             if (property_name != "diagnostics")
1153                 return default_serialize_property (property_name, value, pspec);
1154
1155             var array = new Json.Array ();
1156             if (diagnostics != null)
1157                 foreach (var text_edit in diagnostics)
1158                     array.add_element (Json.gobject_serialize (text_edit));
1159             return new Json.Node.alloc ().init_array (array);
1160         }
1161     }
1162
1163     public class WorkspaceEdit : Object, Json.Serializable {
1164         public Gee.List<TextDocumentEdit>? documentChanges { get; set; }
1165
1166         public Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
1167             if (property_name != "documentChanges")
1168                 return default_serialize_property (property_name, value, pspec);
1169
1170             var node = new Json.Node (Json.NodeType.ARRAY);
1171             node.init_array (new Json.Array ());
1172             if (documentChanges != null) {
1173                 var array = node.get_array ();
1174                 foreach (var text_edit in documentChanges) {
1175                     array.add_element (Json.gobject_serialize (text_edit));
1176                 }
1177             }
1178             return node;
1179         }
1180     }
1181
1182     [Flags]
1183     public enum SymbolTags {
1184         NONE,
1185         DEPRECATED
1186     }
1187
1188     public class CallHierarchyItem : Object, Json.Serializable {
1189         public string name { get; set; }
1190         public SymbolKind kind { get; set; }
1191         public SymbolTags tags { get; set; }
1192         public string? detail { get; set; }
1193         public string uri { get; set; }
1194         public Range range { get; set; }
1195         public Range selectionRange { get; set; }
1196
1197         public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
1198             if (property_name != "tags")
1199                 return default_serialize_property (property_name, value, pspec);
1200             var array = new Json.Array ();
1201             if (SymbolTags.DEPRECATED in tags)
1202                 array.add_int_element (SymbolTags.DEPRECATED);
1203             return new Json.Node.alloc ().init_array (array);
1204         }
1205 /*
1206         public CallHierarchyItem.from_symbol (Vala.Symbol symbol) {
1207             this.name = symbol.get_full_name ();
1208             if (symbol is Vala.Method) {
1209                 if (symbol.parent_symbol is Vala.Namespace)
1210                     this.kind = SymbolKind.Function;
1211                 else
1212                     this.kind = SymbolKind.Method;
1213             } else if (symbol is Vala.Signal) {
1214                 this.kind = SymbolKind.Event;
1215             } else if (symbol is Vala.Constructor) {
1216                 this.kind = SymbolKind.Constructor;
1217             } else {
1218                 this.kind = SymbolKind.Method;
1219             }
1220             var version = symbol.get_attribute ("Version");
1221             if (version != null && (version.get_bool ("deprecated") || version.get_string ("deprecated_since") != null)) {
1222                 this.tags |= SymbolTags.DEPRECATED;
1223             }
1224             this.detail = Vls.CodeHelp.get_symbol_representation (null, symbol, null, true);
1225             this.uri = File.new_for_commandline_arg (symbol.source_reference.file.filename).get_uri ();
1226             this.range = new Range.from_sourceref (symbol.source_reference);
1227             if (symbol.comment != null)
1228                 this.range = new Range.from_sourceref (symbol.comment.source_reference).union (this.range);
1229             if (symbol is Vala.Subroutine && ((Vala.Subroutine)symbol).body != null)
1230                 this.range = new Range.from_sourceref (((Vala.Subroutine)symbol).body.source_reference).union (this.range);
1231             this.selectionRange = new Range.from_sourceref (symbol.source_reference);
1232         }
1233         */
1234     }
1235
1236     public class CallHierarchyIncomingCall : Json.Serializable, Object {
1237         /**
1238          * The method that calls the query method.
1239          */
1240         public CallHierarchyItem from { get; set; }
1241
1242         /**
1243          * The ranges at which the query method is called by `from`.
1244          */
1245         public Gee.ArrayList<Range> fromRanges { get; set; default = new Gee.ArrayList<Range> (); }
1246
1247         public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
1248             if (property_name == "from")
1249                 return default_serialize_property (property_name, value, pspec);
1250             var array = new Json.Array ();
1251             foreach (var range in fromRanges)
1252                 array.add_element (Json.gobject_serialize (range));
1253             return new Json.Node.alloc ().init_array (array);
1254         }
1255     }
1256
1257     public class CallHierarchyOutgoingCall : Json.Serializable, Object {
1258         /**
1259          * The method that the query method calls.
1260          */
1261         public CallHierarchyItem to { get; set; }
1262
1263         /**
1264          * The ranges at which the method is called by the query method.
1265          */
1266         public Gee.ArrayList<Range> fromRanges { get; set; default = new Gee.ArrayList<Range> (); }
1267
1268         public override Json.Node serialize_property (string property_name, GLib.Value value, GLib.ParamSpec pspec) {
1269             if (property_name == "to")
1270                 return default_serialize_property (property_name, value, pspec);
1271             var array = new Json.Array ();
1272             foreach (var range in fromRanges)
1273                 array.add_element (Json.gobject_serialize (range));
1274             return new Json.Node.alloc ().init_array (array);
1275         }
1276     }
1277
1278     public class InlayHintParams : Json.Serializable, Object {
1279         public TextDocumentIdentifier textDocument { get; set; }
1280         public Range range { get; set; }
1281     }
1282
1283     public enum InlayHintKind {
1284         UNSET,
1285         TYPE,
1286         PARAMETER
1287     }
1288
1289     public class InlayHint : Object {
1290         public Position position { get; set; }
1291         public string label { get; set; }
1292         public InlayHintKind kind { get; set; }
1293         public string? tooltip { get; set; }
1294         public bool paddingLeft { get; set; }
1295         public bool paddingRight { get; set; }
1296     }
1297
1298    public  class TypeHierarchyItem : Object, Json.Serializable {
1299         /**
1300          * The name of this item
1301          */
1302         public string name { get; set; }
1303
1304         /**
1305          * The kind of this item
1306          */
1307         public SymbolKind kind { get; set; }
1308
1309         /**
1310          * Tags for this item
1311          */
1312         public SymbolTags tags { get; set; }
1313
1314         /**
1315          * More detail for this item, e.g. the signature of a function.
1316          */
1317         public string? detail { get; set; }
1318
1319         /**
1320          * The resource identifier of this item.
1321          */
1322         public string uri { get; set; }
1323
1324         /**
1325          * The range enclosing this symbol not including leading/trailing
1326          * whitespace, but everything else, e.g. comments and code.
1327          */
1328         public Range range { get; set; }
1329
1330         /**
1331          * The range that should be selected and revealed when this symbol
1332          * is being picked, e.g. the name of a function. Must be contained
1333          * by {@link TypeHierarchyItem.range}
1334          */
1335         public Range selectionRange { get; set; }
1336
1337         private TypeHierarchyItem () {}
1338 /*
1339         public TypeHierarchyItem.from_symbol (Vala.TypeSymbol symbol) {
1340             this.name = symbol.get_full_name ();
1341             if (symbol is Vala.Class)
1342                 this.kind = SymbolKind.Class;
1343             else if (symbol is Vala.Delegate)
1344                 this.kind = SymbolKind.Interface;
1345             else if (symbol is Vala.Enum)
1346                 this.kind = SymbolKind.Enum;
1347             else if (symbol is Vala.ErrorCode)
1348                 this.kind = SymbolKind.EnumMember;
1349             else if (symbol is Vala.ErrorDomain)
1350                 this.kind = SymbolKind.Enum;
1351             else if (symbol is Vala.Interface)
1352                 this.kind = SymbolKind.Interface;
1353             else if (symbol is Vala.Struct)
1354                 this.kind = SymbolKind.Struct;
1355             else if (symbol is Vala.TypeParameter)
1356                 this.kind = SymbolKind.TypeParameter;
1357             else {
1358                 this.kind = SymbolKind.Module;
1359                 warning ("unexpected symbol kind in type hierarchy: `%s'", symbol.type_name);
1360             }
1361
1362             var version = symbol.get_attribute ("Version");
1363             if (version != null && (version.get_bool ("deprecated") || version.get_string ("deprecated_since") != null)) {
1364                 this.tags |= SymbolTags.DEPRECATED;
1365             }
1366             this.detail = Vls.CodeHelp.get_symbol_representation (null, symbol, null, true);
1367             this.uri = File.new_for_commandline_arg (symbol.source_reference.file.filename).get_uri ();
1368             this.range = new Range.from_sourceref (symbol.source_reference);
1369             this.selectionRange = this.range;
1370
1371             // widen range to include all members
1372             if (symbol is Vala.ObjectTypeSymbol) {
1373                 foreach (var member in ((Vala.ObjectTypeSymbol)symbol).get_members ()) {
1374                     if (member.source_reference != null)
1375                         this.range = this.range.union (new Range.from_sourceref (member.source_reference));
1376                 }
1377             } else if (symbol is Vala.Enum) {
1378                 foreach (var member in ((Vala.Enum)symbol).get_values ()) {
1379                     if (member.source_reference != null)
1380                         this.range = this.range.union (new Range.from_sourceref (member.source_reference));
1381                 }
1382                 foreach (var method in ((Vala.Enum)symbol).get_methods ()) {
1383                     if (method.source_reference != null)
1384                         this.range = this.range.union (new Range.from_sourceref (method.source_reference));
1385                 }
1386             } else if (symbol is Vala.ErrorDomain) {
1387                 foreach (var member in ((Vala.ErrorDomain)symbol).get_codes ()) {
1388                     if (member.source_reference != null)
1389                         this.range = this.range.union (new Range.from_sourceref (member.source_reference));
1390                 }
1391                 foreach (var method in ((Vala.ErrorDomain)symbol).get_methods ()) {
1392                     if (method.source_reference != null)
1393                         this.range = this.range.union (new Range.from_sourceref (method.source_reference));
1394                 }
1395             } else if (symbol is Vala.Struct) {
1396                 foreach (var field in ((Vala.Struct)symbol).get_fields ()) {
1397                     if (field.source_reference != null)
1398                         this.range = this.range.union (new Range.from_sourceref (field.source_reference));
1399                 }
1400                 foreach (var method in ((Vala.Struct)symbol).get_methods ()) {
1401                     if (method.source_reference != null)
1402                         this.range = this.range.union (new Range.from_sourceref (method.source_reference));
1403                 }
1404             }
1405         }
1406         */
1407     }
1408 }