|
51 | 51 | #include "clang/Rewrite/Frontend/Rewriters.h"
|
52 | 52 | #include "clang/Sema/Lookup.h"
|
53 | 53 | #include "clang/Sema/Sema.h"
|
54 |
| -#include "llvm/ADT/Statistic.h" |
55 | 54 | #include "llvm/ADT/STLExtras.h"
|
56 | 55 | #include "llvm/Support/CrashRecoveryContext.h"
|
57 | 56 | #include "llvm/Support/Path.h"
|
|
60 | 59 |
|
61 | 60 | using namespace swift;
|
62 | 61 |
|
63 |
| -//===--------------------------------------------------------------------===// |
64 |
| -// Importer statistics |
65 |
| -//===--------------------------------------------------------------------===// |
66 |
| -#define DEBUG_TYPE "Clang module importer" |
67 |
| -STATISTIC(NumNullaryMethodNames, |
68 |
| - "nullary selectors imported"); |
69 |
| -STATISTIC(NumUnaryMethodNames, |
70 |
| - "unary selectors imported"); |
71 |
| -STATISTIC(NumNullaryInitMethodsMadeUnary, |
72 |
| - "nullary Objective-C init methods turned into unary initializers"); |
73 |
| -STATISTIC(NumMultiMethodNames, |
74 |
| - "multi-part selector method names imported"); |
75 |
| -STATISTIC(NumMethodsMissingFirstArgName, |
76 |
| - "selectors where the first argument name is missing"); |
77 |
| -STATISTIC(NumInitsDroppedWith, |
78 |
| - "# of initializer selectors from which \"with\" was dropped"); |
79 |
| -STATISTIC(NumInitsPrepositionSplit, |
80 |
| - "# of initializer selectors where the split was on a preposition"); |
81 |
| -STATISTIC(NumInitsNonPrepositionSplit, |
82 |
| - "# of initializer selectors where the split wasn't on a preposition"); |
83 |
| - |
84 | 62 | // Commonly-used Clang classes.
|
85 | 63 | using clang::CompilerInstance;
|
86 | 64 | using clang::CompilerInvocation;
|
@@ -725,7 +703,7 @@ void ClangImporter::Implementation::addEntryToLookupTable(
|
725 | 703 | if (!suppressDecl) {
|
726 | 704 | // If we have a name to import as, add this entry to the table.
|
727 | 705 | clang::DeclContext *effectiveContext;
|
728 |
| - if (DeclName name = importFullName(named, &effectiveContext)) { |
| 706 | + if (DeclName name = importFullName(named, None, &effectiveContext)) { |
729 | 707 | table.addEntry(name, named, effectiveContext);
|
730 | 708 | }
|
731 | 709 | }
|
@@ -1636,6 +1614,7 @@ static bool shouldMakeSelectorNonVariadic(clang::Selector selector) {
|
1636 | 1614 |
|
1637 | 1615 | auto ClangImporter::Implementation::importFullName(
|
1638 | 1616 | const clang::NamedDecl *D,
|
| 1617 | + ImportNameOptions options, |
1639 | 1618 | clang::DeclContext **effectiveContext) -> ImportedName {
|
1640 | 1619 | ImportedName result;
|
1641 | 1620 |
|
@@ -1680,20 +1659,36 @@ auto ClangImporter::Implementation::importFullName(
|
1680 | 1659 |
|
1681 | 1660 | // If we have a swift_name attribute, use that.
|
1682 | 1661 | if (auto *nameAttr = D->getAttr<clang::SwiftNameAttr>()) {
|
| 1662 | + bool skipCustomName = false; |
| 1663 | + |
1683 | 1664 | // If we have an Objective-C method that is being mapped to an
|
1684 | 1665 | // initializer (e.g., a factory method whose name doesn't fit the
|
1685 | 1666 | // convention for factory methods), make sure that it can be
|
1686 | 1667 | // imported as an initializer.
|
1687 | 1668 | if (auto method = dyn_cast<clang::ObjCMethodDecl>(D)) {
|
1688 | 1669 | unsigned initPrefixLength;
|
1689 |
| - if (nameAttr->getName().startswith("init(") && |
1690 |
| - !shouldImportAsInitializer(method, initPrefixLength, result.InitKind)) |
1691 |
| - return { }; |
| 1670 | + if (nameAttr->getName().startswith("init(")) { |
| 1671 | + if (!shouldImportAsInitializer(method, initPrefixLength, |
| 1672 | + result.InitKind)) { |
| 1673 | + // We cannot import this as an initializer anyway. |
| 1674 | + return { }; |
| 1675 | + } |
| 1676 | + |
| 1677 | + // If this swift_name attribute maps a factory method to an |
| 1678 | + // initializer and we were asked not to do so, ignore the |
| 1679 | + // custom name. |
| 1680 | + if (options.contains(ImportNameFlags::SuppressFactoryMethodAsInit) && |
| 1681 | + (result.InitKind == CtorInitializerKind::Factory || |
| 1682 | + result.InitKind == CtorInitializerKind::ConvenienceFactory)) |
| 1683 | + skipCustomName = true; |
| 1684 | + } |
1692 | 1685 | }
|
1693 | 1686 |
|
1694 |
| - result.HasCustomName = true; |
1695 |
| - result.Imported = parseDeclName(SwiftContext, nameAttr->getName()); |
1696 |
| - return result; |
| 1687 | + if (!skipCustomName) { |
| 1688 | + result.HasCustomName = true; |
| 1689 | + result.Imported = parseDeclName(SwiftContext, nameAttr->getName()); |
| 1690 | + return result; |
| 1691 | + } |
1697 | 1692 | }
|
1698 | 1693 |
|
1699 | 1694 | // For empty names, there is nothing to do.
|
@@ -1728,6 +1723,15 @@ auto ClangImporter::Implementation::importFullName(
|
1728 | 1723 | isInitializer = shouldImportAsInitializer(objcMethod, initializerPrefixLen,
|
1729 | 1724 | result.InitKind);
|
1730 | 1725 |
|
| 1726 | + // If we would import a factory method as an initializer but were |
| 1727 | + // asked not to, don't consider this as an initializer. |
| 1728 | + if (isInitializer && |
| 1729 | + options.contains(ImportNameFlags::SuppressFactoryMethodAsInit) && |
| 1730 | + (result.InitKind == CtorInitializerKind::Factory || |
| 1731 | + result.InitKind == CtorInitializerKind::ConvenienceFactory)) { |
| 1732 | + isInitializer = false; |
| 1733 | + } |
| 1734 | + |
1731 | 1735 | // Map the Objective-C selector directly.
|
1732 | 1736 | auto selector = D->getDeclName().getObjCSelector();
|
1733 | 1737 | if (isInitializer)
|
@@ -1997,139 +2001,6 @@ ClangImporter::Implementation::importIdentifier(
|
1997 | 2001 | return SwiftContext.getIdentifier(name);
|
1998 | 2002 | }
|
1999 | 2003 |
|
2000 |
| -/// Import an argument name. |
2001 |
| -static Identifier importArgName(ASTContext &ctx, StringRef name, |
2002 |
| - bool dropWith, bool isSwiftPrivate) { |
2003 |
| - // Simple case: empty name. |
2004 |
| - if (name.empty()) { |
2005 |
| - if (isSwiftPrivate) |
2006 |
| - return ctx.getIdentifier("__"); |
2007 |
| - return Identifier(); |
2008 |
| - } |
2009 |
| - |
2010 |
| - SmallString<32> scratch; |
2011 |
| - auto words = camel_case::getWords(name); |
2012 |
| - auto firstWord = *words.begin(); |
2013 |
| - StringRef argName = name; |
2014 |
| - |
2015 |
| - // If we're dropping "with", handle that now. |
2016 |
| - if (dropWith) { |
2017 |
| - // If the first word is "with"... |
2018 |
| - if (name.size() > 4 && |
2019 |
| - camel_case::sameWordIgnoreFirstCase(firstWord, "with")) { |
2020 |
| - // Drop it. |
2021 |
| - ++NumInitsDroppedWith; |
2022 |
| - |
2023 |
| - auto iter = words.begin(); |
2024 |
| - ++iter; |
2025 |
| - |
2026 |
| - argName = name.substr(iter.getPosition()); |
2027 |
| - // Don't drop "with" if the resulting arg is a reserved name. |
2028 |
| - if (ClangImporter::Implementation::isSwiftReservedName( |
2029 |
| - camel_case::toLowercaseWord(argName, scratch))) { |
2030 |
| - argName = name; |
2031 |
| - } |
2032 |
| - } else { |
2033 |
| - // If we're tracking statistics, check whether the name starts with |
2034 |
| - // a preposition. |
2035 |
| - if (llvm::AreStatisticsEnabled()) { |
2036 |
| - if (getPrepositionKind(firstWord)) |
2037 |
| - ++NumInitsPrepositionSplit; |
2038 |
| - else |
2039 |
| - ++NumInitsNonPrepositionSplit; |
2040 |
| - } |
2041 |
| - |
2042 |
| - argName = name; |
2043 |
| - } |
2044 |
| - } |
2045 |
| - |
2046 |
| - /// Lowercase the first word to form the argument name. |
2047 |
| - argName = camel_case::toLowercaseWord(argName, scratch); |
2048 |
| - if (!isSwiftPrivate) |
2049 |
| - return ctx.getIdentifier(argName); |
2050 |
| - |
2051 |
| - SmallString<32> prefixed{"__"}; |
2052 |
| - prefixed.append(argName); |
2053 |
| - return ctx.getIdentifier(prefixed.str()); |
2054 |
| -} |
2055 |
| - |
2056 |
| -/// Map an Objective-C selector name to a Swift method name. |
2057 |
| -static DeclName mapSelectorName(ASTContext &ctx, |
2058 |
| - ObjCSelector selector, |
2059 |
| - bool isInitializer, |
2060 |
| - bool isSwiftPrivate) { |
2061 |
| - // Zero-argument selectors. |
2062 |
| - if (selector.getNumArgs() == 0) { |
2063 |
| - ++NumNullaryMethodNames; |
2064 |
| - |
2065 |
| - auto name = selector.getSelectorPieces()[0]; |
2066 |
| - StringRef nameText = name.empty()? "" : name.str(); |
2067 |
| - |
2068 |
| - if (!isInitializer) { |
2069 |
| - if (!isSwiftPrivate) |
2070 |
| - return DeclName(ctx, name, {}); |
2071 |
| - |
2072 |
| - SmallString<32> newName{"__"}; |
2073 |
| - newName.append(nameText); |
2074 |
| - return DeclName(ctx, ctx.getIdentifier(newName.str()), {}); |
2075 |
| - } |
2076 |
| - |
2077 |
| - // Simple case for initializers. |
2078 |
| - if (nameText == "init" && !isSwiftPrivate) |
2079 |
| - return DeclName(ctx, name, { }); |
2080 |
| - |
2081 |
| - // This is an initializer with no parameters but a name that |
2082 |
| - // contains more than 'init', so synthesize an argument to capture |
2083 |
| - // what follows 'init'. |
2084 |
| - ++NumNullaryInitMethodsMadeUnary; |
2085 |
| - assert(camel_case::getFirstWord(nameText).equals("init")); |
2086 |
| - auto baseName = ctx.Id_init; |
2087 |
| - auto argName = importArgName(ctx, nameText.substr(4), /*dropWith=*/true, |
2088 |
| - isSwiftPrivate); |
2089 |
| - return DeclName(ctx, baseName, argName); |
2090 |
| - } |
2091 |
| - |
2092 |
| - // Determine the base name and first argument name. |
2093 |
| - Identifier baseName; |
2094 |
| - SmallVector<Identifier, 2> argumentNames; |
2095 |
| - Identifier firstPiece = selector.getSelectorPieces()[0]; |
2096 |
| - StringRef firstPieceText = firstPiece.empty()? "" : firstPiece.str(); |
2097 |
| - if (isInitializer) { |
2098 |
| - assert(camel_case::getFirstWord(firstPieceText).equals("init")); |
2099 |
| - baseName = ctx.Id_init; |
2100 |
| - argumentNames.push_back(importArgName(ctx, firstPieceText.substr(4), |
2101 |
| - /*dropWith=*/true, isSwiftPrivate)); |
2102 |
| - } else { |
2103 |
| - baseName = firstPiece; |
2104 |
| - if (isSwiftPrivate) { |
2105 |
| - SmallString<32> newName{"__"}; |
2106 |
| - newName.append(firstPieceText); |
2107 |
| - baseName = ctx.getIdentifier(newName); |
2108 |
| - } |
2109 |
| - argumentNames.push_back(Identifier()); |
2110 |
| - } |
2111 |
| - |
2112 |
| - if (argumentNames[0].empty()) |
2113 |
| - ++NumMethodsMissingFirstArgName; |
2114 |
| - |
2115 |
| - // Determine the remaining argument names. |
2116 |
| - unsigned n = selector.getNumArgs(); |
2117 |
| - if (n == 1) |
2118 |
| - ++NumUnaryMethodNames; |
2119 |
| - else |
2120 |
| - ++NumMultiMethodNames; |
2121 |
| - |
2122 |
| - for (auto piece : selector.getSelectorPieces().slice(1)) { |
2123 |
| - if (piece.empty()) |
2124 |
| - argumentNames.push_back(piece); |
2125 |
| - else |
2126 |
| - argumentNames.push_back(importArgName(ctx, piece.str(), |
2127 |
| - /*dropWith=*/false, |
2128 |
| - /*isSwiftPrivate=*/false)); |
2129 |
| - } |
2130 |
| - return DeclName(ctx, baseName, argumentNames); |
2131 |
| -} |
2132 |
| - |
2133 | 2004 | namespace {
|
2134 | 2005 | /// Function object used to create Clang selectors from strings.
|
2135 | 2006 | class CreateSelector {
|
@@ -2230,26 +2101,6 @@ ClangImporter::Implementation::exportSelector(ObjCSelector selector) {
|
2230 | 2101 | pieces.data());
|
2231 | 2102 | }
|
2232 | 2103 |
|
2233 |
| - |
2234 |
| -DeclName |
2235 |
| -ClangImporter::Implementation::mapSelectorToDeclName(ObjCSelector selector, |
2236 |
| - bool isInitializer, |
2237 |
| - bool isSwiftPrivate) |
2238 |
| -{ |
2239 |
| - // Check whether we've already mapped this selector. |
2240 |
| - auto known = SelectorMappings.find({selector, isInitializer}); |
2241 |
| - if (known != SelectorMappings.end()) |
2242 |
| - return known->second; |
2243 |
| - |
2244 |
| - // Map the selector. |
2245 |
| - auto result = mapSelectorName(SwiftContext, selector, isInitializer, |
2246 |
| - isSwiftPrivate); |
2247 |
| - |
2248 |
| - // Cache the result and return. |
2249 |
| - SelectorMappings[{selector, isInitializer}] = result; |
2250 |
| - return result; |
2251 |
| -} |
2252 |
| - |
2253 | 2104 | /// Translate the "nullability" notion from API notes into an optional type
|
2254 | 2105 | /// kind.
|
2255 | 2106 | OptionalTypeKind ClangImporter::Implementation::translateNullability(
|
|
0 commit comments