From a97e338f689b0075600e54c9fd5735c3ee9aee5f Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Mon, 2 Dec 2024 15:06:30 +0100 Subject: [PATCH 1/4] [native_assets_builder] Test hooks stopping after failure (#1768) Closes: https://github.com/dart-lang/native/issues/1630 --- .github/workflows/native.yaml | 9 +++ .../build_runner_caching_test.dart | 1 - .../build_runner_failure_test.dart | 40 ++++++++++ .../depend_on_fail_build/hook/build.dart | 13 +++ .../lib/depend_on_fail_build.dart | 5 ++ .../depend_on_fail_build/pubspec.yaml | 20 +++++ .../bin/depend_on_fail_build_app.dart | 9 +++ .../depend_on_fail_build_app/pubspec.yaml | 20 +++++ .../test_data/fail_build/hook/build.dart | 10 +++ .../test_data/fail_build/lib/fail_build.dart | 5 ++ .../test_data/fail_build/pubspec.yaml | 18 +++++ .../test_data/manifest.yaml | 80 ++++++++++--------- 12 files changed, 193 insertions(+), 37 deletions(-) create mode 100644 pkgs/native_assets_builder/test_data/depend_on_fail_build/hook/build.dart create mode 100644 pkgs/native_assets_builder/test_data/depend_on_fail_build/lib/depend_on_fail_build.dart create mode 100644 pkgs/native_assets_builder/test_data/depend_on_fail_build/pubspec.yaml create mode 100644 pkgs/native_assets_builder/test_data/depend_on_fail_build_app/bin/depend_on_fail_build_app.dart create mode 100644 pkgs/native_assets_builder/test_data/depend_on_fail_build_app/pubspec.yaml create mode 100644 pkgs/native_assets_builder/test_data/fail_build/hook/build.dart create mode 100644 pkgs/native_assets_builder/test_data/fail_build/lib/fail_build.dart create mode 100644 pkgs/native_assets_builder/test_data/fail_build/pubspec.yaml diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 21094bde1..4e2396cf5 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -120,6 +120,15 @@ jobs: - run: dart pub get -C example/link/app_with_asset_treeshaking/ if: ${{ matrix.package == 'native_assets_cli' }} + - run: dart pub get -C test_data/fail_build/ + if: ${{ matrix.package == 'native_assets_builder' }} + + - run: dart pub get -C test_data/depend_on_fail_build/ + if: ${{ matrix.package == 'native_assets_builder' }} + + - run: dart pub get -C test_data/depend_on_fail_build_app/ + if: ${{ matrix.package == 'native_assets_builder' }} + - run: dart analyze --fatal-infos # Run on dev to ensure we're not depending on deprecated SDK things. diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart index 42c5e4939..5b31cae41 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart @@ -62,7 +62,6 @@ void main() async { applicationAssetValidator: validateCodeAssetInApplication, ))!; final hookUri = packageUri.resolve('hook/build.dart'); - print(logMessages.join('\n')); expect( logMessages.join('\n'), isNot(contains('Recompiling ${hookUri.toFilePath()}')), diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart index b15331721..7b9566828 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart @@ -102,4 +102,44 @@ void main() async { } }); }); + + test('do not build dependees after build failure', timeout: longTimeout, + () async { + await inTempDir((tempUri) async { + await copyTestProjects(targetUri: tempUri); + final packageUri = tempUri.resolve('depend_on_fail_build_app/'); + + await runPubGet( + workingDirectory: packageUri, + logger: logger, + ); + + final logMessages = []; + await build( + packageUri, + logger, + capturedLogs: logMessages, + dartExecutable, + supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeAssetBuildConfig, + buildValidator: validateCodeAssetBuildOutput, + applicationAssetValidator: validateCodeAssetInApplication, + ); + Matcher stringContainsBuildHookCompilation(String packageName) => + stringContainsInOrder([ + 'Running', + 'hook.dill', + '$packageName${Platform.pathSeparator}' + 'hook${Platform.pathSeparator}build.dart', + ]); + expect( + logMessages.join('\n'), + stringContainsBuildHookCompilation('fail_build'), + ); + expect( + logMessages.join('\n'), + isNot(stringContainsBuildHookCompilation('depends_on_fail_build')), + ); + }); + }); } diff --git a/pkgs/native_assets_builder/test_data/depend_on_fail_build/hook/build.dart b/pkgs/native_assets_builder/test_data/depend_on_fail_build/hook/build.dart new file mode 100644 index 000000000..bee5aadf4 --- /dev/null +++ b/pkgs/native_assets_builder/test_data/depend_on_fail_build/hook/build.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:fail_build/fail_build.dart'; +import 'package:native_assets_cli/data_assets.dart'; + +void main(List arguments) async { + await build(arguments, (config, output) async { + // Does nothing, just depends on `package:fail_build`. + invokeFailBuildCode(); + }); +} diff --git a/pkgs/native_assets_builder/test_data/depend_on_fail_build/lib/depend_on_fail_build.dart b/pkgs/native_assets_builder/test_data/depend_on_fail_build/lib/depend_on_fail_build.dart new file mode 100644 index 000000000..0457dc633 --- /dev/null +++ b/pkgs/native_assets_builder/test_data/depend_on_fail_build/lib/depend_on_fail_build.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// 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. + +void invokeDependOnFailBuildCode() {} diff --git a/pkgs/native_assets_builder/test_data/depend_on_fail_build/pubspec.yaml b/pkgs/native_assets_builder/test_data/depend_on_fail_build/pubspec.yaml new file mode 100644 index 000000000..253d3141f --- /dev/null +++ b/pkgs/native_assets_builder/test_data/depend_on_fail_build/pubspec.yaml @@ -0,0 +1,20 @@ +name: depend_on_fail_build +description: Has a dependency that fails to build. +version: 0.1.0 + +publish_to: none + +environment: + sdk: '>=3.3.0 <4.0.0' + +dependencies: + fail_build: + path: ../fail_build/ + # native_assets_cli: ^0.9.0 + native_assets_cli: + path: ../../../native_assets_cli/ + +dev_dependencies: + ffigen: ^8.0.2 + lints: ^3.0.0 + test: ^1.23.1 diff --git a/pkgs/native_assets_builder/test_data/depend_on_fail_build_app/bin/depend_on_fail_build_app.dart b/pkgs/native_assets_builder/test_data/depend_on_fail_build_app/bin/depend_on_fail_build_app.dart new file mode 100644 index 000000000..2abcfd041 --- /dev/null +++ b/pkgs/native_assets_builder/test_data/depend_on_fail_build_app/bin/depend_on_fail_build_app.dart @@ -0,0 +1,9 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:depend_on_fail_build/depend_on_fail_build.dart'; + +void main() { + invokeDependOnFailBuildCode(); +} diff --git a/pkgs/native_assets_builder/test_data/depend_on_fail_build_app/pubspec.yaml b/pkgs/native_assets_builder/test_data/depend_on_fail_build_app/pubspec.yaml new file mode 100644 index 000000000..ddb0ec04d --- /dev/null +++ b/pkgs/native_assets_builder/test_data/depend_on_fail_build_app/pubspec.yaml @@ -0,0 +1,20 @@ +name: depend_on_fail_build_app +description: Has a dependency that has a dependency that fails to build. +version: 0.1.0 + +publish_to: none + +environment: + sdk: '>=3.3.0 <4.0.0' + +dependencies: + depend_on_fail_build: + path: ../depend_on_fail_build/ + # native_assets_cli: ^0.9.0 + native_assets_cli: + path: ../../../native_assets_cli/ + +dev_dependencies: + ffigen: ^8.0.2 + lints: ^3.0.0 + test: ^1.23.1 diff --git a/pkgs/native_assets_builder/test_data/fail_build/hook/build.dart b/pkgs/native_assets_builder/test_data/fail_build/hook/build.dart new file mode 100644 index 000000000..790b93525 --- /dev/null +++ b/pkgs/native_assets_builder/test_data/fail_build/hook/build.dart @@ -0,0 +1,10 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:io'; + +void main(List arguments) async { + print('Just here to fail the build!'); + exit(1); +} diff --git a/pkgs/native_assets_builder/test_data/fail_build/lib/fail_build.dart b/pkgs/native_assets_builder/test_data/fail_build/lib/fail_build.dart new file mode 100644 index 000000000..d6eb1aacc --- /dev/null +++ b/pkgs/native_assets_builder/test_data/fail_build/lib/fail_build.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// 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. + +void invokeFailBuildCode() {} diff --git a/pkgs/native_assets_builder/test_data/fail_build/pubspec.yaml b/pkgs/native_assets_builder/test_data/fail_build/pubspec.yaml new file mode 100644 index 000000000..b04fe9a5d --- /dev/null +++ b/pkgs/native_assets_builder/test_data/fail_build/pubspec.yaml @@ -0,0 +1,18 @@ +name: fail_build +description: Always fails to build +version: 0.1.0 + +publish_to: none + +environment: + sdk: '>=3.3.0 <4.0.0' + +dependencies: + # native_assets_cli: ^0.9.0 + native_assets_cli: + path: ../../../native_assets_cli/ + +dev_dependencies: + ffigen: ^8.0.2 + lints: ^3.0.0 + test: ^1.23.1 diff --git a/pkgs/native_assets_builder/test_data/manifest.yaml b/pkgs/native_assets_builder/test_data/manifest.yaml index 6bcdcd32c..9ed41c7c9 100644 --- a/pkgs/native_assets_builder/test_data/manifest.yaml +++ b/pkgs/native_assets_builder/test_data/manifest.yaml @@ -28,6 +28,11 @@ - cyclic_package_2/pubspec.yaml - dart_app/bin/dart_app.dart - dart_app/pubspec.yaml +- depend_on_fail_build_app/bin/depend_on_fail_build_app.dart +- depend_on_fail_build_app/pubspec.yaml +- depend_on_fail_build/hook/build.dart +- depend_on_fail_build/lib/depend_on_fail_build.dart +- depend_on_fail_build/pubspec.yaml - drop_dylib_link/bin/drop_dylib_link.dart - drop_dylib_link/hook/build.dart - drop_dylib_link/hook/link.dart @@ -39,6 +44,9 @@ - drop_dylib_link/src/native_add.h - drop_dylib_link/src/native_multiply.c - drop_dylib_link/src/native_multiply.h +- fail_build/hook/build.dart +- fail_build/lib/fail_build.dart +- fail_build/pubspec.yaml - fail_on_os_sdk_version_link/assets/data.json - fail_on_os_sdk_version_link/hook/build.dart - fail_on_os_sdk_version_link/pubspec.yaml @@ -46,6 +54,12 @@ - fail_on_os_sdk_version_linker/pubspec.yaml - fail_on_os_sdk_version/hook/build.dart - fail_on_os_sdk_version/pubspec.yaml +- native_add_duplicate/bin/native_add_duplicate.dart +- native_add_duplicate/hook/build.dart +- native_add_duplicate/hook/link.dart +- native_add_duplicate/pubspec.yaml +- native_add_duplicate/src/native_add.c +- native_add_duplicate/src/native_add.h - native_add/ffigen.yaml - native_add/hook/build.dart - native_add/lib/native_add.dart @@ -55,12 +69,19 @@ - native_add/src/native_add.c - native_add/src/native_add.h - native_add/test/native_add_test.dart -- native_add_duplicate/bin/native_add_duplicate.dart -- native_add_duplicate/hook/build.dart -- native_add_duplicate/hook/link.dart -- native_add_duplicate/pubspec.yaml -- native_add_duplicate/src/native_add.c -- native_add_duplicate/src/native_add.h +- native_dynamic_linking/bin/native_dynamic_linking.dart +- native_dynamic_linking/ffigen.yaml +- native_dynamic_linking/hook/build.dart +- native_dynamic_linking/lib/add.dart +- native_dynamic_linking/pubspec.yaml +- native_dynamic_linking/README.md +- native_dynamic_linking/src/add.c +- native_dynamic_linking/src/add.h +- native_dynamic_linking/src/debug.c +- native_dynamic_linking/src/debug.h +- native_dynamic_linking/src/math.c +- native_dynamic_linking/src/math.h +- native_dynamic_linking/test/add_test.dart - native_subtract/ffigen.yaml - native_subtract/hook/build.dart - native_subtract/lib/native_subtract.dart @@ -75,6 +96,13 @@ - package_reading_metadata/pubspec.yaml - package_with_metadata/hook/build.dart - package_with_metadata/pubspec.yaml +- simple_data_asset/assets/test_asset.txt +- simple_data_asset/bin/deep_modify_data_asset.dart.debug +- simple_data_asset/bin/modify_data_asset.dart.debug +- simple_data_asset/bin/simple_data_asset.dart.debug +- simple_data_asset/hook/build.dart +- simple_data_asset/pubspec.yaml +- simple_data_asset/README.md - simple_link/assets/data_0.json - simple_link/assets/data_1.json - simple_link/assets/data_2.json @@ -82,13 +110,6 @@ - simple_link/hook/build.dart - simple_link/hook/link.dart - simple_link/pubspec.yaml -- simple_data_asset/pubspec.yaml -- simple_data_asset/assets/test_asset.txt -- simple_data_asset/README.md -- simple_data_asset/hook/build.dart -- simple_data_asset/bin/simple_data_asset.dart.debug -- simple_data_asset/bin/modify_data_asset.dart.debug -- simple_data_asset/bin/deep_modify_data_asset.dart.debug - some_dev_dep/bin/some_dev_dep.dart - some_dev_dep/pubspec.yaml - transformer/data/data0.json @@ -103,20 +124,20 @@ - transformer/data/data9.json - transformer/hook/build.dart - transformer/lib/src/transform.dart -- transformer/tool/generate_data.dart - transformer/pubspec.yaml -- treeshaking_native_libs/pubspec.yaml -- treeshaking_native_libs/lib/treeshaking_native_libs.dart -- treeshaking_native_libs/lib/src/treeshaking_native_libs.dart +- transformer/tool/generate_data.dart +- treeshaking_native_libs/bin/treeshaking_native_libs.dart +- treeshaking_native_libs/ffigen.yaml +- treeshaking_native_libs/hook/build.dart +- treeshaking_native_libs/hook/link.dart - treeshaking_native_libs/lib/src/treeshaking_native_libs_bindings_generated.dart -- treeshaking_native_libs/src/native_add.h -- treeshaking_native_libs/src/native_multiply.h +- treeshaking_native_libs/lib/src/treeshaking_native_libs.dart +- treeshaking_native_libs/lib/treeshaking_native_libs.dart +- treeshaking_native_libs/pubspec.yaml - treeshaking_native_libs/src/native_add.c +- treeshaking_native_libs/src/native_add.h - treeshaking_native_libs/src/native_multiply.c -- treeshaking_native_libs/hook/link.dart -- treeshaking_native_libs/hook/build.dart -- treeshaking_native_libs/bin/treeshaking_native_libs.dart -- treeshaking_native_libs/ffigen.yaml +- treeshaking_native_libs/src/native_multiply.h - wrong_build_output_2/hook/build.dart - wrong_build_output_2/pubspec.yaml - wrong_build_output_3/hook/build.dart @@ -127,16 +148,3 @@ - wrong_linker/pubspec.yaml - wrong_namespace_asset/hook/build.dart - wrong_namespace_asset/pubspec.yaml -- native_dynamic_linking/bin/native_dynamic_linking.dart -- native_dynamic_linking/hook/build.dart -- native_dynamic_linking/lib/add.dart -- native_dynamic_linking/src/add.c -- native_dynamic_linking/src/add.h -- native_dynamic_linking/src/debug.c -- native_dynamic_linking/src/debug.h -- native_dynamic_linking/src/math.c -- native_dynamic_linking/src/math.h -- native_dynamic_linking/test/add_test.dart -- native_dynamic_linking/ffigen.yaml -- native_dynamic_linking/pubspec.yaml -- native_dynamic_linking/README.md From 4b03d952059048149fd680ff77034887b53e7ed9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 23:50:19 +0000 Subject: [PATCH 2/4] Bump the github-actions group with 2 updates (#1771) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) and [subosito/flutter-action](https://github.com/subosito/flutter-action). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

  • Fix zip path handling on Windows 11 (#118[])

#118: dart-lang/setup-dart#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

Updates `subosito/flutter-action` from 2.16.0 to 2.17.0
Release notes

Sourced from subosito/flutter-action's releases.

v2.17.0

This release adds support for older yq versions, as added in PR #329. Thanks for contributing, @​ThomasAunvik!

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- .github/workflows/ffi.yaml | 4 ++-- .github/workflows/ffigen.yml | 12 ++++++------ .github/workflows/ffigen_weekly.yml | 2 +- .github/workflows/jnigen.yaml | 24 +++++++++++------------ .github/workflows/native.yaml | 2 +- .github/workflows/native_toolchain_c.yaml | 2 +- .github/workflows/objective_c.yaml | 6 +++--- .github/workflows/swift2objc.yaml | 4 ++-- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ffi.yaml b/.github/workflows/ffi.yaml index ba20ccf2b..e521a3caf 100644 --- a/.github/workflows/ffi.yaml +++ b/.github/workflows/ffi.yaml @@ -32,7 +32,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -62,7 +62,7 @@ jobs: sdk: [beta, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install diff --git a/.github/workflows/ffigen.yml b/.github/workflows/ffigen.yml index c237ad11d..6e1690b92 100644 --- a/.github/workflows/ffigen.yml +++ b/.github/workflows/ffigen.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - id: install @@ -54,7 +54,7 @@ jobs: working-directory: pkgs/ffigen/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - name: Install dependencies @@ -75,7 +75,7 @@ jobs: working-directory: pkgs/ffigen/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - name: Install dependencies @@ -106,7 +106,7 @@ jobs: working-directory: pkgs/ffigen/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - name: Install dependencies @@ -124,7 +124,7 @@ jobs: working-directory: pkgs/ffigen/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - name: Install dependencies @@ -152,7 +152,7 @@ jobs: working-directory: pkgs/ffigen/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: "master" - name: Install dependencies diff --git a/.github/workflows/ffigen_weekly.yml b/.github/workflows/ffigen_weekly.yml index 726160b99..863eac384 100644 --- a/.github/workflows/ffigen_weekly.yml +++ b/.github/workflows/ffigen_weekly.yml @@ -28,7 +28,7 @@ jobs: working-directory: pkgs/ffigen/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - name: Install dependencies diff --git a/.github/workflows/jnigen.yaml b/.github/workflows/jnigen.yaml index 8eb4aa321..462c84f10 100644 --- a/.github/workflows/jnigen.yaml +++ b/.github/workflows/jnigen.yaml @@ -41,7 +41,7 @@ jobs: sdk: [stable] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: ${{ matrix.sdk }} cache: true @@ -77,7 +77,7 @@ jobs: sdk: [stable, beta] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: ${{ matrix.sdk }} cache: true @@ -128,7 +128,7 @@ jobs: working-directory: ./pkgs/jni steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -167,7 +167,7 @@ jobs: working-directory: ./pkgs/jni steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -216,7 +216,7 @@ jobs: working-directory: ./pkgs/jni steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -243,7 +243,7 @@ jobs: with: version: latest platform: x64 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -269,7 +269,7 @@ jobs: working-directory: ./pkgs/jni steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -294,7 +294,7 @@ jobs: uses: ConorMacBride/install-package@3e7ad059e07782ee54fa35f827df52aae0626f30 with: brew: clang-format - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -317,7 +317,7 @@ jobs: working-directory: ./pkgs/jni/example steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -341,7 +341,7 @@ jobs: working-directory: ./pkgs/jni/example steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -365,7 +365,7 @@ jobs: with: distribution: 'zulu' java-version: '17' - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true @@ -380,7 +380,7 @@ jobs: working-directory: ./pkgs/jnigen/example/pdfbox_plugin steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' cache: true diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 4e2396cf5..26eb0676d 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -46,7 +46,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} diff --git a/.github/workflows/native_toolchain_c.yaml b/.github/workflows/native_toolchain_c.yaml index 7ce6fab08..5af91a33d 100644 --- a/.github/workflows/native_toolchain_c.yaml +++ b/.github/workflows/native_toolchain_c.yaml @@ -34,7 +34,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} diff --git a/.github/workflows/objective_c.yaml b/.github/workflows/objective_c.yaml index 15e6d0c35..2c2ee64cb 100644 --- a/.github/workflows/objective_c.yaml +++ b/.github/workflows/objective_c.yaml @@ -31,7 +31,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - id: install @@ -52,7 +52,7 @@ jobs: working-directory: pkgs/objective_c/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - name: Install dependencies @@ -88,7 +88,7 @@ jobs: working-directory: pkgs/objective_c/example/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 + - uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3 with: channel: 'stable' - name: Install dependencies diff --git a/.github/workflows/swift2objc.yaml b/.github/workflows/swift2objc.yaml index 67bc9192e..ddd79dd8e 100644 --- a/.github/workflows/swift2objc.yaml +++ b/.github/workflows/swift2objc.yaml @@ -29,7 +29,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: stable - id: install @@ -50,7 +50,7 @@ jobs: working-directory: pkgs/swift2objc/ steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: stable - name: Install dependencies From 3210a79448804b1091adc3c572544d2e3b6709cb Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 4 Dec 2024 11:56:33 +1300 Subject: [PATCH 3/4] [swift2objc] Support the `async` annotation (#1779) --- .../src/ast/_core/interfaces/can_async.dart | 9 ++ .../interfaces/function_declaration.dart | 4 +- .../interfaces/variable_declaration.dart | 10 +- .../members/initializer_declaration.dart | 8 +- .../compounds/members/method_declaration.dart | 4 + .../members/property_declaration.dart | 4 + .../src/ast/declarations/globals/globals.dart | 8 ++ .../lib/src/generator/_core/utils.dart | 14 +++ .../generator/generators/class_generator.dart | 18 ++-- .../parse_function_declaration.dart | 14 ++- .../parse_initializer_declaration.dart | 9 ++ .../parse_variable_declaration.dart | 13 +++ .../transformers/transform_compound.dart | 1 + .../transformers/transform_function.dart | 4 + .../transformers/transform_initializer.dart | 4 + .../transformers/transform_variable.dart | 1 + .../test/integration/async_input.swift | 12 +++ .../test/integration/async_output.swift | 39 ++++++++ .../test/unit/parse_function_info_test.dart | 94 +++++++++++++++++++ 19 files changed, 249 insertions(+), 21 deletions(-) create mode 100644 pkgs/swift2objc/lib/src/ast/_core/interfaces/can_async.dart create mode 100644 pkgs/swift2objc/test/integration/async_input.swift create mode 100644 pkgs/swift2objc/test/integration/async_output.swift diff --git a/pkgs/swift2objc/lib/src/ast/_core/interfaces/can_async.dart b/pkgs/swift2objc/lib/src/ast/_core/interfaces/can_async.dart new file mode 100644 index 000000000..1479d7a96 --- /dev/null +++ b/pkgs/swift2objc/lib/src/ast/_core/interfaces/can_async.dart @@ -0,0 +1,9 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// 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. + +/// An interface to describe a Swift entity's ability to be annotated +/// with `async`. +abstract interface class CanAsync { + abstract final bool async; +} diff --git a/pkgs/swift2objc/lib/src/ast/_core/interfaces/function_declaration.dart b/pkgs/swift2objc/lib/src/ast/_core/interfaces/function_declaration.dart index ca90dc5c7..5ee39604b 100644 --- a/pkgs/swift2objc/lib/src/ast/_core/interfaces/function_declaration.dart +++ b/pkgs/swift2objc/lib/src/ast/_core/interfaces/function_declaration.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../shared/referred_type.dart'; +import 'can_async.dart'; import 'can_throw.dart'; import 'declaration.dart'; import 'executable.dart'; @@ -16,6 +17,7 @@ abstract interface class FunctionDeclaration Parameterizable, Executable, TypeParameterizable, - CanThrow { + CanThrow, + CanAsync { abstract final ReferredType returnType; } diff --git a/pkgs/swift2objc/lib/src/ast/_core/interfaces/variable_declaration.dart b/pkgs/swift2objc/lib/src/ast/_core/interfaces/variable_declaration.dart index c2c694e35..cf15229cf 100644 --- a/pkgs/swift2objc/lib/src/ast/_core/interfaces/variable_declaration.dart +++ b/pkgs/swift2objc/lib/src/ast/_core/interfaces/variable_declaration.dart @@ -3,15 +3,17 @@ // BSD-style license that can be found in the LICENSE file. import '../shared/referred_type.dart'; +import 'can_async.dart'; import 'can_throw.dart'; import 'declaration.dart'; /// Describes a variable-like entity. /// -/// This declaration [CanThrow] because Swift variables can have explicit -/// getters, which can be marked with `throws`. Such variables may not have a -/// setter. -abstract interface class VariableDeclaration implements Declaration, CanThrow { +/// This declaration implements [CanThrow] and [CanAsync] because Swift +/// variables can have explicit getters, which can be marked with `throws` and +/// `async`. Such variables may not have a setter. +abstract interface class VariableDeclaration + implements Declaration, CanThrow, CanAsync { abstract final bool isConstant; abstract final ReferredType type; } diff --git a/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/initializer_declaration.dart b/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/initializer_declaration.dart index 1fdf10d96..d7c5431b3 100644 --- a/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/initializer_declaration.dart +++ b/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/initializer_declaration.dart @@ -2,6 +2,7 @@ // 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. +import '../../../_core/interfaces/can_async.dart'; import '../../../_core/interfaces/can_throw.dart'; import '../../../_core/interfaces/declaration.dart'; import '../../../_core/interfaces/executable.dart'; @@ -18,7 +19,8 @@ class InitializerDeclaration Parameterizable, ObjCAnnotatable, Overridable, - CanThrow { + CanThrow, + CanAsync { @override String id; @@ -34,6 +36,9 @@ class InitializerDeclaration @override bool throws; + @override + bool async; + bool isFailable; @override @@ -54,6 +59,7 @@ class InitializerDeclaration required this.hasObjCAnnotation, required this.isOverriding, required this.throws, + required this.async, required this.isFailable, }); } diff --git a/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/method_declaration.dart b/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/method_declaration.dart index 72315a962..c7567fe9c 100644 --- a/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/method_declaration.dart +++ b/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/method_declaration.dart @@ -33,6 +33,9 @@ class MethodDeclaration @override bool throws; + @override + bool async; + @override List statements; @@ -57,5 +60,6 @@ class MethodDeclaration this.isStatic = false, this.isOverriding = false, this.throws = false, + this.async = false, }) : assert(!isStatic || !isOverriding); } diff --git a/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/property_declaration.dart b/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/property_declaration.dart index adf151e51..6bcced2d9 100644 --- a/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/property_declaration.dart +++ b/pkgs/swift2objc/lib/src/ast/declarations/compounds/members/property_declaration.dart @@ -28,6 +28,9 @@ class PropertyDeclaration implements VariableDeclaration, ObjCAnnotatable { @override bool throws; + @override + bool async; + bool hasSetter; PropertyStatements? getter; @@ -46,6 +49,7 @@ class PropertyDeclaration implements VariableDeclaration, ObjCAnnotatable { this.setter, this.isStatic = false, this.throws = false, + this.async = false, }) : assert(!(isConstant && hasSetter)), assert(!(hasSetter && throws)); } diff --git a/pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart b/pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart index 1dd6c248b..c06cc5077 100644 --- a/pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart +++ b/pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart @@ -36,6 +36,9 @@ class GlobalFunctionDeclaration implements FunctionDeclaration { @override bool throws; + @override + bool async; + @override ReferredType returnType; @@ -50,6 +53,7 @@ class GlobalFunctionDeclaration implements FunctionDeclaration { this.typeParams = const [], this.statements = const [], this.throws = false, + this.async = false, }); } @@ -70,11 +74,15 @@ class GlobalVariableDeclaration implements VariableDeclaration { @override bool throws; + @override + bool async; + GlobalVariableDeclaration({ required this.id, required this.name, required this.type, required this.isConstant, required this.throws, + required this.async, }) : assert(!(throws && !isConstant)); } diff --git a/pkgs/swift2objc/lib/src/generator/_core/utils.dart b/pkgs/swift2objc/lib/src/generator/_core/utils.dart index 9ab8a6fba..83dc01a3b 100644 --- a/pkgs/swift2objc/lib/src/generator/_core/utils.dart +++ b/pkgs/swift2objc/lib/src/generator/_core/utils.dart @@ -1,5 +1,8 @@ import 'dart:io'; import 'package:path/path.dart' as path; +import '../../ast/_core/interfaces/can_async.dart'; +import '../../ast/_core/interfaces/can_throw.dart'; +import '../../ast/_core/interfaces/declaration.dart'; import '../../ast/_core/shared/parameter.dart'; String generateParameters(List params) { @@ -34,3 +37,14 @@ void outputNextToFile({ File(outputPath).writeAsStringSync(content); } + +String generateAnnotations(Declaration decl) { + final annotations = StringBuffer(); + if (decl is CanAsync && (decl as CanAsync).async) { + annotations.write('async '); + } + if (decl is CanThrow && (decl as CanThrow).throws) { + annotations.write('throws '); + } + return annotations.toString(); +} diff --git a/pkgs/swift2objc/lib/src/generator/generators/class_generator.dart b/pkgs/swift2objc/lib/src/generator/generators/class_generator.dart index c54837fd7..b5161bfb2 100644 --- a/pkgs/swift2objc/lib/src/generator/generators/class_generator.dart +++ b/pkgs/swift2objc/lib/src/generator/generators/class_generator.dart @@ -87,12 +87,8 @@ List _generateInitializer(InitializerDeclaration initializer) { header.write('(${generateParameters(initializer.params)})'); - if (initializer.throws) { - header.write(' throws'); - } - return [ - '$header {', + '$header ${generateAnnotations(initializer)}{', ...initializer.statements.indent(), '}\n', ]; @@ -117,19 +113,17 @@ List _generateClassMethod(MethodDeclaration method) { } header.write( - 'public func ${method.name}(${generateParameters(method.params)})', + 'public func ${method.name}(${generateParameters(method.params)}) ', ); - if (method.throws) { - header.write(' throws'); - } + header.write(generateAnnotations(method)); if (!method.returnType.sameAs(voidType)) { - header.write(' -> ${method.returnType.swiftType}'); + header.write('-> ${method.returnType.swiftType} '); } return [ - '$header {', + '$header{', ...method.statements.indent(), '}\n', ]; @@ -154,7 +148,7 @@ List _generateClassProperty(PropertyDeclaration property) { header.write('public var ${property.name}: ${property.type.swiftType} {'); final getterLines = [ - 'get {', + 'get ${generateAnnotations(property)}{', ...(property.getter?.statements.indent() ?? []), '}' ]; diff --git a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_function_declaration.dart b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_function_declaration.dart index 6f0acf973..02d705d22 100644 --- a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_function_declaration.dart +++ b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_function_declaration.dart @@ -24,6 +24,7 @@ GlobalFunctionDeclaration parseGlobalFunctionDeclaration( returnType: _parseFunctionReturnType(globalFunctionSymbolJson, symbolgraph), params: info.params, throws: info.throws, + async: info.async, ); } @@ -42,12 +43,14 @@ MethodDeclaration parseMethodDeclaration( hasObjCAnnotation: parseSymbolHasObjcAnnotation(methodSymbolJson), isStatic: isStatic, throws: info.throws, + async: info.async, ); } typedef ParsedFunctionInfo = ({ List params, bool throws, + bool async, }); ParsedFunctionInfo parseFunctionInfo( @@ -120,17 +123,22 @@ ParsedFunctionInfo parseFunctionInfo( } } - // Parse annotations until we run out. + // Parse annotations until we run out. The annotations are keywords separated + // by whitespace tokens. final annotations = {}; while (true) { final keyword = maybeConsume('keyword'); - if (keyword == null) break; - annotations.add(keyword); + if (keyword == null) { + if (maybeConsume('text') != '') break; + } else { + annotations.add(keyword); + } } return ( params: parameters, throws: annotations.contains('throws'), + async: annotations.contains('async'), ); } diff --git a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_initializer_declaration.dart b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_initializer_declaration.dart index b9ce98411..74583e447 100644 --- a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_initializer_declaration.dart +++ b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_initializer_declaration.dart @@ -20,6 +20,14 @@ InitializerDeclaration parseInitializerDeclaration( } final info = parseFunctionInfo(declarationFragments, symbolgraph); + + if (info.async) { + // TODO(https://github.com/dart-lang/native/issues/1778): Support async + // initializerse. + throw Exception("Async initializers aren't supported yet, at " + '${initializerSymbolJson.path}'); + } + return InitializerDeclaration( id: id, params: info.params, @@ -27,6 +35,7 @@ InitializerDeclaration parseInitializerDeclaration( isOverriding: parseIsOverriding(initializerSymbolJson), isFailable: parseIsFailableInit(id, declarationFragments), throws: info.throws, + async: info.async, ); } diff --git a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_variable_declaration.dart b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_variable_declaration.dart index b1aa8c78d..1877af6c1 100644 --- a/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_variable_declaration.dart +++ b/pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_variable_declaration.dart @@ -25,6 +25,7 @@ PropertyDeclaration parsePropertyDeclaration( hasSetter: isConstant ? false : _parsePropertyHasSetter(propertySymbolJson), isStatic: isStatic, throws: _parseVariableThrows(propertySymbolJson), + async: _parseVariableAsync(propertySymbolJson), ); } @@ -41,6 +42,7 @@ GlobalVariableDeclaration parseGlobalVariableDeclaration( type: _parseVariableType(variableSymbolJson, symbolgraph), isConstant: isConstant || !hasSetter, throws: _parseVariableThrows(variableSymbolJson), + async: _parseVariableAsync(variableSymbolJson), ); } @@ -78,6 +80,17 @@ bool _parseVariableThrows(Json json) { return throws; } +bool _parseVariableAsync(Json json) { + final async = json['declarationFragments'] + .any((frag) => matchFragment(frag, 'keyword', 'async')); + if (async) { + // TODO(https://github.com/dart-lang/native/issues/1778): Support async + // getters. + throw Exception("Async getters aren't supported yet, at ${json.path}"); + } + return async; +} + bool _parsePropertyHasSetter(Json propertySymbolJson) { final fragmentsJson = propertySymbolJson['declarationFragments']; diff --git a/pkgs/swift2objc/lib/src/transformer/transformers/transform_compound.dart b/pkgs/swift2objc/lib/src/transformer/transformers/transform_compound.dart index d01bd06f8..cd06487a0 100644 --- a/pkgs/swift2objc/lib/src/transformer/transformers/transform_compound.dart +++ b/pkgs/swift2objc/lib/src/transformer/transformers/transform_compound.dart @@ -101,6 +101,7 @@ InitializerDeclaration _buildWrapperInitializer( isOverriding: false, isFailable: false, throws: false, + async: false, statements: ['self.${wrappedClassInstance.name} = wrappedInstance'], hasObjCAnnotation: wrappedClassInstance.hasObjCAnnotation, ); diff --git a/pkgs/swift2objc/lib/src/transformer/transformers/transform_function.dart b/pkgs/swift2objc/lib/src/transformer/transformers/transform_function.dart index a1ce97dc0..c5e375282 100644 --- a/pkgs/swift2objc/lib/src/transformer/transformers/transform_function.dart +++ b/pkgs/swift2objc/lib/src/transformer/transformers/transform_function.dart @@ -100,6 +100,7 @@ MethodDeclaration _transformFunction( ? originalFunction.isStatic : true, throws: originalFunction.throws, + async: originalFunction.async, ); transformedMethod.statements = _generateStatements( @@ -150,6 +151,9 @@ List _generateStatements( final arguments = generateInvocationParams( localNamer, originalFunction.params, transformedMethod.params); var originalMethodCall = originalCallGenerator(arguments); + if (transformedMethod.async) { + originalMethodCall = 'await $originalMethodCall'; + } if (transformedMethod.throws) { originalMethodCall = 'try $originalMethodCall'; } diff --git a/pkgs/swift2objc/lib/src/transformer/transformers/transform_initializer.dart b/pkgs/swift2objc/lib/src/transformer/transformers/transform_initializer.dart index a7af3c365..293ec96fa 100644 --- a/pkgs/swift2objc/lib/src/transformer/transformers/transform_initializer.dart +++ b/pkgs/swift2objc/lib/src/transformer/transformers/transform_initializer.dart @@ -36,6 +36,7 @@ InitializerDeclaration transformInitializer( hasObjCAnnotation: true, isFailable: originalInitializer.isFailable, throws: originalInitializer.throws, + async: originalInitializer.async, // Because the wrapper class extends NSObject that has an initializer with // no parameters. If we make a similar parameterless initializer we need // to add `override` keyword. @@ -60,6 +61,9 @@ List _generateInitializerStatements( localNamer, originalInitializer.params, transformedInitializer.params); var instanceConstruction = '${wrappedClassInstance.type.swiftType}($arguments)'; + if (transformedInitializer.async) { + instanceConstruction = 'await $instanceConstruction'; + } if (transformedInitializer.throws) { instanceConstruction = 'try $instanceConstruction'; } diff --git a/pkgs/swift2objc/lib/src/transformer/transformers/transform_variable.dart b/pkgs/swift2objc/lib/src/transformer/transformers/transform_variable.dart index 9c061542e..c18e02a50 100644 --- a/pkgs/swift2objc/lib/src/transformer/transformers/transform_variable.dart +++ b/pkgs/swift2objc/lib/src/transformer/transformers/transform_variable.dart @@ -82,6 +82,7 @@ PropertyDeclaration _transformVariable( : true, isConstant: originalVariable.isConstant, throws: originalVariable.throws, + async: originalVariable.async, ); final getterStatements = _generateGetterStatements( diff --git a/pkgs/swift2objc/test/integration/async_input.swift b/pkgs/swift2objc/test/integration/async_input.swift new file mode 100644 index 000000000..44ebd6ef9 --- /dev/null +++ b/pkgs/swift2objc/test/integration/async_input.swift @@ -0,0 +1,12 @@ +import Foundation + +public class MyClass { + public func voidMethod() async {} + public func intMethod(y: Int) async -> MyClass { return MyClass() } + public func asyncThrowsMethod(y: Int) async throws -> MyClass { + return MyClass() + } +} + +public func voidFunc(x: Int, y: Int) async {} +public func intFunc() async -> MyClass { return MyClass() } diff --git a/pkgs/swift2objc/test/integration/async_output.swift b/pkgs/swift2objc/test/integration/async_output.swift new file mode 100644 index 000000000..d10445bb7 --- /dev/null +++ b/pkgs/swift2objc/test/integration/async_output.swift @@ -0,0 +1,39 @@ +// Test preamble text + +import Foundation + +@objc public class GlobalsWrapper: NSObject { + @objc static public func intFuncWrapper() async -> MyClassWrapper { + let result = await intFunc() + return MyClassWrapper(result) + } + + @objc static public func voidFuncWrapper(x: Int, y: Int) async { + return await voidFunc(x: x, y: y) + } + +} + +@objc public class MyClassWrapper: NSObject { + var wrappedInstance: MyClass + + init(_ wrappedInstance: MyClass) { + self.wrappedInstance = wrappedInstance + } + + @objc public func voidMethod() async { + return await wrappedInstance.voidMethod() + } + + @objc public func asyncThrowsMethod(y: Int) async throws -> MyClassWrapper { + let result = try await wrappedInstance.asyncThrowsMethod(y: y) + return MyClassWrapper(result) + } + + @objc public func intMethod(y: Int) async -> MyClassWrapper { + let result = await wrappedInstance.intMethod(y: y) + return MyClassWrapper(result) + } + +} + diff --git a/pkgs/swift2objc/test/unit/parse_function_info_test.dart b/pkgs/swift2objc/test/unit/parse_function_info_test.dart index 909b07cd0..3d86a1b7b 100644 --- a/pkgs/swift2objc/test/unit/parse_function_info_test.dart +++ b/pkgs/swift2objc/test/unit/parse_function_info_test.dart @@ -79,6 +79,7 @@ void main() { expectEqualParams(info.params, expectedParams); expect(info.throws, isFalse); + expect(info.async, isFalse); }); test('Three params with some optional', () { @@ -140,6 +141,7 @@ void main() { expectEqualParams(info.params, expectedParams); expect(info.throws, isFalse); + expect(info.async, isFalse); }); test('One param', () { @@ -171,6 +173,7 @@ void main() { expectEqualParams(info.params, expectedParams); expect(info.throws, isFalse); + expect(info.async, isFalse); }); test('No params', () { @@ -187,6 +190,7 @@ void main() { expectEqualParams(info.params, []); expect(info.throws, isFalse); + expect(info.async, isFalse); }); test('Function with return type', () { @@ -227,6 +231,7 @@ void main() { expectEqualParams(info.params, expectedParams); expect(info.throws, isFalse); + expect(info.async, isFalse); }); test('Function with no params with return type', () { @@ -250,6 +255,7 @@ void main() { expectEqualParams(info.params, []); expect(info.throws, isFalse); + expect(info.async, isFalse); }); test('Function with no params and no return type', () { @@ -268,6 +274,7 @@ void main() { expectEqualParams(info.params, []); expect(info.throws, isFalse); + expect(info.async, isFalse); }); test('Function with return type that throws', () { @@ -308,6 +315,7 @@ void main() { expectEqualParams(info.params, expectedParams); expect(info.throws, isTrue); + expect(info.async, isFalse); }); test('Function with no return type that throws', () { @@ -342,6 +350,7 @@ void main() { expectEqualParams(info.params, expectedParams); expect(info.throws, isTrue); + expect(info.async, isFalse); }); test('Function with no params that throws', () { @@ -361,6 +370,91 @@ void main() { expectEqualParams(info.params, []); expect(info.throws, isTrue); + expect(info.async, isFalse); + }); + + test('Function with async annotation', () { + final json = Json(jsonDecode( + ''' + [ + { "kind": "keyword", "spelling": "func" }, + { "kind": "text", "spelling": " " }, + { "kind": "identifier", "spelling": "foo" }, + { "kind": "text", "spelling": "(" }, + { "kind": "externalParam", "spelling": "parameter" }, + { "kind": "text", "spelling": ": " }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { "kind": "text", "spelling": ") " }, + { "kind": "keyword", "spelling": "async" }, + { "kind": "text", "spelling": " -> " }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + ''', + )); + + final info = parseFunctionInfo(json, emptySymbolgraph); + + final expectedParams = [ + Parameter( + name: 'parameter', + type: intType, + ), + ]; + + expectEqualParams(info.params, expectedParams); + expect(info.throws, isFalse); + expect(info.async, isTrue); + }); + + test('Function with async and throws annotations', () { + final json = Json(jsonDecode( + ''' + [ + { "kind": "keyword", "spelling": "func" }, + { "kind": "text", "spelling": " " }, + { "kind": "identifier", "spelling": "foo" }, + { "kind": "text", "spelling": "(" }, + { "kind": "externalParam", "spelling": "parameter" }, + { "kind": "text", "spelling": ": " }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { "kind": "text", "spelling": ") " }, + { "kind": "keyword", "spelling": "async" }, + { "kind": "text", "spelling": " " }, + { "kind": "keyword", "spelling": "throws" }, + { "kind": "text", "spelling": " -> " }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + ''', + )); + + final info = parseFunctionInfo(json, emptySymbolgraph); + + final expectedParams = [ + Parameter( + name: 'parameter', + type: intType, + ), + ]; + + expectEqualParams(info.params, expectedParams); + expect(info.throws, isTrue); + expect(info.async, isTrue); }); }); From aa82b970f720b8e1557f972ef91e65b1e92b19c8 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 4 Dec 2024 12:43:29 +1300 Subject: [PATCH 4/4] [ffigen][swift2objc] Some small fixes (#1777) --- pkgs/ffigen/lib/ffigen.dart | 9 ++++- .../lib/src/code_generator/pointer.dart | 15 ++++++++ pkgs/ffigen/lib/src/config_provider.dart | 1 + pkgs/ffigen/lib/src/header_parser/parser.dart | 1 - .../sub_parsers/objcinterfacedecl_parser.dart | 2 +- .../src/visitor/fix_overridden_methods.dart | 4 ++- .../large_objc_test.dart | 1 - .../test/unit_tests/subtyping_test.dart | 36 ++++++++++++++----- .../src/objective_c_bindings_generated.dart | 6 ++-- .../built_in/built_in_declaration.dart | 2 ++ pkgs/swift2objc/lib/src/config.dart | 18 +++++----- 11 files changed, 70 insertions(+), 25 deletions(-) diff --git a/pkgs/ffigen/lib/ffigen.dart b/pkgs/ffigen/lib/ffigen.dart index 351ffb857..aa1f364e5 100644 --- a/pkgs/ffigen/lib/ffigen.dart +++ b/pkgs/ffigen/lib/ffigen.dart @@ -8,5 +8,12 @@ /// https://pub.dev/packages/ffigen for details. library ffigen; -export 'src/config_provider.dart' show Config, YamlConfig; +export 'src/config_provider.dart' + show + Config, + DeclarationFilters, + ExternalVersions, + Language, + Versions, + YamlConfig; export 'src/ffigen.dart' show FfiGen; diff --git a/pkgs/ffigen/lib/src/code_generator/pointer.dart b/pkgs/ffigen/lib/src/code_generator/pointer.dart index b4a21c01e..4df2e867c 100644 --- a/pkgs/ffigen/lib/src/code_generator/pointer.dart +++ b/pkgs/ffigen/lib/src/code_generator/pointer.dart @@ -154,6 +154,15 @@ class ObjCObjectPointer extends PointerType { @override String? generateRetain(String value) => 'objc_retain($value)'; + + @override + bool isSupertypeOf(Type other) { + other = other.typealiasType; + // id/Object* is a supertype of all ObjC objects and blocks. + return other is ObjCObjectPointer || + other is ObjCInterface || + other is ObjCBlock; + } } /// A pointer to an Objective C block. @@ -168,4 +177,10 @@ class ObjCBlockPointer extends ObjCObjectPointer { @override String? generateRetain(String value) => 'objc_retainBlock($value)'; + + @override + bool isSupertypeOf(Type other) { + other = other.typealiasType; + return other is ObjCBlockPointer || other is ObjCBlock; + } } diff --git a/pkgs/ffigen/lib/src/config_provider.dart b/pkgs/ffigen/lib/src/config_provider.dart index f3b99499c..8feb6fe89 100644 --- a/pkgs/ffigen/lib/src/config_provider.dart +++ b/pkgs/ffigen/lib/src/config_provider.dart @@ -6,4 +6,5 @@ library config_provider; export 'config_provider/config.dart'; +export 'config_provider/config_types.dart'; export 'config_provider/yaml_config.dart'; diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index 15dc0f5e3..882e68c3f 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -12,7 +12,6 @@ import 'package:logging/logging.dart'; import '../code_generator.dart'; import '../code_generator/utils.dart'; import '../config_provider.dart'; -import '../config_provider/config_types.dart'; import '../strings.dart' as strings; import '../visitor/apply_config_filters.dart'; import '../visitor/ast.dart'; diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart index db4e70f0f..687ba22e8 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart @@ -174,7 +174,7 @@ void _parseSuperType(clang_types.CXCursor cursor, ObjCInterface itf) { kind: ObjCMethodKind.propertySetter, isClassMethod: isClassMethod, isOptional: isOptionalMethod, - returnType: NativeType(SupportedNativeType.voidType), + returnType: voidType, family: null, ); setter.params diff --git a/pkgs/ffigen/lib/src/visitor/fix_overridden_methods.dart b/pkgs/ffigen/lib/src/visitor/fix_overridden_methods.dart index d06c7db1a..62914e53f 100644 --- a/pkgs/ffigen/lib/src/visitor/fix_overridden_methods.dart +++ b/pkgs/ffigen/lib/src/visitor/fix_overridden_methods.dart @@ -130,7 +130,9 @@ class FixOverriddenMethodsVisitation extends Visitation { final (root, rootMethod) = _findRootWithMethod(node, method); // If method and rootMethod are the same kind, then there's nothing to do. if ((method.kind == ObjCMethodKind.propertyGetter) == - (rootMethod.kind == ObjCMethodKind.propertyGetter)) continue; + (rootMethod.kind == ObjCMethodKind.propertyGetter)) { + continue; + } _convertAllSubtreeMethodsToProperties(root, rootMethod); } } diff --git a/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart b/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart index 212f997df..58f919c54 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart @@ -14,7 +14,6 @@ import 'dart:io'; import 'package:ffigen/ffigen.dart'; import 'package:ffigen/src/code_generator/utils.dart'; -import 'package:ffigen/src/config_provider/config.dart'; import 'package:ffigen/src/config_provider/config_types.dart'; import 'package:logging/logging.dart'; import 'package:pub_semver/pub_semver.dart'; diff --git a/pkgs/ffigen/test/unit_tests/subtyping_test.dart b/pkgs/ffigen/test/unit_tests/subtyping_test.dart index 5ac548ca8..191767dad 100644 --- a/pkgs/ffigen/test/unit_tests/subtyping_test.dart +++ b/pkgs/ffigen/test/unit_tests/subtyping_test.dart @@ -32,6 +32,14 @@ void main() { final uncle = makeInterface('Uncle', grandparent); final child = makeInterface('Child', parent); + ObjCBlock makeBlock(Type returnType, List argTypes) => ObjCBlock( + returnType: returnType, + params: [ + for (final t in argTypes) Parameter(type: t, objCConsumed: false), + ], + returnsRetained: false, + builtInFunctions: builtInFunctions); + group('ObjCInterface', () { test('subtype', () { expect(parent.isSubtypeOf(parent), isTrue); @@ -140,14 +148,6 @@ void main() { }); group('ObjCBlock', () { - ObjCBlock makeBlock(Type returnType, List argTypes) => ObjCBlock( - returnType: returnType, - params: [ - for (final t in argTypes) Parameter(type: t, objCConsumed: false), - ], - returnsRetained: false, - builtInFunctions: builtInFunctions); - test('covariant returns', () { // Return types are covariant. S Function() <: T Function() if S <: T. final returnsParent = makeBlock(parent, []); @@ -237,5 +237,25 @@ void main() { expect(makeTypealias(parent).isSubtypeOf(child), isFalse); expect(parent.isSubtypeOf(makeTypealias(child)), isFalse); }); + + test('ObjCObjectPointer', () { + expect(ObjCObjectPointer().isSubtypeOf(ObjCObjectPointer()), isTrue); + expect(parent.isSubtypeOf(ObjCObjectPointer()), isTrue); + expect(ObjCObjectPointer().isSubtypeOf(parent), isFalse); + + final block = makeBlock(voidType, []); + expect(block.isSubtypeOf(ObjCObjectPointer()), isTrue); + expect(ObjCObjectPointer().isSubtypeOf(block), isFalse); + }); + + test('ObjCBlockPointer', () { + expect(ObjCBlockPointer().isSubtypeOf(ObjCBlockPointer()), isTrue); + expect(parent.isSubtypeOf(ObjCBlockPointer()), isFalse); + expect(ObjCBlockPointer().isSubtypeOf(parent), isFalse); + + final block = makeBlock(voidType, []); + expect(block.isSubtypeOf(ObjCBlockPointer()), isTrue); + expect(ObjCBlockPointer().isSubtypeOf(block), isFalse); + }); }); } diff --git a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart index 4a8f27735..e36f5d26e 100644 --- a/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart +++ b/pkgs/objective_c/lib/src/objective_c_bindings_generated.dart @@ -2362,7 +2362,7 @@ class NSItemProvider extends NSObject { /// setSuggestedName: set suggestedName(NSString? value) { - return _objc_msgSend_1jdvcbf(this.ref.pointer, _sel_setSuggestedName_, + _objc_msgSend_1jdvcbf(this.ref.pointer, _sel_setSuggestedName_, value?.ref.pointer ?? ffi.nullptr); } @@ -3074,7 +3074,7 @@ class NSMutableData extends NSData { /// setLength: set length(int value) { - return _objc_msgSend_1i9r4xy(this.ref.pointer, _sel_setLength_, value); + _objc_msgSend_1i9r4xy(this.ref.pointer, _sel_setLength_, value); } } @@ -6228,7 +6228,7 @@ class NSStream extends NSObject { /// setDelegate: set delegate(objc.ObjCObjectBase? value) { - return _objc_msgSend_1jdvcbf( + _objc_msgSend_1jdvcbf( this.ref.pointer, _sel_setDelegate_, value?.ref.pointer ?? ffi.nullptr); } diff --git a/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart b/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart index f3d2f319b..9c75ba42f 100644 --- a/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart +++ b/pkgs/swift2objc/lib/src/ast/declarations/built_in/built_in_declaration.dart @@ -10,6 +10,7 @@ enum BuiltInDeclaration implements Declaration, ObjCAnnotatable { swiftNSObject(id: 'c:objc(cs)NSObject', name: 'NSObject'), swiftString(id: 's:SS', name: 'String'), swiftInt(id: 's:Si', name: 'Int'), + swiftFloat(id: 's:Sf', name: 'Float'), swiftDouble(id: 's:Sd', name: 'Double'), swiftBool(id: 's:Sb', name: 'Bool'), swiftVoid(id: 's:s4Voida', name: 'Void'); @@ -32,6 +33,7 @@ enum BuiltInDeclaration implements Declaration, ObjCAnnotatable { final objectType = BuiltInDeclaration.swiftNSObject.asDeclaredType; final stringType = BuiltInDeclaration.swiftString.asDeclaredType; final intType = BuiltInDeclaration.swiftInt.asDeclaredType; +final floatType = BuiltInDeclaration.swiftFloat.asDeclaredType; final doubleType = BuiltInDeclaration.swiftDouble.asDeclaredType; final boolType = BuiltInDeclaration.swiftBool.asDeclaredType; final voidType = BuiltInDeclaration.swiftVoid.asDeclaredType; diff --git a/pkgs/swift2objc/lib/src/config.dart b/pkgs/swift2objc/lib/src/config.dart index 4f2ac6eba..2f05353c2 100644 --- a/pkgs/swift2objc/lib/src/config.dart +++ b/pkgs/swift2objc/lib/src/config.dart @@ -22,14 +22,14 @@ class Config { /// Specify where the wrapper swift file will be output. final Uri outputFile; - /// Specify where the wrapper swift file will be output. + /// Text inserted into the [outputFile] before the generated output. final String? preamble; /// Specify where to output the intermidiate files (i.g the symbolgraph json). /// If this is null, a teemp directory will be generated in the system temp /// directory (using `Directory.systemTemp`) and then deleted. /// Specifying a temp directory would prevent the tool from deleting the - /// intermediate files after generating the wrapper + /// intermediate files after generating the wrapper. final Uri? tempDir; const Config({ @@ -46,12 +46,12 @@ sealed class InputConfig { Command? get symbolgraphCommand; } -/// Used to generate a objc wrapper for one or more swift files +/// Used to generate a objc wrapper for one or more swift files. class FilesInputConfig implements InputConfig { - /// The swift file(s) to generate a wrapper for + /// The swift file(s) to generate a wrapper for. final List files; - /// The name of the module files generated by `swiftc in `tempDir` + /// The name of the module files generated by `swiftc in `tempDir`. final String generatedModuleName; FilesInputConfig({ @@ -74,17 +74,17 @@ class FilesInputConfig implements InputConfig { ); } -/// Used to generate a objc wrapper for a built-in swift module +/// Used to generate a objc wrapper for a built-in swift module. /// (e.g, AVFoundation) class ModuleInputConfig implements InputConfig { - /// The swift module to generate a wrapper for + /// The swift module to generate a wrapper for. final String module; - /// The target to generate code for + /// The target to generate code for. /// (e.g `x86_64-apple-ios17.0-simulator`) final String target; - /// The sdk to compile against + /// The sdk to compile against. /// (e.g `/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sd`) final Uri sdk;