|
60 | 60 | #include <memory> |
61 | 61 |
|
62 | 62 | using namespace swift; |
| 63 | +using namespace importer; |
63 | 64 |
|
64 | 65 | // Commonly-used Clang classes. |
65 | 66 | using clang::CompilerInstance; |
@@ -1359,235 +1360,6 @@ ClangImporter::Implementation::exportName(Identifier name) { |
1359 | 1360 | return ident; |
1360 | 1361 | } |
1361 | 1362 |
|
1362 | | -/// \brief Returns the common prefix of two strings at camel-case word |
1363 | | -/// granularity. |
1364 | | -/// |
1365 | | -/// For example, given "NSFooBar" and "NSFooBas", returns "NSFoo" |
1366 | | -/// (not "NSFooBa"). The returned StringRef is a slice of the "a" argument. |
1367 | | -/// |
1368 | | -/// If either string has a non-identifier character immediately after the |
1369 | | -/// prefix, \p followedByNonIdentifier will be set to \c true. If both strings |
1370 | | -/// have identifier characters after the prefix, \p followedByNonIdentifier will |
1371 | | -/// be set to \c false. Otherwise, \p followedByNonIdentifier will not be |
1372 | | -/// changed from its initial value. |
1373 | | -/// |
1374 | | -/// This is used to derive the common prefix of enum constants so we can elide |
1375 | | -/// it from the Swift interface. |
1376 | | -static StringRef getCommonWordPrefix(StringRef a, StringRef b, |
1377 | | - bool &followedByNonIdentifier) { |
1378 | | - auto aWords = camel_case::getWords(a), bWords = camel_case::getWords(b); |
1379 | | - auto aI = aWords.begin(), aE = aWords.end(), |
1380 | | - bI = bWords.begin(), bE = bWords.end(); |
1381 | | - |
1382 | | - unsigned prevLength = 0; |
1383 | | - unsigned prefixLength = 0; |
1384 | | - for ( ; aI != aE && bI != bE; ++aI, ++bI) { |
1385 | | - if (*aI != *bI) { |
1386 | | - followedByNonIdentifier = false; |
1387 | | - break; |
1388 | | - } |
1389 | | - |
1390 | | - prevLength = prefixLength; |
1391 | | - prefixLength = aI.getPosition() + aI->size(); |
1392 | | - } |
1393 | | - |
1394 | | - // Avoid creating a prefix where the rest of the string starts with a number. |
1395 | | - if ((aI != aE && !Lexer::isIdentifier(*aI)) || |
1396 | | - (bI != bE && !Lexer::isIdentifier(*bI))) { |
1397 | | - followedByNonIdentifier = true; |
1398 | | - prefixLength = prevLength; |
1399 | | - } |
1400 | | - |
1401 | | - return a.slice(0, prefixLength); |
1402 | | -} |
1403 | | - |
1404 | | -/// Returns the common word-prefix of two strings, allowing the second string |
1405 | | -/// to be a common English plural form of the first. |
1406 | | -/// |
1407 | | -/// For example, given "NSProperty" and "NSProperties", the full "NSProperty" |
1408 | | -/// is returned. Given "NSMagicArmor" and "NSMagicArmory", only |
1409 | | -/// "NSMagic" is returned. |
1410 | | -/// |
1411 | | -/// The "-s", "-es", and "-ies" patterns cover every plural NS_OPTIONS name |
1412 | | -/// in Cocoa and Cocoa Touch. |
1413 | | -/// |
1414 | | -/// \see getCommonWordPrefix |
1415 | | -static StringRef getCommonPluralPrefix(StringRef singular, StringRef plural) { |
1416 | | - assert(!plural.empty()); |
1417 | | - |
1418 | | - if (singular.empty()) |
1419 | | - return singular; |
1420 | | - |
1421 | | - bool ignored; |
1422 | | - StringRef commonPrefix = getCommonWordPrefix(singular, plural, ignored); |
1423 | | - if (commonPrefix.size() == singular.size() || plural.back() != 's') |
1424 | | - return commonPrefix; |
1425 | | - |
1426 | | - StringRef leftover = singular.substr(commonPrefix.size()); |
1427 | | - StringRef firstLeftoverWord = camel_case::getFirstWord(leftover); |
1428 | | - StringRef commonPrefixPlusWord = |
1429 | | - singular.substr(0, commonPrefix.size() + firstLeftoverWord.size()); |
1430 | | - |
1431 | | - // Is the plural string just "[singular]s"? |
1432 | | - plural = plural.drop_back(); |
1433 | | - if (plural.endswith(firstLeftoverWord)) |
1434 | | - return commonPrefixPlusWord; |
1435 | | - |
1436 | | - if (plural.empty() || plural.back() != 'e') |
1437 | | - return commonPrefix; |
1438 | | - |
1439 | | - // Is the plural string "[singular]es"? |
1440 | | - plural = plural.drop_back(); |
1441 | | - if (plural.endswith(firstLeftoverWord)) |
1442 | | - return commonPrefixPlusWord; |
1443 | | - |
1444 | | - if (plural.empty() || !(plural.back() == 'i' && singular.back() == 'y')) |
1445 | | - return commonPrefix; |
1446 | | - |
1447 | | - // Is the plural string "[prefix]ies" and the singular "[prefix]y"? |
1448 | | - plural = plural.drop_back(); |
1449 | | - firstLeftoverWord = firstLeftoverWord.drop_back(); |
1450 | | - if (plural.endswith(firstLeftoverWord)) |
1451 | | - return commonPrefixPlusWord; |
1452 | | - |
1453 | | - return commonPrefix; |
1454 | | -} |
1455 | | - |
1456 | | -StringRef ClangImporter::Implementation::getEnumConstantNamePrefix( |
1457 | | - clang::Sema &sema, |
1458 | | - const clang::EnumDecl *decl) { |
1459 | | - switch (classifyEnum(sema.getPreprocessor(), decl)) { |
1460 | | - case EnumKind::Enum: |
1461 | | - case EnumKind::Options: |
1462 | | - // Enums are mapped to Swift enums, Options to Swift option sets, both |
1463 | | - // of which attempt prefix-stripping. |
1464 | | - break; |
1465 | | - |
1466 | | - case EnumKind::Constants: |
1467 | | - case EnumKind::Unknown: |
1468 | | - // Nothing to do. |
1469 | | - return StringRef(); |
1470 | | - } |
1471 | | - |
1472 | | - // If there are no enumers, there is no prefix to compute. |
1473 | | - auto ec = decl->enumerator_begin(), ecEnd = decl->enumerator_end(); |
1474 | | - if (ec == ecEnd) |
1475 | | - return StringRef(); |
1476 | | - |
1477 | | - // Determine whether we can cache the result. |
1478 | | - // FIXME: Pass in a cache? |
1479 | | - bool useCache = &sema == &getClangSema(); |
1480 | | - |
1481 | | - // If we've already computed the prefix, return it. |
1482 | | - auto known = useCache ? EnumConstantNamePrefixes.find(decl) |
1483 | | - : EnumConstantNamePrefixes.end(); |
1484 | | - if (known != EnumConstantNamePrefixes.end()) |
1485 | | - return known->second; |
1486 | | - |
1487 | | - // Determine whether the given enumerator is non-deprecated and has no |
1488 | | - // specifically-provided name. |
1489 | | - auto isNonDeprecatedWithoutCustomName = |
1490 | | - [](const clang::EnumConstantDecl *elem) -> bool { |
1491 | | - if (elem->hasAttr<clang::SwiftNameAttr>()) |
1492 | | - return false; |
1493 | | - |
1494 | | - clang::VersionTuple maxVersion{~0U, ~0U, ~0U}; |
1495 | | - switch (elem->getAvailability(nullptr, maxVersion)) { |
1496 | | - case clang::AR_Available: |
1497 | | - case clang::AR_NotYetIntroduced: |
1498 | | - for (auto attr : elem->attrs()) { |
1499 | | - if (auto annotate = dyn_cast<clang::AnnotateAttr>(attr)) { |
1500 | | - if (annotate->getAnnotation() == "swift1_unavailable") |
1501 | | - return false; |
1502 | | - } |
1503 | | - if (auto avail = dyn_cast<clang::AvailabilityAttr>(attr)) { |
1504 | | - if (avail->getPlatform()->getName() == "swift") |
1505 | | - return false; |
1506 | | - } |
1507 | | - } |
1508 | | - return true; |
1509 | | - |
1510 | | - case clang::AR_Deprecated: |
1511 | | - case clang::AR_Unavailable: |
1512 | | - return false; |
1513 | | - } |
1514 | | - }; |
1515 | | - |
1516 | | - // Move to the first non-deprecated enumerator, or non-swift_name'd |
1517 | | - // enumerator, if present. |
1518 | | - auto firstNonDeprecated = std::find_if(ec, ecEnd, |
1519 | | - isNonDeprecatedWithoutCustomName); |
1520 | | - bool hasNonDeprecated = (firstNonDeprecated != ecEnd); |
1521 | | - if (hasNonDeprecated) { |
1522 | | - ec = firstNonDeprecated; |
1523 | | - } else { |
1524 | | - // Advance to the first case without a custom name, deprecated or not. |
1525 | | - while (ec != ecEnd && (*ec)->hasAttr<clang::SwiftNameAttr>()) |
1526 | | - ++ec; |
1527 | | - if (ec == ecEnd) { |
1528 | | - if (useCache) |
1529 | | - EnumConstantNamePrefixes.insert({decl, StringRef()}); |
1530 | | - return StringRef(); |
1531 | | - } |
1532 | | - } |
1533 | | - |
1534 | | - // Compute the common prefix. |
1535 | | - StringRef commonPrefix = (*ec)->getName(); |
1536 | | - bool followedByNonIdentifier = false; |
1537 | | - for (++ec; ec != ecEnd; ++ec) { |
1538 | | - // Skip deprecated or swift_name'd enumerators. |
1539 | | - const clang::EnumConstantDecl *elem = *ec; |
1540 | | - if (hasNonDeprecated) { |
1541 | | - if (!isNonDeprecatedWithoutCustomName(elem)) |
1542 | | - continue; |
1543 | | - } else { |
1544 | | - if (elem->hasAttr<clang::SwiftNameAttr>()) |
1545 | | - continue; |
1546 | | - } |
1547 | | - |
1548 | | - commonPrefix = getCommonWordPrefix(commonPrefix, elem->getName(), |
1549 | | - followedByNonIdentifier); |
1550 | | - if (commonPrefix.empty()) |
1551 | | - break; |
1552 | | - } |
1553 | | - |
1554 | | - if (!commonPrefix.empty()) { |
1555 | | - StringRef checkPrefix = commonPrefix; |
1556 | | - |
1557 | | - // Account for the 'kConstant' naming convention on enumerators. |
1558 | | - if (checkPrefix[0] == 'k') { |
1559 | | - bool canDropK; |
1560 | | - if (checkPrefix.size() >= 2) |
1561 | | - canDropK = clang::isUppercase(checkPrefix[1]); |
1562 | | - else |
1563 | | - canDropK = !followedByNonIdentifier; |
1564 | | - |
1565 | | - if (canDropK) |
1566 | | - checkPrefix = checkPrefix.drop_front(); |
1567 | | - } |
1568 | | - |
1569 | | - // Don't use importFullName() here, we want to ignore the swift_name |
1570 | | - // and swift_private attributes. |
1571 | | - StringRef enumNameStr = decl->getName(); |
1572 | | - StringRef commonWithEnum = getCommonPluralPrefix(checkPrefix, |
1573 | | - enumNameStr); |
1574 | | - size_t delta = commonPrefix.size() - checkPrefix.size(); |
1575 | | - |
1576 | | - // Account for the 'EnumName_Constant' convention on enumerators. |
1577 | | - if (commonWithEnum.size() < checkPrefix.size() && |
1578 | | - checkPrefix[commonWithEnum.size()] == '_' && |
1579 | | - !followedByNonIdentifier) { |
1580 | | - delta += 1; |
1581 | | - } |
1582 | | - |
1583 | | - commonPrefix = commonPrefix.slice(0, commonWithEnum.size() + delta); |
1584 | | - } |
1585 | | - |
1586 | | - if (useCache) |
1587 | | - EnumConstantNamePrefixes.insert({decl, commonPrefix}); |
1588 | | - return commonPrefix; |
1589 | | -} |
1590 | | - |
1591 | 1363 | /// Determine whether the given Clang selector matches the given |
1592 | 1364 | /// selector pieces. |
1593 | 1365 | static bool isNonNullarySelector(clang::Selector selector, |
@@ -2038,7 +1810,7 @@ auto ClangImporter::Implementation::importFullName( |
2038 | 1810 | // scope, depending how their enclosing enumeration is imported. |
2039 | 1811 | if (isa<clang::EnumConstantDecl>(D)) { |
2040 | 1812 | auto enumDecl = cast<clang::EnumDecl>(dc); |
2041 | | - switch (classifyEnum(clangSema.getPreprocessor(), enumDecl)) { |
| 1813 | + switch (getEnumKind(enumDecl, &clangSema.getPreprocessor())) { |
2042 | 1814 | case EnumKind::Enum: |
2043 | 1815 | case EnumKind::Options: |
2044 | 1816 | // Enums are mapped to Swift enums, Options to Swift option sets. |
@@ -2289,7 +2061,8 @@ auto ClangImporter::Implementation::importFullName( |
2289 | 2061 | // Enumeration constants may have common prefixes stripped. |
2290 | 2062 | if (isa<clang::EnumConstantDecl>(D)) { |
2291 | 2063 | auto enumDecl = cast<clang::EnumDecl>(D->getDeclContext()); |
2292 | | - StringRef removePrefix = getEnumConstantNamePrefix(clangSema, enumDecl); |
| 2064 | + StringRef removePrefix = |
| 2065 | + getEnumConstantNamePrefix(enumDecl, &clangSema.getPreprocessor()); |
2293 | 2066 | if (baseName.startswith(removePrefix)) |
2294 | 2067 | baseName = baseName.substr(removePrefix.size()); |
2295 | 2068 | } |
@@ -2382,15 +2155,15 @@ auto ClangImporter::Implementation::importFullName( |
2382 | 2155 |
|
2383 | 2156 | // Local function to determine whether the given declaration is subject to |
2384 | 2157 | // a swift_private attribute. |
2385 | | - auto hasSwiftPrivate = [&clangSema](const clang::NamedDecl *D) { |
| 2158 | + auto hasSwiftPrivate = [&clangSema, this](const clang::NamedDecl *D) { |
2386 | 2159 | if (D->hasAttr<clang::SwiftPrivateAttr>()) |
2387 | 2160 | return true; |
2388 | 2161 |
|
2389 | 2162 | // Enum constants that are not imported as members should be considered |
2390 | 2163 | // private if the parent enum is marked private. |
2391 | 2164 | if (auto *ECD = dyn_cast<clang::EnumConstantDecl>(D)) { |
2392 | 2165 | auto *ED = cast<clang::EnumDecl>(ECD->getDeclContext()); |
2393 | | - switch (classifyEnum(clangSema.getPreprocessor(), ED)) { |
| 2166 | + switch (getEnumKind(ED, &clangSema.getPreprocessor())) { |
2394 | 2167 | case EnumKind::Constants: |
2395 | 2168 | case EnumKind::Unknown: |
2396 | 2169 | if (ED->hasAttr<clang::SwiftPrivateAttr>()) |
|
0 commit comments