|
@@ -1973,8 +1973,6 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
|
|
|
if (p_is_local) {
|
|
|
if (p_variable->usages == 0 && !String(p_variable->identifier->name).begins_with("_")) {
|
|
|
parser->push_warning(p_variable, GDScriptWarning::UNUSED_VARIABLE, p_variable->identifier->name);
|
|
|
- } else if (p_variable->assignments == 0) {
|
|
|
- parser->push_warning(p_variable, GDScriptWarning::UNASSIGNED_VARIABLE, p_variable->identifier->name);
|
|
|
}
|
|
|
}
|
|
|
is_shadowing(p_variable->identifier, kind, p_is_local);
|
|
@@ -2615,9 +2613,21 @@ void GDScriptAnalyzer::update_array_literal_element_type(GDScriptParser::ArrayNo
|
|
|
}
|
|
|
|
|
|
void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assignment) {
|
|
|
- reduce_expression(p_assignment->assignee);
|
|
|
reduce_expression(p_assignment->assigned_value);
|
|
|
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ // Increment assignment count for local variables.
|
|
|
+ // Before we reduce the assignee because we don't want to warn about not being assigned when performing the assignment.
|
|
|
+ if (p_assignment->assignee->type == GDScriptParser::Node::IDENTIFIER) {
|
|
|
+ GDScriptParser::IdentifierNode *id = static_cast<GDScriptParser::IdentifierNode *>(p_assignment->assignee);
|
|
|
+ if (id->source == GDScriptParser::IdentifierNode::LOCAL_VARIABLE && id->variable_source) {
|
|
|
+ id->variable_source->assignments++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ reduce_expression(p_assignment->assignee);
|
|
|
+
|
|
|
if (p_assignment->assigned_value == nullptr || p_assignment->assignee == nullptr) {
|
|
|
return;
|
|
|
}
|
|
@@ -2754,6 +2764,14 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
|
|
|
if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) {
|
|
|
parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION);
|
|
|
}
|
|
|
+ // Check for assignment with operation before assignment.
|
|
|
+ if (p_assignment->operation != GDScriptParser::AssignmentNode::OP_NONE && p_assignment->assignee->type == GDScriptParser::Node::IDENTIFIER) {
|
|
|
+ GDScriptParser::IdentifierNode *id = static_cast<GDScriptParser::IdentifierNode *>(p_assignment->assignee);
|
|
|
+ // Use == 1 here because this assignment was already counted in the beginning of the function.
|
|
|
+ if (id->source == GDScriptParser::IdentifierNode::LOCAL_VARIABLE && id->variable_source && id->variable_source->assignments == 1) {
|
|
|
+ parser->push_warning(p_assignment, GDScriptWarning::UNASSIGNED_VARIABLE_OP_ASSIGN, id->name);
|
|
|
+ }
|
|
|
+ }
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -3926,6 +3944,11 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
|
|
|
case GDScriptParser::IdentifierNode::LOCAL_VARIABLE:
|
|
|
p_identifier->set_datatype(p_identifier->variable_source->get_datatype());
|
|
|
found_source = true;
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ if (p_identifier->variable_source && p_identifier->variable_source->assignments == 0 && !(p_identifier->get_datatype().is_hard_type() && p_identifier->get_datatype().kind == GDScriptParser::DataType::BUILTIN)) {
|
|
|
+ parser->push_warning(p_identifier, GDScriptWarning::UNASSIGNED_VARIABLE, p_identifier->name);
|
|
|
+ }
|
|
|
+#endif
|
|
|
break;
|
|
|
case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
|
|
|
p_identifier->set_datatype(p_identifier->bind_source->get_datatype());
|