mirror of
https://github.com/godotengine/godot.git
synced 2025-01-23 11:03:13 -05:00
Fixing null callee crash.
This commit is contained in:
parent
6831da630f
commit
8a13be50ab
4 changed files with 30 additions and 15 deletions
|
@ -872,7 +872,8 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
|
||||||
// Use int, Vector2, Vector3 instead, which also can be used as range iterators.
|
// Use int, Vector2, Vector3 instead, which also can be used as range iterators.
|
||||||
if (p_for->list && p_for->list->type == GDScriptParser::Node::CALL) {
|
if (p_for->list && p_for->list->type == GDScriptParser::Node::CALL) {
|
||||||
GDScriptParser::CallNode *call = static_cast<GDScriptParser::CallNode *>(p_for->list);
|
GDScriptParser::CallNode *call = static_cast<GDScriptParser::CallNode *>(p_for->list);
|
||||||
if (call->callee->type == GDScriptParser::Node::IDENTIFIER) {
|
GDScriptParser::Node::Type callee_type = call->get_callee_type();
|
||||||
|
if (callee_type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
GDScriptParser::IdentifierNode *callee = static_cast<GDScriptParser::IdentifierNode *>(call->callee);
|
GDScriptParser::IdentifierNode *callee = static_cast<GDScriptParser::IdentifierNode *>(call->callee);
|
||||||
if (callee->name == "range") {
|
if (callee->name == "range") {
|
||||||
list_resolved = true;
|
list_resolved = true;
|
||||||
|
@ -1608,9 +1609,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
|
||||||
all_is_constant = all_is_constant && p_call->arguments[i]->is_constant;
|
all_is_constant = all_is_constant && p_call->arguments[i]->is_constant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GDScriptParser::Node::Type callee_type = p_call->get_callee_type();
|
||||||
GDScriptParser::DataType call_type;
|
GDScriptParser::DataType call_type;
|
||||||
|
|
||||||
if (!p_call->is_super && p_call->callee->type == GDScriptParser::Node::IDENTIFIER) {
|
if (!p_call->is_super && callee_type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
// Call to name directly.
|
// Call to name directly.
|
||||||
StringName function_name = p_call->function_name;
|
StringName function_name = p_call->function_name;
|
||||||
Variant::Type builtin_type = GDScriptParser::get_builtin_type(function_name);
|
Variant::Type builtin_type = GDScriptParser::get_builtin_type(function_name);
|
||||||
|
@ -1785,10 +1787,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
|
||||||
if (p_call->is_super) {
|
if (p_call->is_super) {
|
||||||
base_type = parser->current_class->base_type;
|
base_type = parser->current_class->base_type;
|
||||||
is_self = true;
|
is_self = true;
|
||||||
} else if (p_call->callee->type == GDScriptParser::Node::IDENTIFIER) {
|
} else if (callee_type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
base_type = parser->current_class->get_datatype();
|
base_type = parser->current_class->get_datatype();
|
||||||
is_self = true;
|
is_self = true;
|
||||||
} else if (p_call->callee->type == GDScriptParser::Node::SUBSCRIPT) {
|
} else if (callee_type == GDScriptParser::Node::SUBSCRIPT) {
|
||||||
GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee);
|
GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee);
|
||||||
if (!subscript->is_attribute) {
|
if (!subscript->is_attribute) {
|
||||||
// Invalid call. Error already sent in parser.
|
// Invalid call. Error already sent in parser.
|
||||||
|
@ -1825,9 +1827,9 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
|
||||||
} else {
|
} else {
|
||||||
// Check if the name exists as something else.
|
// Check if the name exists as something else.
|
||||||
bool found = false;
|
bool found = false;
|
||||||
if (!p_call->is_super) {
|
if (!p_call->is_super && callee_type != GDScriptParser::Node::NONE) {
|
||||||
GDScriptParser::IdentifierNode *callee_id;
|
GDScriptParser::IdentifierNode *callee_id;
|
||||||
if (p_call->callee->type == GDScriptParser::Node::IDENTIFIER) {
|
if (callee_type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
callee_id = static_cast<GDScriptParser::IdentifierNode *>(p_call->callee);
|
callee_id = static_cast<GDScriptParser::IdentifierNode *>(p_call->callee);
|
||||||
} else {
|
} else {
|
||||||
// Can only be attribute.
|
// Can only be attribute.
|
||||||
|
@ -1835,13 +1837,13 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
|
||||||
}
|
}
|
||||||
if (callee_id) {
|
if (callee_id) {
|
||||||
reduce_identifier_from_base(callee_id, &base_type);
|
reduce_identifier_from_base(callee_id, &base_type);
|
||||||
GDScriptParser::DataType callee_type = callee_id->get_datatype();
|
GDScriptParser::DataType callee_datatype = callee_id->get_datatype();
|
||||||
if (callee_type.is_set() && !callee_type.is_variant()) {
|
if (callee_datatype.is_set() && !callee_datatype.is_variant()) {
|
||||||
found = true;
|
found = true;
|
||||||
if (callee_type.builtin_type == Variant::CALLABLE) {
|
if (callee_datatype.builtin_type == Variant::CALLABLE) {
|
||||||
push_error(vformat(R"*(Name "%s" is a Callable. You can call it with "%s.call()" instead.)*", p_call->function_name, p_call->function_name), p_call->callee);
|
push_error(vformat(R"*(Name "%s" is a Callable. You can call it with "%s.call()" instead.)*", p_call->function_name, p_call->function_name), p_call->callee);
|
||||||
} else {
|
} else {
|
||||||
push_error(vformat(R"*(Name "%s" called as a function but is a "%s".)*", p_call->function_name, callee_type.to_string()), p_call->callee);
|
push_error(vformat(R"*(Name "%s" called as a function but is a "%s".)*", p_call->function_name, callee_datatype.to_string()), p_call->callee);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
} else if (!is_self) {
|
} else if (!is_self) {
|
||||||
|
|
|
@ -1259,8 +1259,10 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
|
||||||
GDScriptParser::CompletionContext c = p_context;
|
GDScriptParser::CompletionContext c = p_context;
|
||||||
c.current_line = call->start_line;
|
c.current_line = call->start_line;
|
||||||
|
|
||||||
|
GDScriptParser::Node::Type callee_type = call->get_callee_type();
|
||||||
|
|
||||||
GDScriptCompletionIdentifier base;
|
GDScriptCompletionIdentifier base;
|
||||||
if (call->callee->type == GDScriptParser::Node::IDENTIFIER || call->is_super) {
|
if (callee_type == GDScriptParser::Node::IDENTIFIER || call->is_super) {
|
||||||
// Simple call, so base is 'self'.
|
// Simple call, so base is 'self'.
|
||||||
if (p_context.current_class) {
|
if (p_context.current_class) {
|
||||||
base.type.kind = GDScriptParser::DataType::CLASS;
|
base.type.kind = GDScriptParser::DataType::CLASS;
|
||||||
|
@ -1271,7 +1273,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (call->callee->type == GDScriptParser::Node::SUBSCRIPT && static_cast<const GDScriptParser::SubscriptNode *>(call->callee)->is_attribute) {
|
} else if (callee_type == GDScriptParser::Node::SUBSCRIPT && static_cast<const GDScriptParser::SubscriptNode *>(call->callee)->is_attribute) {
|
||||||
if (!_guess_expression_type(c, static_cast<const GDScriptParser::SubscriptNode *>(call->callee)->base, base)) {
|
if (!_guess_expression_type(c, static_cast<const GDScriptParser::SubscriptNode *>(call->callee)->base, base)) {
|
||||||
found = false;
|
found = false;
|
||||||
break;
|
break;
|
||||||
|
@ -2290,6 +2292,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
||||||
GDScriptParser::DataType base_type;
|
GDScriptParser::DataType base_type;
|
||||||
bool _static = false;
|
bool _static = false;
|
||||||
const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(p_call);
|
const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(p_call);
|
||||||
|
GDScriptParser::Node::Type callee_type = GDScriptParser::Node::NONE;
|
||||||
|
|
||||||
GDScriptCompletionIdentifier connect_base;
|
GDScriptCompletionIdentifier connect_base;
|
||||||
|
|
||||||
|
@ -2319,14 +2322,14 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (call->is_super || call->callee->type == GDScriptParser::Node::IDENTIFIER) {
|
} else if (call->is_super || callee_type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
base = p_context.base;
|
base = p_context.base;
|
||||||
|
|
||||||
if (p_context.current_class) {
|
if (p_context.current_class) {
|
||||||
base_type = p_context.current_class->get_datatype();
|
base_type = p_context.current_class->get_datatype();
|
||||||
_static = !p_context.current_function || p_context.current_function->is_static;
|
_static = !p_context.current_function || p_context.current_function->is_static;
|
||||||
}
|
}
|
||||||
} else if (call->callee->type == GDScriptParser::Node::SUBSCRIPT) {
|
} else if (callee_type == GDScriptParser::Node::SUBSCRIPT) {
|
||||||
const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(call->callee);
|
const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(call->callee);
|
||||||
|
|
||||||
if (subscript->is_attribute) {
|
if (subscript->is_attribute) {
|
||||||
|
|
|
@ -2419,7 +2419,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
|
||||||
} else {
|
} else {
|
||||||
call->callee = p_previous_operand;
|
call->callee = p_previous_operand;
|
||||||
|
|
||||||
if (call->callee->type == Node::IDENTIFIER) {
|
if (call->callee == nullptr) {
|
||||||
|
push_error(R"*(Cannot call on an expression. Use ".call()" if it's a Callable.)*");
|
||||||
|
} else if (call->callee->type == Node::IDENTIFIER) {
|
||||||
call->function_name = static_cast<IdentifierNode *>(call->callee)->name;
|
call->function_name = static_cast<IdentifierNode *>(call->callee)->name;
|
||||||
make_completion_context(COMPLETION_METHOD, call->callee);
|
make_completion_context(COMPLETION_METHOD, call->callee);
|
||||||
} else if (call->callee->type == Node::SUBSCRIPT) {
|
} else if (call->callee->type == Node::SUBSCRIPT) {
|
||||||
|
|
|
@ -383,6 +383,14 @@ public:
|
||||||
CallNode() {
|
CallNode() {
|
||||||
type = CALL;
|
type = CALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type get_callee_type() const {
|
||||||
|
if (callee == nullptr) {
|
||||||
|
return Type::NONE;
|
||||||
|
} else {
|
||||||
|
return callee->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CastNode : public ExpressionNode {
|
struct CastNode : public ExpressionNode {
|
||||||
|
|
Loading…
Add table
Reference in a new issue