Fix error caused by duplicate declaration names and collision with ffi library prefix (#200)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b037c39..1b811cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 2.4.2
+- Fix issues due to declarations having duplicate names.
+- Fix name conflict of declaration with ffi library prefix.
+- Fix `char` not being recognized on platforms where it's unsigned by default.
+
# 2.4.1
- Added `/usr/lib` to default dynamic library location for linux.
diff --git a/lib/src/code_generator/library.dart b/lib/src/code_generator/library.dart
index d83a19d..e37a062 100644
--- a/lib/src/code_generator/library.dart
+++ b/lib/src/code_generator/library.dart
@@ -31,24 +31,17 @@
}) {
if (sort) _sort();
+ /// Handle any declaration-declaration name conflicts.
+ final declConflictHandler = UniqueNamer({});
+ for (final b in bindings) {
+ _warnIfPrivateDeclaration(b);
+ _resolveIfNameConflicts(declConflictHandler, b);
+ }
+
// Seperate bindings which require lookup.
final lookUpBindings = bindings.whereType<LookUpBinding>().toList();
final noLookUpBindings = bindings.whereType<NoLookUpBinding>().toList();
- /// Handle any declaration-declaration name conflict in [lookUpBindings].
- final lookUpDeclConflictHandler = UniqueNamer({});
- for (final b in lookUpBindings) {
- _warnIfPrivateDeclaration(b);
- _resolveIfNameConflicts(lookUpDeclConflictHandler, b);
- }
-
- /// Handle any declaration-declaration name conflict in [noLookUpBindings].
- final noLookUpDeclConflictHandler = UniqueNamer({});
- for (final b in noLookUpBindings) {
- _warnIfPrivateDeclaration(b);
- _resolveIfNameConflicts(noLookUpDeclConflictHandler, b);
- }
-
_writer = Writer(
lookUpBindings: lookUpBindings,
noLookUpBindings: noLookUpBindings,
diff --git a/lib/src/code_generator/writer.dart b/lib/src/code_generator/writer.dart
index 03c3647..10d1d57 100644
--- a/lib/src/code_generator/writer.dart
+++ b/lib/src/code_generator/writer.dart
@@ -70,23 +70,42 @@
final allLevelsUniqueNamer = UniqueNamer(allNameSet);
/// Wrapper class name must be unique among all names.
- _className = allLevelsUniqueNamer.makeUnique(className);
- _initialWrapperLevelUniqueNamer.markUsed(_className);
- _initialTopLevelUniqueNamer.markUsed(_className);
+ _className = _resolveNameConflict(
+ name: className,
+ makeUnique: allLevelsUniqueNamer,
+ markUsed: [_initialWrapperLevelUniqueNamer, _initialTopLevelUniqueNamer],
+ );
- /// [_ffiLibraryPrefix] should be unique in top level.
- _ffiLibraryPrefix = _initialTopLevelUniqueNamer.makeUnique('ffi');
+ /// [_ffiLibraryPrefix] should be unique unique among all names.
+ _ffiLibraryPrefix = _resolveNameConflict(
+ name: 'ffi',
+ makeUnique: allLevelsUniqueNamer,
+ markUsed: [_initialWrapperLevelUniqueNamer, _initialTopLevelUniqueNamer],
+ );
/// [_lookupFuncIdentifier] should be unique in top level.
- _lookupFuncIdentifier = _initialTopLevelUniqueNamer.makeUnique('_lookup');
+ _lookupFuncIdentifier = _resolveNameConflict(
+ name: '_lookup',
+ makeUnique: _initialTopLevelUniqueNamer,
+ markUsed: [_initialTopLevelUniqueNamer],
+ );
/// Resolve name conflicts of identifiers used for SymbolAddresses.
- _symbolAddressClassName =
- allLevelsUniqueNamer.makeUnique('_SymbolAddresses');
- _symbolAddressVariableName =
- _initialWrapperLevelUniqueNamer.makeUnique('addresses');
- _symbolAddressLibraryVarName =
- _initialWrapperLevelUniqueNamer.makeUnique('_library');
+ _symbolAddressClassName = _resolveNameConflict(
+ name: '_SymbolAddresses',
+ makeUnique: allLevelsUniqueNamer,
+ markUsed: [_initialWrapperLevelUniqueNamer, _initialTopLevelUniqueNamer],
+ );
+ _symbolAddressVariableName = _resolveNameConflict(
+ name: 'addresses',
+ makeUnique: _initialWrapperLevelUniqueNamer,
+ markUsed: [_initialWrapperLevelUniqueNamer],
+ );
+ _symbolAddressLibraryVarName = _resolveNameConflict(
+ name: '_library',
+ makeUnique: _initialWrapperLevelUniqueNamer,
+ markUsed: [_initialWrapperLevelUniqueNamer],
+ );
/// Finding a unique prefix for Array Helper Classes and store into
/// [_arrayHelperClassPrefix].
@@ -105,6 +124,20 @@
_resetUniqueNamersNamers();
}
+ /// Resolved name conflict using [makeUnique] and marks the result as used in
+ /// all [markUsed].
+ String _resolveNameConflict({
+ required String name,
+ required UniqueNamer makeUnique,
+ List<UniqueNamer> markUsed = const [],
+ }) {
+ final s = makeUnique.makeUnique(name);
+ for (final un in markUsed) {
+ un.markUsed(s);
+ }
+ return s;
+ }
+
/// Resets the namers to initial state. Namers are reset before generating.
void _resetUniqueNamersNamers() {
_topLevelUniqueNamer = _initialTopLevelUniqueNamer.clone();
diff --git a/pubspec.yaml b/pubspec.yaml
index deb1c68..d5ad721 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
name: ffigen
-version: 2.4.1
+version: 2.4.2
homepage: https://github.com/dart-lang/ffigen
description: Generator for FFI bindings, using LibClang to parse C header files.
diff --git a/test/collision_tests/decl_decl_collision_test.dart b/test/collision_tests/decl_decl_collision_test.dart
index 554795e..fb6645f 100644
--- a/test/collision_tests/decl_decl_collision_test.dart
+++ b/test/collision_tests/decl_decl_collision_test.dart
@@ -36,6 +36,20 @@
rawType: 'int',
rawValue: '0',
),
+
+ /// Conflicts across declarations.
+ Struc(name: 'testCrossDecl'),
+ Func(
+ name: 'testCrossDecl',
+ returnType: Type.nativeType(SupportedNativeType.Void)),
+ Constant(name: 'testCrossDecl', rawValue: '0', rawType: 'int'),
+ EnumClass(name: 'testCrossDecl'),
+
+ /// Conflicts with ffi library prefix, name of prefix is changed.
+ Struc(name: 'ffi'),
+ Func(
+ name: 'ffi_1',
+ returnType: Type.nativeType(SupportedNativeType.Void)),
]);
final l2 = Library(name: 'Bindings', bindings: [
Struc(name: 'TestStruc'),
@@ -62,6 +76,17 @@
rawType: 'int',
rawValue: '0',
),
+ Struc(name: 'testCrossDecl', originalName: 'testCrossDecl'),
+ Func(
+ name: 'testCrossDecl_1',
+ originalName: 'testCrossDecl',
+ returnType: Type.nativeType(SupportedNativeType.Void)),
+ Constant(name: 'testCrossDecl_2', rawValue: '0', rawType: 'int'),
+ EnumClass(name: 'testCrossDecl_3'),
+ Struc(name: 'ffi'),
+ Func(
+ name: 'ffi_1',
+ returnType: Type.nativeType(SupportedNativeType.Void)),
]);
expect(l1.generate(), l2.generate());