Skip to content

Commit d79546a

Browse files
committed
Merge pull request #2751 from milseman/newtype_fixit
[Import as Member] Print full context in fixit
2 parents 55a97dd + e7b293e commit d79546a

File tree

5 files changed

+112
-31
lines changed

5 files changed

+112
-31
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,12 +1891,48 @@ namespace {
18911891
typedef ClangImporter::Implementation::ImportedName ImportedName;
18921892
}
18931893

1894-
void ClangImporter::Implementation::ImportedName::printSwiftName(
1895-
llvm::raw_ostream &os) const {
1894+
/// Will recursively print out the fully qualified context for the given name.
1895+
/// Ends with a trailing "."
1896+
static void
1897+
printFullContextPrefix(ClangImporter::Implementation::ImportedName name,
1898+
llvm::raw_ostream &os,
1899+
ClangImporter::Implementation &Impl) {
1900+
const clang::NamedDecl *newDeclContextNamed = nullptr;
1901+
switch (name.EffectiveContext.getKind()) {
1902+
case EffectiveClangContext::UnresolvedContext:
1903+
os << name.EffectiveContext.getUnresolvedName() << ".";
1904+
// And we're done!
1905+
return;
1906+
1907+
case EffectiveClangContext::DeclContext: {
1908+
auto namedDecl =
1909+
dyn_cast<clang::NamedDecl>(name.EffectiveContext.getAsDeclContext());
1910+
if (!namedDecl) {
1911+
// We're done
1912+
return;
1913+
}
1914+
newDeclContextNamed = cast<clang::NamedDecl>(namedDecl);
1915+
break;
1916+
}
1917+
1918+
case EffectiveClangContext::TypedefContext:
1919+
newDeclContextNamed = name.EffectiveContext.getTypedefName();
1920+
break;
1921+
}
1922+
1923+
// Now, let's print out the parent
1924+
assert(newDeclContextNamed && "should of been set");
1925+
auto parentName = Impl.importFullName(newDeclContextNamed);
1926+
printFullContextPrefix(parentName, os, Impl);
1927+
os << parentName.Imported << ".";
1928+
}
1929+
1930+
void ClangImporter::Implementation::printSwiftName(ImportedName name,
1931+
llvm::raw_ostream &os) {
18961932
// Property accessors.
18971933
bool isGetter = false;
18981934
bool isSetter = false;
1899-
switch (AccessorKind) {
1935+
switch (name.AccessorKind) {
19001936
case ImportedAccessorKind::None:
19011937
break;
19021938

@@ -1915,43 +1951,27 @@ void ClangImporter::Implementation::ImportedName::printSwiftName(
19151951

19161952
// If we're importing a global as a member, we need to provide the
19171953
// effective context.
1918-
if (ImportAsMember) {
1919-
switch (EffectiveContext.getKind()) {
1920-
case EffectiveClangContext::DeclContext:
1921-
os << SwiftLookupTable::translateDeclContext(
1922-
EffectiveContext.getAsDeclContext())->second;
1923-
break;
1924-
1925-
case EffectiveClangContext::TypedefContext:
1926-
os << EffectiveContext.getTypedefName()->getName();
1927-
break;
1928-
1929-
case EffectiveClangContext::UnresolvedContext:
1930-
os << EffectiveContext.getUnresolvedName();
1931-
break;
1932-
}
1933-
1934-
os << ".";
1935-
}
1954+
if (name.ImportAsMember)
1955+
printFullContextPrefix(name, os, *this);
19361956

19371957
// Base name.
1938-
os << Imported.getBaseName().str();
1958+
os << name.Imported.getBaseName().str();
19391959

19401960
// Determine the number of argument labels we'll be producing.
1941-
auto argumentNames = Imported.getArgumentNames();
1961+
auto argumentNames = name.Imported.getArgumentNames();
19421962
unsigned numArguments = argumentNames.size();
1943-
if (SelfIndex) ++numArguments;
1963+
if (name.SelfIndex) ++numArguments;
19441964
if (isSetter) ++numArguments;
19451965

19461966
// If the result is a simple name that is not a getter, we're done.
1947-
if (numArguments == 0 && Imported.isSimpleName() && !isGetter) return;
1967+
if (numArguments == 0 && name.Imported.isSimpleName() && !isGetter) return;
19481968

19491969
// We need to produce a function name.
19501970
os << "(";
19511971
unsigned currentArgName = 0;
19521972
for (unsigned i = 0; i != numArguments; ++i) {
19531973
// The "self" parameter.
1954-
if (SelfIndex && *SelfIndex == i) {
1974+
if (name.SelfIndex && *name.SelfIndex == i) {
19551975
os << "self:";
19561976
continue;
19571977
}
@@ -2355,6 +2375,7 @@ auto ClangImporter::Implementation::importFullName(
23552375
// Import onto a swift_newtype if present
23562376
} else if (auto newtypeDecl = findSwiftNewtype(D, clangSema, swift2Name)) {
23572377
result.EffectiveContext = newtypeDecl;
2378+
result.ImportAsMember = true;
23582379
// Everything else goes into its redeclaration context.
23592380
} else {
23602381
result.EffectiveContext = dc->getRedeclContext();

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,14 +1284,15 @@ namespace {
12841284

12851285
/// Mark the given declaration as the Swift 2 variant of a Swift 3
12861286
/// declaration with the given name.
1287-
static void markAsSwift2Variant(Decl *decl, ImportedName swift3Name) {
1287+
void markAsSwift2Variant(Decl *decl, ImportedName swift3Name,
1288+
DeclContext *newDC = nullptr) {
12881289
ASTContext &ctx = decl->getASTContext();
12891290

12901291
llvm::SmallString<64> renamed;
12911292
{
12921293
// Render a swift_name string.
12931294
llvm::raw_svector_ostream os(renamed);
1294-
swift3Name.printSwiftName(os);
1295+
Impl.printSwiftName(swift3Name, os);
12951296
}
12961297

12971298
auto attr = AvailableAttr::createUnconditional(

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -907,9 +907,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
907907
}
908908
}
909909

910-
/// Print this imported name as a string suitable for the swift_name
911-
/// attribute.
912-
void printSwiftName(llvm::raw_ostream &os) const;
913910
};
914911

915912
/// Flags that control the import of names in importFullName.
@@ -938,6 +935,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
938935
const clang::MacroInfo *macro,
939936
clang::ASTContext &clangCtx);
940937

938+
/// Print an imported name as a string suitable for the swift_name attribute.
939+
void printSwiftName(ImportedName, llvm::raw_ostream &os);
940+
941941
/// Retrieve the property type as determined by the given accessor.
942942
static clang::QualType
943943
getAccessorPropertyType(const clang::FunctionDecl *accessor, bool isSetter,

test/IDE/Inputs/custom-modules/Newtype.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,11 @@ extern MyABIOldTypeNS getMyABIOldTypeNS(void);
9494
extern void takeMyABINewTypeNonNullNS(__nonnull MyABINewTypeNS);
9595
extern void takeMyABIOldTypeNonNullNS(__nonnull MyABIOldTypeNS);
9696

97+
// Nested types
98+
typedef struct {int i;} NSSomeContext;
99+
100+
typedef NSString *NSSomeContextName __attribute((swift_newtype(struct)))
101+
__attribute((swift_name("NSSomeContext.Name")));
102+
103+
extern const NSSomeContextName NSMyContextName;
104+

test/IDE/newtype.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,52 @@
9191
// PRINT-NEXT: }
9292
// PRINT-NEXT: func FooAudited() -> CFNewType
9393
// PRINT-NEXT: func FooUnaudited() -> Unmanaged<CFString>
94+
//
95+
// PRINT-NEXT: struct MyABINewType : RawRepresentable, _SwiftNewtypeWrapper {
96+
// PRINT-NEXT: init(_ rawValue: CFString)
97+
// PRINT-NEXT: init(rawValue: CFString)
98+
// PRINT-NEXT: let rawValue: CFString
99+
// PRINT-NEXT: }
100+
// PRINT-NEXT: typealias MyABIOldType = CFString
101+
// PRINT-NEXT: extension MyABINewType {
102+
// PRINT-NEXT: static let global: MyABINewType!
103+
// PRINT-NEXT: }
104+
// PRINT-NEXT: let kMyABIOldTypeGlobal: MyABIOldType!
105+
// PRINT-NEXT: func getMyABINewType() -> MyABINewType!
106+
// PRINT-NEXT: func getMyABIOldType() -> MyABIOldType!
107+
// PRINT-NEXT: func takeMyABINewType(_: MyABINewType!)
108+
// PRINT-NEXT: func takeMyABIOldType(_: MyABIOldType!)
109+
// PRINT-NEXT: func takeMyABINewTypeNonNull(_: MyABINewType)
110+
// PRINT-NEXT: func takeMyABIOldTypeNonNull(_: MyABIOldType)
111+
// PRINT-NEXT: struct MyABINewTypeNS : RawRepresentable, _SwiftNewtypeWrapper, Equatable, Hashable, Comparable, _ObjectiveCBridgeable {
112+
// PRINT-NEXT: init(_ rawValue: String)
113+
// PRINT-NEXT: init(rawValue: String)
114+
// PRINT-NEXT: var _rawValue: NSString
115+
// PRINT-NEXT: var rawValue: String { get }
116+
// PRINT-NEXT: }
117+
// PRINT-NEXT: typealias MyABIOldTypeNS = NSString
118+
// PRINT-NEXT: func getMyABINewTypeNS() -> MyABINewTypeNS!
119+
// PRINT-NEXT: func getMyABIOldTypeNS() -> String!
120+
// PRINT-NEXT: func takeMyABINewTypeNonNullNS(_: MyABINewTypeNS)
121+
// PRINT-NEXT: func takeMyABIOldTypeNonNullNS(_: String)
122+
//
123+
// PRINT-NEXT: struct NSSomeContext {
124+
// PRINT-NEXT: var i: Int32
125+
// PRINT-NEXT: init()
126+
// PRINT-NEXT: init(i: Int32)
127+
// PRINT-NEXT: }
128+
// PRINT-NEXT: extension NSSomeContext {
129+
// PRINT-NEXT: struct Name : RawRepresentable, _SwiftNewtypeWrapper, Equatable, Hashable, Comparable, _ObjectiveCBridgeable {
130+
// PRINT-NEXT: init(_ rawValue: String)
131+
// PRINT-NEXT: init(rawValue: String)
132+
// PRINT-NEXT: var _rawValue: NSString
133+
// PRINT-NEXT: var rawValue: String { get }
134+
// PRINT-NEXT: }
135+
// PRINT-NEXT: }
136+
// PRINT-NEXT: extension NSSomeContext.Name {
137+
// PRINT-NEXT: static let myContextName: NSSomeContext.Name
138+
// PRINT-NEXT: }
139+
94140
import Newtype
95141

96142
func tests() {
@@ -129,3 +175,8 @@ func testConformances(ed: ErrorDomain) {
129175
acceptComparable(ed)
130176
acceptObjectiveCBridgeable(ed)
131177
}
178+
179+
func testFixit() {
180+
let _ = NSMyContextName
181+
// expected-error@-1{{'NSMyContextName' has been renamed to 'NSSomeContext.Name.myContextName'}} {{10-25=NSSomeContext.Name.myContextName}}
182+
}

0 commit comments

Comments
 (0)