1/**************************************************************************/
2/* godot_lsp.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef GODOT_LSP_H
32#define GODOT_LSP_H
33
34#include "core/doc_data.h"
35#include "core/object/class_db.h"
36#include "core/templates/list.h"
37
38namespace lsp {
39
40typedef String DocumentUri;
41
42/** Format BBCode documentation from DocData to markdown */
43static String marked_documentation(const String &p_bbcode);
44
45/**
46 * Text documents are identified using a URI. On the protocol level, URIs are passed as strings.
47 */
48struct TextDocumentIdentifier {
49 /**
50 * The text document's URI.
51 */
52 DocumentUri uri;
53
54 _FORCE_INLINE_ void load(const Dictionary &p_params) {
55 uri = p_params["uri"];
56 }
57
58 _FORCE_INLINE_ Dictionary to_json() const {
59 Dictionary dict;
60 dict["uri"] = uri;
61 return dict;
62 }
63};
64
65/**
66 * Position in a text document expressed as zero-based line and zero-based character offset.
67 * A position is between two characters like an ‘insert’ cursor in a editor.
68 * Special values like for example -1 to denote the end of a line are not supported.
69 */
70struct Position {
71 /**
72 * Line position in a document (zero-based).
73 */
74 int line = 0;
75
76 /**
77 * Character offset on a line in a document (zero-based). Assuming that the line is
78 * represented as a string, the `character` value represents the gap between the
79 * `character` and `character + 1`.
80 *
81 * If the character value is greater than the line length it defaults back to the
82 * line length.
83 */
84 int character = 0;
85
86 _FORCE_INLINE_ bool operator==(const Position &p_other) const {
87 return line == p_other.line && character == p_other.character;
88 }
89
90 String to_string() const {
91 return vformat("(%d,%d)", line, character);
92 }
93
94 _FORCE_INLINE_ void load(const Dictionary &p_params) {
95 line = p_params["line"];
96 character = p_params["character"];
97 }
98
99 _FORCE_INLINE_ Dictionary to_json() const {
100 Dictionary dict;
101 dict["line"] = line;
102 dict["character"] = character;
103 return dict;
104 }
105};
106
107/**
108 * A range in a text document expressed as (zero-based) start and end positions.
109 * A range is comparable to a selection in an editor. Therefore the end position is exclusive.
110 * If you want to specify a range that contains a line including the line ending character(s) then use an end position denoting the start of the next line.
111 */
112struct Range {
113 /**
114 * The range's start position.
115 */
116 Position start;
117
118 /**
119 * The range's end position.
120 */
121 Position end;
122
123 _FORCE_INLINE_ bool operator==(const Range &p_other) const {
124 return start == p_other.start && end == p_other.end;
125 }
126
127 bool contains(const Position &p_pos) const {
128 // Inside line range.
129 if (start.line <= p_pos.line && p_pos.line <= end.line) {
130 // If on start line: must come after start char.
131 bool start_ok = p_pos.line == start.line ? start.character <= p_pos.character : true;
132 // If on end line: must come before end char.
133 bool end_ok = p_pos.line == end.line ? p_pos.character <= end.character : true;
134 return start_ok && end_ok;
135 } else {
136 return false;
137 }
138 }
139
140 String to_string() const {
141 return vformat("[%s:%s]", start.to_string(), end.to_string());
142 }
143
144 _FORCE_INLINE_ void load(const Dictionary &p_params) {
145 start.load(p_params["start"]);
146 end.load(p_params["end"]);
147 }
148
149 _FORCE_INLINE_ Dictionary to_json() const {
150 Dictionary dict;
151 dict["start"] = start.to_json();
152 dict["end"] = end.to_json();
153 return dict;
154 }
155};
156
157/**
158 * Represents a location inside a resource, such as a line inside a text file.
159 */
160struct Location {
161 DocumentUri uri;
162 Range range;
163
164 _FORCE_INLINE_ void load(const Dictionary &p_params) {
165 uri = p_params["uri"];
166 range.load(p_params["range"]);
167 }
168
169 _FORCE_INLINE_ Dictionary to_json() const {
170 Dictionary dict;
171 dict["uri"] = uri;
172 dict["range"] = range.to_json();
173 return dict;
174 }
175};
176
177/**
178 * Represents a link between a source and a target location.
179 */
180struct LocationLink {
181 /**
182 * Span of the origin of this link.
183 *
184 * Used as the underlined span for mouse interaction. Defaults to the word range at
185 * the mouse position.
186 */
187 Range *originSelectionRange = nullptr;
188
189 /**
190 * The target resource identifier of this link.
191 */
192 String targetUri;
193
194 /**
195 * The full target range of this link. If the target for example is a symbol then target range is the
196 * range enclosing this symbol not including leading/trailing whitespace but everything else
197 * like comments. This information is typically used to highlight the range in the editor.
198 */
199 Range targetRange;
200
201 /**
202 * The range that should be selected and revealed when this link is being followed, e.g the name of a function.
203 * Must be contained by the the `targetRange`. See also `DocumentSymbol#range`
204 */
205 Range targetSelectionRange;
206};
207
208/**
209 * A parameter literal used in requests to pass a text document and a position inside that document.
210 */
211struct TextDocumentPositionParams {
212 /**
213 * The text document.
214 */
215 TextDocumentIdentifier textDocument;
216
217 /**
218 * The position inside the text document.
219 */
220 Position position;
221
222 _FORCE_INLINE_ void load(const Dictionary &p_params) {
223 textDocument.load(p_params["textDocument"]);
224 position.load(p_params["position"]);
225 }
226
227 _FORCE_INLINE_ Dictionary to_json() const {
228 Dictionary dict;
229 dict["textDocument"] = textDocument.to_json();
230 dict["position"] = position.to_json();
231 return dict;
232 }
233};
234
235struct ReferenceContext {
236 /**
237 * Include the declaration of the current symbol.
238 */
239 bool includeDeclaration;
240};
241
242struct ReferenceParams : TextDocumentPositionParams {
243 ReferenceContext context;
244};
245
246struct DocumentLinkParams {
247 /**
248 * The document to provide document links for.
249 */
250 TextDocumentIdentifier textDocument;
251
252 _FORCE_INLINE_ void load(const Dictionary &p_params) {
253 textDocument.load(p_params["textDocument"]);
254 }
255};
256
257/**
258 * A document link is a range in a text document that links to an internal or external resource, like another
259 * text document or a web site.
260 */
261struct DocumentLink {
262 /**
263 * The range this link applies to.
264 */
265 Range range;
266
267 /**
268 * The uri this link points to. If missing a resolve request is sent later.
269 */
270 DocumentUri target;
271
272 Dictionary to_json() const {
273 Dictionary dict;
274 dict["range"] = range.to_json();
275 dict["target"] = target;
276 return dict;
277 }
278};
279
280/**
281 * A textual edit applicable to a text document.
282 */
283struct TextEdit {
284 /**
285 * The range of the text document to be manipulated. To insert
286 * text into a document create a range where start === end.
287 */
288 Range range;
289
290 /**
291 * The string to be inserted. For delete operations use an
292 * empty string.
293 */
294 String newText;
295};
296
297/**
298 * The edits to be applied.
299 */
300struct WorkspaceEdit {
301 /**
302 * Holds changes to existing resources.
303 */
304 HashMap<String, Vector<TextEdit>> changes;
305
306 _FORCE_INLINE_ void add_edit(const String &uri, const TextEdit &edit) {
307 if (changes.has(uri)) {
308 changes[uri].push_back(edit);
309 } else {
310 Vector<TextEdit> edits;
311 edits.push_back(edit);
312 changes[uri] = edits;
313 }
314 }
315
316 _FORCE_INLINE_ Dictionary to_json() const {
317 Dictionary dict;
318
319 Dictionary out_changes;
320 for (const KeyValue<String, Vector<TextEdit>> &E : changes) {
321 Array edits;
322 for (int i = 0; i < E.value.size(); ++i) {
323 Dictionary text_edit;
324 text_edit["range"] = E.value[i].range.to_json();
325 text_edit["newText"] = E.value[i].newText;
326 edits.push_back(text_edit);
327 }
328 out_changes[E.key] = edits;
329 }
330 dict["changes"] = out_changes;
331
332 return dict;
333 }
334
335 _FORCE_INLINE_ void add_change(const String &uri, const int &line, const int &start_character, const int &end_character, const String &new_text) {
336 TextEdit new_edit;
337 new_edit.newText = new_text;
338 new_edit.range.start.line = line;
339 new_edit.range.start.character = start_character;
340 new_edit.range.end.line = line;
341 new_edit.range.end.character = end_character;
342
343 if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) {
344 E->value.push_back(new_edit);
345 } else {
346 Vector<TextEdit> edit_list;
347 edit_list.push_back(new_edit);
348 changes.insert(uri, edit_list);
349 }
350 }
351};
352
353/**
354 * Represents a reference to a command.
355 * Provides a title which will be used to represent a command in the UI.
356 * Commands are identified by a string identifier.
357 * The recommended way to handle commands is to implement their execution on the server side if the client and server provides the corresponding capabilities.
358 * Alternatively the tool extension code could handle the command. The protocol currently doesn’t specify a set of well-known commands.
359 */
360struct Command {
361 /**
362 * Title of the command, like `save`.
363 */
364 String title;
365 /**
366 * The identifier of the actual command handler.
367 */
368 String command;
369 /**
370 * Arguments that the command handler should be
371 * invoked with.
372 */
373 Array arguments;
374
375 Dictionary to_json() const {
376 Dictionary dict;
377 dict["title"] = title;
378 dict["command"] = command;
379 if (arguments.size()) {
380 dict["arguments"] = arguments;
381 }
382 return dict;
383 }
384};
385
386// Use namespace instead of enumeration to follow the LSP specifications.
387// `lsp::EnumName::EnumValue` is OK but `lsp::EnumValue` is not.
388
389namespace TextDocumentSyncKind {
390/**
391 * Documents should not be synced at all.
392 */
393static const int None = 0;
394
395/**
396 * Documents are synced by always sending the full content
397 * of the document.
398 */
399static const int Full = 1;
400
401/**
402 * Documents are synced by sending the full content on open.
403 * After that only incremental updates to the document are
404 * send.
405 */
406static const int Incremental = 2;
407}; // namespace TextDocumentSyncKind
408
409/**
410 * Completion options.
411 */
412struct CompletionOptions {
413 /**
414 * The server provides support to resolve additional
415 * information for a completion item.
416 */
417 bool resolveProvider = true;
418
419 /**
420 * The characters that trigger completion automatically.
421 */
422 Vector<String> triggerCharacters;
423
424 CompletionOptions() {
425 triggerCharacters.push_back(".");
426 triggerCharacters.push_back("$");
427 triggerCharacters.push_back("'");
428 triggerCharacters.push_back("\"");
429 }
430
431 Dictionary to_json() const {
432 Dictionary dict;
433 dict["resolveProvider"] = resolveProvider;
434 dict["triggerCharacters"] = triggerCharacters;
435 return dict;
436 }
437};
438
439/**
440 * Signature help options.
441 */
442struct SignatureHelpOptions {
443 /**
444 * The characters that trigger signature help
445 * automatically.
446 */
447 Vector<String> triggerCharacters;
448
449 Dictionary to_json() {
450 Dictionary dict;
451 dict["triggerCharacters"] = triggerCharacters;
452 return dict;
453 }
454};
455
456/**
457 * Code Lens options.
458 */
459struct CodeLensOptions {
460 /**
461 * Code lens has a resolve provider as well.
462 */
463 bool resolveProvider = false;
464
465 Dictionary to_json() {
466 Dictionary dict;
467 dict["resolveProvider"] = resolveProvider;
468 return dict;
469 }
470};
471
472/**
473 * Rename options
474 */
475struct RenameOptions {
476 /**
477 * Renames should be checked and tested before being executed.
478 */
479 bool prepareProvider = true;
480
481 Dictionary to_json() {
482 Dictionary dict;
483 dict["prepareProvider"] = prepareProvider;
484 return dict;
485 }
486};
487
488/**
489 * Document link options.
490 */
491struct DocumentLinkOptions {
492 /**
493 * Document links have a resolve provider as well.
494 */
495 bool resolveProvider = false;
496
497 Dictionary to_json() {
498 Dictionary dict;
499 dict["resolveProvider"] = resolveProvider;
500 return dict;
501 }
502};
503
504/**
505 * Execute command options.
506 */
507struct ExecuteCommandOptions {
508 /**
509 * The commands to be executed on the server
510 */
511 Vector<String> commands;
512
513 Dictionary to_json() {
514 Dictionary dict;
515 dict["commands"] = commands;
516 return dict;
517 }
518};
519
520/**
521 * Save options.
522 */
523struct SaveOptions {
524 /**
525 * The client is supposed to include the content on save.
526 */
527 bool includeText = true;
528
529 Dictionary to_json() {
530 Dictionary dict;
531 dict["includeText"] = includeText;
532 return dict;
533 }
534};
535
536/**
537 * Color provider options.
538 */
539struct ColorProviderOptions {
540 Dictionary to_json() {
541 Dictionary dict;
542 return dict;
543 }
544};
545
546/**
547 * Folding range provider options.
548 */
549struct FoldingRangeProviderOptions {
550 Dictionary to_json() {
551 Dictionary dict;
552 return dict;
553 }
554};
555
556struct TextDocumentSyncOptions {
557 /**
558 * Open and close notifications are sent to the server. If omitted open close notification should not
559 * be sent.
560 */
561 bool openClose = true;
562
563 /**
564 * Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full
565 * and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None.
566 */
567 int change = TextDocumentSyncKind::Full;
568
569 /**
570 * If present will save notifications are sent to the server. If omitted the notification should not be
571 * sent.
572 */
573 bool willSave = false;
574
575 /**
576 * If present will save wait until requests are sent to the server. If omitted the request should not be
577 * sent.
578 */
579 bool willSaveWaitUntil = true;
580
581 /**
582 * If present save notifications are sent to the server. If omitted the notification should not be
583 * sent.
584 */
585 SaveOptions save;
586
587 Dictionary to_json() {
588 Dictionary dict;
589 dict["willSaveWaitUntil"] = willSaveWaitUntil;
590 dict["willSave"] = willSave;
591 dict["openClose"] = openClose;
592 dict["change"] = change;
593 dict["save"] = save.to_json();
594 return dict;
595 }
596};
597
598/**
599 * Static registration options to be returned in the initialize request.
600 */
601struct StaticRegistrationOptions {
602 /**
603 * The id used to register the request. The id can be used to deregister
604 * the request again. See also Registration#id.
605 */
606 String id;
607};
608
609/**
610 * Format document on type options.
611 */
612struct DocumentOnTypeFormattingOptions {
613 /**
614 * A character on which formatting should be triggered, like `}`.
615 */
616 String firstTriggerCharacter;
617
618 /**
619 * More trigger characters.
620 */
621 Vector<String> moreTriggerCharacter;
622
623 Dictionary to_json() {
624 Dictionary dict;
625 dict["firstTriggerCharacter"] = firstTriggerCharacter;
626 dict["moreTriggerCharacter"] = moreTriggerCharacter;
627 return dict;
628 }
629};
630
631struct TextDocumentItem {
632 /**
633 * The text document's URI.
634 */
635 DocumentUri uri;
636
637 /**
638 * The text document's language identifier.
639 */
640 String languageId;
641
642 /**
643 * The version number of this document (it will increase after each
644 * change, including undo/redo).
645 */
646 int version = 0;
647
648 /**
649 * The content of the opened text document.
650 */
651 String text;
652
653 void load(const Dictionary &p_dict) {
654 uri = p_dict["uri"];
655 languageId = p_dict["languageId"];
656 version = p_dict["version"];
657 text = p_dict["text"];
658 }
659
660 Dictionary to_json() const {
661 Dictionary dict;
662 dict["uri"] = uri;
663 dict["languageId"] = languageId;
664 dict["version"] = version;
665 dict["text"] = text;
666 return dict;
667 }
668};
669
670/**
671 * An event describing a change to a text document. If range and rangeLength are omitted
672 * the new text is considered to be the full content of the document.
673 */
674struct TextDocumentContentChangeEvent {
675 /**
676 * The range of the document that changed.
677 */
678 Range range;
679
680 /**
681 * The length of the range that got replaced.
682 */
683 int rangeLength = 0;
684
685 /**
686 * The new text of the range/document.
687 */
688 String text;
689
690 void load(const Dictionary &p_params) {
691 text = p_params["text"];
692 rangeLength = p_params["rangeLength"];
693 range.load(p_params["range"]);
694 }
695};
696
697// Use namespace instead of enumeration to follow the LSP specifications
698namespace DiagnosticSeverity {
699/**
700 * Reports an error.
701 */
702static const int Error = 1;
703/**
704 * Reports a warning.
705 */
706static const int Warning = 2;
707/**
708 * Reports an information.
709 */
710static const int Information = 3;
711/**
712 * Reports a hint.
713 */
714static const int Hint = 4;
715}; // namespace DiagnosticSeverity
716
717/**
718 * Represents a related message and source code location for a diagnostic. This should be
719 * used to point to code locations that cause or related to a diagnostics, e.g when duplicating
720 * a symbol in a scope.
721 */
722struct DiagnosticRelatedInformation {
723 /**
724 * The location of this related diagnostic information.
725 */
726 Location location;
727
728 /**
729 * The message of this related diagnostic information.
730 */
731 String message;
732
733 Dictionary to_json() const {
734 Dictionary dict;
735 dict["location"] = location.to_json();
736 dict["message"] = message;
737 return dict;
738 }
739};
740
741/**
742 * Represents a diagnostic, such as a compiler error or warning.
743 * Diagnostic objects are only valid in the scope of a resource.
744 */
745struct Diagnostic {
746 /**
747 * The range at which the message applies.
748 */
749 Range range;
750
751 /**
752 * The diagnostic's severity. Can be omitted. If omitted it is up to the
753 * client to interpret diagnostics as error, warning, info or hint.
754 */
755 int severity = 0;
756
757 /**
758 * The diagnostic's code, which might appear in the user interface.
759 */
760 int code = 0;
761
762 /**
763 * A human-readable string describing the source of this
764 * diagnostic, e.g. 'typescript' or 'super lint'.
765 */
766 String source;
767
768 /**
769 * The diagnostic's message.
770 */
771 String message;
772
773 /**
774 * An array of related diagnostic information, e.g. when symbol-names within
775 * a scope collide all definitions can be marked via this property.
776 */
777 Vector<DiagnosticRelatedInformation> relatedInformation;
778
779 Dictionary to_json() const {
780 Dictionary dict;
781 dict["range"] = range.to_json();
782 dict["code"] = code;
783 dict["severity"] = severity;
784 dict["message"] = message;
785 dict["source"] = source;
786 if (!relatedInformation.is_empty()) {
787 Array arr;
788 arr.resize(relatedInformation.size());
789 for (int i = 0; i < relatedInformation.size(); i++) {
790 arr[i] = relatedInformation[i].to_json();
791 }
792 dict["relatedInformation"] = arr;
793 }
794 return dict;
795 }
796};
797
798// Use namespace instead of enumeration to follow the LSP specifications
799/**
800 * Describes the content type that a client supports in various
801 * result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
802 *
803 * Please note that `MarkupKinds` must not start with a `$`. This kinds
804 * are reserved for internal usage.
805 */
806namespace MarkupKind {
807static const String PlainText = "plaintext";
808static const String Markdown = "markdown";
809}; // namespace MarkupKind
810
811/**
812 * A `MarkupContent` literal represents a string value which content is interpreted base on its
813 * kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds.
814 *
815 * If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues.
816 * See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting
817 *
818 * Here is an example how such a string can be constructed using JavaScript / TypeScript:
819 * ```typescript
820 * let markdown: MarkdownContent = {
821 * kind: MarkupKind.Markdown,
822 * value: [
823 * '# Header',
824 * 'Some text',
825 * '```typescript',
826 * 'someCode();',
827 * '```'
828 * ].join('\n')
829 * };
830 * ```
831 *
832 * *Please Note* that clients might sanitize the return markdown. A client could decide to
833 * remove HTML from the markdown to avoid script execution.
834 */
835struct MarkupContent {
836 /**
837 * The type of the Markup.
838 */
839 String kind;
840
841 /**
842 * The content itself.
843 */
844 String value;
845
846 MarkupContent() {
847 kind = MarkupKind::Markdown;
848 }
849
850 MarkupContent(const String &p_value) {
851 value = p_value;
852 kind = MarkupKind::Markdown;
853 }
854
855 Dictionary to_json() const {
856 Dictionary dict;
857 dict["kind"] = kind;
858 dict["value"] = value;
859 return dict;
860 }
861};
862
863// Use namespace instead of enumeration to follow the LSP specifications
864// `lsp::EnumName::EnumValue` is OK but `lsp::EnumValue` is not.
865// And here C++ compilers are unhappy with our enumeration name like `Color`, `File`, `RefCounted` etc.
866/**
867 * The kind of a completion entry.
868 */
869namespace CompletionItemKind {
870static const int Text = 1;
871static const int Method = 2;
872static const int Function = 3;
873static const int Constructor = 4;
874static const int Field = 5;
875static const int Variable = 6;
876static const int Class = 7;
877static const int Interface = 8;
878static const int Module = 9;
879static const int Property = 10;
880static const int Unit = 11;
881static const int Value = 12;
882static const int Enum = 13;
883static const int Keyword = 14;
884static const int Snippet = 15;
885static const int Color = 16;
886static const int File = 17;
887static const int RefCounted = 18;
888static const int Folder = 19;
889static const int EnumMember = 20;
890static const int Constant = 21;
891static const int Struct = 22;
892static const int Event = 23;
893static const int Operator = 24;
894static const int TypeParameter = 25;
895}; // namespace CompletionItemKind
896
897// Use namespace instead of enumeration to follow the LSP specifications.
898/**
899 * Defines whether the insert text in a completion item should be interpreted as
900 * plain text or a snippet.
901 */
902namespace InsertTextFormat {
903/**
904 * The primary text to be inserted is treated as a plain string.
905 */
906static const int PlainText = 1;
907
908/**
909 * The primary text to be inserted is treated as a snippet.
910 *
911 * A snippet can define tab stops and placeholders with `$1`, `$2`
912 * and `${3:foo}`. `$0` defines the final tab stop, it defaults to
913 * the end of the snippet. Placeholders with equal identifiers are linked,
914 * that is typing in one will update others too.
915 */
916static const int Snippet = 2;
917}; // namespace InsertTextFormat
918
919struct CompletionItem {
920 /**
921 * The label of this completion item. By default
922 * also the text that is inserted when selecting
923 * this completion.
924 */
925 String label;
926
927 /**
928 * The kind of this completion item. Based of the kind
929 * an icon is chosen by the editor. The standardized set
930 * of available values is defined in `CompletionItemKind`.
931 */
932 int kind = 0;
933
934 /**
935 * A human-readable string with additional information
936 * about this item, like type or symbol information.
937 */
938 String detail;
939
940 /**
941 * A human-readable string that represents a doc-comment.
942 */
943 MarkupContent documentation;
944
945 /**
946 * Indicates if this item is deprecated.
947 */
948 bool deprecated = false;
949
950 /**
951 * Select this item when showing.
952 *
953 * *Note* that only one completion item can be selected and that the
954 * tool / client decides which item that is. The rule is that the *first*
955 * item of those that match best is selected.
956 */
957 bool preselect = false;
958
959 /**
960 * A string that should be used when comparing this item
961 * with other items. When `falsy` the label is used.
962 */
963 String sortText;
964
965 /**
966 * A string that should be used when filtering a set of
967 * completion items. When `falsy` the label is used.
968 */
969 String filterText;
970
971 /**
972 * A string that should be inserted into a document when selecting
973 * this completion. When `falsy` the label is used.
974 *
975 * The `insertText` is subject to interpretation by the client side.
976 * Some tools might not take the string literally. For example
977 * VS Code when code complete is requested in this example `con<cursor position>`
978 * and a completion item with an `insertText` of `console` is provided it
979 * will only insert `sole`. Therefore it is recommended to use `textEdit` instead
980 * since it avoids additional client side interpretation.
981 *
982 * @deprecated Use textEdit instead.
983 */
984 String insertText;
985
986 /**
987 * The format of the insert text. The format applies to both the `insertText` property
988 * and the `newText` property of a provided `textEdit`.
989 */
990 int insertTextFormat = 0;
991
992 /**
993 * An edit which is applied to a document when selecting this completion. When an edit is provided the value of
994 * `insertText` is ignored.
995 *
996 * *Note:* The range of the edit must be a single line range and it must contain the position at which completion
997 * has been requested.
998 */
999 TextEdit textEdit;
1000
1001 /**
1002 * An optional array of additional text edits that are applied when
1003 * selecting this completion. Edits must not overlap (including the same insert position)
1004 * with the main edit nor with themselves.
1005 *
1006 * Additional text edits should be used to change text unrelated to the current cursor position
1007 * (for example adding an import statement at the top of the file if the completion item will
1008 * insert an unqualified type).
1009 */
1010 Vector<TextEdit> additionalTextEdits;
1011
1012 /**
1013 * An optional set of characters that when pressed while this completion is active will accept it first and
1014 * then type that character. *Note* that all commit characters should have `length=1` and that superfluous
1015 * characters will be ignored.
1016 */
1017 Vector<String> commitCharacters;
1018
1019 /**
1020 * An optional command that is executed *after* inserting this completion. *Note* that
1021 * additional modifications to the current document should be described with the
1022 * additionalTextEdits-property.
1023 */
1024 Command command;
1025
1026 /**
1027 * A data entry field that is preserved on a completion item between
1028 * a completion and a completion resolve request.
1029 */
1030 Variant data;
1031
1032 _FORCE_INLINE_ Dictionary to_json(bool resolved = false) const {
1033 Dictionary dict;
1034 dict["label"] = label;
1035 dict["kind"] = kind;
1036 dict["data"] = data;
1037 dict["insertText"] = insertText;
1038 if (resolved) {
1039 dict["detail"] = detail;
1040 dict["documentation"] = documentation.to_json();
1041 dict["deprecated"] = deprecated;
1042 dict["preselect"] = preselect;
1043 dict["sortText"] = sortText;
1044 dict["filterText"] = filterText;
1045 if (commitCharacters.size()) {
1046 dict["commitCharacters"] = commitCharacters;
1047 }
1048 if (!command.command.is_empty()) {
1049 dict["command"] = command.to_json();
1050 }
1051 }
1052 return dict;
1053 }
1054
1055 void load(const Dictionary &p_dict) {
1056 if (p_dict.has("label")) {
1057 label = p_dict["label"];
1058 }
1059 if (p_dict.has("kind")) {
1060 kind = p_dict["kind"];
1061 }
1062 if (p_dict.has("detail")) {
1063 detail = p_dict["detail"];
1064 }
1065 if (p_dict.has("documentation")) {
1066 Variant doc = p_dict["documentation"];
1067 if (doc.get_type() == Variant::STRING) {
1068 documentation.value = doc;
1069 } else if (doc.get_type() == Variant::DICTIONARY) {
1070 Dictionary v = doc;
1071 documentation.value = v["value"];
1072 }
1073 }
1074 if (p_dict.has("deprecated")) {
1075 deprecated = p_dict["deprecated"];
1076 }
1077 if (p_dict.has("preselect")) {
1078 preselect = p_dict["preselect"];
1079 }
1080 if (p_dict.has("sortText")) {
1081 sortText = p_dict["sortText"];
1082 }
1083 if (p_dict.has("filterText")) {
1084 filterText = p_dict["filterText"];
1085 }
1086 if (p_dict.has("insertText")) {
1087 insertText = p_dict["insertText"];
1088 }
1089 if (p_dict.has("data")) {
1090 data = p_dict["data"];
1091 }
1092 }
1093};
1094
1095/**
1096 * Represents a collection of [completion items](#CompletionItem) to be presented
1097 * in the editor.
1098 */
1099struct CompletionList {
1100 /**
1101 * This list it not complete. Further typing should result in recomputing
1102 * this list.
1103 */
1104 bool isIncomplete = false;
1105
1106 /**
1107 * The completion items.
1108 */
1109 Vector<CompletionItem> items;
1110};
1111
1112// Use namespace instead of enumeration to follow the LSP specifications
1113// `lsp::EnumName::EnumValue` is OK but `lsp::EnumValue` is not
1114// And here C++ compilers are unhappy with our enumeration name like `String`, `Array`, `Object` etc
1115/**
1116 * A symbol kind.
1117 */
1118namespace SymbolKind {
1119static const int File = 1;
1120static const int Module = 2;
1121static const int Namespace = 3;
1122static const int Package = 4;
1123static const int Class = 5;
1124static const int Method = 6;
1125static const int Property = 7;
1126static const int Field = 8;
1127static const int Constructor = 9;
1128static const int Enum = 10;
1129static const int Interface = 11;
1130static const int Function = 12;
1131static const int Variable = 13;
1132static const int Constant = 14;
1133static const int String = 15;
1134static const int Number = 16;
1135static const int Boolean = 17;
1136static const int Array = 18;
1137static const int Object = 19;
1138static const int Key = 20;
1139static const int Null = 21;
1140static const int EnumMember = 22;
1141static const int Struct = 23;
1142static const int Event = 24;
1143static const int Operator = 25;
1144static const int TypeParameter = 26;
1145}; // namespace SymbolKind
1146
1147/**
1148 * Represents programming constructs like variables, classes, interfaces etc. that appear in a document. Document symbols can be
1149 * hierarchical and they have two ranges: one that encloses its definition and one that points to its most interesting range,
1150 * e.g. the range of an identifier.
1151 */
1152struct DocumentSymbol {
1153 /**
1154 * The name of this symbol. Will be displayed in the user interface and therefore must not be
1155 * an empty string or a string only consisting of white spaces.
1156 */
1157 String name;
1158
1159 /**
1160 * More detail for this symbol, e.g the signature of a function.
1161 */
1162 String detail;
1163
1164 /**
1165 * Documentation for this symbol.
1166 */
1167 String documentation;
1168
1169 /**
1170 * Class name for the native symbols.
1171 */
1172 String native_class;
1173
1174 /**
1175 * The kind of this symbol.
1176 */
1177 int kind = SymbolKind::File;
1178
1179 /**
1180 * Indicates if this symbol is deprecated.
1181 */
1182 bool deprecated = false;
1183
1184 /**
1185 * If `true`: Symbol is local to script and cannot be accessed somewhere else.
1186 *
1187 * For example: local variable inside a `func`.
1188 */
1189 bool local = false;
1190
1191 /**
1192 * The range enclosing this symbol not including leading/trailing whitespace but everything else
1193 * like comments. This information is typically used to determine if the clients cursor is
1194 * inside the symbol to reveal in the symbol in the UI.
1195 */
1196 Range range;
1197
1198 /**
1199 * The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
1200 * Must be contained by the `range`.
1201 */
1202 Range selectionRange;
1203
1204 DocumentUri uri;
1205 String script_path;
1206
1207 /**
1208 * Children of this symbol, e.g. properties of a class.
1209 */
1210 Vector<DocumentSymbol> children;
1211
1212 Dictionary to_json(bool with_doc = false) const {
1213 Dictionary dict;
1214 dict["name"] = name;
1215 dict["detail"] = detail;
1216 dict["kind"] = kind;
1217 dict["deprecated"] = deprecated;
1218 dict["range"] = range.to_json();
1219 dict["selectionRange"] = selectionRange.to_json();
1220 if (with_doc) {
1221 dict["documentation"] = documentation;
1222 dict["native_class"] = native_class;
1223 }
1224 if (!children.is_empty()) {
1225 Array arr;
1226 for (int i = 0; i < children.size(); i++) {
1227 if (children[i].local) {
1228 continue;
1229 }
1230 arr.push_back(children[i].to_json(with_doc));
1231 }
1232 if (!children.is_empty()) {
1233 dict["children"] = arr;
1234 }
1235 }
1236 return dict;
1237 }
1238
1239 _FORCE_INLINE_ MarkupContent render() const {
1240 MarkupContent markdown;
1241 if (detail.length()) {
1242 markdown.value = "\t" + detail + "\n\n";
1243 }
1244 if (documentation.length()) {
1245 markdown.value += marked_documentation(documentation) + "\n\n";
1246 }
1247 if (script_path.length()) {
1248 markdown.value += "Defined in [" + script_path + "](" + uri + ")";
1249 }
1250 return markdown;
1251 }
1252
1253 _FORCE_INLINE_ CompletionItem make_completion_item(bool resolved = false) const {
1254 lsp::CompletionItem item;
1255 item.label = name;
1256
1257 if (resolved) {
1258 item.documentation = render();
1259 }
1260
1261 switch (kind) {
1262 case lsp::SymbolKind::Enum:
1263 item.kind = lsp::CompletionItemKind::Enum;
1264 break;
1265 case lsp::SymbolKind::Class:
1266 item.kind = lsp::CompletionItemKind::Class;
1267 break;
1268 case lsp::SymbolKind::Property:
1269 item.kind = lsp::CompletionItemKind::Property;
1270 break;
1271 case lsp::SymbolKind::Method:
1272 case lsp::SymbolKind::Function:
1273 item.kind = lsp::CompletionItemKind::Method;
1274 break;
1275 case lsp::SymbolKind::Event:
1276 item.kind = lsp::CompletionItemKind::Event;
1277 break;
1278 case lsp::SymbolKind::Constant:
1279 item.kind = lsp::CompletionItemKind::Constant;
1280 break;
1281 case lsp::SymbolKind::Variable:
1282 item.kind = lsp::CompletionItemKind::Variable;
1283 break;
1284 case lsp::SymbolKind::File:
1285 item.kind = lsp::CompletionItemKind::File;
1286 break;
1287 default:
1288 item.kind = lsp::CompletionItemKind::Text;
1289 break;
1290 }
1291
1292 return item;
1293 }
1294};
1295
1296struct ApplyWorkspaceEditParams {
1297 WorkspaceEdit edit;
1298
1299 Dictionary to_json() {
1300 Dictionary dict;
1301
1302 dict["edit"] = edit.to_json();
1303
1304 return dict;
1305 }
1306};
1307
1308struct NativeSymbolInspectParams {
1309 String native_class;
1310 String symbol_name;
1311
1312 void load(const Dictionary &p_params) {
1313 native_class = p_params["native_class"];
1314 symbol_name = p_params["symbol_name"];
1315 }
1316};
1317
1318/**
1319 * Enum of known range kinds
1320 */
1321namespace FoldingRangeKind {
1322/**
1323 * Folding range for a comment
1324 */
1325static const String Comment = "comment";
1326/**
1327 * Folding range for a imports or includes
1328 */
1329static const String Imports = "imports";
1330/**
1331 * Folding range for a region (e.g. `#region`)
1332 */
1333static const String Region = "region";
1334} // namespace FoldingRangeKind
1335
1336/**
1337 * Represents a folding range.
1338 */
1339struct FoldingRange {
1340 /**
1341 * The zero-based line number from where the folded range starts.
1342 */
1343 int startLine = 0;
1344
1345 /**
1346 * The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.
1347 */
1348 int startCharacter = 0;
1349
1350 /**
1351 * The zero-based line number where the folded range ends.
1352 */
1353 int endLine = 0;
1354
1355 /**
1356 * The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.
1357 */
1358 int endCharacter = 0;
1359
1360 /**
1361 * Describes the kind of the folding range such as `comment' or 'region'. The kind
1362 * is used to categorize folding ranges and used by commands like 'Fold all comments'. See
1363 * [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.
1364 */
1365 String kind = FoldingRangeKind::Region;
1366
1367 _FORCE_INLINE_ Dictionary to_json() const {
1368 Dictionary dict;
1369 dict["startLine"] = startLine;
1370 dict["startCharacter"] = startCharacter;
1371 dict["endLine"] = endLine;
1372 dict["endCharacter"] = endCharacter;
1373 return dict;
1374 }
1375};
1376
1377// Use namespace instead of enumeration to follow the LSP specifications
1378/**
1379 * How a completion was triggered
1380 */
1381namespace CompletionTriggerKind {
1382/**
1383 * Completion was triggered by typing an identifier (24x7 code
1384 * complete), manual invocation (e.g Ctrl+Space) or via API.
1385 */
1386static const int Invoked = 1;
1387
1388/**
1389 * Completion was triggered by a trigger character specified by
1390 * the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
1391 */
1392static const int TriggerCharacter = 2;
1393
1394/**
1395 * Completion was re-triggered as the current completion list is incomplete.
1396 */
1397static const int TriggerForIncompleteCompletions = 3;
1398} // namespace CompletionTriggerKind
1399
1400/**
1401 * Contains additional information about the context in which a completion request is triggered.
1402 */
1403struct CompletionContext {
1404 /**
1405 * How the completion was triggered.
1406 */
1407 int triggerKind = CompletionTriggerKind::TriggerCharacter;
1408
1409 /**
1410 * The trigger character (a single character) that has trigger code complete.
1411 * Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
1412 */
1413 String triggerCharacter;
1414
1415 void load(const Dictionary &p_params) {
1416 triggerKind = int(p_params["triggerKind"]);
1417 triggerCharacter = p_params["triggerCharacter"];
1418 }
1419};
1420
1421struct CompletionParams : public TextDocumentPositionParams {
1422 /**
1423 * The completion context. This is only available if the client specifies
1424 * to send this using `ClientCapabilities.textDocument.completion.contextSupport === true`
1425 */
1426 CompletionContext context;
1427
1428 void load(const Dictionary &p_params) {
1429 TextDocumentPositionParams::load(p_params);
1430 context.load(p_params["context"]);
1431 }
1432};
1433
1434/**
1435 * The result of a hover request.
1436 */
1437struct Hover {
1438 /**
1439 * The hover's content
1440 */
1441 MarkupContent contents;
1442
1443 /**
1444 * An optional range is a range inside a text document
1445 * that is used to visualize a hover, e.g. by changing the background color.
1446 */
1447 Range range;
1448
1449 _FORCE_INLINE_ Dictionary to_json() const {
1450 Dictionary dict;
1451 dict["range"] = range.to_json();
1452 dict["contents"] = contents.to_json();
1453 return dict;
1454 }
1455};
1456
1457/**
1458 * Represents a parameter of a callable-signature. A parameter can
1459 * have a label and a doc-comment.
1460 */
1461struct ParameterInformation {
1462 /**
1463 * The label of this parameter information.
1464 *
1465 * Either a string or an inclusive start and exclusive end offsets within its containing
1466 * signature label. (see SignatureInformation.label). The offsets are based on a UTF-16
1467 * string representation as `Position` and `Range` does.
1468 *
1469 * *Note*: a label of type string should be a substring of its containing signature label.
1470 * Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.
1471 */
1472 String label;
1473
1474 /**
1475 * The human-readable doc-comment of this parameter. Will be shown
1476 * in the UI but can be omitted.
1477 */
1478 MarkupContent documentation;
1479
1480 Dictionary to_json() const {
1481 Dictionary dict;
1482 dict["label"] = label;
1483 dict["documentation"] = documentation.to_json();
1484 return dict;
1485 }
1486};
1487
1488/**
1489 * Represents the signature of something callable. A signature
1490 * can have a label, like a function-name, a doc-comment, and
1491 * a set of parameters.
1492 */
1493struct SignatureInformation {
1494 /**
1495 * The label of this signature. Will be shown in
1496 * the UI.
1497 */
1498 String label;
1499
1500 /**
1501 * The human-readable doc-comment of this signature. Will be shown
1502 * in the UI but can be omitted.
1503 */
1504 MarkupContent documentation;
1505
1506 /**
1507 * The parameters of this signature.
1508 */
1509 Vector<ParameterInformation> parameters;
1510
1511 Dictionary to_json() const {
1512 Dictionary dict;
1513 dict["label"] = label;
1514 dict["documentation"] = documentation.to_json();
1515 Array args;
1516 for (int i = 0; i < parameters.size(); i++) {
1517 args.push_back(parameters[i].to_json());
1518 }
1519 dict["parameters"] = args;
1520 return dict;
1521 }
1522};
1523
1524/**
1525 * Signature help represents the signature of something
1526 * callable. There can be multiple signature but only one
1527 * active and only one active parameter.
1528 */
1529struct SignatureHelp {
1530 /**
1531 * One or more signatures.
1532 */
1533 Vector<SignatureInformation> signatures;
1534
1535 /**
1536 * The active signature. If omitted or the value lies outside the
1537 * range of `signatures` the value defaults to zero or is ignored if
1538 * `signatures.length === 0`. Whenever possible implementers should
1539 * make an active decision about the active signature and shouldn't
1540 * rely on a default value.
1541 * In future version of the protocol this property might become
1542 * mandatory to better express this.
1543 */
1544 int activeSignature = 0;
1545
1546 /**
1547 * The active parameter of the active signature. If omitted or the value
1548 * lies outside the range of `signatures[activeSignature].parameters`
1549 * defaults to 0 if the active signature has parameters. If
1550 * the active signature has no parameters it is ignored.
1551 * In future version of the protocol this property might become
1552 * mandatory to better express the active parameter if the
1553 * active signature does have any.
1554 */
1555 int activeParameter = 0;
1556
1557 Dictionary to_json() const {
1558 Dictionary dict;
1559 Array sigs;
1560 for (int i = 0; i < signatures.size(); i++) {
1561 sigs.push_back(signatures[i].to_json());
1562 }
1563 dict["signatures"] = sigs;
1564 dict["activeSignature"] = activeSignature;
1565 dict["activeParameter"] = activeParameter;
1566 return dict;
1567 }
1568};
1569
1570/**
1571 * A pattern to describe in which file operation requests or notifications
1572 * the server is interested in.
1573 */
1574struct FileOperationPattern {
1575 /**
1576 * The glob pattern to match.
1577 */
1578 String glob = "**/*.gd";
1579
1580 /**
1581 * Whether to match `file`s or `folder`s with this pattern.
1582 *
1583 * Matches both if undefined.
1584 */
1585 String matches = "file";
1586
1587 Dictionary to_json() const {
1588 Dictionary dict;
1589
1590 dict["glob"] = glob;
1591 dict["matches"] = matches;
1592
1593 return dict;
1594 }
1595};
1596
1597/**
1598 * A filter to describe in which file operation requests or notifications
1599 * the server is interested in.
1600 */
1601struct FileOperationFilter {
1602 /**
1603 * The actual file operation pattern.
1604 */
1605 FileOperationPattern pattern;
1606
1607 Dictionary to_json() const {
1608 Dictionary dict;
1609
1610 dict["pattern"] = pattern.to_json();
1611
1612 return dict;
1613 }
1614};
1615
1616/**
1617 * The options to register for file operations.
1618 */
1619struct FileOperationRegistrationOptions {
1620 /**
1621 * The actual filters.
1622 */
1623 Vector<FileOperationFilter> filters;
1624
1625 FileOperationRegistrationOptions() {
1626 filters.push_back(FileOperationFilter());
1627 }
1628
1629 Dictionary to_json() const {
1630 Dictionary dict;
1631
1632 Array filts;
1633 for (int i = 0; i < filters.size(); i++) {
1634 filts.push_back(filters[i].to_json());
1635 }
1636 dict["filters"] = filts;
1637
1638 return dict;
1639 }
1640};
1641
1642/**
1643 * The server is interested in file notifications/requests.
1644 */
1645struct FileOperations {
1646 /**
1647 * The server is interested in receiving didDeleteFiles file notifications.
1648 */
1649 FileOperationRegistrationOptions didDelete;
1650
1651 Dictionary to_json() const {
1652 Dictionary dict;
1653
1654 dict["didDelete"] = didDelete.to_json();
1655
1656 return dict;
1657 }
1658};
1659
1660/**
1661 * Workspace specific server capabilities
1662 */
1663struct Workspace {
1664 /**
1665 * The server is interested in file notifications/requests.
1666 */
1667 FileOperations fileOperations;
1668
1669 Dictionary to_json() const {
1670 Dictionary dict;
1671
1672 dict["fileOperations"] = fileOperations.to_json();
1673
1674 return dict;
1675 }
1676};
1677
1678struct ServerCapabilities {
1679 /**
1680 * Defines how text documents are synced. Is either a detailed structure defining each notification or
1681 * for backwards compatibility the TextDocumentSyncKind number. If omitted it defaults to `TextDocumentSyncKind.None`.
1682 */
1683 TextDocumentSyncOptions textDocumentSync;
1684
1685 /**
1686 * The server provides hover support.
1687 */
1688 bool hoverProvider = true;
1689
1690 /**
1691 * The server provides completion support.
1692 */
1693 CompletionOptions completionProvider;
1694
1695 /**
1696 * The server provides signature help support.
1697 */
1698 SignatureHelpOptions signatureHelpProvider;
1699
1700 /**
1701 * The server provides goto definition support.
1702 */
1703 bool definitionProvider = true;
1704
1705 /**
1706 * The server provides Goto Type Definition support.
1707 *
1708 * Since 3.6.0
1709 */
1710 bool typeDefinitionProvider = false;
1711
1712 /**
1713 * The server provides Goto Implementation support.
1714 *
1715 * Since 3.6.0
1716 */
1717 bool implementationProvider = false;
1718
1719 /**
1720 * The server provides find references support.
1721 */
1722 bool referencesProvider = true;
1723
1724 /**
1725 * The server provides document highlight support.
1726 */
1727 bool documentHighlightProvider = false;
1728
1729 /**
1730 * The server provides document symbol support.
1731 */
1732 bool documentSymbolProvider = true;
1733
1734 /**
1735 * The server provides workspace symbol support.
1736 */
1737 bool workspaceSymbolProvider = true;
1738
1739 /**
1740 * The server supports workspace folder.
1741 */
1742 Workspace workspace;
1743
1744 /**
1745 * The server provides code actions. The `CodeActionOptions` return type is only
1746 * valid if the client signals code action literal support via the property
1747 * `textDocument.codeAction.codeActionLiteralSupport`.
1748 */
1749 bool codeActionProvider = false;
1750
1751 /**
1752 * The server provides code lens.
1753 */
1754 CodeLensOptions codeLensProvider;
1755
1756 /**
1757 * The server provides document formatting.
1758 */
1759 bool documentFormattingProvider = false;
1760
1761 /**
1762 * The server provides document range formatting.
1763 */
1764 bool documentRangeFormattingProvider = false;
1765
1766 /**
1767 * The server provides document formatting on typing.
1768 */
1769 DocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;
1770
1771 /**
1772 * The server provides rename support. RenameOptions may only be
1773 * specified if the client states that it supports
1774 * `prepareSupport` in its initial `initialize` request.
1775 */
1776 RenameOptions renameProvider;
1777
1778 /**
1779 * The server provides document link support.
1780 */
1781 DocumentLinkOptions documentLinkProvider;
1782
1783 /**
1784 * The server provides color provider support.
1785 *
1786 * Since 3.6.0
1787 */
1788 ColorProviderOptions colorProvider;
1789
1790 /**
1791 * The server provides folding provider support.
1792 *
1793 * Since 3.10.0
1794 */
1795 FoldingRangeProviderOptions foldingRangeProvider;
1796
1797 /**
1798 * The server provides go to declaration support.
1799 *
1800 * Since 3.14.0
1801 */
1802 bool declarationProvider = true;
1803
1804 /**
1805 * The server provides execute command support.
1806 */
1807 ExecuteCommandOptions executeCommandProvider;
1808
1809 _FORCE_INLINE_ Dictionary to_json() {
1810 Dictionary dict;
1811 dict["textDocumentSync"] = textDocumentSync.to_json();
1812 dict["completionProvider"] = completionProvider.to_json();
1813 signatureHelpProvider.triggerCharacters.push_back(",");
1814 signatureHelpProvider.triggerCharacters.push_back("(");
1815 dict["signatureHelpProvider"] = signatureHelpProvider.to_json();
1816 //dict["codeLensProvider"] = codeLensProvider.to_json();
1817 dict["documentOnTypeFormattingProvider"] = documentOnTypeFormattingProvider.to_json();
1818 dict["renameProvider"] = renameProvider.to_json();
1819 dict["documentLinkProvider"] = documentLinkProvider.to_json();
1820 dict["colorProvider"] = false; // colorProvider.to_json();
1821 dict["foldingRangeProvider"] = false; //foldingRangeProvider.to_json();
1822 dict["executeCommandProvider"] = executeCommandProvider.to_json();
1823 dict["hoverProvider"] = hoverProvider;
1824 dict["definitionProvider"] = definitionProvider;
1825 dict["typeDefinitionProvider"] = typeDefinitionProvider;
1826 dict["implementationProvider"] = implementationProvider;
1827 dict["referencesProvider"] = referencesProvider;
1828 dict["documentHighlightProvider"] = documentHighlightProvider;
1829 dict["documentSymbolProvider"] = documentSymbolProvider;
1830 dict["workspaceSymbolProvider"] = workspaceSymbolProvider;
1831 dict["workspace"] = workspace.to_json();
1832 dict["codeActionProvider"] = codeActionProvider;
1833 dict["documentFormattingProvider"] = documentFormattingProvider;
1834 dict["documentRangeFormattingProvider"] = documentRangeFormattingProvider;
1835 dict["declarationProvider"] = declarationProvider;
1836 return dict;
1837 }
1838};
1839
1840struct InitializeResult {
1841 /**
1842 * The capabilities the language server provides.
1843 */
1844 ServerCapabilities capabilities;
1845
1846 _FORCE_INLINE_ Dictionary to_json() {
1847 Dictionary dict;
1848 dict["capabilities"] = capabilities.to_json();
1849 return dict;
1850 }
1851};
1852
1853struct GodotNativeClassInfo {
1854 String name;
1855 const DocData::ClassDoc *class_doc = nullptr;
1856 const ClassDB::ClassInfo *class_info = nullptr;
1857
1858 Dictionary to_json() {
1859 Dictionary dict;
1860 dict["name"] = name;
1861 dict["inherits"] = class_doc->inherits;
1862 return dict;
1863 }
1864};
1865
1866/** Features not included in the standard lsp specifications */
1867struct GodotCapabilities {
1868 /**
1869 * Native class list
1870 */
1871 List<GodotNativeClassInfo> native_classes;
1872
1873 Dictionary to_json() {
1874 Dictionary dict;
1875 Array classes;
1876 for (List<GodotNativeClassInfo>::Element *E = native_classes.front(); E; E = E->next()) {
1877 classes.push_back(E->get().to_json());
1878 }
1879 dict["native_classes"] = classes;
1880 return dict;
1881 }
1882};
1883
1884/** Format BBCode documentation from DocData to markdown */
1885static String marked_documentation(const String &p_bbcode) {
1886 String markdown = p_bbcode.strip_edges();
1887
1888 Vector<String> lines = markdown.split("\n");
1889 bool in_code_block = false;
1890 int code_block_indent = -1;
1891
1892 markdown = "";
1893 for (int i = 0; i < lines.size(); i++) {
1894 String line = lines[i];
1895 int block_start = line.find("[codeblock]");
1896 if (block_start != -1) {
1897 code_block_indent = block_start;
1898 in_code_block = true;
1899 line = "\n";
1900 } else if (in_code_block) {
1901 line = "\t" + line.substr(code_block_indent, line.length());
1902 }
1903
1904 if (in_code_block && line.contains("[/codeblock]")) {
1905 line = "\n";
1906 in_code_block = false;
1907 }
1908
1909 if (!in_code_block) {
1910 line = line.strip_edges();
1911 line = line.replace("[code]", "`");
1912 line = line.replace("[/code]", "`");
1913 line = line.replace("[i]", "*");
1914 line = line.replace("[/i]", "*");
1915 line = line.replace("[b]", "**");
1916 line = line.replace("[/b]", "**");
1917 line = line.replace("[u]", "__");
1918 line = line.replace("[/u]", "__");
1919 line = line.replace("[method ", "`");
1920 line = line.replace("[member ", "`");
1921 line = line.replace("[signal ", "`");
1922 line = line.replace("[enum ", "`");
1923 line = line.replace("[constant ", "`");
1924 line = line.replace("[", "`");
1925 line = line.replace("]", "`");
1926 }
1927
1928 if (!in_code_block && i < lines.size() - 1) {
1929 line += "\n\n";
1930 } else if (i < lines.size() - 1) {
1931 line += "\n";
1932 }
1933 markdown += line;
1934 }
1935 return markdown;
1936}
1937} // namespace lsp
1938
1939#endif // GODOT_LSP_H
1940