Skip to content

Commit

Permalink
Merge pull request #74842 from vonagam/fix-builtin-shadow
Browse files Browse the repository at this point in the history
GDScript: Fix missing warning for shadowing of built-in types
  • Loading branch information
YuriSizov authored Mar 20, 2023
2 parents 05d373c + 703274f commit a5f3474
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 14 deletions.
28 changes: 15 additions & 13 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4778,7 +4778,7 @@ void GDScriptAnalyzer::validate_call_arg(const List<GDScriptParser::DataType> &p
}

#ifdef DEBUG_ENABLED
bool GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_local, const String &p_context) {
void GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_local, const String &p_context) {
const StringName &name = p_local->name;
GDScriptParser::DataType base = parser->current_class->get_datatype();
GDScriptParser::ClassNode *base_class = base.class_type;
Expand All @@ -4790,50 +4790,52 @@ bool GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_local, con
for (MethodInfo &info : gdscript_funcs) {
if (info.name == name) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function");
return true;
return;
}
}

if (Variant::has_utility_function(name)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function");
return true;
return;
} else if (ClassDB::class_exists(name)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "global class");
return true;
return;
} else if (GDScriptParser::get_builtin_type(name) != Variant::VARIANT_MAX) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in type");
return;
}
}

while (base_class != nullptr) {
if (base_class->has_member(name)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE, p_context, p_local->name, base_class->get_member(name).get_type_name(), itos(base_class->get_member(name).get_line()));
return true;
return;
}
base_class = base_class->base_type.class_type;
}

StringName parent = base.native_type;
while (parent != StringName()) {
ERR_FAIL_COND_V_MSG(!class_exists(parent), false, "Non-existent native base class.");
ERR_FAIL_COND_MSG(!class_exists(parent), "Non-existent native base class.");

if (ClassDB::has_method(parent, name, true)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_local->name, "method", parent);
return true;
return;
} else if (ClassDB::has_signal(parent, name, true)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_local->name, "signal", parent);
return true;
return;
} else if (ClassDB::has_property(parent, name, true)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_local->name, "property", parent);
return true;
return;
} else if (ClassDB::has_integer_constant(parent, name, true)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_local->name, "constant", parent);
return true;
return;
} else if (ClassDB::has_enum(parent, name, true)) {
parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_local->name, "enum", parent);
return true;
return;
}
parent = ClassDB::get_parent_class(parent);
}

return false;
}
#endif

Expand Down
2 changes: 1 addition & 1 deletion modules/gdscript/gdscript_analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class GDScriptAnalyzer {
Ref<GDScriptParserRef> get_parser_for(const String &p_path);
void reduce_identifier_from_base_set_class(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType p_identifier_datatype);
#ifdef DEBUG_ENABLED
bool is_shadowing(GDScriptParser::IdentifierNode *p_local, const String &p_context);
void is_shadowing(GDScriptParser::IdentifierNode *p_local, const String &p_context);
#endif

public:
Expand Down
12 changes: 12 additions & 0 deletions modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var member: int = 0

@warning_ignore("unused_variable")
func test():
var Array := 'Array'
var Node := 'Node'
var is_same := 'is_same'
var sqrt := 'sqrt'
var member := 'member'
var reference := 'reference'

print('warn')
26 changes: 26 additions & 0 deletions modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
GDTEST_OK
>> WARNING
>> Line: 5
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable 'Array' has the same name as a built-in type.
>> WARNING
>> Line: 6
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable 'Node' has the same name as a global class.
>> WARNING
>> Line: 7
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable 'is_same' has the same name as a built-in function.
>> WARNING
>> Line: 8
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable 'sqrt' has the same name as a built-in function.
>> WARNING
>> Line: 9
>> SHADOWED_VARIABLE
>> The local variable "member" is shadowing an already-declared variable at line 1.
>> WARNING
>> Line: 10
>> SHADOWED_VARIABLE_BASE_CLASS
>> The local variable "reference" is shadowing an already-declared method at the base class "RefCounted".
warn

0 comments on commit a5f3474

Please sign in to comment.