Stable release: Update dependencies to sound null safety, minor changes. (#168)

Co-authored-by: Daco Harkes <dacoharkes@google.com>
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 7de66eb..d5e1f2d 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -13,14 +13,13 @@
   PUB_ENVIRONMENT: bot.github
 
 jobs:
-  # Check code formatting and static analysis on a single OS (linux)
-  # against Dart dev.
+  # Check code formatting and static analysis on a single OS (linux).
   analyze:
     runs-on: ubuntu-latest
     strategy:
       fail-fast: false
       matrix:
-        sdk: [2.12.0-237.0.dev] # TODO(127): Revert to stable.
+        sdk: [2.12.0-259.9.beta] # TODO(127): Revert to stable.
     steps:
       - uses: actions/checkout@v2
       - uses: dart-lang/setup-dart@v1.0
@@ -33,7 +32,7 @@
         run: dart format --output=none --set-exit-if-changed .
         if: always() && steps.install.outcome == 'success'
       - name: Analyze code
-        run: dart analyze # --fatal-infos # Removed till we stop using legacy libraries.
+        run: dart analyze --fatal-infos
         if: always() && steps.install.outcome == 'success'
 
   test:
@@ -44,7 +43,7 @@
       - uses: actions/checkout@v2
       - uses: dart-lang/setup-dart@v1.0
         with:
-          sdk: 2.12.0-237.0.dev # TODO(127): Revert to stable.
+          sdk: 2.12.0-259.9.beta # TODO(127): Revert to stable.
       - name: Install dependencies
         run: dart pub get
       - name: Install libclang-10-dev
@@ -52,7 +51,7 @@
       - name: Build test dylib
         run: cd test/native_test && dart build_test_dylib.dart && cd ../..
       - name: Run VM tests
-        run: dart --no-sound-null-safety test --platform vm
+        run: dart test --platform vm
       - name: Collect coverage
         run: ./tool/coverage.sh
       - name: Upload coverage
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a3cbb6..4ab98d4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 2.0.1
+- Switch to preview release of `package:quiver`.
+
+# 2.0.0
+- Upgraded all dependencies. `package:ffigen` now runs with sound null safety.
+
 # 2.0.0-dev.6
 - Functions marked `inline` are now skipped.
 
diff --git a/README.md b/README.md
index f2c194e..d531b4d 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@
 Configurations can be provided in 2 ways-
 1. In the project's `pubspec.yaml` file under the key `ffigen`.
 2. Via a custom YAML file, then specify this file while running -
-`pub run ffigen --config config.yaml`
+`dart run ffigen --config config.yaml`
 
 The following configuration options are available-
 <table>
@@ -391,15 +391,15 @@
 1. Multi OS support for types such as long. [Issue #7](https://github.com/dart-lang/ffigen/issues/7)
 
 ## Trying out examples
-1. `cd examples/<example_u_want_to_run>`, Run `pub get`.
-2. Run `pub run ffigen`.
+1. `cd examples/<example_u_want_to_run>`, Run `dart pub get`.
+2. Run `dart run ffigen`.
 
 ## Running Tests
 1. Dynamic library for some tests need to be built before running the examples.
   1. `cd test/native_test`.
   2. Run `dart build_test_dylib.dart`.
 
-Run tests from the root of the package with `pub run test`.
+Run tests from the root of the package with `dart run test`.
 > Note: If llvm is not installed in one of the default locations, tests may fail.
 ## FAQ
 ### Can ffigen be used for removing underscores or renaming declarations?
@@ -449,7 +449,7 @@
 ### How does ffigen handle C Strings?
 
 Ffigen treats `char*` just as any other pointer,(`Pointer<Int8>`).
-To convert these to/from `String`, you can use [package:ffi](https://pub.dev/packages/ffi) and use `Utf8.fromUtf8(ptr.cast())` to convert `char*` to dart `string`.
+To convert these to/from `String`, you can use [package:ffi](https://pub.dev/packages/ffi). Use `ptr.cast<Utf8>().toDartString()` to convert `char*` to dart `string` and `"str".toNativeUtf8()` to convert `string` to `char*`.
 ### How does ffigen handle C99 bool data type?
 
 Although `dart:ffi` doesn't have a NativeType for `bool`, they can be implemented as `Uint8`.
diff --git a/bin/ffigen.dart b/bin/ffigen.dart
index cfb482c..6156ed0 100644
--- a/bin/ffigen.dart
+++ b/bin/ffigen.dart
@@ -2,7 +2,5 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
-// TODO(128): Remove this when package can run with sound null safety.
-// @dart=2.7
 
 export 'package:ffigen/src/executables/ffigen.dart';
diff --git a/example/c_json/README.md b/example/c_json/README.md
index d689ce5..229d65b 100644
--- a/example/c_json/README.md
+++ b/example/c_json/README.md
@@ -15,7 +15,7 @@
 ## Generating bindings
 At the root of this example (`example/c_json`), run -
 ```
-pub run ffigen
+dart run ffigen
 ```
 This will generate bindings in a file: [cjson_generated_bindings.dart](./cjson_generated_bindings.dart)
 
diff --git a/example/c_json/main.dart b/example/c_json/main.dart
index fbd6f69..2774c31 100644
--- a/example/c_json/main.dart
+++ b/example/c_json/main.dart
@@ -18,7 +18,7 @@
   final jsonString = File('./example.json').readAsStringSync();
 
   // Parse this json string using our cJSON library.
-  final cjsonParsedJson = cjson.cJSON_Parse(Utf8.toUtf8(jsonString).cast());
+  final cjsonParsedJson = cjson.cJSON_Parse(jsonString.toNativeUtf8().cast());
   if (cjsonParsedJson == nullptr) {
     print('Error parsing cjson.');
     exit(1);
@@ -78,7 +78,7 @@
       ptr = ptr.ref.next;
     }
   } else if (cjson.cJSON_IsString(parsedcjson.cast()) == 1) {
-    obj = Utf8.fromUtf8(parsedcjson.ref.valuestring.cast());
+    obj = parsedcjson.ref.valuestring.cast<Utf8>().toDartString();
   } else if (cjson.cJSON_IsNumber(parsedcjson.cast()) == 1) {
     obj = parsedcjson.ref.valueint == parsedcjson.ref.valuedouble
         ? parsedcjson.ref.valueint
@@ -90,7 +90,7 @@
 
 void _addToObj(dynamic obj, dynamic o, [Pointer<Utf8>? name]) {
   if (obj is Map<String, dynamic>) {
-    obj[Utf8.fromUtf8(name!)] = o;
+    obj[name!.toDartString()] = o;
   } else if (obj is List<dynamic>) {
     obj.add(o);
   }
diff --git a/example/c_json/pubspec.yaml b/example/c_json/pubspec.yaml
index 76e4198..929dccf 100644
--- a/example/c_json/pubspec.yaml
+++ b/example/c_json/pubspec.yaml
@@ -5,10 +5,10 @@
 name: c_json_example
 
 environment:
-  sdk: '>=2.12.0-237.0.dev <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 
 dependencies:
-  ffi: ^0.2.0-nullsafety.1
+  ffi: ^1.0.0
 
 dev_dependencies:
   ffigen:
diff --git a/example/libclang-example/pubspec.yaml b/example/libclang-example/pubspec.yaml
index efce084..61373da 100644
--- a/example/libclang-example/pubspec.yaml
+++ b/example/libclang-example/pubspec.yaml
@@ -5,7 +5,7 @@
 name: libclang_example
 
 environment:
-  sdk: '>=2.12.0-237.0.dev <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 
 dev_dependencies:
   ffigen:
diff --git a/example/libclang-example/readme.md b/example/libclang-example/readme.md
index 0b8da39..dab0bdf 100644
--- a/example/libclang-example/readme.md
+++ b/example/libclang-example/readme.md
@@ -6,6 +6,6 @@
 ## Generating bindings
 At the root of this example (`example/libclang-example`), run -
 ```
-pub run ffigen
+dart run ffigen
 ```
 This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart).
diff --git a/example/simple/README.md b/example/simple/README.md
index d286dab..026ae9f 100644
--- a/example/simple/README.md
+++ b/example/simple/README.md
@@ -5,6 +5,6 @@
 ## Generating bindings
 At the root of this example (`example/simple`), run -
 ```
-pub run ffigen
+dart run ffigen
 ```
 This will generate bindings in a file: [generated_bindings.dart](./generated_bindings.dart).
diff --git a/example/simple/pubspec.yaml b/example/simple/pubspec.yaml
index d3562ef..bd45857 100644
--- a/example/simple/pubspec.yaml
+++ b/example/simple/pubspec.yaml
@@ -5,7 +5,7 @@
 name: simple_example
 
 environment:
-  sdk: '>=2.12.0-237.0.dev <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 
 dev_dependencies:
   ffigen:
diff --git a/lib/src/README.md b/lib/src/README.md
index cdfc01a..7564006 100644
--- a/lib/src/README.md
+++ b/lib/src/README.md
@@ -17,7 +17,7 @@
 The config file for generating bindings is `tool/libclang_config.yaml`. The bindings are generated to `lib/src/header_parser/clang_bindings/clang_bindings.dart`. These are used by [Header Parser](#header-parser) for calling libclang functions.
 # Scripts
 ## ffigen.dart
-This is the main entry point for the user-  `pub run ffigen`.
+This is the main entry point for the user-  `dart run ffigen`.
 - Command-line options:
     - `--verbose`: Sets log level.
     - `--config`: Specifies a config file.
diff --git a/lib/src/code_generator/library.dart b/lib/src/code_generator/library.dart
index 139ef4f..fd16446 100644
--- a/lib/src/code_generator/library.dart
+++ b/lib/src/code_generator/library.dart
@@ -7,7 +7,6 @@
 import 'package:cli_util/cli_util.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart' as p;
-import 'package:pub_semver/pub_semver.dart';
 import 'binding.dart';
 import 'utils.dart';
 import 'writer.dart';
@@ -97,17 +96,9 @@
   /// Formats a file using `dartfmt`.
   void _dartFmt(String path) {
     final sdkPath = getSdkPath();
-    final versionAtleast2dot10 = Version.parse(
-            File(p.join(sdkPath, 'version')).readAsStringSync().trim()) >=
-        Version(2, 10, 0);
-
-    /// Starting from version `>=2.10.0` the dart sdk has a unified `dart` tool
-    /// So we call `dart format` instead of `dartfmt`.
-    final result = versionAtleast2dot10
-        ? Process.runSync(p.join(sdkPath, 'bin', 'dart'), ['format', path],
-            runInShell: Platform.isWindows)
-        : Process.runSync(p.join(sdkPath, 'bin', 'dartfmt'), ['-w', path],
-            runInShell: Platform.isWindows);
+    final result = Process.runSync(
+        p.join(sdkPath, 'bin', 'dart'), ['format', path],
+        runInShell: Platform.isWindows);
     if (result.stderr.toString().isNotEmpty) {
       _logger.severe(result.stderr);
       throw FormatException('Unable to format generated file: $path.');
diff --git a/lib/src/config_provider/config.dart b/lib/src/config_provider/config.dart
index 6c11b34..34f9de5 100644
--- a/lib/src/config_provider/config.dart
+++ b/lib/src/config_provider/config.dart
@@ -92,12 +92,12 @@
   late String _wrapperName;
 
   /// Doc comment for the wrapper class.
-  String get wrapperDocComment => _wrapperDocComment;
-  late String _wrapperDocComment;
+  String? get wrapperDocComment => _wrapperDocComment;
+  String? _wrapperDocComment;
 
   /// Header of the generated bindings.
-  String get preamble => _preamble;
-  late String _preamble;
+  String? get preamble => _preamble;
+  String? _preamble;
 
   /// If `Dart_Handle` should be mapped with Handle/Object.
   bool get useDartHandle => _useDartHandle;
@@ -314,13 +314,13 @@
         extractor: stringExtractor,
         defaultValue: () => null,
         extractedResult: (dynamic result) =>
-            _wrapperDocComment = result as String,
+            _wrapperDocComment = result as String?,
       ),
-      strings.preamble: Specification<String>(
+      strings.preamble: Specification<String?>(
         requirement: Requirement.no,
         validator: nonEmptyStringValidator,
         extractor: stringExtractor,
-        extractedResult: (dynamic result) => _preamble = result as String,
+        extractedResult: (dynamic result) => _preamble = result as String?,
       ),
       strings.useDartHandle: Specification<bool>(
         requirement: Requirement.no,
diff --git a/lib/src/config_provider/spec_utils.dart b/lib/src/config_provider/spec_utils.dart
index 839333a..d377c95 100644
--- a/lib/src/config_provider/spec_utils.dart
+++ b/lib/src/config_provider/spec_utils.dart
@@ -5,6 +5,7 @@
 import 'dart:io';
 
 import 'package:ffigen/src/code_generator.dart';
+import 'package:file/local.dart';
 import 'package:glob/glob.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart' as p;
@@ -122,7 +123,8 @@
           _logger.fine('Adding header/file: $headerGlob');
         } else {
           final glob = Glob(headerGlob);
-          for (final file in glob.listSync(followLinks: true)) {
+          for (final file in glob.listFileSystemSync(const LocalFileSystem(),
+              followLinks: true)) {
             final fixedPath = _replaceSeparators(file.path);
             entryPoints.add(fixedPath);
             _logger.fine('Adding header/file: ${fixedPath}');
diff --git a/lib/src/header_parser/parser.dart b/lib/src/header_parser/parser.dart
index 2ce1cb9..3d4c5f0 100644
--- a/lib/src/header_parser/parser.dart
+++ b/lib/src/header_parser/parser.dart
@@ -78,7 +78,7 @@
 
     final tu = clang.clang_parseTranslationUnit(
       index,
-      Utf8.toUtf8(headerLocation).cast(),
+      headerLocation.toNativeUtf8().cast(),
       clangCmdArgs.cast(),
       cmdLen,
       nullptr,
diff --git a/lib/src/header_parser/sub_parsers/macro_parser.dart b/lib/src/header_parser/sub_parsers/macro_parser.dart
index 4f18ce6..7d93814 100644
--- a/lib/src/header_parser/sub_parsers/macro_parser.dart
+++ b/lib/src/header_parser/sub_parsers/macro_parser.dart
@@ -65,7 +65,7 @@
   cmdLen = config.compilerOpts.length;
   final tu = clang.clang_parseTranslationUnit(
     index,
-    Utf8.toUtf8(file.path).cast(),
+    file.path.toNativeUtf8().cast(),
     clangCmdArgs.cast(),
     cmdLen,
     nullptr,
@@ -247,7 +247,7 @@
     sb.clear();
     // This throws a Format Exception if string isn't Utf8 so that we handle it
     // in the catch block.
-    final result = Utf8.fromUtf8(strPtr.cast());
+    final result = strPtr.cast<Utf8>().toDartString();
     for (final s in result.runes) {
       sb.write(_getWritableChar(s));
     }
@@ -257,7 +257,7 @@
     _logger.warning(
         "Couldn't decode Macro string '$macroName' as Utf8, using ASCII instead.");
     sb.clear();
-    final length = Utf8.strlen(strPtr.cast());
+    final length = strPtr.cast<Utf8>().length;
     final charList = Uint8List.view(
         strPtr.cast<Uint8>().asTypedList(length).buffer, 0, length);
 
diff --git a/lib/src/header_parser/utils.dart b/lib/src/header_parser/utils.dart
index 28ca657..915d4b7 100644
--- a/lib/src/header_parser/utils.dart
+++ b/lib/src/header_parser/utils.dart
@@ -52,7 +52,7 @@
 
 extension CXSourceRangeExt on Pointer<clang_types.CXSourceRange> {
   void dispose() {
-    free(this);
+    calloc.free(this);
   }
 }
 
@@ -100,19 +100,19 @@
 
   String sourceFileName() {
     final cxsource = clang.clang_getCursorLocation(this);
-    final cxfilePtr = allocate<Pointer<Void>>();
-    final line = allocate<Uint32>();
-    final column = allocate<Uint32>();
-    final offset = allocate<Uint32>();
+    final cxfilePtr = calloc<Pointer<Void>>();
+    final line = calloc<Uint32>();
+    final column = calloc<Uint32>();
+    final offset = calloc<Uint32>();
 
     // Puts the values in these pointers.
     clang.clang_getFileLocation(cxsource, cxfilePtr, line, column, offset);
     final s = clang.clang_getFileName(cxfilePtr.value).toStringAndDispose();
 
-    free(cxfilePtr);
-    free(line);
-    free(column);
-    free(offset);
+    calloc.free(cxfilePtr);
+    calloc.free(line);
+    calloc.free(column);
+    calloc.free(offset);
     return s;
   }
 }
@@ -241,7 +241,7 @@
   String string() {
     final cstring = clang.clang_getCString(this);
     if (cstring != nullptr) {
-      return Utf8.fromUtf8(cstring.cast());
+      return cstring.cast<Utf8>().toDartString();
     } else {
       return '';
     }
@@ -262,10 +262,10 @@
 
 /// Converts a [List<String>] to [Pointer<Pointer<Utf8>>].
 Pointer<Pointer<Utf8>> createDynamicStringArray(List<String> list) {
-  final nativeCmdArgs = allocate<Pointer<Utf8>>(count: list.length);
+  final nativeCmdArgs = calloc<Pointer<Utf8>>(list.length);
 
   for (var i = 0; i < list.length; i++) {
-    nativeCmdArgs[i] = Utf8.toUtf8(list[i]);
+    nativeCmdArgs[i] = list[i].toNativeUtf8();
   }
 
   return nativeCmdArgs;
@@ -275,9 +275,9 @@
   // Properly disposes a Pointer<Pointer<Utf8>, ensure that sure length is correct.
   void dispose(int length) {
     for (var i = 0; i < length; i++) {
-      free(this[i]);
+      calloc.free(this[i]);
     }
-    free(this);
+    calloc.free(this);
   }
 }
 
diff --git a/pubspec.yaml b/pubspec.yaml
index e8501c0..ccb3e8b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,24 +3,24 @@
 # BSD-style license that can be found in the LICENSE file.
 
 name: ffigen
-version: 2.0.0-dev.6
+version: 2.0.1
 homepage: https://github.com/dart-lang/ffigen
-description: Experimental generator for FFI bindings, using LibClang to parse C header files.
+description: Generator for FFI bindings, using LibClang to parse C header files.
 
 environment:
-  sdk: '>=2.12.0-237.0.dev <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 
 dependencies:
-  ffi: ^0.2.0-nullsafety.1
-  yaml: ^3.0.0-nullsafety.0
-  path: ^1.8.0-nullsafety.3
-  quiver: ^3.0.0-nullsafety.2
-  args: ^1.6.0        # Not available
-  logging: ^0.11.4    # test->coverage->logging
-  cli_util: ^0.2.0    # test->analyzer->cli_util
-  glob: ^1.0.3        # test->analyzer->glob
-  pub_semver: ^1.4.4  # test->analyzer->pub_semver
+  ffi: ^1.0.0
+  yaml: ^3.0.0
+  path: ^1.8.0
+  quiver: ^3.0.0
+  args: ^2.0.0
+  logging: ^1.0.0
+  cli_util: ^0.3.0
+  glob: ^2.0.0
+  file: ^6.0.0
 
 dev_dependencies:
-  pedantic: ^1.10.0-nullsafety.3
-  test: ^1.16.0-nullsafety.13
+  pedantic: ^1.10.0
+  test: ^1.16.2
diff --git a/test/native_test/config.yaml b/test/native_test/config.yaml
index 2b2ded2..3933518 100644
--- a/test/native_test/config.yaml
+++ b/test/native_test/config.yaml
@@ -3,7 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # =================== GENERATING TEST BINDINGS ==================
-#    pub run ffigen --config test/native_test/config.yaml
+#    dart run ffigen --config test/native_test/config.yaml
 # ===============================================================
 
 name: NativeLibrary
diff --git a/tool/coverage.sh b/tool/coverage.sh
index d43016d..7cecbfe 100755
--- a/tool/coverage.sh
+++ b/tool/coverage.sh
@@ -8,12 +8,12 @@
 set -e
 
 # Gather coverage.
-pub global activate remove_from_coverage
-pub global activate coverage
+dart pub global activate remove_from_coverage
+dart pub global activate coverage
 # Generate coverage report.
-dart --no-sound-null-safety --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=3000 test/test_coverage.dart &
+dart --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=3000 test/test_coverage.dart &
 dart pub global run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:3000/ -o coverage.json --resume-isolates
 dart pub global run coverage:format_coverage --lcov -i coverage.json -o lcov.info
 
 # Remove extra files from coverage report.
-pub global run remove_from_coverage -f lcov.info -r ".pub-cache"
+dart pub global run remove_from_coverage -f lcov.info -r ".pub-cache"
diff --git a/tool/libclang_config.yaml b/tool/libclang_config.yaml
index c27f17c..178aa97 100644
--- a/tool/libclang_config.yaml
+++ b/tool/libclang_config.yaml
@@ -6,7 +6,7 @@
 
 # ===================== GENERATING BINDINGS =====================
 #    cd to project's root, and run -
-#    pub run ffigen --config tool/libclang_config.yaml
+#    dart run ffigen --config tool/libclang_config.yaml
 # ===============================================================
 
 name: Clang