@@ -4590,7 +4590,27 @@ namespace {
45904590 if (auto Known = Impl.importDeclCached (decl, getVersion ()))
45914591 return Known;
45924592
4593- return importObjCMethodDecl (decl, dc, None);
4593+ ImportedName importedName;
4594+ Optional<ImportedName> correctSwiftName; // TODO: not sure if we need this.
4595+ importedName = importFullName (decl, correctSwiftName);
4596+ if (!importedName)
4597+ return nullptr ;
4598+
4599+ // some ObjC method decls are imported as computed properties.
4600+ switch (importedName.getAccessorKind ()) {
4601+ case ImportedAccessorKind::PropertyGetter:
4602+ if (importedName.getAsyncInfo ())
4603+ return importObjCMethodAsEffectfulProp (decl, dc, importedName);
4604+
4605+ // if there is no valid async info, then fall-back to method import.
4606+ LLVM_FALLTHROUGH;
4607+
4608+ case ImportedAccessorKind::PropertySetter:
4609+ case ImportedAccessorKind::SubscriptGetter:
4610+ case ImportedAccessorKind::SubscriptSetter:
4611+ case ImportedAccessorKind::None:
4612+ return importObjCMethodDecl (decl, dc, None);
4613+ }
45944614 }
45954615
45964616 // / Check whether we have already imported a method with the given
@@ -4666,6 +4686,78 @@ namespace {
46664686 return (accessor && accessor->getAccessorKind () == accessorInfo->Kind );
46674687 }
46684688
4689+ // / Creates a fresh VarDecl with a single 'get' accessor to represent
4690+ // / an ObjC method that takes no arguments other than a completion-handler
4691+ // / (where the handler may have an NSError argument).
4692+ Decl *importObjCMethodAsEffectfulProp (const clang::ObjCMethodDecl *decl,
4693+ DeclContext *dc,
4694+ ImportedName name) {
4695+ assert (name.getAsyncInfo () && " expected to be for an effectful prop!" );
4696+
4697+ if (name.getAccessorKind () != ImportedAccessorKind::PropertyGetter) {
4698+ assert (false && " unexpected accessor kind as a computed prop" );
4699+ // NOTE: to handle setters, we would need to search for an existing
4700+ // VarDecl corresponding to the one we might have already created
4701+ // for the 'get' accessor, and tack this accessor onto it.
4702+ return nullptr ;
4703+ }
4704+
4705+ auto importedType = Impl.importEffectfulPropertyType (decl, dc, name,
4706+ isInSystemModule (dc));
4707+ if (!importedType)
4708+ return nullptr ;
4709+
4710+ auto type = importedType.getType ();
4711+ const auto access = getOverridableAccessLevel (dc);
4712+ auto ident = name.getDeclName ().getBaseIdentifier ();
4713+ auto propDecl = Impl.createDeclWithClangNode <VarDecl>(decl, access,
4714+ /* IsStatic*/ decl->isClassMethod (), VarDecl::Introducer::Var,
4715+ Impl.importSourceLoc (decl->getLocation ()), ident, dc);
4716+ propDecl->setInterfaceType (type);
4717+ Impl.recordImplicitUnwrapForDecl (propDecl,
4718+ importedType.isImplicitlyUnwrapped ());
4719+
4720+ // //
4721+ // Build the getter
4722+ AccessorInfo info{propDecl, AccessorKind::Get};
4723+ auto *getter = cast_or_null<AccessorDecl>(
4724+ importObjCMethodDecl (decl, dc, info));
4725+ if (!getter)
4726+ return nullptr ;
4727+
4728+ Impl.importAttributes (decl, getter);
4729+
4730+ // //
4731+ // Combine the getter and the VarDecl into a computed property.
4732+
4733+ // NOTE: since it's an ObjC method we're turning into a Swift computed
4734+ // property, we infer that it has no ObjC 'atomic' guarantees.
4735+ auto inferredObjCPropertyAttrs =
4736+ static_cast <clang::ObjCPropertyAttribute::Kind>
4737+ ( clang::ObjCPropertyAttribute::Kind::kind_readonly
4738+ | clang::ObjCPropertyAttribute::Kind::kind_nonatomic
4739+ | (decl->isInstanceMethod ()
4740+ ? clang::ObjCPropertyAttribute::Kind::kind_class
4741+ : clang::ObjCPropertyAttribute::Kind::kind_noattr)
4742+ );
4743+
4744+ // FIXME: Fake locations for '{' and '}'?
4745+ propDecl->setIsSetterMutating (false );
4746+ makeComputed (propDecl, getter, /* setter=*/ nullptr );
4747+ addObjCAttribute (propDecl, Impl.importIdentifier (decl->getIdentifier ()));
4748+ applyPropertyOwnership (propDecl, inferredObjCPropertyAttrs);
4749+
4750+ // //
4751+ // Check correctness
4752+
4753+ if (getter->getParameters ()->size () != 0 ) {
4754+ assert (false && " this should not happen!" );
4755+ return nullptr ;
4756+ }
4757+
4758+ return propDecl;
4759+ }
4760+
46694761 Decl *importObjCMethodDecl (const clang::ObjCMethodDecl *decl,
46704762 DeclContext *dc,
46714763 bool forceClassMethod,
@@ -4797,11 +4889,16 @@ namespace {
47974889 prop = nullptr ;
47984890 }
47994891
4800- // If we have an accessor-import request but didn't find a property,
4801- // reject the import request.
4802- if (accessorInfo && !prop) {
4892+ const bool nameImportIsGetter =
4893+ importedName.getAccessorKind () == ImportedAccessorKind::PropertyGetter;
4894+
4895+ const bool needAccessorDecl = prop || nameImportIsGetter;
4896+
4897+ // If we have an accessor-import request, but didn't find a property
4898+ // or it's ImportedName doesn't indicate a getter,
4899+ // then reject the import request.
4900+ if (accessorInfo && !needAccessorDecl)
48034901 return nullptr ;
4804- }
48054902
48064903 // Import the parameter list and result type.
48074904 ParameterList *bodyParams = nullptr ;
@@ -4854,7 +4951,7 @@ namespace {
48544951
48554952 // If the method has a related result type that is representable
48564953 // in Swift as DynamicSelf, do so.
4857- if (!prop && decl->hasRelatedResultType ()) {
4954+ if (!needAccessorDecl && decl->hasRelatedResultType ()) {
48584955 resultTy = dc->getSelfInterfaceType ();
48594956 if (dc->getSelfClassDecl ())
48604957 resultTy = DynamicSelfType::get (resultTy, Impl.SwiftContext );
@@ -5020,7 +5117,7 @@ namespace {
50205117 FuncDecl *setter);
50215118
50225119 // / Import the accessor and its attributes.
5023- AccessorDecl *importAccessor (clang::ObjCMethodDecl *clangAccessor,
5120+ AccessorDecl *importAccessor (const clang::ObjCMethodDecl *clangAccessor,
50245121 AbstractStorageDecl *storage,
50255122 AccessorKind accessorKind,
50265123 DeclContext *dc);
@@ -7389,7 +7486,7 @@ SwiftDeclConverter::importSubscript(Decl *decl,
73897486}
73907487
73917488AccessorDecl *
7392- SwiftDeclConverter::importAccessor (clang::ObjCMethodDecl *clangAccessor,
7489+ SwiftDeclConverter::importAccessor (const clang::ObjCMethodDecl *clangAccessor,
73937490 AbstractStorageDecl *storage,
73947491 AccessorKind accessorKind,
73957492 DeclContext *dc) {
0 commit comments