Skip to content

Commit bafe220

Browse files
authored
Some quick fixes for ffigen (#1246)
1 parent 7ea9a2d commit bafe220

16 files changed

+225
-78
lines changed

pkgs/ffigen/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
https://github.com/dart-lang/native/issues/1007.
2626
- Added support for implementing ObjC protocols from Dart. Use the
2727
`objc-protocols` config option to generate bindings for a protocol.
28+
- Fix some bugs where ObjC interface/protocol methods could collide with Dart
29+
built-in methods, or with types declared elsewhere in the generated bindings.
2830

2931
## 12.0.0
3032

pkgs/ffigen/lib/src/code_generator/compound.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ abstract class Compound extends BindingType {
5858
int? pack,
5959
String? dartDoc,
6060
List<Member>? members,
61-
required ObjCBuiltInFunctions objCBuiltInFunctions,
61+
ObjCBuiltInFunctions? objCBuiltInFunctions,
6262
}) {
6363
switch (type) {
6464
case CompoundType.struct:
@@ -95,7 +95,7 @@ abstract class Compound extends BindingType {
9595
}
9696

9797
bool get _isBuiltIn =>
98-
objCBuiltInFunctions?.isBuiltInInterface(originalName) ?? false;
98+
objCBuiltInFunctions?.isBuiltInCompound(originalName) ?? false;
9999

100100
@override
101101
BindingString toBindingString(Writer w) {

pkgs/ffigen/lib/src/code_generator/enum_class.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:collection/collection.dart';
77
import 'binding.dart';
88
import 'binding_string.dart';
99
import 'imports.dart';
10+
import 'objc_built_in_functions.dart';
1011
import 'type.dart';
1112
import 'utils.dart';
1213
import 'writer.dart';
@@ -49,13 +50,16 @@ class EnumClass extends BindingType {
4950
/// Generates new names for all members that don't equal [name].
5051
final UniqueNamer namer;
5152

53+
ObjCBuiltInFunctions? objCBuiltInFunctions;
54+
5255
EnumClass({
5356
super.usr,
5457
super.originalName,
5558
required super.name,
5659
super.dartDoc,
5760
Type? nativeType,
5861
List<EnumConstant>? enumConstants,
62+
this.objCBuiltInFunctions,
5963
}) : nativeType = nativeType ?? intType,
6064
enumConstants = enumConstants ?? [],
6165
namer = UniqueNamer({name});
@@ -209,9 +213,15 @@ class EnumClass extends BindingType {
209213
s.write("$depth};\n");
210214
}
211215

216+
bool get _isBuiltIn =>
217+
objCBuiltInFunctions?.isBuiltInEnum(originalName) ?? false;
218+
212219
@override
213220
BindingString toBindingString(Writer w) {
214221
final s = StringBuffer();
222+
if (_isBuiltIn) {
223+
return BindingString(type: BindingStringType.enum_, string: '');
224+
}
215225
scanForDuplicates();
216226

217227
writeDartDoc(s);
@@ -239,7 +249,7 @@ class EnumClass extends BindingType {
239249

240250
@override
241251
void addDependencies(Set<Binding> dependencies) {
242-
if (dependencies.contains(this)) return;
252+
if (dependencies.contains(this) || _isBuiltIn) return;
243253
dependencies.add(this);
244254
}
245255

@@ -253,7 +263,8 @@ class EnumClass extends BindingType {
253263
String getFfiDartType(Writer w) => nativeType.getFfiDartType(w);
254264

255265
@override
256-
String getDartType(Writer w) => name;
266+
String getDartType(Writer w) =>
267+
_isBuiltIn ? '${w.objcPkgPrefix}.$name' : name;
257268

258269
@override
259270
String getNativeType({String varName = ''}) => '$originalName $varName';
@@ -282,7 +293,7 @@ class EnumClass extends BindingType {
282293
required bool objCRetain,
283294
String? objCEnclosingClass,
284295
}) =>
285-
"$name.fromValue($value)";
296+
"${getDartType(w)}.fromValue($value)";
286297
}
287298

288299
/// Represents a single value in an enum.

pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,36 @@ class ObjCBuiltInFunctions {
7171
'NSFastEnumerationState',
7272
'NSRange',
7373
};
74+
static const builtInEnums = {
75+
'NSBinarySearchingOptions',
76+
'NSComparisonResult',
77+
'NSDataBase64DecodingOptions',
78+
'NSDataBase64EncodingOptions',
79+
'NSDataCompressionAlgorithm',
80+
'NSDataReadingOptions',
81+
'NSDataSearchOptions',
82+
'NSDataWritingOptions',
83+
'NSEnumerationOptions',
84+
'NSItemProviderFileOptions',
85+
'NSItemProviderRepresentationVisibility',
86+
'NSOrderedCollectionDifferenceCalculationOptions',
87+
'NSSortOptions',
88+
'NSStringCompareOptions',
89+
'NSStringEncodingConversionOptions',
90+
'NSStringEnumerationOptions',
91+
'NSURLBookmarkCreationOptions',
92+
'NSURLBookmarkResolutionOptions',
93+
'NSURLHandleStatus',
94+
};
7495

7596
// TODO(https://github.com/dart-lang/native/issues/1173): Ideally this check
7697
// would be based on more than just the name.
7798
bool isBuiltInInterface(String name) =>
7899
!generateForPackageObjectiveC && builtInInterfaces.contains(name);
79100
bool isBuiltInCompound(String name) =>
80101
!generateForPackageObjectiveC && builtInCompounds.contains(name);
102+
bool isBuiltInEnum(String name) =>
103+
!generateForPackageObjectiveC && builtInEnums.contains(name);
81104
bool isNSObject(String name) => name == 'NSObject';
82105

83106
// We need to load a separate instance of objc_msgSend for each signature. If

pkgs/ffigen/lib/src/code_generator/objc_interface.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ class ObjCInterface extends BindingType with ObjCMethods {
7575
final s = StringBuffer();
7676
s.write(makeDartDoc(dartDoc ?? originalName));
7777

78-
final uniqueNamer =
79-
UniqueNamer({name, 'pointer'}, parent: w.topLevelUniqueNamer);
78+
final methodNamer = createMethodRenamer(w);
8079

8180
final rawObjType = PointerType(objCObjectType).getCType(w);
8281
final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(w);
@@ -113,7 +112,7 @@ class ObjCInterface extends BindingType with ObjCMethods {
113112

114113
// Methods.
115114
for (final m in methods) {
116-
final methodName = m.getDartMethodName(uniqueNamer);
115+
final methodName = m.getDartMethodName(methodNamer);
117116
final isStatic = m.isClassMethod;
118117
final isStret = m.msgSend!.isStret;
119118

pkgs/ffigen/lib/src/code_generator/objc_methods.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:ffigen/src/code_generator.dart';
66
import 'package:logging/logging.dart';
77

88
import 'utils.dart';
9+
import 'writer.dart';
910

1011
final _logger = Logger('ffigen.code_generator.objc_methods');
1112

@@ -16,6 +17,7 @@ mixin ObjCMethods {
1617
ObjCMethod? getMethod(String name) => _methods[name];
1718

1819
String get originalName;
20+
String get name;
1921
ObjCBuiltInFunctions get builtInFunctions;
2022

2123
void addMethod(ObjCMethod method) {
@@ -93,6 +95,10 @@ mixin ObjCMethods {
9395

9496
return true;
9597
});
98+
99+
UniqueNamer createMethodRenamer(Writer w) => UniqueNamer(
100+
{name, 'pointer', 'toString', 'hashCode', 'runtimeType', 'noSuchMethod'},
101+
parent: w.topLevelUniqueNamer);
96102
}
97103

98104
enum ObjCMethodKind {
@@ -149,10 +155,10 @@ class ObjCMethod {
149155
for (final p in params) {
150156
p.type.addDependencies(dependencies);
151157
}
152-
selObject ??= builtInFunctions.getSelObject(originalName)
158+
selObject = builtInFunctions.getSelObject(originalName)
153159
..addDependencies(dependencies);
154160
if (needMsgSend) {
155-
msgSend ??= builtInFunctions.getMsgSendFunc(returnType, params)
161+
msgSend = builtInFunctions.getMsgSendFunc(returnType, params)
156162
..addDependencies(dependencies);
157163
}
158164
if (needProtocolBlock) {

pkgs/ffigen/lib/src/code_generator/objc_protocol.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ class ObjCProtocol extends NoLookUpBinding with ObjCMethods {
3939
final buildImplementations = StringBuffer();
4040
final methodFields = StringBuffer();
4141

42-
final uniqueNamer = UniqueNamer({name, 'pointer'});
42+
final methodNamer = createMethodRenamer(w);
4343

4444
for (final method in methods) {
45-
final methodName = method.getDartMethodName(uniqueNamer);
45+
final methodName = method.getDartMethodName(methodNamer);
4646
final fieldName = methodName;
4747
final argName = methodName;
4848
final block = method.protocolBlock;

pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ final _logger = Logger('ffigen.header_parser.enumdecl_parser');
5555
originalName: enumName,
5656
name: config.enumClassDecl.renameUsingConfig(enumName),
5757
nativeType: nativeType,
58+
objCBuiltInFunctions: objCBuiltInFunctions,
5859
);
5960
cursor.visitChildren((clang_types.CXCursor child) {
6061
try {

pkgs/ffigen/test/native_objc_test/rename_config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ objc-interfaces:
1616
- _Renamed
1717
rename:
1818
'_(.*)': '$1'
19+
structs:
20+
include:
21+
- CollidingStructName
1922
headers:
2023
entry-points:
2124
- 'rename_test.m'

pkgs/ffigen/test/native_objc_test/rename_test.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,23 @@ void main() {
2727

2828
test('Renamed class', () {
2929
final renamed = Renamed.new1();
30+
3031
renamed.property = 123;
3132
expect(renamed.property, 123);
3233
});
34+
35+
test('Method with the same name as a Dart built in method', () {
36+
final renamed = Renamed.new1();
37+
38+
renamed.property = 123;
39+
expect(renamed.toString(), "Instance of 'Renamed'");
40+
expect(renamed.toString1().toString(), "123");
41+
});
42+
43+
test('Method with the same name as a type', () {
44+
final renamed = Renamed.new1();
45+
46+
expect(renamed.CollidingStructName1(), 456);
47+
});
3348
});
3449
}

0 commit comments

Comments
 (0)