Explorar el Código

Implement DocumentLink of GDScript LSP Server

geequlim hace 5 años
padre
commit
6a8303f82f

+ 39 - 0
modules/gdscript/language_server/gdscript_extend_parser.cpp

@@ -105,6 +105,40 @@ void ExtendGDScriptParser::update_symbols() {
 	}
 }
 
+void ExtendGDScriptParser::update_document_links(const String &p_code) {
+	document_links.clear();
+
+	GDScriptTokenizerText tokenizer;
+	FileAccessRef fs = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+	tokenizer.set_code(p_code);
+	while (true) {
+		if (tokenizer.get_token() == GDScriptTokenizer::TK_EOF) {
+			break;
+		} else if (tokenizer.get_token() == GDScriptTokenizer::TK_CONSTANT) {
+			Variant const_val = tokenizer.get_token_constant();
+			if (const_val.get_type() == Variant::STRING) {
+				String path = const_val;
+				bool exists = fs->file_exists(path);
+				if (!exists) {
+					path = get_path().get_base_dir() + "/" + path;
+					exists = fs->file_exists(path);
+				}
+				if (exists) {
+					String value = const_val;
+					lsp::DocumentLink link;
+					link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(path);
+					link.range.start.line = LINE_NUMBER_TO_INDEX(tokenizer.get_token_line());
+					link.range.end.line = link.range.start.line;
+					link.range.end.character = LINE_NUMBER_TO_INDEX(tokenizer.get_token_column());
+					link.range.start.character = link.range.end.character - value.length();
+					document_links.push_back(link);
+				}
+			}
+		}
+		tokenizer.advance();
+	}
+}
+
 void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol) {
 
 	const String uri = get_uri();
@@ -572,6 +606,10 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String
 	return NULL;
 }
 
+const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const {
+	return document_links;
+}
+
 const Array &ExtendGDScriptParser::get_member_completions() {
 
 	if (member_completions.empty()) {
@@ -755,5 +793,6 @@ Error ExtendGDScriptParser::parse(const String &p_code, const String &p_path) {
 	Error err = GDScriptParser::parse(p_code, p_path.get_base_dir(), false, p_path, false, NULL, false);
 	update_diagnostics();
 	update_symbols();
+	update_document_links(p_code);
 	return err;
 }

+ 3 - 0
modules/gdscript/language_server/gdscript_extend_parser.h

@@ -56,12 +56,14 @@ class ExtendGDScriptParser : public GDScriptParser {
 
 	lsp::DocumentSymbol class_symbol;
 	Vector<lsp::Diagnostic> diagnostics;
+	List<lsp::DocumentLink> document_links;
 	ClassMembers members;
 	HashMap<String, ClassMembers> inner_classes;
 
 	void update_diagnostics();
 
 	void update_symbols();
+	void update_document_links(const String &p_code);
 	void parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol);
 	void parse_function_symbol(const GDScriptParser::FunctionNode *p_func, lsp::DocumentSymbol &r_symbol);
 
@@ -93,6 +95,7 @@ public:
 
 	const lsp::DocumentSymbol *get_symbol_defined_at_line(int p_line) const;
 	const lsp::DocumentSymbol *get_member_symbol(const String &p_name, const String &p_subclass = "") const;
+	const List<lsp::DocumentLink> &get_document_links() const;
 
 	const Array &get_member_completions();
 	Dictionary generate_api() const;

+ 11 - 2
modules/gdscript/language_server/gdscript_text_document.cpp

@@ -271,8 +271,17 @@ Array GDScriptTextDocument::codeLens(const Dictionary &p_params) {
 	return arr;
 }
 
-Variant GDScriptTextDocument::documentLink(const Dictionary &p_params) {
-	Variant ret;
+Array GDScriptTextDocument::documentLink(const Dictionary &p_params) {
+	Array ret;
+
+	lsp::DocumentLinkParams params;
+	params.load(p_params);
+
+	List<lsp::DocumentLink> links;
+	GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_document_links(params.textDocument.uri, links);
+	for (const List<lsp::DocumentLink>::Element *E = links.front(); E; E = E->next()) {
+		ret.push_back(E->get().to_json());
+	}
 	return ret;
 }
 

+ 1 - 1
modules/gdscript/language_server/gdscript_text_document.h

@@ -59,7 +59,7 @@ public:
 	Dictionary resolve(const Dictionary &p_params);
 	Array foldingRange(const Dictionary &p_params);
 	Array codeLens(const Dictionary &p_params);
-	Variant documentLink(const Dictionary &p_params);
+	Array documentLink(const Dictionary &p_params);
 	Array colorPresentation(const Dictionary &p_params);
 	Variant hover(const Dictionary &p_params);
 	Array definition(const Dictionary &p_params);

+ 9 - 0
modules/gdscript/language_server/gdscript_workspace.cpp

@@ -475,6 +475,15 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
 	}
 }
 
+void GDScriptWorkspace::resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list) {
+	if (const ExtendGDScriptParser *parser = get_parse_successed_script(get_file_path(p_uri))) {
+		const List<lsp::DocumentLink> &links = parser->get_document_links();
+		for (const List<lsp::DocumentLink>::Element *E = links.front(); E; E = E->next()) {
+			r_list.push_back(E->get());
+		}
+	}
+}
+
 Dictionary GDScriptWorkspace::generate_script_api(const String &p_path) {
 	Dictionary api;
 	if (const ExtendGDScriptParser *parser = get_parse_successed_script(p_path)) {

+ 1 - 1
modules/gdscript/language_server/gdscript_workspace.h

@@ -53,7 +53,6 @@ protected:
 	ExtendGDScriptParser *get_parse_successed_script(const String &p_path);
 	ExtendGDScriptParser *get_parse_result(const String &p_path);
 
-	void strip_flat_symbols(const String &p_branch);
 	void list_script_files(const String &p_root_dir, List<String> &r_files);
 
 public:
@@ -82,6 +81,7 @@ public:
 	const lsp::DocumentSymbol *resolve_symbol(const lsp::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name = "", bool p_func_requred = false);
 	void resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list);
 
+	void resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list);
 	Dictionary generate_script_api(const String &p_path);
 
 	GDScriptWorkspace();

+ 35 - 0
modules/gdscript/language_server/lsp.hpp

@@ -199,6 +199,41 @@ struct TextDocumentPositionParams {
 	}
 };
 
+struct DocumentLinkParams {
+	/**
+	 * The document to provide document links for.
+	 */
+	TextDocumentIdentifier textDocument;
+
+	_FORCE_INLINE_ void load(const Dictionary &p_params) {
+		textDocument.load(p_params["textDocument"]);
+	}
+};
+
+/**
+ * A document link is a range in a text document that links to an internal or external resource, like another
+ * text document or a web site.
+ */
+struct DocumentLink {
+
+	/**
+	 * The range this link applies to.
+	 */
+	Range range;
+
+	/**
+	 * The uri this link points to. If missing a resolve request is sent later.
+	 */
+	DocumentUri target;
+
+	Dictionary to_json() const {
+		Dictionary dict;
+		dict["range"] = range.to_json();
+		dict["target"] = target;
+		return dict;
+	}
+};
+
 /**
  * A textual edit applicable to a text document.
  */