@@ -4590,7 +4590,27 @@ namespace {
4590
4590
if (auto Known = Impl.importDeclCached (decl, getVersion ()))
4591
4591
return Known;
4592
4592
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
+ }
4594
4614
}
4595
4615
4596
4616
// / Check whether we have already imported a method with the given
@@ -4666,6 +4686,78 @@ namespace {
4666
4686
return (accessor && accessor->getAccessorKind () == accessorInfo->Kind );
4667
4687
}
4668
4688
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
+
4669
4761
Decl *importObjCMethodDecl (const clang::ObjCMethodDecl *decl,
4670
4762
DeclContext *dc,
4671
4763
bool forceClassMethod,
@@ -4797,11 +4889,16 @@ namespace {
4797
4889
prop = nullptr ;
4798
4890
}
4799
4891
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)
4803
4901
return nullptr ;
4804
- }
4805
4902
4806
4903
// Import the parameter list and result type.
4807
4904
ParameterList *bodyParams = nullptr ;
@@ -4854,7 +4951,7 @@ namespace {
4854
4951
4855
4952
// If the method has a related result type that is representable
4856
4953
// in Swift as DynamicSelf, do so.
4857
- if (!prop && decl->hasRelatedResultType ()) {
4954
+ if (!needAccessorDecl && decl->hasRelatedResultType ()) {
4858
4955
resultTy = dc->getSelfInterfaceType ();
4859
4956
if (dc->getSelfClassDecl ())
4860
4957
resultTy = DynamicSelfType::get (resultTy, Impl.SwiftContext );
@@ -5020,7 +5117,7 @@ namespace {
5020
5117
FuncDecl *setter);
5021
5118
5022
5119
// / Import the accessor and its attributes.
5023
- AccessorDecl *importAccessor (clang::ObjCMethodDecl *clangAccessor,
5120
+ AccessorDecl *importAccessor (const clang::ObjCMethodDecl *clangAccessor,
5024
5121
AbstractStorageDecl *storage,
5025
5122
AccessorKind accessorKind,
5026
5123
DeclContext *dc);
@@ -7389,7 +7486,7 @@ SwiftDeclConverter::importSubscript(Decl *decl,
7389
7486
}
7390
7487
7391
7488
AccessorDecl *
7392
- SwiftDeclConverter::importAccessor (clang::ObjCMethodDecl *clangAccessor,
7489
+ SwiftDeclConverter::importAccessor (const clang::ObjCMethodDecl *clangAccessor,
7393
7490
AbstractStorageDecl *storage,
7394
7491
AccessorKind accessorKind,
7395
7492
DeclContext *dc) {
0 commit comments