Skip to content

Commit 9d538ae

Browse files
authored
[ffigen] Tighten up synthetic USRs (#2843)
1 parent d754fff commit 9d538ae

File tree

7 files changed

+26
-16
lines changed

7 files changed

+26
-16
lines changed

pkgs/ffigen/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
`Categories`, `Interfaces`, and `Protocols`.
77
- __Breaking change__: Remove deprecated `wrapperName` field from
88
`NativeExternalBindings`.
9+
- __Breaking change__: Certain synthetic USRs have been modified to ensure they
10+
cannot collide with real USRs. It's very unlikely that any user facing USRs
11+
are affected.
912

1013
## 20.1.1
1114

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import '../code_generator.dart';
66
import '../context.dart';
7+
import '../strings.dart' as strings;
78
import '../visitor/ast.dart';
89

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

121120
bool get hasListener => returnType == voidType;

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import '../../code_generator.dart';
66
import '../../config_provider/config.dart';
77
import '../../config_provider/config_types.dart';
88
import '../../context.dart';
9+
import '../../strings.dart';
910
import '../clang_bindings/clang_bindings.dart' as clang_types;
1011
import '../utils.dart';
1112
import 'api_availability.dart';
@@ -119,7 +120,7 @@ List<Func> parseFunctionDeclaration(
119120
);
120121

121122
// Initialized with a single value with no prefix and empty var args.
122-
var varArgFunctions = [VarArgFunction('', [])];
123+
var varArgFunctions = <VarArgFunction?>[null];
123124
if (config.functions.varArgs.containsKey(funcName)) {
124125
if (clang.clang_isFunctionTypeVariadic(cursor.type()) == 1) {
125126
varArgFunctions = config.functions.varArgs[funcName]!;
@@ -131,6 +132,8 @@ List<Func> parseFunctionDeclaration(
131132
}
132133
}
133134
for (final vaFunc in varArgFunctions) {
135+
var usr = funcUsr;
136+
if (vaFunc != null) usr += '$synthUsrChar vaFunc: ${vaFunc.postfix}';
134137
funcs.add(
135138
Func(
136139
dartDoc: getCursorDocComment(
@@ -139,13 +142,13 @@ List<Func> parseFunctionDeclaration(
139142
indent: nesting.length + commentPrefix.length,
140143
availability: apiAvailability.dartDoc,
141144
),
142-
usr: funcUsr + vaFunc.postfix,
143-
name: config.functions.rename(decl) + vaFunc.postfix,
145+
usr: usr,
146+
name: config.functions.rename(decl) + (vaFunc?.postfix ?? ''),
144147
originalName: funcName,
145148
returnType: returnType,
146149
parameters: parameters,
147150
varArgParameters: [
148-
for (final ta in vaFunc.types)
151+
for (final ta in vaFunc?.types ?? const <Type>[])
149152
Parameter(type: ta, name: 'va', objCConsumed: false),
150153
],
151154
exposeSymbolAddress: config.functions.includeSymbolAddress(decl),

pkgs/ffigen/lib/src/header_parser/utils.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:logging/logging.dart';
1010
import '../code_generator.dart';
1111
import '../config_provider/config_types.dart';
1212
import '../context.dart';
13+
import '../strings.dart';
1314
import 'clang_bindings/clang_bindings.dart' as clang_types;
1415
import 'type_extractor/extractor.dart';
1516

@@ -91,8 +92,9 @@ extension CXCursorExt on clang_types.CXCursor {
9192

9293
String usr() {
9394
var res = clang.clang_getCursorUSR(this).toStringAndDispose();
95+
assert(!res.contains(synthUsrChar));
9496
if (isAnonymousRecordDecl()) {
95-
res += '@offset:${sourceFileOffset()}';
97+
res += '$synthUsrChar anonRec: offset:${sourceFileOffset()}';
9698
}
9799
return res;
98100
}

pkgs/ffigen/lib/src/strings.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ const doubleNaN = 'double.nan';
274274
/// USR for struct `_Dart_Handle`.
275275
const dartHandleUsr = 'c:@S@_Dart_Handle';
276276

277+
// A character that will never appear in real USRs, for making synthetic USRs.
278+
const synthUsrChar = '~';
279+
277280
const ffiNative = 'ffi-native';
278281
const ffiNativeAsset = 'asset-id';
279282

pkgs/ffigen/test/regen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ $ dart run test/setup.dart && dart run test/regen.dart && dart test
2222
void _regenConfig(Logger logger, String yamlConfigPath) {
2323
final path = p.join(packagePathForTests, yamlConfigPath);
2424
Directory.current = File(path).parent;
25-
testConfigFromPath(path).generate(logger: logger);
25+
testConfigFromPath(path, logger: logger).generate(logger: logger);
2626
}
2727

2828
Future<void> main(List<String> args) async {

pkgs/ffigen/test/test_utils.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,10 @@ FfiGenerator testConfig(String yamlBody, {String? filename, Logger? logger}) {
235235
).configAdapter();
236236
}
237237

238-
FfiGenerator testConfigFromPath(String path) {
238+
FfiGenerator testConfigFromPath(String path, {Logger? logger}) {
239239
final file = File(path);
240240
final yamlBody = file.readAsStringSync();
241-
return testConfig(yamlBody, filename: path);
241+
return testConfig(yamlBody, filename: path, logger: logger);
242242
}
243243

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

0 commit comments

Comments
 (0)