3.0 Class modifiers (#553)

diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 8bcf6e6..d9aa8a4 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -3,9 +3,9 @@
 on:
   # Run on PRs and pushes to the default branch.
   push:
-    branches: [ master, stable]
+    branches: [master, stable]
   pull_request:
-    branches: [ master, stable]
+    branches: [master, stable]
   schedule:
     - cron: "0 0 * * 0"
 
@@ -19,7 +19,7 @@
     strategy:
       fail-fast: false
       matrix:
-        sdk: [stable]
+        sdk: [3.0.0-417.0.dev] # TODO(#554)
     steps:
       - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
       - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
@@ -44,7 +44,7 @@
       - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
       - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: stable
+          sdk: 3.0.0-417.0.dev # TODO(#554)
       - name: Install dependencies
         run: dart pub get
       - name: Install libclang-14-dev
@@ -61,7 +61,7 @@
       - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
       - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: stable
+          sdk: 3.0.0-417.0.dev # TODO(#554)
       - name: Install dependencies
         run: dart pub get
       - name: Build test dylib and bindings
@@ -83,7 +83,7 @@
       - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
       - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: stable
+          sdk: 3.0.0-417.0.dev # TODO(#554)
       - name: Install dependencies
         run: dart pub get
       - name: Build test dylib and bindings
@@ -108,7 +108,7 @@
       - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
       - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa
         with:
-          channel: 'master'
+          channel: "master"
       - name: Install dependencies
         run: flutter pub get
       - name: Build test dylib and bindings
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e996b1c..6b40576 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+# 8.0.0-dev.0
+
+- Adds `final` class modifier to generated sub types `Struct`, `Union` and
+  `Opaque`. A class modifier is required in Dart 3.0 because the classes
+  `dart:ffi` as marked `base`.
+  When migrating a package that uses FFIgen, _and_ exposes the generated code in
+  the public API of the package, to Dart 3.0, that package does not
+  need a major version bump. Sub typing `Struct`, `Union` and
+  `Opaque` sub types is already disallowed by `dart:ffi` pre 3.0, so adding the
+  `final` keyword is not a breaking change.
+- Bumps SDK lowerbound to 3.0.
+
 # 7.2.10
 
 - Generate parameter names in function pointer fields and typedefs.
diff --git a/example/c_json/cjson_generated_bindings.dart b/example/c_json/cjson_generated_bindings.dart
index c520c20..0fb9e1a 100644
--- a/example/c_json/cjson_generated_bindings.dart
+++ b/example/c_json/cjson_generated_bindings.dart
@@ -1234,7 +1234,7 @@
       _cJSON_freePtr.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 }
 
-class cJSON extends ffi.Struct {
+final class cJSON extends ffi.Struct {
   external ffi.Pointer<cJSON> next;
 
   external ffi.Pointer<cJSON> prev;
@@ -1255,7 +1255,7 @@
   external ffi.Pointer<ffi.Char> string;
 }
 
-class cJSON_Hooks extends ffi.Struct {
+final class cJSON_Hooks extends ffi.Struct {
   external ffi.Pointer<
           ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size sz)>>
       malloc_fn;
diff --git a/example/c_json/pubspec.yaml b/example/c_json/pubspec.yaml
index 1733b5f..120d197 100644
--- a/example/c_json/pubspec.yaml
+++ b/example/c_json/pubspec.yaml
@@ -5,7 +5,7 @@
 name: c_json_example
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   ffi: ^2.0.1
@@ -13,5 +13,5 @@
 
 dev_dependencies:
   ffigen:
-    path: '../../'
+    path: "../../"
   lints: ^2.0.1
diff --git a/example/ffinative/pubspec.yaml b/example/ffinative/pubspec.yaml
index 2247de4..920ec99 100644
--- a/example/ffinative/pubspec.yaml
+++ b/example/ffinative/pubspec.yaml
@@ -5,11 +5,11 @@
 name: ffinative_example
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   ffi: ^2.0.1
 dev_dependencies:
   ffigen:
-    path: '../../'
+    path: "../../"
   lints: ^2.0.0
diff --git a/example/libclang-example/custom_import.dart b/example/libclang-example/custom_import.dart
index df11af4..dd6196c 100644
--- a/example/libclang-example/custom_import.dart
+++ b/example/libclang-example/custom_import.dart
@@ -28,7 +28,7 @@
   Abi.windowsIA32: Uint32(),
   Abi.windowsX64: Uint64(),
 })
-class UintPtr extends AbiSpecificInteger {
+final class UintPtr extends AbiSpecificInteger {
   const UintPtr();
 }
 
@@ -56,8 +56,8 @@
   Abi.windowsIA32: Uint32(),
   Abi.windowsX64: Uint32(),
 })
-class UnsignedLong extends AbiSpecificInteger {
+final class UnsignedLong extends AbiSpecificInteger {
   const UnsignedLong();
 }
 
-class CXCursorSetImpl extends Opaque {}
+final class CXCursorSetImpl extends Opaque {}
diff --git a/example/libclang-example/generated_bindings.dart b/example/libclang-example/generated_bindings.dart
index 800c580..64de33c 100644
--- a/example/libclang-example/generated_bindings.dart
+++ b/example/libclang-example/generated_bindings.dart
@@ -7647,14 +7647,14 @@
 /// the ownership of that string might differ from one call to the next.
 /// Use \c clang_getCString() to retrieve the string data and, once finished
 /// with the string data, call \c clang_disposeString() to free the string.
-class CXString extends ffi.Struct {
+final class CXString extends ffi.Struct {
   external ffi.Pointer<ffi.Void> data;
 
   @ffi.UnsignedInt()
   external int private_flags;
 }
 
-class CXStringSet extends ffi.Struct {
+final class CXStringSet extends ffi.Struct {
   external ffi.Pointer<CXString> Strings;
 
   @ffi.UnsignedInt()
@@ -7671,16 +7671,16 @@
 typedef DartClang_disposeStringSet = void Function(
     ffi.Pointer<CXStringSet> set1);
 
-class CXTargetInfoImpl extends ffi.Opaque {}
+final class CXTargetInfoImpl extends ffi.Opaque {}
 
-class CXTranslationUnitImpl extends ffi.Opaque {}
+final class CXTranslationUnitImpl extends ffi.Opaque {}
 
 /// Provides the contents of a file that has not yet been saved to disk.
 ///
 /// Each CXUnsavedFile instance provides the name of a file on the
 /// system along with the current contents of that file that have not
 /// yet been saved to disk.
-class CXUnsavedFile extends ffi.Struct {
+final class CXUnsavedFile extends ffi.Struct {
   /// The file whose contents have not yet been saved.
   ///
   /// This file must already exist in the file system.
@@ -7695,7 +7695,7 @@
 }
 
 /// Describes a version number of the form major.minor.subminor.
-class CXVersion extends ffi.Struct {
+final class CXVersion extends ffi.Struct {
   /// The major version number, e.g., the '10' in '10.7.3'. A negative
   /// value indicates that there is no version number at all.
   @ffi.Int()
@@ -7768,7 +7768,7 @@
 
 /// Uniquely identifies a CXFile, that refers to the same underlying file,
 /// across an indexing session.
-class CXFileUniqueID extends ffi.Struct {
+final class CXFileUniqueID extends ffi.Struct {
   @ffi.Array.multi([3])
   external ffi.Array<ffi.UnsignedLongLong> data;
 }
@@ -7802,7 +7802,7 @@
 ///
 /// Use clang_getExpansionLocation() or clang_getSpellingLocation()
 /// to map a source location to a particular file, line, and column.
-class CXSourceLocation extends ffi.Struct {
+final class CXSourceLocation extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -7814,7 +7814,7 @@
 ///
 /// Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
 /// starting and end locations from a source range, respectively.
-class CXSourceRange extends ffi.Struct {
+final class CXSourceRange extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -7929,7 +7929,7 @@
 typedef DartClang_getRangeEnd = CXSourceLocation Function(CXSourceRange range);
 
 /// Identifies an array of ranges.
-class CXSourceRangeList extends ffi.Struct {
+final class CXSourceRangeList extends ffi.Struct {
   /// The number of ranges in the \c ranges array.
   @ffi.UnsignedInt()
   external int count;
@@ -8251,7 +8251,7 @@
 typedef DartClang_getTUResourceUsageName = ffi.Pointer<ffi.Char> Function(
     int kind);
 
-class CXTUResourceUsageEntry extends ffi.Struct {
+final class CXTUResourceUsageEntry extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -8260,7 +8260,7 @@
 }
 
 /// The memory usage of a CXTranslationUnit, broken into categories.
-class CXTUResourceUsage extends ffi.Struct {
+final class CXTUResourceUsage extends ffi.Struct {
   external ffi.Pointer<ffi.Void> data;
 
   @ffi.UnsignedInt()
@@ -8309,7 +8309,7 @@
 /// translation unit. clang_getCursor() maps from a physical source location
 /// to the entity that resides at that location, allowing one to map from the
 /// source code into the AST.
-class CXCursor extends ffi.Struct {
+final class CXCursor extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -9212,7 +9212,7 @@
 
 /// Describes the availability of a given entity on a particular platform, e.g.,
 /// a particular class might only be available on Mac OS 10.7 or newer.
-class CXPlatformAvailability extends ffi.Struct {
+final class CXPlatformAvailability extends ffi.Struct {
   /// A string that describes the platform for which this structure
   /// provides availability information.
   ///
@@ -9460,7 +9460,7 @@
 }
 
 /// The type of an element in the abstract syntax tree.
-class CXType extends ffi.Struct {
+final class CXType extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -10007,7 +10007,7 @@
     CXCursor C, int NameFlags, int PieceIndex);
 
 /// Describes a single preprocessing token.
-class CXToken extends ffi.Struct {
+final class CXToken extends ffi.Struct {
   @ffi.Array.multi([4])
   external ffi.Array<ffi.UnsignedInt> int_data;
 
@@ -10104,7 +10104,7 @@
     int stack_size);
 
 /// A single result of code completion.
-class CXCompletionResult extends ffi.Struct {
+final class CXCompletionResult extends ffi.Struct {
   /// The kind of entity that this completion refers to.
   ///
   /// The cursor kind will be a macro, keyword, or a declaration (one of the
@@ -10332,7 +10332,7 @@
 /// This data structure contains the results of code completion, as
 /// produced by \c clang_codeCompleteAt(). Its contents must be freed by
 /// \c clang_disposeCodeCompleteResults.
-class CXCodeCompleteResults extends ffi.Struct {
+final class CXCodeCompleteResults extends ffi.Struct {
   /// The code-completion results.
   external ffi.Pointer<CXCompletionResult> Results;
 
@@ -10501,7 +10501,7 @@
 typedef NativeClang_remap_dispose = ffi.Void Function(CXRemapping arg0);
 typedef DartClang_remap_dispose = void Function(CXRemapping arg0);
 
-class CXCursorAndRangeVisitor extends ffi.Struct {
+final class CXCursorAndRangeVisitor extends ffi.Struct {
   external ffi.Pointer<ffi.Void> context;
 
   external ffi.Pointer<
@@ -10540,7 +10540,7 @@
     CXTranslationUnit TU, CXFile file, CXCursorAndRangeVisitor visitor);
 
 /// Source location passed to index callbacks.
-class CXIdxLoc extends ffi.Struct {
+final class CXIdxLoc extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -10549,7 +10549,7 @@
 }
 
 /// Data for ppIncludedFile callback.
-class CXIdxIncludedFileInfo extends ffi.Struct {
+final class CXIdxIncludedFileInfo extends ffi.Struct {
   /// Location of '#' in the \#include/\#import directive.
   external CXIdxLoc hashLoc;
 
@@ -10572,7 +10572,7 @@
 }
 
 /// Data for IndexerCallbacks#importedASTFile.
-class CXIdxImportedASTFileInfo extends ffi.Struct {
+final class CXIdxImportedASTFileInfo extends ffi.Struct {
   /// Top level AST file containing the imported PCH, module or submodule.
   external CXFile file;
 
@@ -10588,7 +10588,7 @@
   external int isImplicit;
 }
 
-class CXIdxAttrInfo extends ffi.Struct {
+final class CXIdxAttrInfo extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -10604,7 +10604,7 @@
   static const int CXIdxAttr_IBOutletCollection = 3;
 }
 
-class CXIdxEntityInfo extends ffi.Struct {
+final class CXIdxEntityInfo extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -10679,11 +10679,11 @@
   static const int CXIdxEntityLang_Swift = 4;
 }
 
-class CXIdxContainerInfo extends ffi.Struct {
+final class CXIdxContainerInfo extends ffi.Struct {
   external CXCursor cursor;
 }
 
-class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct {
+final class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxAttrInfo> attrInfo;
 
   external ffi.Pointer<CXIdxEntityInfo> objcClass;
@@ -10693,7 +10693,7 @@
   external CXIdxLoc classLoc;
 }
 
-class CXIdxDeclInfo extends ffi.Struct {
+final class CXIdxDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxEntityInfo> entityInfo;
 
   external CXCursor cursor;
@@ -10731,7 +10731,7 @@
   external int flags;
 }
 
-class CXIdxObjCContainerDeclInfo extends ffi.Struct {
+final class CXIdxObjCContainerDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxDeclInfo> declInfo;
 
   @ffi.Int32()
@@ -10744,7 +10744,7 @@
   static const int CXIdxObjCContainer_Implementation = 2;
 }
 
-class CXIdxBaseClassInfo extends ffi.Struct {
+final class CXIdxBaseClassInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxEntityInfo> base;
 
   external CXCursor cursor;
@@ -10752,7 +10752,7 @@
   external CXIdxLoc loc;
 }
 
-class CXIdxObjCProtocolRefInfo extends ffi.Struct {
+final class CXIdxObjCProtocolRefInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxEntityInfo> protocol;
 
   external CXCursor cursor;
@@ -10760,14 +10760,14 @@
   external CXIdxLoc loc;
 }
 
-class CXIdxObjCProtocolRefListInfo extends ffi.Struct {
+final class CXIdxObjCProtocolRefListInfo extends ffi.Struct {
   external ffi.Pointer<ffi.Pointer<CXIdxObjCProtocolRefInfo>> protocols;
 
   @ffi.UnsignedInt()
   external int numProtocols;
 }
 
-class CXIdxObjCInterfaceDeclInfo extends ffi.Struct {
+final class CXIdxObjCInterfaceDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxObjCContainerDeclInfo> containerInfo;
 
   external ffi.Pointer<CXIdxBaseClassInfo> superInfo;
@@ -10775,7 +10775,7 @@
   external ffi.Pointer<CXIdxObjCProtocolRefListInfo> protocols;
 }
 
-class CXIdxObjCCategoryDeclInfo extends ffi.Struct {
+final class CXIdxObjCCategoryDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxObjCContainerDeclInfo> containerInfo;
 
   external ffi.Pointer<CXIdxEntityInfo> objcClass;
@@ -10787,7 +10787,7 @@
   external ffi.Pointer<CXIdxObjCProtocolRefListInfo> protocols;
 }
 
-class CXIdxObjCPropertyDeclInfo extends ffi.Struct {
+final class CXIdxObjCPropertyDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxDeclInfo> declInfo;
 
   external ffi.Pointer<CXIdxEntityInfo> getter;
@@ -10795,7 +10795,7 @@
   external ffi.Pointer<CXIdxEntityInfo> setter;
 }
 
-class CXIdxCXXClassDeclInfo extends ffi.Struct {
+final class CXIdxCXXClassDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxDeclInfo> declInfo;
 
   external ffi.Pointer<ffi.Pointer<CXIdxBaseClassInfo>> bases;
@@ -10805,7 +10805,7 @@
 }
 
 /// Data for IndexerCallbacks#indexEntityReference.
-class CXIdxEntityRefInfo extends ffi.Struct {
+final class CXIdxEntityRefInfo extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -10944,7 +10944,7 @@
 
 /// A group of callbacks used by #clang_indexSourceFile and
 /// #clang_indexTranslationUnit.
-class IndexerCallbacks extends ffi.Struct {
+final class IndexerCallbacks extends ffi.Struct {
   /// Called periodically to check whether indexing should be aborted.
   /// Should return 0 to continue, and non-zero to abort.
   external ffi.Pointer<
diff --git a/example/libclang-example/pubspec.yaml b/example/libclang-example/pubspec.yaml
index daef35b..c263c76 100644
--- a/example/libclang-example/pubspec.yaml
+++ b/example/libclang-example/pubspec.yaml
@@ -5,11 +5,11 @@
 name: libclang_example
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   ffi: ^2.0.1
 dev_dependencies:
   ffigen:
-    path: '../../'
+    path: "../../"
   lints: ^2.0.1
diff --git a/example/objective_c/avf_audio_bindings.dart b/example/objective_c/avf_audio_bindings.dart
index 972e8fe..ae0d3fd 100644
--- a/example/objective_c/avf_audio_bindings.dart
+++ b/example/objective_c/avf_audio_bindings.dart
@@ -30391,13 +30391,13 @@
   }
 }
 
-class ObjCSel extends ffi.Opaque {}
+final class ObjCSel extends ffi.Opaque {}
 
-class ObjCObject extends ffi.Opaque {}
+final class ObjCObject extends ffi.Opaque {}
 
 typedef instancetype = ffi.Pointer<ObjCObject>;
 
-class _NSZone extends ffi.Opaque {}
+final class _NSZone extends ffi.Opaque {}
 
 class Protocol extends _ObjCWrapper {
   Protocol._(ffi.Pointer<ObjCObject> id, AVFAudio lib,
@@ -33375,7 +33375,7 @@
 
 typedef NSRange = _NSRange;
 
-class _NSRange extends ffi.Struct {
+final class _NSRange extends ffi.Struct {
   @NSUInteger()
   external int location;
 
@@ -34616,7 +34616,7 @@
 
 typedef NSPoint = CGPoint;
 
-class CGPoint extends ffi.Struct {
+final class CGPoint extends ffi.Struct {
   @CGFloat()
   external double x;
 
@@ -34627,7 +34627,7 @@
 typedef CGFloat = ffi.Double;
 typedef NSSize = CGSize;
 
-class CGSize extends ffi.Struct {
+final class CGSize extends ffi.Struct {
   @CGFloat()
   external double width;
 
@@ -34637,13 +34637,13 @@
 
 typedef NSRect = CGRect;
 
-class CGRect extends ffi.Struct {
+final class CGRect extends ffi.Struct {
   external CGPoint origin;
 
   external CGSize size;
 }
 
-class NSEdgeInsets extends ffi.Struct {
+final class NSEdgeInsets extends ffi.Struct {
   @CGFloat()
   external double top;
 
@@ -35786,7 +35786,7 @@
   ffi.Pointer<_ObjCBlock> get pointer => _id;
 }
 
-class _ObjCBlockDesc extends ffi.Struct {
+final class _ObjCBlockDesc extends ffi.Struct {
   @ffi.UnsignedLong()
   external int reserved;
 
@@ -35800,7 +35800,7 @@
   external ffi.Pointer<ffi.Char> signature;
 }
 
-class _ObjCBlock extends ffi.Struct {
+final class _ObjCBlock extends ffi.Struct {
   external ffi.Pointer<ffi.Void> isa;
 
   @ffi.Int()
@@ -36434,7 +36434,7 @@
   }
 }
 
-class __va_list_tag extends ffi.Struct {
+final class __va_list_tag extends ffi.Struct {
   @ffi.UnsignedInt()
   external int gp_offset;
 
@@ -37121,7 +37121,7 @@
   ffi.Pointer<_ObjCBlock> get pointer => _id;
 }
 
-class NSFastEnumerationState extends ffi.Struct {
+final class NSFastEnumerationState extends ffi.Struct {
   @ffi.UnsignedLong()
   external int state;
 
@@ -44040,7 +44040,7 @@
 typedef NSRunLoopMode = ffi.Pointer<ObjCObject>;
 typedef CFRunLoopRef = ffi.Pointer<__CFRunLoop>;
 
-class __CFRunLoop extends ffi.Opaque {}
+final class __CFRunLoop extends ffi.Opaque {}
 
 class NSTimer extends NSObject {
   NSTimer._(ffi.Pointer<ObjCObject> id, AVFAudio lib,
@@ -45951,7 +45951,7 @@
 typedef __int32_t = ffi.Int;
 
 @ffi.Packed(2)
-class AEDesc extends ffi.Struct {
+final class AEDesc extends ffi.Struct {
   @DescType()
   external int descriptorType;
 
@@ -45961,7 +45961,7 @@
 typedef AEDataStorage = ffi.Pointer<AEDataStorageType>;
 typedef AEDataStorageType = ffi.Pointer<OpaqueAEDataStorageType>;
 
-class OpaqueAEDataStorageType extends ffi.Opaque {}
+final class OpaqueAEDataStorageType extends ffi.Opaque {}
 
 typedef AEKeyword = FourCharCode;
 
@@ -53059,7 +53059,7 @@
   }
 }
 
-class NSDecimal extends ffi.Opaque {}
+final class NSDecimal extends ffi.Opaque {}
 
 class NSException extends NSObject {
   NSException._(ffi.Pointer<ObjCObject> id, AVFAudio lib,
@@ -57469,7 +57469,7 @@
   }
 }
 
-class NSOperatingSystemVersion extends ffi.Struct {
+final class NSOperatingSystemVersion extends ffi.Struct {
   @NSInteger()
   external int majorVersion;
 
@@ -59371,11 +59371,11 @@
 
 typedef SecIdentityRef = ffi.Pointer<__SecIdentity>;
 
-class __SecIdentity extends ffi.Opaque {}
+final class __SecIdentity extends ffi.Opaque {}
 
 typedef SecTrustRef = ffi.Pointer<__SecTrust>;
 
-class __SecTrust extends ffi.Opaque {}
+final class __SecTrust extends ffi.Opaque {}
 
 class NSURLProtectionSpace extends NSObject {
   NSURLProtectionSpace._(ffi.Pointer<ObjCObject> id, AVFAudio lib,
@@ -67493,7 +67493,7 @@
   }
 }
 
-class AudioStreamBasicDescription extends ffi.Struct {
+final class AudioStreamBasicDescription extends ffi.Struct {
   @Float64()
   external double mSampleRate;
 
@@ -67680,7 +67680,7 @@
 
 typedef AudioChannelLayoutTag = UInt32;
 
-class AudioChannelLayout extends ffi.Struct {
+final class AudioChannelLayout extends ffi.Struct {
   @AudioChannelLayoutTag()
   external int mChannelLayoutTag;
 
@@ -67724,7 +67724,7 @@
   static const int kAudioChannelBit_RightTopRear = 67108864;
 }
 
-class AudioChannelDescription extends ffi.Struct {
+final class AudioChannelDescription extends ffi.Struct {
   @AudioChannelLabel()
   external int mChannelLabel;
 
@@ -67758,4 +67758,4 @@
 typedef CMAudioFormatDescriptionRef = CMFormatDescriptionRef;
 typedef CMFormatDescriptionRef = ffi.Pointer<opaqueCMFormatDescription>;
 
-class opaqueCMFormatDescription extends ffi.Opaque {}
+final class opaqueCMFormatDescription extends ffi.Opaque {}
diff --git a/example/objective_c/pubspec.yaml b/example/objective_c/pubspec.yaml
index 33b0c31..76aef5f 100644
--- a/example/objective_c/pubspec.yaml
+++ b/example/objective_c/pubspec.yaml
@@ -5,11 +5,11 @@
 name: objective_c_example
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   ffi: ^2.0.1
 dev_dependencies:
   ffigen:
-    path: '../../'
+    path: "../../"
   lints: ^2.0.0
diff --git a/example/shared_bindings/lib/generated/a_gen.dart b/example/shared_bindings/lib/generated/a_gen.dart
index 6cd4f8a..4661c25 100644
--- a/example/shared_bindings/lib/generated/a_gen.dart
+++ b/example/shared_bindings/lib/generated/a_gen.dart
@@ -65,22 +65,22 @@
       .asFunction<void Function(BaseStruct2, BaseUnion2, BaseTypedef2)>();
 }
 
-class BaseStruct1 extends ffi.Struct {
+final class BaseStruct1 extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class BaseUnion1 extends ffi.Union {
+final class BaseUnion1 extends ffi.Union {
   @ffi.Int()
   external int a;
 }
 
-class BaseStruct2 extends ffi.Struct {
+final class BaseStruct2 extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class BaseUnion2 extends ffi.Union {
+final class BaseUnion2 extends ffi.Union {
   @ffi.Int()
   external int a;
 }
@@ -93,12 +93,12 @@
 typedef BaseTypedef1 = BaseStruct1;
 typedef BaseTypedef2 = BaseStruct2;
 
-class A_Struct1 extends ffi.Struct {
+final class A_Struct1 extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class A_Union1 extends ffi.Union {
+final class A_Union1 extends ffi.Union {
   @ffi.Int()
   external int a;
 }
diff --git a/example/shared_bindings/lib/generated/a_shared_b_gen.dart b/example/shared_bindings/lib/generated/a_shared_b_gen.dart
index 1346bec..ba61da4 100644
--- a/example/shared_bindings/lib/generated/a_shared_b_gen.dart
+++ b/example/shared_bindings/lib/generated/a_shared_b_gen.dart
@@ -51,12 +51,12 @@
       void Function(imp1.BaseStruct2, imp1.BaseUnion2, imp1.BaseTypedef2)>();
 }
 
-class A_Struct1 extends ffi.Struct {
+final class A_Struct1 extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class A_Union1 extends ffi.Union {
+final class A_Union1 extends ffi.Union {
   @ffi.Int()
   external int a;
 }
diff --git a/example/shared_bindings/lib/generated/base_gen.dart b/example/shared_bindings/lib/generated/base_gen.dart
index b31c2e8..9d90b53 100644
--- a/example/shared_bindings/lib/generated/base_gen.dart
+++ b/example/shared_bindings/lib/generated/base_gen.dart
@@ -39,22 +39,22 @@
       _base_func1Ptr.asFunction<void Function(BaseTypedef1, BaseTypedef2)>();
 }
 
-class BaseStruct1 extends ffi.Struct {
+final class BaseStruct1 extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class BaseUnion1 extends ffi.Union {
+final class BaseUnion1 extends ffi.Union {
   @ffi.Int()
   external int a;
 }
 
-class BaseStruct2 extends ffi.Struct {
+final class BaseStruct2 extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class BaseUnion2 extends ffi.Union {
+final class BaseUnion2 extends ffi.Union {
   @ffi.Int()
   external int a;
 }
diff --git a/example/shared_bindings/pubspec.yaml b/example/shared_bindings/pubspec.yaml
index fbe942e..fd8cbde 100644
--- a/example/shared_bindings/pubspec.yaml
+++ b/example/shared_bindings/pubspec.yaml
@@ -5,7 +5,7 @@
 name: shared_bindings
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   cli_util: ^0.4.0
@@ -14,5 +14,5 @@
 
 dev_dependencies:
   ffigen:
-    path: '../../'
+    path: "../../"
   lints: ^2.0.1
diff --git a/example/simple/pubspec.yaml b/example/simple/pubspec.yaml
index d59f53e..b6a4c67 100644
--- a/example/simple/pubspec.yaml
+++ b/example/simple/pubspec.yaml
@@ -5,12 +5,11 @@
 name: simple_example
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   ffi: ^2.0.1
 dev_dependencies:
   ffigen:
-    path: '../../'
+    path: "../../"
   lints: ^2.0.1
-
diff --git a/example/swift/pubspec.yaml b/example/swift/pubspec.yaml
index d00ffa9..d0725dd 100644
--- a/example/swift/pubspec.yaml
+++ b/example/swift/pubspec.yaml
@@ -5,11 +5,11 @@
 name: swift_example
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   ffi: ^2.0.1
 dev_dependencies:
   ffigen:
-    path: '../../'
+    path: "../../"
   lints: ^2.0.0
diff --git a/example/swift/swift_api_bindings.dart b/example/swift/swift_api_bindings.dart
index 383944f..f741f7f 100644
--- a/example/swift/swift_api_bindings.dart
+++ b/example/swift/swift_api_bindings.dart
@@ -29122,13 +29122,13 @@
   }
 }
 
-class ObjCSel extends ffi.Opaque {}
+final class ObjCSel extends ffi.Opaque {}
 
-class ObjCObject extends ffi.Opaque {}
+final class ObjCObject extends ffi.Opaque {}
 
 typedef instancetype = ffi.Pointer<ObjCObject>;
 
-class _NSZone extends ffi.Opaque {}
+final class _NSZone extends ffi.Opaque {}
 
 class Protocol extends _ObjCWrapper {
   Protocol._(ffi.Pointer<ObjCObject> id, SwiftLibrary lib,
@@ -32115,7 +32115,7 @@
 
 typedef NSRange = _NSRange;
 
-class _NSRange extends ffi.Struct {
+final class _NSRange extends ffi.Struct {
   @NSUInteger()
   external int location;
 
@@ -33364,7 +33364,7 @@
 
 typedef NSPoint = CGPoint;
 
-class CGPoint extends ffi.Struct {
+final class CGPoint extends ffi.Struct {
   @CGFloat()
   external double x;
 
@@ -33375,7 +33375,7 @@
 typedef CGFloat = ffi.Double;
 typedef NSSize = CGSize;
 
-class CGSize extends ffi.Struct {
+final class CGSize extends ffi.Struct {
   @CGFloat()
   external double width;
 
@@ -33385,13 +33385,13 @@
 
 typedef NSRect = CGRect;
 
-class CGRect extends ffi.Struct {
+final class CGRect extends ffi.Struct {
   external CGPoint origin;
 
   external CGSize size;
 }
 
-class NSEdgeInsets extends ffi.Struct {
+final class NSEdgeInsets extends ffi.Struct {
   @CGFloat()
   external double top;
 
@@ -34538,7 +34538,7 @@
   ffi.Pointer<_ObjCBlock> get pointer => _id;
 }
 
-class _ObjCBlockDesc extends ffi.Struct {
+final class _ObjCBlockDesc extends ffi.Struct {
   @ffi.UnsignedLong()
   external int reserved;
 
@@ -34552,7 +34552,7 @@
   external ffi.Pointer<ffi.Char> signature;
 }
 
-class _ObjCBlock extends ffi.Struct {
+final class _ObjCBlock extends ffi.Struct {
   external ffi.Pointer<ffi.Void> isa;
 
   @ffi.Int()
@@ -35183,7 +35183,7 @@
   }
 }
 
-class __va_list_tag extends ffi.Struct {
+final class __va_list_tag extends ffi.Struct {
   @ffi.UnsignedInt()
   external int gp_offset;
 
@@ -35871,7 +35871,7 @@
   ffi.Pointer<_ObjCBlock> get pointer => _id;
 }
 
-class NSFastEnumerationState extends ffi.Struct {
+final class NSFastEnumerationState extends ffi.Struct {
   @ffi.UnsignedLong()
   external int state;
 
@@ -42805,7 +42805,7 @@
 typedef NSRunLoopMode = ffi.Pointer<ObjCObject>;
 typedef CFRunLoopRef = ffi.Pointer<__CFRunLoop>;
 
-class __CFRunLoop extends ffi.Opaque {}
+final class __CFRunLoop extends ffi.Opaque {}
 
 class NSTimer extends NSObject {
   NSTimer._(ffi.Pointer<ObjCObject> id, SwiftLibrary lib,
@@ -44721,7 +44721,7 @@
 typedef __int32_t = ffi.Int;
 
 @ffi.Packed(2)
-class AEDesc extends ffi.Struct {
+final class AEDesc extends ffi.Struct {
   @DescType()
   external int descriptorType;
 
@@ -44731,7 +44731,7 @@
 typedef AEDataStorage = ffi.Pointer<AEDataStorageType>;
 typedef AEDataStorageType = ffi.Pointer<OpaqueAEDataStorageType>;
 
-class OpaqueAEDataStorageType extends ffi.Opaque {}
+final class OpaqueAEDataStorageType extends ffi.Opaque {}
 
 typedef AEKeyword = FourCharCode;
 
@@ -51847,7 +51847,7 @@
   }
 }
 
-class NSDecimal extends ffi.Opaque {}
+final class NSDecimal extends ffi.Opaque {}
 
 class NSException extends NSObject {
   NSException._(ffi.Pointer<ObjCObject> id, SwiftLibrary lib,
@@ -56260,7 +56260,7 @@
   }
 }
 
-class NSOperatingSystemVersion extends ffi.Struct {
+final class NSOperatingSystemVersion extends ffi.Struct {
   @NSInteger()
   external int majorVersion;
 
@@ -58169,11 +58169,11 @@
 
 typedef SecIdentityRef = ffi.Pointer<__SecIdentity>;
 
-class __SecIdentity extends ffi.Opaque {}
+final class __SecIdentity extends ffi.Opaque {}
 
 typedef SecTrustRef = ffi.Pointer<__SecTrust>;
 
-class __SecTrust extends ffi.Opaque {}
+final class __SecTrust extends ffi.Opaque {}
 
 class NSURLProtectionSpace extends NSObject {
   NSURLProtectionSpace._(ffi.Pointer<ObjCObject> id, SwiftLibrary lib,
diff --git a/lib/src/code_generator/compound.dart b/lib/src/code_generator/compound.dart
index 2c915a2..894d379 100644
--- a/lib/src/code_generator/compound.dart
+++ b/lib/src/code_generator/compound.dart
@@ -129,7 +129,7 @@
     }
     final dartClassName = isStruct ? 'Struct' : 'Union';
     // Write class declaration.
-    s.write('class $enclosingClassName extends ');
+    s.write('final class $enclosingClassName extends ');
     s.write('${w.ffiLibraryPrefix}.${isOpaque ? 'Opaque' : dartClassName}{\n');
     const depth = '  ';
     for (final m in members) {
diff --git a/lib/src/code_generator/struct.dart b/lib/src/code_generator/struct.dart
index c65e04b..ae9e35b 100644
--- a/lib/src/code_generator/struct.dart
+++ b/lib/src/code_generator/struct.dart
@@ -16,7 +16,7 @@
 /// ```
 /// The generated dart code is -
 /// ```dart
-/// class Struct extends ffi.Struct{
+/// final class Struct extends ffi.Struct {
 ///  @ffi.Int32()
 ///  int a;
 ///
diff --git a/lib/src/code_generator/union.dart b/lib/src/code_generator/union.dart
index fc7be96..8455004 100644
--- a/lib/src/code_generator/union.dart
+++ b/lib/src/code_generator/union.dart
@@ -15,7 +15,7 @@
 /// ```
 /// The generated dart code is -
 /// ```dart
-/// class Union extends ffi.Union{
+/// final class Union extends ffi.Union{
 ///  @ffi.Int32()
 ///  int a;
 ///
diff --git a/lib/src/header_parser/clang_bindings/clang_bindings.dart b/lib/src/header_parser/clang_bindings/clang_bindings.dart
index 6b77794..4c4c472 100644
--- a/lib/src/header_parser/clang_bindings/clang_bindings.dart
+++ b/lib/src/header_parser/clang_bindings/clang_bindings.dart
@@ -1310,21 +1310,21 @@
 /// the ownership of that string might differ from one call to the next.
 /// Use \c clang_getCString() to retrieve the string data and, once finished
 /// with the string data, call \c clang_disposeString() to free the string.
-class CXString extends ffi.Struct {
+final class CXString extends ffi.Struct {
   external ffi.Pointer<ffi.Void> data;
 
   @ffi.UnsignedInt()
   external int private_flags;
 }
 
-class CXTranslationUnitImpl extends ffi.Opaque {}
+final class CXTranslationUnitImpl extends ffi.Opaque {}
 
 /// Provides the contents of a file that has not yet been saved to disk.
 ///
 /// Each CXUnsavedFile instance provides the name of a file on the
 /// system along with the current contents of that file that have not
 /// yet been saved to disk.
-class CXUnsavedFile extends ffi.Struct {
+final class CXUnsavedFile extends ffi.Struct {
   /// The file whose contents have not yet been saved.
   ///
   /// This file must already exist in the file system.
@@ -1350,7 +1350,7 @@
 ///
 /// Use clang_getExpansionLocation() or clang_getSpellingLocation()
 /// to map a source location to a particular file, line, and column.
-class CXSourceLocation extends ffi.Struct {
+final class CXSourceLocation extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -1362,7 +1362,7 @@
 ///
 /// Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
 /// starting and end locations from a source range, respectively.
-class CXSourceRange extends ffi.Struct {
+final class CXSourceRange extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -2356,7 +2356,7 @@
 /// translation unit. clang_getCursor() maps from a physical source location
 /// to the entity that resides at that location, allowing one to map from the
 /// source code into the AST.
-class CXCursor extends ffi.Struct {
+final class CXCursor extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -2498,7 +2498,7 @@
 }
 
 /// The type of an element in the abstract syntax tree.
-class CXType extends ffi.Struct {
+final class CXType extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
diff --git a/lib/src/header_parser/type_extractor/extractor.dart b/lib/src/header_parser/type_extractor/extractor.dart
index c6a0951..5b2620b 100644
--- a/lib/src/header_parser/type_extractor/extractor.dart
+++ b/lib/src/header_parser/type_extractor/extractor.dart
@@ -117,13 +117,13 @@
       // Primarily used for function types with zero arguments.
       return _extractFromFunctionProto(cxtype, cursor: originalCursor);
     case clang_types.CXTypeKind
-        .CXType_ConstantArray: // Primarily used for constant array in struct members.
+          .CXType_ConstantArray: // Primarily used for constant array in struct members.
       return ConstantArray(
         clang.clang_getNumElements(cxtype),
         clang.clang_getArrayElementType(cxtype).toCodeGenType(),
       );
     case clang_types.CXTypeKind
-        .CXType_IncompleteArray: // Primarily used for incomplete array in function parameters.
+          .CXType_IncompleteArray: // Primarily used for incomplete array in function parameters.
       return IncompleteArray(
         clang.clang_getArrayElementType(cxtype).toCodeGenType(),
       );
diff --git a/pubspec.yaml b/pubspec.yaml
index 6c2e147..53dc9f2 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,12 +3,12 @@
 # BSD-style license that can be found in the LICENSE file.
 
 name: ffigen
-version: 7.2.10
+version: 8.0.0-dev.0
 description: Generator for FFI bindings, using LibClang to parse C header files.
 repository: https://github.com/dart-lang/ffigen
 
 environment:
-  sdk: '>=2.17.0 <4.0.0'
+  sdk: ">=3.0.0-417.0.dev <4.0.0"
 
 dependencies:
   ffi: ^2.0.1
diff --git a/test/code_generator_tests/expected_bindings/_expected_boolean_dartbool_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_boolean_dartbool_bindings.dart
index 0bc046c..015821e 100644
--- a/test/code_generator_tests/expected_bindings/_expected_boolean_dartbool_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_boolean_dartbool_bindings.dart
@@ -35,7 +35,7 @@
       _test1Ptr.asFunction<bool Function(bool, ffi.Pointer<ffi.Bool>)>();
 }
 
-class Test2 extends ffi.Struct {
+final class Test2 extends ffi.Struct {
   @ffi.Bool()
   external bool a;
 }
diff --git a/test/code_generator_tests/expected_bindings/_expected_function_n_struct_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_function_n_struct_bindings.dart
index cad1980..cf255b2 100644
--- a/test/code_generator_tests/expected_bindings/_expected_function_n_struct_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_function_n_struct_bindings.dart
@@ -34,7 +34,7 @@
       ffi.Pointer<SomeStruct> Function(ffi.Pointer<ffi.Pointer<SomeStruct>>)>();
 }
 
-class SomeStruct extends ffi.Struct {
+final class SomeStruct extends ffi.Struct {
   @ffi.Int32()
   external int a;
 
diff --git a/test/code_generator_tests/expected_bindings/_expected_global_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_global_bindings.dart
index f3f3f12..37081b8 100644
--- a/test/code_generator_tests/expected_bindings/_expected_global_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_global_bindings.dart
@@ -44,6 +44,6 @@
   ffi.Pointer<EmptyStruct> get globalStruct => _globalStruct;
 }
 
-class Some extends ffi.Opaque {}
+final class Some extends ffi.Opaque {}
 
-class EmptyStruct extends ffi.Opaque {}
+final class EmptyStruct extends ffi.Opaque {}
diff --git a/test/code_generator_tests/expected_bindings/_expected_internal_conflict_resolution_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_internal_conflict_resolution_bindings.dart
index edc3935..1a71e3b 100644
--- a/test/code_generator_tests/expected_bindings/_expected_internal_conflict_resolution_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_internal_conflict_resolution_bindings.dart
@@ -62,12 +62,12 @@
   late final _Test = _TestPtr.asFunction<void Function()>();
 }
 
-class _Test extends ffi.Struct {
+final class _Test extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Int8> array;
 }
 
-class ArrayHelperPrefixCollisionTest extends ffi.Opaque {}
+final class ArrayHelperPrefixCollisionTest extends ffi.Opaque {}
 
 abstract class _c_Test {}
 
diff --git a/test/code_generator_tests/expected_bindings/_expected_packed_structs_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_packed_structs_bindings.dart
index e703e28..f882e7e 100644
--- a/test/code_generator_tests/expected_bindings/_expected_packed_structs_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_packed_structs_bindings.dart
@@ -4,37 +4,37 @@
 // ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
-class NoPacking extends ffi.Struct {
+final class NoPacking extends ffi.Struct {
   @ffi.Uint8()
   external int a;
 }
 
 @ffi.Packed(1)
-class Pack1 extends ffi.Struct {
+final class Pack1 extends ffi.Struct {
   @ffi.Uint8()
   external int a;
 }
 
 @ffi.Packed(2)
-class Pack2 extends ffi.Struct {
+final class Pack2 extends ffi.Struct {
   @ffi.Uint8()
   external int a;
 }
 
 @ffi.Packed(4)
-class Pack21 extends ffi.Struct {
+final class Pack21 extends ffi.Struct {
   @ffi.Uint8()
   external int a;
 }
 
 @ffi.Packed(8)
-class Pack22 extends ffi.Struct {
+final class Pack22 extends ffi.Struct {
   @ffi.Uint8()
   external int a;
 }
 
 @ffi.Packed(16)
-class Pack16 extends ffi.Struct {
+final class Pack16 extends ffi.Struct {
   @ffi.Uint8()
   external int a;
 }
diff --git a/test/code_generator_tests/expected_bindings/_expected_sort_bindings_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_sort_bindings_bindings.dart
index 3a9aa67..eddeeb7 100644
--- a/test/code_generator_tests/expected_bindings/_expected_sort_bindings_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_sort_bindings_bindings.dart
@@ -33,6 +33,6 @@
   late final _b = _bPtr.asFunction<void Function()>();
 }
 
-class C extends ffi.Opaque {}
+final class C extends ffi.Opaque {}
 
-class D extends ffi.Opaque {}
+final class D extends ffi.Opaque {}
diff --git a/test/code_generator_tests/expected_bindings/_expected_struct_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_struct_bindings.dart
index f8482e7..b7a4e9d 100644
--- a/test/code_generator_tests/expected_bindings/_expected_struct_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_struct_bindings.dart
@@ -6,9 +6,9 @@
 
 /// Just a test struct
 /// heres another line
-class NoMember extends ffi.Opaque {}
+final class NoMember extends ffi.Opaque {}
 
-class WithPrimitiveMember extends ffi.Struct {
+final class WithPrimitiveMember extends ffi.Struct {
   @ffi.Int32()
   external int a;
 
@@ -19,7 +19,7 @@
   external int c;
 }
 
-class WithPointerMember extends ffi.Struct {
+final class WithPointerMember extends ffi.Struct {
   external ffi.Pointer<ffi.Int32> a;
 
   external ffi.Pointer<ffi.Pointer<ffi.Double>> b;
@@ -28,7 +28,7 @@
   external int c;
 }
 
-class WithIntPtrUintPtr extends ffi.Struct {
+final class WithIntPtrUintPtr extends ffi.Struct {
   external ffi.Pointer<ffi.UintPtr> a;
 
   external ffi.Pointer<ffi.Pointer<ffi.IntPtr>> b;
diff --git a/test/code_generator_tests/expected_bindings/_expected_typealias_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_typealias_bindings.dart
index 00306c6..4383756 100644
--- a/test/code_generator_tests/expected_bindings/_expected_typealias_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_typealias_bindings.dart
@@ -39,19 +39,19 @@
 
 typedef RawUnused = Struct1;
 
-class Struct1 extends ffi.Opaque {}
+final class Struct1 extends ffi.Opaque {}
 
-class WithTypealiasStruct extends ffi.Struct {
+final class WithTypealiasStruct extends ffi.Struct {
   external Struct2Typealias t;
 }
 
 typedef Struct2Typealias = Struct2;
 
-class Struct2 extends ffi.Struct {
+final class Struct2 extends ffi.Struct {
   @ffi.Double()
   external double a;
 }
 
 typedef Struct3Typealias = Struct3;
 
-class Struct3 extends ffi.Opaque {}
+final class Struct3 extends ffi.Opaque {}
diff --git a/test/code_generator_tests/expected_bindings/_expected_unions_bindings.dart b/test/code_generator_tests/expected_bindings/_expected_unions_bindings.dart
index 1865919..692f0d6 100644
--- a/test/code_generator_tests/expected_bindings/_expected_unions_bindings.dart
+++ b/test/code_generator_tests/expected_bindings/_expected_unions_bindings.dart
@@ -4,19 +4,19 @@
 // ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
-class Struct1 extends ffi.Struct {
+final class Struct1 extends ffi.Struct {
   @ffi.Char()
   external int a;
 }
 
-class Union1 extends ffi.Union {
+final class Union1 extends ffi.Union {
   @ffi.Char()
   external int a;
 }
 
-class EmptyUnion extends ffi.Opaque {}
+final class EmptyUnion extends ffi.Opaque {}
 
-class Primitives extends ffi.Union {
+final class Primitives extends ffi.Union {
   @ffi.Char()
   external int a;
 
@@ -30,7 +30,7 @@
   external double d;
 }
 
-class PrimitivesWithPointers extends ffi.Union {
+final class PrimitivesWithPointers extends ffi.Union {
   @ffi.Char()
   external int a;
 
@@ -44,7 +44,7 @@
   external ffi.Pointer<Struct1> d1;
 }
 
-class WithArray extends ffi.Union {
+final class WithArray extends ffi.Union {
   @ffi.Array.multi([10])
   external ffi.Array<ffi.Char> a;
 
diff --git a/test/collision_tests/expected_bindings/_expected_decl_symbol_address_collision_bindings.dart b/test/collision_tests/expected_bindings/_expected_decl_symbol_address_collision_bindings.dart
index 3b3e791..0d5473f 100644
--- a/test/collision_tests/expected_bindings/_expected_decl_symbol_address_collision_bindings.dart
+++ b/test/collision_tests/expected_bindings/_expected_decl_symbol_address_collision_bindings.dart
@@ -50,9 +50,9 @@
       _library1.__SymbolAddresses_1Ptr;
 }
 
-class addresses extends ffi.Opaque {}
+final class addresses extends ffi.Opaque {}
 
-class _SymbolAddresses extends ffi.Opaque {}
+final class _SymbolAddresses extends ffi.Opaque {}
 
 abstract class Bindings {}
 
diff --git a/test/collision_tests/expected_bindings/_expected_decl_type_name_collision_bindings.dart b/test/collision_tests/expected_bindings/_expected_decl_type_name_collision_bindings.dart
index f7207cf..625c69a 100644
--- a/test/collision_tests/expected_bindings/_expected_decl_type_name_collision_bindings.dart
+++ b/test/collision_tests/expected_bindings/_expected_decl_type_name_collision_bindings.dart
@@ -6,12 +6,12 @@
 // ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
-class A extends ffi.Struct {
+final class A extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class B extends ffi.Struct {
+final class B extends ffi.Struct {
   @ffi.Int()
   external int B1;
 
@@ -19,13 +19,13 @@
   external int A;
 }
 
-class C extends ffi.Struct {
+final class C extends ffi.Struct {
   external A A1;
 
   external B B1;
 }
 
-class D extends ffi.Struct {
+final class D extends ffi.Struct {
   external B A1;
 
   external A B1;
diff --git a/test/header_parser_tests/expected_bindings/_expected_comment_markup_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_comment_markup_bindings.dart
index ea88b5b..0575478 100644
--- a/test/header_parser_tests/expected_bindings/_expected_comment_markup_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_comment_markup_bindings.dart
@@ -52,7 +52,7 @@
 }
 
 /// Test comment for struct.
-class Com4 extends ffi.Struct {
+final class Com4 extends ffi.Struct {
   /// Muli-line test comment for struct field
   /// With multiple line and both // and ///.
   @ffi.Int()
diff --git a/test/header_parser_tests/expected_bindings/_expected_dart_handle_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_dart_handle_bindings.dart
index f51bf57..8455b7a 100644
--- a/test/header_parser_tests/expected_bindings/_expected_dart_handle_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_dart_handle_bindings.dart
@@ -71,8 +71,8 @@
 typedef Typedef1
     = ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Handle)>>;
 
-class Struct1 extends ffi.Opaque {}
+final class Struct1 extends ffi.Opaque {}
 
-class Struct2 extends ffi.Struct {
+final class Struct2 extends ffi.Struct {
   external ffi.Pointer<ffi.Handle> h;
 }
diff --git a/test/header_parser_tests/expected_bindings/_expected_forward_decl_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_forward_decl_bindings.dart
index 81cb2e3..f1175cc 100644
--- a/test/header_parser_tests/expected_bindings/_expected_forward_decl_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_forward_decl_bindings.dart
@@ -36,7 +36,7 @@
   late final _func = _funcPtr.asFunction<void Function(ffi.Pointer<A>, int)>();
 }
 
-class A extends ffi.Struct {
+final class A extends ffi.Struct {
   @ffi.Int()
   external int a;
 
diff --git a/test/header_parser_tests/expected_bindings/_expected_native_func_typedef_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_native_func_typedef_bindings.dart
index 6ef30ff..f77a57b 100644
--- a/test/header_parser_tests/expected_bindings/_expected_native_func_typedef_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_native_func_typedef_bindings.dart
@@ -64,7 +64,7 @@
       _funcWithNativeFuncPtr.asFunction<void Function(WithTypedefReturnType)>();
 }
 
-class Struct extends ffi.Struct {
+final class Struct extends ffi.Struct {
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Void Function(
@@ -76,7 +76,7 @@
     = ffi.Pointer<ffi.NativeFunction<InsideReturnType Function()>>;
 typedef InsideReturnType = ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>;
 
-class Struct2 extends ffi.Struct {
+final class Struct2 extends ffi.Struct {
   external VoidFuncPointer constFuncPointer;
 }
 
diff --git a/test/header_parser_tests/expected_bindings/_expected_opaque_dependencies_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_opaque_dependencies_bindings.dart
index c53f04f..6481420 100644
--- a/test/header_parser_tests/expected_bindings/_expected_opaque_dependencies_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_opaque_dependencies_bindings.dart
@@ -51,36 +51,36 @@
 
 typedef BAlias = B;
 
-class B extends ffi.Opaque {}
+final class B extends ffi.Opaque {}
 
-class A extends ffi.Opaque {}
+final class A extends ffi.Opaque {}
 
-class E extends ffi.Struct {
+final class E extends ffi.Struct {
   external ffi.Pointer<C> c;
 
   external D d;
 }
 
-class C extends ffi.Opaque {}
+final class C extends ffi.Opaque {}
 
-class D extends ffi.Struct {
+final class D extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
-class UB extends ffi.Opaque {}
+final class UB extends ffi.Opaque {}
 
-class UA extends ffi.Opaque {}
+final class UA extends ffi.Opaque {}
 
-class UE extends ffi.Union {
+final class UE extends ffi.Union {
   external ffi.Pointer<UC> c;
 
   external UD d;
 }
 
-class UC extends ffi.Opaque {}
+final class UC extends ffi.Opaque {}
 
-class UD extends ffi.Union {
+final class UD extends ffi.Union {
   @ffi.Int()
   external int a;
 }
diff --git a/test/header_parser_tests/expected_bindings/_expected_packed_structs_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_packed_structs_bindings.dart
index 9dfabd2..dc2ea75 100644
--- a/test/header_parser_tests/expected_bindings/_expected_packed_structs_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_packed_structs_bindings.dart
@@ -4,13 +4,13 @@
 // ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
-class NormalStruct1 extends ffi.Struct {
+final class NormalStruct1 extends ffi.Struct {
   @ffi.Char()
   external int a;
 }
 
 /// Should not be packed.
-class StructWithAttr extends ffi.Struct {
+final class StructWithAttr extends ffi.Struct {
   external ffi.Pointer<ffi.Int> a;
 
   external ffi.Pointer<ffi.Int> b;
@@ -18,33 +18,33 @@
 
 /// Should be packed with 1.
 @ffi.Packed(1)
-class PackedAttr extends ffi.Struct {
+final class PackedAttr extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
 /// Should be packed with 8.
 @ffi.Packed(8)
-class PackedAttrAlign8 extends ffi.Struct {
+final class PackedAttrAlign8 extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
 /// Should be packed with 2.
 @ffi.Packed(2)
-class Pack2WithPragma extends ffi.Struct {
+final class Pack2WithPragma extends ffi.Struct {
   @ffi.Int()
   external int a;
 }
 
 /// Should be packed with 4.
 @ffi.Packed(4)
-class Pack4WithPragma extends ffi.Struct {
+final class Pack4WithPragma extends ffi.Struct {
   @ffi.LongLong()
   external int a;
 }
 
-class NormalStruct2 extends ffi.Struct {
+final class NormalStruct2 extends ffi.Struct {
   @ffi.Char()
   external int a;
 }
diff --git a/test/header_parser_tests/expected_bindings/_expected_struct_fptr_fields_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_struct_fptr_fields_bindings.dart
index b0490b2..2b2fe8a 100644
--- a/test/header_parser_tests/expected_bindings/_expected_struct_fptr_fields_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_struct_fptr_fields_bindings.dart
@@ -4,7 +4,7 @@
 // ignore_for_file: type=lint
 import 'dart:ffi' as ffi;
 
-class S extends ffi.Struct {
+final class S extends ffi.Struct {
   external ffi.Pointer<ffi.NativeFunction<ffi.Int Function()>> func1;
 
   external ffi
diff --git a/test/header_parser_tests/expected_bindings/_expected_typedef_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_typedef_bindings.dart
index 412acb2..b880746 100644
--- a/test/header_parser_tests/expected_bindings/_expected_typedef_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_typedef_bindings.dart
@@ -84,7 +84,7 @@
       _func4Ptr.asFunction<bool Function(ffi.Pointer<ffi.Bool>)>();
 }
 
-class Struct1 extends ffi.Struct {
+final class Struct1 extends ffi.Struct {
   external NamedFunctionProto named;
 
   external ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> unnamed;
@@ -93,14 +93,14 @@
 typedef NamedFunctionProto
     = ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>;
 
-class AnonymousStructInTypedef extends ffi.Opaque {}
+final class AnonymousStructInTypedef extends ffi.Opaque {}
 
-class _NamedStructInTypedef extends ffi.Opaque {}
+final class _NamedStructInTypedef extends ffi.Opaque {}
 
 typedef NTyperef1 = ExcludedStruct;
 typedef ExcludedStruct = _ExcludedStruct;
 
-class _ExcludedStruct extends ffi.Opaque {}
+final class _ExcludedStruct extends ffi.Opaque {}
 
 abstract class AnonymousEnumInTypedef {
   static const int a = 0;
@@ -112,9 +112,9 @@
 
 typedef NestingASpecifiedType = ffi.IntPtr;
 
-class Struct2 extends ffi.Opaque {}
+final class Struct2 extends ffi.Opaque {}
 
-class WithBoolAlias extends ffi.Struct {
+final class WithBoolAlias extends ffi.Struct {
   @ffi.Bool()
   external bool b;
 }
diff --git a/test/header_parser_tests/expected_bindings/_expected_unions_bindings.dart b/test/header_parser_tests/expected_bindings/_expected_unions_bindings.dart
index 585ab9a..ca7a938 100644
--- a/test/header_parser_tests/expected_bindings/_expected_unions_bindings.dart
+++ b/test/header_parser_tests/expected_bindings/_expected_unions_bindings.dart
@@ -49,17 +49,17 @@
       _func2Ptr.asFunction<void Function(ffi.Pointer<Union3>)>();
 }
 
-class Union1 extends ffi.Union {
+final class Union1 extends ffi.Union {
   @ffi.Int()
   external int a;
 }
 
-class Union2 extends ffi.Union {
+final class Union2 extends ffi.Union {
   external Union1 a;
 }
 
-class Union3 extends ffi.Opaque {}
+final class Union3 extends ffi.Opaque {}
 
-class Union4 extends ffi.Opaque {}
+final class Union4 extends ffi.Opaque {}
 
-class Union5 extends ffi.Opaque {}
+final class Union5 extends ffi.Opaque {}
diff --git a/test/large_integration_tests/_expected_cjson_bindings.dart b/test/large_integration_tests/_expected_cjson_bindings.dart
index fe6b008..b93c74f 100644
--- a/test/large_integration_tests/_expected_cjson_bindings.dart
+++ b/test/large_integration_tests/_expected_cjson_bindings.dart
@@ -1215,7 +1215,7 @@
       _cJSON_freePtr.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
 }
 
-class cJSON extends ffi.Struct {
+final class cJSON extends ffi.Struct {
   external ffi.Pointer<cJSON> next;
 
   external ffi.Pointer<cJSON> prev;
@@ -1236,7 +1236,7 @@
   external ffi.Pointer<ffi.Char> string;
 }
 
-class cJSON_Hooks extends ffi.Struct {
+final class cJSON_Hooks extends ffi.Struct {
   external ffi.Pointer<
           ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Size sz)>>
       malloc_fn;
diff --git a/test/large_integration_tests/_expected_libclang_bindings.dart b/test/large_integration_tests/_expected_libclang_bindings.dart
index 510e0b0..22c6f26 100644
--- a/test/large_integration_tests/_expected_libclang_bindings.dart
+++ b/test/large_integration_tests/_expected_libclang_bindings.dart
@@ -6036,37 +6036,37 @@
 }
 
 /// A character string.
-class CXString extends ffi.Struct {
+final class CXString extends ffi.Struct {
   external ffi.Pointer<ffi.Void> data;
 
   @ffi.UnsignedInt()
   external int private_flags;
 }
 
-class CXStringSet extends ffi.Struct {
+final class CXStringSet extends ffi.Struct {
   external ffi.Pointer<CXString> Strings;
 
   @ffi.UnsignedInt()
   external int Count;
 }
 
-class CXVirtualFileOverlayImpl extends ffi.Opaque {}
+final class CXVirtualFileOverlayImpl extends ffi.Opaque {}
 
 /// Object encapsulating information about overlaying virtual file/directories
 /// over the real file system.
 typedef CXVirtualFileOverlay = ffi.Pointer<CXVirtualFileOverlayImpl>;
 
-class CXModuleMapDescriptorImpl extends ffi.Opaque {}
+final class CXModuleMapDescriptorImpl extends ffi.Opaque {}
 
 /// Object encapsulating information about a module.map file.
 typedef CXModuleMapDescriptor = ffi.Pointer<CXModuleMapDescriptorImpl>;
 
-class CXTargetInfoImpl extends ffi.Opaque {}
+final class CXTargetInfoImpl extends ffi.Opaque {}
 
-class CXTranslationUnitImpl extends ffi.Opaque {}
+final class CXTranslationUnitImpl extends ffi.Opaque {}
 
 /// Provides the contents of a file that has not yet been saved to disk.
-class CXUnsavedFile extends ffi.Struct {
+final class CXUnsavedFile extends ffi.Struct {
   /// The file whose contents have not yet been saved.
   external ffi.Pointer<ffi.Char> Filename;
 
@@ -6098,7 +6098,7 @@
 }
 
 /// Describes a version number of the form major.minor.subminor.
-class CXVersion extends ffi.Struct {
+final class CXVersion extends ffi.Struct {
   /// The major version number, e.g., the '10' in '10.7.3'. A negative value
   /// indicates that there is no version number at all.
   @ffi.Int()
@@ -6175,7 +6175,7 @@
 
 /// Uniquely identifies a CXFile, that refers to the same underlying file,
 /// across an indexing session.
-class CXFileUniqueID extends ffi.Struct {
+final class CXFileUniqueID extends ffi.Struct {
   @ffi.Array.multi([3])
   external ffi.Array<ffi.UnsignedLongLong> data;
 }
@@ -6184,7 +6184,7 @@
 typedef CXTranslationUnit = ffi.Pointer<CXTranslationUnitImpl>;
 
 /// Identifies a specific source location within a translation unit.
-class CXSourceLocation extends ffi.Struct {
+final class CXSourceLocation extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -6193,7 +6193,7 @@
 }
 
 /// Identifies a half-open character range in the source code.
-class CXSourceRange extends ffi.Struct {
+final class CXSourceRange extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -6205,7 +6205,7 @@
 }
 
 /// Identifies an array of ranges.
-class CXSourceRangeList extends ffi.Struct {
+final class CXSourceRangeList extends ffi.Struct {
   /// The number of ranges in the ranges array.
   @ffi.UnsignedInt()
   external int count;
@@ -6399,7 +6399,7 @@
   static const int CXTUResourceUsage_Last = 14;
 }
 
-class CXTUResourceUsageEntry extends ffi.Struct {
+final class CXTUResourceUsageEntry extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -6408,7 +6408,7 @@
 }
 
 /// The memory usage of a CXTranslationUnit, broken into categories.
-class CXTUResourceUsage extends ffi.Struct {
+final class CXTUResourceUsage extends ffi.Struct {
   external ffi.Pointer<ffi.Void> data;
 
   @ffi.UnsignedInt()
@@ -7074,7 +7074,7 @@
 
 /// A cursor representing some element in the abstract syntax tree for a
 /// translation unit.
-class CXCursor extends ffi.Struct {
+final class CXCursor extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -7123,7 +7123,7 @@
 
 /// Describes the availability of a given entity on a particular platform, e.g.,
 /// a particular class might only be available on Mac OS 10.7 or newer.
-class CXPlatformAvailability extends ffi.Struct {
+final class CXPlatformAvailability extends ffi.Struct {
   /// A string that describes the platform for which this structure provides
   /// availability information.
   external CXString Platform;
@@ -7164,7 +7164,7 @@
   static const int CXTLS_Static = 2;
 }
 
-class CXCursorSetImpl extends ffi.Opaque {}
+final class CXCursorSetImpl extends ffi.Opaque {}
 
 /// A fast container representing a set of CXCursors.
 typedef CXCursorSet = ffi.Pointer<CXCursorSetImpl>;
@@ -7321,7 +7321,7 @@
 }
 
 /// The type of an element in the abstract syntax tree.
-class CXType extends ffi.Struct {
+final class CXType extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -7538,7 +7538,7 @@
 }
 
 /// Describes a single preprocessing token.
-class CXToken extends ffi.Struct {
+final class CXToken extends ffi.Struct {
   @ffi.Array.multi([4])
   external ffi.Array<ffi.UnsignedInt> int_data;
 
@@ -7546,7 +7546,7 @@
 }
 
 /// A single result of code completion.
-class CXCompletionResult extends ffi.Struct {
+final class CXCompletionResult extends ffi.Struct {
   /// The kind of entity that this completion refers to.
   @ffi.Int32()
   external int CursorKind;
@@ -7633,7 +7633,7 @@
 }
 
 /// Contains the results of code-completion.
-class CXCodeCompleteResults extends ffi.Struct {
+final class CXCodeCompleteResults extends ffi.Struct {
   /// The code-completion results.
   external ffi.Pointer<CXCompletionResult> Results;
 
@@ -7791,7 +7791,7 @@
   static const int CXVisit_Continue = 1;
 }
 
-class CXCursorAndRangeVisitor extends ffi.Struct {
+final class CXCursorAndRangeVisitor extends ffi.Struct {
   external ffi.Pointer<ffi.Void> context;
 
   external ffi.Pointer<
@@ -7812,7 +7812,7 @@
 }
 
 /// Source location passed to index callbacks.
-class CXIdxLoc extends ffi.Struct {
+final class CXIdxLoc extends ffi.Struct {
   @ffi.Array.multi([2])
   external ffi.Array<ffi.Pointer<ffi.Void>> ptr_data;
 
@@ -7821,7 +7821,7 @@
 }
 
 /// Data for ppIncludedFile callback.
-class CXIdxIncludedFileInfo extends ffi.Struct {
+final class CXIdxIncludedFileInfo extends ffi.Struct {
   /// Location of '#' in the #include/#import directive.
   external CXIdxLoc hashLoc;
 
@@ -7843,7 +7843,7 @@
 }
 
 /// Data for IndexerCallbacks#importedASTFile.
-class CXIdxImportedASTFileInfo extends ffi.Struct {
+final class CXIdxImportedASTFileInfo extends ffi.Struct {
   /// Top level AST file containing the imported PCH, module or submodule.
   external CXFile file;
 
@@ -7915,7 +7915,7 @@
   static const int CXIdxAttr_IBOutletCollection = 3;
 }
 
-class CXIdxAttrInfo extends ffi.Struct {
+final class CXIdxAttrInfo extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -7924,7 +7924,7 @@
   external CXIdxLoc loc;
 }
 
-class CXIdxEntityInfo extends ffi.Struct {
+final class CXIdxEntityInfo extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -7946,11 +7946,11 @@
   external int numAttributes;
 }
 
-class CXIdxContainerInfo extends ffi.Struct {
+final class CXIdxContainerInfo extends ffi.Struct {
   external CXCursor cursor;
 }
 
-class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct {
+final class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxAttrInfo> attrInfo;
 
   external ffi.Pointer<CXIdxEntityInfo> objcClass;
@@ -7964,7 +7964,7 @@
   static const int CXIdxDeclFlag_Skipped = 1;
 }
 
-class CXIdxDeclInfo extends ffi.Struct {
+final class CXIdxDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxEntityInfo> entityInfo;
 
   external CXCursor cursor;
@@ -8008,14 +8008,14 @@
   static const int CXIdxObjCContainer_Implementation = 2;
 }
 
-class CXIdxObjCContainerDeclInfo extends ffi.Struct {
+final class CXIdxObjCContainerDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxDeclInfo> declInfo;
 
   @ffi.Int32()
   external int kind;
 }
 
-class CXIdxBaseClassInfo extends ffi.Struct {
+final class CXIdxBaseClassInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxEntityInfo> base;
 
   external CXCursor cursor;
@@ -8023,7 +8023,7 @@
   external CXIdxLoc loc;
 }
 
-class CXIdxObjCProtocolRefInfo extends ffi.Struct {
+final class CXIdxObjCProtocolRefInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxEntityInfo> protocol;
 
   external CXCursor cursor;
@@ -8031,14 +8031,14 @@
   external CXIdxLoc loc;
 }
 
-class CXIdxObjCProtocolRefListInfo extends ffi.Struct {
+final class CXIdxObjCProtocolRefListInfo extends ffi.Struct {
   external ffi.Pointer<ffi.Pointer<CXIdxObjCProtocolRefInfo>> protocols;
 
   @ffi.UnsignedInt()
   external int numProtocols;
 }
 
-class CXIdxObjCInterfaceDeclInfo extends ffi.Struct {
+final class CXIdxObjCInterfaceDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxObjCContainerDeclInfo> containerInfo;
 
   external ffi.Pointer<CXIdxBaseClassInfo> superInfo;
@@ -8046,7 +8046,7 @@
   external ffi.Pointer<CXIdxObjCProtocolRefListInfo> protocols;
 }
 
-class CXIdxObjCCategoryDeclInfo extends ffi.Struct {
+final class CXIdxObjCCategoryDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxObjCContainerDeclInfo> containerInfo;
 
   external ffi.Pointer<CXIdxEntityInfo> objcClass;
@@ -8058,7 +8058,7 @@
   external ffi.Pointer<CXIdxObjCProtocolRefListInfo> protocols;
 }
 
-class CXIdxObjCPropertyDeclInfo extends ffi.Struct {
+final class CXIdxObjCPropertyDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxDeclInfo> declInfo;
 
   external ffi.Pointer<CXIdxEntityInfo> getter;
@@ -8066,7 +8066,7 @@
   external ffi.Pointer<CXIdxEntityInfo> setter;
 }
 
-class CXIdxCXXClassDeclInfo extends ffi.Struct {
+final class CXIdxCXXClassDeclInfo extends ffi.Struct {
   external ffi.Pointer<CXIdxDeclInfo> declInfo;
 
   external ffi.Pointer<ffi.Pointer<CXIdxBaseClassInfo>> bases;
@@ -8100,7 +8100,7 @@
 }
 
 /// Data for IndexerCallbacks#indexEntityReference.
-class CXIdxEntityRefInfo extends ffi.Struct {
+final class CXIdxEntityRefInfo extends ffi.Struct {
   @ffi.Int32()
   external int kind;
 
@@ -8125,7 +8125,7 @@
 
 /// A group of callbacks used by #clang_indexSourceFile and
 /// #clang_indexTranslationUnit.
-class IndexerCallbacks extends ffi.Struct {
+final class IndexerCallbacks extends ffi.Struct {
   /// Called periodically to check whether indexing should be aborted. Should
   /// return 0 to continue, and non-zero to abort.
   external ffi.Pointer<
diff --git a/test/large_integration_tests/_expected_sqlite_bindings.dart b/test/large_integration_tests/_expected_sqlite_bindings.dart
index d3b48db..af6cccf 100644
--- a/test/large_integration_tests/_expected_sqlite_bindings.dart
+++ b/test/large_integration_tests/_expected_sqlite_bindings.dart
@@ -10718,20 +10718,20 @@
                       ffi.Void Function(ffi.Pointer<ffi.Void>)>>)>();
 }
 
-class sqlite3 extends ffi.Opaque {}
+final class sqlite3 extends ffi.Opaque {}
 
-class sqlite3_file extends ffi.Struct {
+final class sqlite3_file extends ffi.Struct {
   /// Methods for an open file
   external ffi.Pointer<sqlite3_io_methods> pMethods;
 }
 
-class sqlite3_io_methods extends ffi.Opaque {}
+final class sqlite3_io_methods extends ffi.Opaque {}
 
-class sqlite3_mutex extends ffi.Opaque {}
+final class sqlite3_mutex extends ffi.Opaque {}
 
-class sqlite3_api_routines extends ffi.Opaque {}
+final class sqlite3_api_routines extends ffi.Opaque {}
 
-class sqlite3_vfs extends ffi.Struct {
+final class sqlite3_vfs extends ffi.Struct {
   /// Structure version number (currently 3)
   @ffi.Int()
   external int iVersion;
@@ -10850,7 +10850,7 @@
 typedef sqlite3_syscall_ptr
     = ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>;
 
-class sqlite3_mem_methods extends ffi.Struct {
+final class sqlite3_mem_methods extends ffi.Struct {
   /// Memory allocation function
   external ffi
           .Pointer<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Int)>>
@@ -10892,11 +10892,11 @@
 typedef sqlite3_uint64 = sqlite_uint64;
 typedef sqlite_uint64 = ffi.UnsignedLongLong;
 
-class sqlite3_stmt extends ffi.Opaque {}
+final class sqlite3_stmt extends ffi.Opaque {}
 
-class sqlite3_value extends ffi.Opaque {}
+final class sqlite3_value extends ffi.Opaque {}
 
-class sqlite3_context extends ffi.Opaque {}
+final class sqlite3_context extends ffi.Opaque {}
 
 /// CAPI3REF: Virtual Table Instance Object
 /// KEYWORDS: sqlite3_vtab
@@ -10914,7 +10914,7 @@
 /// prior to assigning a new string to zErrMsg.  ^After the error message
 /// is delivered up to the client application, the string will be automatically
 /// freed by sqlite3_free() and the zErrMsg field will be zeroed.
-class sqlite3_vtab extends ffi.Struct {
+final class sqlite3_vtab extends ffi.Struct {
   /// The module for this virtual table
   external ffi.Pointer<sqlite3_module> pModule;
 
@@ -10940,7 +10940,7 @@
 /// module or until the [database connection] closes.  The content
 /// of this structure must not change while it is registered with
 /// any database connection.
-class sqlite3_module extends ffi.Struct {
+final class sqlite3_module extends ffi.Struct {
   @ffi.Int()
   external int iVersion;
 
@@ -11181,7 +11181,7 @@
 /// It may therefore only be used if
 /// sqlite3_libversion_number() returns a value greater than or equal to
 /// 3009000.
-class sqlite3_index_info extends ffi.Struct {
+final class sqlite3_index_info extends ffi.Struct {
   /// Number of entries in aConstraint
   @ffi.Int()
   external int nConstraint;
@@ -11230,7 +11230,7 @@
   external int colUsed;
 }
 
-class sqlite3_index_constraint extends ffi.Struct {
+final class sqlite3_index_constraint extends ffi.Struct {
   /// Column constrained.  -1 for ROWID
   @ffi.Int()
   external int iColumn;
@@ -11248,7 +11248,7 @@
   external int iTermOffset;
 }
 
-class sqlite3_index_orderby extends ffi.Struct {
+final class sqlite3_index_orderby extends ffi.Struct {
   /// Column number
   @ffi.Int()
   external int iColumn;
@@ -11259,7 +11259,7 @@
 }
 
 /// Outputs
-class sqlite3_index_constraint_usage extends ffi.Struct {
+final class sqlite3_index_constraint_usage extends ffi.Struct {
   /// if >0, constraint is part of argv to xFilter
   @ffi.Int()
   external int argvIndex;
@@ -11284,14 +11284,14 @@
 ///
 /// This superclass exists in order to define fields of the cursor that
 /// are common to all implementations.
-class sqlite3_vtab_cursor extends ffi.Struct {
+final class sqlite3_vtab_cursor extends ffi.Struct {
   /// Virtual table of this cursor
   external ffi.Pointer<sqlite3_vtab> pVtab;
 }
 
-class sqlite3_blob extends ffi.Opaque {}
+final class sqlite3_blob extends ffi.Opaque {}
 
-class sqlite3_mutex_methods extends ffi.Struct {
+final class sqlite3_mutex_methods extends ffi.Struct {
   external ffi.Pointer<ffi.NativeFunction<ffi.Int Function()>> xMutexInit;
 
   external ffi.Pointer<ffi.NativeFunction<ffi.Int Function()>> xMutexEnd;
@@ -11325,11 +11325,11 @@
       xMutexNotheld;
 }
 
-class sqlite3_str extends ffi.Opaque {}
+final class sqlite3_str extends ffi.Opaque {}
 
-class sqlite3_pcache extends ffi.Opaque {}
+final class sqlite3_pcache extends ffi.Opaque {}
 
-class sqlite3_pcache_page extends ffi.Struct {
+final class sqlite3_pcache_page extends ffi.Struct {
   /// The content of the page
   external ffi.Pointer<ffi.Void> pBuf;
 
@@ -11337,7 +11337,7 @@
   external ffi.Pointer<ffi.Void> pExtra;
 }
 
-class sqlite3_pcache_methods2 extends ffi.Struct {
+final class sqlite3_pcache_methods2 extends ffi.Struct {
   @ffi.Int()
   external int iVersion;
 
@@ -11396,7 +11396,7 @@
       xShrink;
 }
 
-class sqlite3_pcache_methods extends ffi.Struct {
+final class sqlite3_pcache_methods extends ffi.Struct {
   external ffi.Pointer<ffi.Void> pArg;
 
   external ffi
@@ -11446,7 +11446,7 @@
       xDestroy;
 }
 
-class sqlite3_backup extends ffi.Opaque {}
+final class sqlite3_backup extends ffi.Opaque {}
 
 /// CAPI3REF: Database Snapshot
 /// KEYWORDS: {snapshot} {sqlite3_snapshot}
@@ -11466,14 +11466,14 @@
 /// version of the database file so that it is possible to later open a new read
 /// transaction that sees that historical version of the database rather than
 /// the most recent version.
-class sqlite3_snapshot extends ffi.Struct {
+final class sqlite3_snapshot extends ffi.Struct {
   @ffi.Array.multi([48])
   external ffi.Array<ffi.UnsignedChar> hidden;
 }
 
 /// A pointer to a structure of the following type is passed as the first
 /// argument to callbacks registered using rtree_geometry_callback().
-class sqlite3_rtree_geometry extends ffi.Struct {
+final class sqlite3_rtree_geometry extends ffi.Struct {
   /// Copy of pContext passed to s_r_g_c()
   external ffi.Pointer<ffi.Void> pContext;
 
@@ -11502,7 +11502,7 @@
 /// Note that the first 5 fields of this structure are identical to
 /// sqlite3_rtree_geometry.  This structure is a subclass of
 /// sqlite3_rtree_geometry.
-class sqlite3_rtree_query_info extends ffi.Struct {
+final class sqlite3_rtree_query_info extends ffi.Struct {
   /// pContext from when function registered
   external ffi.Pointer<ffi.Void> pContext;
 
@@ -11772,7 +11772,7 @@
 ///
 /// xPhraseNextColumn()
 /// See xPhraseFirstColumn above.
-class Fts5ExtensionApi extends ffi.Struct {
+final class Fts5ExtensionApi extends ffi.Struct {
   /// Currently always set to 3
   @ffi.Int()
   external int iVersion;
@@ -11912,17 +11912,17 @@
               ffi.Pointer<ffi.Int>)>> xPhraseNextColumn;
 }
 
-class Fts5Context extends ffi.Opaque {}
+final class Fts5Context extends ffi.Opaque {}
 
-class Fts5PhraseIter extends ffi.Struct {
+final class Fts5PhraseIter extends ffi.Struct {
   external ffi.Pointer<ffi.UnsignedChar> a;
 
   external ffi.Pointer<ffi.UnsignedChar> b;
 }
 
-class Fts5Tokenizer extends ffi.Opaque {}
+final class Fts5Tokenizer extends ffi.Opaque {}
 
-class fts5_tokenizer extends ffi.Struct {
+final class fts5_tokenizer extends ffi.Struct {
   external ffi.Pointer<
       ffi.NativeFunction<
           ffi.Int Function(
@@ -11954,7 +11954,7 @@
                           ffi.Int)>>)>> xTokenize;
 }
 
-class fts5_api extends ffi.Struct {
+final class fts5_api extends ffi.Struct {
   /// Currently always set to 2
   @ffi.Int()
   external int iVersion;
diff --git a/test/native_test/native_test_bindings.dart b/test/native_test/native_test_bindings.dart
index d4a25d6..58934cf 100644
--- a/test/native_test/native_test_bindings.dart
+++ b/test/native_test/native_test_bindings.dart
@@ -244,7 +244,7 @@
       _Function1StructPassByValuePtr.asFunction<int Function(Struct3)>();
 }
 
-class Struct1 extends ffi.Struct {
+final class Struct1 extends ffi.Struct {
   @ffi.Int8()
   external int a;
 
@@ -252,7 +252,7 @@
   external ffi.Array<ffi.Array<ffi.Array<ffi.Int32>>> data;
 }
 
-class Struct3 extends ffi.Struct {
+final class Struct3 extends ffi.Struct {
   @ffi.Int()
   external int a;