Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkgs/ffigen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
`Categories`, `Interfaces`, and `Protocols`.
- __Breaking change__: Remove deprecated `wrapperName` field from
`NativeExternalBindings`.
- __Breaking change__: Certain synthetic USRs have been modified to ensure they
cannot collide with real USRs. It's very unlikely that any user facing USRs
are affected.

## 20.1.1

Expand Down
15 changes: 7 additions & 8 deletions pkgs/ffigen/lib/src/code_generator/objc_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import '../code_generator.dart';
import '../context.dart';
import '../strings.dart' as strings;
import '../visitor/ast.dart';

import 'binding_string.dart';
Expand Down Expand Up @@ -108,14 +109,12 @@ class ObjCBlock extends BindingType with HasLocalScope {
) {
// Create a fake USR code for the block. This code is used to dedupe blocks
// with the same signature. Not intended to be human readable.
final usr = StringBuffer();
usr.write(
'objcBlock: ${returnType.cacheKey()} ${returnsRetained ? 'R' : ''}',
);
for (final param in params) {
usr.write(' ${param.type.cacheKey()} ${param.objCConsumed ? 'C' : ''}');
}
return usr.toString();
return [
'${strings.synthUsrChar} objcBlock:',
'${returnType.cacheKey()} ${returnsRetained ? 'R' : ''}',
for (final param in params)
'${param.type.cacheKey()} ${param.objCConsumed ? 'C' : ''}',
].join(' ');
}

bool get hasListener => returnType == voidType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import '../../code_generator.dart';
import '../../config_provider/config_types.dart';
import '../../context.dart';
import '../../strings.dart';
import '../clang_bindings/clang_bindings.dart' as clang_types;
import '../utils.dart';
import 'api_availability.dart';
Expand Down Expand Up @@ -118,7 +119,7 @@ List<Func> parseFunctionDeclaration(
);

// Initialized with a single value with no prefix and empty var args.
var varArgFunctions = [VarArgFunction('', [])];
var varArgFunctions = <VarArgFunction?>[null];
if (config.functions.varArgs.containsKey(funcName)) {
if (clang.clang_isFunctionTypeVariadic(cursor.type()) == 1) {
varArgFunctions = config.functions.varArgs[funcName]!;
Expand All @@ -130,6 +131,8 @@ List<Func> parseFunctionDeclaration(
}
}
for (final vaFunc in varArgFunctions) {
var usr = funcUsr;
if (vaFunc != null) usr += '$synthUsrChar vaFunc: ${vaFunc.postfix}';
funcs.add(
Func(
dartDoc: getCursorDocComment(
Expand All @@ -138,13 +141,13 @@ List<Func> parseFunctionDeclaration(
indent: nesting.length + commentPrefix.length,
availability: apiAvailability.dartDoc,
),
usr: funcUsr + vaFunc.postfix,
name: config.functions.rename(decl) + vaFunc.postfix,
usr: usr,
name: config.functions.rename(decl) + (vaFunc?.postfix ?? ''),
originalName: funcName,
returnType: returnType,
parameters: parameters,
varArgParameters: [
for (final ta in vaFunc.types)
for (final ta in vaFunc?.types ?? const <Type>[])
Parameter(type: ta, name: 'va', objCConsumed: false),
],
exposeSymbolAddress: config.functions.includeSymbolAddress(decl),
Expand Down
4 changes: 3 additions & 1 deletion pkgs/ffigen/lib/src/header_parser/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:logging/logging.dart';
import '../code_generator.dart';
import '../config_provider/config_types.dart';
import '../context.dart';
import '../strings.dart';
import 'clang_bindings/clang_bindings.dart' as clang_types;
import 'type_extractor/extractor.dart';

Expand Down Expand Up @@ -87,8 +88,9 @@ extension CXSourceRangePtrExt on Pointer<clang_types.CXSourceRange> {
extension CXCursorExt on clang_types.CXCursor {
String usr() {
var res = clang.clang_getCursorUSR(this).toStringAndDispose();
assert(!res.contains(synthUsrChar));
if (isAnonymousRecordDecl()) {
res += '@offset:${sourceFileOffset()}';
res += '$synthUsrChar anonRec: offset:${sourceFileOffset()}';
}
return res;
}
Expand Down
3 changes: 3 additions & 0 deletions pkgs/ffigen/lib/src/strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ const doubleNaN = 'double.nan';
/// USR for struct `_Dart_Handle`.
const dartHandleUsr = 'c:@S@_Dart_Handle';

// A character that will never appear in real USRs, for making synthetic USRs.
const synthUsrChar = '~';

const ffiNative = 'ffi-native';
const ffiNativeAsset = 'asset-id';

Expand Down
2 changes: 1 addition & 1 deletion pkgs/ffigen/test/regen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ $ dart run test/setup.dart && dart run test/regen.dart && dart test
void _regenConfig(Logger logger, String yamlConfigPath) {
final path = p.join(packagePathForTests, yamlConfigPath);
Directory.current = File(path).parent;
testConfigFromPath(path).generate(logger: logger);
testConfigFromPath(path, logger: logger).generate(logger: logger);
}

Future<void> main(List<String> args) async {
Expand Down
4 changes: 2 additions & 2 deletions pkgs/ffigen/test/test_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,10 @@ FfiGenerator testConfig(String yamlBody, {String? filename, Logger? logger}) {
).configAdapter();
}

FfiGenerator testConfigFromPath(String path) {
FfiGenerator testConfigFromPath(String path, {Logger? logger}) {
final file = File(path);
final yamlBody = file.readAsStringSync();
return testConfig(yamlBody, filename: path);
return testConfig(yamlBody, filename: path, logger: logger);
}

bool isFlutterTester = Platform.resolvedExecutable.contains('flutter_tester');
Loading