|
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