diff options
Diffstat (limited to 'modules/gdscript/language_server/lsp.hpp')
-rw-r--r-- | modules/gdscript/language_server/lsp.hpp | 163 |
1 files changed, 155 insertions, 8 deletions
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp index 81fa4c6181..7e98bfa279 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/lsp.hpp @@ -610,6 +610,70 @@ struct Diagnostic { }; /** + * Describes the content type that a client supports in various + * result literals like `Hover`, `ParameterInfo` or `CompletionItem`. + * + * Please note that `MarkupKinds` must not start with a `$`. This kinds + * are reserved for internal usage. + */ +namespace MarkupKind { +static const String PlainText = "plaintext"; +static const String Markdown = "markdown"; +}; // namespace MarkupKind + +/** + * A `MarkupContent` literal represents a string value which content is interpreted base on its + * kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds. + * + * If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues. + * See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + * + * Here is an example how such a string can be constructed using JavaScript / TypeScript: + * ```typescript + * let markdown: MarkdownContent = { + * kind: MarkupKind.Markdown, + * value: [ + * '# Header', + * 'Some text', + * '```typescript', + * 'someCode();', + * '```' + * ].join('\n') + * }; + * ``` + * + * *Please Note* that clients might sanitize the return markdown. A client could decide to + * remove HTML from the markdown to avoid script execution. + */ +struct MarkupContent { + /** + * The type of the Markup + */ + String kind; + + /** + * The content itself + */ + String value; + + MarkupContent() { + kind = MarkupKind::Markdown; + } + + MarkupContent(const String &p_value) { + value = p_value; + kind = MarkupKind::Markdown; + } + + Dictionary to_json() const { + Dictionary dict; + dict["kind"] = kind; + dict["value"] = value; + return dict; + } +}; + +/** * A symbol kind. */ namespace SymbolKind { @@ -693,6 +757,18 @@ struct SymbolInformation { } }; +struct DocumentedSymbolInformation : public SymbolInformation { + /** + * A human-readable string with additional information + */ + String detail; + + /** + * A human-readable string that represents a doc-comment. + */ + String documentation; +}; + /** * Represents programming constructs like variables, classes, interfaces etc. that appear in a document. Document symbols can be * hierarchical and they have two ranges: one that encloses its definition and one that points to its most interesting range, @@ -712,6 +788,11 @@ struct DocumentSymbol { String detail; /** + * Documentation for this symbol + */ + String documentation; + + /** * The kind of this symbol. */ int kind = SymbolKind::File; @@ -734,6 +815,9 @@ struct DocumentSymbol { */ Range selectionRange; + DocumentUri uri; + String script_path; + /** * Children of this symbol, e.g. properties of a class. */ @@ -756,19 +840,39 @@ struct DocumentSymbol { return dict; } - void symbol_tree_as_list(const String &p_uri, Vector<SymbolInformation> &r_list, const String &p_container = "") const { - SymbolInformation si; - si.name = name; + void symbol_tree_as_list(const String &p_uri, Vector<DocumentedSymbolInformation> &r_list, const String &p_container = "", bool p_join_name = false) const { + DocumentedSymbolInformation si; + if (p_join_name && !p_container.empty()) { + si.name = p_container + ">" + name; + } else { + si.name = name; + } si.kind = kind; si.containerName = p_container; si.deprecated = deprecated; si.location.uri = p_uri; si.location.range = range; + si.detail = detail; + si.documentation = documentation; r_list.push_back(si); for (int i = 0; i < children.size(); i++) { - children[i].symbol_tree_as_list(p_uri, r_list, name); + children[i].symbol_tree_as_list(p_uri, r_list, si.name, p_join_name); } } + + MarkupContent render() const { + MarkupContent markdown; + if (detail.length()) { + markdown.value = "\t" + detail + "\n\n"; + } + if (documentation.length()) { + markdown.value += documentation + "\n\n"; + } + if (script_path.length()) { + markdown.value += "Defined in [" + script_path + "](" + uri + ")"; + } + return markdown; + } }; /** @@ -895,7 +999,7 @@ struct CompletionItem { /** * A human-readable string that represents a doc-comment. */ - String documentation; + MarkupContent documentation; /** * Indicates if this item is deprecated. @@ -988,9 +1092,8 @@ struct CompletionItem { Dictionary dict; dict["label"] = label; dict["kind"] = kind; - dict["kind"] = kind; dict["detail"] = detail; - dict["documentation"] = documentation; + dict["documentation"] = documentation.to_json(); dict["deprecated"] = deprecated; dict["preselect"] = preselect; dict["sortText"] = sortText; @@ -1001,6 +1104,27 @@ struct CompletionItem { dict["data"] = data; return dict; } + + void load(const Dictionary &p_dict) { + if (p_dict.has("label")) label = p_dict["label"]; + if (p_dict.has("kind")) kind = p_dict["kind"]; + if (p_dict.has("detail")) detail = p_dict["detail"]; + if (p_dict.has("documentation")) { + Variant doc = p_dict["documentation"]; + if (doc.get_type() == Variant::STRING) { + documentation.value = doc; + } else if (doc.get_type() == Variant::DICTIONARY) { + Dictionary v = doc; + documentation.value = v["value"]; + } + } + if (p_dict.has("deprecated")) deprecated = p_dict["deprecated"]; + if (p_dict.has("preselect")) preselect = p_dict["preselect"]; + if (p_dict.has("sortText")) sortText = p_dict["sortText"]; + if (p_dict.has("filterText")) filterText = p_dict["filterText"]; + if (p_dict.has("insertText")) insertText = p_dict["insertText"]; + if (p_dict.has("data")) data = p_dict["data"]; + } }; /** @@ -1137,6 +1261,29 @@ struct CompletionParams : public TextDocumentPositionParams { } }; +/** + * The result of a hover request. + */ +struct Hover { + /** + * The hover's content + */ + MarkupContent contents; + + /** + * An optional range is a range inside a text document + * that is used to visualize a hover, e.g. by changing the background color. + */ + Range range; + + Dictionary to_json() const { + Dictionary dict; + dict["range"] = range.to_json(); + dict["contents"] = contents.to_json(); + return dict; + } +}; + struct ServerCapabilities { /** * Defines how text documents are synced. Is either a detailed structure defining each notification or @@ -1162,7 +1309,7 @@ struct ServerCapabilities { /** * The server provides goto definition support. */ - bool definitionProvider = false; + bool definitionProvider = true; /** * The server provides Goto Type Definition support. |