From 10fe6f14bba67950bde486051f1fd5e06c7f6dcd Mon Sep 17 00:00:00 2001
From: Adam Scott <ascott.ca@gmail.com>
Date: Sat, 15 Apr 2023 12:29:11 -0400
Subject: [PATCH] Fix GDScript LSP variable rename

---
 .../gdscript_extend_parser.cpp                | 14 +++++++
 .../language_server/gdscript_workspace.cpp    | 40 ++++++++++++++-----
 modules/gdscript/language_server/godot_lsp.h  | 10 -----
 3 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 07f94655167..3a5a54e275e 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -400,6 +400,20 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
 				}
 			} break;
 
+			case GDScriptParser::TypeNode::VARIABLE: {
+				GDScriptParser::VariableNode *variable_node = (GDScriptParser::VariableNode *)(node);
+				lsp::DocumentSymbol symbol;
+				symbol.kind = lsp::SymbolKind::Variable;
+				symbol.name = variable_node->identifier->name;
+				symbol.range.start.line = LINE_NUMBER_TO_INDEX(variable_node->start_line);
+				symbol.range.start.character = LINE_NUMBER_TO_INDEX(variable_node->start_column);
+				symbol.range.end.line = LINE_NUMBER_TO_INDEX(variable_node->end_line);
+				symbol.range.end.character = LINE_NUMBER_TO_INDEX(variable_node->end_column);
+				symbol.uri = uri;
+				symbol.script_path = path;
+				r_symbol.children.push_back(symbol);
+			} break;
+
 			default:
 				continue;
 		}
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index b90c4523469..7fc29623419 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -185,15 +185,27 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_local_symbol(const ExtendGDScr
 	const lsp::DocumentSymbol *class_symbol = &p_parser->get_symbols();
 
 	for (int i = 0; i < class_symbol->children.size(); ++i) {
-		if (class_symbol->children[i].kind == lsp::SymbolKind::Function || class_symbol->children[i].kind == lsp::SymbolKind::Class) {
-			const lsp::DocumentSymbol *function_symbol = &class_symbol->children[i];
+		int kind = class_symbol->children[i].kind;
+		switch (kind) {
+			case lsp::SymbolKind::Function:
+			case lsp::SymbolKind::Method:
+			case lsp::SymbolKind::Class: {
+				const lsp::DocumentSymbol *function_symbol = &class_symbol->children[i];
 
-			for (int l = 0; l < function_symbol->children.size(); ++l) {
-				const lsp::DocumentSymbol *local = &function_symbol->children[l];
-				if (!local->detail.is_empty() && local->name == p_symbol_identifier) {
-					return local;
+				for (int l = 0; l < function_symbol->children.size(); ++l) {
+					const lsp::DocumentSymbol *local = &function_symbol->children[l];
+					if (!local->detail.is_empty() && local->name == p_symbol_identifier) {
+						return local;
+					}
 				}
-			}
+			} break;
+
+			case lsp::SymbolKind::Variable: {
+				const lsp::DocumentSymbol *variable_symbol = &class_symbol->children[i];
+				if (variable_symbol->name == p_symbol_identifier) {
+					return variable_symbol;
+				}
+			} break;
 		}
 	}
 
@@ -650,8 +662,18 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu
 						if (const ExtendGDScriptParser *target_parser = get_parse_result(target_script_path)) {
 							symbol = target_parser->get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(ret.location));
 
-							if (symbol && symbol->kind == lsp::SymbolKind::Function && symbol->name != symbol_identifier) {
-								symbol = get_parameter_symbol(symbol, symbol_identifier);
+							if (symbol) {
+								switch (symbol->kind) {
+									case lsp::SymbolKind::Function: {
+										if (symbol->name != symbol_identifier) {
+											symbol = get_parameter_symbol(symbol, symbol_identifier);
+										}
+									} break;
+
+									case lsp::SymbolKind::Variable: {
+										symbol = get_local_symbol(parser, symbol_identifier);
+									} break;
+								}
 							}
 						}
 
diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h
index 8a033204dad..5b5327bdb77 100644
--- a/modules/gdscript/language_server/godot_lsp.h
+++ b/modules/gdscript/language_server/godot_lsp.h
@@ -293,16 +293,6 @@ struct WorkspaceEdit {
 	}
 
 	_FORCE_INLINE_ void add_change(const String &uri, const int &line, const int &start_character, const int &end_character, const String &new_text) {
-		if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) {
-			Vector<TextEdit> edit_list = E->value;
-			for (int i = 0; i < edit_list.size(); ++i) {
-				TextEdit edit = edit_list[i];
-				if (edit.range.start.character == start_character) {
-					return;
-				}
-			}
-		}
-
 		TextEdit new_edit;
 		new_edit.newText = new_text;
 		new_edit.range.start.line = line;