summaryrefslogtreecommitdiff
path: root/modules/gdscript/language_server/lsp.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/language_server/lsp.hpp')
-rw-r--r--modules/gdscript/language_server/lsp.hpp163
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.