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