Path: blob/master/modules/gdscript/language_server/godot_lsp.h
10278 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() {577Dictionary dict;578return dict;579}580};581582/**583* Folding range provider options.584*/585struct FoldingRangeProviderOptions {586Dictionary to_json() {587Dictionary dict;588return dict;589}590};591592struct TextDocumentSyncOptions {593/**594* Open and close notifications are sent to the server. If omitted open close notification should not595* be sent.596*/597bool openClose = true;598599/**600* Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full601* and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None.602*/603int change = TextDocumentSyncKind::Full;604605/**606* If present will save notifications are sent to the server. If omitted the notification should not be607* sent.608*/609bool willSave = false;610611/**612* If present will save wait until requests are sent to the server. If omitted the request should not be613* sent.614*/615bool willSaveWaitUntil = true;616617/**618* If present save notifications are sent to the server. If omitted the notification should not be619* sent.620*/621SaveOptions save;622623Dictionary to_json() {624Dictionary dict;625dict["willSaveWaitUntil"] = willSaveWaitUntil;626dict["willSave"] = willSave;627dict["openClose"] = openClose;628dict["change"] = change;629dict["save"] = save.to_json();630return dict;631}632};633634/**635* Static registration options to be returned in the initialize request.636*/637struct StaticRegistrationOptions {638/**639* The id used to register the request. The id can be used to deregister640* the request again. See also Registration#id.641*/642String id;643};644645/**646* Format document on type options.647*/648struct DocumentOnTypeFormattingOptions {649/**650* A character on which formatting should be triggered, like `}`.651*/652String firstTriggerCharacter;653654/**655* More trigger characters.656*/657Vector<String> moreTriggerCharacter;658659Dictionary to_json() {660Dictionary dict;661dict["firstTriggerCharacter"] = firstTriggerCharacter;662dict["moreTriggerCharacter"] = moreTriggerCharacter;663return dict;664}665};666667struct TextDocumentItem {668/**669* The text document's URI.670*/671DocumentUri uri;672673/**674* The text document's language identifier.675*/676String languageId;677678/**679* The version number of this document (it will increase after each680* change, including undo/redo).681*/682int version = 0;683684/**685* The content of the opened text document.686*/687String text;688689void load(const Dictionary &p_dict) {690uri = p_dict["uri"];691languageId = p_dict["languageId"];692version = p_dict["version"];693text = p_dict["text"];694}695696Dictionary to_json() const {697Dictionary dict;698dict["uri"] = uri;699dict["languageId"] = languageId;700dict["version"] = version;701dict["text"] = text;702return dict;703}704};705706/**707* An event describing a change to a text document. If range and rangeLength are omitted708* the new text is considered to be the full content of the document.709*/710struct TextDocumentContentChangeEvent {711/**712* The range of the document that changed.713*/714Range range;715716/**717* The length of the range that got replaced.718*/719int rangeLength = 0;720721/**722* The new text of the range/document.723*/724String text;725726void load(const Dictionary &p_params) {727text = p_params["text"];728rangeLength = p_params["rangeLength"];729range.load(p_params["range"]);730}731};732733// Use namespace instead of enumeration to follow the LSP specifications734namespace DiagnosticSeverity {735/**736* Reports an error.737*/738static const int Error = 1;739/**740* Reports a warning.741*/742static const int Warning = 2;743/**744* Reports an information.745*/746static const int Information = 3;747/**748* Reports a hint.749*/750static const int Hint = 4;751}; // namespace DiagnosticSeverity752753/**754* Represents a related message and source code location for a diagnostic. This should be755* used to point to code locations that cause or related to a diagnostics, e.g when duplicating756* a symbol in a scope.757*/758struct DiagnosticRelatedInformation {759/**760* The location of this related diagnostic information.761*/762Location location;763764/**765* The message of this related diagnostic information.766*/767String message;768769Dictionary to_json() const {770Dictionary dict;771dict["location"] = location.to_json();772dict["message"] = message;773return dict;774}775};776777/**778* Represents a diagnostic, such as a compiler error or warning.779* Diagnostic objects are only valid in the scope of a resource.780*/781struct Diagnostic {782/**783* The range at which the message applies.784*/785Range range;786787/**788* The diagnostic's severity. Can be omitted. If omitted it is up to the789* client to interpret diagnostics as error, warning, info or hint.790*/791int severity = 0;792793/**794* The diagnostic's code, which might appear in the user interface.795*/796int code = 0;797798/**799* A human-readable string describing the source of this800* diagnostic, e.g. 'typescript' or 'super lint'.801*/802String source;803804/**805* The diagnostic's message.806*/807String message;808809/**810* An array of related diagnostic information, e.g. when symbol-names within811* a scope collide all definitions can be marked via this property.812*/813Vector<DiagnosticRelatedInformation> relatedInformation;814815Dictionary to_json() const {816Dictionary dict;817dict["range"] = range.to_json();818dict["code"] = code;819dict["severity"] = severity;820dict["message"] = message;821dict["source"] = source;822if (!relatedInformation.is_empty()) {823Array arr;824arr.resize(relatedInformation.size());825for (int i = 0; i < relatedInformation.size(); i++) {826arr[i] = relatedInformation[i].to_json();827}828dict["relatedInformation"] = arr;829}830return dict;831}832};833834// Use namespace instead of enumeration to follow the LSP specifications835/**836* Describes the content type that a client supports in various837* result literals like `Hover`, `ParameterInfo` or `CompletionItem`.838*839* Please note that `MarkupKinds` must not start with a `$`. This kinds840* are reserved for internal usage.841*/842namespace MarkupKind {843static const String PlainText = "plaintext";844static const String Markdown = "markdown";845}; // namespace MarkupKind846847/**848* A `MarkupContent` literal represents a string value which content is interpreted base on its849* kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds.850*851* If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues.852* See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting853*854* Here is an example how such a string can be constructed using JavaScript / TypeScript:855* ```typescript856* let markdown: MarkdownContent = {857* kind: MarkupKind.Markdown,858* value: [859* '# Header',860* 'Some text',861* '```typescript',862* 'someCode();',863* '```'864* ].join('\n')865* };866* ```867*868* *Please Note* that clients might sanitize the return markdown. A client could decide to869* remove HTML from the markdown to avoid script execution.870*/871struct MarkupContent {872/**873* The type of the Markup.874*/875String kind;876877/**878* The content itself.879*/880String value;881882MarkupContent() {883kind = MarkupKind::Markdown;884}885886MarkupContent(const String &p_value) {887value = p_value;888kind = MarkupKind::Markdown;889}890891Dictionary to_json() const {892Dictionary dict;893dict["kind"] = kind;894dict["value"] = value;895return dict;896}897};898899// Use namespace instead of enumeration to follow the LSP specifications900// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not.901// And here C++ compilers are unhappy with our enumeration name like `Color`, `File`, `RefCounted` etc.902/**903* The kind of a completion entry.904*/905namespace CompletionItemKind {906static const int Text = 1;907static const int Method = 2;908static const int Function = 3;909static const int Constructor = 4;910static const int Field = 5;911static const int Variable = 6;912static const int Class = 7;913static const int Interface = 8;914static const int Module = 9;915static const int Property = 10;916static const int Unit = 11;917static const int Value = 12;918static const int Enum = 13;919static const int Keyword = 14;920static const int Snippet = 15;921static const int Color = 16;922static const int File = 17;923static const int RefCounted = 18;924static const int Folder = 19;925static const int EnumMember = 20;926static const int Constant = 21;927static const int Struct = 22;928static const int Event = 23;929static const int Operator = 24;930static const int TypeParameter = 25;931}; // namespace CompletionItemKind932933// Use namespace instead of enumeration to follow the LSP specifications.934/**935* Defines whether the insert text in a completion item should be interpreted as936* plain text or a snippet.937*/938namespace InsertTextFormat {939/**940* The primary text to be inserted is treated as a plain string.941*/942static const int PlainText = 1;943944/**945* The primary text to be inserted is treated as a snippet.946*947* A snippet can define tab stops and placeholders with `$1`, `$2`948* and `${3:foo}`. `$0` defines the final tab stop, it defaults to949* the end of the snippet. Placeholders with equal identifiers are linked,950* that is typing in one will update others too.951*/952static const int Snippet = 2;953}; // namespace InsertTextFormat954955struct CompletionItem {956/**957* The label of this completion item. By default958* also the text that is inserted when selecting959* this completion.960*/961String label;962963/**964* The kind of this completion item. Based of the kind965* an icon is chosen by the editor. The standardized set966* of available values is defined in `CompletionItemKind`.967*/968int kind = 0;969970/**971* A human-readable string with additional information972* about this item, like type or symbol information.973*/974String detail;975976/**977* A human-readable string that represents a doc-comment.978*/979MarkupContent documentation;980981/**982* Indicates if this item is deprecated.983*/984bool deprecated = false;985986/**987* Select this item when showing.988*989* *Note* that only one completion item can be selected and that the990* tool / client decides which item that is. The rule is that the *first*991* item of those that match best is selected.992*/993bool preselect = false;994995/**996* A string that should be used when comparing this item997* with other items. When omitted the label is used998* as the filter text for this item.999*/1000String sortText;10011002/**1003* A string that should be used when filtering a set of1004* completion items. When omitted the label is used as the1005* filter text for this item.1006*/1007String filterText;10081009/**1010* A string that should be inserted into a document when selecting1011* this completion. When omitted the label is used as the insert text1012* for this item.1013*1014* The `insertText` is subject to interpretation by the client side.1015* Some tools might not take the string literally. For example1016* VS Code when code complete is requested in this example1017* `con<cursor position>` and a completion item with an `insertText` of1018* `console` is provided it will only insert `sole`. Therefore it is1019* recommended to use `textEdit` instead since it avoids additional client1020* side interpretation.1021*/1022String insertText;10231024/**1025* The format of the insert text. The format applies to both the `insertText` property1026* and the `newText` property of a provided `textEdit`.1027*/1028int insertTextFormat = 0;10291030/**1031* An edit which is applied to a document when selecting this completion. When an edit is provided the value of1032* `insertText` is ignored.1033*1034* *Note:* The range of the edit must be a single line range and it must contain the position at which completion1035* has been requested.1036*/1037TextEdit textEdit;10381039/**1040* An optional array of additional text edits that are applied when1041* selecting this completion. Edits must not overlap (including the same insert position)1042* with the main edit nor with themselves.1043*1044* Additional text edits should be used to change text unrelated to the current cursor position1045* (for example adding an import statement at the top of the file if the completion item will1046* insert an unqualified type).1047*/1048Vector<TextEdit> additionalTextEdits;10491050/**1051* An optional set of characters that when pressed while this completion is active will accept it first and1052* then type that character. *Note* that all commit characters should have `length=1` and that superfluous1053* characters will be ignored.1054*/1055Vector<String> commitCharacters;10561057/**1058* An optional command that is executed *after* inserting this completion. *Note* that1059* additional modifications to the current document should be described with the1060* additionalTextEdits-property.1061*/1062Command command;10631064/**1065* A data entry field that is preserved on a completion item between1066* a completion and a completion resolve request.1067*/1068Variant data;10691070_FORCE_INLINE_ Dictionary to_json(bool resolved = false) const {1071Dictionary dict;1072dict["label"] = label;1073dict["kind"] = kind;1074dict["data"] = data;1075if (!insertText.is_empty()) {1076dict["insertText"] = insertText;1077}1078if (resolved) {1079dict["detail"] = detail;1080dict["documentation"] = documentation.to_json();1081dict["deprecated"] = deprecated;1082dict["preselect"] = preselect;1083if (!sortText.is_empty()) {1084dict["sortText"] = sortText;1085}1086if (!filterText.is_empty()) {1087dict["filterText"] = filterText;1088}1089if (commitCharacters.size()) {1090dict["commitCharacters"] = commitCharacters;1091}1092if (!command.command.is_empty()) {1093dict["command"] = command.to_json();1094}1095}1096return dict;1097}10981099void load(const Dictionary &p_dict) {1100if (p_dict.has("label")) {1101label = p_dict["label"];1102}1103if (p_dict.has("kind")) {1104kind = p_dict["kind"];1105}1106if (p_dict.has("detail")) {1107detail = p_dict["detail"];1108}1109if (p_dict.has("documentation")) {1110Variant doc = p_dict["documentation"];1111if (doc.is_string()) {1112documentation.value = doc;1113} else if (doc.get_type() == Variant::DICTIONARY) {1114Dictionary v = doc;1115documentation.value = v["value"];1116}1117}1118if (p_dict.has("deprecated")) {1119deprecated = p_dict["deprecated"];1120}1121if (p_dict.has("preselect")) {1122preselect = p_dict["preselect"];1123}1124if (p_dict.has("sortText")) {1125sortText = p_dict["sortText"];1126}1127if (p_dict.has("filterText")) {1128filterText = p_dict["filterText"];1129}1130if (p_dict.has("insertText")) {1131insertText = p_dict["insertText"];1132}1133if (p_dict.has("data")) {1134data = p_dict["data"];1135}1136}1137};11381139/**1140* Represents a collection of [completion items](#CompletionItem) to be presented1141* in the editor.1142*/1143struct CompletionList {1144/**1145* This list it not complete. Further typing should result in recomputing1146* this list.1147*/1148bool isIncomplete = false;11491150/**1151* The completion items.1152*/1153Vector<CompletionItem> items;1154};11551156// Use namespace instead of enumeration to follow the LSP specifications1157// `LSP::EnumName::EnumValue` is OK but `LSP::EnumValue` is not1158// And here C++ compilers are unhappy with our enumeration name like `String`, `Array`, `Object` etc1159/**1160* A symbol kind.1161*/1162namespace SymbolKind {1163static const int File = 1;1164static const int Module = 2;1165static const int Namespace = 3;1166static const int Package = 4;1167static const int Class = 5;1168static const int Method = 6;1169static const int Property = 7;1170static const int Field = 8;1171static const int Constructor = 9;1172static const int Enum = 10;1173static const int Interface = 11;1174static const int Function = 12;1175static const int Variable = 13;1176static const int Constant = 14;1177static const int String = 15;1178static const int Number = 16;1179static const int Boolean = 17;1180static const int Array = 18;1181static const int Object = 19;1182static const int Key = 20;1183static const int Null = 21;1184static const int EnumMember = 22;1185static const int Struct = 23;1186static const int Event = 24;1187static const int Operator = 25;1188static const int TypeParameter = 26;1189}; // namespace SymbolKind11901191/**1192* Represents programming constructs like variables, classes, interfaces etc. that appear in a document. Document symbols can be1193* hierarchical and they have two ranges: one that encloses its definition and one that points to its most interesting range,1194* e.g. the range of an identifier.1195*/1196struct DocumentSymbol {1197/**1198* The name of this symbol. Will be displayed in the user interface and therefore must not be1199* an empty string or a string only consisting of white spaces.1200*/1201String name;12021203/**1204* More detail for this symbol, e.g the signature of a function.1205*/1206String detail;12071208/**1209* Documentation for this symbol.1210*/1211String documentation;12121213/**1214* Class name for the native symbols.1215*/1216String native_class;12171218/**1219* The kind of this symbol.1220*/1221int kind = SymbolKind::File;12221223/**1224* Indicates if this symbol is deprecated.1225*/1226bool deprecated = false;12271228/**1229* If `true`: Symbol is local to script and cannot be accessed somewhere else.1230*1231* For example: local variable inside a `func`.1232*/1233bool local = false;12341235/**1236* The range enclosing this symbol not including leading/trailing whitespace but everything else1237* like comments. This information is typically used to determine if the clients cursor is1238* inside the symbol to reveal in the symbol in the UI.1239*/1240Range range;12411242/**1243* The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.1244* Must be contained by the `range`.1245*/1246Range selectionRange;12471248DocumentUri uri;1249String script_path;12501251/**1252* Children of this symbol, e.g. properties of a class.1253*/1254Vector<DocumentSymbol> children;12551256Dictionary to_json(bool with_doc = false) const {1257Dictionary dict;1258dict["name"] = name;1259dict["detail"] = detail;1260dict["kind"] = kind;1261dict["deprecated"] = deprecated;1262dict["range"] = range.to_json();1263dict["selectionRange"] = selectionRange.to_json();1264if (with_doc) {1265dict["documentation"] = documentation;1266dict["native_class"] = native_class;1267}1268if (!children.is_empty()) {1269Array arr;1270for (int i = 0; i < children.size(); i++) {1271if (children[i].local) {1272continue;1273}1274arr.push_back(children[i].to_json(with_doc));1275}1276if (!children.is_empty()) {1277dict["children"] = arr;1278}1279}1280return dict;1281}12821283_FORCE_INLINE_ MarkupContent render() const {1284MarkupContent markdown;1285if (detail.length()) {1286markdown.value = "\t" + detail + "\n\n";1287}1288if (documentation.length()) {1289markdown.value += marked_documentation(documentation) + "\n\n";1290}1291if (script_path.length()) {1292markdown.value += "Defined in [" + script_path + "](" + uri + ")";1293}1294return markdown;1295}12961297_FORCE_INLINE_ CompletionItem make_completion_item(bool resolved = false) const {1298LSP::CompletionItem item;1299item.label = name;13001301if (resolved) {1302item.documentation = render();1303}13041305switch (kind) {1306case LSP::SymbolKind::Enum:1307item.kind = LSP::CompletionItemKind::Enum;1308break;1309case LSP::SymbolKind::Class:1310item.kind = LSP::CompletionItemKind::Class;1311break;1312case LSP::SymbolKind::Property:1313item.kind = LSP::CompletionItemKind::Property;1314break;1315case LSP::SymbolKind::Method:1316case LSP::SymbolKind::Function:1317item.kind = LSP::CompletionItemKind::Method;1318break;1319case LSP::SymbolKind::Event:1320item.kind = LSP::CompletionItemKind::Event;1321break;1322case LSP::SymbolKind::Constant:1323item.kind = LSP::CompletionItemKind::Constant;1324break;1325case LSP::SymbolKind::Variable:1326item.kind = LSP::CompletionItemKind::Variable;1327break;1328case LSP::SymbolKind::File:1329item.kind = LSP::CompletionItemKind::File;1330break;1331default:1332item.kind = LSP::CompletionItemKind::Text;1333break;1334}13351336return item;1337}1338};13391340struct ApplyWorkspaceEditParams {1341WorkspaceEdit edit;13421343Dictionary to_json() {1344Dictionary dict;13451346dict["edit"] = edit.to_json();13471348return dict;1349}1350};13511352struct NativeSymbolInspectParams {1353String native_class;1354String symbol_name;13551356void load(const Dictionary &p_params) {1357native_class = p_params["native_class"];1358symbol_name = p_params["symbol_name"];1359}1360};13611362/**1363* Enum of known range kinds1364*/1365namespace FoldingRangeKind {1366/**1367* Folding range for a comment1368*/1369static const String Comment = "comment";1370/**1371* Folding range for a imports or includes1372*/1373static const String Imports = "imports";1374/**1375* Folding range for a region (e.g. `#region`)1376*/1377static const String Region = "region";1378} // namespace FoldingRangeKind13791380/**1381* Represents a folding range.1382*/1383struct FoldingRange {1384/**1385* The zero-based line number from where the folded range starts.1386*/1387int startLine = 0;13881389/**1390* The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.1391*/1392int startCharacter = 0;13931394/**1395* The zero-based line number where the folded range ends.1396*/1397int endLine = 0;13981399/**1400* The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.1401*/1402int endCharacter = 0;14031404/**1405* Describes the kind of the folding range such as `comment' or 'region'. The kind1406* is used to categorize folding ranges and used by commands like 'Fold all comments'. See1407* [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.1408*/1409String kind = FoldingRangeKind::Region;14101411_FORCE_INLINE_ Dictionary to_json() const {1412Dictionary dict;1413dict["startLine"] = startLine;1414dict["startCharacter"] = startCharacter;1415dict["endLine"] = endLine;1416dict["endCharacter"] = endCharacter;1417return dict;1418}1419};14201421// Use namespace instead of enumeration to follow the LSP specifications1422/**1423* How a completion was triggered1424*/1425namespace CompletionTriggerKind {1426/**1427* Completion was triggered by typing an identifier (24x7 code1428* complete), manual invocation (e.g Ctrl+Space) or via API.1429*/1430static const int Invoked = 1;14311432/**1433* Completion was triggered by a trigger character specified by1434* the `triggerCharacters` properties of the `CompletionRegistrationOptions`.1435*/1436static const int TriggerCharacter = 2;14371438/**1439* Completion was re-triggered as the current completion list is incomplete.1440*/1441static const int TriggerForIncompleteCompletions = 3;1442} // namespace CompletionTriggerKind14431444/**1445* Contains additional information about the context in which a completion request is triggered.1446*/1447struct CompletionContext {1448/**1449* How the completion was triggered.1450*/1451int triggerKind = CompletionTriggerKind::TriggerCharacter;14521453/**1454* The trigger character (a single character) that has trigger code complete.1455* Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`1456*/1457String triggerCharacter;14581459void load(const Dictionary &p_params) {1460triggerKind = int(p_params["triggerKind"]);1461triggerCharacter = p_params["triggerCharacter"];1462}1463};14641465struct CompletionParams : public TextDocumentPositionParams {1466/**1467* The completion context. This is only available if the client specifies1468* to send this using `ClientCapabilities.textDocument.completion.contextSupport === true`1469*/1470CompletionContext context;14711472void load(const Dictionary &p_params) {1473TextDocumentPositionParams::load(p_params);1474context.load(p_params["context"]);1475}14761477Dictionary to_json() {1478Dictionary ctx;1479ctx["triggerCharacter"] = context.triggerCharacter;1480ctx["triggerKind"] = context.triggerKind;14811482Dictionary dict;1483dict = TextDocumentPositionParams::to_json();1484dict["context"] = ctx;1485return dict;1486}1487};14881489/**1490* The result of a hover request.1491*/1492struct Hover {1493/**1494* The hover's content1495*/1496MarkupContent contents;14971498/**1499* An optional range is a range inside a text document1500* that is used to visualize a hover, e.g. by changing the background color.1501*/1502Range range;15031504_FORCE_INLINE_ Dictionary to_json() const {1505Dictionary dict;1506dict["range"] = range.to_json();1507dict["contents"] = contents.to_json();1508return dict;1509}1510};15111512/**1513* Represents a parameter of a callable-signature. A parameter can1514* have a label and a doc-comment.1515*/1516struct ParameterInformation {1517/**1518* The label of this parameter information.1519*1520* Either a string or an inclusive start and exclusive end offsets within its containing1521* signature label. (see SignatureInformation.label). The offsets are based on a UTF-161522* string representation as `Position` and `Range` does.1523*1524* *Note*: a label of type string should be a substring of its containing signature label.1525* Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.1526*/1527String label;15281529/**1530* The human-readable doc-comment of this parameter. Will be shown1531* in the UI but can be omitted.1532*/1533MarkupContent documentation;15341535Dictionary to_json() const {1536Dictionary dict;1537dict["label"] = label;1538dict["documentation"] = documentation.to_json();1539return dict;1540}1541};15421543/**1544* Represents the signature of something callable. A signature1545* can have a label, like a function-name, a doc-comment, and1546* a set of parameters.1547*/1548struct SignatureInformation {1549/**1550* The label of this signature. Will be shown in1551* the UI.1552*/1553String label;15541555/**1556* The human-readable doc-comment of this signature. Will be shown1557* in the UI but can be omitted.1558*/1559MarkupContent documentation;15601561/**1562* The parameters of this signature.1563*/1564Vector<ParameterInformation> parameters;15651566Dictionary to_json() const {1567Dictionary dict;1568dict["label"] = label;1569dict["documentation"] = documentation.to_json();1570Array args;1571for (int i = 0; i < parameters.size(); i++) {1572args.push_back(parameters[i].to_json());1573}1574dict["parameters"] = args;1575return dict;1576}1577};15781579/**1580* Signature help represents the signature of something1581* callable. There can be multiple signature but only one1582* active and only one active parameter.1583*/1584struct SignatureHelp {1585/**1586* One or more signatures.1587*/1588Vector<SignatureInformation> signatures;15891590/**1591* The active signature. If omitted or the value lies outside the1592* range of `signatures` the value defaults to zero or is ignored if1593* `signatures.length === 0`. Whenever possible implementers should1594* make an active decision about the active signature and shouldn't1595* rely on a default value.1596* In future version of the protocol this property might become1597* mandatory to better express this.1598*/1599int activeSignature = 0;16001601/**1602* The active parameter of the active signature. If omitted or the value1603* lies outside the range of `signatures[activeSignature].parameters`1604* defaults to 0 if the active signature has parameters. If1605* the active signature has no parameters it is ignored.1606* In future version of the protocol this property might become1607* mandatory to better express the active parameter if the1608* active signature does have any.1609*/1610int activeParameter = 0;16111612Dictionary to_json() const {1613Dictionary dict;1614Array sigs;1615for (int i = 0; i < signatures.size(); i++) {1616sigs.push_back(signatures[i].to_json());1617}1618dict["signatures"] = sigs;1619dict["activeSignature"] = activeSignature;1620dict["activeParameter"] = activeParameter;1621return dict;1622}1623};16241625/**1626* A pattern to describe in which file operation requests or notifications1627* the server is interested in.1628*/1629struct FileOperationPattern {1630/**1631* The glob pattern to match.1632*/1633String glob = "**/*.gd";16341635/**1636* Whether to match `file`s or `folder`s with this pattern.1637*1638* Matches both if undefined.1639*/1640String matches = "file";16411642Dictionary to_json() const {1643Dictionary dict;16441645dict["glob"] = glob;1646dict["matches"] = matches;16471648return dict;1649}1650};16511652/**1653* A filter to describe in which file operation requests or notifications1654* the server is interested in.1655*/1656struct FileOperationFilter {1657/**1658* The actual file operation pattern.1659*/1660FileOperationPattern pattern;16611662Dictionary to_json() const {1663Dictionary dict;16641665dict["pattern"] = pattern.to_json();16661667return dict;1668}1669};16701671/**1672* The options to register for file operations.1673*/1674struct FileOperationRegistrationOptions {1675/**1676* The actual filters.1677*/1678Vector<FileOperationFilter> filters;16791680FileOperationRegistrationOptions() {1681filters.push_back(FileOperationFilter());1682}16831684Dictionary to_json() const {1685Dictionary dict;16861687Array filts;1688for (int i = 0; i < filters.size(); i++) {1689filts.push_back(filters[i].to_json());1690}1691dict["filters"] = filts;16921693return dict;1694}1695};16961697/**1698* The server is interested in file notifications/requests.1699*/1700struct FileOperations {1701/**1702* The server is interested in receiving didDeleteFiles file notifications.1703*/1704FileOperationRegistrationOptions didDelete;17051706Dictionary to_json() const {1707Dictionary dict;17081709dict["didDelete"] = didDelete.to_json();17101711return dict;1712}1713};17141715/**1716* Workspace specific server capabilities1717*/1718struct Workspace {1719/**1720* The server is interested in file notifications/requests.1721*/1722FileOperations fileOperations;17231724Dictionary to_json() const {1725Dictionary dict;17261727dict["fileOperations"] = fileOperations.to_json();17281729return dict;1730}1731};17321733struct ServerCapabilities {1734/**1735* Defines how text documents are synced. Is either a detailed structure defining each notification or1736* for backwards compatibility the TextDocumentSyncKind number. If omitted it defaults to `TextDocumentSyncKind.None`.1737*/1738TextDocumentSyncOptions textDocumentSync;17391740/**1741* The server provides hover support.1742*/1743bool hoverProvider = true;17441745/**1746* The server provides completion support.1747*/1748CompletionOptions completionProvider;17491750/**1751* The server provides signature help support.1752*/1753SignatureHelpOptions signatureHelpProvider;17541755/**1756* The server provides goto definition support.1757*/1758bool definitionProvider = true;17591760/**1761* The server provides Goto Type Definition support.1762*1763* Since 3.6.01764*/1765bool typeDefinitionProvider = false;17661767/**1768* The server provides Goto Implementation support.1769*1770* Since 3.6.01771*/1772bool implementationProvider = false;17731774/**1775* The server provides find references support.1776*/1777bool referencesProvider = true;17781779/**1780* The server provides document highlight support.1781*/1782bool documentHighlightProvider = false;17831784/**1785* The server provides document symbol support.1786*/1787bool documentSymbolProvider = true;17881789/**1790* The server provides workspace symbol support.1791*/1792bool workspaceSymbolProvider = false;17931794/**1795* The server supports workspace folder.1796*/1797Workspace workspace;17981799/**1800* The server provides code actions. The `CodeActionOptions` return type is only1801* valid if the client signals code action literal support via the property1802* `textDocument.codeAction.codeActionLiteralSupport`.1803*/1804bool codeActionProvider = false;18051806/**1807* The server provides code lens.1808*/1809CodeLensOptions codeLensProvider;18101811/**1812* The server provides document formatting.1813*/1814bool documentFormattingProvider = false;18151816/**1817* The server provides document range formatting.1818*/1819bool documentRangeFormattingProvider = false;18201821/**1822* The server provides document formatting on typing.1823*/1824DocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;18251826/**1827* The server provides rename support. RenameOptions may only be1828* specified if the client states that it supports1829* `prepareSupport` in its initial `initialize` request.1830*/1831RenameOptions renameProvider;18321833/**1834* The server provides document link support.1835*/1836DocumentLinkOptions documentLinkProvider;18371838/**1839* The server provides color provider support.1840*1841* Since 3.6.01842*/1843ColorProviderOptions colorProvider;18441845/**1846* The server provides folding provider support.1847*1848* Since 3.10.01849*/1850FoldingRangeProviderOptions foldingRangeProvider;18511852/**1853* The server provides go to declaration support.1854*1855* Since 3.14.01856*/1857bool declarationProvider = true;18581859/**1860* The server provides execute command support.1861*/1862ExecuteCommandOptions executeCommandProvider;18631864_FORCE_INLINE_ Dictionary to_json() {1865Dictionary dict;1866dict["textDocumentSync"] = textDocumentSync.to_json();1867dict["completionProvider"] = completionProvider.to_json();1868signatureHelpProvider.triggerCharacters.push_back(",");1869signatureHelpProvider.triggerCharacters.push_back("(");1870dict["signatureHelpProvider"] = signatureHelpProvider.to_json();1871//dict["codeLensProvider"] = codeLensProvider.to_json();1872dict["documentOnTypeFormattingProvider"] = documentOnTypeFormattingProvider.to_json();1873dict["renameProvider"] = renameProvider.to_json();1874dict["documentLinkProvider"] = documentLinkProvider.to_json();1875dict["colorProvider"] = false; // colorProvider.to_json();1876dict["foldingRangeProvider"] = false; //foldingRangeProvider.to_json();1877dict["executeCommandProvider"] = executeCommandProvider.to_json();1878dict["hoverProvider"] = hoverProvider;1879dict["definitionProvider"] = definitionProvider;1880dict["typeDefinitionProvider"] = typeDefinitionProvider;1881dict["implementationProvider"] = implementationProvider;1882dict["referencesProvider"] = referencesProvider;1883dict["documentHighlightProvider"] = documentHighlightProvider;1884dict["documentSymbolProvider"] = documentSymbolProvider;1885dict["workspaceSymbolProvider"] = workspaceSymbolProvider;1886dict["workspace"] = workspace.to_json();1887dict["codeActionProvider"] = codeActionProvider;1888dict["documentFormattingProvider"] = documentFormattingProvider;1889dict["documentRangeFormattingProvider"] = documentRangeFormattingProvider;1890dict["declarationProvider"] = declarationProvider;1891return dict;1892}1893};18941895struct InitializeResult {1896/**1897* The capabilities the language server provides.1898*/1899ServerCapabilities capabilities;19001901_FORCE_INLINE_ Dictionary to_json() {1902Dictionary dict;1903dict["capabilities"] = capabilities.to_json();1904return dict;1905}1906};19071908struct GodotNativeClassInfo {1909String name;1910const DocData::ClassDoc *class_doc = nullptr;1911const ClassDB::ClassInfo *class_info = nullptr;19121913Dictionary to_json() const {1914Dictionary dict;1915dict["name"] = name;1916dict["inherits"] = class_doc->inherits;1917return dict;1918}1919};19201921/** Features not included in the standard lsp specifications */1922struct GodotCapabilities {1923/**1924* Native class list1925*/1926List<GodotNativeClassInfo> native_classes;19271928Dictionary to_json() const {1929Dictionary dict;1930Array classes;1931for (const GodotNativeClassInfo &native_class : native_classes) {1932classes.push_back(native_class.to_json());1933}1934dict["native_classes"] = classes;1935return dict;1936}1937};19381939/** Format BBCode documentation from DocData to markdown */1940static String marked_documentation(const String &p_bbcode) {1941String markdown = p_bbcode.strip_edges();19421943Vector<String> lines = markdown.split("\n");1944bool in_code_block = false;1945int code_block_indent = -1;19461947markdown = "";1948for (int i = 0; i < lines.size(); i++) {1949String line = lines[i];1950int block_start = line.find("[codeblock]");1951if (block_start != -1) {1952code_block_indent = block_start;1953in_code_block = true;1954line = "\n";1955} else if (in_code_block) {1956line = "\t" + line.substr(code_block_indent);1957}19581959if (in_code_block && line.contains("[/codeblock]")) {1960line = "\n";1961in_code_block = false;1962}19631964if (!in_code_block) {1965line = line.strip_edges();1966line = line.replace("[code]", "`");1967line = line.replace("[/code]", "`");1968line = line.replace("[i]", "*");1969line = line.replace("[/i]", "*");1970line = line.replace("[b]", "**");1971line = line.replace("[/b]", "**");1972line = line.replace("[u]", "__");1973line = line.replace("[/u]", "__");1974line = line.replace("[method ", "`");1975line = line.replace("[member ", "`");1976line = line.replace("[signal ", "`");1977line = line.replace("[enum ", "`");1978line = line.replace("[constant ", "`");1979line = line.replace_chars("[]", '`');1980}19811982if (!in_code_block && i < lines.size() - 1) {1983line += "\n\n";1984} else if (i < lines.size() - 1) {1985line += "\n";1986}1987markdown += line;1988}1989return markdown;1990}1991} // namespace LSP199219931994