From 3ef8568e7543c7f52c1d6aced0b9df2e5052adf7 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 10 Sep 2025 11:36:29 +1000 Subject: [PATCH 1/3] [ffigen] Replace `Writer` with `Context` in all `Type` to string methods --- .../lib/src/code_generator/compound.dart | 12 +-- .../lib/src/code_generator/enum_class.dart | 18 ++-- pkgs/ffigen/lib/src/code_generator/func.dart | 21 +++-- .../lib/src/code_generator/func_type.dart | 33 +++---- .../ffigen/lib/src/code_generator/global.dart | 17 ++-- .../ffigen/lib/src/code_generator/handle.dart | 8 +- .../lib/src/code_generator/imports.dart | 17 ++-- .../lib/src/code_generator/native_type.dart | 10 +- .../lib/src/code_generator/objc_block.dart | 94 ++++++++++--------- .../objc_built_in_functions.dart | 22 +++-- .../lib/src/code_generator/objc_category.dart | 2 +- .../src/code_generator/objc_interface.dart | 40 ++++---- .../lib/src/code_generator/objc_methods.dart | 48 +++++----- .../lib/src/code_generator/objc_nullable.dart | 23 +++-- .../lib/src/code_generator/objc_protocol.dart | 57 ++++++----- .../lib/src/code_generator/pointer.dart | 34 +++---- pkgs/ffigen/lib/src/code_generator/type.dart | 29 +++--- .../lib/src/code_generator/typealias.dart | 43 +++++---- 18 files changed, 281 insertions(+), 247 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/compound.dart b/pkgs/ffigen/lib/src/code_generator/compound.dart index 357b4bb2d5..c2ad7ff884 100644 --- a/pkgs/ffigen/lib/src/code_generator/compound.dart +++ b/pkgs/ffigen/lib/src/code_generator/compound.dart @@ -105,7 +105,7 @@ abstract class Compound extends BindingType { return '${context.libs.prefix(ffiImport)}.Array<' '${_getInlineArrayTypeString(type.child, w)}>'; } - return type.getCType(w); + return type.getCType(context); } @override @@ -129,7 +129,7 @@ abstract class Compound extends BindingType { /// Marking type names because dart doesn't allow class member to have the /// same name as a type name used internally. for (final m in members) { - localUniqueNamer.markUsed(m.type.getFfiDartType(w)); + localUniqueNamer.markUsed(m.type.getFfiDartType(context)); } /// Write @Packed(X) annotation if struct is packed. @@ -155,19 +155,19 @@ abstract class Compound extends BindingType { s.write('${m.name};\n\n'); } else { if (!m.type.sameFfiDartAndCType) { - s.write('$depth@${m.type.getCType(w)}()\n'); + s.write('$depth@${m.type.getCType(context)}()\n'); } final memberName = m.type.sameDartAndFfiDartType ? m.name : '${m.name}AsInt'; s.write( - '${depth}external ${m.type.getFfiDartType(w)} $memberName;\n\n', + '${depth}external ${m.type.getFfiDartType(context)} $memberName;\n\n', ); } if (m.type case EnumClass( :final style, ) when style == EnumStyle.dartEnum) { - final enumName = m.type.getDartType(w); + final enumName = m.type.getDartType(context); final memberName = m.name; s.write( '$enumName get $memberName => ' @@ -184,7 +184,7 @@ abstract class Compound extends BindingType { bool get isIncompleteCompound => isIncomplete; @override - String getCType(Writer w) { + String getCType(Context context) { final builtInName = context.objCBuiltInFunctions.getBuiltInCompoundName( originalName, ); diff --git a/pkgs/ffigen/lib/src/code_generator/enum_class.dart b/pkgs/ffigen/lib/src/code_generator/enum_class.dart index 49ec1a6ca3..05777ff629 100644 --- a/pkgs/ffigen/lib/src/code_generator/enum_class.dart +++ b/pkgs/ffigen/lib/src/code_generator/enum_class.dart @@ -265,17 +265,17 @@ class EnumClass extends BindingType { } @override - String getCType(Writer w) => nativeType.getCType(w); + String getCType(Context context) => nativeType.getCType(context); @override - String getFfiDartType(Writer w) => nativeType.getFfiDartType(w); + String getFfiDartType(Context context) => nativeType.getFfiDartType(context); @override - String getDartType(Writer w) { + String getDartType(Context context) { if (isObjCImport) { return '${context.libs.prefix(objcPkgImport)}.$name'; } else if (style == EnumStyle.intConstants) { - return nativeType.getDartType(w); + return nativeType.getDartType(context); } else { return name; } @@ -291,11 +291,11 @@ class EnumClass extends BindingType { bool get sameDartAndFfiDartType => style == EnumStyle.intConstants; @override - String? getDefaultValue(Writer w) => '0'; + String? getDefaultValue(Context context) => '0'; @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -303,11 +303,13 @@ class EnumClass extends BindingType { @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, - }) => sameDartAndFfiDartType ? value : '${getDartType(w)}.fromValue($value)'; + }) => sameDartAndFfiDartType + ? value + : '${getDartType(context)}.fromValue($value)'; @override void visitChildren(Visitor visitor) { diff --git a/pkgs/ffigen/lib/src/code_generator/func.dart b/pkgs/ffigen/lib/src/code_generator/func.dart index d6fe2b2ad3..a654d3afd0 100644 --- a/pkgs/ffigen/lib/src/code_generator/func.dart +++ b/pkgs/ffigen/lib/src/code_generator/func.dart @@ -109,33 +109,34 @@ class Func extends LookUpBinding { p.name = paramNamer.makeUnique(p.name); } + final context = w.context; final cType = - _exposedFunctionTypealias?.getCType(w) ?? - functionType.getCType(w, writeArgumentNames: false); + _exposedFunctionTypealias?.getCType(context) ?? + functionType.getCType(context, writeArgumentNames: false); final dartType = - _exposedFunctionTypealias?.getFfiDartType(w) ?? - functionType.getFfiDartType(w, writeArgumentNames: false); + _exposedFunctionTypealias?.getFfiDartType(context) ?? + functionType.getFfiDartType(context, writeArgumentNames: false); final needsWrapper = !functionType.sameDartAndFfiDartType && !isInternal; final funcVarName = w.wrapperLevelUniqueNamer.makeUnique('_$name'); - final ffiReturnType = functionType.returnType.getFfiDartType(w); + final ffiReturnType = functionType.returnType.getFfiDartType(context); final ffiArgDeclString = functionType.dartTypeParameters - .map((p) => '${p.type.getFfiDartType(w)} ${p.name},\n') + .map((p) => '${p.type.getFfiDartType(context)} ${p.name},\n') .join(''); late final String dartReturnType; late final String dartArgDeclString; late final String funcImplCall; if (needsWrapper) { - dartReturnType = functionType.returnType.getDartType(w); + dartReturnType = functionType.returnType.getDartType(context); dartArgDeclString = functionType.dartTypeParameters - .map((p) => '${p.type.getDartType(w)} ${p.name},\n') + .map((p) => '${p.type.getDartType(context)} ${p.name},\n') .join(''); final argString = functionType.dartTypeParameters .map((p) { final type = p.type.convertDartTypeToFfiDartType( - w, + context, p.name, objCRetain: p.objCConsumed, objCAutorelease: false, @@ -144,7 +145,7 @@ class Func extends LookUpBinding { }) .join(''); funcImplCall = functionType.returnType.convertFfiDartTypeToDartType( - w, + context, '$funcVarName($argString)', objCRetain: !objCReturnsRetained, ); diff --git a/pkgs/ffigen/lib/src/code_generator/func_type.dart b/pkgs/ffigen/lib/src/code_generator/func_type.dart index 10110b5093..0c3b341ec1 100644 --- a/pkgs/ffigen/lib/src/code_generator/func_type.dart +++ b/pkgs/ffigen/lib/src/code_generator/func_type.dart @@ -3,10 +3,10 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; +import '../context.dart'; import '../visitor/ast.dart'; import 'unique_namer.dart'; -import 'writer.dart'; /// Represents a function type. class FunctionType extends Type { @@ -66,19 +66,20 @@ class FunctionType extends Type { } @override - String getCType(Writer w, {bool writeArgumentNames = true}) => _getTypeImpl( - writeArgumentNames, - (Type t) => t.getCType(w), - varArgWrapper: '${w.context.libs.prefix(ffiImport)}.VarArgs', - ); + String getCType(Context context, {bool writeArgumentNames = true}) => + _getTypeImpl( + writeArgumentNames, + (Type t) => t.getCType(context), + varArgWrapper: '${context.libs.prefix(ffiImport)}.VarArgs', + ); @override - String getFfiDartType(Writer w, {bool writeArgumentNames = true}) => - _getTypeImpl(writeArgumentNames, (Type t) => t.getFfiDartType(w)); + String getFfiDartType(Context context, {bool writeArgumentNames = true}) => + _getTypeImpl(writeArgumentNames, (Type t) => t.getFfiDartType(context)); @override - String getDartType(Writer w, {bool writeArgumentNames = true}) => - _getTypeImpl(writeArgumentNames, (Type t) => t.getDartType(w)); + String getDartType(Context context, {bool writeArgumentNames = true}) => + _getTypeImpl(writeArgumentNames, (Type t) => t.getDartType(context)); @override String getNativeType({String varName = ''}) { @@ -164,16 +165,16 @@ class NativeFunc extends Type { } @override - String getCType(Writer w, {bool writeArgumentNames = true}) { + String getCType(Context context, {bool writeArgumentNames = true}) { final funcType = _type is FunctionType - ? _type.getCType(w, writeArgumentNames: writeArgumentNames) - : _type.getCType(w); - return '${w.context.libs.prefix(ffiImport)}.NativeFunction<$funcType>'; + ? _type.getCType(context, writeArgumentNames: writeArgumentNames) + : _type.getCType(context); + return '${context.libs.prefix(ffiImport)}.NativeFunction<$funcType>'; } @override - String getFfiDartType(Writer w, {bool writeArgumentNames = true}) => - getCType(w, writeArgumentNames: writeArgumentNames); + String getFfiDartType(Context context, {bool writeArgumentNames = true}) => + getCType(context, writeArgumentNames: writeArgumentNames); @override String getNativeType({String varName = ''}) => diff --git a/pkgs/ffigen/lib/src/code_generator/global.dart b/pkgs/ffigen/lib/src/code_generator/global.dart index 175650d9e2..f570e1c7e8 100644 --- a/pkgs/ffigen/lib/src/code_generator/global.dart +++ b/pkgs/ffigen/lib/src/code_generator/global.dart @@ -46,32 +46,33 @@ class Global extends LookUpBinding { final s = StringBuffer(); final globalVarName = name; s.write(makeDartDoc(dartDoc)); - final dartType = type.getDartType(w); - final ffiDartType = type.getFfiDartType(w); + final context = w.context; + final dartType = type.getDartType(context); + final ffiDartType = type.getFfiDartType(context); // Removing pointer reference for ConstantArray cType since we always wrap // globals with pointer below. final cType = (type is ConstantArray && !nativeConfig.enabled) - ? (type as ConstantArray).child.getCType(w) - : type.getCType(w); + ? (type as ConstantArray).child.getCType(context) + : type.getCType(context); - final ptrType = '${w.context.libs.prefix(ffiImport)}.Pointer<$cType>'; + final ptrType = '${context.libs.prefix(ffiImport)}.Pointer<$cType>'; void generateConvertingGetterAndSetter(String pointerValue) { final getValue = type.convertFfiDartTypeToDartType( - w, + context, pointerValue, objCRetain: true, ); s.write('$dartType get $globalVarName => $getValue;\n\n'); if (!constant) { final releaseOldValue = type.convertFfiDartTypeToDartType( - w, + context, pointerValue, objCRetain: false, ); final newValue = type.convertDartTypeToFfiDartType( - w, + context, 'value', objCRetain: true, objCAutorelease: false, diff --git a/pkgs/ffigen/lib/src/code_generator/handle.dart b/pkgs/ffigen/lib/src/code_generator/handle.dart index 03501a6c89..2a564d79eb 100644 --- a/pkgs/ffigen/lib/src/code_generator/handle.dart +++ b/pkgs/ffigen/lib/src/code_generator/handle.dart @@ -3,10 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; +import '../context.dart'; import '../visitor/ast.dart'; -import 'writer.dart'; - /// Represents a Dart_Handle. class HandleType extends Type { const HandleType._(); @@ -14,10 +13,11 @@ class HandleType extends Type { factory HandleType() => _handle; @override - String getCType(Writer w) => '${w.context.libs.prefix(ffiImport)}.Handle'; + String getCType(Context context) => + '${context.libs.prefix(ffiImport)}.Handle'; @override - String getFfiDartType(Writer w) => 'Object'; + String getFfiDartType(Context context) => 'Object'; // The real native type is Dart_Handle, but that would mean importing // dart_api.h into the generated native code. diff --git a/pkgs/ffigen/lib/src/code_generator/imports.dart b/pkgs/ffigen/lib/src/code_generator/imports.dart index c5a0477470..99821950be 100644 --- a/pkgs/ffigen/lib/src/code_generator/imports.dart +++ b/pkgs/ffigen/lib/src/code_generator/imports.dart @@ -2,10 +2,10 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import '../context.dart'; import '../visitor/ast.dart'; import 'type.dart'; -import 'writer.dart'; /// A library import which will be written as an import in the generated file. class LibraryImport extends AstNode { @@ -63,14 +63,15 @@ class ImportedType extends Type { }); @override - String getCType(Writer w) => '${w.context.libs.prefix(libraryImport)}.$cType'; + String getCType(Context context) => + '${context.libs.prefix(libraryImport)}.$cType'; @override - String getFfiDartType(Writer w) { + String getFfiDartType(Context context) { if (importedDartType) { - return '${w.context.libs.prefix(libraryImport)}.$dartType'; + return '${context.libs.prefix(libraryImport)}.$dartType'; } else { - return cType == dartType ? getCType(w) : dartType; + return cType == dartType ? getCType(context) : dartType; } } @@ -84,7 +85,7 @@ class ImportedType extends Type { String toString() => '${libraryImport.name}.$cType'; @override - String? getDefaultValue(Writer w) => defaultValue; + String? getDefaultValue(Context context) => defaultValue; @override void visit(Visitation visitation) => visitation.visitImportedType(this); @@ -106,10 +107,10 @@ class SelfImportedType extends Type { SelfImportedType(this.cType, this.dartType, [this.defaultValue]); @override - String getCType(Writer w) => cType; + String getCType(Context context) => cType; @override - String getFfiDartType(Writer w) => dartType; + String getFfiDartType(Context context) => dartType; @override bool get sameFfiDartAndCType => cType == dartType; diff --git a/pkgs/ffigen/lib/src/code_generator/native_type.dart b/pkgs/ffigen/lib/src/code_generator/native_type.dart index e3de96fdde..06a4f82ae3 100644 --- a/pkgs/ffigen/lib/src/code_generator/native_type.dart +++ b/pkgs/ffigen/lib/src/code_generator/native_type.dart @@ -3,10 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; +import '../context.dart'; import '../visitor/ast.dart'; -import 'writer.dart'; - enum SupportedNativeType { voidType, char, @@ -68,10 +67,11 @@ class NativeType extends Type { factory NativeType(SupportedNativeType type) => _primitives[type]!; @override - String getCType(Writer w) => '${w.context.libs.prefix(ffiImport)}.$_cType'; + String getCType(Context context) => + '${context.libs.prefix(ffiImport)}.$_cType'; @override - String getFfiDartType(Writer w) => _dartType; + String getFfiDartType(Context context) => _dartType; @override String getNativeType({String varName = ''}) => '$_nativeType $varName'; @@ -86,7 +86,7 @@ class NativeType extends Type { String cacheKey() => _cType; @override - String? getDefaultValue(Writer w) => _defaultValue; + String? getDefaultValue(Context context) => _defaultValue; @override void visitChildren(Visitor visitor) { diff --git a/pkgs/ffigen/lib/src/code_generator/objc_block.dart b/pkgs/ffigen/lib/src/code_generator/objc_block.dart index 5a7a1d1148..32a72b2f22 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_block.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_block.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; - import '../context.dart'; import '../visitor/ast.dart'; @@ -101,32 +100,33 @@ class ObjCBlock extends BindingType { bool get hasListener => returnType == voidType; - String _blockType(Writer w) { + String _blockType(Context context) { final argStr = params .map((param) { - final type = param.type.getObjCBlockSignatureType(w); + final type = param.type.getObjCBlockSignatureType(context); return param.objCConsumed - ? '${ObjCBuiltInFunctions.consumedType.gen(w)}<$type>' + ? '${ObjCBuiltInFunctions.consumedType.gen(context)}<$type>' : type; }) .join(', '); - final retType = returnType.getObjCBlockSignatureType(w); + final retType = returnType.getObjCBlockSignatureType(context); final retStr = returnsRetained - ? '${ObjCBuiltInFunctions.retainedType.gen(w)}<$retType>' + ? '${ObjCBuiltInFunctions.retainedType.gen(context)}<$retType>' : retType; final func = '$retStr Function($argStr)'; - return '${ObjCBuiltInFunctions.blockType.gen(w)}<$func>'; + return '${ObjCBuiltInFunctions.blockType.gen(context)}<$func>'; } @override BindingString toBindingString(Writer w) { final s = StringBuffer(); + final context = w.context; final voidPtr = PointerType(voidType); final blockPtr = PointerType(objCBlockType); - final func = _FnHelper(w, returnType, params); + final func = _FnHelper(context, returnType, params); - final blockingFunc = _FnHelper(w, returnType, [ + final blockingFunc = _FnHelper(context, returnType, [ Parameter(type: voidPtr, name: 'waiter', objCConsumed: false), ...params, ]); @@ -162,17 +162,17 @@ class ObjCBlock extends BindingType { '${name}_CallExtension', ); - final newPointerBlock = ObjCBuiltInFunctions.newPointerBlock.gen(w); - final newClosureBlock = ObjCBuiltInFunctions.newClosureBlock.gen(w); - final getBlockClosure = ObjCBuiltInFunctions.getBlockClosure.gen(w); - final releaseFn = ObjCBuiltInFunctions.objectRelease.gen(w); - final objCContext = ObjCBuiltInFunctions.objCContext.gen(w); - final signalWaiterFn = ObjCBuiltInFunctions.signalWaiter.gen(w); - final returnFfiDartType = returnType.getFfiDartType(w); - final voidPtrCType = voidPtr.getCType(w); - final blockCType = blockPtr.getCType(w); - final blockType = _blockType(w); - final defaultValue = returnType.getDefaultValue(w); + final newPointerBlock = ObjCBuiltInFunctions.newPointerBlock.gen(context); + final newClosureBlock = ObjCBuiltInFunctions.newClosureBlock.gen(context); + final getBlockClosure = ObjCBuiltInFunctions.getBlockClosure.gen(context); + final releaseFn = ObjCBuiltInFunctions.objectRelease.gen(context); + final objCContext = ObjCBuiltInFunctions.objCContext.gen(context); + final signalWaiterFn = ObjCBuiltInFunctions.signalWaiter.gen(context); + final returnFfiDartType = returnType.getFfiDartType(context); + final voidPtrCType = voidPtr.getCType(context); + final blockCType = blockPtr.getCType(context); + final blockType = _blockType(context); + final defaultValue = returnType.getDefaultValue(context); final exceptionalReturn = defaultValue == null ? '' : ', $defaultValue'; final ffiPrefix = w.context.libs.prefix(ffiImport); @@ -229,14 +229,14 @@ ${blockingFunc.trampNatCallType} $blockingListenerCallable = final convertedFnArgs = params .map( (p) => p.type.convertFfiDartTypeToDartType( - w, + context, p.name, objCRetain: !p.objCConsumed, ), ) .join(', '); final convFnInvocation = returnType.convertDartTypeToFfiDartType( - w, + context, 'fn($convertedFnArgs)', objCRetain: true, objCAutorelease: !returnsRetained, @@ -284,14 +284,14 @@ abstract final class $name { final listenerConvertedFnArgs = params .map( (p) => p.type.convertFfiDartTypeToDartType( - w, + context, p.name, objCRetain: false, ), ) .join(', '); final listenerConvFnInvocation = returnType.convertDartTypeToFfiDartType( - w, + context, 'fn($listenerConvertedFnArgs)', objCRetain: true, objCAutorelease: !returnsRetained, @@ -318,7 +318,7 @@ abstract final class $name { $listenerConvFn, keepIsolateAlive); final wrapper = $wrapListenerFn(raw); $releaseFn(raw.cast()); - return $blockType(wrapper, retain: false, release: true); + return $blockType(contextrapper, retain: false, release: true); } /// Creates a blocking block from a Dart function. @@ -341,7 +341,7 @@ abstract final class $name { final wrapper = $wrapBlockingFn(raw, rawListener, $objCContext); $releaseFn(raw.cast()); $releaseFn(rawListener.cast()); - return $blockType(wrapper, retain: false, release: true); + return $blockType(contextrapper, retain: false, release: true); } '''); } @@ -351,11 +351,11 @@ abstract final class $name { s.write(''' /// Call operator for `$blockType`. extension $callExtension on $blockType { - ${returnType.getDartType(w)} call(${func.paramsDartType}) =>'''); + ${returnType.getDartType(context)} call(${func.paramsDartType}) =>'''); final callMethodArgs = params .map( (p) => p.type.convertDartTypeToFfiDartType( - w, + context, p.name, objCRetain: p.objCConsumed, objCAutorelease: false, @@ -369,7 +369,7 @@ ref.pointer.ref.invoke.cast<${func.trampNatFnCType}>() ref.pointer, $callMethodArgs)'''; s.write( returnType.convertFfiDartTypeToDartType( - w, + context, callMethodInvocation, objCRetain: !returnsRetained, ), @@ -493,16 +493,17 @@ $ret $fnName(id target, $argRecv) { } @override - String getCType(Writer w) => PointerType(objCBlockType).getCType(w); + String getCType(Context context) => + PointerType(objCBlockType).getCType(context); // We return `ObjCBlockBase` here instead of the code genned wrapper, so // that the subtyping rules work as expected. // See https://github.com/dart-lang/native/issues/1416 for details. @override - String getDartType(Writer w) => _blockType(w); + String getDartType(Context context) => _blockType(context); @override - String getObjCBlockSignatureType(Writer w) => getDartType(w); + String getObjCBlockSignatureType(Context context) => getDartType(context); @override String getNativeType({String varName = ''}) => 'id $varName'; @@ -518,7 +519,7 @@ $ret $fnName(id target, $argRecv) { @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -526,7 +527,7 @@ $ret $fnName(id target, $argRecv) { @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, @@ -579,13 +580,13 @@ class _FnHelper { late final String paramsFfiDartType; late final String paramsDartType; - _FnHelper(Writer w, Type returnType, List params) { + _FnHelper(Context context, Type returnType, List params) { final fnType = FunctionType(returnType: returnType, parameters: params); natFnType = NativeFunc(fnType); - natFnFfiDartType = natFnType.getFfiDartType(w); - natFnPtrCType = PointerType(natFnType).getCType(w); - dartType = fnType.getDartType(w, writeArgumentNames: false); - ffiDartType = fnType.getFfiDartType(w, writeArgumentNames: false); + natFnFfiDartType = natFnType.getFfiDartType(context); + natFnPtrCType = PointerType(natFnType).getCType(context); + dartType = fnType.getDartType(context, writeArgumentNames: false); + ffiDartType = fnType.getFfiDartType(context, writeArgumentNames: false); final trampFnType = FunctionType( returnType: returnType, @@ -598,18 +599,21 @@ class _FnHelper { ...params, ], ); - trampCType = trampFnType.getCType(w, writeArgumentNames: false); - trampFfiDartType = trampFnType.getFfiDartType(w, writeArgumentNames: false); + trampCType = trampFnType.getCType(context, writeArgumentNames: false); + trampFfiDartType = trampFnType.getFfiDartType( + context, + writeArgumentNames: false, + ); trampNatCallType = - '${w.context.libs.prefix(ffiImport)}.NativeCallable<$trampCType>'; - trampNatFnCType = NativeFunc(trampFnType).getCType(w); + '${context.libs.prefix(ffiImport)}.NativeCallable<$trampCType>'; + trampNatFnCType = NativeFunc(trampFnType).getCType(context); paramsNameOnly = params.map((p) => p.name).join(', '); paramsFfiDartType = params - .map((p) => '${p.type.getFfiDartType(w)} ${p.name}') + .map((p) => '${p.type.getFfiDartType(context)} ${p.name}') .join(', '); paramsDartType = params - .map((p) => '${p.type.getDartType(w)} ${p.name}') + .map((p) => '${p.type.getDartType(context)} ${p.name}') .join(', '); } } 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 c9824bed6f..0b421600f3 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 @@ -4,6 +4,7 @@ import '../code_generator.dart'; import '../config_provider/config_types.dart'; +import '../context.dart'; import '../visitor/ast.dart'; import 'binding_string.dart'; @@ -85,7 +86,7 @@ class ObjCBuiltInFunctions { ObjCInternalGlobal getSelObject(String methodName) { return _selObjects[methodName] ??= ObjCInternalGlobal( '_sel_${methodName.replaceAll(":", "_")}', - (Writer w) => '${registerName.gen(w)}("$methodName")', + (Context context) => '${registerName.gen(context)}("$methodName")', ); } @@ -255,12 +256,12 @@ class ObjCImport { const ObjCImport(this.name); - String gen(Writer w) => '${w.context.libs.prefix(objcPkgImport)}.$name'; + String gen(Context context) => '${context.libs.prefix(objcPkgImport)}.$name'; } /// Globals only used internally by ObjC bindings, such as classes and SELs. class ObjCInternalGlobal extends NoLookUpBinding { - final String Function(Writer) makeValue; + final String Function(Context) makeValue; ObjCInternalGlobal(String name, this.makeValue) : super(originalName: name, name: name, isInternal: true); @@ -269,7 +270,7 @@ class ObjCInternalGlobal extends NoLookUpBinding { BindingString toBindingString(Writer w) { final s = StringBuffer(); name = w.wrapperLevelUniqueNamer.makeUnique(name); - s.write('late final $name = ${makeValue(w)};\n'); + s.write('late final $name = ${makeValue(w.context)};\n'); return BindingString(type: BindingStringType.global, string: s.toString()); } } @@ -306,9 +307,10 @@ class ObjCMsgSendVariantFunc extends NoLookUpBinding { @override BindingString toBindingString(Writer w) { - final cType = NativeFunc(type).getCType(w, writeArgumentNames: false); - final dartType = type.getFfiDartType(w, writeArgumentNames: false); - final pointer = variant.pointer.gen(w); + final context = w.context; + final cType = NativeFunc(type).getCType(context, writeArgumentNames: false); + final dartType = type.getFfiDartType(context, writeArgumentNames: false); + final pointer = variant.pointer.gen(context); final bindingString = ''' @@ -394,7 +396,7 @@ class ObjCMsgSendFunc extends AstNode { bool get isStret => variant == ObjCMsgSendVariant.stret; String invoke( - Writer w, + Context context, String target, String sel, Iterable params, { @@ -406,7 +408,7 @@ class ObjCMsgSendFunc extends AstNode { return normalCall; case ObjCMsgSendVariant.fpret: final fpretCall = _invoke(variantFunc!.name, target, sel, params); - return '${useVariants.gen(w)} ? $fpretCall : $normalCall'; + return '${useVariants.gen(context)} ? $fpretCall : $normalCall'; case ObjCMsgSendVariant.stret: final stretCall = _invoke( variantFunc!.name, @@ -415,7 +417,7 @@ class ObjCMsgSendFunc extends AstNode { params, structRetPtr: structRetPtr, ); - return '${useVariants.gen(w)} ? $stretCall : ' + return '${useVariants.gen(context)} ? $stretCall : ' '$structRetPtr.ref = $normalCall'; } } diff --git a/pkgs/ffigen/lib/src/code_generator/objc_category.dart b/pkgs/ffigen/lib/src/code_generator/objc_category.dart index dab06a11a0..3dfed3d7e3 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_category.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_category.dart @@ -50,7 +50,7 @@ class ObjCCategory extends NoLookUpBinding with ObjCMethods { s.write('\n'); s.write(makeDartDoc(dartDoc)); s.write(''' -extension $name on ${parent.getDartType(w)} { +extension $name on ${parent.getDartType(context)} { ${generateMethodBindings(w, parent)} } diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart index 1f8a82d237..43513a2c54 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart @@ -48,7 +48,8 @@ class ObjCInterface extends BindingType with ObjCMethods { ) { classObject = ObjCInternalGlobal( '_class_$originalName', - (Writer w) => '${ObjCBuiltInFunctions.getClass.gen(w)}("$lookupName")', + (Context context) => + '${ObjCBuiltInFunctions.getClass.gen(context)}("$lookupName")', ); _isKindOfClass = context.objCBuiltInFunctions.getSelObject( 'isKindOfClass:', @@ -81,6 +82,7 @@ class ObjCInterface extends BindingType with ObjCMethods { @override BindingString toBindingString(Writer w) { + final context = w.context; final s = StringBuffer(); s.write('\n'); if (generateAsStub) { @@ -93,20 +95,20 @@ class ObjCInterface extends BindingType with ObjCMethods { s.write(makeDartDoc(dartDoc)); final versionCheck = apiAvailability.runtimeCheck( - ObjCBuiltInFunctions.checkOsVersion.gen(w), + ObjCBuiltInFunctions.checkOsVersion.gen(context), originalName, ); final ctorBody = versionCheck == null ? ';' : ' { $versionCheck }'; - final rawObjType = PointerType(objCObjectType).getCType(w); - final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(w); - final protoImpl = protocols.isEmpty - ? '' - : 'implements ${protocols.map((p) => p.getDartType(w)).join(', ')} '; + final rawObjType = PointerType(objCObjectType).getCType(context); + final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(context); + final protos = protocols.map((p) => p.getDartType(context)).join(', '); + final protoImpl = protocols.isEmpty ? '' : 'implements $protos '; + final superTypeDartType = superType?.getDartType(context) ?? wrapObjType; final superCtor = superType == null ? 'super' : 'super.castFromPointer'; s.write(''' -class $name extends ${superType?.getDartType(w) ?? wrapObjType} $protoImpl{ +class $name extends $superTypeDartType $protoImpl{ $name._($rawObjType pointer, {bool retain = false, bool release = false}) : $superCtor(pointer, retain: retain, release: release)$ctorBody @@ -141,13 +143,14 @@ ${generateInstanceMethodBindings(w, this)} } String _generateStaticMethods(Writer w) { - final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(w); + final context = w.context; + final wrapObjType = ObjCBuiltInFunctions.objectBase.gen(context); final s = StringBuffer(); s.write(''' /// Returns whether [obj] is an instance of [$name]. static bool isInstance($wrapObjType obj) { - return ${_isKindOfClassMsgSend.invoke(w, 'obj.ref.pointer', _isKindOfClass.name, [classObject.name])}; + return ${_isKindOfClassMsgSend.invoke(context, 'obj.ref.pointer', _isKindOfClass.name, [classObject.name])}; } '''); @@ -173,17 +176,18 @@ ${generateInstanceMethodBindings(w, this)} } @override - String getCType(Writer w) => PointerType(objCObjectType).getCType(w); + String getCType(Context context) => + PointerType(objCObjectType).getCType(context); @override - String getDartType(Writer w) => + String getDartType(Context context) => isObjCImport ? '${context.libs.prefix(objcPkgImport)}.$name' : name; @override String getNativeType({String varName = ''}) => 'id $varName'; @override - String getObjCBlockSignatureType(Writer w) => getDartType(w); + String getObjCBlockSignatureType(Context context) => getDartType(context); @override bool get sameFfiDartAndCType => true; @@ -196,7 +200,7 @@ ${generateInstanceMethodBindings(w, this)} @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -214,11 +218,15 @@ ${generateInstanceMethodBindings(w, this)} @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, - }) => ObjCInterface.generateConstructor(getDartType(w), value, objCRetain); + }) => ObjCInterface.generateConstructor( + getDartType(context), + value, + objCRetain, + ); static String generateConstructor( String className, diff --git a/pkgs/ffigen/lib/src/code_generator/objc_methods.dart b/pkgs/ffigen/lib/src/code_generator/objc_methods.dart index febcf7a55d..231311b89d 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_methods.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_methods.dart @@ -368,26 +368,29 @@ class ObjCMethod extends AstNode { return false; } - String _getConvertedReturnType(Writer w, String instanceType) { + String _getConvertedReturnType(Context context, String instanceType) { if (returnType is ObjCInstanceType) return instanceType; final baseType = returnType.typealiasType; if (baseType is ObjCNullable && baseType.child is ObjCInstanceType) { return '$instanceType?'; } - return returnType.getDartType(w); + return returnType.getDartType(context); } - static String _paramToStr(Writer w, Parameter p) => - '${p.type.getDartType(w)} ${p.name}'; + static String _paramToStr(Context context, Parameter p) => + '${p.type.getDartType(context)} ${p.name}'; - static String _paramToNamed(Writer w, Parameter p) => - '${p.isNullable ? '' : 'required '}${_paramToStr(w, p)}'; + static String _paramToNamed(Context context, Parameter p) => + '${p.isNullable ? '' : 'required '}${_paramToStr(context, p)}'; - static String _joinParamStr(Writer w, List params) { + static String _joinParamStr(Context context, List params) { if (params.isEmpty) return ''; - if (params.length == 1) return _paramToStr(w, params.first); - final named = params.sublist(1).map((p) => _paramToNamed(w, p)).join(','); - return '${_paramToStr(w, params.first)}, {$named}'; + if (params.length == 1) return _paramToStr(context, params.first); + final named = params + .sublist(1) + .map((p) => _paramToNamed(context, p)) + .join(','); + return '${_paramToStr(context, params.first)}, {$named}'; } String generateBindings( @@ -395,6 +398,7 @@ class ObjCMethod extends AstNode { ObjCInterface target, UniqueNamer methodNamer, ) { + final context = w.context; if (dartMethodName == null) { dartMethodName = getDartMethodName(methodNamer); final paramNamer = UniqueNamer(parent: methodNamer); @@ -406,9 +410,9 @@ class ObjCMethod extends AstNode { final upperName = methodName[0].toUpperCase() + methodName.substring(1); final s = StringBuffer(); - final targetType = target.getDartType(w); - final returnTypeStr = _getConvertedReturnType(w, targetType); - final paramStr = _joinParamStr(w, params); + final targetType = target.getDartType(context); + final returnTypeStr = _getConvertedReturnType(context, targetType); + final paramStr = _joinParamStr(context, params); // The method declaration. s.write('\n ${makeDartDoc(dartDoc)} '); @@ -428,7 +432,7 @@ class ObjCMethod extends AstNode { } } else { targetStr = target.convertDartTypeToFfiDartType( - w, + context, 'this', objCRetain: consumesSelf, objCAutorelease: false, @@ -449,7 +453,7 @@ class ObjCMethod extends AstNode { // Implementation. final versionCheck = apiAvailability.runtimeCheck( - ObjCBuiltInFunctions.checkOsVersion.gen(w), + ObjCBuiltInFunctions.checkOsVersion.gen(context), '${target.originalName}.$originalName', ); if (versionCheck != null) { @@ -459,8 +463,8 @@ class ObjCMethod extends AstNode { final sel = selObject.name; if (isOptional) { s.write(''' - if (!${ObjCBuiltInFunctions.respondsToSelector.gen(w)}($targetStr, $sel)) { - throw ${ObjCBuiltInFunctions.unimplementedOptionalMethodException.gen(w)}( + if (!${ObjCBuiltInFunctions.respondsToSelector.gen(context)}($targetStr, $sel)) { + throw ${ObjCBuiltInFunctions.unimplementedOptionalMethodException.gen(context)}( '${target.originalName}', '$originalName'); } '''); @@ -471,7 +475,7 @@ class ObjCMethod extends AstNode { final msgSendParams = params.map( (p) => p.type.convertDartTypeToFfiDartType( - w, + context, p.name, objCRetain: p.objCConsumed, objCAutorelease: false, @@ -481,9 +485,9 @@ class ObjCMethod extends AstNode { assert(!convertReturn); final calloc = '${context.libs.prefix(ffiPkgImport)}.calloc'; final sizeOf = '${context.libs.prefix(ffiImport)}.sizeOf'; - final uint8Type = NativeType(SupportedNativeType.uint8).getCType(w); + final uint8Type = NativeType(SupportedNativeType.uint8).getCType(context); final invoke = msgSend!.invoke( - w, + context, targetStr, sel, msgSendParams, @@ -500,11 +504,11 @@ class ObjCMethod extends AstNode { if (returnType != voidType) { s.write(' ${convertReturn ? 'final _ret = ' : 'return '}'); } - s.write(msgSend!.invoke(w, targetStr, sel, msgSendParams)); + s.write(msgSend!.invoke(context, targetStr, sel, msgSendParams)); s.write(';\n'); if (convertReturn) { final result = returnType.convertFfiDartTypeToDartType( - w, + context, '_ret', objCRetain: !returnsRetained, objCEnclosingClass: targetType, diff --git a/pkgs/ffigen/lib/src/code_generator/objc_nullable.dart b/pkgs/ffigen/lib/src/code_generator/objc_nullable.dart index 12d1ad2fab..cad63918bb 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_nullable.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_nullable.dart @@ -3,10 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; +import '../context.dart'; import '../visitor/ast.dart'; -import 'writer.dart'; - /// An ObjC type annotated with nullable. Eg: /// +(nullable NSObject*) methodWithNullableResult; class ObjCNullable extends Type { @@ -29,21 +28,21 @@ class ObjCNullable extends Type { Type get baseType => child.baseType; @override - String getCType(Writer w) => child.getCType(w); + String getCType(Context context) => child.getCType(context); @override - String getFfiDartType(Writer w) => child.getFfiDartType(w); + String getFfiDartType(Context context) => child.getFfiDartType(context); @override - String getDartType(Writer w) => '${child.getDartType(w)}?'; + String getDartType(Context context) => '${child.getDartType(context)}?'; @override String getNativeType({String varName = ''}) => child.getNativeType(varName: varName); @override - String getObjCBlockSignatureType(Writer w) => - '${child.getObjCBlockSignatureType(w)}?'; + String getObjCBlockSignatureType(Context context) => + '${child.getObjCBlockSignatureType(context)}?'; @override bool get sameFfiDartAndCType => child.sameFfiDartAndCType; @@ -56,7 +55,7 @@ class ObjCNullable extends Type { @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -66,24 +65,24 @@ class ObjCNullable extends Type { // child types, we may have to start special casing each type. For example, // `value.pointer` becomes `value?.pointer ?? nullptr`. final convertedValue = child.convertDartTypeToFfiDartType( - w, + context, '$value?', objCRetain: objCRetain, objCAutorelease: objCAutorelease, ); - return '$convertedValue ?? ${w.context.libs.prefix(ffiImport)}.nullptr'; + return '$convertedValue ?? ${context.libs.prefix(ffiImport)}.nullptr'; } @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, }) { // All currently supported child types have a Pointer as their FfiDartType. final convertedValue = child.convertFfiDartTypeToDartType( - w, + context, value, objCRetain: objCRetain, objCEnclosingClass: objCEnclosingClass, diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index 1f31026cbf..8cdb106cdb 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -35,8 +35,8 @@ class ObjCProtocol extends BindingType with ObjCMethods { }) : lookupName = lookupName ?? originalName, _protocolPointer = ObjCInternalGlobal( '_protocol_$originalName', - (Writer w) => - '${ObjCBuiltInFunctions.getProtocol.gen(w)}("$lookupName")', + (Context context) => + '${ObjCBuiltInFunctions.getProtocol.gen(context)}("$lookupName")', ), super( name: @@ -70,16 +70,18 @@ class ObjCProtocol extends BindingType with ObjCMethods { @override BindingString toBindingString(Writer w) { - final protocolClass = ObjCBuiltInFunctions.protocolClass.gen(w); - final protocolBase = ObjCBuiltInFunctions.protocolBase.gen(w); - final protocolMethod = ObjCBuiltInFunctions.protocolMethod.gen(w); + final protocolClass = ObjCBuiltInFunctions.protocolClass.gen(context); + final protocolBase = ObjCBuiltInFunctions.protocolBase.gen(context); + final protocolMethod = ObjCBuiltInFunctions.protocolMethod.gen(context); final protocolListenableMethod = 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); + .gen(context); + final protocolBuilder = ObjCBuiltInFunctions.protocolBuilder.gen(context); + final objectBase = ObjCBuiltInFunctions.objectBase.gen(context); + final rawObjType = PointerType(objCObjectType).getCType(context); + final getSignature = ObjCBuiltInFunctions.getProtocolMethodSignature.gen( + context, + ); final s = StringBuffer(); s.write('\n'); @@ -92,7 +94,7 @@ class ObjCProtocol extends BindingType with ObjCMethods { } s.write(makeDartDoc(dartDoc ?? originalName)); - final sp = superProtocols.map((p) => p.getDartType(w)); + final sp = superProtocols.map((p) => p.getDartType(context)); final impls = superProtocols.isEmpty ? '' : 'implements ${sp.join(', ')}'; s.write(''' interface class $name extends $protocolBase $impls{ @@ -135,7 +137,7 @@ interface class $name extends $protocolBase $impls{ returnType: block.returnType, parameters: [...block.params.skip(1)], ); - final funcType = func.getDartType(w, writeArgumentNames: false); + final funcType = func.getDartType(context, writeArgumentNames: false); if (method.isOptional) { buildArgs.add('$funcType? $argName'); @@ -143,9 +145,9 @@ interface class $name extends $protocolBase $impls{ buildArgs.add('required $funcType $argName'); } - final blockFirstArg = block.params[0].type.getDartType(w); + final blockFirstArg = block.params[0].type.getDartType(context); final argsReceived = func.parameters - .map((p) => '${p.type.getDartType(w)} ${p.name}') + .map((p) => '${p.type.getDartType(context)} ${p.name}') .join(', '); final argsPassed = func.parameters.map((p) => p.name).join(', '); final wrapper = @@ -176,7 +178,7 @@ interface class $name extends $protocolBase $impls{ methodFields.write('''static final $fieldName = $methodClass<$funcType>( ${_protocolPointer.name}, ${method.selObject.name}, - ${_trampolineAddress(w, block)}, + ${_trampolineAddress(block)}, $getSignature( ${_protocolPointer.name}, ${method.selObject.name}, @@ -272,7 +274,7 @@ interface class $name extends $protocolBase $impls{ } final msgSendInvoke = _conformsToMsgSend.invoke( - w, + context, 'obj.ref.pointer', _conformsTo.name, [_protocolPointer.name], @@ -298,12 +300,12 @@ interface class $name extends $protocolBase $impls{ ); } - static String _trampolineAddress(Writer w, ObjCBlock block) { + String _trampolineAddress(ObjCBlock block) { final func = block.protocolTrampoline!.func; final type = NativeFunc( func.functionType, - ).getCType(w, writeArgumentNames: false); - final ffiPrefix = w.context.libs.prefix(ffiImport); + ).getCType(context, writeArgumentNames: false); + final ffiPrefix = context.libs.prefix(ffiImport); return '$ffiPrefix.Native.addressOf<$type>(${func.name}).cast()'; } @@ -323,17 +325,18 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } } @override - String getCType(Writer w) => PointerType(objCObjectType).getCType(w); + String getCType(Context context) => + PointerType(objCObjectType).getCType(context); @override - String getDartType(Writer w) => + String getDartType(Context context) => isObjCImport ? '${context.libs.prefix(objcPkgImport)}.$name' : name; @override String getNativeType({String varName = ''}) => 'id $varName'; @override - String getObjCBlockSignatureType(Writer w) => getDartType(w); + String getObjCBlockSignatureType(Context context) => getDartType(context); @override bool get sameFfiDartAndCType => true; @@ -346,7 +349,7 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -354,11 +357,15 @@ Protocol* _${wrapName}_$originalName(void) { return @protocol($originalName); } @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, - }) => ObjCInterface.generateConstructor(getDartType(w), value, objCRetain); + }) => ObjCInterface.generateConstructor( + getDartType(context), + 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 6cc3cf90f4..391d6362ee 100644 --- a/pkgs/ffigen/lib/src/code_generator/pointer.dart +++ b/pkgs/ffigen/lib/src/code_generator/pointer.dart @@ -3,10 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; +import '../context.dart'; import '../visitor/ast.dart'; -import 'writer.dart'; - /// Represents a pointer. class PointerType extends Type { final Type child; @@ -26,8 +25,8 @@ class PointerType extends Type { Type get baseType => child.baseType; @override - String getCType(Writer w) => - '${w.context.libs.prefix(ffiImport)}.Pointer<${child.getCType(w)}>'; + String getCType(Context context) => + '${context.libs.prefix(ffiImport)}.Pointer<${child.getCType(context)}>'; @override String getNativeType({String varName = ''}) => @@ -88,12 +87,13 @@ class ConstantArray extends PointerType { String cacheKey() => '${child.cacheKey()}[$length]'; @override - String getCType(Writer w) { + String getCType(Context context) { if (useArrayType) { - return '${w.context.libs.prefix(ffiImport)}.Array<${child.getCType(w)}>'; + final lib = context.libs.prefix(ffiImport); + return '$lib.Array<${child.getCType(context)}>'; } - return super.getCType(w); + return super.getCType(context); } } @@ -124,8 +124,8 @@ class ObjCObjectPointer extends PointerType { ObjCObjectPointer._() : super._(objCObjectType); @override - String getDartType(Writer w) => - '${w.context.libs.prefix(objcPkgImport)}.ObjCObjectBase'; + String getDartType(Context context) => + '${context.libs.prefix(objcPkgImport)}.ObjCObjectBase'; @override String getNativeType({String varName = ''}) => 'id $varName'; @@ -138,7 +138,7 @@ class ObjCObjectPointer extends PointerType { @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -146,11 +146,11 @@ class ObjCObjectPointer extends PointerType { @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, - }) => '${getDartType(w)}($value, retain: $objCRetain, release: true)'; + }) => '${getDartType(context)}($value, retain: $objCRetain, release: true)'; @override String? generateRetain(String value) => @@ -180,8 +180,8 @@ class ObjCBlockPointer extends ObjCObjectPointer { ObjCBlockPointer._() : super.__(objCBlockType); @override - String getDartType(Writer w) => - '${w.context.libs.prefix(objcPkgImport)}.ObjCBlockBase'; + String getDartType(Context context) => + '${context.libs.prefix(objcPkgImport)}.ObjCBlockBase'; @override String? generateRetain(String value) => 'objc_retainBlock($value)'; @@ -202,7 +202,7 @@ class ObjCObjectPointerWithProtocols extends ObjCObjectPointer { super._(); @override - String getDartType(Writer w) => protocols.first.getDartType(w); + String getDartType(Context context) => protocols.first.getDartType(context); @override bool isSupertypeOf(Type other) { @@ -226,12 +226,12 @@ class ObjCObjectPointerWithProtocols extends ObjCObjectPointer { @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, }) => protocols.first.convertFfiDartTypeToDartType( - w, + context, value, objCRetain: objCRetain, objCEnclosingClass: objCEnclosingClass, diff --git a/pkgs/ffigen/lib/src/code_generator/type.dart b/pkgs/ffigen/lib/src/code_generator/type.dart index 71c9297553..cd5ada02f9 100644 --- a/pkgs/ffigen/lib/src/code_generator/type.dart +++ b/pkgs/ffigen/lib/src/code_generator/type.dart @@ -3,10 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; +import '../context.dart'; import '../visitor/ast.dart'; -import 'writer.dart'; - /// Type class for return types, variable types, etc. /// /// Implementers should extend either Type, or BindingType if the type is also a @@ -47,23 +46,23 @@ abstract class Type extends AstNode { /// Returns the C type of the Type. This is the FFI compatible type that is /// passed to native code. - String getCType(Writer w) => + String getCType(Context context) => throw UnsupportedError('No mapping for type: $this'); /// Returns the Dart type of the Type. This is the type that is passed from /// FFI to Dart code. - String getFfiDartType(Writer w) => getCType(w); + String getFfiDartType(Context context) => getCType(context); /// Returns the user type of the Type. This is the type that is presented to /// users by the ffigened API to users. For C bindings this is always the same /// as getFfiDartType. For ObjC bindings this refers to the wrapper object. - String getDartType(Writer w) => getFfiDartType(w); + String getDartType(Context context) => getFfiDartType(context); /// Returns the type to be used if this type appears in an ObjC block /// signature. By default it's the same as [getCType]. But for some types /// that's not enough to distinguish them (eg all ObjC objects have a C type /// of `Pointer`), so we use [getDartType] instead. - String getObjCBlockSignatureType(Writer w) => getCType(w); + String getObjCBlockSignatureType(Context context) => getCType(context); /// Returns the C/ObjC type of the Type. This is the type as it appears in /// C/ObjC source code. It should not be used in Dart source code. @@ -89,7 +88,7 @@ abstract class Type extends AstNode { /// [value] is the value to be converted. If [objCRetain] is true, the ObjC /// object will be reained (ref count incremented) during conversion. String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -104,7 +103,7 @@ abstract class Type extends AstNode { /// then [objCEnclosingClass] should be the name of the Dart wrapper class /// (this is used by instancetype). String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, @@ -130,7 +129,7 @@ abstract class Type extends AstNode { /// Returns a string of code that creates a default value for this type. For /// example, for int types this returns the string '0'. A null return means /// that default values aren't supported for this type, eg void. - String? getDefaultValue(Writer w) => null; + String? getDefaultValue(Context context) => null; @override void visit(Visitation visitation) => visitation.visitType(this); @@ -193,13 +192,13 @@ abstract class BindingType extends NoLookUpBinding implements Type { bool isSupertypeOf(Type other) => typealiasType == other.typealiasType; @override - String getFfiDartType(Writer w) => getCType(w); + String getFfiDartType(Context context) => getCType(context); @override - String getDartType(Writer w) => getFfiDartType(w); + String getDartType(Context context) => getFfiDartType(context); @override - String getObjCBlockSignatureType(Writer w) => getCType(w); + String getObjCBlockSignatureType(Context context) => getCType(context); @override String getNativeType({String varName = ''}) => @@ -213,7 +212,7 @@ abstract class BindingType extends NoLookUpBinding implements Type { @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -221,7 +220,7 @@ abstract class BindingType extends NoLookUpBinding implements Type { @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, @@ -237,7 +236,7 @@ abstract class BindingType extends NoLookUpBinding implements Type { String cacheKey() => hashCode.toRadixString(36); @override - String? getDefaultValue(Writer w) => null; + String? getDefaultValue(Context context) => null; @override bool get isObjCImport => false; diff --git a/pkgs/ffigen/lib/src/code_generator/typealias.dart b/pkgs/ffigen/lib/src/code_generator/typealias.dart index 1c5e70c79b..6349a195d3 100644 --- a/pkgs/ffigen/lib/src/code_generator/typealias.dart +++ b/pkgs/ffigen/lib/src/code_generator/typealias.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; +import '../context.dart'; import '../strings.dart' as strings; import '../visitor/ast.dart'; @@ -101,14 +102,17 @@ class Typealias extends BindingType { dartAliasName = w.topLevelUniqueNamer.makeUnique(dartAliasName!); } + final context = w.context; final sb = StringBuffer(); sb.write(makeDartDoc(dartDoc)); - sb.write('typedef $name = ${type.getCType(w)};\n'); + sb.write('typedef $name = ${type.getCType(context)};\n'); if (_ffiDartAliasName != null) { - sb.write('typedef $_ffiDartAliasName = ${type.getFfiDartType(w)};\n'); + sb.write( + 'typedef $_ffiDartAliasName = ${type.getFfiDartType(context)};\n', + ); } if (dartAliasName != null) { - sb.write('typedef $dartAliasName = ${type.getDartType(w)};\n'); + sb.write('typedef $dartAliasName = ${type.getDartType(context)};\n'); } return BindingString( type: BindingStringType.typeDef, @@ -123,14 +127,15 @@ class Typealias extends BindingType { bool get isIncompleteCompound => type.isIncompleteCompound; @override - String getCType(Writer w) => generateBindings ? name : type.getCType(w); + String getCType(Context context) => + generateBindings ? name : type.getCType(context); @override String getNativeType({String varName = ''}) => type.getNativeType(varName: varName); @override - String getFfiDartType(Writer w) { + String getFfiDartType(Context context) { if (generateBindings) { if (_ffiDartAliasName != null) { return _ffiDartAliasName!; @@ -138,24 +143,24 @@ class Typealias extends BindingType { return name; } } - return type.getFfiDartType(w); + return type.getFfiDartType(context); } @override - String getDartType(Writer w) { + String getDartType(Context context) { if (generateBindings) { if (dartAliasName != null) { return dartAliasName!; } else if (type.sameDartAndCType) { - return getFfiDartType(w); + return getFfiDartType(context); } } - return type.getDartType(w); + return type.getDartType(context); } @override - String getObjCBlockSignatureType(Writer w) => - type.getObjCBlockSignatureType(w); + String getObjCBlockSignatureType(Context context) => + type.getObjCBlockSignatureType(context); @override bool get sameFfiDartAndCType => type.sameFfiDartAndCType; @@ -168,12 +173,12 @@ class Typealias extends BindingType { @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, }) => type.convertDartTypeToFfiDartType( - w, + context, value, objCRetain: objCRetain, objCAutorelease: objCAutorelease, @@ -181,12 +186,12 @@ class Typealias extends BindingType { @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, }) => type.convertFfiDartTypeToDartType( - w, + context, value, objCRetain: objCRetain, objCEnclosingClass: objCEnclosingClass, @@ -199,7 +204,7 @@ class Typealias extends BindingType { String cacheKey() => type.cacheKey(); @override - String? getDefaultValue(Writer w) => type.getDefaultValue(w); + String? getDefaultValue(Context context) => type.getDefaultValue(context); @override void visitChildren(Visitor visitor) { @@ -232,7 +237,7 @@ class ObjCInstanceType extends Typealias { @override String convertDartTypeToFfiDartType( - Writer w, + Context context, String value, { required bool objCRetain, required bool objCAutorelease, @@ -240,13 +245,13 @@ class ObjCInstanceType extends Typealias { @override String convertFfiDartTypeToDartType( - Writer w, + Context context, String value, { required bool objCRetain, String? objCEnclosingClass, }) => objCEnclosingClass == null ? super.convertFfiDartTypeToDartType( - w, + context, value, objCRetain: objCRetain, objCEnclosingClass: objCEnclosingClass, From acdb87204bd8ccf5a12c781ac6103230bf561dae Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 10 Sep 2025 11:54:16 +1000 Subject: [PATCH 2/3] fix --- pkgs/ffigen/lib/src/code_generator/objc_block.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_block.dart b/pkgs/ffigen/lib/src/code_generator/objc_block.dart index 32a72b2f22..c0ecaf8e49 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_block.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_block.dart @@ -318,7 +318,7 @@ abstract final class $name { $listenerConvFn, keepIsolateAlive); final wrapper = $wrapListenerFn(raw); $releaseFn(raw.cast()); - return $blockType(contextrapper, retain: false, release: true); + return $blockType(wrapper, retain: false, release: true); } /// Creates a blocking block from a Dart function. @@ -341,7 +341,7 @@ abstract final class $name { final wrapper = $wrapBlockingFn(raw, rawListener, $objCContext); $releaseFn(raw.cast()); $releaseFn(rawListener.cast()); - return $blockType(contextrapper, retain: false, release: true); + return $blockType(wrapper, retain: false, release: true); } '''); } From 6091ce7cfaaee10a6b0574ffca5694cf32d2fedc Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 10 Sep 2025 13:43:52 +1000 Subject: [PATCH 3/3] fix jni --- .../tool/wrapper_generators/ffigen_util.dart | 17 ------------- .../generate_dart_extensions.dart | 24 +++++++++++-------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/pkgs/jni/tool/wrapper_generators/ffigen_util.dart b/pkgs/jni/tool/wrapper_generators/ffigen_util.dart index 7e26e12d51..0443517162 100644 --- a/pkgs/jni/tool/wrapper_generators/ffigen_util.dart +++ b/pkgs/jni/tool/wrapper_generators/ffigen_util.dart @@ -3,23 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:ffigen/src/code_generator.dart'; -import 'package:ffigen/src/code_generator/writer.dart'; -import 'package:ffigen/src/config_provider.dart'; -import 'package:ffigen/src/context.dart'; -import 'package:logging/logging.dart'; - -final dummyWriter = Writer( - lookUpBindings: [], - ffiNativeBindings: [], - noLookUpBindings: [], - nativeEntryPoints: [], - className: 'unused', - silenceEnumWarning: true, - generateForPackageObjectiveC: false, - nativeAssetId: null, - context: Context( - Logger.root, FfiGenerator(output: Output(dartFile: Uri.file('unused')))), -); /// Find compound having [name] in [library]. Compound findCompound(Library library, String name) { diff --git a/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart b/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart index 2ef1ec3ab0..36ac3d196f 100644 --- a/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart +++ b/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart @@ -5,6 +5,7 @@ import 'dart:io'; import 'package:ffigen/src/code_generator.dart'; +import 'package:ffigen/src/context.dart'; import 'ffigen_util.dart'; import 'generate_helper_functions.dart'; @@ -37,11 +38,11 @@ const globalEnvType = 'GlobalJniEnvStruct'; const localEnvType = 'JNINativeInterface'; const jvmType = 'JNIInvokeInterface'; -String getCheckedGetter(Type returnType) { +String getCheckedGetter(Context context, Type returnType) { const objectPointerGetter = 'objectPointer'; if (returnType is PointerType) { - final child = returnType.child.getCType(dummyWriter); + final child = returnType.child.getCType(context); return 'getPointer<$child>()'; } final cType = returnType.toString(); @@ -78,6 +79,7 @@ String getCheckedGetter(Type returnType) { } String? getGlobalEnvExtensionFunction( + Context context, CompoundMember field, Type? checkedReturnType, { required bool isLeaf, @@ -96,15 +98,15 @@ String? getGlobalEnvExtensionFunction( params = params.sublist(1); final signature = params - .map((p) => '${p.type.getDartType(dummyWriter)} ${p.name}') + .map((p) => '${p.type.getDartType(context)} ${p.name}') .join(', '); final dartType = FunctionType(returnType: checkedReturnType!, parameters: params) - .getDartType(dummyWriter); + .getDartType(context); final callArgs = params.map((p) => p.name).join(', '); - final checkedGetter = getCheckedGetter(returnType); - var returns = returnType.getDartType(dummyWriter); + final checkedGetter = getCheckedGetter(context, returnType); + var returns = returnType.getDartType(context); if (checkedGetter == 'boolean') { returns = 'bool'; } @@ -257,6 +259,7 @@ String getGlobalEnvExtension( } final extensionFunctions = env.members .map((member) => getGlobalEnvExtensionFunction( + library.context, member, checkedReturnTypes[member.name], isLeaf: leafFunctions.contains(member.name), @@ -278,6 +281,7 @@ class GlobalJniEnv { } String? getFunctionPointerExtensionFunction( + Context context, CompoundMember field, { bool indirect = false, bool implicitThis = false, @@ -296,16 +300,16 @@ String? getFunctionPointerExtensionFunction( final visibleParams = implicitThis ? params.sublist(1) : params; final signature = visibleParams - .map((p) => '${p.type.getDartType(dummyWriter)} ${p.name}') + .map((p) => '${p.type.getDartType(context)} ${p.name}') .join(', '); final dartType = FunctionType(returnType: returnType, parameters: params) - .getDartType(dummyWriter); + .getDartType(context); final callArgs = [ if (implicitThis) 'ptr', ...visibleParams.map((p) => p.name) ].join(', '); - final returns = returnType.getDartType(dummyWriter); + final returns = returnType.getDartType(context); final dereference = indirect ? 'value.ref' : 'ref'; final leafCall = isLeaf ? 'isLeaf: true' : ''; return ''' @@ -325,7 +329,7 @@ String getFunctionPointerExtension( library.bindings.firstWhere((b) => b.name == type) as Type; final compound = typeBinding.typealiasType.baseType as Compound; final extensionFunctions = compound.members - .map((f) => getFunctionPointerExtensionFunction(f, + .map((f) => getFunctionPointerExtensionFunction(library.context, f, indirect: indirect, implicitThis: implicitThis, isLeaf: leafFunctions.contains(f.name)))