Skip to content

Commit e5cbea9

Browse files
committed
Fix issues with enum (detects correctly enum names/values)
1 parent f19479f commit e5cbea9

File tree

9 files changed

+260
-51
lines changed

9 files changed

+260
-51
lines changed

modules/gdscript/gdscript_editor.cpp

Lines changed: 103 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4231,7 +4231,9 @@ static void _refactor_rename_symbol_add_match(const String &p_path, const GDScri
42314231
r_result.add_match(p_path, match);
42324232
}
42334233

4234-
static Error _refactor_rename_symbol_match_from_class_loop_nodes(GDScriptParser::NodeList &p_node_list, const String &p_symbol, const String &p_path, ScriptLanguage::RefactorRenameSymbolResult &r_result, RefactorRenameSymbolDefinintionType p_expected_definition_type, GDScriptParser::Node *p_source_node) {
4234+
static Error _refactor_rename_symbol_match_from_class_loop_nodes(GDScriptParser::NodeList &p_node_list, const String &p_symbol, const String &p_path, ScriptLanguage::RefactorRenameSymbolResult &r_result, RefactorRenameSymbolDefinintionType p_expected_definition_type, GDScriptParser::Node *p_source_node, LocalVector<GDScriptParser::IdentifierNode::Source> p_target_sources = {}) {
4235+
ERR_FAIL_NULL_V(p_source_node, FAILED);
4236+
42354237
for (GDScriptParser::Node *node : p_node_list) {
42364238
switch (node->type) {
42374239
case GDScriptParser::Node::Type::IDENTIFIER: {
@@ -4245,16 +4247,36 @@ static Error _refactor_rename_symbol_match_from_class_loop_nodes(GDScriptParser:
42454247
if (identifier_node_source_node == p_source_node) {
42464248
_refactor_rename_symbol_add_match(p_path, identifier_node, r_result);
42474249
continue;
4250+
} else if (identifier_node_source_node != nullptr) {
4251+
continue;
42484252
}
42494253

42504254
// Maybe the identifier is in the definition itself of the source, so it doesn't have any source.
42514255
// Though, it's owner could be the same as the source node.
42524256
GDScriptParser::Node *identifier_node_owner = p_node_list.get_owner(identifier_node);
42534257
if (identifier_node_owner == p_source_node) {
4254-
_refactor_rename_symbol_add_match(p_path, identifier_node, r_result);
4258+
if (identifier_node_owner->type != GDScriptParser::Node::ENUM) {
4259+
_refactor_rename_symbol_add_match(p_path, identifier_node, r_result);
4260+
continue;
4261+
}
4262+
} else if (identifier_node_owner == nullptr) {
4263+
// No leads to anything.
42554264
continue;
42564265
}
42574266

4267+
if (!p_target_sources.is_empty()) {
4268+
bool found_target_source = false;
4269+
for (GDScriptParser::IdentifierNode::Source target_source : p_target_sources) {
4270+
if (identifier_node->source == target_source) {
4271+
found_target_source = true;
4272+
break;
4273+
}
4274+
}
4275+
if (!found_target_source) {
4276+
continue;
4277+
}
4278+
}
4279+
42584280
switch (p_source_node->type) {
42594281
case GDScriptParser::Node::IDENTIFIER: {
42604282
GDScriptParser::IdentifierNode *source_node_identifier_node = static_cast<GDScriptParser::IdentifierNode *>(p_source_node);
@@ -4269,29 +4291,54 @@ static Error _refactor_rename_symbol_match_from_class_loop_nodes(GDScriptParser:
42694291
} break;
42704292
case GDScriptParser::Node::ENUM: {
42714293
GDScriptParser::EnumNode *source_node_enum_node = static_cast<GDScriptParser::EnumNode *>(p_source_node);
4272-
if (identifier_node->name != source_node_enum_node->identifier->name) {
4273-
bool found = false;
4274-
for (GDScriptParser::EnumNode::Value &value : source_node_enum_node->values) {
4275-
if (identifier_node->name == value.identifier->name) {
4276-
found = true;
4277-
break;
4294+
4295+
if (identifier_node_owner == source_node_enum_node) {
4296+
if (source_node_enum_node->identifier == identifier_node) {
4297+
if (p_expected_definition_type == REFACTOR_RENAME_SYMBOL_DEFINITION_TYPE_ENUM) {
4298+
_refactor_rename_symbol_add_match(p_path, identifier_node, r_result);
4299+
} else if (p_expected_definition_type == REFACTOR_RENAME_SYMBOL_DEFINITION_TYPE_ENUM_VALUE) {
4300+
// Skip. This is an enum name.
4301+
}
4302+
} else if (p_expected_definition_type == REFACTOR_RENAME_SYMBOL_DEFINITION_TYPE_ENUM_VALUE) {
4303+
for (GDScriptParser::EnumNode::Value &value : source_node_enum_node->values) {
4304+
if (value.identifier == identifier_node || value.identifier->name == identifier_node->name) {
4305+
_refactor_rename_symbol_add_match(p_path, identifier_node, r_result);
4306+
break;
4307+
}
42784308
}
42794309
}
4280-
if (!found) {
4310+
continue;
4311+
}
4312+
4313+
GDScriptParser::DataType identifier_datatype = identifier_node->get_datatype();
4314+
if (identifier_datatype.kind == GDScriptParser::DataType::Kind::UNRESOLVED) {
4315+
if (identifier_node_owner->get_datatype().kind != GDScriptParser::DataType::ENUM) {
42814316
continue;
42824317
}
4318+
identifier_datatype = identifier_node_owner->get_datatype();
4319+
} else if (identifier_datatype.kind != GDScriptParser::DataType::Kind::ENUM) {
4320+
continue;
42834321
}
4284-
ERR_FAIL_COND_V_MSG(identifier_node_owner == nullptr, FAILED, "identifier node owner datatype is null");
4285-
GDScriptParser::DataType identifier_node_owner_datatype = identifier_node_owner->get_datatype();
4286-
ERR_FAIL_COND_V_MSG(identifier_node_owner_datatype.class_type == nullptr, FAILED, "identifier node owner datatype class_type is null");
4287-
if (identifier_node_owner_datatype.script_path != source_node_enum_node->get_datatype().script_path) {
4322+
4323+
if (p_expected_definition_type == REFACTOR_RENAME_SYMBOL_DEFINITION_TYPE_ENUM) {
4324+
if (identifier_datatype.builtin_type == Variant::INT) {
4325+
// It refers to an enum value. Skipping.
4326+
continue;
4327+
}
4328+
} else if (p_expected_definition_type == REFACTOR_RENAME_SYMBOL_DEFINITION_TYPE_ENUM_VALUE) {
4329+
if (identifier_datatype.builtin_type == Variant::DICTIONARY) {
4330+
// It refers to an enum name. Skipping.
4331+
continue;
4332+
}
4333+
} else {
42884334
continue;
42894335
}
4290-
if (identifier_node_owner_datatype.class_type->fqcn != source_node_enum_node->get_datatype().class_type->fqcn) {
4336+
4337+
if (identifier_node->get_datatype().native_type != source_node_enum_node->get_datatype().native_type) {
42914338
continue;
42924339
}
4340+
42934341
_refactor_rename_symbol_add_match(p_path, identifier_node, r_result);
4294-
continue;
42954342
} break;
42964343
case GDScriptParser::Node::SIGNAL: {
42974344
GDScriptParser::SignalNode *source_node_signal_node = static_cast<GDScriptParser::SignalNode *>(p_source_node);
@@ -4363,7 +4410,7 @@ static Error _refactor_rename_symbol_match_from_class_find_matching_nodes(GDScri
43634410

43644411
// As we found that the match comes from a class, let's find all the matches in that class.
43654412
GDScriptParser::NodeList list(p_class_node);
4366-
return _refactor_rename_symbol_match_from_class_loop_nodes(list, p_symbol, p_path, r_result, p_expected_definition_type, p_source_node);
4413+
return _refactor_rename_symbol_match_from_class_loop_nodes(list, p_symbol, p_path, r_result, p_expected_definition_type, p_source_node, target_sources);
43674414
}
43684415

43694416
// This function finds and match all instances of the symbol outside the class.
@@ -4680,16 +4727,17 @@ ::Error GDScriptLanguage::refactor_rename_symbol_code(const String &p_code, cons
46804727
}
46814728
#endif // TOOLS_ENABLED
46824729

4730+
Vector2i cursor_position = GDScriptParser::get_cursor_sentinel_position(p_code, tab_size);
4731+
if (cursor_position.y == -1 || cursor_position.x == -1) {
4732+
REFACTOR_RENAME_RETURN(FAILED);
4733+
}
4734+
46834735
GDScriptParser parser;
46844736
parser.parse(p_code, p_path, GDScriptParser::ParsingType::PARSING_TYPE_REFACTOR_RENAME);
46854737

46864738
GDScriptParser::RefactorRenameContext context = parser.get_refactor_rename_context();
46874739
context.base = p_owner;
46884740

4689-
Vector2i cursor_position = GDScriptParser::get_cursor_sentinel_position(p_code, tab_size);
4690-
if (cursor_position.y == -1 || cursor_position.x == -1) {
4691-
REFACTOR_RENAME_RETURN(FAILED);
4692-
}
46934741
r_result.sentinel = cursor_position;
46944742
r_result.code = p_code;
46954743

@@ -5038,7 +5086,7 @@ ::Error GDScriptLanguage::refactor_rename_symbol_code(const String &p_code, cons
50385086
REFACTOR_RENAME_RETURN(OK);
50395087
} break;
50405088
default: {
5041-
// Do nothing.
5089+
REFACTOR_RENAME_RETURN(ERR_CANT_RESOLVE);
50425090
}
50435091
}
50445092
} break;
@@ -5056,12 +5104,12 @@ ::Error GDScriptLanguage::refactor_rename_symbol_code(const String &p_code, cons
50565104
REFACTOR_RENAME_RETURN(OK);
50575105
} break;
50585106
default: {
5059-
// Do nothing.
5107+
REFACTOR_RENAME_RETURN(ERR_CANT_RESOLVE);
50605108
}
50615109
}
50625110
} break;
50635111
default: {
5064-
// Do nothing.
5112+
REFACTOR_RENAME_RETURN(ERR_CANT_RESOLVE);
50655113
}
50665114
}
50675115
} break;
@@ -5076,8 +5124,39 @@ ::Error GDScriptLanguage::refactor_rename_symbol_code(const String &p_code, cons
50765124
REFACTOR_RENAME_OUTSIDE_GDSCRIPT(REFACTOR_RENAME_SYMBOL_RESULT_SYMBOL);
50775125
REFACTOR_RENAME_RETURN(OK);
50785126
} break;
5127+
case GDScriptParser::REFACTOR_RENAME_TYPE_ENUM: {
5128+
GDScriptParser::DataType base_type;
5129+
if (context.current_class) {
5130+
if (context.type != GDScriptParser::REFACTOR_RENAME_TYPE_SUPER_METHOD) {
5131+
base_type = context.current_class->get_datatype();
5132+
} else {
5133+
base_type = context.current_class->base_type;
5134+
}
5135+
} else {
5136+
REFACTOR_RENAME_RETURN(ERR_CANT_RESOLVE);
5137+
}
5138+
5139+
if (context.identifier != nullptr) {
5140+
RefactorRenameSymbolDefinintionType enum_type = context.identifier_is_enum_value
5141+
? RefactorRenameSymbolDefinintionType::REFACTOR_RENAME_SYMBOL_DEFINITION_TYPE_ENUM_VALUE
5142+
: RefactorRenameSymbolDefinintionType::REFACTOR_RENAME_SYMBOL_DEFINITION_TYPE_ENUM;
5143+
print_line("refactor rename symbol enum");
5144+
Error enum_err = _refactor_rename_symbol_match_from_class(context, symbol, p_path, base_type.script_path, p_unsaved_scripts_source_code, r_result, enum_type, context.node);
5145+
REFACTOR_RENAME_RETURN(enum_err);
5146+
}
5147+
5148+
if (context.node->start_line == context.token.start_line && context.node->start_column == context.token.start_column) {
5149+
// The user tried to refactor the enum keyword.
5150+
REFACTOR_RENAME_OUTSIDE_GDSCRIPT(REFACTOR_RENAME_SYMBOL_RESULT_KEYWORD);
5151+
REFACTOR_RENAME_RETURN(OK);
5152+
}
5153+
5154+
// The user tried to refactor the enum braces.
5155+
REFACTOR_RENAME_OUTSIDE_GDSCRIPT(REFACTOR_RENAME_SYMBOL_RESULT_SYMBOL);
5156+
REFACTOR_RENAME_RETURN(OK);
5157+
} break;
50795158
default: {
5080-
// Do nothing.
5159+
REFACTOR_RENAME_RETURN(ERR_CANT_RESOLVE);
50815160
}
50825161
}
50835162

modules/gdscript/gdscript_parser.cpp

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -427,42 +427,69 @@ bool GDScriptParser::refactor_rename_is_node_more_specific(const GDScriptParser:
427427
return other_code_area.contains(node_code_area);
428428
}
429429

430-
bool GDScriptParser::refactor_rename_register(GDScriptParser::RefactorRenameType p_type, GDScriptParser::Node *p_node) {
430+
bool GDScriptParser::refactor_rename_register(GDScriptParser::RefactorRenameType p_type, GDScriptParser::Node *p_node, bool p_check_for_cursor) {
431431
if (!is_for_refactor_rename()) {
432432
return false;
433433
}
434-
if (!previous.has_cursor() && tokenizer->is_past_cursor()) {
435-
return false;
434+
if (p_check_for_cursor) {
435+
if (!previous.has_cursor() && tokenizer->is_past_cursor()) {
436+
return false;
437+
}
436438
}
437439

440+
GDScriptParser::Node *previous_node = refactor_rename_context.node;
441+
438442
RefactorRenameContext context;
439443
context.type = p_type;
440444
context.current_class = current_class;
441445
context.current_function = current_function;
442446
context.current_suite = current_suite;
443447
context.current_line = tokenizer->get_cursor_line();
444448
context.parser = this;
445-
if (refactor_rename_context.node == p_node) {
446-
context.token = refactor_rename_context.token;
447-
}
448449
context.node = p_node;
449-
context.value = nullptr;
450+
if (p_node == previous_node) {
451+
if (refactor_rename_context.token.has_cursor()) {
452+
context.token = refactor_rename_context.token;
453+
}
454+
context.identifier = refactor_rename_context.identifier;
455+
context.identifier_is_enum_value = refactor_rename_context.identifier_is_enum_value;
456+
context.literal = refactor_rename_context.literal;
457+
} else {
458+
context.identifier = nullptr;
459+
context.literal = nullptr;
460+
}
450461
if (previous.has_cursor()) {
451462
context.token = previous;
452463
}
453464
refactor_rename_context = context;
465+
454466
return true;
455467
}
456468

457-
bool GDScriptParser::refactor_rename_register_value(GDScriptParser::Node *p_value_node) {
469+
bool GDScriptParser::refactor_rename_register_identifier(GDScriptParser::IdentifierNode *p_identifier) {
458470
if (!is_for_refactor_rename()) {
459471
return false;
460472
}
461473
if (!previous.has_cursor()) {
462474
return false;
463475
}
464476
ERR_FAIL_NULL_V(refactor_rename_context.node, false);
465-
refactor_rename_context.value = p_value_node;
477+
refactor_rename_context.identifier = p_identifier;
478+
if (previous.has_cursor()) {
479+
refactor_rename_context.token = previous;
480+
}
481+
return true;
482+
}
483+
484+
bool GDScriptParser::refactor_rename_register_literal(GDScriptParser::LiteralNode *p_literal) {
485+
if (!is_for_refactor_rename()) {
486+
return false;
487+
}
488+
if (!previous.has_cursor()) {
489+
return false;
490+
}
491+
ERR_FAIL_NULL_V(refactor_rename_context.node, false);
492+
refactor_rename_context.literal = p_literal;
466493
if (previous.has_cursor()) {
467494
refactor_rename_context.token = previous;
468495
}
@@ -1611,8 +1638,14 @@ GDScriptParser::SignalNode *GDScriptParser::parse_signal(bool p_is_static) {
16111638
}
16121639

16131640
GDScriptParser::EnumNode *GDScriptParser::parse_enum(bool p_is_static) {
1641+
GDScriptTokenizer::Token enum_start = previous;
1642+
16141643
EnumNode *enum_node = alloc_node<EnumNode>();
1615-
refactor_rename_register(REFACTOR_RENAME_TYPE_ENUM, enum_node);
1644+
if (is_for_refactor_rename()) {
1645+
if (previous.has_cursor() || current.has_cursor() || !tokenizer->is_past_cursor()) {
1646+
refactor_rename_register(REFACTOR_RENAME_TYPE_ENUM, enum_node, false);
1647+
}
1648+
}
16161649
bool named = false;
16171650

16181651
if (match(GDScriptTokenizer::Token::IDENTIFIER)) {
@@ -1639,6 +1672,9 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum(bool p_is_static) {
16391672
}
16401673
if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for enum key.)")) {
16411674
GDScriptParser::IdentifierNode *identifier = parse_identifier();
1675+
if (is_for_refactor_rename() && refactor_rename_context.identifier == identifier) {
1676+
refactor_rename_context.identifier_is_enum_value = true;
1677+
}
16421678

16431679
EnumNode::Value item;
16441680
item.identifier = identifier;
@@ -1705,6 +1741,16 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum(bool p_is_static) {
17051741
consume(GDScriptTokenizer::Token::BRACE_CLOSE, R"(Expected closing "}" for enum.)");
17061742
complete_extents(enum_node);
17071743
end_statement("enum");
1744+
1745+
GDScriptTokenizer::Token enum_end = previous;
1746+
1747+
if (is_for_refactor_rename()) {
1748+
GDScriptTokenizer::CodeArea enum_code_area(enum_start.get_code_area().start, enum_end.get_code_area().end);
1749+
if (enum_code_area.contains(GDScriptTokenizer::LineColumn(tokenizer->get_cursor_line(), tokenizer->get_cursor_column()))) {
1750+
refactor_rename_register(REFACTOR_RENAME_TYPE_ENUM, enum_node, false);
1751+
}
1752+
}
1753+
17081754
return enum_node;
17091755
}
17101756

@@ -2864,7 +2910,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_identifier(ExpressionNode
28642910
ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing identifier node without identifier token.");
28652911
}
28662912
IdentifierNode *identifier = alloc_node<IdentifierNode>();
2867-
refactor_rename_register_value(identifier);
2913+
refactor_rename_register_identifier(identifier);
28682914
complete_extents(identifier);
28692915

28702916
identifier->name = previous.get_identifier();
@@ -2922,7 +2968,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_literal(ExpressionNode *p_
29222968
}
29232969

29242970
LiteralNode *literal = alloc_node<LiteralNode>();
2925-
refactor_rename_register_value(literal);
2971+
refactor_rename_register_literal(literal);
29262972
literal->value = previous.literal;
29272973
reset_extents(literal, p_previous_operand);
29282974
update_extents(literal);

modules/gdscript/gdscript_parser.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,8 +1799,10 @@ class GDScriptParser {
17991799

18001800
struct RefactorRenameContext : ParsingContext {
18011801
RefactorRenameType type = REFACTOR_RENAME_TYPE_NONE;
1802-
GDScriptParser::Node *value = nullptr;
1802+
GDScriptParser::IdentifierNode *identifier = nullptr;
1803+
GDScriptParser::LiteralNode *literal = nullptr;
18031804
GDScriptTokenizer::Token token;
1805+
bool identifier_is_enum_value = false;
18041806
};
18051807

18061808
private:
@@ -1984,8 +1986,9 @@ class GDScriptParser {
19841986
bool refactor_rename_does_token_have_cursor(const GDScriptTokenizer::Token &p_token) const;
19851987
bool refactor_rename_was_cursor_just_parsed() const;
19861988
bool refactor_rename_is_node_more_specific(const GDScriptParser::Node *p_node) const;
1987-
bool refactor_rename_register(GDScriptParser::RefactorRenameType p_type, GDScriptParser::Node *p_node);
1988-
bool refactor_rename_register_value(GDScriptParser::Node *p_node);
1989+
bool refactor_rename_register(GDScriptParser::RefactorRenameType p_type, GDScriptParser::Node *p_node, bool p_check_for_cursor = true);
1990+
bool refactor_rename_register_identifier(GDScriptParser::IdentifierNode *p_node);
1991+
bool refactor_rename_register_literal(GDScriptParser::LiteralNode *p_node);
19891992

19901993
GDScriptTokenizer::Token advance();
19911994
bool match(GDScriptTokenizer::Token::Type p_token_type);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
class_name ClassCisB
22
extends B
33

4+
const EnumClass = preload("enum.gd")
5+
6+
47
static func get_new_me() -> ClassCisB:
58
return ClassCisB.new()
9+
10+
11+
func _ready() -> void:
12+
print(EnumClass.ENUM_VALUE_1.ENUM_VALUE_1)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
enum ENUM_VALUE_1 {
2+
ENUM_VALUE_1,
3+
ENUM_VALUE_2
4+
}
5+
6+
7+
func _ready() -> void:
8+
print(ENUM_VALUE_1.ENUM_VALUE_1)

0 commit comments

Comments
 (0)