Skip to content

Commit b324249

Browse files
authored
[SourceKit] Add a new request to translate from Objc names to Swift names and vice versa.
Extensive cross-language tooling support needs to bridge decl names between two different languages more freely. This SourceKit request is designed to translate Objc names to Swift names and vice versa. Working similarly to cursor-info requisition, the name translation request requires a Swift reference to a Swift/Clang decl, and the preferred name to translate from, and language kind that the given name belongs to. If the translation succeeds, SourceKit service responds with the corresponding name than belongs to the other kind of language. Newly introduced keys: “key.namekind": “source.lang.name.kind.objc” | "source.lang.name.kind.swift" “key.basename”: “name" “key.argnames”: [“name"] “key.selectorpieces”: [“name[:]"] This commit only implements translation from Objc to Swift.
1 parent 1eedf4f commit b324249

File tree

22 files changed

+1031
-30
lines changed

22 files changed

+1031
-30
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ namespace clang {
3838
class Sema;
3939
class TargetInfo;
4040
class VisibleDeclConsumer;
41+
class DeclarationName;
4142
}
4243

4344
namespace swift {
44-
4545
class ASTContext;
4646
class ClangImporterOptions;
4747
class ClangModuleUnit;
@@ -267,13 +267,13 @@ class ClangImporter final : public ClangModuleLoader {
267267
void getMangledName(raw_ostream &os, const clang::NamedDecl *clangDecl) const;
268268

269269
using ClangModuleLoader::addDependency;
270-
270+
271271
// Print statistics from the Clang AST reader.
272272
void printStatistics() const override;
273273

274274
/// Dump Swift lookup tables.
275275
void dumpSwiftLookupTables();
276-
276+
277277
/// Given the path of a Clang module, collect the names of all its submodules.
278278
/// Calling this function does not load the module.
279279
void collectSubModuleNames(
@@ -282,6 +282,9 @@ class ClangImporter final : public ClangModuleLoader {
282282

283283
/// Given a Clang module, decide whether this module is imported already.
284284
static bool isModuleImported(const clang::Module *M);
285+
286+
DeclName importName(const clang::NamedDecl *D,
287+
clang::DeclarationName givenName);
285288
};
286289

287290
ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2889,3 +2889,10 @@ void ClangImporter::Implementation::dumpSwiftLookupTables() {
28892889
llvm::errs() << "<<Bridging header lookup table>>\n";
28902890
BridgingHeaderLookupTable->dump();
28912891
}
2892+
2893+
DeclName ClangImporter::
2894+
importName(const clang::NamedDecl *D,
2895+
clang::DeclarationName preferredName) {
2896+
return Impl.importFullName(D, Impl.CurrentVersion, preferredName).
2897+
getDeclName();
2898+
}

lib/ClangImporter/ImportName.cpp

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,8 @@ static bool suppressFactoryMethodAsInit(const clang::ObjCMethodDecl *method,
10731073
}
10741074

10751075
ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1076-
ImportNameVersion version) {
1076+
ImportNameVersion version,
1077+
clang::DeclarationName givenName) {
10771078
ImportedName result;
10781079

10791080
/// Whether we want a Swift 3 or later name
@@ -1112,7 +1113,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
11121113
SmallVector<const clang::ObjCMethodDecl *, 4> overriddenMethods;
11131114
method->getOverriddenMethods(overriddenMethods);
11141115
for (auto overridden : overriddenMethods) {
1115-
const auto overriddenName = importName(overridden, version);
1116+
const auto overriddenName = importName(overridden, version, givenName);
11161117
if (overriddenName.getDeclName())
11171118
overriddenNames.push_back({overridden, overriddenName});
11181119
}
@@ -1144,7 +1145,8 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
11441145
if (!knownProperties.insert(overriddenProperty).second)
11451146
continue;
11461147

1147-
const auto overriddenName = importName(overriddenProperty, version);
1148+
const auto overriddenName = importName(overriddenProperty, version,
1149+
givenName);
11481150
if (overriddenName.getDeclName())
11491151
overriddenNames.push_back({overriddenProperty, overriddenName});
11501152
}
@@ -1293,6 +1295,12 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
12931295
// Map the identifier.
12941296
baseName = D->getDeclName().getAsIdentifierInfo()->getName();
12951297

1298+
if (givenName) {
1299+
if (!givenName.isIdentifier())
1300+
return ImportedName();
1301+
baseName = givenName.getAsIdentifierInfo()->getName();
1302+
}
1303+
12961304
// For Objective-C BOOL properties, use the name of the getter
12971305
// which, conventionally, has an "is" prefix.
12981306
if (swift3OrLaterName) {
@@ -1322,6 +1330,24 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
13221330

13231331
// Map the Objective-C selector directly.
13241332
auto selector = D->getDeclName().getObjCSelector();
1333+
1334+
// Respect the given name.
1335+
if (givenName) {
1336+
switch (givenName.getNameKind()) {
1337+
case clang::DeclarationName::ObjCOneArgSelector:
1338+
case clang::DeclarationName::ObjCMultiArgSelector:
1339+
case clang::DeclarationName::ObjCZeroArgSelector:
1340+
1341+
// Make sure the given name has the right count of arguments.
1342+
if (selector.getNumArgs() != givenName.getObjCSelector().getNumArgs())
1343+
return ImportedName();
1344+
selector = givenName.getObjCSelector();
1345+
break;
1346+
default:
1347+
return ImportedName();
1348+
}
1349+
}
1350+
13251351
baseName = selector.getNameForSlot(0);
13261352

13271353
// We don't support methods with empty first selector pieces.
@@ -1435,9 +1461,24 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
14351461
auto enumInfo = getEnumInfo(enumDecl);
14361462

14371463
StringRef removePrefix = enumInfo.getConstantNamePrefix();
1438-
if (!removePrefix.empty() && baseName.startswith(removePrefix)) {
1439-
baseName = baseName.substr(removePrefix.size());
1440-
strippedPrefix = true;
1464+
if (!removePrefix.empty()) {
1465+
if (baseName.startswith(removePrefix)) {
1466+
baseName = baseName.substr(removePrefix.size());
1467+
strippedPrefix = true;
1468+
} else if (givenName) {
1469+
// Calculate the new prefix.
1470+
// What if the preferred name causes longer prefix?
1471+
StringRef subPrefix = [](StringRef LHS, StringRef RHS) {
1472+
if(LHS.size() > RHS.size())
1473+
std::swap(LHS, RHS) ;
1474+
return StringRef(LHS.data(), std::mismatch(LHS.begin(), LHS.end(),
1475+
RHS.begin()).first - LHS.begin());
1476+
}(removePrefix, baseName);
1477+
if (!subPrefix.empty()) {
1478+
baseName = baseName.substr(subPrefix.size());
1479+
strippedPrefix = true;
1480+
}
1481+
}
14411482
}
14421483
}
14431484

@@ -1611,15 +1652,17 @@ NameImporter::importMacroName(const clang::IdentifierInfo *clangIdentifier,
16111652
}
16121653

16131654
ImportedName NameImporter::importName(const clang::NamedDecl *decl,
1614-
ImportNameVersion version) {
1655+
ImportNameVersion version,
1656+
clang::DeclarationName givenName) {
16151657
CacheKeyType key(decl, version);
1616-
if (importNameCache.count(key)) {
1658+
if (importNameCache.count(key) && !givenName) {
16171659
++ImportNameNumCacheHits;
16181660
return importNameCache[key];
16191661
}
16201662
++ImportNameNumCacheMisses;
1621-
auto res = importNameImpl(decl, version);
1663+
auto res = importNameImpl(decl, version, givenName);
16221664
res.setVersion(version);
1623-
importNameCache[key] = res;
1665+
if (!givenName)
1666+
importNameCache[key] = res;
16241667
return res;
16251668
}

lib/ClangImporter/ImportName.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class ImportedName {
212212
case ImportedAccessorKind::SubscriptSetter:
213213
return true;
214214
}
215-
215+
216216
llvm_unreachable("Invalid ImportedAccessorKind.");
217217
}
218218
};
@@ -250,7 +250,9 @@ class NameImporter {
250250

251251
/// Determine the Swift name for a Clang decl
252252
ImportedName importName(const clang::NamedDecl *decl,
253-
ImportNameVersion version);
253+
ImportNameVersion version,
254+
clang::DeclarationName preferredName =
255+
clang::DeclarationName());
254256

255257
/// Imports the name of the given Clang macro into Swift.
256258
Identifier importMacroName(const clang::IdentifierInfo *clangIdentifier,
@@ -313,7 +315,8 @@ class NameImporter {
313315
ImportNameVersion version);
314316

315317
ImportedName importNameImpl(const clang::NamedDecl *,
316-
ImportNameVersion version);
318+
ImportNameVersion version,
319+
clang::DeclarationName);
317320
};
318321

319322
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,8 +607,10 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
607607
///
608608
/// \param D The Clang declaration whose name should be imported.
609609
importer::ImportedName importFullName(const clang::NamedDecl *D,
610-
Version version) {
611-
return getNameImporter().importName(D, version);
610+
Version version,
611+
clang::DeclarationName givenName =
612+
clang::DeclarationName()) {
613+
return getNameImporter().importName(D, version, givenName);
612614
}
613615

614616
/// Print an imported name as a string suitable for the swift_name attribute,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#if !defined(__FOOSUB_H__)
2+
#define __FOOSUB_H__ 1
3+
4+
int fooSubFunc1(int a);
5+
6+
enum FooSubEnum1 {
7+
FooSubEnum1X,
8+
FooSubEnum1Y
9+
};
10+
11+
enum {
12+
FooSubUnnamedEnumeratorA1
13+
};
14+
15+
#endif /* ! __FOOSUB_H__ */

0 commit comments

Comments
 (0)