| 2440 | } |
| 2441 | |
| 2442 | void GDScriptAnalyzer::resolve_match_pattern(GDScriptParser::PatternNode *p_match_pattern, GDScriptParser::ExpressionNode *p_match_test) { |
| 2443 | if (p_match_pattern == nullptr) { |
| 2444 | return; |
| 2445 | } |
| 2446 | |
| 2447 | GDScriptParser::DataType result; |
| 2448 | |
| 2449 | switch (p_match_pattern->pattern_type) { |
| 2450 | case GDScriptParser::PatternNode::PT_LITERAL: |
| 2451 | if (p_match_pattern->literal) { |
| 2452 | reduce_literal(p_match_pattern->literal); |
| 2453 | result = p_match_pattern->literal->get_datatype(); |
| 2454 | } |
| 2455 | break; |
| 2456 | case GDScriptParser::PatternNode::PT_EXPRESSION: |
| 2457 | if (p_match_pattern->expression) { |
| 2458 | GDScriptParser::ExpressionNode *expr = p_match_pattern->expression; |
| 2459 | reduce_expression(expr); |
| 2460 | result = expr->get_datatype(); |
| 2461 | if (!expr->is_constant) { |
| 2462 | while (expr && expr->type == GDScriptParser::Node::SUBSCRIPT) { |
| 2463 | GDScriptParser::SubscriptNode *sub = static_cast<GDScriptParser::SubscriptNode *>(expr); |
| 2464 | if (!sub->is_attribute) { |
| 2465 | expr = nullptr; |
| 2466 | } else { |
| 2467 | expr = sub->base; |
| 2468 | } |
| 2469 | } |
| 2470 | if (!expr || expr->type != GDScriptParser::Node::IDENTIFIER) { |
| 2471 | push_error(R"(Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").)", expr); |
| 2472 | } |
| 2473 | } |
| 2474 | } |
| 2475 | break; |
| 2476 | case GDScriptParser::PatternNode::PT_BIND: |
| 2477 | if (p_match_test != nullptr) { |
| 2478 | result = p_match_test->get_datatype(); |
| 2479 | } else { |
| 2480 | result.kind = GDScriptParser::DataType::VARIANT; |
| 2481 | } |
| 2482 | p_match_pattern->bind->set_datatype(result); |
| 2483 | #ifdef DEBUG_ENABLED |
| 2484 | is_shadowing(p_match_pattern->bind, "pattern bind", true); |
| 2485 | if (p_match_pattern->bind->usages == 0 && !String(p_match_pattern->bind->name).begins_with("_")) { |
| 2486 | parser->push_warning(p_match_pattern->bind, GDScriptWarning::UNUSED_VARIABLE, p_match_pattern->bind->name); |
| 2487 | } |
| 2488 | #endif // DEBUG_ENABLED |
| 2489 | break; |
| 2490 | case GDScriptParser::PatternNode::PT_ARRAY: |
| 2491 | for (int i = 0; i < p_match_pattern->array.size(); i++) { |
| 2492 | resolve_match_pattern(p_match_pattern->array[i], nullptr); |
| 2493 | decide_suite_type(p_match_pattern, p_match_pattern->array[i]); |
| 2494 | } |
| 2495 | result = p_match_pattern->get_datatype(); |
| 2496 | break; |
| 2497 | case GDScriptParser::PatternNode::PT_DICTIONARY: |
| 2498 | for (int i = 0; i < p_match_pattern->dictionary.size(); i++) { |
| 2499 | if (p_match_pattern->dictionary[i].key) { |
nothing calls this directly
no test coverage detected