| 1472 | } |
| 1473 | |
| 1474 | bool DeclarationBuilder::areTypesEqual(const AbstractType::Ptr& a, const AbstractType::Ptr& b) |
| 1475 | { |
| 1476 | if (!a || !b) { |
| 1477 | return true; |
| 1478 | } |
| 1479 | |
| 1480 | if (a->whichType() == AbstractType::TypeUnsure || b->whichType() == AbstractType::TypeUnsure) { |
| 1481 | // Don't try to guess something if one of the types is unsure |
| 1482 | return true; |
| 1483 | } |
| 1484 | |
| 1485 | const auto bIntegral = b.dynamicCast<IntegralType>(); |
| 1486 | if (bIntegral && (bIntegral->dataType() == IntegralType::TypeString || bIntegral->dataType() == IntegralType::TypeMixed)) { |
| 1487 | // In QML/JS, a string can be converted to nearly everything else, similarly ignore mixed types |
| 1488 | return true; |
| 1489 | } |
| 1490 | |
| 1491 | const auto aIntegral = a.dynamicCast<IntegralType>(); |
| 1492 | if (aIntegral && (aIntegral->dataType() == IntegralType::TypeString || aIntegral->dataType() == IntegralType::TypeMixed)) { |
| 1493 | // In QML/JS, nearly everything can be to a string, similarly ignore mixed types |
| 1494 | return true; |
| 1495 | } |
| 1496 | if (aIntegral && bIntegral) { |
| 1497 | if (isNumeric(aIntegral) && isNumeric(bIntegral)) { |
| 1498 | // Casts between integral types is possible |
| 1499 | return true; |
| 1500 | } |
| 1501 | } |
| 1502 | |
| 1503 | if (a->whichType() == AbstractType::TypeEnumeration && b->whichType() == AbstractType::TypeEnumerator) { |
| 1504 | return enumContainsEnumerator(a, b); |
| 1505 | } else if (a->whichType() == AbstractType::TypeEnumerator && b->whichType() == AbstractType::TypeEnumeration) { |
| 1506 | return enumContainsEnumerator(b, a); |
| 1507 | } |
| 1508 | |
| 1509 | { |
| 1510 | auto aId = dynamic_cast<const IdentifiedType*>(a.constData()); |
| 1511 | auto bId = dynamic_cast<const IdentifiedType*>(b.constData()); |
| 1512 | if (aId && bId && aId->qualifiedIdentifier() == bId->qualifiedIdentifier()) |
| 1513 | return true; |
| 1514 | } |
| 1515 | |
| 1516 | { |
| 1517 | auto aStruct = a.dynamicCast<StructureType>(); |
| 1518 | auto bStruct = b.dynamicCast<StructureType>(); |
| 1519 | if (aStruct && bStruct) { |
| 1520 | auto top = currentContext()->topContext(); |
| 1521 | auto aDecl = dynamic_cast<ClassDeclaration*>(aStruct->declaration(top)); |
| 1522 | auto bDecl = dynamic_cast<ClassDeclaration*>(bStruct->declaration(top)); |
| 1523 | if (aDecl && bDecl) { |
| 1524 | if (aDecl->isPublicBaseClass(bDecl, top) || bDecl->isPublicBaseClass(aDecl, top)) { |
| 1525 | return true; |
| 1526 | } |
| 1527 | } |
| 1528 | } |
| 1529 | } |
| 1530 | |
| 1531 | return a->equals(b.constData()); |
nothing calls this directly
no test coverage detected