| 1677 | } |
| 1678 | |
| 1679 | void GDScriptAnalyzer::resolve_annotation(GDScriptParser::AnnotationNode *p_annotation) { |
| 1680 | ERR_FAIL_COND_MSG(!parser->valid_annotations.has(p_annotation->name), vformat(R"(Annotation "%s" not found to validate.)", p_annotation->name)); |
| 1681 | |
| 1682 | if (p_annotation->is_resolved) { |
| 1683 | return; |
| 1684 | } |
| 1685 | p_annotation->is_resolved = true; |
| 1686 | |
| 1687 | const MethodInfo &annotation_info = parser->valid_annotations[p_annotation->name].info; |
| 1688 | |
| 1689 | for (int64_t i = 0, j = 0; i < p_annotation->arguments.size(); i++) { |
| 1690 | GDScriptParser::ExpressionNode *argument = p_annotation->arguments[i]; |
| 1691 | const PropertyInfo &argument_info = annotation_info.arguments[j]; |
| 1692 | |
| 1693 | if (j + 1 < annotation_info.arguments.size()) { |
| 1694 | ++j; |
| 1695 | } |
| 1696 | |
| 1697 | reduce_expression(argument); |
| 1698 | |
| 1699 | if (!argument->is_constant) { |
| 1700 | push_error(vformat(R"(Argument %d of annotation "%s" isn't a constant expression.)", i + 1, p_annotation->name), argument); |
| 1701 | return; |
| 1702 | } |
| 1703 | |
| 1704 | Variant value = argument->reduced_value; |
| 1705 | |
| 1706 | if (value.get_type() != argument_info.type) { |
| 1707 | #ifdef DEBUG_ENABLED |
| 1708 | if (argument_info.type == Variant::INT && value.get_type() == Variant::FLOAT) { |
| 1709 | parser->push_warning(argument, GDScriptWarning::NARROWING_CONVERSION); |
| 1710 | } |
| 1711 | #endif // DEBUG_ENABLED |
| 1712 | |
| 1713 | if (!Variant::can_convert_strict(value.get_type(), argument_info.type)) { |
| 1714 | push_error(vformat(R"(Invalid argument for annotation "%s": argument %d should be "%s" but is "%s".)", p_annotation->name, i + 1, Variant::get_type_name(argument_info.type), argument->get_datatype().to_string()), argument); |
| 1715 | return; |
| 1716 | } |
| 1717 | |
| 1718 | Variant converted_to; |
| 1719 | const Variant *converted_from = &value; |
| 1720 | Callable::CallError call_error; |
| 1721 | Variant::construct(argument_info.type, converted_to, &converted_from, 1, call_error); |
| 1722 | |
| 1723 | if (call_error.error != Callable::CallError::CALL_OK) { |
| 1724 | push_error(vformat(R"(Cannot convert argument %d of annotation "%s" from "%s" to "%s".)", i + 1, p_annotation->name, Variant::get_type_name(value.get_type()), Variant::get_type_name(argument_info.type)), argument); |
| 1725 | return; |
| 1726 | } |
| 1727 | |
| 1728 | value = converted_to; |
| 1729 | } |
| 1730 | |
| 1731 | p_annotation->resolved_arguments.push_back(value); |
| 1732 | } |
| 1733 | } |
| 1734 | |
| 1735 | void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *p_function, const GDScriptParser::Node *p_source, bool p_is_lambda) { |
| 1736 | if (p_source == nullptr) { |
nothing calls this directly
no test coverage detected