Path: blob/master/modules/gdscript/language_server/godot_lsp.h
11353 views
/**************************************************************************/1/* godot_lsp.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "core/doc_data.h"33#include "core/object/class_db.h"34#include "core/templates/list.h"3536namespace LSP {3738typedef String DocumentUri;3940/** Format BBCode documentation from DocData to markdown */41static String marked_documentation(const String &p_bbcode);4243/**44* Text documents are identified using a URI. On the protocol level, URIs are passed as strings.45*/46struct TextDocumentIdentifier {47/**48* The text document's URI.49*/50DocumentUri uri;5152_FORCE_INLINE_ void load(const Dictionary &p_params) {53uri = p_params["uri"];54}5556_FORCE_INLINE_ Dictionary to_json() const {57Dictionary dict;58dict["uri"] = uri;59return dict;60}61};6263/**64* Position in a text document expressed as zero-based line and zero-based character offset.65* A position is between two characters like an ‘insert’ cursor in a editor.66* Special values like for example -1 to denote the end of a line are not supported.67*/68struct Position {69/**70* Line position in a document (zero-based).71*/72int line = 0;7374/**75* Character offset on a line in a document (zero-based). Assuming that the line is76* represented as a string, the `character` value represents the gap between the77* `character` and `character + 1`.78*79* If the character value is greater than the line length it defaults back to the80* line length.81*/82int character = 0;8384_FORCE_INLINE_ bool operator==(const Position &p_other) const {85return line == p_other.line && character == p_other.character;86}8788String to_string() const {89return vformat("(%d,%d)", line, character);90}9192_FORCE_INLINE_ void load(const Dictionary &p_params) {93line = p_params["line"];94character = p_params["character"];95}9697_FORCE_INLINE_ Dictionary to_json() const {98Dictionary dict;99dict["line"] = line;100dict["character"] = character;101return dict;102}103};104105/**106* A range in a text document expressed as (zero-based) start and end positions.107* A range is comparable to a selection in an editor. Therefore the end position is exclusive.108* 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.109*/110struct Range {111/**112* The range's start position.113*/114Position start;115116/**117* The range's end position.118*/119Position end;120121_FORCE_INLINE_ bool operator==(const Range &p_other) const {122return start == p_other.start && end == p_other.end;123}124125bool contains(const Position &p_pos) const {126// Inside line range.127if (start.line <= p_pos.line && p_pos.line <= end.line) {128// If on start line: must come after start char.129bool start_ok = p_pos.line == start.line ? start.character <= p_pos.character : true;130// If on end line: must come before end char.131bool end_ok = p_pos.line == end.line ? p_pos.character <= end.character : true;132return start_ok && end_ok;133} else {134return false;135}136}137138String to_string() const {139return vformat("[%s:%s]", start.to_string(), end.to_string());140}141142_FORCE_INLINE_ void load(const Dictionary &p_params) {143start.load(p_params["start"]);144end.load(p_params["end"]);145}146147_FORCE_INLINE_ Dictionary to_json() const {148Dictionary dict;149dict["start"] = start.to_json();150dict["end"] = end.to_json();151return dict;152}153};154155/**156* Represents a location inside a resource, such as a line inside a text file.157*/158struct Location {159DocumentUri uri;160Range range;161162_FORCE_INLINE_ void load(const Dictionary &p_params) {163uri = p_params["uri"];164range.load(p_params["range"]);165}166167_FORCE_INLINE_ Dictionary to_json() const {168Dictionary dict;169dict["uri"] = uri;170dict["range"] = range.to_json();171return dict;172}173};174175/**176* Represents a link between a source and a target location.177*/178struct LocationLink {179/**180* Span of the origin of this link.181*182* Used as the underlined span for mouse interaction. Defaults to the word range at183* the mouse position.184*/185Range *originSelectionRange = nullptr;186187/**188* The target resource identifier of this link.189*/190String targetUri;191192/**193* The full target range of this link. If the target for example is a symbol then target range is the194* range enclosing this symbol not including leading/trailing whitespace but everything else195* like comments. This information is typically used to highlight the range in the editor.196*/197Range targetRange;198199/**200* The range that should be selected and revealed when this link is being followed, e.g the name of a function.201* Must be contained by the `targetRange`. See also `DocumentSymbol#range`202*/203Range targetSelectionRange;204};205206/**207* A parameter literal used in requests to pass a text document and a position inside that document.208*/209struct TextDocumentPositionParams {210/**211* The text document.212*/213TextDocumentIdentifier textDocument;214215/**216* The position inside the text document.217*/218Position position;219220_FORCE_INLINE_ void load(const Dictionary &p_params) {221textDocument.load(p_params["textDocument"]);222position.load(p_params["position"]);223}224225_FORCE_INLINE_ Dictionary to_json() const {226Dictionary dict;227dict["textDocument"] = textDocument.to_json();228dict["position"] = position.to_json();229return dict;230}231};232233struct ReferenceContext {234/**235* Include the declaration of the current symbol.236*/237bool includeDeclaration = false;238};239240struct ShowMessageParams {241/**242* The message type. See {@link MessageType}.243*/244int type;245246/**247* The actual message.248*/249String message;250251_FORCE_INLINE_ Dictionary to_json() const {252Dictionary dict;253dict["type"] = type;254dict["message"] = message;255return dict;256}257};258259struct ReferenceParams : TextDocumentPositionParams {260ReferenceContext context;261};262263struct DocumentLinkParams {264/**265* The document to provide document links for.266*/267TextDocumentIdentifier textDocument;268269_FORCE_INLINE_ void load(const Dictionary &p_params) {270textDocument.load(p_params["textDocument"]);271}272};273274/**275* A document link is a range in a text document that links to an internal or external resource, like another276* text document or a web site.277*/278struct DocumentLink {279/**280* The range this link applies to.281*/282Range range;283284/**285* The uri this link points to. If missing a resolve request is sent later.286*/287DocumentUri target;288289Dictionary to_json() const {290Dictionary dict;291dict["range"] = range.to_json();292dict["target"] = target;293return dict;294}295};296297/**298* A textual edit applicable to a text document.299*/300struct TextEdit {301/**302* The range of the text document to be manipulated. To insert303* text into a document create a range where start === end.304*/305Range range;306307/**308* The string to be inserted. For delete operations use an309* empty string.310*/311String newText;312};313314/**315* The edits to be applied.316*/317struct WorkspaceEdit {318/**319* Holds changes to existing resources.320*/321HashMap<String, Vector<TextEdit>> changes;322323_FORCE_INLINE_ void add_edit(const String &uri, const TextEdit &edit) {324if (changes.has(uri)) {325changes[uri].push_back(edit);326} else {327Vector<TextEdit> edits;328edits.push_back(edit);329changes[uri] = edits;330}331}332333_FORCE_INLINE_ Dictionary to_json() const {334Dictionary dict;335336Dictionary out_changes;337for (const KeyValue<String, Vector<TextEdit>> &E : changes) {338Array edits;339for (int i = 0; i < E.value.size(); ++i) {340Dictionary text_edit;341text_edit["range"] = E.value[i].range.to_json();342text_edit["newText"] = E.value[i].newText;343edits.push_back(text_edit);344}345out_changes[E.key] = edits;346}347dict["changes"] = out_changes;348349return dict;350}351352_FORCE_INLINE_ void add_change(const String &uri, const int &line, const int &start_character, const int &end_character, const String &new_text) {353TextEdit new_edit;354new_edit.newText = new_text;355new_edit.range.start.line = line;356new_edit.range.start.character = start_character;357new_edit.range.end.line = line;358new_edit.range.end.character = end_character;359360if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) {361E->value.push_back(new_edit);362} else {363Vector<TextEdit> edit_list;364edit_list.push_back(new_edit);365changes.insert(uri, edit_list);366}367}368};369370/**371* Represents a reference to a command.372* Provides a title which will be used to represent a command in the UI.373* Commands are identified by a string identifier.374* The recommended way to handle commands is to implement their execution on the server side if the client and server provides the corresponding capabilities.375* Alternatively the tool extension code could handle the command. The protocol currently doesn’t specify a set of well-known commands.376*/377struct Command {378/**379* Title of the command, like `save`.380*/381String title;382/**383* The identifier of the actual command handler.384*/385String command;386/**387* Arguments that the command handler should be388* invoked with.389*/390Array arguments;391392Dictionary to_json() const {393Dictionary dict;394dict["title"] = title;395dict["command"] = command;396if (arguments.size()) {397dict["arguments"] = arguments;398}399return dict;400}401};402403// Use namespace instead of enumeration to follow the LSP specifications.404// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not.405406namespace TextDocumentSyncKind {407/**408* Documents should not be synced at all.409*/410static const int None = 0;411412/**413* Documents are synced by always sending the full content414* of the document.415*/416static const int Full = 1;417418/**419* Documents are synced by sending the full content on open.420* After that only incremental updates to the document are421* send.422*/423static const int Incremental = 2;424}; // namespace TextDocumentSyncKind425426namespace MessageType {427/**428* An error message.429*/430static const int Error = 1;431/**432* A warning message.433*/434static const int Warning = 2;435/**436* An information message.437*/438static const int Info = 3;439/**440* A log message.441*/442static const int Log = 4;443}; // namespace MessageType444445/**446* Completion options.447*/448struct CompletionOptions {449/**450* The server provides support to resolve additional451* information for a completion item.452*/453bool resolveProvider = true;454455/**456* The characters that trigger completion automatically.457*/458Vector<String> triggerCharacters;459460CompletionOptions() {461triggerCharacters.push_back(".");462triggerCharacters.push_back("$");463triggerCharacters.push_back("'");464triggerCharacters.push_back("\"");465}466467Dictionary to_json() const {468Dictionary dict;469dict["resolveProvider"] = resolveProvider;470dict["triggerCharacters"] = triggerCharacters;471return dict;472}473};474475/**476* Signature help options.477*/478struct SignatureHelpOptions {479/**480* The characters that trigger signature help481* automatically.482*/483Vector<String> triggerCharacters;484485Dictionary to_json() {486Dictionary dict;487dict["triggerCharacters"] = triggerCharacters;488return dict;489}490};491492/**493* Code Lens options.494*/495struct CodeLensOptions {496/**497* Code lens has a resolve provider as well.498*/499bool resolveProvider = false;500501Dictionary to_json() {502Dictionary dict;503dict["resolveProvider"] = resolveProvider;504return dict;505}506};507508/**509* Rename options510*/511struct RenameOptions {512/**513* Renames should be checked and tested before being executed.514*/515bool prepareProvider = true;516517Dictionary to_json() {518Dictionary dict;519dict["prepareProvider"] = prepareProvider;520return dict;521}522};523524/**525* Document link options.526*/527struct DocumentLinkOptions {528/**529* Document links have a resolve provider as well.530*/531bool resolveProvider = false;532533Dictionary to_json() {534Dictionary dict;535dict["resolveProvider"] = resolveProvider;536return dict;537}538};539540/**541* Execute command options.542*/543struct ExecuteCommandOptions {544/**545* The commands to be executed on the server546*/547Vector<String> commands;548549Dictionary to_json() {550Dictionary dict;551dict["commands"] = commands;552return dict;553}554};555556/**557* Save options.558*/559struct SaveOptions {560/**561* The client is supposed to include the content on save.562*/563bool includeText = true;564565Dictionary to_json() {566Dictionary dict;567dict["includeText"] = includeText;568return dict;569}570};571572/**573* Color provider options.574*/575struct ColorProviderOptions {576Dictionary to_json() {577return Dictionary();578}579};580581/**582* Folding range provider options.583*/584struct FoldingRangeProviderOptions {585Dictionary to_json() {586return Dictionary();587}588};589590struct TextDocumentSyncOptions {591/**592* Open and close notifications are sent to the server. If omitted open close notification should not593* be sent.594*/595bool openClose = true;596597/**598* Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full599* and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None.600*/601int change = TextDocumentSyncKind::Full;602603/**604* If present will save notifications are sent to the server. If omitted the notification should not be605* sent.606*/607bool willSave = false;608609/**610* If present will save wait until requests are sent to the server. If omitted the request should not be611* sent.612*/613bool willSaveWaitUntil = true;614615/**616* If present save notifications are sent to the server. If omitted the notification should not be617* sent.618*/619SaveOptions save;620621Dictionary to_json() {622Dictionary dict;623dict["willSaveWaitUntil"] = willSaveWaitUntil;624dict["willSave"] = willSave;625dict["openClose"] = openClose;626dict["change"] = change;627dict["save"] = save.to_json();628return dict;629}630};631632/**633* Static registration options to be returned in the initialize request.634*/635struct StaticRegistrationOptions {636/**637* The id used to register the request. The id can be used to deregister638* the request again. See also Registration#id.639*/640String id;641};642643/**644* Format document on type options.645*/646struct DocumentOnTypeFormattingOptions {647/**648* A character on which formatting should be triggered, like `}`.649*/650String firstTriggerCharacter;651652/**653* More trigger characters.654*/655Vector<String> moreTriggerCharacter;656657Dictionary to_json() {658Dictionary dict;659dict["firstTriggerCharacter"] = firstTriggerCharacter;660dict["moreTriggerCharacter"] = moreTriggerCharacter;661return dict;662}663};664665struct TextDocumentItem {666/**667* The text document's URI.668*/669DocumentUri uri;670671/**672* The text document's language identifier.673*/674String languageId;675676/**677* The version number of this document (it will increase after each678* change, including undo/redo).679*/680int version = 0;681682/**683* The content of the opened text document.684*/685String text;686687void load(const Dictionary &p_dict) {688uri = p_dict["uri"];689languageId = p_dict["languageId"];690version = p_dict["version"];691text = p_dict["text"];692}693694Dictionary to_json() const {695Dictionary dict;696dict["uri"] = uri;697dict["languageId"] = languageId;698dict["version"] = version;699dict["text"] = text;700return dict;701}702};703704/**705* An event describing a change to a text document. If range and rangeLength are omitted706* the new text is considered to be the full content of the document.707*/708struct TextDocumentContentChangeEvent {709/**710* The range of the document that changed.711*/712Range range;713714/**715* The length of the range that got replaced.716*/717int rangeLength = 0;718719/**720* The new text of the range/document.721*/722String text;723724void load(const Dictionary &p_params) {725text = p_params["text"];726rangeLength = p_params["rangeLength"];727range.load(p_params["range"]);728}729};730731// Use namespace instead of enumeration to follow the LSP specifications732namespace DiagnosticSeverity {733/**734* Reports an error.735*/736static const int Error = 1;737/**738* Reports a warning.739*/740static const int Warning = 2;741/**742* Reports an information.743*/744static const int Information = 3;745/**746* Reports a hint.747*/748static const int Hint = 4;749}; // namespace DiagnosticSeverity750751/**752* Represents a related message and source code location for a diagnostic. This should be753* used to point to code locations that cause or related to a diagnostics, e.g when duplicating754* a symbol in a scope.755*/756struct DiagnosticRelatedInformation {757/**758* The location of this related diagnostic information.759*/760Location location;761762/**763* The message of this related diagnostic information.764*/765String message;766767Dictionary to_json() const {768Dictionary dict;769dict["location"] = location.to_json();770dict["message"] = message;771return dict;772}773};774775/**776* Represents a diagnostic, such as a compiler error or warning.777* Diagnostic objects are only valid in the scope of a resource.778*/779struct Diagnostic {780/**781* The range at which the message applies.782*/783Range range;784785/**786* The diagnostic's severity. Can be omitted. If omitted it is up to the787* client to interpret diagnostics as error, warning, info or hint.788*/789int severity = 0;790791/**792* The diagnostic's code, which might appear in the user interface.793*/794int code = 0;795796/**797* A human-readable string describing the source of this798* diagnostic, e.g. 'typescript' or 'super lint'.799*/800String source;801802/**803* The diagnostic's message.804*/805String message;806807/**808* An array of related diagnostic information, e.g. when symbol-names within809* a scope collide all definitions can be marked via this property.810*/811Vector<DiagnosticRelatedInformation> relatedInformation;812813Dictionary to_json() const {814Dictionary dict;815dict["range"] = range.to_json();816dict["code"] = code;817dict["severity"] = severity;818dict["message"] = message;819dict["source"] = source;820if (!relatedInformation.is_empty()) {821Array arr;822arr.resize(relatedInformation.size());823for (int i = 0; i < relatedInformation.size(); i++) {824arr[i] = relatedInformation[i].to_json();825}826dict["relatedInformation"] = arr;827}828return dict;829}830};831832// Use namespace instead of enumeration to follow the LSP specifications833/**834* Describes the content type that a client supports in various835* result literals like `Hover`, `ParameterInfo` or `CompletionItem`.836*837* Please note that `MarkupKinds` must not start with a `$`. This kinds838* are reserved for internal usage.839*/840namespace MarkupKind {841static const String PlainText = "plaintext";842static const String Markdown = "markdown";843}; // namespace MarkupKind844845/**846* A `MarkupContent` literal represents a string value which content is interpreted base on its847* kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds.848*849* If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues.850* See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting851*852* Here is an example how such a string can be constructed using JavaScript / TypeScript:853* ```typescript854* let markdown: MarkdownContent = {855* kind: MarkupKind.Markdown,856* value: [857* '# Header',858* 'Some text',859* '```typescript',860* 'someCode();',861* '```'862* ].join('\n')863* };864* ```865*866* *Please Note* that clients might sanitize the return markdown. A client could decide to867* remove HTML from the markdown to avoid script execution.868*/869struct MarkupContent {870/**871* The type of the Markup.872*/873String kind;874875/**876* The content itself.877*/878String value;879880MarkupContent() {881kind = MarkupKind::Markdown;882}883884MarkupContent(const String &p_value) {885value = p_value;886kind = MarkupKind::Markdown;887}888889Dictionary to_json() const {890Dictionary dict;891dict["kind"] = kind;892dict["value"] = value;893return dict;894}895};896897// Use namespace instead of enumeration to follow the LSP specifications898// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not.899// And here C++ compilers are unhappy with our enumeration name like `Color`, `File`, `RefCounted` etc.900/**901* The kind of a completion entry.902*/903namespace CompletionItemKind {904static const int Text = 1;905static const int Method = 2;906static const int Function = 3;907static const int Constructor = 4;908static const int Field = 5;909static const int Variable = 6;910static const int Class = 7;911static const int Interface = 8;912static const int Module = 9;913static const int Property = 10;914static const int Unit = 11;915static const int Value = 12;916static const int Enum = 13;917static const int Keyword = 14;918static const int Snippet = 15;919static const int Color = 16;920static const int File = 17;921static const int RefCounted = 18;922static const int Folder = 19;923static const int EnumMember = 20;924static const int Constant = 21;925static const int Struct = 22;926static const int Event = 23;927static const int Operator = 24;928static const int TypeParameter = 25;929}; // namespace CompletionItemKind930931// Use namespace instead of enumeration to follow the LSP specifications.932/**933* Defines whether the insert text in a completion item should be interpreted as934* plain text or a snippet.935*/936namespace InsertTextFormat {937/**938* The primary text to be inserted is treated as a plain string.939*/940static const int PlainText = 1;941942/**943* The primary text to be inserted is treated as a snippet.944*945* A snippet can define tab stops and placeholders with `$1`, `$2`946* and `${3:foo}`. `$0` defines the final tab stop, it defaults to947* the end of the snippet. Placeholders with equal identifiers are linked,948* that is typing in one will update others too.949*/950static const int Snippet = 2;951}; // namespace InsertTextFormat952953struct CompletionItem {954/**955* The label of this completion item. By default956* also the text that is inserted when selecting957* this completion.958*/959String label;960961/**962* The kind of this completion item. Based of the kind963* an icon is chosen by the editor. The standardized set964* of available values is defined in `CompletionItemKind`.965*/966int kind = 0;967968/**969* A human-readable string with additional information970* about this item, like type or symbol information.971*/972String detail;973974/**975* A human-readable string that represents a doc-comment.976*/977MarkupContent documentation;978979/**980* Indicates if this item is deprecated.981*/982bool deprecated = false;983984/**985* Select this item when showing.986*987* *Note* that only one completion item can be selected and that the988* tool / client decides which item that is. The rule is that the *first*989* item of those that match best is selected.990*/991bool preselect = false;992993/**994* A string that should be used when comparing this item995* with other items. When omitted the label is used996* as the filter text for this item.997*/998String sortText;9991000/**1001* A string that should be used when filtering a set of1002* completion items. When omitted the label is used as the1003* filter text for this item.1004*/1005String filterText;10061007/**1008* A string that should be inserted into a document when selecting1009* this completion. When omitted the label is used as the insert text1010* for this item.1011*1012* The `insertText` is subject to interpretation by the client side.1013* Some tools might not take the string literally. For example1014* VS Code when code complete is requested in this example1015* `con<cursor position>` and a completion item with an `insertText` of1016* `console` is provided it will only insert `sole`. Therefore it is1017* recommended to use `textEdit` instead since it avoids additional client1018* side interpretation.1019*/1020String insertText;10211022/**1023* The format of the insert text. The format applies to both the `insertText` property1024* and the `newText` property of a provided `textEdit`.1025*/1026int insertTextFormat = 0;10271028/**1029* An edit which is applied to a document when selecting this completion. When an edit is provided the value of1030* `insertText` is ignored.1031*1032* *Note:* The range of the edit must be a single line range and it must contain the position at which completion1033* has been requested.1034*/1035TextEdit textEdit;10361037/**1038* An optional array of additional text edits that are applied when1039* selecting this completion. Edits must not overlap (including the same insert position)1040* with the main edit nor with themselves.1041*1042* Additional text edits should be used to change text unrelated to the current cursor position1043* (for example adding an import statement at the top of the file if the completion item will1044* insert an unqualified type).1045*/1046Vector<TextEdit> additionalTextEdits;10471048/**1049* An optional set of characters that when pressed while this completion is active will accept it first and1050* then type that character. *Note* that all commit characters should have `length=1` and that superfluous1051* characters will be ignored.1052*/1053Vector<String> commitCharacters;10541055/**1056* An optional command that is executed *after* inserting this completion. *Note* that1057* additional modifications to the current document should be described with the1058* additionalTextEdits-property.1059*/1060Command command;10611062/**1063* A data entry field that is preserved on a completion item between1064* a completion and a completion resolve request.1065*/1066Variant data;10671068_FORCE_INLINE_ Dictionary to_json(bool resolved = false) const {1069Dictionary dict;1070dict["label"] = label;1071dict["kind"] = kind;1072dict["data"] = data;1073if (!insertText.is_empty()) {1074dict["insertText"] = insertText;1075}1076if (resolved) {1077dict["detail"] = detail;1078dict["documentation"] = documentation.to_json();1079dict["deprecated"] = deprecated;1080dict["preselect"] = preselect;1081if (!sortText.is_empty()) {1082dict["sortText"] = sortText;1083}1084if (!filterText.is_empty()) {1085dict["filterText"] = filterText;1086}1087if (commitCharacters.size()) {1088dict["commitCharacters"] = commitCharacters;1089}1090if (!command.command.is_empty()) {1091dict["command"] = command.to_json();1092}1093}1094return dict;1095}10961097void load(const Dictionary &p_dict) {1098if (p_dict.has("label")) {1099label = p_dict["label"];1100}1101if (p_dict.has("kind")) {1102kind = p_dict["kind"];1103}1104if (p_dict.has("detail")) {1105detail = p_dict["detail"];1106}1107if (p_dict.has("documentation")) {1108Variant doc = p_dict["documentation"];1109if (doc.is_string()) {1110documentation.value = doc;1111} else if (doc.get_type() == Variant::DICTIONARY) {1112Dictionary v = doc;1113documentation.value = v["value"];1114}1115}1116if (p_dict.has("deprecated")) {1117deprecated = p_dict["deprecated"];1118}1119if (p_dict.has("preselect")) {1120preselect = p_dict["preselect"];1121}1122if (p_dict.has("sortText")) {1123sortText = p_dict["sortText"];1124}1125if (p_dict.has("filterText")) {1126filterText = p_dict["filterText"];1127}1128if (p_dict.has("insertText")) {1129insertText = p_dict["insertText"];1130}1131if (p_dict.has("data")) {1132data = p_dict["data"];1133}1134}1135};11361137/**1138* Represents a collection of [completion items](#CompletionItem) to be presented1139* in the editor.1140*/1141struct CompletionList {1142/**1143* This list it not complete. Further typing should result in recomputing1144* this list.1145*/1146bool isIncomplete = false;11471148/**1149* The completion items.1150*/1151Vector<CompletionItem> items;1152};11531154// Use namespace instead of enumeration to follow the LSP specifications1155// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not1156// And here C++ compilers are unhappy with our enumeration name like `String`, `Array`, `Object` etc1157/**1158* A symbol kind.1159*/1160namespace SymbolKind {1161static const int File = 1;1162static const int Module = 2;1163static const int Namespace = 3;1164static const int Package = 4;1165static const int Class = 5;1166static const int Method = 6;1167static const int Property = 7;1168static const int Field = 8;1169static const int Constructor = 9;1170static const int Enum = 10;1171static const int Interface = 11;1172static const int Function = 12;1173static const int Variable = 13;1174static const int Constant = 14;1175static const int String = 15;1176static const int Number = 16;1177static const int Boolean = 17;1178static const int Array = 18;1179static const int Object = 19;1180static const int Key = 20;1181static const int Null = 21;1182static const int EnumMember = 22;1183static const int Struct = 23;1184static const int Event = 24;1185static const int Operator = 25;1186static const int TypeParameter = 26;1187}; // namespace SymbolKind11881189/**1190* Represents programming constructs like variables, classes, interfaces etc. that appear in a document. Document symbols can be1191* hierarchical and they have two ranges: one that encloses its definition and one that points to its most interesting range,1192* e.g. the range of an identifier.1193*/1194struct DocumentSymbol {1195/**1196* The name of this symbol. Will be displayed in the user interface and therefore must not be1197* an empty string or a string only consisting of white spaces.1198*/1199String name;12001201/**1202* More detail for this symbol, e.g the signature of a function.1203*/1204String detail;12051206/**1207* Documentation for this symbol.1208*/1209String documentation;12101211/**1212* Class name for the native symbols.1213*/1214String native_class;12151216/**1217* The kind of this symbol.1218*/1219int kind = SymbolKind::File;12201221/**1222* Indicates if this symbol is deprecated.1223*/1224bool deprecated = false;12251226/**1227* If `true`: Symbol is local to script and cannot be accessed somewhere else.1228*1229* For example: local variable inside a `func`.1230*/1231bool local = false;12321233/**1234* The range enclosing this symbol not including leading/trailing whitespace but everything else1235* like comments. This information is typically used to determine if the clients cursor is1236* inside the symbol to reveal in the symbol in the UI.1237*/1238Range range;12391240/**1241* The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.1242* Must be contained by the `range`.1243*/1244Range selectionRange;12451246DocumentUri uri;1247String script_path;12481249/**1250* Children of this symbol, e.g. properties of a class.1251*/1252Vector<DocumentSymbol> children;12531254Dictionary to_json(bool with_doc = false) const {1255Dictionary dict;1256dict["name"] = name;1257dict["detail"] = detail;1258dict["kind"] = kind;1259dict["deprecated"] = deprecated;1260dict["range"] = range.to_json();1261dict["selectionRange"] = selectionRange.to_json();1262if (with_doc) {1263dict["documentation"] = documentation;1264dict["native_class"] = native_class;1265}1266if (!children.is_empty()) {1267Array arr;1268for (int i = 0; i < children.size(); i++) {1269if (children[i].local) {1270continue;1271}1272arr.push_back(children[i].to_json(with_doc));1273}1274if (!children.is_empty()) {1275dict["children"] = arr;1276}1277}1278return dict;1279}12801281_FORCE_INLINE_ MarkupContent render() const {1282MarkupContent markdown;1283if (detail.length()) {1284markdown.value = "\t" + detail + "\n\n";1285}1286if (documentation.length()) {1287markdown.value += marked_documentation(documentation) + "\n\n";1288}1289if (script_path.length()) {1290markdown.value += "Defined in [" + script_path + "](" + uri + ")";1291}1292return markdown;1293}12941295_FORCE_INLINE_ CompletionItem make_completion_item(bool resolved = false) const {1296LSP::CompletionItem item;1297item.label = name;12981299if (resolved) {1300item.documentation = render();1301}13021303switch (kind) {1304case LSP::SymbolKind::Enum:1305item.kind = LSP::CompletionItemKind::Enum;1306break;1307case LSP::SymbolKind::Class:1308item.kind = LSP::CompletionItemKind::Class;1309break;1310case LSP::SymbolKind::Property:1311item.kind = LSP::CompletionItemKind::Property;1312break;1313case LSP::SymbolKind::Method:1314case LSP::SymbolKind::Function:1315item.kind = LSP::CompletionItemKind::Method;1316break;1317case LSP::SymbolKind::Event:1318item.kind = LSP::CompletionItemKind::Event;1319break;1320case LSP::SymbolKind::Constant:1321item.kind = LSP::CompletionItemKind::Constant;1322break;1323case LSP::SymbolKind::Variable:1324item.kind = LSP::CompletionItemKind::Variable;1325break;1326case LSP::SymbolKind::File:1327item.kind = LSP::CompletionItemKind::File;1328break;1329default:1330item.kind = LSP::CompletionItemKind::Text;1331break;1332}13331334return item;1335}1336};13371338struct ApplyWorkspaceEditParams {1339WorkspaceEdit edit;13401341Dictionary to_json() {1342Dictionary dict;13431344dict["edit"] = edit.to_json();13451346return dict;1347}1348};13491350struct NativeSymbolInspectParams {1351String native_class;1352String symbol_name;13531354void load(const Dictionary &p_params) {1355native_class = p_params["native_class"];1356symbol_name = p_params["symbol_name"];1357}1358};13591360/**1361* Enum of known range kinds1362*/1363namespace FoldingRangeKind {1364/**1365* Folding range for a comment1366*/1367static const String Comment = "comment";1368/**1369* Folding range for a imports or includes1370*/1371static const String Imports = "imports";1372/**1373* Folding range for a region (e.g. `#region`)1374*/1375static const String Region = "region";1376} // namespace FoldingRangeKind13771378/**1379* Represents a folding range.1380*/1381struct FoldingRange {1382/**1383* The zero-based line number from where the folded range starts.1384*/1385int startLine = 0;13861387/**1388* The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.1389*/1390int startCharacter = 0;13911392/**1393* The zero-based line number where the folded range ends.1394*/1395int endLine = 0;13961397/**1398* The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.1399*/1400int endCharacter = 0;14011402/**1403* Describes the kind of the folding range such as `comment' or 'region'. The kind1404* is used to categorize folding ranges and used by commands like 'Fold all comments'. See1405* [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.1406*/1407String kind = FoldingRangeKind::Region;14081409_FORCE_INLINE_ Dictionary to_json() const {1410Dictionary dict;1411dict["startLine"] = startLine;1412dict["startCharacter"] = startCharacter;1413dict["endLine"] = endLine;1414dict["endCharacter"] = endCharacter;1415return dict;1416}1417};14181419// Use namespace instead of enumeration to follow the LSP specifications1420/**1421* How a completion was triggered1422*/1423namespace CompletionTriggerKind {1424/**1425* Completion was triggered by typing an identifier (24x7 code1426* complete), manual invocation (e.g Ctrl+Space) or via API.1427*/1428static const int Invoked = 1;14291430/**1431* Completion was triggered by a trigger character specified by1432* the `triggerCharacters` properties of the `CompletionRegistrationOptions`.1433*/1434static const int TriggerCharacter = 2;14351436/**1437* Completion was re-triggered as the current completion list is incomplete.1438*/1439static const int TriggerForIncompleteCompletions = 3;1440} // namespace CompletionTriggerKind14411442/**1443* Contains additional information about the context in which a completion request is triggered.1444*/1445struct CompletionContext {1446/**1447* How the completion was triggered.1448*/1449int triggerKind = CompletionTriggerKind::TriggerCharacter;14501451/**1452* The trigger character (a single character) that has trigger code complete.1453* Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`1454*/1455String triggerCharacter;14561457void load(const Dictionary &p_params) {1458triggerKind = int(p_params["triggerKind"]);1459triggerCharacter = p_params["triggerCharacter"];1460}1461};14621463struct CompletionParams : public TextDocumentPositionParams {1464/**1465* The completion context. This is only available if the client specifies1466* to send this using `ClientCapabilities.textDocument.completion.contextSupport === true`1467*/1468CompletionContext context;14691470void load(const Dictionary &p_params) {1471TextDocumentPositionParams::load(p_params);1472context.load(p_params["context"]);1473}14741475Dictionary to_json() {1476Dictionary ctx;1477ctx["triggerCharacter"] = context.triggerCharacter;1478ctx["triggerKind"] = context.triggerKind;14791480Dictionary dict;1481dict = TextDocumentPositionParams::to_json();1482dict["context"] = ctx;1483return dict;1484}1485};14861487/**1488* The result of a hover request.1489*/1490struct Hover {1491/**1492* The hover's content1493*/1494MarkupContent contents;14951496/**1497* An optional range is a range inside a text document1498* that is used to visualize a hover, e.g. by changing the background color.1499*/1500Range range;15011502_FORCE_INLINE_ Dictionary to_json() const {1503Dictionary dict;1504dict["range"] = range.to_json();1505dict["contents"] = contents.to_json();1506return dict;1507}1508};15091510/**1511* Represents a parameter of a callable-signature. A parameter can1512* have a label and a doc-comment.1513*/1514struct ParameterInformation {1515/**1516* The label of this parameter information.1517*1518* Either a string or an inclusive start and exclusive end offsets within its containing1519* signature label. (see SignatureInformation.label). The offsets are based on a UTF-161520* string representation as `Position` and `Range` does.1521*1522* *Note*: a label of type string should be a substring of its containing signature label.1523* Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.1524*/1525String label;15261527/**1528* The human-readable doc-comment of this parameter. Will be shown1529* in the UI but can be omitted.1530*/1531MarkupContent documentation;15321533Dictionary to_json() const {1534Dictionary dict;1535dict["label"] = label;1536dict["documentation"] = documentation.to_json();1537return dict;1538}1539};15401541/**1542* Represents the signature of something callable. A signature1543* can have a label, like a function-name, a doc-comment, and1544* a set of parameters.1545*/1546struct SignatureInformation {1547/**1548* The label of this signature. Will be shown in1549* the UI.1550*/1551String label;15521553/**1554* The human-readable doc-comment of this signature. Will be shown1555* in the UI but can be omitted.1556*/1557MarkupContent documentation;15581559/**1560* The parameters of this signature.1561*/1562Vector<ParameterInformation> parameters;15631564Dictionary to_json() const {1565Dictionary dict;1566dict["label"] = label;1567dict["documentation"] = documentation.to_json();1568Array args;1569for (int i = 0; i < parameters.size(); i++) {1570args.push_back(parameters[i].to_json());1571}1572dict["parameters"] = args;1573return dict;1574}1575};15761577/**1578* Signature help represents the signature of something1579* callable. There can be multiple signature but only one1580* active and only one active parameter.1581*/1582struct SignatureHelp {1583/**1584* One or more signatures.1585*/1586Vector<SignatureInformation> signatures;15871588/**1589* The active signature. If omitted or the value lies outside the1590* range of `signatures` the value defaults to zero or is ignored if1591* `signatures.length === 0`. Whenever possible implementers should1592* make an active decision about the active signature and shouldn't1593* rely on a default value.1594* In future version of the protocol this property might become1595* mandatory to better express this.1596*/1597int activeSignature = 0;15981599/**1600* The active parameter of the active signature. If omitted or the value1601* lies outside the range of `signatures[activeSignature].parameters`1602* defaults to 0 if the active signature has parameters. If1603* the active signature has no parameters it is ignored.1604* In future version of the protocol this property might become1605* mandatory to better express the active parameter if the1606* active signature does have any.1607*/1608int activeParameter = 0;16091610Dictionary to_json() const {1611Dictionary dict;1612Array sigs;1613for (int i = 0; i < signatures.size(); i++) {1614sigs.push_back(signatures[i].to_json());1615}1616dict["signatures"] = sigs;1617dict["activeSignature"] = activeSignature;1618dict["activeParameter"] = activeParameter;1619return dict;1620}1621};16221623/**1624* A pattern to describe in which file operation requests or notifications1625* the server is interested in.1626*/1627struct FileOperationPattern {1628/**1629* The glob pattern to match.1630*/1631String glob = "**/*.gd";16321633/**1634* Whether to match `file`s or `folder`s with this pattern.1635*1636* Matches both if undefined.1637*/1638String matches = "file";16391640Dictionary to_json() const {1641Dictionary dict;16421643dict["glob"] = glob;1644dict["matches"] = matches;16451646return dict;1647}1648};16491650/**1651* A filter to describe in which file operation requests or notifications1652* the server is interested in.1653*/1654struct FileOperationFilter {1655/**1656* The actual file operation pattern.1657*/1658FileOperationPattern pattern;16591660Dictionary to_json() const {1661Dictionary dict;16621663dict["pattern"] = pattern.to_json();16641665return dict;1666}1667};16681669/**1670* The options to register for file operations.1671*/1672struct FileOperationRegistrationOptions {1673/**1674* The actual filters.1675*/1676Vector<FileOperationFilter> filters;16771678FileOperationRegistrationOptions() {1679filters.push_back(FileOperationFilter());1680}16811682Dictionary to_json() const {1683Dictionary dict;16841685Array filts;1686for (int i = 0; i < filters.size(); i++) {1687filts.push_back(filters[i].to_json());1688}1689dict["filters"] = filts;16901691return dict;1692}1693};16941695/**1696* The server is interested in file notifications/requests.1697*/1698struct FileOperations {1699/**1700* The server is interested in receiving didDeleteFiles file notifications.1701*/1702FileOperationRegistrationOptions didDelete;17031704Dictionary to_json() const {1705Dictionary dict;17061707dict["didDelete"] = didDelete.to_json();17081709return dict;1710}1711};17121713/**1714* Workspace specific server capabilities1715*/1716struct Workspace {1717/**1718* The server is interested in file notifications/requests.1719*/1720FileOperations fileOperations;17211722Dictionary to_json() const {1723Dictionary dict;17241725dict["fileOperations"] = fileOperations.to_json();17261727return dict;1728}1729};17301731struct ServerCapabilities {1732/**1733* Defines how text documents are synced. Is either a detailed structure defining each notification or1734* for backwards compatibility the TextDocumentSyncKind number. If omitted it defaults to `TextDocumentSyncKind.None`.1735*/1736TextDocumentSyncOptions textDocumentSync;17371738/**1739* The server provides hover support.1740*/1741bool hoverProvider = true;17421743/**1744* The server provides completion support.1745*/1746CompletionOptions completionProvider;17471748/**1749* The server provides signature help support.1750*/1751SignatureHelpOptions signatureHelpProvider;17521753/**1754* The server provides goto definition support.1755*/1756bool definitionProvider = true;17571758/**1759* The server provides Goto Type Definition support.1760*1761* Since 3.6.01762*/1763bool typeDefinitionProvider = false;17641765/**1766* The server provides Goto Implementation support.1767*1768* Since 3.6.01769*/1770bool implementationProvider = false;17711772/**1773* The server provides find references support.1774*/1775bool referencesProvider = true;17761777/**1778* The server provides document highlight support.1779*/1780bool documentHighlightProvider = false;17811782/**1783* The server provides document symbol support.1784*/1785bool documentSymbolProvider = true;17861787/**1788* The server provides workspace symbol support.1789*/1790bool workspaceSymbolProvider = false;17911792/**1793* The server supports workspace folder.1794*/1795Workspace workspace;17961797/**1798* The server provides code actions. The `CodeActionOptions` return type is only1799* valid if the client signals code action literal support via the property1800* `textDocument.codeAction.codeActionLiteralSupport`.1801*/1802bool codeActionProvider = false;18031804/**1805* The server provides code lens.1806*/1807CodeLensOptions codeLensProvider;18081809/**1810* The server provides document formatting.1811*/1812bool documentFormattingProvider = false;18131814/**1815* The server provides document range formatting.1816*/1817bool documentRangeFormattingProvider = false;18181819/**1820* The server provides document formatting on typing.1821*/1822DocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;18231824/**1825* The server provides rename support. RenameOptions may only be1826* specified if the client states that it supports1827* `prepareSupport` in its initial `initialize` request.1828*/1829RenameOptions renameProvider;18301831/**1832* The server provides document link support.1833*/1834DocumentLinkOptions documentLinkProvider;18351836/**1837* The server provides color provider support.1838*1839* Since 3.6.01840*/1841ColorProviderOptions colorProvider;18421843/**1844* The server provides folding provider support.1845*1846* Since 3.10.01847*/1848FoldingRangeProviderOptions foldingRangeProvider;18491850/**1851* The server provides go to declaration support.1852*1853* Since 3.14.01854*/1855bool declarationProvider = true;18561857/**1858* The server provides execute command support.1859*/1860ExecuteCommandOptions executeCommandProvider;18611862_FORCE_INLINE_ Dictionary to_json() {1863Dictionary dict;1864dict["textDocumentSync"] = textDocumentSync.to_json();1865dict["completionProvider"] = completionProvider.to_json();1866signatureHelpProvider.triggerCharacters.push_back(",");1867signatureHelpProvider.triggerCharacters.push_back("(");1868dict["signatureHelpProvider"] = signatureHelpProvider.to_json();1869//dict["codeLensProvider"] = codeLensProvider.to_json();1870dict["documentOnTypeFormattingProvider"] = documentOnTypeFormattingProvider.to_json();1871dict["renameProvider"] = renameProvider.to_json();1872dict["documentLinkProvider"] = documentLinkProvider.to_json();1873dict["colorProvider"] = false; // colorProvider.to_json();1874dict["foldingRangeProvider"] = false; //foldingRangeProvider.to_json();1875dict["executeCommandProvider"] = executeCommandProvider.to_json();1876dict["hoverProvider"] = hoverProvider;1877dict["definitionProvider"] = definitionProvider;1878dict["typeDefinitionProvider"] = typeDefinitionProvider;1879dict["implementationProvider"] = implementationProvider;1880dict["referencesProvider"] = referencesProvider;1881dict["documentHighlightProvider"] = documentHighlightProvider;1882dict["documentSymbolProvider"] = documentSymbolProvider;1883dict["workspaceSymbolProvider"] = workspaceSymbolProvider;1884dict["workspace"] = workspace.to_json();1885dict["codeActionProvider"] = codeActionProvider;1886dict["documentFormattingProvider"] = documentFormattingProvider;1887dict["documentRangeFormattingProvider"] = documentRangeFormattingProvider;1888dict["declarationProvider"] = declarationProvider;1889return dict;1890}1891};18921893struct InitializeResult {1894/**1895* The capabilities the language server provides.1896*/1897ServerCapabilities capabilities;18981899_FORCE_INLINE_ Dictionary to_json() {1900Dictionary dict;1901dict["capabilities"] = capabilities.to_json();1902return dict;1903}1904};19051906struct GodotNativeClassInfo {1907String name;1908const DocData::ClassDoc *class_doc = nullptr;1909const ClassDB::ClassInfo *class_info = nullptr;19101911Dictionary to_json() const {1912Dictionary dict;1913dict["name"] = name;1914dict["inherits"] = class_doc->inherits;1915return dict;1916}1917};19181919/** Features not included in the standard lsp specifications */1920struct GodotCapabilities {1921/**1922* Native class list1923*/1924List<GodotNativeClassInfo> native_classes;19251926Dictionary to_json() const {1927Dictionary dict;1928Array classes;1929for (const GodotNativeClassInfo &native_class : native_classes) {1930classes.push_back(native_class.to_json());1931}1932dict["native_classes"] = classes;1933return dict;1934}1935};19361937/** Format BBCode documentation from DocData to markdown */1938static String marked_documentation(const String &p_bbcode) {1939String markdown = p_bbcode.strip_edges();19401941Vector<String> lines = markdown.split("\n");1942bool in_code_block = false;1943int code_block_indent = -1;19441945markdown = "";1946for (int i = 0; i < lines.size(); i++) {1947String line = lines[i];1948int block_start = line.find("[codeblock]");1949if (block_start != -1) {1950code_block_indent = block_start;1951in_code_block = true;1952line = "\n";1953} else if (in_code_block) {1954line = "\t" + line.substr(code_block_indent);1955}19561957if (in_code_block && line.contains("[/codeblock]")) {1958line = "\n";1959in_code_block = false;1960}19611962if (!in_code_block) {1963line = line.strip_edges();1964line = line.replace("[code]", "`");1965line = line.replace("[/code]", "`");1966line = line.replace("[i]", "*");1967line = line.replace("[/i]", "*");1968line = line.replace("[b]", "**");1969line = line.replace("[/b]", "**");1970line = line.replace("[u]", "__");1971line = line.replace("[/u]", "__");1972line = line.replace("[method ", "`");1973line = line.replace("[member ", "`");1974line = line.replace("[signal ", "`");1975line = line.replace("[enum ", "`");1976line = line.replace("[constant ", "`");1977line = line.replace_chars("[]", '`');1978}19791980if (!in_code_block && i < lines.size() - 1) {1981line += "\n\n";1982} else if (i < lines.size() - 1) {1983line += "\n";1984}1985markdown += line;1986}1987return markdown;1988}1989} // namespace LSP199019911992