From 03a46f8150d596d677cba4343c77e1ef59f9ddba Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 12:02:24 +1100 Subject: [PATCH 01/13] Make protocols instantiable and castable --- .../lib/src/code_generator/imports.dart | 2 + .../src/code_generator/objc_interface.dart | 30 +- .../lib/src/code_generator/objc_protocol.dart | 62 +++- .../test/native_objc_test/protocol_test.dart | 96 ++++-- .../test/native_objc_test/protocol_test.h | 3 +- .../test/native_objc_test/protocol_test.m | 8 +- pkgs/objective_c/lib/src/internal.dart | 5 +- .../src/objective_c_bindings_generated.dart | 283 +++++++++++++----- 8 files changed, 366 insertions(+), 123 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/imports.dart b/pkgs/ffigen/lib/src/code_generator/imports.dart index d442d68934..45708ae4c1 100644 --- a/pkgs/ffigen/lib/src/code_generator/imports.dart +++ b/pkgs/ffigen/lib/src/code_generator/imports.dart @@ -167,3 +167,5 @@ final objCSelType = ImportedType( objcPkgImport, 'ObjCSelector', 'ObjCSelector', 'struct objc_selector'); final objCBlockType = ImportedType(objcPkgImport, 'ObjCBlockImpl', 'ObjCBlockImpl', 'id'); +final objCProtocolType = + ImportedType(objcPkgImport, 'ObjCProtocol', 'ObjCProtocol', 'void'); diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart index 6825e1545a..72774ce055 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart @@ -78,21 +78,15 @@ class ObjCInterface extends BindingType with ObjCMethods { ? '' : 'implements ${protocols.map((p) => p.getDartType(w)).join(', ')} '; + final superCtor = superType == null + ? 'super' + : superType!.isObjCImport + ? 'super.castFromPointer' + : 'super._'; s.write(''' class $name extends ${superType?.getDartType(w) ?? wrapObjType} $protoImpl{ - $name._($rawObjType pointer, - {bool retain = false, bool release = false}) : - ${superTypeIsInPkgObjc ? 'super' : 'super.castFromPointer'} - (pointer, retain: retain, release: release); - - /// Constructs a [$name] that points to the same underlying object as [other]. - $name.castFrom($wrapObjType other) : - this._(other.ref.pointer, retain: true, release: true); - - /// Constructs a [$name] that wraps the given raw object pointer. - $name.castFromPointer($rawObjType other, - {bool retain = false, bool release = false}) : - this._(other, retain: retain, release: release); + $name._($rawObjType pointer, {bool retain = false, bool release = false}) : + $superCtor(pointer, retain: retain, release: release); ${generateAsStub ? '' : _generateMethods(w)} } @@ -104,10 +98,20 @@ ${generateAsStub ? '' : _generateMethods(w)} } String _generateMethods(Writer w) { + final rawObjType = PointerType(objCObjectType).getCType(w); final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(w); final s = StringBuffer(); s.write(''' + /// Constructs a [$name] that points to the same underlying object as [other]. + $name.castFrom($wrapObjType other) : + this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [$name] that wraps the given raw object pointer. + $name.castFromPointer($rawObjType other, + {bool retain = false, bool release = false}) : + this._(other, retain: retain, release: release); + /// Returns whether [obj] is an instance of [$name]. static bool isInstance($wrapObjType obj) { return ${_isKindOfClassMsgSend.invoke( diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index 57d6ede6e3..4b71499bd2 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -13,6 +13,8 @@ class ObjCProtocol extends BindingType with ObjCMethods { final superProtocols = []; final String lookupName; final ObjCInternalGlobal _protocolPointer; + late final ObjCInternalGlobal _conformsTo; + late final ObjCMsgSendFunc _conformsToMsgSend; // Filled by ListBindingsVisitation. bool generateAsStub = false; @@ -33,9 +35,18 @@ class ObjCProtocol extends BindingType with ObjCMethods { (Writer w) => '${ObjCBuiltInFunctions.getProtocol.gen(w)}("$lookupName")'), super( - name: name ?? - builtInFunctions.getBuiltInProtocolName(originalName) ?? - originalName); + name: builtInFunctions.getBuiltInProtocolName(originalName) ?? + name ?? + originalName) { + _conformsTo = builtInFunctions.getSelObject('conformsToProtocol:'); + _conformsToMsgSend = builtInFunctions.getMsgSendFunc(BooleanType(), [ + Parameter( + name: 'protocol', + type: PointerType(objCProtocolType), + objCConsumed: false, + ) + ]); + } @override bool get isObjCImport => @@ -52,6 +63,7 @@ class ObjCProtocol extends BindingType with ObjCMethods { ObjCBuiltInFunctions.protocolListenableMethod.gen(w); final protocolBuilder = ObjCBuiltInFunctions.protocolBuilder.gen(w); final objectBase = ObjCBuiltInFunctions.objectBase.gen(w); + final rawObjType = PointerType(objCObjectType).getCType(w); final getSignature = ObjCBuiltInFunctions.getProtocolMethodSignature.gen(w); final s = StringBuffer(); @@ -65,10 +77,13 @@ class ObjCProtocol extends BindingType with ObjCMethods { } s.write(makeDartDoc(dartDoc ?? originalName)); - final protoImpl = superProtocols.isEmpty - ? protocolBase - : superProtocols.map((p) => p.getDartType(w)).join(', '); - s.write('abstract interface class $name implements $protoImpl {'); + final protoImpls = superProtocols.map((p) => p.getDartType(w)).join(', '); + final protoImpl = superProtocols.isEmpty ? '' : 'implements $protoImpls'; + s.write(''' +interface class $name extends $protocolBase $protoImpl{ + $name._($rawObjType pointer, {bool retain = false, bool release = false}) : + super(pointer, retain: retain, release: release); +'''); if (!generateAsStub) { final buildArgs = []; @@ -150,10 +165,10 @@ class ObjCProtocol extends BindingType with ObjCMethods { final builders = ''' /// Builds an object that implements the $originalName protocol. To implement /// multiple protocols, use [addToBuilder] or [$protocolBuilder] directly. - static $objectBase implement($args) { + static $name implement($args) { final builder = $protocolBuilder(); $buildImplementations - return builder.build(); + return $name.castFrom(builder.build()); } /// Adds the implementation of the $originalName protocol to an existing @@ -169,10 +184,10 @@ class ObjCProtocol extends BindingType with ObjCMethods { /// Builds an object that implements the $originalName protocol. To implement /// multiple protocols, use [addToBuilder] or [$protocolBuilder] directly. All /// methods that can be implemented as listeners will be. - static $objectBase implementAsListener($args) { + static $name implementAsListener($args) { final builder = $protocolBuilder(); $buildListenerImplementations - return builder.build(); + return $name.castFrom(builder.build()); } /// Adds the implementation of the $originalName protocol to an existing @@ -185,10 +200,10 @@ class ObjCProtocol extends BindingType with ObjCMethods { /// Builds an object that implements the $originalName protocol. To implement /// multiple protocols, use [addToBuilder] or [$protocolBuilder] directly. All /// methods that can be implemented as blocking listeners will be. - static $objectBase implementAsBlocking($args) { + static $name implementAsBlocking($args) { final builder = $protocolBuilder(); $buildBlockingImplementations - return builder.build(); + return $name.castFrom(builder.build()); } /// Adds the implementation of the $originalName protocol to an existing @@ -201,6 +216,25 @@ class ObjCProtocol extends BindingType with ObjCMethods { } s.write(''' + /// Constructs a [$name] that points to the same underlying object as [other]. + $name.castFrom($objectBase other) : + this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [$name] that wraps the given raw object pointer. + $name.castFromPointer($rawObjType other, + {bool retain = false, bool release = false}) : + this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [$name]. + static bool conformsTo($objectBase obj) { + return ${_conformsToMsgSend.invoke( + w, + 'obj.ref.pointer', + _conformsTo.name, + [_protocolPointer.name], + )}; + } + $builders $listenerBuilders $methodFields @@ -305,6 +339,8 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } super.visitChildren(visitor); visitor.visit(_protocolPointer); visitor.visitAll(superProtocols); + visitor.visit(_conformsTo); + visitor.visit(_conformsToMsgSend); visitMethods(visitor); } } diff --git a/pkgs/ffigen/test/native_objc_test/protocol_test.dart b/pkgs/ffigen/test/native_objc_test/protocol_test.dart index 1c74314311..fad9415918 100644 --- a/pkgs/ffigen/test/native_objc_test/protocol_test.dart +++ b/pkgs/ffigen/test/native_objc_test/protocol_test.dart @@ -36,20 +36,27 @@ void main() { group('ObjC implementation', () { test('Method implementation', () { final protocolImpl = ObjCProtocolImpl.new1(); + final MyProtocol asMyProtocol = protocolImpl; + final SecondaryProtocol asSecondaryProtocol = protocolImpl; + final consumer = ProtocolConsumer.new1(); // Required instance method. - final result = consumer.callInstanceMethod_(protocolImpl); + final result = consumer.callInstanceMethod_(asMyProtocol); expect( result.toDartString(), 'ObjCProtocolImpl: Hello from ObjC: 3.14'); // Optional instance method. - final intResult = consumer.callOptionalMethod_(protocolImpl); + final intResult = consumer.callOptionalMethod_(asMyProtocol); expect(intResult, 579); // Required instance method from secondary protocol. - final otherIntResult = consumer.callOtherMethod_(protocolImpl); + final otherIntResult = consumer.callOtherMethod_(asSecondaryProtocol); expect(otherIntResult, 10); + + // Method using two protocols. + final twoMethodResult = consumer.callTwoMethods_(asMyProtocol); + expect(twoMethodResult, 579); }); test('Method implementation, invoke from Dart', () { @@ -109,7 +116,7 @@ void main() { test('Method implementation', () { final consumer = ProtocolConsumer.new1(); - final myProtocol = MyProtocol.implement( + final MyProtocol myProtocol = MyProtocol.implement( instanceMethod_withDouble_: (NSString s, double x) { return 'MyProtocol: ${s.toDartString()}: $x'.toNSString(); }, @@ -131,23 +138,35 @@ void main() { final consumer = ProtocolConsumer.new1(); final protocolBuilder = ObjCProtocolBuilder(); - MyProtocol.addToBuilder(protocolBuilder, - instanceMethod_withDouble_: (NSString s, double x) { - return 'ProtocolBuilder: ${s.toDartString()}: $x'.toNSString(); - }); + MyProtocol.addToBuilder( + protocolBuilder, + instanceMethod_withDouble_: (NSString s, double x) { + return 'ProtocolBuilder: ${s.toDartString()}: $x'.toNSString(); + }, + optionalMethod_: (SomeStruct s) { + return s.y - s.x; + }, + ); SecondaryProtocol.addToBuilder(protocolBuilder, otherMethod_b_c_d_: (int a, int b, int c, int d) { return a * b * c * d; }); final protocolImpl = protocolBuilder.build(); + final MyProtocol asMyProtocol = MyProtocol.castFrom(protocolImpl); + final SecondaryProtocol asSecondaryProtocol = + SecondaryProtocol.castFrom(protocolImpl); // Required instance method. - final result = consumer.callInstanceMethod_(protocolImpl); + final result = consumer.callInstanceMethod_(asMyProtocol); expect(result.toDartString(), 'ProtocolBuilder: Hello from ObjC: 3.14'); // Required instance method from secondary protocol. - final otherIntResult = consumer.callOtherMethod_(protocolImpl); + final otherIntResult = consumer.callOtherMethod_(asSecondaryProtocol); expect(otherIntResult, 24); + + // Method using two protocols. + final twoMethodResult = consumer.callTwoMethods_(asMyProtocol); + expect(twoMethodResult, 222000); }); test('Multiple protocol implementation using method fields', () { @@ -163,20 +182,23 @@ void main() { return a * b * c * d; }); final protocolImpl = protocolBuilder.build(); + final MyProtocol asMyProtocol = MyProtocol.castFrom(protocolImpl); + final SecondaryProtocol asSecondaryProtocol = + SecondaryProtocol.castFrom(protocolImpl); // Required instance method. - final result = consumer.callInstanceMethod_(protocolImpl); + final result = consumer.callInstanceMethod_(asMyProtocol); expect(result.toDartString(), 'ProtocolBuilder: Hello from ObjC: 3.14'); // Required instance method from secondary protocol. - final otherIntResult = consumer.callOtherMethod_(protocolImpl); + final otherIntResult = consumer.callOtherMethod_(asSecondaryProtocol); expect(otherIntResult, 24); }); test('Unimplemented method', () { final consumer = ProtocolConsumer.new1(); - final myProtocol = MyProtocol.implement( + final MyProtocol myProtocol = MyProtocol.implement( instanceMethod_withDouble_: (NSString s, double x) { throw UnimplementedError(); }, @@ -191,7 +213,7 @@ void main() { final consumer = ProtocolConsumer.new1(); final listenerCompleter = Completer(); - final myProtocol = MyProtocol.implementAsListener( + final MyProtocol myProtocol = MyProtocol.implementAsListener( instanceMethod_withDouble_: (NSString s, double x) { return 'MyProtocol: ${s.toDartString()}: $x'.toNSString(); }, @@ -235,17 +257,20 @@ void main() { return a * b * c * d; }); final protocolImpl = protocolBuilder.build(); + final MyProtocol asMyProtocol = MyProtocol.castFrom(protocolImpl); + final SecondaryProtocol asSecondaryProtocol = + SecondaryProtocol.castFrom(protocolImpl); // Required instance method. - final result = consumer.callInstanceMethod_(protocolImpl); + final result = consumer.callInstanceMethod_(asMyProtocol); expect(result.toDartString(), 'ProtocolBuilder: Hello from ObjC: 3.14'); // Required instance method from secondary protocol. - final otherIntResult = consumer.callOtherMethod_(protocolImpl); + final otherIntResult = consumer.callOtherMethod_(asSecondaryProtocol); expect(otherIntResult, 24); // Listener method. - consumer.callMethodOnRandomThread_(protocolImpl); + consumer.callMethodOnRandomThread_(asMyProtocol); expect(await listenerCompleter.future, 123); }); @@ -261,7 +286,7 @@ void main() { final consumer = ProtocolConsumer.new1(); final listenerCompleter = Completer(); - final myProtocol = MyProtocol.implementAsBlocking( + final MyProtocol myProtocol = MyProtocol.implementAsBlocking( instanceMethod_withDouble_: (NSString s, double x) { throw UnimplementedError(); }, @@ -302,13 +327,16 @@ void main() { return a * b * c * d; }); final protocolImpl = protocolBuilder.build(); + final MyProtocol asMyProtocol = MyProtocol.castFrom(protocolImpl); + final SecondaryProtocol asSecondaryProtocol = + SecondaryProtocol.castFrom(protocolImpl); // Required instance method from secondary protocol. - final otherIntResult = consumer.callOtherMethod_(protocolImpl); + final otherIntResult = consumer.callOtherMethod_(asMyProtocol); expect(otherIntResult, 24); // Blocking method. - consumer.callBlockingMethodOnRandomThread_(protocolImpl); + consumer.callBlockingMethodOnRandomThread_(asSecondaryProtocol); expect(await listenerCompleter.future, 98765); }); }); @@ -352,27 +380,35 @@ void main() { otherSel, otherSignature, otherBlock.ref.pointer.cast()); final proxy = DartProxy.newFromBuilder_(proxyBuilder); + final MyProtocol asMyProtocol = MyProtocol.castFrom(proxy); + final SecondaryProtocol asSecondaryProtocol = + SecondaryProtocol.castFrom(proxy); // Required instance method. - final result = consumer.callInstanceMethod_(proxy); + final result = consumer.callInstanceMethod_(asMyProtocol); expect(result.toDartString(), "DartProxy: Hello from ObjC: 3.14"); // Optional instance method. - final intResult = consumer.callOptionalMethod_(proxy); + final intResult = consumer.callOptionalMethod_(asMyProtocol); expect(intResult, 333); // Required instance method from secondary protocol. - final otherIntResult = consumer.callOtherMethod_(proxy); + final otherIntResult = consumer.callOtherMethod_(asSecondaryProtocol); expect(otherIntResult, 24); + + // Method using two protocols. + final twoMethodResult = consumer.callTwoMethods_(asMyProtocol); + expect(twoMethodResult, 222000); }); test('Unimplemented method', () { final proxyBuilder = DartProxyBuilder.new1(); final consumer = ProtocolConsumer.new1(); final proxy = DartProxy.newFromBuilder_(proxyBuilder); + final MyProtocol asMyProtocol = MyProtocol.castFrom(proxy); // Optional instance method, not implemented. - final intResult = consumer.callOptionalMethod_(proxy); + final intResult = consumer.callOptionalMethod_(asMyProtocol); expect(intResult, -999); }); @@ -389,9 +425,10 @@ void main() { }); final proxy = protocolBuilder.build(); + final MyProtocol asMyProtocol = MyProtocol.castFrom(proxy); for (int i = 0; i < 1000; ++i) { - consumer.callMethodOnRandomThread_(proxy); + consumer.callMethodOnRandomThread_(asMyProtocol); } await completer.future; expect(count, 1000); @@ -493,5 +530,14 @@ void main() { .implement(ObjCProtocolBuilder(), () => 123), throwsA(isA())); }); + + test('conformsTo', () { + final inst = ObjCProtocolImpl.new1(); + expect(NSObjectProtocol.conformsTo(inst), isTrue); + expect(MyProtocol.conformsTo(inst), isTrue); + expect(SecondaryProtocol.conformsTo(inst), isTrue); + expect(EmptyProtocol.conformsTo(inst), isFalse); + expect(UnusedProtocol.conformsTo(inst), isFalse); + }); }); } diff --git a/pkgs/ffigen/test/native_objc_test/protocol_test.h b/pkgs/ffigen/test/native_objc_test/protocol_test.h index 16fd66c11b..769d97d6aa 100644 --- a/pkgs/ffigen/test/native_objc_test/protocol_test.h +++ b/pkgs/ffigen/test/native_objc_test/protocol_test.h @@ -74,11 +74,12 @@ typedef struct { @interface ProtocolConsumer : NSObject -- (NSString*)callInstanceMethod:(id)protocol; +- (NSString*)callInstanceMethod:(id)protocol; - (int32_t)callOptionalMethod:(id)protocol; - (int32_t)callOtherMethod:(id)protocol; - (void)callMethodOnRandomThread:(id)protocol; - (void)callBlockingMethodOnRandomThread:(id)protocol; +- (int32_t)callTwoMethods:(id)protocol; @end diff --git a/pkgs/ffigen/test/native_objc_test/protocol_test.m b/pkgs/ffigen/test/native_objc_test/protocol_test.m index 975effc685..dcd55ad59e 100644 --- a/pkgs/ffigen/test/native_objc_test/protocol_test.m +++ b/pkgs/ffigen/test/native_objc_test/protocol_test.m @@ -9,7 +9,7 @@ #include "protocol_test.h" @implementation ProtocolConsumer : NSObject -- (NSString*)callInstanceMethod:(id)protocol { +- (NSString*)callInstanceMethod:(id)protocol { return [protocol instanceMethod:@"Hello from ObjC" withDouble:3.14]; } @@ -39,6 +39,12 @@ - (void)callBlockingMethodOnRandomThread:(id)protocol { [protocol voidMethod:x]; }); } + +- (int32_t)callTwoMethods:(id)protocol { + SomeStruct s = {123, 345}; + int32_t x = [protocol optionalMethod:s]; + return [protocol otherMethod:x b:1 c:10 d:100]; +} @end diff --git a/pkgs/objective_c/lib/src/internal.dart b/pkgs/objective_c/lib/src/internal.dart index 7a348d70f2..17b1c7dffb 100644 --- a/pkgs/objective_c/lib/src/internal.dart +++ b/pkgs/objective_c/lib/src/internal.dart @@ -328,7 +328,10 @@ bool _isValidClass(ObjectPtr clazz) { } /// Only for use by ffigen bindings. -abstract interface class ObjCProtocolBase implements ObjCObjectBase {} +class ObjCProtocolBase extends ObjCObjectBase { + ObjCProtocolBase(ObjectPtr ptr, {required bool retain, required bool release}) + : super(ptr, retain: retain, release: release); +} @pragma('vm:deeply-immutable') final class ObjCBlockRef extends _ObjCReference { diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index 3c3108b479..cb13e8d7f1 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -165,7 +165,7 @@ external ffi.Pointer class DartInputStreamAdapter extends NSInputStream implements NSStreamDelegate { DartInputStreamAdapter._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [DartInputStreamAdapter] that points to the same underlying object as [other]. DartInputStreamAdapter.castFrom(objc.ObjCObjectBase other) @@ -282,7 +282,7 @@ class DartInputStreamAdapter extends NSInputStream implements NSStreamDelegate { class DartProxy extends NSProxy { DartProxy._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [DartProxy] that points to the same underlying object as [other]. DartProxy.castFrom(objc.ObjCObjectBase other) @@ -362,7 +362,7 @@ class DartProxy extends NSProxy { class DartProxyBuilder extends NSObject { DartProxyBuilder._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [DartProxyBuilder] that points to the same underlying object as [other]. DartProxyBuilder.castFrom(objc.ObjCObjectBase other) @@ -443,7 +443,7 @@ class NSArray extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSArray._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSArray] that points to the same underlying object as [other]. NSArray.castFrom(objc.ObjCObjectBase other) @@ -614,7 +614,7 @@ class NSCharacterSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding { NSCharacterSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSCharacterSet] that points to the same underlying object as [other]. NSCharacterSet.castFrom(objc.ObjCObjectBase other) @@ -892,16 +892,35 @@ class NSCoder extends objc.ObjCObjectBase { } /// NSCoding -abstract interface class NSCoding implements objc.ObjCProtocolBase { +interface class NSCoding extends objc.ObjCProtocolBase { + NSCoding._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); + + /// Constructs a [NSCoding] that points to the same underlying object as [other]. + NSCoding.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSCoding] that wraps the given raw object pointer. + NSCoding.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSCoding]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz( + obj.ref.pointer, _sel_conformsToProtocol_, _protocol_NSCoding); + } + /// Builds an object that implements the NSCoding protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static objc.ObjCObjectBase implement( + static NSCoding implement( {required void Function(NSCoder) encodeWithCoder_, required Dartinstancetype? Function(NSCoder) initWithCoder_}) { final builder = objc.ObjCProtocolBuilder(); NSCoding.encodeWithCoder_.implement(builder, encodeWithCoder_); NSCoding.initWithCoder_.implement(builder, initWithCoder_); - return builder.build(); + return NSCoding.castFrom(builder.build()); } /// Adds the implementation of the NSCoding protocol to an existing @@ -916,13 +935,13 @@ abstract interface class NSCoding implements objc.ObjCProtocolBase { /// Builds an object that implements the NSCoding protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as listeners will be. - static objc.ObjCObjectBase implementAsListener( + static NSCoding implementAsListener( {required void Function(NSCoder) encodeWithCoder_, required Dartinstancetype? Function(NSCoder) initWithCoder_}) { final builder = objc.ObjCProtocolBuilder(); NSCoding.encodeWithCoder_.implementAsListener(builder, encodeWithCoder_); NSCoding.initWithCoder_.implement(builder, initWithCoder_); - return builder.build(); + return NSCoding.castFrom(builder.build()); } /// Adds the implementation of the NSCoding protocol to an existing @@ -938,13 +957,13 @@ abstract interface class NSCoding implements objc.ObjCProtocolBase { /// Builds an object that implements the NSCoding protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as blocking listeners will be. - static objc.ObjCObjectBase implementAsBlocking( + static NSCoding implementAsBlocking( {required void Function(NSCoder) encodeWithCoder_, required Dartinstancetype? Function(NSCoder) initWithCoder_}) { final builder = objc.ObjCProtocolBuilder(); NSCoding.encodeWithCoder_.implementAsBlocking(builder, encodeWithCoder_); NSCoding.initWithCoder_.implement(builder, initWithCoder_); - return builder.build(); + return NSCoding.castFrom(builder.build()); } /// Adds the implementation of the NSCoding protocol to an existing @@ -1012,15 +1031,34 @@ enum NSComparisonResult { } /// NSCopying -abstract interface class NSCopying implements objc.ObjCProtocolBase { +interface class NSCopying extends objc.ObjCProtocolBase { + NSCopying._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); + + /// Constructs a [NSCopying] that points to the same underlying object as [other]. + NSCopying.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSCopying] that wraps the given raw object pointer. + NSCopying.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSCopying]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz( + obj.ref.pointer, _sel_conformsToProtocol_, _protocol_NSCopying); + } + /// Builds an object that implements the NSCopying protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static objc.ObjCObjectBase implement( + static NSCopying implement( {required objc.ObjCObjectBase Function(ffi.Pointer) copyWithZone_}) { final builder = objc.ObjCProtocolBuilder(); NSCopying.copyWithZone_.implement(builder, copyWithZone_); - return builder.build(); + return NSCopying.castFrom(builder.build()); } /// Adds the implementation of the NSCopying protocol to an existing @@ -1053,7 +1091,7 @@ class NSData extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding { NSData._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSData] that points to the same underlying object as [other]. NSData.castFrom(objc.ObjCObjectBase other) @@ -1480,7 +1518,7 @@ enum NSDataWritingOptions { class NSDate extends NSObject implements NSCopying, NSSecureCoding { NSDate._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSDate] that points to the same underlying object as [other]. NSDate.castFrom(objc.ObjCObjectBase other) @@ -1646,7 +1684,7 @@ class NSDictionary extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSDictionary._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSDictionary] that points to the same underlying object as [other]. NSDictionary.castFrom(objc.ObjCObjectBase other) @@ -1847,7 +1885,7 @@ enum NSEnumerationOptions { class NSEnumerator extends NSObject implements NSFastEnumeration { NSEnumerator._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSEnumerator] that points to the same underlying object as [other]. NSEnumerator.castFrom(objc.ObjCObjectBase other) @@ -1912,7 +1950,7 @@ class NSEnumerator extends NSObject implements NSFastEnumeration { class NSError extends NSObject implements NSCopying, NSSecureCoding { NSError._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSError] that points to the same underlying object as [other]. NSError.castFrom(objc.ObjCObjectBase other) @@ -3183,17 +3221,36 @@ extension NSExtendedSet on NSSet { } /// NSFastEnumeration -abstract interface class NSFastEnumeration implements objc.ObjCProtocolBase { +interface class NSFastEnumeration extends objc.ObjCProtocolBase { + NSFastEnumeration._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); + + /// Constructs a [NSFastEnumeration] that points to the same underlying object as [other]. + NSFastEnumeration.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSFastEnumeration] that wraps the given raw object pointer. + NSFastEnumeration.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSFastEnumeration]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz( + obj.ref.pointer, _sel_conformsToProtocol_, _protocol_NSFastEnumeration); + } + /// Builds an object that implements the NSFastEnumeration protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static objc.ObjCObjectBase implement( + static NSFastEnumeration implement( {required int Function(ffi.Pointer, ffi.Pointer>, int) countByEnumeratingWithState_objects_count_}) { final builder = objc.ObjCProtocolBuilder(); NSFastEnumeration.countByEnumeratingWithState_objects_count_ .implement(builder, countByEnumeratingWithState_objects_count_); - return builder.build(); + return NSFastEnumeration.castFrom(builder.build()); } /// Adds the implementation of the NSFastEnumeration protocol to an existing @@ -3248,7 +3305,7 @@ class NSIndexSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding { NSIndexSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSIndexSet] that points to the same underlying object as [other]. NSIndexSet.castFrom(objc.ObjCObjectBase other) @@ -3440,7 +3497,7 @@ class NSIndexSet extends NSObject class NSInputStream extends NSStream { NSInputStream._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSInputStream] that points to the same underlying object as [other]. NSInputStream.castFrom(objc.ObjCObjectBase other) @@ -3554,7 +3611,7 @@ class NSInvocation extends objc.ObjCObjectBase { class NSItemProvider extends NSObject implements NSCopying { NSItemProvider._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSItemProvider] that points to the same underlying object as [other]. NSItemProvider.castFrom(objc.ObjCObjectBase other) @@ -3830,7 +3887,7 @@ class NSLocale extends objc.ObjCObjectBase { class NSMethodSignature extends NSObject { NSMethodSignature._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMethodSignature] that points to the same underlying object as [other]. NSMethodSignature.castFrom(objc.ObjCObjectBase other) @@ -3923,7 +3980,7 @@ class NSMethodSignature extends NSObject { class NSMutableArray extends NSArray { NSMutableArray._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMutableArray] that points to the same underlying object as [other]. NSMutableArray.castFrom(objc.ObjCObjectBase other) @@ -4090,16 +4147,35 @@ class NSMutableArray extends NSArray { } /// NSMutableCopying -abstract interface class NSMutableCopying implements objc.ObjCProtocolBase { +interface class NSMutableCopying extends objc.ObjCProtocolBase { + NSMutableCopying._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); + + /// Constructs a [NSMutableCopying] that points to the same underlying object as [other]. + NSMutableCopying.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSMutableCopying] that wraps the given raw object pointer. + NSMutableCopying.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSMutableCopying]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz( + obj.ref.pointer, _sel_conformsToProtocol_, _protocol_NSMutableCopying); + } + /// Builds an object that implements the NSMutableCopying protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static objc.ObjCObjectBase implement( + static NSMutableCopying implement( {required objc.ObjCObjectBase Function(ffi.Pointer) mutableCopyWithZone_}) { final builder = objc.ObjCProtocolBuilder(); NSMutableCopying.mutableCopyWithZone_ .implement(builder, mutableCopyWithZone_); - return builder.build(); + return NSMutableCopying.castFrom(builder.build()); } /// Adds the implementation of the NSMutableCopying protocol to an existing @@ -4132,7 +4208,7 @@ abstract interface class NSMutableCopying implements objc.ObjCProtocolBase { class NSMutableData extends NSData { NSMutableData._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMutableData] that points to the same underlying object as [other]. NSMutableData.castFrom(objc.ObjCObjectBase other) @@ -4461,7 +4537,7 @@ class NSMutableData extends NSData { class NSMutableDictionary extends NSDictionary { NSMutableDictionary._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMutableDictionary] that points to the same underlying object as [other]. NSMutableDictionary.castFrom(objc.ObjCObjectBase other) @@ -4659,7 +4735,7 @@ class NSMutableDictionary extends NSDictionary { class NSMutableIndexSet extends NSIndexSet { NSMutableIndexSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMutableIndexSet] that points to the same underlying object as [other]. NSMutableIndexSet.castFrom(objc.ObjCObjectBase other) @@ -4813,7 +4889,7 @@ class NSMutableIndexSet extends NSIndexSet { class NSMutableOrderedSet extends NSOrderedSet { NSMutableOrderedSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMutableOrderedSet] that points to the same underlying object as [other]. NSMutableOrderedSet.castFrom(objc.ObjCObjectBase other) @@ -5121,7 +5197,7 @@ class NSMutableOrderedSet extends NSOrderedSet { class NSMutableSet extends NSSet { NSMutableSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMutableSet] that points to the same underlying object as [other]. NSMutableSet.castFrom(objc.ObjCObjectBase other) @@ -5286,7 +5362,7 @@ class NSMutableSet extends NSSet { class NSMutableString extends NSString { NSMutableString._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSMutableString] that points to the same underlying object as [other]. NSMutableString.castFrom(objc.ObjCObjectBase other) @@ -5731,7 +5807,7 @@ class NSMutableString extends NSString { class NSNotification extends NSObject implements NSCopying, NSCoding { NSNotification._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSNotification] that points to the same underlying object as [other]. NSNotification.castFrom(objc.ObjCObjectBase other) @@ -5869,7 +5945,7 @@ class NSNotification extends NSObject implements NSCopying, NSCoding { class NSNumber extends NSValue { NSNumber._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSNumber] that points to the same underlying object as [other]. NSNumber.castFrom(objc.ObjCObjectBase other) @@ -6584,10 +6660,29 @@ class NSObject extends objc.ObjCObjectBase implements NSObjectProtocol { } /// NSObject -abstract interface class NSObjectProtocol implements objc.ObjCProtocolBase { +interface class NSObjectProtocol extends objc.ObjCProtocolBase { + NSObjectProtocol._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); + + /// Constructs a [NSObjectProtocol] that points to the same underlying object as [other]. + NSObjectProtocol.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSObjectProtocol] that wraps the given raw object pointer. + NSObjectProtocol.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSObjectProtocol]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz( + obj.ref.pointer, _sel_conformsToProtocol_, _protocol_NSObject); + } + /// Builds an object that implements the NSObject protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static objc.ObjCObjectBase implement( + static NSObjectProtocol implement( {required objc.ObjCObjectBase Function() autorelease, required objc.ObjCObjectBase Function() class1, required bool Function(Protocol) conformsToProtocol_, @@ -6639,7 +6734,7 @@ abstract interface class NSObjectProtocol implements objc.ObjCProtocolBase { NSObjectProtocol.self1.implement(builder, self1); NSObjectProtocol.superclass.implement(builder, superclass); NSObjectProtocol.zone.implement(builder, zone); - return builder.build(); + return NSObjectProtocol.castFrom(builder.build()); } /// Adds the implementation of the NSObject protocol to an existing @@ -6700,7 +6795,7 @@ abstract interface class NSObjectProtocol implements objc.ObjCProtocolBase { /// Builds an object that implements the NSObject protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as listeners will be. - static objc.ObjCObjectBase implementAsListener( + static NSObjectProtocol implementAsListener( {required objc.ObjCObjectBase Function() autorelease, required objc.ObjCObjectBase Function() class1, required bool Function(Protocol) conformsToProtocol_, @@ -6752,7 +6847,7 @@ abstract interface class NSObjectProtocol implements objc.ObjCProtocolBase { NSObjectProtocol.self1.implement(builder, self1); NSObjectProtocol.superclass.implement(builder, superclass); NSObjectProtocol.zone.implement(builder, zone); - return builder.build(); + return NSObjectProtocol.castFrom(builder.build()); } /// Adds the implementation of the NSObject protocol to an existing @@ -6814,7 +6909,7 @@ abstract interface class NSObjectProtocol implements objc.ObjCProtocolBase { /// Builds an object that implements the NSObject protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as blocking listeners will be. - static objc.ObjCObjectBase implementAsBlocking( + static NSObjectProtocol implementAsBlocking( {required objc.ObjCObjectBase Function() autorelease, required objc.ObjCObjectBase Function() class1, required bool Function(Protocol) conformsToProtocol_, @@ -6866,7 +6961,7 @@ abstract interface class NSObjectProtocol implements objc.ObjCProtocolBase { NSObjectProtocol.self1.implement(builder, self1); NSObjectProtocol.superclass.implement(builder, superclass); NSObjectProtocol.zone.implement(builder, zone); - return builder.build(); + return NSObjectProtocol.castFrom(builder.build()); } /// Adds the implementation of the NSObject protocol to an existing @@ -7282,7 +7377,7 @@ class NSOrderedCollectionDifference extends NSObject implements NSFastEnumeration { NSOrderedCollectionDifference._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSOrderedCollectionDifference] that points to the same underlying object as [other]. NSOrderedCollectionDifference.castFrom(objc.ObjCObjectBase other) @@ -7438,7 +7533,7 @@ class NSOrderedSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSOrderedSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSOrderedSet] that points to the same underlying object as [other]. NSOrderedSet.castFrom(objc.ObjCObjectBase other) @@ -7712,7 +7807,7 @@ class NSOrderedSet extends NSObject class NSOutputStream extends NSStream { NSOutputStream._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSOutputStream] that points to the same underlying object as [other]. NSOutputStream.castFrom(objc.ObjCObjectBase other) @@ -8009,16 +8104,36 @@ class NSRunLoop extends objc.ObjCObjectBase { } /// NSSecureCoding -abstract interface class NSSecureCoding implements NSCoding { +interface class NSSecureCoding extends objc.ObjCProtocolBase + implements NSCoding { + NSSecureCoding._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); + + /// Constructs a [NSSecureCoding] that points to the same underlying object as [other]. + NSSecureCoding.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSSecureCoding] that wraps the given raw object pointer. + NSSecureCoding.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSSecureCoding]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz( + obj.ref.pointer, _sel_conformsToProtocol_, _protocol_NSSecureCoding); + } + /// Builds an object that implements the NSSecureCoding protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static objc.ObjCObjectBase implement( + static NSSecureCoding implement( {required void Function(NSCoder) encodeWithCoder_, required Dartinstancetype? Function(NSCoder) initWithCoder_}) { final builder = objc.ObjCProtocolBuilder(); NSSecureCoding.encodeWithCoder_.implement(builder, encodeWithCoder_); NSSecureCoding.initWithCoder_.implement(builder, initWithCoder_); - return builder.build(); + return NSSecureCoding.castFrom(builder.build()); } /// Adds the implementation of the NSSecureCoding protocol to an existing @@ -8033,14 +8148,14 @@ abstract interface class NSSecureCoding implements NSCoding { /// Builds an object that implements the NSSecureCoding protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as listeners will be. - static objc.ObjCObjectBase implementAsListener( + static NSSecureCoding implementAsListener( {required void Function(NSCoder) encodeWithCoder_, required Dartinstancetype? Function(NSCoder) initWithCoder_}) { final builder = objc.ObjCProtocolBuilder(); NSSecureCoding.encodeWithCoder_ .implementAsListener(builder, encodeWithCoder_); NSSecureCoding.initWithCoder_.implement(builder, initWithCoder_); - return builder.build(); + return NSSecureCoding.castFrom(builder.build()); } /// Adds the implementation of the NSSecureCoding protocol to an existing @@ -8057,14 +8172,14 @@ abstract interface class NSSecureCoding implements NSCoding { /// Builds an object that implements the NSSecureCoding protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as blocking listeners will be. - static objc.ObjCObjectBase implementAsBlocking( + static NSSecureCoding implementAsBlocking( {required void Function(NSCoder) encodeWithCoder_, required Dartinstancetype? Function(NSCoder) initWithCoder_}) { final builder = objc.ObjCProtocolBuilder(); NSSecureCoding.encodeWithCoder_ .implementAsBlocking(builder, encodeWithCoder_); NSSecureCoding.initWithCoder_.implement(builder, initWithCoder_); - return builder.build(); + return NSSecureCoding.castFrom(builder.build()); } /// Adds the implementation of the NSSecureCoding protocol to an existing @@ -8120,7 +8235,7 @@ class NSSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSSet] that points to the same underlying object as [other]. NSSet.castFrom(objc.ObjCObjectBase other) @@ -8308,7 +8423,7 @@ enum NSSortOptions { class NSStream extends NSObject { NSStream._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSStream] that points to the same underlying object as [other]. NSStream.castFrom(objc.ObjCObjectBase other) @@ -8436,15 +8551,35 @@ class NSStream extends NSObject { } /// NSStreamDelegate -abstract interface class NSStreamDelegate implements NSObjectProtocol { +interface class NSStreamDelegate extends objc.ObjCProtocolBase + implements NSObjectProtocol { + NSStreamDelegate._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); + + /// Constructs a [NSStreamDelegate] that points to the same underlying object as [other]. + NSStreamDelegate.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSStreamDelegate] that wraps the given raw object pointer. + NSStreamDelegate.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSStreamDelegate]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz( + obj.ref.pointer, _sel_conformsToProtocol_, _protocol_NSStreamDelegate); + } + /// Builds an object that implements the NSStreamDelegate protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static objc.ObjCObjectBase implement( + static NSStreamDelegate implement( {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { final builder = objc.ObjCProtocolBuilder(); NSStreamDelegate.stream_handleEvent_ .implement(builder, stream_handleEvent_); - return builder.build(); + return NSStreamDelegate.castFrom(builder.build()); } /// Adds the implementation of the NSStreamDelegate protocol to an existing @@ -8458,12 +8593,12 @@ abstract interface class NSStreamDelegate implements NSObjectProtocol { /// Builds an object that implements the NSStreamDelegate protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as listeners will be. - static objc.ObjCObjectBase implementAsListener( + static NSStreamDelegate implementAsListener( {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { final builder = objc.ObjCProtocolBuilder(); NSStreamDelegate.stream_handleEvent_ .implementAsListener(builder, stream_handleEvent_); - return builder.build(); + return NSStreamDelegate.castFrom(builder.build()); } /// Adds the implementation of the NSStreamDelegate protocol to an existing @@ -8478,12 +8613,12 @@ abstract interface class NSStreamDelegate implements NSObjectProtocol { /// Builds an object that implements the NSStreamDelegate protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All /// methods that can be implemented as blocking listeners will be. - static objc.ObjCObjectBase implementAsBlocking( + static NSStreamDelegate implementAsBlocking( {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { final builder = objc.ObjCProtocolBuilder(); NSStreamDelegate.stream_handleEvent_ .implementAsBlocking(builder, stream_handleEvent_); - return builder.build(); + return NSStreamDelegate.castFrom(builder.build()); } /// Adds the implementation of the NSStreamDelegate protocol to an existing @@ -8581,7 +8716,7 @@ class NSString extends NSObject NSString._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSString] that points to the same underlying object as [other]. NSString.castFrom(objc.ObjCObjectBase other) @@ -9871,7 +10006,7 @@ extension NSStringExtensionMethods on NSString { class NSURL extends NSObject implements NSSecureCoding, NSCopying { NSURL._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSURL] that points to the same underlying object as [other]. NSURL.castFrom(objc.ObjCObjectBase other) @@ -10570,7 +10705,7 @@ enum NSURLBookmarkResolutionOptions { class NSURLHandle extends NSObject { NSURLHandle._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSURLHandle] that points to the same underlying object as [other]. NSURLHandle.castFrom(objc.ObjCObjectBase other) @@ -10654,7 +10789,7 @@ enum NSURLHandleStatus { class NSValue extends NSObject implements NSCopying, NSSecureCoding { NSValue._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super.castFromPointer(pointer, retain: retain, release: release); + : super._(pointer, retain: retain, release: release); /// Constructs a [NSValue] that points to the same underlying object as [other]. NSValue.castFrom(objc.ObjCObjectBase other) @@ -15110,6 +15245,16 @@ final _objc_msgSend_dv3z6r = objc.msgSendPointer bool, int, ffi.Pointer>)>(); +final _objc_msgSend_e3qsqz = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>() + .asFunction< + bool Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>(); final _objc_msgSend_e9mncn = objc.msgSendPointer .cast< ffi.NativeFunction< From af2e1bae84eb7a5d3a1025ae661653753bf79580 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 14:14:57 +1100 Subject: [PATCH 02/13] Translate id to Foo --- .../lib/src/code_generator/pointer.dart | 36 +++ .../clang_bindings/clang_bindings.dart | 288 +++++++++++++----- .../type_extractor/extractor.dart | 13 + .../test/native_objc_test/protocol_test.dart | 4 +- .../test/unit_tests/subtyping_test.dart | 34 ++- pkgs/ffigen/tool/libclang_config.yaml | 2 + 6 files changed, 301 insertions(+), 76 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/pointer.dart b/pkgs/ffigen/lib/src/code_generator/pointer.dart index 98abd88d6a..e76c2c5f8e 100644 --- a/pkgs/ffigen/lib/src/code_generator/pointer.dart +++ b/pkgs/ffigen/lib/src/code_generator/pointer.dart @@ -185,3 +185,39 @@ class ObjCBlockPointer extends ObjCObjectPointer { return other is ObjCBlockPointer || other is ObjCBlock; } } + +/// A pointer to an Objective C object with protocols. +class ObjCObjectPointerWithProtocols extends ObjCObjectPointer { + List protocols; + + ObjCObjectPointerWithProtocols(this.protocols) : assert(protocols.isNotEmpty), super._(); + + @override + String getDartType(Writer w) => protocols.first.getDartType(w); + + @override + bool isSupertypeOf(Type other) { + other = other.typealiasType; + if (other is ObjCObjectPointerWithProtocols) { + // The "correct" logic would be to return true if each of our protocols + // was a supertype of one of the other's protocols. But this method is + // designed to reflect the subtyping rules of the *Dart bindings*, not the + // ObjC types. So since the codegen just uses the first protocol, we do + // the same here. + return protocols.first.isSupertypeOf(other.protocols.first); + } + return false; + } + + @override + String toString() => 'id<${protocols.join(', ')}>'; + + @override + String cacheKey() => 'id<${protocols.map((p) => p.cacheKey()).join(', ')}>'; + + @override + void visitChildren(Visitor visitor) { + super.visitChildren(visitor); + visitor.visitAll(protocols); + } +} diff --git a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart index 7bedda292a..b0bdb8f866 100644 --- a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart +++ b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart @@ -954,6 +954,44 @@ class Clang { _clang_Type_getObjCObjectBaseTypePtr .asFunction(); + /// Retrieve the number of protocol references associated with an ObjC object/id. + /// + /// If the type is not an ObjC object, 0 is returned. + int clang_Type_getNumObjCProtocolRefs( + CXType T, + ) { + return _clang_Type_getNumObjCProtocolRefs( + T, + ); + } + + late final _clang_Type_getNumObjCProtocolRefsPtr = + _lookup>( + 'clang_Type_getNumObjCProtocolRefs'); + late final _clang_Type_getNumObjCProtocolRefs = + _clang_Type_getNumObjCProtocolRefsPtr.asFunction(); + + /// Retrieve the decl for a protocol reference for an ObjC object/id. + /// + /// If the type is not an ObjC object or there are not enough protocol + /// references, an invalid cursor is returned. + CXCursor clang_Type_getObjCProtocolDecl( + CXType T, + int i, + ) { + return _clang_Type_getObjCProtocolDecl( + T, + i, + ); + } + + late final _clang_Type_getObjCProtocolDeclPtr = + _lookup>( + 'clang_Type_getObjCProtocolDecl'); + late final _clang_Type_getObjCProtocolDecl = + _clang_Type_getObjCProtocolDeclPtr + .asFunction(); + /// Return 1 if the CXType is a variadic function type, and 0 otherwise. int clang_isFunctionTypeVariadic( CXType T, @@ -1546,8 +1584,25 @@ final class CXString extends ffi.Struct { external int private_flags; } +/// An "index" that consists of a set of translation units that would +/// typically be linked together into an executable or library. +typedef CXIndex = ffi.Pointer; + +final class CXTargetInfoImpl extends ffi.Opaque {} + +/// An opaque type representing target information for a given translation +/// unit. +typedef CXTargetInfo = ffi.Pointer; + final class CXTranslationUnitImpl extends ffi.Opaque {} +/// A single translation unit, which resides in an index. +typedef CXTranslationUnit = ffi.Pointer; + +/// Opaque pointer representing client data that will be passed through +/// to various callbacks and visitors. +typedef CXClientData = ffi.Pointer; + /// Provides the contents of a file that has not yet been saved to disk. /// /// Each CXUnsavedFile instance provides the name of a file on the @@ -1567,9 +1622,44 @@ final class CXUnsavedFile extends ffi.Struct { external int Length; } -/// An "index" that consists of a set of translation units that would -/// typically be linked together into an executable or library. -typedef CXIndex = ffi.Pointer; +/// Describes the availability of a particular entity, which indicates +/// whether the use of this entity will result in a warning or error due to +/// it being deprecated or unavailable. +sealed class CXAvailabilityKind { + /// The entity is available. + static const CXAvailability_Available = 0; + + /// The entity is available, but has been deprecated (and its use is + /// not recommended). + static const CXAvailability_Deprecated = 1; + + /// The entity is not available; any use of it will be an error. + static const CXAvailability_NotAvailable = 2; + + /// The entity is available, but not accessible; any use of it will be + /// an error. + static const CXAvailability_NotAccessible = 3; +} + +/// Describes a version number of the form major.minor.subminor. +final class CXVersion extends ffi.Struct { + /// The major version number, e.g., the '10' in '10.7.3'. A negative + /// value indicates that there is no version number at all. + @ffi.Int() + external int Major; + + /// The minor version number, e.g., the '7' in '10.7.3'. This value + /// will be negative if no minor version number was provided, e.g., for + /// version '10'. + @ffi.Int() + external int Minor; + + /// The subminor version number, e.g., the '3' in '10.7.3'. This value + /// will be negative if no minor or subminor version number was provided, + /// e.g., in version '10' or '10.7'. + @ffi.Int() + external int Subminor; +} /// A particular source file that is part of a translation unit. typedef CXFile = ffi.Pointer; @@ -1602,13 +1692,36 @@ final class CXSourceRange extends ffi.Struct { external int end_int_data; } -/// A single translation unit, which resides in an index. -typedef CXTranslationUnit = ffi.Pointer; +/// Describes the severity of a particular diagnostic. +sealed class CXDiagnosticSeverity { + /// A diagnostic that has been suppressed, e.g., by a command-line + /// option. + static const CXDiagnostic_Ignored = 0; + + /// This diagnostic is a note that should be attached to the + /// previous (non-note) diagnostic. + static const CXDiagnostic_Note = 1; + + /// This diagnostic indicates suspicious code that may not be + /// wrong. + static const CXDiagnostic_Warning = 2; + + /// This diagnostic indicates that the code is ill-formed. + static const CXDiagnostic_Error = 3; + + /// This diagnostic indicates that the code is ill-formed such + /// that future parser recovery is unlikely to produce useful + /// results. + static const CXDiagnostic_Fatal = 4; +} /// A single diagnostic, containing the diagnostic's severity, /// location, text, source ranges, and fix-it hints. typedef CXDiagnostic = ffi.Pointer; +/// A group of CXDiagnostics. +typedef CXDiagnosticSet = ffi.Pointer; + /// Options to control the display of diagnostics. /// /// The values in this enum are meant to be combined to customize the @@ -1663,29 +1776,6 @@ sealed class CXDiagnosticDisplayOptions { static const CXDiagnostic_DisplayCategoryName = 32; } -/// Describes the severity of a particular diagnostic. -sealed class CXDiagnosticSeverity { - /// A diagnostic that has been suppressed, e.g., by a command-line - /// option. - static const CXDiagnostic_Ignored = 0; - - /// This diagnostic is a note that should be attached to the - /// previous (non-note) diagnostic. - static const CXDiagnostic_Note = 1; - - /// This diagnostic indicates suspicious code that may not be - /// wrong. - static const CXDiagnostic_Warning = 2; - - /// This diagnostic indicates that the code is ill-formed. - static const CXDiagnostic_Error = 3; - - /// This diagnostic indicates that the code is ill-formed such - /// that future parser recovery is unlikely to produce useful - /// results. - static const CXDiagnostic_Fatal = 4; -} - /// Flags that control the creation of translation units. /// /// The enumerators in this enumeration type are meant to be bitwise @@ -2618,25 +2708,6 @@ final class CXCursor extends ffi.Struct { external ffi.Array> data; } -/// Describes the availability of a particular entity, which indicates -/// whether the use of this entity will result in a warning or error due to -/// it being deprecated or unavailable. -sealed class CXAvailabilityKind { - /// The entity is available. - static const CXAvailability_Available = 0; - - /// The entity is available, but has been deprecated (and its use is - /// not recommended). - static const CXAvailability_Deprecated = 1; - - /// The entity is not available; any use of it will be an error. - static const CXAvailability_NotAvailable = 2; - - /// The entity is available, but not accessible; any use of it will be - /// an error. - static const CXAvailability_NotAccessible = 3; -} - /// Describes the availability of a given entity on a particular platform, e.g., /// a particular class might only be available on Mac OS 10.7 or newer. final class CXPlatformAvailability extends ffi.Struct { @@ -2666,25 +2737,10 @@ final class CXPlatformAvailability extends ffi.Struct { external CXString Message; } -/// Describes a version number of the form major.minor.subminor. -final class CXVersion extends ffi.Struct { - /// The major version number, e.g., the '10' in '10.7.3'. A negative - /// value indicates that there is no version number at all. - @ffi.Int() - external int Major; - - /// The minor version number, e.g., the '7' in '10.7.3'. This value - /// will be negative if no minor version number was provided, e.g., for - /// version '10'. - @ffi.Int() - external int Minor; +final class CXCursorSetImpl extends ffi.Opaque {} - /// The subminor version number, e.g., the '3' in '10.7.3'. This value - /// will be negative if no minor or subminor version number was provided, - /// e.g., in version '10' or '10.7'. - @ffi.Int() - external int Subminor; -} +/// A fast container representing a set of CXCursors. +typedef CXCursorSet = ffi.Pointer; /// Describes the kind of type sealed class CXTypeKind { @@ -2899,6 +2955,11 @@ sealed class CXChildVisitResult { static const CXChildVisit_Recurse = 2; } +typedef CXCursorVisitorFunction = ffi.UnsignedInt Function( + CXCursor cursor, CXCursor parent, CXClientData client_data); +typedef DartCXCursorVisitorFunction = int Function( + CXCursor cursor, CXCursor parent, CXClientData client_data); + /// Visitor invoked for each cursor found by a traversal. /// /// This visitor function will be invoked for each cursor found by @@ -2911,14 +2972,10 @@ sealed class CXChildVisitResult { /// to direct clang_visitCursorChildren(). typedef CXCursorVisitor = ffi.Pointer>; -typedef CXCursorVisitorFunction = ffi.UnsignedInt Function( - CXCursor cursor, CXCursor parent, CXClientData client_data); -typedef DartCXCursorVisitorFunction = int Function( - CXCursor cursor, CXCursor parent, CXClientData client_data); -/// Opaque pointer representing client data that will be passed through -/// to various callbacks and visitors. -typedef CXClientData = ffi.Pointer; +/// Opaque pointer representing a policy that controls pretty printing +/// for \c clang_getCursorPrettyPrinted. +typedef CXPrintingPolicy = ffi.Pointer; /// Property attributes for a \c CXCursor_ObjCPropertyDecl. sealed class CXObjCPropertyAttrKind { @@ -2938,6 +2995,48 @@ sealed class CXObjCPropertyAttrKind { static const CXObjCPropertyAttr_class = 4096; } +/// \defgroup CINDEX_MODULE Module introspection +/// +/// The functions in this group provide access to information about modules. +/// +/// @{ +typedef CXModule = ffi.Pointer; + +/// A semantic string that describes a code-completion result. +/// +/// A semantic string that describes the formatting of a code-completion +/// result as a single "template" of text that should be inserted into the +/// source buffer when a particular code-completion result is selected. +/// Each semantic string is made up of some number of "chunks", each of which +/// contains some text along with a description of what that text means, e.g., +/// the name of the entity being referenced, whether the text chunk is part of +/// the template, or whether it is a "placeholder" that the user should replace +/// with actual code,of a specific kind. See \c CXCompletionChunkKind for a +/// description of the different kinds of chunks. +typedef CXCompletionString = ffi.Pointer; +typedef CXInclusionVisitorFunction = ffi.Void Function( + CXFile included_file, + ffi.Pointer inclusion_stack, + ffi.UnsignedInt include_len, + CXClientData client_data); +typedef DartCXInclusionVisitorFunction = void Function( + CXFile included_file, + ffi.Pointer inclusion_stack, + int include_len, + CXClientData client_data); + +/// Visitor invoked for each file in a translation unit +/// (used with clang_getInclusions()). +/// +/// This visitor function will be invoked by clang_getInclusions() for each +/// file included (either at the top-level or by \#include directives) within +/// a translation unit. The first argument is the file being included, and +/// the second and third arguments provide the inclusion stack. The +/// array is sorted in order of immediate inclusion. For example, +/// the first element refers to the location that included 'included_file'. +typedef CXInclusionVisitor + = ffi.Pointer>; + sealed class CXEvalResultKind { static const CXEval_Int = 1; static const CXEval_Float = 2; @@ -2951,6 +3050,51 @@ sealed class CXEvalResultKind { /// Evaluation result of a cursor typedef CXEvalResult = ffi.Pointer; +/// A remapping of original source files and their translated files. +typedef CXRemapping = ffi.Pointer; + +/// \defgroup CINDEX_HIGH Higher level API functions +/// +/// @{ +sealed class CXVisitorResult { + static const CXVisit_Break = 0; + static const CXVisit_Continue = 1; +} + +/// The client's data object that is associated with a CXFile. +typedef CXIdxClientFile = ffi.Pointer; + +/// The client's data object that is associated with a semantic entity. +typedef CXIdxClientEntity = ffi.Pointer; + +/// The client's data object that is associated with a semantic container +/// of entities. +typedef CXIdxClientContainer = ffi.Pointer; + +/// The client's data object that is associated with an AST file (PCH +/// or module). +typedef CXIdxClientASTFile = ffi.Pointer; + +/// An indexing action/session, to be applied to one or multiple +/// translation units. +typedef CXIndexAction = ffi.Pointer; +typedef CXFieldVisitorFunction = ffi.UnsignedInt Function( + CXCursor C, CXClientData client_data); +typedef DartCXFieldVisitorFunction = int Function( + CXCursor C, CXClientData client_data); + +/// Visitor invoked for each field found by a traversal. +/// +/// This visitor function will be invoked for each field found by +/// \c clang_Type_visitFields. Its first argument is the cursor being +/// visited, its second argument is the client data provided to +/// \c clang_Type_visitFields. +/// +/// The visitor should return one of the \c CXVisitorResult values +/// to direct \c clang_Type_visitFields. +typedef CXFieldVisitor + = ffi.Pointer>; + const int CINDEX_VERSION_MAJOR = 0; const int CINDEX_VERSION_MINOR = 59; diff --git a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart index 42743fdfdf..78689b8d75 100644 --- a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart +++ b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart @@ -17,6 +17,7 @@ import '../sub_parsers/enumdecl_parser.dart'; import '../sub_parsers/function_type_param_parser.dart'; import '../sub_parsers/objc_block_parser.dart'; import '../sub_parsers/objcinterfacedecl_parser.dart'; +import '../sub_parsers/objcprotocoldecl_parser.dart'; import '../sub_parsers/typedefdecl_parser.dart'; import '../type_extractor/cxtypekindmap.dart'; import '../utils.dart'; @@ -55,6 +56,18 @@ Type getCodeGenType( if (s is ObjCInterface) { return s; } + final numProtocols = clang.clang_Type_getNumObjCProtocolRefs(pt); + if (numProtocols > 0) { + final protocols = []; + for (var i = 0; i < numProtocols; ++i) { + final pdecl = clang.clang_Type_getObjCProtocolDecl(pt, i); + final p = parseObjCProtocolDeclaration(pdecl); + if (p != null) protocols.add(p); + } + if (protocols.isNotEmpty) { + return ObjCObjectPointerWithProtocols(protocols); + } + } return PointerType(objCObjectType); case clang_types.CXTypeKind.CXType_ObjCId: case clang_types.CXTypeKind.CXType_ObjCTypeParam: diff --git a/pkgs/ffigen/test/native_objc_test/protocol_test.dart b/pkgs/ffigen/test/native_objc_test/protocol_test.dart index fad9415918..f949d4887d 100644 --- a/pkgs/ffigen/test/native_objc_test/protocol_test.dart +++ b/pkgs/ffigen/test/native_objc_test/protocol_test.dart @@ -332,11 +332,11 @@ void main() { SecondaryProtocol.castFrom(protocolImpl); // Required instance method from secondary protocol. - final otherIntResult = consumer.callOtherMethod_(asMyProtocol); + final otherIntResult = consumer.callOtherMethod_(asSecondaryProtocol); expect(otherIntResult, 24); // Blocking method. - consumer.callBlockingMethodOnRandomThread_(asSecondaryProtocol); + consumer.callBlockingMethodOnRandomThread_(asMyProtocol); expect(await listenerCompleter.future, 98765); }); }); diff --git a/pkgs/ffigen/test/unit_tests/subtyping_test.dart b/pkgs/ffigen/test/unit_tests/subtyping_test.dart index 3c23f7d047..59d26afe2a 100644 --- a/pkgs/ffigen/test/unit_tests/subtyping_test.dart +++ b/pkgs/ffigen/test/unit_tests/subtyping_test.dart @@ -41,8 +41,8 @@ void main() { final proto2 = makeProtocol('Proto2', []); final proto3 = makeProtocol('Proto3', []); final proto4 = makeProtocol('Proto4', []); - final protoSub1 = makeProtocol('ProtoS1', [proto1]); - final protoSub12 = makeProtocol('ProtoS12', [protoSub1, proto2]); + final protoSub1 = makeProtocol('ProtoSub1', [proto1]); + final protoSub12 = makeProtocol('ProtoSub12', [protoSub1, proto2]); final grandparent = makeInterface('Grandparent', null, [protoSub12]); final parent = makeInterface('Parent', grandparent, [protoSub1, proto3]); @@ -353,5 +353,35 @@ void main() { expect(block.isSubtypeOf(ObjCBlockPointer()), isTrue); expect(ObjCBlockPointer().isSubtypeOf(block), isFalse); }); + + test('ObjCObjectPointerWithProtocols', () { + final idP1 = ObjCObjectPointerWithProtocols([proto1]); + final idP2 = ObjCObjectPointerWithProtocols([proto2]); + final idP1P2 = ObjCObjectPointerWithProtocols([proto1, proto2]); + final idP2P1 = ObjCObjectPointerWithProtocols([proto2, proto1]); + final idPSub1 = ObjCObjectPointerWithProtocols([protoSub1]); + final idPSub12 = ObjCObjectPointerWithProtocols([protoSub12]); + + expect(idP1.isSubtypeOf(idP1), isTrue); + expect(idP1.isSubtypeOf(idP2), isFalse); + expect(idP2.isSubtypeOf(idP1), isFalse); + + expect(idP1P2.isSubtypeOf(idP1), isTrue); + expect(idP1.isSubtypeOf(idP1P2), isTrue); + expect(idP1P2.isSubtypeOf(idP2), isFalse); + expect(idP1P2.isSubtypeOf(idP2P1), isFalse); + expect(idP2P1.isSubtypeOf(idP2), isTrue); + expect(idP2.isSubtypeOf(idP2P1), isTrue); + + expect(idPSub1.isSubtypeOf(idP1), isTrue); + expect(idP1.isSubtypeOf(idPSub1), isFalse); + expect(idPSub12.isSubtypeOf(idP1), isTrue); + expect(idPSub12.isSubtypeOf(idP2), isTrue); + expect(idP1.isSubtypeOf(idPSub12), isFalse); + expect(idP2.isSubtypeOf(idPSub12), isFalse); + + expect(ObjCObjectPointer().isSubtypeOf(idP1), isFalse); + expect(idP1.isSubtypeOf(ObjCObjectPointer()), isTrue); + }); }); } diff --git a/pkgs/ffigen/tool/libclang_config.yaml b/pkgs/ffigen/tool/libclang_config.yaml index 4b305df54c..1efa9f783a 100644 --- a/pkgs/ffigen/tool/libclang_config.yaml +++ b/pkgs/ffigen/tool/libclang_config.yaml @@ -134,3 +134,5 @@ functions: - clang_Type_getModifiedType - clang_Location_isInSystemHeader - clang_getClangVersion + - clang_Type_getNumObjCProtocolRefs + - clang_Type_getObjCProtocolDecl From 44a1eac8b6d4c4188f4dd484d1adcd3d833db48d Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 14:27:52 +1100 Subject: [PATCH 03/13] fmt --- pkgs/ffigen/CHANGELOG.md | 10 ++++++++++ pkgs/ffigen/lib/src/code_generator/pointer.dart | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md index 2db1169bb2..a0952e985c 100644 --- a/pkgs/ffigen/CHANGELOG.md +++ b/pkgs/ffigen/CHANGELOG.md @@ -3,6 +3,16 @@ - Use package:objective_c 5.0.0 - Support transitive categories of built-in types: https://github.com/dart-lang/native/issues/1820 +- __Breaking change__: Maintain protocol conformance when translating from ObjC + to Dart. For example, ObjC's `id` is now translated to Dart's + `FooProtocol`. Generally this shouldn't be a breaking change for code that is + using protocols correctly, with a few caveats: + - For more advanced use cases that use `ObjCProtocolBuilder` directly, after + calling `build()` you will need to cast the generated object to the target + protocol: `FooProtocol.castFrom(protocolBuilder.build())`. + - Due to limitations in the Dart type system, only the first protocol of an + `id` is used: `id` becomes `FooProtocol`. The + `FooProtocol.castFrom` method can help work around issues this may cause. ## 16.1.0 diff --git a/pkgs/ffigen/lib/src/code_generator/pointer.dart b/pkgs/ffigen/lib/src/code_generator/pointer.dart index e76c2c5f8e..08fa745ba6 100644 --- a/pkgs/ffigen/lib/src/code_generator/pointer.dart +++ b/pkgs/ffigen/lib/src/code_generator/pointer.dart @@ -190,7 +190,9 @@ class ObjCBlockPointer extends ObjCObjectPointer { class ObjCObjectPointerWithProtocols extends ObjCObjectPointer { List protocols; - ObjCObjectPointerWithProtocols(this.protocols) : assert(protocols.isNotEmpty), super._(); + ObjCObjectPointerWithProtocols(this.protocols) + : assert(protocols.isNotEmpty), + super._(); @override String getDartType(Writer w) => protocols.first.getDartType(w); From aaf68c34f27366d7a17d1190a52e701827018179 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 14:29:34 +1100 Subject: [PATCH 04/13] Fix analysis --- pkgs/objective_c/lib/src/internal.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/objective_c/lib/src/internal.dart b/pkgs/objective_c/lib/src/internal.dart index 17b1c7dffb..e7851e0e2f 100644 --- a/pkgs/objective_c/lib/src/internal.dart +++ b/pkgs/objective_c/lib/src/internal.dart @@ -329,8 +329,7 @@ bool _isValidClass(ObjectPtr clazz) { /// Only for use by ffigen bindings. class ObjCProtocolBase extends ObjCObjectBase { - ObjCProtocolBase(ObjectPtr ptr, {required bool retain, required bool release}) - : super(ptr, retain: retain, release: release); + ObjCProtocolBase(super.ptr, {required super.retain, required super.release}); } @pragma('vm:deeply-immutable') From 220344d5fc26bc37e44455c561c64307b7668770 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 14:44:13 +1100 Subject: [PATCH 05/13] More fixes --- .../lib/src/code_generator/objc_protocol.dart | 10 ++++++---- pkgs/ffigen/test/unit_tests/subtyping_test.dart | 13 +++++++++++++ pkgs/objective_c/test/interface_lists_test.dart | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index 4b71499bd2..57626090a4 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -305,10 +305,12 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } String? generateRetain(String value) => '(__bridge id)(__bridge_retained void*)($value)'; - bool _isSuperProtocolOf(ObjCProtocol protocol) { + bool _isSuperProtocolOf(ObjCProtocol protocol, Set visited) { if (protocol == this) return true; + if (visited.contains(protocol)) return false; + visited.add(protocol); for (final superProtocol in protocol.superProtocols) { - if (_isSuperProtocolOf(superProtocol)) return true; + if (_isSuperProtocolOf(superProtocol, visited)) return true; } return false; } @@ -317,11 +319,11 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } bool isSupertypeOf(Type other) { other = other.typealiasType; if (other is ObjCProtocol) { - return _isSuperProtocolOf(other); + return _isSuperProtocolOf(other, {}); } else if (other is ObjCInterface) { for (ObjCInterface? t = other; t != null; t = t.superType) { for (final protocol in t.protocols) { - if (_isSuperProtocolOf(protocol)) return true; + if (_isSuperProtocolOf(protocol, {})) return true; } } } diff --git a/pkgs/ffigen/test/unit_tests/subtyping_test.dart b/pkgs/ffigen/test/unit_tests/subtyping_test.dart index 59d26afe2a..16d776619d 100644 --- a/pkgs/ffigen/test/unit_tests/subtyping_test.dart +++ b/pkgs/ffigen/test/unit_tests/subtyping_test.dart @@ -128,6 +128,19 @@ void main() { expect(proto3.isSupertypeOf(proto1), isFalse); }); + test('loop', () { + final loop = ObjCProtocol( + usr: "Loop", + originalName: "Loop", + builtInFunctions: builtInFunctions, + ); + loop.superProtocols.add(loop); + + expect(loop.isSupertypeOf(loop), isTrue); + expect(loop.isSupertypeOf(proto1), isFalse); + expect(proto1.isSupertypeOf(loop), isFalse); + }); + test('vs ObjCInterface', () { expect(grandparent.isSubtypeOf(protoSub12), isTrue); expect(grandparent.isSubtypeOf(protoSub1), isTrue); diff --git a/pkgs/objective_c/test/interface_lists_test.dart b/pkgs/objective_c/test/interface_lists_test.dart index 9a884ee52e..7c246d1542 100644 --- a/pkgs/objective_c/test/interface_lists_test.dart +++ b/pkgs/objective_c/test/interface_lists_test.dart @@ -163,7 +163,7 @@ void main() { }); test('All code genned protocols are included in the list', () { - final protocolNameRegExp = RegExp(r'^abstract interface class (\w+) '); + final protocolNameRegExp = RegExp(r'^interface class (\w+) '); final allProtocolNames = []; for (final line in File('lib/src/objective_c_bindings_generated.dart') .readAsLinesSync()) { From a05891f02991d129cbd1dde1cab8c3ee0a4323f2 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 15:01:21 +1100 Subject: [PATCH 06/13] Fixes --- .../src/code_generator/objc_interface.dart | 1 - .../test/unit_tests/subtyping_test.dart | 4 +- .../src/objective_c_bindings_generated.dart | 503 +++--------------- .../src/objective_c_bindings_generated.m | 42 +- 4 files changed, 84 insertions(+), 466 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart index 72774ce055..99027b9cda 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart @@ -73,7 +73,6 @@ class ObjCInterface extends BindingType with ObjCMethods { final rawObjType = PointerType(objCObjectType).getCType(w); final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(w); - final superTypeIsInPkgObjc = superType == null; final protoImpl = protocols.isEmpty ? '' : 'implements ${protocols.map((p) => p.getDartType(w)).join(', ')} '; diff --git a/pkgs/ffigen/test/unit_tests/subtyping_test.dart b/pkgs/ffigen/test/unit_tests/subtyping_test.dart index 16d776619d..c5855cb6b4 100644 --- a/pkgs/ffigen/test/unit_tests/subtyping_test.dart +++ b/pkgs/ffigen/test/unit_tests/subtyping_test.dart @@ -130,8 +130,8 @@ void main() { test('loop', () { final loop = ObjCProtocol( - usr: "Loop", - originalName: "Loop", + usr: 'Loop', + originalName: 'Loop', builtInFunctions: builtInFunctions, ); loop.superProtocols.add(loop); diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index cb13e8d7f1..43bc2669b2 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -70,23 +70,6 @@ external ffi.Pointer awaitWaiter, ); -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer Function()>>, - ffi.Pointer< - ffi.NativeFunction)>>)>( - isLeaf: true) -external ffi.Pointer - _ObjectiveCBindings_wrapBlockingBlock_hoampi( - ffi.Pointer block, - ffi.Pointer listnerBlock, - ffi.Pointer Function()>> newWaiter, - ffi.Pointer)>> - awaitWaiter, -); - @ffi.Native< ffi.Pointer Function( ffi.Pointer, @@ -137,14 +120,6 @@ external ffi.Pointer ffi.Pointer block, ); -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer)>(isLeaf: true) -external ffi.Pointer - _ObjectiveCBindings_wrapListenerBlock_hoampi( - ffi.Pointer block, -); - @ffi.Native< ffi.Pointer Function( ffi.Pointer)>(isLeaf: true) @@ -266,16 +241,6 @@ class DartInputStreamAdapter extends NSInputStream implements NSStreamDelegate { void setError_(NSError error) { _objc_msgSend_xtuoz7(this.ref.pointer, _sel_setError_, error.ref.pointer); } - - /// stream:handleEvent: - void stream_handleEvent_(NSStream aStream, NSStreamEvent eventCode) { - if (!objc.respondsToSelector(this.ref.pointer, _sel_stream_handleEvent_)) { - throw objc.UnimplementedOptionalMethodException( - 'DOBJCDartInputStreamAdapter', 'stream:handleEvent:'); - } - _objc_msgSend_3l8zum(this.ref.pointer, _sel_stream_handleEvent_, - aStream.ref.pointer, eventCode.value); - } } /// DOBJCDartProxy @@ -1729,7 +1694,7 @@ class NSDictionary extends NSObject /// dictionaryWithObject:forKey: static NSDictionary dictionaryWithObject_forKey_( - objc.ObjCObjectBase object, objc.ObjCObjectBase key) { + objc.ObjCObjectBase object, NSCopying key) { final _ret = _objc_msgSend_15qeuct(_class_NSDictionary, _sel_dictionaryWithObject_forKey_, object.ref.pointer, key.ref.pointer); return NSDictionary.castFromPointer(_ret, retain: true, release: true); @@ -2823,8 +2788,7 @@ extension NSExtendedMutableDictionary on NSMutableDictionary { } /// setObject:forKeyedSubscript: - void setObject_forKeyedSubscript_( - objc.ObjCObjectBase? obj, objc.ObjCObjectBase key) { + void setObject_forKeyedSubscript_(objc.ObjCObjectBase? obj, NSCopying key) { _objc_msgSend_pfv6jd(this.ref.pointer, _sel_setObject_forKeyedSubscript_, obj?.ref.pointer ?? ffi.nullptr, key.ref.pointer); } @@ -3654,7 +3618,7 @@ class NSItemProvider extends NSObject implements NSCopying { } /// canLoadObjectOfClass: - bool canLoadObjectOfClass_(objc.ObjCObjectBase aClass) { + bool canLoadObjectOfClass_(NSItemProviderReading aClass) { return _objc_msgSend_19nvye5( this.ref.pointer, _sel_canLoadObjectOfClass_, aClass.ref.pointer); } @@ -3693,7 +3657,7 @@ class NSItemProvider extends NSObject implements NSCopying { /// initWithItem:typeIdentifier: NSItemProvider initWithItem_typeIdentifier_( - objc.ObjCObjectBase? item, NSString? typeIdentifier) { + NSSecureCoding? item, NSString? typeIdentifier) { final _ret = _objc_msgSend_15qeuct( this.ref.retainAndReturnPointer(), _sel_initWithItem_typeIdentifier_, @@ -3703,7 +3667,7 @@ class NSItemProvider extends NSObject implements NSCopying { } /// initWithObject: - NSItemProvider initWithObject_(objc.ObjCObjectBase object) { + NSItemProvider initWithObject_(NSItemProviderWriting object) { final _ret = _objc_msgSend_1sotr3r(this.ref.retainAndReturnPointer(), _sel_initWithObject_, object.ref.pointer); return NSItemProvider.castFromPointer(_ret, retain: false, release: true); @@ -3724,7 +3688,7 @@ class NSItemProvider extends NSObject implements NSCopying { } /// registerObject:visibility: - void registerObject_visibility_(objc.ObjCObjectBase object, + void registerObject_visibility_(NSItemProviderWriting object, NSItemProviderRepresentationVisibility visibility) { _objc_msgSend_1k745tv(this.ref.pointer, _sel_registerObject_visibility_, object.ref.pointer, visibility.value); @@ -3785,6 +3749,17 @@ enum NSItemProviderFileOptions { }; } +/// WARNING: NSItemProviderReading is a stub. To generate bindings for this class, include +/// NSItemProviderReading in your config's objc-protocols list. +/// +/// NSItemProviderReading +interface class NSItemProviderReading extends objc.ObjCProtocolBase + implements NSObjectProtocol { + NSItemProviderReading._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); +} + enum NSItemProviderRepresentationVisibility { NSItemProviderRepresentationVisibilityAll(0), NSItemProviderRepresentationVisibilityTeam(1), @@ -3805,6 +3780,17 @@ enum NSItemProviderRepresentationVisibility { }; } +/// WARNING: NSItemProviderWriting is a stub. To generate bindings for this class, include +/// NSItemProviderWriting in your config's objc-protocols list. +/// +/// NSItemProviderWriting +interface class NSItemProviderWriting extends objc.ObjCProtocolBase + implements NSObjectProtocol { + NSItemProviderWriting._(ffi.Pointer pointer, + {bool retain = false, bool release = false}) + : super(pointer, retain: retain, release: release); +} + enum NSKeyValueChange { NSKeyValueChangeSetting(1), NSKeyValueChangeInsertion(2), @@ -4595,7 +4581,7 @@ class NSMutableDictionary extends NSDictionary { /// dictionaryWithObject:forKey: static NSMutableDictionary dictionaryWithObject_forKey_( - objc.ObjCObjectBase object, objc.ObjCObjectBase key) { + objc.ObjCObjectBase object, NSCopying key) { final _ret = _objc_msgSend_15qeuct(_class_NSMutableDictionary, _sel_dictionaryWithObject_forKey_, object.ref.pointer, key.ref.pointer); return NSMutableDictionary.castFromPointer(_ret, @@ -4724,8 +4710,7 @@ class NSMutableDictionary extends NSDictionary { } /// setObject:forKey: - void setObject_forKey_( - objc.ObjCObjectBase anObject, objc.ObjCObjectBase aKey) { + void setObject_forKey_(objc.ObjCObjectBase anObject, NSCopying aKey) { _objc_msgSend_pfv6jd(this.ref.pointer, _sel_setObject_forKey_, anObject.ref.pointer, aKey.ref.pointer); } @@ -8471,11 +8456,11 @@ class NSStream extends NSObject { } /// delegate - objc.ObjCObjectBase? get delegate { + NSStreamDelegate? get delegate { final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_delegate); return _ret.address == 0 ? null - : objc.ObjCObjectBase(_ret, retain: true, release: true); + : NSStreamDelegate(_ret, retain: true, release: true); } /// init @@ -8524,7 +8509,7 @@ class NSStream extends NSObject { } /// setDelegate: - set delegate(objc.ObjCObjectBase? value) { + set delegate(NSStreamDelegate? value) { _objc_msgSend_xtuoz7( this.ref.pointer, _sel_setDelegate_, value?.ref.pointer ?? ffi.nullptr); } @@ -8552,7 +8537,7 @@ class NSStream extends NSObject { /// NSStreamDelegate interface class NSStreamDelegate extends objc.ObjCProtocolBase - implements NSObjectProtocol { + implements NSStreamDelegate { NSStreamDelegate._(ffi.Pointer pointer, {bool retain = false, bool release = false}) : super(pointer, retain: retain, release: release); @@ -8574,86 +8559,17 @@ interface class NSStreamDelegate extends objc.ObjCProtocolBase /// Builds an object that implements the NSStreamDelegate protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static NSStreamDelegate implement( - {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { - final builder = objc.ObjCProtocolBuilder(); - NSStreamDelegate.stream_handleEvent_ - .implement(builder, stream_handleEvent_); - return NSStreamDelegate.castFrom(builder.build()); - } - - /// Adds the implementation of the NSStreamDelegate protocol to an existing - /// [objc.ObjCProtocolBuilder]. - static void addToBuilder(objc.ObjCProtocolBuilder builder, - {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { - NSStreamDelegate.stream_handleEvent_ - .implement(builder, stream_handleEvent_); - } - - /// Builds an object that implements the NSStreamDelegate protocol. To implement - /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All - /// methods that can be implemented as listeners will be. - static NSStreamDelegate implementAsListener( - {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { + static NSStreamDelegate implement() { final builder = objc.ObjCProtocolBuilder(); - NSStreamDelegate.stream_handleEvent_ - .implementAsListener(builder, stream_handleEvent_); - return NSStreamDelegate.castFrom(builder.build()); - } - - /// Adds the implementation of the NSStreamDelegate protocol to an existing - /// [objc.ObjCProtocolBuilder]. All methods that can be implemented as listeners will - /// be. - static void addToBuilderAsListener(objc.ObjCProtocolBuilder builder, - {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { - NSStreamDelegate.stream_handleEvent_ - .implementAsListener(builder, stream_handleEvent_); - } - /// Builds an object that implements the NSStreamDelegate protocol. To implement - /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All - /// methods that can be implemented as blocking listeners will be. - static NSStreamDelegate implementAsBlocking( - {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { - final builder = objc.ObjCProtocolBuilder(); - NSStreamDelegate.stream_handleEvent_ - .implementAsBlocking(builder, stream_handleEvent_); return NSStreamDelegate.castFrom(builder.build()); } /// Adds the implementation of the NSStreamDelegate protocol to an existing - /// [objc.ObjCProtocolBuilder]. All methods that can be implemented as blocking - /// listeners will be. - static void addToBuilderAsBlocking(objc.ObjCProtocolBuilder builder, - {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { - NSStreamDelegate.stream_handleEvent_ - .implementAsBlocking(builder, stream_handleEvent_); - } - - /// stream:handleEvent: - static final stream_handleEvent_ = - objc.ObjCProtocolListenableMethod( - _protocol_NSStreamDelegate, - _sel_stream_handleEvent_, - objc.getProtocolMethodSignature( - _protocol_NSStreamDelegate, - _sel_stream_handleEvent_, - isRequired: false, - isInstanceMethod: true, - ), - (void Function(NSStream, NSStreamEvent) func) => - ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent.fromFunction( - (ffi.Pointer _, NSStream arg1, NSStreamEvent arg2) => - func(arg1, arg2)), - (void Function(NSStream, NSStreamEvent) func) => - ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent.listener( - (ffi.Pointer _, NSStream arg1, NSStreamEvent arg2) => - func(arg1, arg2)), - (void Function(NSStream, NSStreamEvent) func) => - ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent.blocking( - (ffi.Pointer _, NSStream arg1, NSStreamEvent arg2) => - func(arg1, arg2)), - ); + /// [objc.ObjCProtocolBuilder]. + static void addToBuilder( + objc.ObjCProtocolBuilder builder, + ) {} } enum NSStreamEvent { @@ -11809,7 +11725,7 @@ abstract final class ObjCBlock_ffiVoid_NSItemProviderCompletionHandler_objcObjCO ffi.Pointer arg1, ffi.Pointer arg2) => fn( - ObjCBlock_ffiVoid_objcObjCObject_NSError.castFromPointer(arg0, retain: true, release: true), + ObjCBlock_ffiVoid_idNSSecureCoding_NSError.castFromPointer(arg0, retain: true, release: true), objc.ObjCObjectBase(arg1, retain: true, release: true), NSDictionary.castFromPointer(arg2, retain: true, release: true))), retain: false, @@ -11844,7 +11760,7 @@ abstract final class ObjCBlock_ffiVoid_NSItemProviderCompletionHandler_objcObjCO ffi.Pointer arg1, ffi.Pointer arg2) => fn( - ObjCBlock_ffiVoid_objcObjCObject_NSError.castFromPointer(arg0, + ObjCBlock_ffiVoid_idNSSecureCoding_NSError.castFromPointer(arg0, retain: false, release: true), objc.ObjCObjectBase(arg1, retain: false, release: true), NSDictionary.castFromPointer(arg2, @@ -11888,7 +11804,7 @@ abstract final class ObjCBlock_ffiVoid_NSItemProviderCompletionHandler_objcObjCO ffi.Pointer arg1, ffi.Pointer arg2) => fn( - ObjCBlock_ffiVoid_objcObjCObject_NSError.castFromPointer(arg0, + ObjCBlock_ffiVoid_idNSSecureCoding_NSError.castFromPointer(arg0, retain: false, release: true), objc.ObjCObjectBase(arg1, retain: false, release: true), NSDictionary.castFromPointer(arg2, @@ -11901,7 +11817,7 @@ abstract final class ObjCBlock_ffiVoid_NSItemProviderCompletionHandler_objcObjCO ffi.Pointer arg1, ffi.Pointer arg2) => fn( - ObjCBlock_ffiVoid_objcObjCObject_NSError.castFromPointer(arg0, + ObjCBlock_ffiVoid_idNSSecureCoding_NSError.castFromPointer(arg0, retain: false, release: true), objc.ObjCObjectBase(arg1, retain: false, release: true), NSDictionary.castFromPointer(arg2, @@ -12322,266 +12238,7 @@ extension ObjCBlock_ffiVoid_ffiVoid_NSCoder_CallExtension ref.pointer, arg0, arg1.ref.pointer); } -void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2) => - block.ref.target - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.UnsignedLong arg2)>>() - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, - int)>()(arg0, arg1, arg2); -ffi.Pointer - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrCallable = - ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)>( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrTrampoline) - .cast(); -void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2) => - (objc.getBlockClosure(block) as void Function(ffi.Pointer, - ffi.Pointer, int))(arg0, arg1, arg2); -ffi.Pointer - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureCallable = - ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)>( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureTrampoline) - .cast(); -void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2) { - (objc.getBlockClosure(block) as void Function(ffi.Pointer, - ffi.Pointer, int))(arg0, arg1, arg2); - objc.objectRelease(block.cast()); -} - -ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)> - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerCallable = ffi - .NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)>.listener( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerTrampoline) - ..keepIsolateAlive = false; -void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingTrampoline( - ffi.Pointer block, - ffi.Pointer waiter, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2) { - try { - (objc.getBlockClosure(block) as void Function(ffi.Pointer, - ffi.Pointer, int))(arg0, arg1, arg2); - } catch (e) { - } finally { - objc.signalWaiter(waiter); - objc.objectRelease(block.cast()); - } -} - -ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)> - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)>.isolateLocal( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingTrampoline) - ..keepIsolateAlive = false; -ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)> - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingListenerCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)>.listener( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingTrampoline) - ..keepIsolateAlive = false; - -/// Construction methods for `objc.ObjCBlock, NSStream, ffi.UnsignedLong)>`. -abstract final class ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent { - /// Returns a block that wraps the given raw block pointer. - static objc.ObjCBlock< - ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> - castFromPointer(ffi.Pointer pointer, - {bool retain = false, bool release = false}) => - objc.ObjCBlock< - ffi.Void Function(ffi.Pointer, NSStream, - ffi.UnsignedLong)>(pointer, retain: retain, release: release); - - /// Creates a block from a C function pointer. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - static objc - .ObjCBlock, NSStream, ffi.UnsignedLong)> - fromFunctionPointer( - ffi.Pointer arg0, ffi.Pointer arg1, ffi.UnsignedLong arg2)>> - ptr) => - objc.ObjCBlock, NSStream, ffi.UnsignedLong)>( - objc.newPointerBlock( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrCallable, - ptr.cast()), - retain: false, - release: true); - - /// Creates a block from a Dart function. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - static objc.ObjCBlock, NSStream, ffi.UnsignedLong)> fromFunction( - void Function(ffi.Pointer, NSStream, NSStreamEvent) fn) => - objc.ObjCBlock, NSStream, ffi.UnsignedLong)>( - objc.newClosureBlock( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureCallable, - (ffi.Pointer arg0, ffi.Pointer arg1, - int arg2) => - fn( - arg0, - NSStream.castFromPointer(arg1, retain: true, release: true), - NSStreamEvent.fromValue(arg2))), - retain: false, - release: true); - - /// Creates a listener block from a Dart function. - /// - /// This is based on FFI's NativeCallable.listener, and has the same - /// capabilities and limitations. This block can be invoked from any thread, - /// but only supports void functions, and is not run synchronously. See - /// NativeCallable.listener for more details. - /// - /// Note that unlike the default behavior of NativeCallable.listener, listener - /// blocks do not keep the isolate alive. - static objc.ObjCBlock< - ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> - listener( - void Function(ffi.Pointer, NSStream, NSStreamEvent) fn) { - final raw = objc.newClosureBlock( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerCallable - .nativeFunction - .cast(), - (ffi.Pointer arg0, ffi.Pointer arg1, - int arg2) => - fn( - arg0, - NSStream.castFromPointer(arg1, retain: false, release: true), - NSStreamEvent.fromValue(arg2))); - final wrapper = _ObjectiveCBindings_wrapListenerBlock_hoampi(raw); - objc.objectRelease(raw.cast()); - return objc.ObjCBlock< - ffi.Void Function(ffi.Pointer, NSStream, - ffi.UnsignedLong)>(wrapper, retain: false, release: true); - } - - /// Creates a blocking block from a Dart function. - /// - /// This callback can be invoked from any native thread, and will block the - /// caller until the callback is handled by the Dart isolate that created - /// the block. Async functions are not supported. - /// - /// This block does not keep the owner isolate alive. If the owner isolate has - /// shut down, and the block is invoked by native code, it may block - /// indefinitely, or have other undefined behavior. - static objc.ObjCBlock< - ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> - blocking( - void Function(ffi.Pointer, NSStream, NSStreamEvent) fn) { - final raw = objc.newClosureBlock( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingCallable - .nativeFunction - .cast(), - (ffi.Pointer arg0, ffi.Pointer arg1, - int arg2) => - fn( - arg0, - NSStream.castFromPointer(arg1, retain: false, release: true), - NSStreamEvent.fromValue(arg2))); - final rawListener = objc.newClosureBlock( - _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingListenerCallable - .nativeFunction - .cast(), - (ffi.Pointer arg0, ffi.Pointer arg1, - int arg2) => - fn( - arg0, - NSStream.castFromPointer(arg1, retain: false, release: true), - NSStreamEvent.fromValue(arg2))); - final wrapper = objc.wrapBlockingBlock( - _ObjectiveCBindings_wrapBlockingBlock_hoampi, raw, rawListener); - objc.objectRelease(raw.cast()); - objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock< - ffi.Void Function(ffi.Pointer, NSStream, - ffi.UnsignedLong)>(wrapper, retain: false, release: true); - } -} - -/// Call operator for `objc.ObjCBlock, NSStream, ffi.UnsignedLong)>`. -extension ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_CallExtension - on objc.ObjCBlock< - ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> { - void call(ffi.Pointer arg0, NSStream arg1, NSStreamEvent arg2) => - ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.UnsignedLong arg2)>>() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int)>()(ref.pointer, arg0, arg1.ref.pointer, arg2.value); -} - -void _ObjCBlock_ffiVoid_objcObjCObject_NSError_fnPtrTrampoline( +void _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_fnPtrTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => @@ -12593,30 +12250,31 @@ void _ObjCBlock_ffiVoid_objcObjCObject_NSError_fnPtrTrampoline( .asFunction< void Function(ffi.Pointer, ffi.Pointer)>()(arg0, arg1); -ffi.Pointer _ObjCBlock_ffiVoid_objcObjCObject_NSError_fnPtrCallable = +ffi.Pointer + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_fnPtrCallable = ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer)>( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_fnPtrTrampoline) + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_fnPtrTrampoline) .cast(); -void _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureTrampoline( +void _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) => (objc.getBlockClosure(block) as void Function(ffi.Pointer, ffi.Pointer))(arg0, arg1); ffi.Pointer - _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureCallable = + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_closureCallable = ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer)>( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureTrampoline) + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_closureTrampoline) .cast(); -void _ObjCBlock_ffiVoid_objcObjCObject_NSError_listenerTrampoline( +void _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_listenerTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1) { @@ -12628,15 +12286,15 @@ void _ObjCBlock_ffiVoid_objcObjCObject_NSError_listenerTrampoline( ffi.NativeCallable< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)> - _ObjCBlock_ffiVoid_objcObjCObject_NSError_listenerCallable = ffi + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_listenerCallable = ffi .NativeCallable< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_listenerTrampoline) + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_listenerTrampoline) ..keepIsolateAlive = false; -void _ObjCBlock_ffiVoid_objcObjCObject_NSError_blockingTrampoline( +void _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingTrampoline( ffi.Pointer block, ffi.Pointer waiter, ffi.Pointer arg0, @@ -12657,14 +12315,14 @@ ffi.NativeCallable< ffi.Pointer, ffi.Pointer, ffi.Pointer)> - _ObjCBlock_ffiVoid_objcObjCObject_NSError_blockingCallable = ffi + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingCallable = ffi .NativeCallable< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>.isolateLocal( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_blockingTrampoline) + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingTrampoline) ..keepIsolateAlive = false; ffi.NativeCallable< ffi.Void Function( @@ -12672,18 +12330,18 @@ ffi.NativeCallable< ffi.Pointer, ffi.Pointer, ffi.Pointer)> - _ObjCBlock_ffiVoid_objcObjCObject_NSError_blockingListenerCallable = ffi + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingListenerCallable = ffi .NativeCallable< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>.listener( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_blockingTrampoline) + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingTrampoline) ..keepIsolateAlive = false; /// Construction methods for `objc.ObjCBlock?, NSError)>`. -abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { +abstract final class ObjCBlock_ffiVoid_idNSSecureCoding_NSError { /// Returns a block that wraps the given raw block pointer. static objc .ObjCBlock?, NSError)> @@ -12705,7 +12363,7 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { ffi.Pointer arg1)>> ptr) => objc.ObjCBlock?, NSError)>( - objc.newPointerBlock(_ObjCBlock_ffiVoid_objcObjCObject_NSError_fnPtrCallable, ptr.cast()), + objc.newPointerBlock(_ObjCBlock_ffiVoid_idNSSecureCoding_NSError_fnPtrCallable, ptr.cast()), retain: false, release: true); @@ -12715,16 +12373,16 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. static objc.ObjCBlock?, NSError)> fromFunction( - void Function(objc.ObjCObjectBase?, NSError) fn) => + void Function(NSSecureCoding?, NSError) fn) => objc.ObjCBlock?, NSError)>( objc.newClosureBlock( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_closureCallable, + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_closureCallable, (ffi.Pointer arg0, ffi.Pointer arg1) => fn( arg0.address == 0 ? null - : objc.ObjCObjectBase(arg0, retain: true, release: true), + : NSSecureCoding(arg0, retain: true, release: true), NSError.castFromPointer(arg1, retain: true, release: true))), retain: false, release: true); @@ -12740,9 +12398,9 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { /// blocks do not keep the isolate alive. static objc .ObjCBlock?, NSError)> - listener(void Function(objc.ObjCObjectBase?, NSError) fn) { + listener(void Function(NSSecureCoding?, NSError) fn) { final raw = objc.newClosureBlock( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_listenerCallable + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_listenerCallable .nativeFunction .cast(), (ffi.Pointer arg0, @@ -12750,7 +12408,7 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { fn( arg0.address == 0 ? null - : objc.ObjCObjectBase(arg0, retain: false, release: true), + : NSSecureCoding(arg0, retain: false, release: true), NSError.castFromPointer(arg1, retain: false, release: true))); final wrapper = _ObjectiveCBindings_wrapListenerBlock_pfv6jd(raw); objc.objectRelease(raw.cast()); @@ -12770,9 +12428,9 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { /// indefinitely, or have other undefined behavior. static objc .ObjCBlock?, NSError)> - blocking(void Function(objc.ObjCObjectBase?, NSError) fn) { + blocking(void Function(NSSecureCoding?, NSError) fn) { final raw = objc.newClosureBlock( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_blockingCallable + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingCallable .nativeFunction .cast(), (ffi.Pointer arg0, @@ -12780,10 +12438,10 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { fn( arg0.address == 0 ? null - : objc.ObjCObjectBase(arg0, retain: false, release: true), + : NSSecureCoding(arg0, retain: false, release: true), NSError.castFromPointer(arg1, retain: false, release: true))); final rawListener = objc.newClosureBlock( - _ObjCBlock_ffiVoid_objcObjCObject_NSError_blockingListenerCallable + _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingListenerCallable .nativeFunction .cast(), (ffi.Pointer arg0, @@ -12791,7 +12449,7 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { fn( arg0.address == 0 ? null - : objc.ObjCObjectBase(arg0, retain: false, release: true), + : NSSecureCoding(arg0, retain: false, release: true), NSError.castFromPointer(arg1, retain: false, release: true))); final wrapper = objc.wrapBlockingBlock( _ObjectiveCBindings_wrapBlockingBlock_pfv6jd, raw, rawListener); @@ -12804,9 +12462,9 @@ abstract final class ObjCBlock_ffiVoid_objcObjCObject_NSError { } /// Call operator for `objc.ObjCBlock?, NSError)>`. -extension ObjCBlock_ffiVoid_objcObjCObject_NSError_CallExtension on objc +extension ObjCBlock_ffiVoid_idNSSecureCoding_NSError_CallExtension on objc .ObjCBlock?, NSError)> { - void call(objc.ObjCObjectBase? arg0, NSError arg1) => ref.pointer.ref.invoke + void call(NSSecureCoding? arg0, NSError arg1) => ref.pointer.ref.invoke .cast< ffi.NativeFunction< ffi.Void Function( @@ -14913,20 +14571,6 @@ final _objc_msgSend_3ctkt6 = objc.msgSendPointer .asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); -final _objc_msgSend_3l8zum = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong)>>() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int)>(); final _objc_msgSend_3nbx5e = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -16603,7 +16247,6 @@ late final _sel_stopAccessingSecurityScopedResource = objc.registerName("stopAccessingSecurityScopedResource"); late final _sel_streamError = objc.registerName("streamError"); late final _sel_streamStatus = objc.registerName("streamStatus"); -late final _sel_stream_handleEvent_ = objc.registerName("stream:handleEvent:"); late final _sel_string = objc.registerName("string"); late final _sel_stringByAppendingFormat_ = objc.registerName("stringByAppendingFormat:"); diff --git a/pkgs/objective_c/src/objective_c_bindings_generated.m b/pkgs/objective_c/src/objective_c_bindings_generated.m index 2225913e04..5c14b266d7 100644 --- a/pkgs/objective_c/src/objective_c_bindings_generated.m +++ b/pkgs/objective_c/src/objective_c_bindings_generated.m @@ -16,6 +16,10 @@ Protocol* _ObjectiveCBindings_NSFastEnumeration(void) { return @protocol(NSFastEnumeration); } +Protocol* _ObjectiveCBindings_NSItemProviderReading(void) { return @protocol(NSItemProviderReading); } + +Protocol* _ObjectiveCBindings_NSItemProviderWriting(void) { return @protocol(NSItemProviderWriting); } + Protocol* _ObjectiveCBindings_NSMutableCopying(void) { return @protocol(NSMutableCopying); } Protocol* _ObjectiveCBindings_NSObject(void) { return @protocol(NSObject); } @@ -108,47 +112,19 @@ _ListenerTrampoline2 _ObjectiveCBindings_wrapBlockingBlock_18v1jvf( }; } -typedef void (^_ListenerTrampoline3)(void * arg0, id arg1, NSStreamEvent arg2); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline3 _ObjectiveCBindings_wrapListenerBlock_hoampi(_ListenerTrampoline3 block) NS_RETURNS_RETAINED { - return ^void(void * arg0, id arg1, NSStreamEvent arg2) { - objc_retainBlock(block); - block(arg0, (__bridge id)(__bridge_retained void*)(arg1), arg2); - }; -} - -typedef void (^_BlockingTrampoline3)(void * waiter, void * arg0, id arg1, NSStreamEvent arg2); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline3 _ObjectiveCBindings_wrapBlockingBlock_hoampi( - _BlockingTrampoline3 block, _BlockingTrampoline3 listenerBlock, - void* (*newWaiter)(), void (*awaitWaiter)(void*)) NS_RETURNS_RETAINED { - NSThread *targetThread = [NSThread currentThread]; - return ^void(void * arg0, id arg1, NSStreamEvent arg2) { - if ([NSThread currentThread] == targetThread) { - objc_retainBlock(block); - block(nil, arg0, (__bridge id)(__bridge_retained void*)(arg1), arg2); - } else { - void* waiter = newWaiter(); - objc_retainBlock(listenerBlock); - listenerBlock(waiter, arg0, (__bridge id)(__bridge_retained void*)(arg1), arg2); - awaitWaiter(waiter); - } - }; -} - -typedef void (^_ListenerTrampoline4)(id arg0, id arg1); +typedef void (^_ListenerTrampoline3)(id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline4 _ObjectiveCBindings_wrapListenerBlock_pfv6jd(_ListenerTrampoline4 block) NS_RETURNS_RETAINED { +_ListenerTrampoline3 _ObjectiveCBindings_wrapListenerBlock_pfv6jd(_ListenerTrampoline3 block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1) { objc_retainBlock(block); block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); }; } -typedef void (^_BlockingTrampoline4)(void * waiter, id arg0, id arg1); +typedef void (^_BlockingTrampoline3)(void * waiter, id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline4 _ObjectiveCBindings_wrapBlockingBlock_pfv6jd( - _BlockingTrampoline4 block, _BlockingTrampoline4 listenerBlock, +_ListenerTrampoline3 _ObjectiveCBindings_wrapBlockingBlock_pfv6jd( + _BlockingTrampoline3 block, _BlockingTrampoline3 listenerBlock, void* (*newWaiter)(), void (*awaitWaiter)(void*)) NS_RETURNS_RETAINED { NSThread *targetThread = [NSThread currentThread]; return ^void(id arg0, id arg1) { From 67a927956a23aa1e3543f2ba573eb7170d1452dc Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 15:08:34 +1100 Subject: [PATCH 07/13] Fix analysis --- pkgs/ffigen/lib/src/code_generator/objc_protocol.dart | 9 +++++---- pkgs/ffigen/lib/src/code_generator/pointer.dart | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index 57626090a4..efdc2187e2 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -77,8 +77,10 @@ class ObjCProtocol extends BindingType with ObjCMethods { } s.write(makeDartDoc(dartDoc ?? originalName)); - final protoImpls = superProtocols.map((p) => p.getDartType(w)).join(', '); - final protoImpl = superProtocols.isEmpty ? '' : 'implements $protoImpls'; + final sp = superProtocols.where((p) => p != this); + final protoImpl = sp.isEmpty + ? '' + : 'implements ${sp.map((p) => p.getDartType(w)).join(', ')}'; s.write(''' interface class $name extends $protocolBase $protoImpl{ $name._($rawObjType pointer, {bool retain = false, bool release = false}) : @@ -298,8 +300,7 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } required bool objCRetain, String? objCEnclosingClass, }) => - ObjCInterface.generateConstructor( - '${w.objcPkgPrefix}.ObjCObjectBase', value, objCRetain); + ObjCInterface.generateConstructor(getDartType(w), value, objCRetain); @override String? generateRetain(String value) => diff --git a/pkgs/ffigen/lib/src/code_generator/pointer.dart b/pkgs/ffigen/lib/src/code_generator/pointer.dart index 08fa745ba6..a12282ac85 100644 --- a/pkgs/ffigen/lib/src/code_generator/pointer.dart +++ b/pkgs/ffigen/lib/src/code_generator/pointer.dart @@ -217,6 +217,16 @@ class ObjCObjectPointerWithProtocols extends ObjCObjectPointer { @override String cacheKey() => 'id<${protocols.map((p) => p.cacheKey()).join(', ')}>'; + @override + String convertFfiDartTypeToDartType( + Writer w, + String value, { + required bool objCRetain, + String? objCEnclosingClass, + }) => + protocols.first.convertFfiDartTypeToDartType(w, value, + objCRetain: objCRetain, objCEnclosingClass: objCEnclosingClass); + @override void visitChildren(Visitor visitor) { super.visitChildren(visitor); From 8caa73c1a8df8e84e4812f186a79750d5795ee9a Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 31 Jan 2025 15:11:02 +1100 Subject: [PATCH 08/13] regen bindings --- .../src/objective_c_bindings_generated.dart | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index 43bc2669b2..7684106d65 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -8460,7 +8460,7 @@ class NSStream extends NSObject { final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_delegate); return _ret.address == 0 ? null - : NSStreamDelegate(_ret, retain: true, release: true); + : NSStreamDelegate.castFromPointer(_ret, retain: true, release: true); } /// init @@ -8536,8 +8536,7 @@ class NSStream extends NSObject { } /// NSStreamDelegate -interface class NSStreamDelegate extends objc.ObjCProtocolBase - implements NSStreamDelegate { +interface class NSStreamDelegate extends objc.ObjCProtocolBase { NSStreamDelegate._(ffi.Pointer pointer, {bool retain = false, bool release = false}) : super(pointer, retain: retain, release: release); @@ -12377,13 +12376,12 @@ abstract final class ObjCBlock_ffiVoid_idNSSecureCoding_NSError { objc.ObjCBlock?, NSError)>( objc.newClosureBlock( _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_closureCallable, - (ffi.Pointer arg0, - ffi.Pointer arg1) => - fn( - arg0.address == 0 - ? null - : NSSecureCoding(arg0, retain: true, release: true), - NSError.castFromPointer(arg1, retain: true, release: true))), + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : NSSecureCoding.castFromPointer(arg0, + retain: true, release: true), + NSError.castFromPointer(arg1, retain: true, release: true))), retain: false, release: true); @@ -12408,7 +12406,8 @@ abstract final class ObjCBlock_ffiVoid_idNSSecureCoding_NSError { fn( arg0.address == 0 ? null - : NSSecureCoding(arg0, retain: false, release: true), + : NSSecureCoding.castFromPointer(arg0, + retain: false, release: true), NSError.castFromPointer(arg1, retain: false, release: true))); final wrapper = _ObjectiveCBindings_wrapListenerBlock_pfv6jd(raw); objc.objectRelease(raw.cast()); @@ -12438,7 +12437,8 @@ abstract final class ObjCBlock_ffiVoid_idNSSecureCoding_NSError { fn( arg0.address == 0 ? null - : NSSecureCoding(arg0, retain: false, release: true), + : NSSecureCoding.castFromPointer(arg0, + retain: false, release: true), NSError.castFromPointer(arg1, retain: false, release: true))); final rawListener = objc.newClosureBlock( _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_blockingListenerCallable @@ -12449,7 +12449,8 @@ abstract final class ObjCBlock_ffiVoid_idNSSecureCoding_NSError { fn( arg0.address == 0 ? null - : NSSecureCoding(arg0, retain: false, release: true), + : NSSecureCoding.castFromPointer(arg0, + retain: false, release: true), NSError.castFromPointer(arg1, retain: false, release: true))); final wrapper = objc.wrapBlockingBlock( _ObjectiveCBindings_wrapBlockingBlock_pfv6jd, raw, rawListener); From 9155719d2c9a7a9a71e2d076042d3dc1b9fc15ad Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Mon, 3 Feb 2025 11:56:24 +1100 Subject: [PATCH 09/13] Handle weirdly shaped proto decl ASTs --- .../lib/src/code_generator/objc_protocol.dart | 18 +- .../sub_parsers/objcprotocoldecl_parser.dart | 16 + pkgs/ffigen/lib/src/header_parser/utils.dart | 12 +- .../src/objective_c_bindings_generated.dart | 391 +++++++++++++++++- .../src/objective_c_bindings_generated.m | 38 +- .../test/ns_input_stream_test.dart | 6 +- 6 files changed, 452 insertions(+), 29 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index efdc2187e2..f4c9813707 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -77,12 +77,10 @@ class ObjCProtocol extends BindingType with ObjCMethods { } s.write(makeDartDoc(dartDoc ?? originalName)); - final sp = superProtocols.where((p) => p != this); - final protoImpl = sp.isEmpty - ? '' - : 'implements ${sp.map((p) => p.getDartType(w)).join(', ')}'; + final sp = superProtocols.map((p) => p.getDartType(w)); + final impls = superProtocols.isEmpty ? '' : 'implements ${sp.join(', ')}'; s.write(''' -interface class $name extends $protocolBase $protoImpl{ +interface class $name extends $protocolBase $impls{ $name._($rawObjType pointer, {bool retain = false, bool release = false}) : super(pointer, retain: retain, release: release); '''); @@ -306,12 +304,10 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } String? generateRetain(String value) => '(__bridge id)(__bridge_retained void*)($value)'; - bool _isSuperProtocolOf(ObjCProtocol protocol, Set visited) { + bool _isSuperProtocolOf(ObjCProtocol protocol) { if (protocol == this) return true; - if (visited.contains(protocol)) return false; - visited.add(protocol); for (final superProtocol in protocol.superProtocols) { - if (_isSuperProtocolOf(superProtocol, visited)) return true; + if (_isSuperProtocolOf(superProtocol)) return true; } return false; } @@ -320,11 +316,11 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } bool isSupertypeOf(Type other) { other = other.typealiasType; if (other is ObjCProtocol) { - return _isSuperProtocolOf(other, {}); + return _isSuperProtocolOf(other); } else if (other is ObjCInterface) { for (ObjCInterface? t = other; t != null; t = t.superType) { for (final protocol in t.protocols) { - if (_isSuperProtocolOf(protocol, {})) return true; + if (_isSuperProtocolOf(protocol)) return true; } } } diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart index dde0a22c88..239937d732 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart @@ -29,6 +29,22 @@ ObjCProtocol? parseObjCProtocolDeclaration(clang_types.CXCursor cursor) { return cachedProtocol; } + // There's a strange shape in the AST for protocols seen in certain contexts, + // where instead of the AST looking like (decl -> methods/etc), it looks like + // (stubDecl --superProto-> decl -> methods/etc). If we try and parse the stub + // in this case, we'll be left with an empty protocol with itself as its super + // protocol. The USR is the same for both the stub and the real decl, so at + // least this case is easy to detect and fix. + final selfSuperCursor = cursor.findChildWhere((child) { + if (child.kind == clang_types.CXCursorKind.CXCursor_ObjCProtocolRef) { + return clang.clang_getCursorDefinition(child).usr() == usr; + } + return false; + }); + if (selfSuperCursor != null) { + cursor = clang.clang_getCursorDefinition(selfSuperCursor); + } + if (!isApiAvailable(cursor)) { _logger.info('Omitting deprecated protocol $name'); return null; diff --git a/pkgs/ffigen/lib/src/header_parser/utils.dart b/pkgs/ffigen/lib/src/header_parser/utils.dart index 42b22663c0..aca6912dd2 100644 --- a/pkgs/ffigen/lib/src/header_parser/utils.dart +++ b/pkgs/ffigen/lib/src/header_parser/utils.dart @@ -197,12 +197,13 @@ extension CXCursorExt on clang_types.CXCursor { return result == 0; } - /// Returns the first child with the given CXCursorKind, or null if there + /// Returns the first child where `predicate(child)` is true, or null if there /// isn't one. - clang_types.CXCursor? findChildWithKind(int kind) { + clang_types.CXCursor? findChildWhere( + bool Function(clang_types.CXCursor) predicate) { clang_types.CXCursor? result; visitChildrenMayBreak((child) { - if (child.kind == kind) { + if (predicate(child)) { result = child; return false; } @@ -211,6 +212,11 @@ extension CXCursorExt on clang_types.CXCursor { return result; } + /// Returns the first child with the given CXCursorKind, or null if there + /// isn't one. + clang_types.CXCursor? findChildWithKind(int kind) => + findChildWhere((child) => child.kind == kind); + /// Returns whether there is a child with the given CXCursorKind. bool hasChildWithKind(int kind) => findChildWithKind(kind) != null; diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index 7684106d65..d06edb1eaa 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -70,6 +70,23 @@ external ffi.Pointer awaitWaiter, ); +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer Function()>>, + ffi.Pointer< + ffi.NativeFunction)>>)>( + isLeaf: true) +external ffi.Pointer + _ObjectiveCBindings_wrapBlockingBlock_hoampi( + ffi.Pointer block, + ffi.Pointer listnerBlock, + ffi.Pointer Function()>> newWaiter, + ffi.Pointer)>> + awaitWaiter, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer, @@ -120,6 +137,14 @@ external ffi.Pointer ffi.Pointer block, ); +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer)>(isLeaf: true) +external ffi.Pointer + _ObjectiveCBindings_wrapListenerBlock_hoampi( + ffi.Pointer block, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer)>(isLeaf: true) @@ -241,6 +266,16 @@ class DartInputStreamAdapter extends NSInputStream implements NSStreamDelegate { void setError_(NSError error) { _objc_msgSend_xtuoz7(this.ref.pointer, _sel_setError_, error.ref.pointer); } + + /// stream:handleEvent: + void stream_handleEvent_(NSStream aStream, NSStreamEvent eventCode) { + if (!objc.respondsToSelector(this.ref.pointer, _sel_stream_handleEvent_)) { + throw objc.UnimplementedOptionalMethodException( + 'DOBJCDartInputStreamAdapter', 'stream:handleEvent:'); + } + _objc_msgSend_3l8zum(this.ref.pointer, _sel_stream_handleEvent_, + aStream.ref.pointer, eventCode.value); + } } /// DOBJCDartProxy @@ -8536,7 +8571,8 @@ class NSStream extends NSObject { } /// NSStreamDelegate -interface class NSStreamDelegate extends objc.ObjCProtocolBase { +interface class NSStreamDelegate extends objc.ObjCProtocolBase + implements NSObjectProtocol { NSStreamDelegate._(ffi.Pointer pointer, {bool retain = false, bool release = false}) : super(pointer, retain: retain, release: release); @@ -8558,17 +8594,86 @@ interface class NSStreamDelegate extends objc.ObjCProtocolBase { /// Builds an object that implements the NSStreamDelegate protocol. To implement /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. - static NSStreamDelegate implement() { + static NSStreamDelegate implement( + {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { final builder = objc.ObjCProtocolBuilder(); - + NSStreamDelegate.stream_handleEvent_ + .implement(builder, stream_handleEvent_); return NSStreamDelegate.castFrom(builder.build()); } /// Adds the implementation of the NSStreamDelegate protocol to an existing /// [objc.ObjCProtocolBuilder]. - static void addToBuilder( - objc.ObjCProtocolBuilder builder, - ) {} + static void addToBuilder(objc.ObjCProtocolBuilder builder, + {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { + NSStreamDelegate.stream_handleEvent_ + .implement(builder, stream_handleEvent_); + } + + /// Builds an object that implements the NSStreamDelegate protocol. To implement + /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All + /// methods that can be implemented as listeners will be. + static NSStreamDelegate implementAsListener( + {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { + final builder = objc.ObjCProtocolBuilder(); + NSStreamDelegate.stream_handleEvent_ + .implementAsListener(builder, stream_handleEvent_); + return NSStreamDelegate.castFrom(builder.build()); + } + + /// Adds the implementation of the NSStreamDelegate protocol to an existing + /// [objc.ObjCProtocolBuilder]. All methods that can be implemented as listeners will + /// be. + static void addToBuilderAsListener(objc.ObjCProtocolBuilder builder, + {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { + NSStreamDelegate.stream_handleEvent_ + .implementAsListener(builder, stream_handleEvent_); + } + + /// Builds an object that implements the NSStreamDelegate protocol. To implement + /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. All + /// methods that can be implemented as blocking listeners will be. + static NSStreamDelegate implementAsBlocking( + {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { + final builder = objc.ObjCProtocolBuilder(); + NSStreamDelegate.stream_handleEvent_ + .implementAsBlocking(builder, stream_handleEvent_); + return NSStreamDelegate.castFrom(builder.build()); + } + + /// Adds the implementation of the NSStreamDelegate protocol to an existing + /// [objc.ObjCProtocolBuilder]. All methods that can be implemented as blocking + /// listeners will be. + static void addToBuilderAsBlocking(objc.ObjCProtocolBuilder builder, + {void Function(NSStream, NSStreamEvent)? stream_handleEvent_}) { + NSStreamDelegate.stream_handleEvent_ + .implementAsBlocking(builder, stream_handleEvent_); + } + + /// stream:handleEvent: + static final stream_handleEvent_ = + objc.ObjCProtocolListenableMethod( + _protocol_NSStreamDelegate, + _sel_stream_handleEvent_, + objc.getProtocolMethodSignature( + _protocol_NSStreamDelegate, + _sel_stream_handleEvent_, + isRequired: false, + isInstanceMethod: true, + ), + (void Function(NSStream, NSStreamEvent) func) => + ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent.fromFunction( + (ffi.Pointer _, NSStream arg1, NSStreamEvent arg2) => + func(arg1, arg2)), + (void Function(NSStream, NSStreamEvent) func) => + ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent.listener( + (ffi.Pointer _, NSStream arg1, NSStreamEvent arg2) => + func(arg1, arg2)), + (void Function(NSStream, NSStreamEvent) func) => + ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent.blocking( + (ffi.Pointer _, NSStream arg1, NSStreamEvent arg2) => + func(arg1, arg2)), + ); } enum NSStreamEvent { @@ -12237,6 +12342,265 @@ extension ObjCBlock_ffiVoid_ffiVoid_NSCoder_CallExtension ref.pointer, arg0, arg1.ref.pointer); } +void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2) => + block.ref.target + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.UnsignedLong arg2)>>() + .asFunction< + void Function(ffi.Pointer, ffi.Pointer, + int)>()(arg0, arg1, arg2); +ffi.Pointer + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)>( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrTrampoline) + .cast(); +void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2) => + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer, int))(arg0, arg1, arg2); +ffi.Pointer + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)>( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureTrampoline) + .cast(); +void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2) { + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer, int))(arg0, arg1, arg2); + objc.objectRelease(block.cast()); +} + +ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)> + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerCallable = ffi + .NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)>.listener( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerTrampoline) + ..keepIsolateAlive = false; +void _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingTrampoline( + ffi.Pointer block, + ffi.Pointer waiter, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2) { + try { + (objc.getBlockClosure(block) as void Function(ffi.Pointer, + ffi.Pointer, int))(arg0, arg1, arg2); + } catch (e) { + } finally { + objc.signalWaiter(waiter); + objc.objectRelease(block.cast()); + } +} + +ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)> + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)>.isolateLocal( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingTrampoline) + ..keepIsolateAlive = false; +ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)> + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingListenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)>.listener( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingTrampoline) + ..keepIsolateAlive = false; + +/// Construction methods for `objc.ObjCBlock, NSStream, ffi.UnsignedLong)>`. +abstract final class ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock< + ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> + castFromPointer(ffi.Pointer pointer, + {bool retain = false, bool release = false}) => + objc.ObjCBlock< + ffi.Void Function(ffi.Pointer, NSStream, + ffi.UnsignedLong)>(pointer, retain: retain, release: release); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc + .ObjCBlock, NSStream, ffi.UnsignedLong)> + fromFunctionPointer( + ffi.Pointer arg0, ffi.Pointer arg1, ffi.UnsignedLong arg2)>> + ptr) => + objc.ObjCBlock, NSStream, ffi.UnsignedLong)>( + objc.newPointerBlock( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_fnPtrCallable, + ptr.cast()), + retain: false, + release: true); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock, NSStream, ffi.UnsignedLong)> fromFunction( + void Function(ffi.Pointer, NSStream, NSStreamEvent) fn) => + objc.ObjCBlock, NSStream, ffi.UnsignedLong)>( + objc.newClosureBlock( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_closureCallable, + (ffi.Pointer arg0, ffi.Pointer arg1, + int arg2) => + fn( + arg0, + NSStream.castFromPointer(arg1, retain: true, release: true), + NSStreamEvent.fromValue(arg2))), + retain: false, + release: true); + + /// Creates a listener block from a Dart function. + /// + /// This is based on FFI's NativeCallable.listener, and has the same + /// capabilities and limitations. This block can be invoked from any thread, + /// but only supports void functions, and is not run synchronously. See + /// NativeCallable.listener for more details. + /// + /// Note that unlike the default behavior of NativeCallable.listener, listener + /// blocks do not keep the isolate alive. + static objc.ObjCBlock< + ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> + listener( + void Function(ffi.Pointer, NSStream, NSStreamEvent) fn) { + final raw = objc.newClosureBlock( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_listenerCallable + .nativeFunction + .cast(), + (ffi.Pointer arg0, ffi.Pointer arg1, + int arg2) => + fn( + arg0, + NSStream.castFromPointer(arg1, retain: false, release: true), + NSStreamEvent.fromValue(arg2))); + final wrapper = _ObjectiveCBindings_wrapListenerBlock_hoampi(raw); + objc.objectRelease(raw.cast()); + return objc.ObjCBlock< + ffi.Void Function(ffi.Pointer, NSStream, + ffi.UnsignedLong)>(wrapper, retain: false, release: true); + } + + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions are not supported. + /// + /// This block does not keep the owner isolate alive. If the owner isolate has + /// shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock< + ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> + blocking( + void Function(ffi.Pointer, NSStream, NSStreamEvent) fn) { + final raw = objc.newClosureBlock( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingCallable + .nativeFunction + .cast(), + (ffi.Pointer arg0, ffi.Pointer arg1, + int arg2) => + fn( + arg0, + NSStream.castFromPointer(arg1, retain: false, release: true), + NSStreamEvent.fromValue(arg2))); + final rawListener = objc.newClosureBlock( + _ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_blockingListenerCallable + .nativeFunction + .cast(), + (ffi.Pointer arg0, ffi.Pointer arg1, + int arg2) => + fn( + arg0, + NSStream.castFromPointer(arg1, retain: false, release: true), + NSStreamEvent.fromValue(arg2))); + final wrapper = objc.wrapBlockingBlock( + _ObjectiveCBindings_wrapBlockingBlock_hoampi, raw, rawListener); + objc.objectRelease(raw.cast()); + objc.objectRelease(rawListener.cast()); + return objc.ObjCBlock< + ffi.Void Function(ffi.Pointer, NSStream, + ffi.UnsignedLong)>(wrapper, retain: false, release: true); + } +} + +/// Call operator for `objc.ObjCBlock, NSStream, ffi.UnsignedLong)>`. +extension ObjCBlock_ffiVoid_ffiVoid_NSStream_NSStreamEvent_CallExtension + on objc.ObjCBlock< + ffi.Void Function(ffi.Pointer, NSStream, ffi.UnsignedLong)> { + void call(ffi.Pointer arg0, NSStream arg1, NSStreamEvent arg2) => + ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.UnsignedLong arg2)>>() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int)>()(ref.pointer, arg0, arg1.ref.pointer, arg2.value); +} + void _ObjCBlock_ffiVoid_idNSSecureCoding_NSError_fnPtrTrampoline( ffi.Pointer block, ffi.Pointer arg0, @@ -14572,6 +14936,20 @@ final _objc_msgSend_3ctkt6 = objc.msgSendPointer .asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); +final _objc_msgSend_3l8zum = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong)>>() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int)>(); final _objc_msgSend_3nbx5e = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -16248,6 +16626,7 @@ late final _sel_stopAccessingSecurityScopedResource = objc.registerName("stopAccessingSecurityScopedResource"); late final _sel_streamError = objc.registerName("streamError"); late final _sel_streamStatus = objc.registerName("streamStatus"); +late final _sel_stream_handleEvent_ = objc.registerName("stream:handleEvent:"); late final _sel_string = objc.registerName("string"); late final _sel_stringByAppendingFormat_ = objc.registerName("stringByAppendingFormat:"); diff --git a/pkgs/objective_c/src/objective_c_bindings_generated.m b/pkgs/objective_c/src/objective_c_bindings_generated.m index 5c14b266d7..6a1372a06b 100644 --- a/pkgs/objective_c/src/objective_c_bindings_generated.m +++ b/pkgs/objective_c/src/objective_c_bindings_generated.m @@ -112,19 +112,47 @@ _ListenerTrampoline2 _ObjectiveCBindings_wrapBlockingBlock_18v1jvf( }; } -typedef void (^_ListenerTrampoline3)(id arg0, id arg1); +typedef void (^_ListenerTrampoline3)(void * arg0, id arg1, NSStreamEvent arg2); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline3 _ObjectiveCBindings_wrapListenerBlock_pfv6jd(_ListenerTrampoline3 block) NS_RETURNS_RETAINED { +_ListenerTrampoline3 _ObjectiveCBindings_wrapListenerBlock_hoampi(_ListenerTrampoline3 block) NS_RETURNS_RETAINED { + return ^void(void * arg0, id arg1, NSStreamEvent arg2) { + objc_retainBlock(block); + block(arg0, (__bridge id)(__bridge_retained void*)(arg1), arg2); + }; +} + +typedef void (^_BlockingTrampoline3)(void * waiter, void * arg0, id arg1, NSStreamEvent arg2); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline3 _ObjectiveCBindings_wrapBlockingBlock_hoampi( + _BlockingTrampoline3 block, _BlockingTrampoline3 listenerBlock, + void* (*newWaiter)(), void (*awaitWaiter)(void*)) NS_RETURNS_RETAINED { + NSThread *targetThread = [NSThread currentThread]; + return ^void(void * arg0, id arg1, NSStreamEvent arg2) { + if ([NSThread currentThread] == targetThread) { + objc_retainBlock(block); + block(nil, arg0, (__bridge id)(__bridge_retained void*)(arg1), arg2); + } else { + void* waiter = newWaiter(); + objc_retainBlock(listenerBlock); + listenerBlock(waiter, arg0, (__bridge id)(__bridge_retained void*)(arg1), arg2); + awaitWaiter(waiter); + } + }; +} + +typedef void (^_ListenerTrampoline4)(id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline4 _ObjectiveCBindings_wrapListenerBlock_pfv6jd(_ListenerTrampoline4 block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1) { objc_retainBlock(block); block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); }; } -typedef void (^_BlockingTrampoline3)(void * waiter, id arg0, id arg1); +typedef void (^_BlockingTrampoline4)(void * waiter, id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline3 _ObjectiveCBindings_wrapBlockingBlock_pfv6jd( - _BlockingTrampoline3 block, _BlockingTrampoline3 listenerBlock, +_ListenerTrampoline4 _ObjectiveCBindings_wrapBlockingBlock_pfv6jd( + _BlockingTrampoline4 block, _BlockingTrampoline4 listenerBlock, void* (*newWaiter)(), void (*awaitWaiter)(void*)) NS_RETURNS_RETAINED { NSThread *targetThread = [NSThread currentThread]; return ^void(id arg0, id arg1) { diff --git a/pkgs/objective_c/test/ns_input_stream_test.dart b/pkgs/objective_c/test/ns_input_stream_test.dart index 40682a2aee..123dda3062 100644 --- a/pkgs/objective_c/test/ns_input_stream_test.dart +++ b/pkgs/objective_c/test/ns_input_stream_test.dart @@ -253,12 +253,10 @@ void main() { }); test('non-self delegate', () async { - final protoBuilder = ObjCProtocolBuilder(); final events = []; - NSStreamDelegate.addToBuilder(protoBuilder, + inputStream.delegate = NSStreamDelegate.implement( stream_handleEvent_: (stream, event) => events.add(event)); - inputStream.delegate = protoBuilder.build(); inputStream.stream_handleEvent_( inputStream, NSStreamEvent.NSStreamEventOpenCompleted); expect(events, [NSStreamEvent.NSStreamEventOpenCompleted]); @@ -298,7 +296,7 @@ void main() { [1, 2, 3], ]).toNSInputStream() as DartInputStreamAdapter; - inputStream.delegate = NSObject.new1(); + inputStream.delegate = NSStreamDelegate.castFrom(NSObject.new1()); expect(inputStream.delegate, isNot(inputStream)); final ptr = inputStream.ref.pointer; From ef8eb983eb017f76be7ec95ecec530e9aec466bf Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Mon, 3 Feb 2025 12:11:21 +1100 Subject: [PATCH 10/13] Fix tests --- .../objc_built_in_functions.dart | 2 + .../test/unit_tests/subtyping_test.dart | 13 - pkgs/objective_c/ffigen_objc.yaml | 2 + pkgs/objective_c/lib/objective_c.dart | 2 + .../src/objective_c_bindings_generated.dart | 321 +++++++++++++++++- 5 files changed, 321 insertions(+), 19 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart index 49cdc4da43..b230bb49ef 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart @@ -130,6 +130,8 @@ class ObjCBuiltInFunctions { 'NSCoding': 'NSCoding', 'NSCopying': 'NSCopying', 'NSFastEnumeration': 'NSFastEnumeration', + 'NSItemProviderReading': 'NSItemProviderReading', + 'NSItemProviderWriting': 'NSItemProviderWriting', 'NSMutableCopying': 'NSMutableCopying', 'NSObject': 'NSObjectProtocol', 'NSSecureCoding': 'NSSecureCoding', diff --git a/pkgs/ffigen/test/unit_tests/subtyping_test.dart b/pkgs/ffigen/test/unit_tests/subtyping_test.dart index c5855cb6b4..59d26afe2a 100644 --- a/pkgs/ffigen/test/unit_tests/subtyping_test.dart +++ b/pkgs/ffigen/test/unit_tests/subtyping_test.dart @@ -128,19 +128,6 @@ void main() { expect(proto3.isSupertypeOf(proto1), isFalse); }); - test('loop', () { - final loop = ObjCProtocol( - usr: 'Loop', - originalName: 'Loop', - builtInFunctions: builtInFunctions, - ); - loop.superProtocols.add(loop); - - expect(loop.isSupertypeOf(loop), isTrue); - expect(loop.isSupertypeOf(proto1), isFalse); - expect(proto1.isSupertypeOf(loop), isFalse); - }); - test('vs ObjCInterface', () { expect(grandparent.isSubtypeOf(protoSub12), isTrue); expect(grandparent.isSubtypeOf(protoSub1), isTrue); diff --git a/pkgs/objective_c/ffigen_objc.yaml b/pkgs/objective_c/ffigen_objc.yaml index 8e4eecf801..835fc06221 100644 --- a/pkgs/objective_c/ffigen_objc.yaml +++ b/pkgs/objective_c/ffigen_objc.yaml @@ -72,6 +72,8 @@ objc-protocols: - NSCoding - NSCopying - NSFastEnumeration + - NSItemProviderReading + - NSItemProviderWriting - NSMutableCopying - NSObject - NSSecureCoding diff --git a/pkgs/objective_c/lib/objective_c.dart b/pkgs/objective_c/lib/objective_c.dart index c4f436d9b5..58d82a24f9 100644 --- a/pkgs/objective_c/lib/objective_c.dart +++ b/pkgs/objective_c/lib/objective_c.dart @@ -66,7 +66,9 @@ export 'src/objective_c_bindings_generated.dart' NSInvocation, NSItemProvider, NSItemProviderFileOptions, + NSItemProviderReading, NSItemProviderRepresentationVisibility, + NSItemProviderWriting, NSKeyValueChange, NSKeyValueObservingOptions, NSKeyValueSetMutationKind, diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index d06edb1eaa..1c68995001 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -3784,15 +3784,41 @@ enum NSItemProviderFileOptions { }; } -/// WARNING: NSItemProviderReading is a stub. To generate bindings for this class, include -/// NSItemProviderReading in your config's objc-protocols list. -/// /// NSItemProviderReading interface class NSItemProviderReading extends objc.ObjCProtocolBase implements NSObjectProtocol { NSItemProviderReading._(ffi.Pointer pointer, {bool retain = false, bool release = false}) : super(pointer, retain: retain, release: release); + + /// Constructs a [NSItemProviderReading] that points to the same underlying object as [other]. + NSItemProviderReading.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSItemProviderReading] that wraps the given raw object pointer. + NSItemProviderReading.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSItemProviderReading]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz(obj.ref.pointer, _sel_conformsToProtocol_, + _protocol_NSItemProviderReading); + } + + /// Builds an object that implements the NSItemProviderReading protocol. To implement + /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. + static NSItemProviderReading implement() { + final builder = objc.ObjCProtocolBuilder(); + + return NSItemProviderReading.castFrom(builder.build()); + } + + /// Adds the implementation of the NSItemProviderReading protocol to an existing + /// [objc.ObjCProtocolBuilder]. + static void addToBuilder( + objc.ObjCProtocolBuilder builder, + ) {} } enum NSItemProviderRepresentationVisibility { @@ -3815,15 +3841,92 @@ enum NSItemProviderRepresentationVisibility { }; } -/// WARNING: NSItemProviderWriting is a stub. To generate bindings for this class, include -/// NSItemProviderWriting in your config's objc-protocols list. -/// /// NSItemProviderWriting interface class NSItemProviderWriting extends objc.ObjCProtocolBase implements NSObjectProtocol { NSItemProviderWriting._(ffi.Pointer pointer, {bool retain = false, bool release = false}) : super(pointer, retain: retain, release: release); + + /// Constructs a [NSItemProviderWriting] that points to the same underlying object as [other]. + NSItemProviderWriting.castFrom(objc.ObjCObjectBase other) + : this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [NSItemProviderWriting] that wraps the given raw object pointer. + NSItemProviderWriting.castFromPointer(ffi.Pointer other, + {bool retain = false, bool release = false}) + : this._(other, retain: retain, release: release); + + /// Returns whether [obj] is an instance of [NSItemProviderWriting]. + static bool conformsTo(objc.ObjCObjectBase obj) { + return _objc_msgSend_e3qsqz(obj.ref.pointer, _sel_conformsToProtocol_, + _protocol_NSItemProviderWriting); + } + + /// Builds an object that implements the NSItemProviderWriting protocol. To implement + /// multiple protocols, use [addToBuilder] or [objc.ObjCProtocolBuilder] directly. + static NSItemProviderWriting implement( + {NSItemProviderRepresentationVisibility Function(NSString)? + itemProviderVisibilityForRepresentationWithTypeIdentifier_, + NSArray Function()? writableTypeIdentifiersForItemProvider}) { + final builder = objc.ObjCProtocolBuilder(); + NSItemProviderWriting + .itemProviderVisibilityForRepresentationWithTypeIdentifier_ + .implement(builder, + itemProviderVisibilityForRepresentationWithTypeIdentifier_); + NSItemProviderWriting.writableTypeIdentifiersForItemProvider + .implement(builder, writableTypeIdentifiersForItemProvider); + return NSItemProviderWriting.castFrom(builder.build()); + } + + /// Adds the implementation of the NSItemProviderWriting protocol to an existing + /// [objc.ObjCProtocolBuilder]. + static void addToBuilder(objc.ObjCProtocolBuilder builder, + {NSItemProviderRepresentationVisibility Function(NSString)? + itemProviderVisibilityForRepresentationWithTypeIdentifier_, + NSArray Function()? writableTypeIdentifiersForItemProvider}) { + NSItemProviderWriting + .itemProviderVisibilityForRepresentationWithTypeIdentifier_ + .implement(builder, + itemProviderVisibilityForRepresentationWithTypeIdentifier_); + NSItemProviderWriting.writableTypeIdentifiersForItemProvider + .implement(builder, writableTypeIdentifiersForItemProvider); + } + + /// itemProviderVisibilityForRepresentationWithTypeIdentifier: + static final itemProviderVisibilityForRepresentationWithTypeIdentifier_ = + objc.ObjCProtocolMethod< + NSItemProviderRepresentationVisibility Function(NSString)>( + _protocol_NSItemProviderWriting, + _sel_itemProviderVisibilityForRepresentationWithTypeIdentifier_, + objc.getProtocolMethodSignature( + _protocol_NSItemProviderWriting, + _sel_itemProviderVisibilityForRepresentationWithTypeIdentifier_, + isRequired: false, + isInstanceMethod: true, + ), + (NSItemProviderRepresentationVisibility Function(NSString) func) => + ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString + .fromFunction( + (ffi.Pointer _, NSString arg1) => func(arg1)), + ); + + /// writableTypeIdentifiersForItemProvider + static final writableTypeIdentifiersForItemProvider = + objc.ObjCProtocolMethod( + _protocol_NSItemProviderWriting, + _sel_writableTypeIdentifiersForItemProvider, + objc.getProtocolMethodSignature( + _protocol_NSItemProviderWriting, + _sel_writableTypeIdentifiersForItemProvider, + isRequired: false, + isInstanceMethod: true, + ), + (NSArray Function() func) => ObjCBlock_NSArray_ffiVoid.fromFunction(( + ffi.Pointer _, + ) => + func()), + ); } enum NSKeyValueChange { @@ -10893,6 +10996,193 @@ class NSValue extends NSObject implements NSCopying, NSSecureCoding { final class NSZone extends ffi.Opaque {} +ffi.Pointer _ObjCBlock_NSArray_ffiVoid_fnPtrTrampoline( + ffi.Pointer block, ffi.Pointer arg0) => + block.ref.target + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer arg0)>>() + .asFunction< + ffi.Pointer Function( + ffi.Pointer)>()(arg0); +ffi.Pointer _ObjCBlock_NSArray_ffiVoid_fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>( + _ObjCBlock_NSArray_ffiVoid_fnPtrTrampoline) + .cast(); +ffi.Pointer _ObjCBlock_NSArray_ffiVoid_closureTrampoline( + ffi.Pointer block, ffi.Pointer arg0) => + (objc.getBlockClosure(block) as ffi.Pointer Function( + ffi.Pointer))(arg0); +ffi.Pointer _ObjCBlock_NSArray_ffiVoid_closureCallable = + ffi.Pointer.fromFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>( + _ObjCBlock_NSArray_ffiVoid_closureTrampoline) + .cast(); + +/// Construction methods for `objc.ObjCBlock)>`. +abstract final class ObjCBlock_NSArray_ffiVoid { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock)> + castFromPointer(ffi.Pointer pointer, + {bool retain = false, bool release = false}) => + objc.ObjCBlock)>(pointer, + retain: retain, release: release); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock)> fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer arg0)>> + ptr) => + objc.ObjCBlock)>( + objc.newPointerBlock( + _ObjCBlock_NSArray_ffiVoid_fnPtrCallable, ptr.cast()), + retain: false, + release: true); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock)> fromFunction( + NSArray Function(ffi.Pointer) fn) => + objc.ObjCBlock)>( + objc.newClosureBlock( + _ObjCBlock_NSArray_ffiVoid_closureCallable, + (ffi.Pointer arg0) => + fn(arg0).ref.retainAndAutorelease()), + retain: false, + release: true); +} + +/// Call operator for `objc.ObjCBlock)>`. +extension ObjCBlock_NSArray_ffiVoid_CallExtension + on objc.ObjCBlock)> { + NSArray call(ffi.Pointer arg0) => NSArray.castFromPointer( + ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer block, + ffi.Pointer arg0)>>() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer)>()(ref.pointer, arg0), + retain: true, + release: true); +} + +int _ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1) => + block.ref.target + .cast< + ffi.NativeFunction< + ffi.Long Function(ffi.Pointer arg0, + ffi.Pointer arg1)>>() + .asFunction< + int Function(ffi.Pointer, + ffi.Pointer)>()(arg0, arg1); +ffi.Pointer + _ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Long Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>( + _ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_fnPtrTrampoline, + 0) + .cast(); +int _ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1) => + (objc.getBlockClosure(block) as int Function( + ffi.Pointer, ffi.Pointer))(arg0, arg1); +ffi.Pointer + _ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_closureCallable = + ffi.Pointer.fromFunction< + ffi.Long Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>( + _ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_closureTrampoline, + 0) + .cast(); + +/// Construction methods for `objc.ObjCBlock, NSString)>`. +abstract final class ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock, NSString)> + castFromPointer(ffi.Pointer pointer, + {bool retain = false, bool release = false}) => + objc.ObjCBlock, NSString)>( + pointer, + retain: retain, + release: release); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock, NSString)> + fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Long Function(ffi.Pointer arg0, + ffi.Pointer arg1)>> + ptr) => + objc.ObjCBlock, NSString)>( + objc.newPointerBlock(_ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_fnPtrCallable, ptr.cast()), + retain: false, + release: true); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock, NSString)> fromFunction( + NSItemProviderRepresentationVisibility Function( + ffi.Pointer, NSString) + fn) => + objc.ObjCBlock, NSString)>( + objc.newClosureBlock( + _ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_closureCallable, + (ffi.Pointer arg0, ffi.Pointer arg1) => + fn(arg0, NSString.castFromPointer(arg1, retain: true, release: true)) + .value), + retain: false, + release: true); +} + +/// Call operator for `objc.ObjCBlock, NSString)>`. +extension ObjCBlock_NSItemProviderRepresentationVisibility_ffiVoid_NSString_CallExtension + on objc.ObjCBlock, NSString)> { + NSItemProviderRepresentationVisibility call( + ffi.Pointer arg0, NSString arg1) => + NSItemProviderRepresentationVisibility.fromValue(ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Long Function( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1)>>() + .asFunction< + int Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>()( + ref.pointer, arg0, arg1.ref.pointer)); +} + ffi.Pointer _ObjCBlock_NSString_ffiVoid_fnPtrTrampoline( ffi.Pointer block, ffi.Pointer arg0) => block.ref.target @@ -13975,6 +14265,16 @@ final _objc_msgSend_16f0drb = objc.msgSendPointer .asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int)>(); +final _objc_msgSend_16fy0up = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Long Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>() + .asFunction< + int Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>(); final _objc_msgSend_17amj0z = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -15800,6 +16100,10 @@ final _objc_msgSend_zug4wi = objc.msgSendPointer late final _protocol_NSCoding = objc.getProtocol("NSCoding"); late final _protocol_NSCopying = objc.getProtocol("NSCopying"); late final _protocol_NSFastEnumeration = objc.getProtocol("NSFastEnumeration"); +late final _protocol_NSItemProviderReading = + objc.getProtocol("NSItemProviderReading"); +late final _protocol_NSItemProviderWriting = + objc.getProtocol("NSItemProviderWriting"); late final _protocol_NSMutableCopying = objc.getProtocol("NSMutableCopying"); late final _protocol_NSObject = objc.getProtocol("NSObject"); late final _protocol_NSSecureCoding = objc.getProtocol("NSSecureCoding"); @@ -16302,6 +16606,9 @@ late final _sel_isSubsetOfOrderedSet_ = objc.registerName("isSubsetOfOrderedSet:"); late final _sel_isSubsetOfSet_ = objc.registerName("isSubsetOfSet:"); late final _sel_isSupersetOfSet_ = objc.registerName("isSupersetOfSet:"); +late final _sel_itemProviderVisibilityForRepresentationWithTypeIdentifier_ = + objc.registerName( + "itemProviderVisibilityForRepresentationWithTypeIdentifier:"); late final _sel_keyEnumerator = objc.registerName("keyEnumerator"); late final _sel_keysSortedByValueUsingSelector_ = objc.registerName("keysSortedByValueUsingSelector:"); @@ -16706,6 +17013,8 @@ late final _sel_whitespaceAndNewlineCharacterSet = objc.registerName("whitespaceAndNewlineCharacterSet"); late final _sel_whitespaceCharacterSet = objc.registerName("whitespaceCharacterSet"); +late final _sel_writableTypeIdentifiersForItemProvider = + objc.registerName("writableTypeIdentifiersForItemProvider"); late final _sel_writeBookmarkData_toURL_options_error_ = objc.registerName("writeBookmarkData:toURL:options:error:"); late final _sel_writeToFile_atomically_ = From b721af9ea92dda06a4ac38dde6c208a8b2cedfe1 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Mon, 3 Feb 2025 12:38:36 +1100 Subject: [PATCH 11/13] Revert stub ctor changes --- .../src/code_generator/objc_interface.dart | 27 ++++++++----------- .../lib/src/code_generator/objc_protocol.dart | 19 ++++++------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart index 99027b9cda..6d62671009 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart @@ -77,15 +77,20 @@ class ObjCInterface extends BindingType with ObjCMethods { ? '' : 'implements ${protocols.map((p) => p.getDartType(w)).join(', ')} '; - final superCtor = superType == null - ? 'super' - : superType!.isObjCImport - ? 'super.castFromPointer' - : 'super._'; + final superCtor = superType == null ? 'super' : 'super.castFromPointer'; s.write(''' class $name extends ${superType?.getDartType(w) ?? wrapObjType} $protoImpl{ $name._($rawObjType pointer, {bool retain = false, bool release = false}) : - $superCtor(pointer, retain: retain, release: release); + $superCtor(pointer, retain: retain, release: release); + + /// Constructs a [$name] that points to the same underlying object as [other]. + $name.castFrom($wrapObjType other) : + this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [$name] that wraps the given raw object pointer. + $name.castFromPointer($rawObjType other, + {bool retain = false, bool release = false}) : + this._(other, retain: retain, release: release); ${generateAsStub ? '' : _generateMethods(w)} } @@ -97,20 +102,10 @@ ${generateAsStub ? '' : _generateMethods(w)} } String _generateMethods(Writer w) { - final rawObjType = PointerType(objCObjectType).getCType(w); final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(w); final s = StringBuffer(); s.write(''' - /// Constructs a [$name] that points to the same underlying object as [other]. - $name.castFrom($wrapObjType other) : - this._(other.ref.pointer, retain: true, release: true); - - /// Constructs a [$name] that wraps the given raw object pointer. - $name.castFromPointer($rawObjType other, - {bool retain = false, bool release = false}) : - this._(other, retain: retain, release: release); - /// Returns whether [obj] is an instance of [$name]. static bool isInstance($wrapObjType obj) { return ${_isKindOfClassMsgSend.invoke( diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index f4c9813707..ebd138d45e 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -83,6 +83,16 @@ class ObjCProtocol extends BindingType with ObjCMethods { interface class $name extends $protocolBase $impls{ $name._($rawObjType pointer, {bool retain = false, bool release = false}) : super(pointer, retain: retain, release: release); + + /// Constructs a [$name] that points to the same underlying object as [other]. + $name.castFrom($objectBase other) : + this._(other.ref.pointer, retain: true, release: true); + + /// Constructs a [$name] that wraps the given raw object pointer. + $name.castFromPointer($rawObjType other, + {bool retain = false, bool release = false}) : + this._(other, retain: retain, release: release); + '''); if (!generateAsStub) { @@ -216,15 +226,6 @@ interface class $name extends $protocolBase $impls{ } s.write(''' - /// Constructs a [$name] that points to the same underlying object as [other]. - $name.castFrom($objectBase other) : - this._(other.ref.pointer, retain: true, release: true); - - /// Constructs a [$name] that wraps the given raw object pointer. - $name.castFromPointer($rawObjType other, - {bool retain = false, bool release = false}) : - this._(other, retain: retain, release: release); - /// Returns whether [obj] is an instance of [$name]. static bool conformsTo($objectBase obj) { return ${_conformsToMsgSend.invoke( From fbf1c3dd1ce8292d250e3460aacea485674f7aea Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Mon, 3 Feb 2025 12:58:40 +1100 Subject: [PATCH 12/13] Fix tests --- .../native_objc_test/transitive_test.dart | 34 +++++----- .../src/objective_c_bindings_generated.dart | 64 +++++++++---------- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/pkgs/ffigen/test/native_objc_test/transitive_test.dart b/pkgs/ffigen/test/native_objc_test/transitive_test.dart index 45b8b5eb82..c9f4adf7ad 100644 --- a/pkgs/ffigen/test/native_objc_test/transitive_test.dart +++ b/pkgs/ffigen/test/native_objc_test/transitive_test.dart @@ -148,14 +148,12 @@ void main() { test('included', () { bindings = generate(includeTransitiveObjCProtocols: true); - // TODO(https://github.com/dart-lang/native/issues/1462): Transitive - // protocols should be included. - expect(incProto('DoublyTransitiveProtocol'), Inclusion.omitted); - expect(incProto('TransitiveSuperProtocol'), Inclusion.omitted); - expect(incProto('TransitiveProtocol'), Inclusion.omitted); + expect(incProto('DoublyTransitiveProtocol'), Inclusion.included); + expect(incProto('TransitiveSuperProtocol'), Inclusion.included); + expect(incProto('TransitiveProtocol'), Inclusion.included); expect(incProto('SuperSuperProtocol'), Inclusion.included); - expect(incProto('DoublySuperTransitiveProtocol'), Inclusion.omitted); - expect(incProto('SuperTransitiveProtocol'), Inclusion.omitted); + expect(incProto('DoublySuperTransitiveProtocol'), Inclusion.included); + expect(incProto('SuperTransitiveProtocol'), Inclusion.included); expect(incProto('SuperProtocol'), Inclusion.included); expect(incProto('AnotherSuperProtocol'), Inclusion.included); expect(incProto('DirectlyIncludedProtocol'), Inclusion.included); @@ -163,15 +161,15 @@ void main() { expect(incProto('NotIncludedTransitiveProtocol'), Inclusion.omitted); expect(incProto('NotIncludedProtocol'), Inclusion.omitted); expect(incProto('SuperFromInterfaceProtocol'), Inclusion.included); - expect(incProto('TransitiveFromInterfaceProtocol'), Inclusion.omitted); + expect(incProto('TransitiveFromInterfaceProtocol'), Inclusion.included); expect(incItf('DirectlyIncludedWithProtocol'), Inclusion.included); - expect(bindings.contains('doubleProtoMethod'), isFalse); - expect(bindings.contains('transitiveSuperProtoMethod'), isFalse); - expect(bindings.contains('transitiveProtoMethod'), isFalse); + expect(bindings.contains('doubleProtoMethod'), isTrue); + expect(bindings.contains('transitiveSuperProtoMethod'), isTrue); + expect(bindings.contains('transitiveProtoMethod'), isTrue); expect(bindings.contains('superSuperProtoMethod'), isTrue); - expect(bindings.contains('doublySuperProtoMethod'), isFalse); - expect(bindings.contains('superTransitiveProtoMethod'), isFalse); + expect(bindings.contains('doublySuperProtoMethod'), isTrue); + expect(bindings.contains('superTransitiveProtoMethod'), isTrue); expect(bindings.contains('superProtoMethod'), isTrue); expect(bindings.contains('anotherSuperProtoMethod'), isTrue); expect(bindings.contains('directProtoMethod'), isTrue); @@ -180,7 +178,7 @@ void main() { expect(bindings.contains('notIncludedProtoMethod'), isFalse); expect(bindings.contains('superFromInterfaceProtoMethod'), isTrue); expect( - bindings.contains('transitiveFromInterfaceProtoMethod'), isFalse); + bindings.contains('transitiveFromInterfaceProtoMethod'), isTrue); expect(bindings.contains('directlyIncludedWithProtoMethod'), isTrue); }); @@ -188,11 +186,11 @@ void main() { bindings = generate(includeTransitiveObjCProtocols: false); expect(incProto('DoublyTransitiveProtocol'), Inclusion.omitted); - expect(incProto('TransitiveSuperProtocol'), Inclusion.omitted); - expect(incProto('TransitiveProtocol'), Inclusion.omitted); + expect(incProto('TransitiveSuperProtocol'), Inclusion.stubbed); + expect(incProto('TransitiveProtocol'), Inclusion.stubbed); expect(incProto('SuperSuperProtocol'), Inclusion.stubbed); expect(incProto('DoublySuperTransitiveProtocol'), Inclusion.omitted); - expect(incProto('SuperTransitiveProtocol'), Inclusion.omitted); + expect(incProto('SuperTransitiveProtocol'), Inclusion.stubbed); expect(incProto('SuperProtocol'), Inclusion.stubbed); expect(incProto('AnotherSuperProtocol'), Inclusion.stubbed); expect(incProto('DirectlyIncludedProtocol'), Inclusion.included); @@ -200,7 +198,7 @@ void main() { expect(incProto('NotIncludedTransitiveProtocol'), Inclusion.omitted); expect(incProto('NotIncludedProtocol'), Inclusion.omitted); expect(incProto('SuperFromInterfaceProtocol'), Inclusion.stubbed); - expect(incProto('TransitiveFromInterfaceProtocol'), Inclusion.omitted); + expect(incProto('TransitiveFromInterfaceProtocol'), Inclusion.stubbed); expect(incItf('DirectlyIncludedWithProtocol'), Inclusion.included); expect(bindings.contains('doubleProtoMethod'), isFalse); diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index 1c68995001..6fc737148d 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -165,7 +165,7 @@ external ffi.Pointer class DartInputStreamAdapter extends NSInputStream implements NSStreamDelegate { DartInputStreamAdapter._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [DartInputStreamAdapter] that points to the same underlying object as [other]. DartInputStreamAdapter.castFrom(objc.ObjCObjectBase other) @@ -282,7 +282,7 @@ class DartInputStreamAdapter extends NSInputStream implements NSStreamDelegate { class DartProxy extends NSProxy { DartProxy._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [DartProxy] that points to the same underlying object as [other]. DartProxy.castFrom(objc.ObjCObjectBase other) @@ -362,7 +362,7 @@ class DartProxy extends NSProxy { class DartProxyBuilder extends NSObject { DartProxyBuilder._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [DartProxyBuilder] that points to the same underlying object as [other]. DartProxyBuilder.castFrom(objc.ObjCObjectBase other) @@ -443,7 +443,7 @@ class NSArray extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSArray._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSArray] that points to the same underlying object as [other]. NSArray.castFrom(objc.ObjCObjectBase other) @@ -614,7 +614,7 @@ class NSCharacterSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding { NSCharacterSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSCharacterSet] that points to the same underlying object as [other]. NSCharacterSet.castFrom(objc.ObjCObjectBase other) @@ -1091,7 +1091,7 @@ class NSData extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding { NSData._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSData] that points to the same underlying object as [other]. NSData.castFrom(objc.ObjCObjectBase other) @@ -1518,7 +1518,7 @@ enum NSDataWritingOptions { class NSDate extends NSObject implements NSCopying, NSSecureCoding { NSDate._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSDate] that points to the same underlying object as [other]. NSDate.castFrom(objc.ObjCObjectBase other) @@ -1684,7 +1684,7 @@ class NSDictionary extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSDictionary._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSDictionary] that points to the same underlying object as [other]. NSDictionary.castFrom(objc.ObjCObjectBase other) @@ -1885,7 +1885,7 @@ enum NSEnumerationOptions { class NSEnumerator extends NSObject implements NSFastEnumeration { NSEnumerator._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSEnumerator] that points to the same underlying object as [other]. NSEnumerator.castFrom(objc.ObjCObjectBase other) @@ -1950,7 +1950,7 @@ class NSEnumerator extends NSObject implements NSFastEnumeration { class NSError extends NSObject implements NSCopying, NSSecureCoding { NSError._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSError] that points to the same underlying object as [other]. NSError.castFrom(objc.ObjCObjectBase other) @@ -3304,7 +3304,7 @@ class NSIndexSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding { NSIndexSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSIndexSet] that points to the same underlying object as [other]. NSIndexSet.castFrom(objc.ObjCObjectBase other) @@ -3496,7 +3496,7 @@ class NSIndexSet extends NSObject class NSInputStream extends NSStream { NSInputStream._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSInputStream] that points to the same underlying object as [other]. NSInputStream.castFrom(objc.ObjCObjectBase other) @@ -3610,7 +3610,7 @@ class NSInvocation extends objc.ObjCObjectBase { class NSItemProvider extends NSObject implements NSCopying { NSItemProvider._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSItemProvider] that points to the same underlying object as [other]. NSItemProvider.castFrom(objc.ObjCObjectBase other) @@ -4011,7 +4011,7 @@ class NSLocale extends objc.ObjCObjectBase { class NSMethodSignature extends NSObject { NSMethodSignature._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMethodSignature] that points to the same underlying object as [other]. NSMethodSignature.castFrom(objc.ObjCObjectBase other) @@ -4104,7 +4104,7 @@ class NSMethodSignature extends NSObject { class NSMutableArray extends NSArray { NSMutableArray._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMutableArray] that points to the same underlying object as [other]. NSMutableArray.castFrom(objc.ObjCObjectBase other) @@ -4332,7 +4332,7 @@ interface class NSMutableCopying extends objc.ObjCProtocolBase { class NSMutableData extends NSData { NSMutableData._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMutableData] that points to the same underlying object as [other]. NSMutableData.castFrom(objc.ObjCObjectBase other) @@ -4661,7 +4661,7 @@ class NSMutableData extends NSData { class NSMutableDictionary extends NSDictionary { NSMutableDictionary._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMutableDictionary] that points to the same underlying object as [other]. NSMutableDictionary.castFrom(objc.ObjCObjectBase other) @@ -4858,7 +4858,7 @@ class NSMutableDictionary extends NSDictionary { class NSMutableIndexSet extends NSIndexSet { NSMutableIndexSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMutableIndexSet] that points to the same underlying object as [other]. NSMutableIndexSet.castFrom(objc.ObjCObjectBase other) @@ -5012,7 +5012,7 @@ class NSMutableIndexSet extends NSIndexSet { class NSMutableOrderedSet extends NSOrderedSet { NSMutableOrderedSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMutableOrderedSet] that points to the same underlying object as [other]. NSMutableOrderedSet.castFrom(objc.ObjCObjectBase other) @@ -5320,7 +5320,7 @@ class NSMutableOrderedSet extends NSOrderedSet { class NSMutableSet extends NSSet { NSMutableSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMutableSet] that points to the same underlying object as [other]. NSMutableSet.castFrom(objc.ObjCObjectBase other) @@ -5485,7 +5485,7 @@ class NSMutableSet extends NSSet { class NSMutableString extends NSString { NSMutableString._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSMutableString] that points to the same underlying object as [other]. NSMutableString.castFrom(objc.ObjCObjectBase other) @@ -5930,7 +5930,7 @@ class NSMutableString extends NSString { class NSNotification extends NSObject implements NSCopying, NSCoding { NSNotification._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSNotification] that points to the same underlying object as [other]. NSNotification.castFrom(objc.ObjCObjectBase other) @@ -6068,7 +6068,7 @@ class NSNotification extends NSObject implements NSCopying, NSCoding { class NSNumber extends NSValue { NSNumber._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSNumber] that points to the same underlying object as [other]. NSNumber.castFrom(objc.ObjCObjectBase other) @@ -7500,7 +7500,7 @@ class NSOrderedCollectionDifference extends NSObject implements NSFastEnumeration { NSOrderedCollectionDifference._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSOrderedCollectionDifference] that points to the same underlying object as [other]. NSOrderedCollectionDifference.castFrom(objc.ObjCObjectBase other) @@ -7656,7 +7656,7 @@ class NSOrderedSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSOrderedSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSOrderedSet] that points to the same underlying object as [other]. NSOrderedSet.castFrom(objc.ObjCObjectBase other) @@ -7930,7 +7930,7 @@ class NSOrderedSet extends NSObject class NSOutputStream extends NSStream { NSOutputStream._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSOutputStream] that points to the same underlying object as [other]. NSOutputStream.castFrom(objc.ObjCObjectBase other) @@ -8358,7 +8358,7 @@ class NSSet extends NSObject implements NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration { NSSet._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSSet] that points to the same underlying object as [other]. NSSet.castFrom(objc.ObjCObjectBase other) @@ -8546,7 +8546,7 @@ enum NSSortOptions { class NSStream extends NSObject { NSStream._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSStream] that points to the same underlying object as [other]. NSStream.castFrom(objc.ObjCObjectBase other) @@ -8839,7 +8839,7 @@ class NSString extends NSObject NSString._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSString] that points to the same underlying object as [other]. NSString.castFrom(objc.ObjCObjectBase other) @@ -10129,7 +10129,7 @@ extension NSStringExtensionMethods on NSString { class NSURL extends NSObject implements NSSecureCoding, NSCopying { NSURL._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSURL] that points to the same underlying object as [other]. NSURL.castFrom(objc.ObjCObjectBase other) @@ -10828,7 +10828,7 @@ enum NSURLBookmarkResolutionOptions { class NSURLHandle extends NSObject { NSURLHandle._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSURLHandle] that points to the same underlying object as [other]. NSURLHandle.castFrom(objc.ObjCObjectBase other) @@ -10912,7 +10912,7 @@ enum NSURLHandleStatus { class NSValue extends NSObject implements NSCopying, NSSecureCoding { NSValue._(ffi.Pointer pointer, {bool retain = false, bool release = false}) - : super._(pointer, retain: retain, release: release); + : super.castFromPointer(pointer, retain: retain, release: release); /// Constructs a [NSValue] that points to the same underlying object as [other]. NSValue.castFrom(objc.ObjCObjectBase other) From 567fc7903182a70a20f52959265b51ec7fb26fd1 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Mon, 3 Feb 2025 13:47:10 +1100 Subject: [PATCH 13/13] fmt --- pkgs/ffigen/test/native_objc_test/transitive_test.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/ffigen/test/native_objc_test/transitive_test.dart b/pkgs/ffigen/test/native_objc_test/transitive_test.dart index c9f4adf7ad..62f7738ce5 100644 --- a/pkgs/ffigen/test/native_objc_test/transitive_test.dart +++ b/pkgs/ffigen/test/native_objc_test/transitive_test.dart @@ -177,8 +177,7 @@ void main() { expect(bindings.contains('notIncludedTransitiveProtoMethod'), isFalse); expect(bindings.contains('notIncludedProtoMethod'), isFalse); expect(bindings.contains('superFromInterfaceProtoMethod'), isTrue); - expect( - bindings.contains('transitiveFromInterfaceProtoMethod'), isTrue); + expect(bindings.contains('transitiveFromInterfaceProtoMethod'), isTrue); expect(bindings.contains('directlyIncludedWithProtoMethod'), isTrue); });