diff --git a/.ci/flutter_master.version b/.ci/flutter_master.version index 49a8a2b24f82..be931f8a82b0 100644 --- a/.ci/flutter_master.version +++ b/.ci/flutter_master.version @@ -1 +1 @@ -e81907e07a385e79e67734162d435b11f5339000 +c00d241938b1b1ddf09121ce7e1cc62873f7af91 diff --git a/.cirrus.yml b/.cirrus.yml index bf96b7b7d519..71b801f4223f 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,4 +1,4 @@ -gcp_credentials: ENCRYPTED[!9c8e92e8da192ce2a51b7d4ed9948c4250d0bae3660193d9b901196c9692abbebe784d4a32e9f38b328571d65f6e7aed!] +gcp_credentials: ENCRYPTED[!9409b709ab4de7293a70606cca13eaf42e9cbc704e8a6b4e3d2b09484cf997cbd2334e1eeafe23626ad07a726106df90!] # Run on PRs and main branch post submit only. Don't run tests when tagging. only_if: $CIRRUS_TAG == '' && ($CIRRUS_PR != '' || $CIRRUS_BRANCH == 'main') diff --git a/.github/workflows/pull_request_label.yml b/.github/workflows/pull_request_label.yml index a474d2c4b5e4..ddcf40008c3c 100644 --- a/.github/workflows/pull_request_label.yml +++ b/.github/workflows/pull_request_label.yml @@ -21,7 +21,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@9fcb2c2f5584144ca754f8bfe8c6f81e77753375 + - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" sync-labels: true diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b45749f17859..75b7e013e021 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -49,6 +49,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1813ca74c3faaa3a2da2070b9b8a0b3e7373a0d8 # v1.0.26 + uses: github/codeql-action/upload-sarif@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v1.0.26 with: sarif_file: results.sarif diff --git a/packages/camera/camera_android_camerax/example/android/build.gradle b/packages/camera/camera_android_camerax/example/android/build.gradle index 702f1d280649..601db113a9e1 100644 --- a/packages/camera/camera_android_camerax/example/android/build.gradle +++ b/packages/camera/camera_android_camerax/example/android/build.gradle @@ -1,7 +1,7 @@ buildscript { - // This version should intentionally be a 1.7.* version and lower than the + // This version should intentionally be a 1.7.* version and lower than the // version of kotlin-bom defined in packages/camera/camera_android_camerax/android/build.gradle. - // This tests that the kotlin version resolution continues to work. + // This tests that the kotlin version resolution continues to work. ext.kotlin_version = '1.7.10' repositories { google() @@ -16,6 +16,12 @@ buildscript { allprojects { repositories { + // See https://github.com/flutter/flutter/wiki/Plugins-and-Packages-repository-structure#gradle-structure for more info. + def artifactRepoKey = 'ARTIFACT_HUB_REPOSITORY' + if (System.getenv().containsKey(artifactRepoKey)) { + println "Using artifact hub" + maven { url System.getenv(artifactRepoKey) } + } google() mavenCentral() } diff --git a/packages/camera/camera_android_camerax/example/android/settings.gradle b/packages/camera/camera_android_camerax/example/android/settings.gradle index 44e62bcf06ae..3a97314b38c7 100644 --- a/packages/camera/camera_android_camerax/example/android/settings.gradle +++ b/packages/camera/camera_android_camerax/example/android/settings.gradle @@ -9,3 +9,16 @@ localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } def flutterSdkPath = properties.getProperty("flutter.sdk") assert flutterSdkPath != null, "flutter.sdk not set in local.properties" apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" + +// See https://github.com/flutter/flutter/wiki/Plugins-and-Packages-repository-structure#gradle-structure for more info. +buildscript { + repositories { + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "gradle.plugin.com.google.cloud.artifactregistry:artifactregistry-gradle-plugin:2.2.1" + } +} +apply plugin: "com.google.cloud.artifactregistry.gradle-plugin" diff --git a/packages/camera/camera_web/CHANGELOG.md b/packages/camera/camera_web/CHANGELOG.md index 1d736b0ac541..e820f450fe2c 100644 --- a/packages/camera/camera_web/CHANGELOG.md +++ b/packages/camera/camera_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.2 + +* Changes `availableCameras` to not ask for the microphone permission. + ## 0.3.1+4 * Removes obsolete null checks on non-nullable values. diff --git a/packages/camera/camera_web/example/integration_test/camera_web_test.dart b/packages/camera/camera_web/example/integration_test/camera_web_test.dart index 784249e68481..6c73bcf76bdc 100644 --- a/packages/camera/camera_web/example/integration_test/camera_web_test.dart +++ b/packages/camera/camera_web/example/integration_test/camera_web_test.dart @@ -98,24 +98,18 @@ void main() { ); }); - testWidgets('requests video and audio permissions', - (WidgetTester tester) async { + testWidgets('requests video permissions', (WidgetTester tester) async { final List _ = await CameraPlatform.instance.availableCameras(); verify( - () => cameraService.getMediaStreamForOptions( - const CameraOptions( - audio: AudioConstraints(enabled: true), - ), - ), + () => cameraService.getMediaStreamForOptions(const CameraOptions()), ).called(1); }); testWidgets( 'releases the camera stream ' - 'used to request video and audio permissions', - (WidgetTester tester) async { + 'used to request video permissions', (WidgetTester tester) async { final MockMediaStreamTrack videoTrack = MockMediaStreamTrack(); bool videoTrackStopped = false; @@ -124,11 +118,7 @@ void main() { }); when( - () => cameraService.getMediaStreamForOptions( - const CameraOptions( - audio: AudioConstraints(enabled: true), - ), - ), + () => cameraService.getMediaStreamForOptions(const CameraOptions()), ).thenAnswer( (_) => Future.value( FakeMediaStream([videoTrack]), diff --git a/packages/camera/camera_web/lib/src/camera_web.dart b/packages/camera/camera_web/lib/src/camera_web.dart index 52fdc1c3f8d6..be41e7b9a874 100644 --- a/packages/camera/camera_web/lib/src/camera_web.dart +++ b/packages/camera/camera_web/lib/src/camera_web.dart @@ -96,15 +96,11 @@ class CameraPlugin extends CameraPlatform { ); } - // Request video and audio permissions. + // Request video permissions only. final html.MediaStream cameraStream = - await _cameraService.getMediaStreamForOptions( - const CameraOptions( - audio: AudioConstraints(enabled: true), - ), - ); + await _cameraService.getMediaStreamForOptions(const CameraOptions()); - // Release the camera stream used to request video and audio permissions. + // Release the camera stream used to request video permissions. cameraStream .getVideoTracks() .forEach((html.MediaStreamTrack videoTrack) => videoTrack.stop()); diff --git a/packages/camera/camera_web/pubspec.yaml b/packages/camera/camera_web/pubspec.yaml index 382444d3624b..19148a4fcd99 100644 --- a/packages/camera/camera_web/pubspec.yaml +++ b/packages/camera/camera_web/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_web description: A Flutter plugin for getting information about and controlling the camera on Web. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.3.1+4 +version: 0.3.2 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/dynamic_layouts/example/test/staggered_example_test.dart b/packages/dynamic_layouts/example/test/staggered_example_test.dart index caa6c38aa70a..c43b4ff413d6 100644 --- a/packages/dynamic_layouts/example/test/staggered_example_test.dart +++ b/packages/dynamic_layouts/example/test/staggered_example_test.dart @@ -9,13 +9,9 @@ import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('StaggeredExample lays out children correctly', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(400, 200); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(400, 200); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( const MaterialApp( diff --git a/packages/dynamic_layouts/test/staggered_layout_test.dart b/packages/dynamic_layouts/test/staggered_layout_test.dart index 622f03aed6c4..e86b2b4e3db3 100644 --- a/packages/dynamic_layouts/test/staggered_layout_test.dart +++ b/packages/dynamic_layouts/test/staggered_layout_test.dart @@ -11,13 +11,9 @@ void main() { testWidgets( 'DynamicGridView works when using DynamicSliverGridDelegateWithFixedCrossAxisCount', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(400, 100); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(400, 100); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( MaterialApp( @@ -59,13 +55,9 @@ void main() { testWidgets( 'DynamicGridView works when using DynamicSliverGridDelegateWithMaxCrossAxisExtent', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(440, 100); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(440, 100); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( MaterialApp( @@ -106,13 +98,9 @@ void main() { group('DynamicGridView.staggered', () { testWidgets('DynamicGridView.staggered works with simple layout', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(400, 100); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(400, 100); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( MaterialApp( @@ -158,13 +146,9 @@ void main() { }); testWidgets('DynamicGridView.staggered works with a horizontal grid', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(100, 500); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(100, 500); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( MaterialApp( @@ -216,13 +200,9 @@ void main() { }); testWidgets('DynamicGridView.staggered works with a reversed grid', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(600, 200); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(600, 200); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( MaterialApp( @@ -290,13 +270,10 @@ void main() { testWidgets('DynamicGridView.staggered deletes children appropriately', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(600, 1000); + tester.view.physicalSize = const Size(600, 1000); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; final List children = List.generate( 50, (int index) => SizedBox( @@ -375,13 +352,9 @@ void main() { group('DynamicGridView.builder', () { testWidgets('DynamicGridView.builder works with a staggered layout', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(400, 100); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(400, 100); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( MaterialApp( @@ -430,13 +403,9 @@ void main() { testWidgets( 'DynamicGridView.builder works with an infinite grid using a staggered layout', (WidgetTester tester) async { - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(400, 100); - - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatioTestValue = 1.0; + tester.view.physicalSize = const Size(400, 100); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.reset); await tester.pumpWidget( MaterialApp( diff --git a/packages/dynamic_layouts/test/wrap_layout_test.dart b/packages/dynamic_layouts/test/wrap_layout_test.dart index 1b0f7958c93c..31daa8b3476e 100644 --- a/packages/dynamic_layouts/test/wrap_layout_test.dart +++ b/packages/dynamic_layouts/test/wrap_layout_test.dart @@ -508,9 +508,7 @@ void main() { expect(find.text('Item 4'), findsNothing); await tester.binding.setSurfaceSize(const Size(280, 100)); // resets the screen to its original size after the test end - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - addTearDown(tester.binding.window.clearPhysicalSizeTestValue); + addTearDown(tester.view.resetPhysicalSize); await tester.pumpAndSettle(); expect(find.text('Item 0'), findsOneWidget); expect(find.text('Item 1'), findsOneWidget); @@ -572,9 +570,7 @@ void main() { await tester.binding.setSurfaceSize(const Size(560, 100)); // resets the screen to its original size after the test end - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - addTearDown(tester.binding.window.clearPhysicalSizeTestValue); + addTearDown(tester.view.resetPhysicalSize); await tester.pumpAndSettle(); expect(find.text('Item 0'), findsOneWidget); diff --git a/packages/go_router_builder/CHANGELOG.md b/packages/go_router_builder/CHANGELOG.md index cb3433fb376c..3cd835996966 100644 --- a/packages/go_router_builder/CHANGELOG.md +++ b/packages/go_router_builder/CHANGELOG.md @@ -1,3 +1,11 @@ +## 2.3.0 + +* Adds Support for StatefulShellRoute + +## 2.2.5 + +* Fixes a bug where shell routes without const constructor were not generated correctly. + ## 2.2.4 * Bumps example go_router version to v10.0.0 and migrate example code. diff --git a/packages/go_router_builder/README.md b/packages/go_router_builder/README.md index 797231c6be8f..73faf973937c 100644 --- a/packages/go_router_builder/README.md +++ b/packages/go_router_builder/README.md @@ -8,12 +8,12 @@ To use `go_router_builder`, you need to have the following dependencies in ```yaml dependencies: # ...along with your other dependencies - go_router: ^7.0.0 + go_router: ^9.0.3 dev_dependencies: # ...along with your other dev-dependencies build_runner: ^2.0.0 - go_router_builder: ^2.0.0 + go_router_builder: ^2.3.0 ``` ### Source code diff --git a/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart b/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart index 31f9d4bca6d4..6151889582d0 100644 --- a/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart +++ b/packages/go_router_builder/example/lib/shell_route_with_keys_example.g.dart @@ -26,8 +26,8 @@ RouteBase get $myShellRouteData => ShellRouteData.$route( routes: [ GoRouteData.$route( path: ':id', - factory: $UserRouteDataExtension._fromState, parentNavigatorKey: UserRouteData.$parentNavigatorKey, + factory: $UserRouteDataExtension._fromState, ), ], ), diff --git a/packages/go_router_builder/example/lib/stateful_shell_route_example.dart b/packages/go_router_builder/example/lib/stateful_shell_route_example.dart new file mode 100644 index 000000000000..9e9748e870dc --- /dev/null +++ b/packages/go_router_builder/example/lib/stateful_shell_route_example.dart @@ -0,0 +1,266 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +part 'stateful_shell_route_example.g.dart'; + +final GlobalKey _sectionANavigatorKey = + GlobalKey(debugLabel: 'sectionANav'); +void main() => runApp(App()); + +class App extends StatelessWidget { + App({super.key}); + + @override + Widget build(BuildContext context) => MaterialApp.router( + routerConfig: _router, + ); + + final GoRouter _router = GoRouter( + routes: $appRoutes, + initialLocation: '/detailsA', + ); +} + +class HomeScreen extends StatelessWidget { + const HomeScreen({super.key}); + + @override + Widget build(BuildContext context) => Scaffold( + appBar: AppBar(title: const Text('foo')), + ); +} + +@TypedStatefulShellRoute( + branches: >[ + TypedStatefulShellBranch( + routes: >[ + TypedGoRoute(path: '/detailsA'), + ], + ), + TypedStatefulShellBranch( + routes: >[ + TypedGoRoute(path: '/detailsB'), + ], + ), + ], +) +class MyShellRouteData extends StatefulShellRouteData { + const MyShellRouteData(); + + @override + Widget builder( + BuildContext context, + GoRouterState state, + StatefulNavigationShell navigationShell, + ) { + return navigationShell; + } + + static const String $restorationScopeId = 'restorationScopeId'; + + static Widget $navigatorContainerBuilder(BuildContext context, + StatefulNavigationShell navigationShell, List children) { + return ScaffoldWithNavBar( + navigationShell: navigationShell, + children: children, + ); + } +} + +class BranchAData extends StatefulShellBranchData { + const BranchAData(); +} + +class BranchBData extends StatefulShellBranchData { + const BranchBData(); + + static final GlobalKey $navigatorKey = _sectionANavigatorKey; + static const String $restorationScopeId = 'restorationScopeId'; +} + +class DetailsARouteData extends GoRouteData { + const DetailsARouteData(); + + @override + Widget build(BuildContext context, GoRouterState state) { + return const DetailsScreen(label: 'A'); + } +} + +class DetailsBRouteData extends GoRouteData { + const DetailsBRouteData(); + + @override + Widget build(BuildContext context, GoRouterState state) { + return const DetailsScreen(label: 'B'); + } +} + +/// Builds the "shell" for the app by building a Scaffold with a +/// BottomNavigationBar, where [child] is placed in the body of the Scaffold. +class ScaffoldWithNavBar extends StatelessWidget { + /// Constructs an [ScaffoldWithNavBar]. + const ScaffoldWithNavBar({ + required this.navigationShell, + required this.children, + Key? key, + }) : super(key: key ?? const ValueKey('ScaffoldWithNavBar')); + + /// The navigation shell and container for the branch Navigators. + final StatefulNavigationShell navigationShell; + + /// The children (branch Navigators) to display in a custom container + /// ([AnimatedBranchContainer]). + final List children; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: AnimatedBranchContainer( + currentIndex: navigationShell.currentIndex, + children: children, + ), + bottomNavigationBar: BottomNavigationBar( + // Here, the items of BottomNavigationBar are hard coded. In a real + // world scenario, the items would most likely be generated from the + // branches of the shell route, which can be fetched using + // `navigationShell.route.branches`. + items: const [ + BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Section A'), + BottomNavigationBarItem(icon: Icon(Icons.work), label: 'Section B'), + ], + currentIndex: navigationShell.currentIndex, + onTap: (int index) => _onTap(context, index), + ), + ); + } + + /// Navigate to the current location of the branch at the provided index when + /// tapping an item in the BottomNavigationBar. + void _onTap(BuildContext context, int index) { + // When navigating to a new branch, it's recommended to use the goBranch + // method, as doing so makes sure the last navigation state of the + // Navigator for the branch is restored. + navigationShell.goBranch( + index, + // A common pattern when using bottom navigation bars is to support + // navigating to the initial location when tapping the item that is + // already active. This example demonstrates how to support this behavior, + // using the initialLocation parameter of goBranch. + initialLocation: index == navigationShell.currentIndex, + ); + } +} + +/// Custom branch Navigator container that provides animated transitions +/// when switching branches. +class AnimatedBranchContainer extends StatelessWidget { + /// Creates a AnimatedBranchContainer + const AnimatedBranchContainer( + {super.key, required this.currentIndex, required this.children}); + + /// The index (in [children]) of the branch Navigator to display. + final int currentIndex; + + /// The children (branch Navigators) to display in this container. + final List children; + + @override + Widget build(BuildContext context) { + return Stack( + children: children.mapIndexed( + (int index, Widget navigator) { + return AnimatedScale( + scale: index == currentIndex ? 1 : 1.5, + duration: const Duration(milliseconds: 400), + child: AnimatedOpacity( + opacity: index == currentIndex ? 1 : 0, + duration: const Duration(milliseconds: 400), + child: _branchNavigatorWrapper(index, navigator), + ), + ); + }, + ).toList()); + } + + Widget _branchNavigatorWrapper(int index, Widget navigator) => IgnorePointer( + ignoring: index != currentIndex, + child: TickerMode( + enabled: index == currentIndex, + child: navigator, + ), + ); +} + +/// The details screen for either the A or B screen. +class DetailsScreen extends StatefulWidget { + /// Constructs a [DetailsScreen]. + const DetailsScreen({ + required this.label, + this.param, + this.extra, + super.key, + }); + + /// The label to display in the center of the screen. + final String label; + + /// Optional param + final String? param; + + /// Optional extra object + final Object? extra; + @override + State createState() => DetailsScreenState(); +} + +/// The state for DetailsScreen +class DetailsScreenState extends State { + int _counter = 0; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Details Screen - ${widget.label}'), + ), + body: _build(context), + ); + } + + Widget _build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('Details for ${widget.label} - Counter: $_counter', + style: Theme.of(context).textTheme.titleLarge), + const Padding(padding: EdgeInsets.all(4)), + TextButton( + onPressed: () { + setState(() { + _counter++; + }); + }, + child: const Text('Increment counter'), + ), + const Padding(padding: EdgeInsets.all(8)), + if (widget.param != null) + Text('Parameter: ${widget.param!}', + style: Theme.of(context).textTheme.titleMedium), + const Padding(padding: EdgeInsets.all(8)), + if (widget.extra != null) + Text('Extra: ${widget.extra!}', + style: Theme.of(context).textTheme.titleMedium), + ], + ), + ); + } +} diff --git a/packages/go_router_builder/example/lib/stateful_shell_route_example.g.dart b/packages/go_router_builder/example/lib/stateful_shell_route_example.g.dart new file mode 100644 index 000000000000..9be15d9859a4 --- /dev/null +++ b/packages/go_router_builder/example/lib/stateful_shell_route_example.g.dart @@ -0,0 +1,80 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: always_specify_types, public_member_api_docs + +part of 'stateful_shell_route_example.dart'; + +// ************************************************************************** +// GoRouterGenerator +// ************************************************************************** + +List get $appRoutes => [ + $myShellRouteData, + ]; + +RouteBase get $myShellRouteData => StatefulShellRouteData.$route( + restorationScopeId: MyShellRouteData.$restorationScopeId, + navigatorContainerBuilder: MyShellRouteData.$navigatorContainerBuilder, + factory: $MyShellRouteDataExtension._fromState, + branches: [ + StatefulShellBranchData.$branch( + routes: [ + GoRouteData.$route( + path: '/detailsA', + factory: $DetailsARouteDataExtension._fromState, + ), + ], + ), + StatefulShellBranchData.$branch( + navigatorKey: BranchBData.$navigatorKey, + restorationScopeId: BranchBData.$restorationScopeId, + routes: [ + GoRouteData.$route( + path: '/detailsB', + factory: $DetailsBRouteDataExtension._fromState, + ), + ], + ), + ], + ); + +extension $MyShellRouteDataExtension on MyShellRouteData { + static MyShellRouteData _fromState(GoRouterState state) => + const MyShellRouteData(); +} + +extension $DetailsARouteDataExtension on DetailsARouteData { + static DetailsARouteData _fromState(GoRouterState state) => + const DetailsARouteData(); + + String get location => GoRouteData.$location( + '/detailsA', + ); + + void go(BuildContext context) => context.go(location); + + Future push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); + + void replace(BuildContext context) => context.replace(location); +} + +extension $DetailsBRouteDataExtension on DetailsBRouteData { + static DetailsBRouteData _fromState(GoRouterState state) => + const DetailsBRouteData(); + + String get location => GoRouteData.$location( + '/detailsB', + ); + + void go(BuildContext context) => context.go(location); + + Future push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); + + void replace(BuildContext context) => context.replace(location); +} diff --git a/packages/go_router_builder/example/pubspec.yaml b/packages/go_router_builder/example/pubspec.yaml index 3dea2475de71..1cc07ea34302 100644 --- a/packages/go_router_builder/example/pubspec.yaml +++ b/packages/go_router_builder/example/pubspec.yaml @@ -6,6 +6,7 @@ environment: sdk: ">=2.18.0 <4.0.0" dependencies: + collection: ^1.15.0 flutter: sdk: flutter go_router: ^10.0.0 diff --git a/packages/go_router_builder/example/test/stateful_shell_route_test.dart b/packages/go_router_builder/example/test/stateful_shell_route_test.dart new file mode 100644 index 000000000000..f885e54c531e --- /dev/null +++ b/packages/go_router_builder/example/test/stateful_shell_route_test.dart @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. 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:flutter_test/flutter_test.dart'; +import 'package:go_router_builder_example/stateful_shell_route_example.dart'; + +void main() { + testWidgets('Navigate between section A and section B', + (WidgetTester tester) async { + await tester.pumpWidget(App()); + expect(find.text('Details for A - Counter: 0'), findsOneWidget); + + await tester.tap(find.text('Increment counter')); + await tester.pumpAndSettle(); + expect(find.text('Details for A - Counter: 1'), findsOneWidget); + + await tester.tap(find.text('Section B')); + await tester.pumpAndSettle(); + expect(find.text('Details for B - Counter: 0'), findsOneWidget); + + await tester.tap(find.text('Section A')); + await tester.pumpAndSettle(); + expect(find.text('Details for A - Counter: 1'), findsOneWidget); + }); +} diff --git a/packages/go_router_builder/lib/src/go_router_generator.dart b/packages/go_router_builder/lib/src/go_router_generator.dart index cf57329f3a34..e094d1f98edd 100644 --- a/packages/go_router_builder/lib/src/go_router_generator.dart +++ b/packages/go_router_builder/lib/src/go_router_generator.dart @@ -16,6 +16,8 @@ const String _routeDataUrl = 'package:go_router/src/route_data.dart'; const Map _annotations = { 'TypedGoRoute': 'GoRouteData', 'TypedShellRoute': 'ShellRouteData', + 'TypedStatefulShellBranch': 'StatefulShellBranchData', + 'TypedStatefulShellRoute': 'StatefulShellRouteData', }; /// A [Generator] for classes annotated with a typed go route annotation. diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index ef3b82edfb61..5925c11541fb 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -38,14 +38,72 @@ class InfoIterable extends IterableBase { class ShellRouteConfig extends RouteBaseConfig { ShellRouteConfig._({ required this.navigatorKey, + required this.parentNavigatorKey, required super.routeDataClass, required super.parent, - required super.parentNavigatorKey, }) : super._(); /// The command for calling the navigator key getter from the ShellRouteData. final String? navigatorKey; + /// The parent navigator key. + final String? parentNavigatorKey; + + @override + Iterable classDeclarations() { + if (routeDataClass.unnamedConstructor == null) { + throw InvalidGenerationSourceError( + 'The ShellRouteData "$_className" class must have an unnamed constructor.', + element: routeDataClass, + ); + } + + final bool isConst = routeDataClass.unnamedConstructor!.isConst; + + return [ + ''' + extension $_extensionName on $_className { + static $_className _fromState(GoRouterState state) =>${isConst ? ' const' : ''} $_className(); + } + ''' + ]; + } + + @override + String get routeConstructorParameters => + '${navigatorKey == null ? '' : 'navigatorKey: $navigatorKey,'}' + '${parentNavigatorKey == null ? '' : 'parentNavigatorKey: $parentNavigatorKey,'}'; + + @override + String get factorConstructorParameters => + 'factory: $_extensionName._fromState,'; + + @override + String get routeDataClassName => 'ShellRouteData'; + + @override + String get dataConvertionFunctionName => r'$route'; +} + +/// The configuration to generate class declarations for a StatefulShellRouteData. +class StatefulShellRouteConfig extends RouteBaseConfig { + StatefulShellRouteConfig._({ + required this.parentNavigatorKey, + required super.routeDataClass, + required super.parent, + required this.navigatorContainerBuilder, + required this.restorationScopeId, + }) : super._(); + + /// The parent navigator key. + final String? parentNavigatorKey; + + /// The navigator container builder. + final String? navigatorContainerBuilder; + + /// The restoration scope id. + final String? restorationScopeId; + @override Iterable classDeclarations() => [ ''' @@ -57,10 +115,51 @@ extension $_extensionName on $_className { @override String get routeConstructorParameters => - navigatorKey == null ? '' : 'navigatorKey: $navigatorKey,'; + '${parentNavigatorKey == null ? '' : 'parentNavigatorKey: $parentNavigatorKey,'}' + '${restorationScopeId == null ? '' : 'restorationScopeId: $restorationScopeId,'}' + '${navigatorContainerBuilder == null ? '' : 'navigatorContainerBuilder: $navigatorContainerBuilder,'}'; @override - String get routeDataClassName => 'ShellRouteData'; + String get factorConstructorParameters => + 'factory: $_extensionName._fromState,'; + + @override + String get routeDataClassName => 'StatefulShellRouteData'; + + @override + String get dataConvertionFunctionName => r'$route'; +} + +/// The configuration to generate class declarations for a StatefulShellBranchData. +class StatefulShellBranchConfig extends RouteBaseConfig { + StatefulShellBranchConfig._({ + required this.navigatorKey, + required super.routeDataClass, + required super.parent, + this.restorationScopeId, + }) : super._(); + + /// The command for calling the navigator key getter from the ShellRouteData. + final String? navigatorKey; + + /// The restoration scope id. + final String? restorationScopeId; + + @override + Iterable classDeclarations() => []; + + @override + String get factorConstructorParameters => ''; + @override + String get routeConstructorParameters => + '${navigatorKey == null ? '' : 'navigatorKey: $navigatorKey,'}' + '${restorationScopeId == null ? '' : 'restorationScopeId: $restorationScopeId,'}'; + + @override + String get routeDataClassName => 'StatefulShellBranchData'; + + @override + String get dataConvertionFunctionName => r'$branch'; } /// The configuration to generate class declarations for a GoRouteData. @@ -68,9 +167,9 @@ class GoRouteConfig extends RouteBaseConfig { GoRouteConfig._({ required this.path, required this.name, + required this.parentNavigatorKey, required super.routeDataClass, required super.parent, - required super.parentNavigatorKey, }) : super._(); /// The path of the GoRoute to be created by this configuration. @@ -79,6 +178,9 @@ class GoRouteConfig extends RouteBaseConfig { /// The name of the GoRoute to be created by this configuration. final String? name; + /// The parent navigator key. + final String? parentNavigatorKey; + late final Set _pathParams = pathParametersFromPattern(_rawJoinedPath); @@ -284,14 +386,22 @@ extension $_extensionName on $_className { return enumParamTypes.map(_enumMapConst); } + @override + String get factorConstructorParameters => + 'factory: $_extensionName._fromState,'; + @override String get routeConstructorParameters => ''' path: ${escapeDartString(path)}, ${name != null ? 'name: ${escapeDartString(name!)},' : ''} + ${parentNavigatorKey == null ? '' : 'parentNavigatorKey: $parentNavigatorKey,'} '''; @override String get routeDataClassName => 'GoRouteData'; + + @override + String get dataConvertionFunctionName => r'$route'; } /// Represents a `TypedGoRoute` annotation to the builder. @@ -299,7 +409,6 @@ abstract class RouteBaseConfig { RouteBaseConfig._({ required this.routeDataClass, required this.parent, - required this.parentNavigatorKey, }); /// Creates a new [RouteBaseConfig] represented the annotation data in [reader]. @@ -331,7 +440,7 @@ abstract class RouteBaseConfig { // TODO(stuartmorgan): Remove this ignore once 'analyze' can be set to // 5.2+ (when Flutter 3.4+ is on stable). // ignore: deprecated_member_use - final bool isShellRoute = type.element.name == 'TypedShellRoute'; + final String typeName = type.element.name; final DartType typeParamType = type.typeArguments.single; if (typeParamType is! InterfaceType) { throw InvalidGenerationSourceError( @@ -348,43 +457,81 @@ abstract class RouteBaseConfig { final InterfaceElement classElement = typeParamType.element; final RouteBaseConfig value; - if (isShellRoute) { - value = ShellRouteConfig._( - routeDataClass: classElement, - parent: parent, - navigatorKey: _generateNavigatorKeyGetterCode( - classElement, - keyName: r'$navigatorKey', - ), - parentNavigatorKey: _generateNavigatorKeyGetterCode( - classElement, - keyName: r'$parentNavigatorKey', - ), - ); - } else { - final ConstantReader pathValue = reader.read('path'); - if (pathValue.isNull) { - throw InvalidGenerationSourceError( - 'Missing `path` value on annotation.', - element: element, + switch (typeName) { + case 'TypedShellRoute': + value = ShellRouteConfig._( + routeDataClass: classElement, + parent: parent, + navigatorKey: _generateParameterGetterCode( + classElement, + parameterName: r'$navigatorKey', + ), + parentNavigatorKey: _generateParameterGetterCode( + classElement, + parameterName: r'$parentNavigatorKey', + ), ); - } - - final ConstantReader nameValue = reader.read('name'); - value = GoRouteConfig._( - path: pathValue.stringValue, - name: nameValue.isNull ? null : nameValue.stringValue, - routeDataClass: classElement, - parent: parent, - parentNavigatorKey: _generateNavigatorKeyGetterCode( - classElement, - keyName: r'$parentNavigatorKey', - ), - ); + break; + case 'TypedStatefulShellRoute': + value = StatefulShellRouteConfig._( + routeDataClass: classElement, + parent: parent, + parentNavigatorKey: _generateParameterGetterCode( + classElement, + parameterName: r'$parentNavigatorKey', + ), + restorationScopeId: _generateParameterGetterCode( + classElement, + parameterName: r'$restorationScopeId', + ), + navigatorContainerBuilder: _generateParameterGetterCode( + classElement, + parameterName: r'$navigatorContainerBuilder', + ), + ); + break; + case 'TypedStatefulShellBranch': + value = StatefulShellBranchConfig._( + routeDataClass: classElement, + parent: parent, + navigatorKey: _generateParameterGetterCode( + classElement, + parameterName: r'$navigatorKey', + ), + restorationScopeId: _generateParameterGetterCode( + classElement, + parameterName: r'$restorationScopeId', + ), + ); + break; + case 'TypedGoRoute': + final ConstantReader pathValue = reader.read('path'); + if (pathValue.isNull) { + throw InvalidGenerationSourceError( + 'Missing `path` value on annotation.', + element: element, + ); + } + final ConstantReader nameValue = reader.read('name'); + value = GoRouteConfig._( + path: pathValue.stringValue, + name: nameValue.isNull ? null : nameValue.stringValue, + routeDataClass: classElement, + parent: parent, + parentNavigatorKey: _generateParameterGetterCode( + classElement, + parameterName: r'$parentNavigatorKey', + ), + ); + break; + default: + throw UnsupportedError('Unrecognized type $typeName'); } - value._children.addAll(reader.read('routes').listValue.map( - (DartObject e) => RouteBaseConfig._fromAnnotation( + value._children.addAll(reader + .read(_generateChildrenGetterName(typeName)) + .listValue + .map((DartObject e) => RouteBaseConfig._fromAnnotation( ConstantReader(e), element, value))); return value; @@ -398,40 +545,55 @@ abstract class RouteBaseConfig { /// The parent of this route config. final RouteBaseConfig? parent; - /// The parent navigator key string that is used for initialize the - /// `RouteBase` class this config generates. - final String? parentNavigatorKey; + static String _generateChildrenGetterName(String name) { + return (name == 'TypedStatefulShellRoute' || + name == 'StatefulShellRouteData') + ? 'branches' + : 'routes'; + } - static String? _generateNavigatorKeyGetterCode( - InterfaceElement classElement, { - required String keyName, - }) { + static String? _generateParameterGetterCode(InterfaceElement classElement, + {required String parameterName}) { final String? fieldDisplayName = classElement.fields .where((FieldElement element) { - final DartType type = element.type; - if (!element.isStatic || - element.name != keyName || - type is! ParameterizedType) { - return false; - } - final List typeArguments = type.typeArguments; - if (typeArguments.length != 1) { + if (!element.isStatic || element.name != parameterName) { return false; } - final DartType typeArgument = typeArguments.single; - if (typeArgument.getDisplayString(withNullability: false) == - 'NavigatorState') { - return true; + if (parameterName.toLowerCase().contains('navigatorkey')) { + final DartType type = element.type; + if (type is! ParameterizedType) { + return false; + } + final List typeArguments = type.typeArguments; + if (typeArguments.length != 1) { + return false; + } + final DartType typeArgument = typeArguments.single; + if (typeArgument.getDisplayString(withNullability: false) != + 'NavigatorState') { + return false; + } } - return false; + return true; }) .map((FieldElement e) => e.displayName) .firstOrNull; - if (fieldDisplayName == null) { - return null; + if (fieldDisplayName != null) { + return '${classElement.name}.$fieldDisplayName'; } - return '${classElement.name}.$fieldDisplayName'; + + final String? methodDisplayName = classElement.methods + .where((MethodElement element) { + return element.isStatic && element.name == parameterName; + }) + .map((MethodElement e) => e.displayName) + .firstOrNull; + + if (methodDisplayName != null) { + return '${classElement.name}.$methodDisplayName'; + } + return null; } /// Generates all of the members that correspond to `this`. @@ -485,16 +647,13 @@ RouteBase get $_routeGetterName => ${_invokesRouteConstructor()}; final String routesBit = _children.isEmpty ? '' : ''' -routes: [${_children.map((RouteBaseConfig e) => '${e._invokesRouteConstructor()},').join()}], +${_generateChildrenGetterName(routeDataClassName)}: [${_children.map((RouteBaseConfig e) => '${e._invokesRouteConstructor()},').join()}], '''; - final String parentNavigatorKeyParameter = parentNavigatorKey == null - ? '' - : 'parentNavigatorKey: $parentNavigatorKey,'; + return ''' -$routeDataClassName.\$route( +$routeDataClassName.$dataConvertionFunctionName( $routeConstructorParameters - factory: $_extensionName._fromState, - $parentNavigatorKeyParameter + $factorConstructorParameters $routesBit ) '''; @@ -507,6 +666,14 @@ $routeDataClassName.\$route( @protected String get routeDataClassName; + /// The function name of `RouteData` to get Routes or branches. + @protected + String get dataConvertionFunctionName; + + /// Additional factory constructor. + @protected + String get factorConstructorParameters; + /// Additional constructor parameter for invoking route constructor. @protected String get routeConstructorParameters; diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 1bd454a71be6..c3beffd473c6 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -2,7 +2,7 @@ name: go_router_builder description: >- A builder that supports generated strongly-typed route helpers for package:go_router -version: 2.2.4 +version: 2.3.0 repository: https://github.com/flutter/packages/tree/main/packages/go_router_builder issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router_builder%22 diff --git a/packages/go_router_builder/test_inputs/shell_route_data.dart b/packages/go_router_builder/test_inputs/shell_route_data.dart new file mode 100644 index 000000000000..43f2b28498bd --- /dev/null +++ b/packages/go_router_builder/test_inputs/shell_route_data.dart @@ -0,0 +1,17 @@ +// Copyright 2013 The Flutter Authors. 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:go_router/go_router.dart'; + +@TypedShellRoute( + routes: >[], +) +class ShellRouteNoConstConstructor extends ShellRouteData {} + +@TypedShellRoute( + routes: >[], +) +class ShellRouteWithConstConstructor extends ShellRouteData { + const ShellRouteWithConstConstructor(); +} diff --git a/packages/go_router_builder/test_inputs/shell_route_data.dart.expect b/packages/go_router_builder/test_inputs/shell_route_data.dart.expect new file mode 100644 index 000000000000..b99dd5176beb --- /dev/null +++ b/packages/go_router_builder/test_inputs/shell_route_data.dart.expect @@ -0,0 +1,19 @@ +RouteBase get $shellRouteNoConstConstructor => ShellRouteData.$route( + factory: $ShellRouteNoConstConstructorExtension._fromState, + ); + +extension $ShellRouteNoConstConstructorExtension + on ShellRouteNoConstConstructor { + static ShellRouteNoConstConstructor _fromState(GoRouterState state) => + ShellRouteNoConstConstructor(); +} + +RouteBase get $shellRouteWithConstConstructor => ShellRouteData.$route( + factory: $ShellRouteWithConstConstructorExtension._fromState, + ); + +extension $ShellRouteWithConstConstructorExtension + on ShellRouteWithConstConstructor { + static ShellRouteWithConstConstructor _fromState(GoRouterState state) => + const ShellRouteWithConstConstructor(); +} diff --git a/packages/go_router_builder/test_inputs/shell_route_data_without_unnamed_constructor.dart b/packages/go_router_builder/test_inputs/shell_route_data_without_unnamed_constructor.dart new file mode 100644 index 000000000000..24e97bfd9c22 --- /dev/null +++ b/packages/go_router_builder/test_inputs/shell_route_data_without_unnamed_constructor.dart @@ -0,0 +1,12 @@ +// Copyright 2013 The Flutter Authors. 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:go_router/go_router.dart'; + +@TypedShellRoute( + routes: >[], +) +class ShellRouteWithoutUnnamedConstructor extends ShellRouteData { + const ShellRouteWithoutUnnamedConstructor.namedConstructor(); +} diff --git a/packages/go_router_builder/test_inputs/shell_route_data_without_unnamed_constructor.dart.expect b/packages/go_router_builder/test_inputs/shell_route_data_without_unnamed_constructor.dart.expect new file mode 100644 index 000000000000..c3d6e57e861a --- /dev/null +++ b/packages/go_router_builder/test_inputs/shell_route_data_without_unnamed_constructor.dart.expect @@ -0,0 +1 @@ +The ShellRouteData "ShellRouteWithoutUnnamedConstructor" class must have an unnamed constructor. diff --git a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart index 7b056b0d3779..98ea6d932b25 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart @@ -58,17 +58,11 @@ void runTests() { } else { expect( coordinate.x, - ((rect.center.dx - rect.topLeft.dx) * - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatio) + ((rect.center.dx - rect.topLeft.dx) * tester.view.devicePixelRatio) .round()); expect( coordinate.y, - ((rect.center.dy - rect.topLeft.dy) * - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatio) + ((rect.center.dy - rect.topLeft.dy) * tester.view.devicePixelRatio) .round()); } await tester.binding.setSurfaceSize(null); diff --git a/packages/google_maps_flutter/google_maps_flutter_android/example/integration_test/google_maps_tests.dart b/packages/google_maps_flutter/google_maps_flutter_android/example/integration_test/google_maps_tests.dart index 345038f6ad9a..a0a9d3049c7d 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/example/integration_test/google_maps_tests.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/example/integration_test/google_maps_tests.dart @@ -470,17 +470,11 @@ void googleMapsTests() { final Rect rect = tester.getRect(find.byKey(key)); expect( coordinate.x, - ((rect.center.dx - rect.topLeft.dx) * - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatio) + ((rect.center.dx - rect.topLeft.dx) * tester.view.devicePixelRatio) .round()); expect( coordinate.y, - ((rect.center.dy - rect.topLeft.dy) * - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.devicePixelRatio) + ((rect.center.dy - rect.topLeft.dy) * tester.view.devicePixelRatio) .round()); await tester.binding.setSurfaceSize(null); }); @@ -958,7 +952,9 @@ void googleMapsTests() { await controller.hideMarkerInfoWindow(marker.markerId); iwVisibleStatus = await controller.isMarkerInfoWindowShown(marker.markerId); expect(iwVisibleStatus, false); - }); + }, + // TODO(camsim99): Fix https://github.com/flutter/flutter/issues/131783. + skip: true); testWidgets('fromAssetImage', (WidgetTester tester) async { const double pixelRatio = 2; diff --git a/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md index 0427818ca507..6a9b6ad8d5b4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.3 + +* Initial support for custom overlays. [#98596](https://github.com/flutter/flutter/issues/98596). + ## 0.5.2 * Adds options for gesture handling and tilt controls. diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart index 00a448a979b8..fda38f29b52b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart @@ -14,14 +14,14 @@ import 'package:integration_test/integration_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'google_maps_controller_test.mocks.dart'; - -@GenerateMocks([], customMocks: >[ - MockSpec(onMissingStub: OnMissingStub.returnDefault), - MockSpec(onMissingStub: OnMissingStub.returnDefault), - MockSpec(onMissingStub: OnMissingStub.returnDefault), - MockSpec(onMissingStub: OnMissingStub.returnDefault), +@GenerateNiceMocks(>[ + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), ]) +import 'google_maps_controller_test.mocks.dart'; /// Test Google Map Controller void main() { @@ -194,6 +194,15 @@ void main() { }, throwsAssertionError); }); + testWidgets('cannot updateTileOverlays after dispose', + (WidgetTester tester) async { + controller.dispose(); + + expect(() { + controller.updateTileOverlays(const {}); + }, throwsAssertionError); + }); + testWidgets('isInfoWindowShown defaults to false', (WidgetTester tester) async { controller.dispose(); @@ -208,6 +217,7 @@ void main() { late MockMarkersController markers; late MockPolygonsController polygons; late MockPolylinesController polylines; + late MockTileOverlaysController tileOverlays; late gmaps.GMap map; setUp(() { @@ -215,20 +225,20 @@ void main() { markers = MockMarkersController(); polygons = MockPolygonsController(); polylines = MockPolylinesController(); + tileOverlays = MockTileOverlaysController(); map = gmaps.GMap(html.DivElement()); }); testWidgets('listens to map events', (WidgetTester tester) async { - controller = createController(); - controller.debugSetOverrides( - createMap: (_, __) => map, - circles: circles, - markers: markers, - polygons: polygons, - polylines: polylines, - ); - - controller.init(); + controller = createController() + ..debugSetOverrides( + createMap: (_, __) => map, + circles: circles, + markers: markers, + polygons: polygons, + polylines: polylines, + ) + ..init(); // Trigger events on the map, and verify they've been broadcast to the stream final Stream> capturedEvents = stream.stream.take(5); @@ -258,26 +268,26 @@ void main() { testWidgets("binds geometry controllers to map's", (WidgetTester tester) async { - controller = createController(); - controller.debugSetOverrides( - createMap: (_, __) => map, - circles: circles, - markers: markers, - polygons: polygons, - polylines: polylines, - ); - - controller.init(); + controller = createController() + ..debugSetOverrides( + createMap: (_, __) => map, + circles: circles, + markers: markers, + polygons: polygons, + polylines: polylines, + tileOverlays: tileOverlays, + ) + ..init(); verify(circles.bindToMap(mapId, map)); verify(markers.bindToMap(mapId, map)); verify(polygons.bindToMap(mapId, map)); verify(polylines.bindToMap(mapId, map)); + verify(tileOverlays.bindToMap(mapId, map)); }); testWidgets('renders initial geometry', (WidgetTester tester) async { - controller = createController( - mapObjects: MapObjects(circles: { + final MapObjects mapObjects = MapObjects(circles: { const Circle( circleId: CircleId('circle-1'), zIndex: 1234, @@ -320,57 +330,25 @@ void main() { LatLng(43.354469, -5.851318), LatLng(43.354762, -5.850824), ]) - })); - - controller.debugSetOverrides( - circles: circles, - markers: markers, - polygons: polygons, - polylines: polylines, - ); - - controller.init(); - - final Set capturedCircles = - verify(circles.addCircles(captureAny)).captured[0] as Set; - final Set capturedMarkers = - verify(markers.addMarkers(captureAny)).captured[0] as Set; - final Set capturedPolygons = - verify(polygons.addPolygons(captureAny)).captured[0] - as Set; - final Set capturedPolylines = - verify(polylines.addPolylines(captureAny)).captured[0] - as Set; - - expect(capturedCircles.first.circleId.value, 'circle-1'); - expect(capturedCircles.first.zIndex, 1234); - expect(capturedMarkers.first.markerId.value, 'marker-1'); - expect(capturedMarkers.first.infoWindow.snippet, 'snippet for test'); - expect(capturedMarkers.first.infoWindow.title, 'title for test'); - expect(capturedPolygons.first.polygonId.value, 'polygon-1'); - expect(capturedPolygons.elementAt(1).polygonId.value, - 'polygon-2-with-holes'); - expect(capturedPolygons.elementAt(1).holes, isNot(null)); - expect(capturedPolylines.first.polylineId.value, 'polyline-1'); - }); - - testWidgets('empty infoWindow does not create InfoWindow instance.', - (WidgetTester tester) async { - controller = createController( - mapObjects: MapObjects(markers: { - const Marker(markerId: MarkerId('marker-1')), - })); - - controller.debugSetOverrides( - markers: markers, - ); - - controller.init(); - - final Set capturedMarkers = - verify(markers.addMarkers(captureAny)).captured[0] as Set; + }, tileOverlays: { + const TileOverlay(tileOverlayId: TileOverlayId('overlay-1')) + }); - expect(capturedMarkers.first.infoWindow, InfoWindow.noText); + controller = createController(mapObjects: mapObjects) + ..debugSetOverrides( + circles: circles, + markers: markers, + polygons: polygons, + polylines: polylines, + tileOverlays: tileOverlays, + ) + ..init(); + + verify(circles.addCircles(mapObjects.circles)); + verify(markers.addMarkers(mapObjects.markers)); + verify(polygons.addPolygons(mapObjects.polygons)); + verify(polylines.addPolylines(mapObjects.polylines)); + verify(tileOverlays.addTileOverlays(mapObjects.tileOverlays)); }); group('Initialization options', () { @@ -449,15 +427,12 @@ void main() { target: LatLng(43.308, -5.6910), zoom: 12, ), - ); - - controller.debugSetOverrides( - createMap: (_, gmaps.MapOptions options) { - capturedOptions = options; - return map; - }); - - controller.init(); + ) + ..debugSetOverrides(createMap: (_, gmaps.MapOptions options) { + capturedOptions = options; + return map; + }) + ..init(); expect(capturedOptions, isNotNull); expect(capturedOptions!.zoom, 12); @@ -467,8 +442,7 @@ void main() { group('Traffic Layer', () { testWidgets('by default is disabled', (WidgetTester tester) async { - controller = createController(); - controller.init(); + controller = createController()..init(); expect(controller.trafficLayer, isNull); }); @@ -477,9 +451,9 @@ void main() { controller = createController( mapConfiguration: const MapConfiguration( trafficEnabled: true, - )); - controller.debugSetOverrides(createMap: (_, __) => map); - controller.init(); + )) + ..debugSetOverrides(createMap: (_, __) => map) + ..init(); expect(controller.trafficLayer, isNotNull); }); }); @@ -496,9 +470,9 @@ void main() { ..zoom = 10 ..center = gmaps.LatLng(0, 0), ); - controller = createController(); - controller.debugSetOverrides(createMap: (_, __) => map); - controller.init(); + controller = createController() + ..debugSetOverrides(createMap: (_, __) => map) + ..init(); }); group('updateRawOptions', () { @@ -556,13 +530,9 @@ void main() { // These are the methods that get forwarded to other controllers, so we just verify calls. group('Pass-through methods', () { - setUp(() { - controller = createController(); - }); - testWidgets('updateCircles', (WidgetTester tester) async { final MockCirclesController mock = MockCirclesController(); - controller.debugSetOverrides(circles: mock); + controller = createController()..debugSetOverrides(circles: mock); final Set previous = { const Circle(circleId: CircleId('to-be-updated')), @@ -589,7 +559,7 @@ void main() { testWidgets('updateMarkers', (WidgetTester tester) async { final MockMarkersController mock = MockMarkersController(); - controller.debugSetOverrides(markers: mock); + controller = createController()..debugSetOverrides(markers: mock); final Set previous = { const Marker(markerId: MarkerId('to-be-updated')), @@ -616,7 +586,7 @@ void main() { testWidgets('updatePolygons', (WidgetTester tester) async { final MockPolygonsController mock = MockPolygonsController(); - controller.debugSetOverrides(polygons: mock); + controller = createController()..debugSetOverrides(polygons: mock); final Set previous = { const Polygon(polygonId: PolygonId('to-be-updated')), @@ -643,7 +613,7 @@ void main() { testWidgets('updatePolylines', (WidgetTester tester) async { final MockPolylinesController mock = MockPolylinesController(); - controller.debugSetOverrides(polylines: mock); + controller = createController()..debugSetOverrides(polylines: mock); final Set previous = { const Polyline(polylineId: PolylineId('to-be-updated')), @@ -674,11 +644,38 @@ void main() { })); }); + testWidgets('updateTileOverlays', (WidgetTester tester) async { + final MockTileOverlaysController mock = MockTileOverlaysController(); + controller = createController( + mapObjects: MapObjects(tileOverlays: { + const TileOverlay(tileOverlayId: TileOverlayId('to-be-updated')), + const TileOverlay(tileOverlayId: TileOverlayId('to-be-removed')), + })) + ..debugSetOverrides(tileOverlays: mock); + + controller.updateTileOverlays({ + const TileOverlay( + tileOverlayId: TileOverlayId('to-be-updated'), visible: false), + const TileOverlay(tileOverlayId: TileOverlayId('to-be-added')), + }); + + verify(mock.removeTileOverlays({ + const TileOverlayId('to-be-removed'), + })); + verify(mock.addTileOverlays({ + const TileOverlay(tileOverlayId: TileOverlayId('to-be-added')), + })); + verify(mock.changeTileOverlays({ + const TileOverlay( + tileOverlayId: TileOverlayId('to-be-updated'), visible: false), + })); + }); + testWidgets('infoWindow visibility', (WidgetTester tester) async { final MockMarkersController mock = MockMarkersController(); const MarkerId markerId = MarkerId('marker-with-infowindow'); when(mock.isInfoWindowShown(markerId)).thenReturn(true); - controller.debugSetOverrides(markers: mock); + controller = createController()..debugSetOverrides(markers: mock); controller.showInfoWindow(markerId); diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart index 4bc5f365d2d0..f73b3d734afa 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart @@ -403,3 +403,65 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); } + +/// A class which mocks [TileOverlaysController]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTileOverlaysController extends _i1.Mock + implements _i3.TileOverlaysController { + @override + _i2.GMap get googleMap => (super.noSuchMethod( + Invocation.getter(#googleMap), + returnValue: _FakeGMap_0( + this, + Invocation.getter(#googleMap), + ), + returnValueForMissingStub: _FakeGMap_0( + this, + Invocation.getter(#googleMap), + ), + ) as _i2.GMap); + @override + set googleMap(_i2.GMap? _googleMap) => super.noSuchMethod( + Invocation.setter( + #googleMap, + _googleMap, + ), + returnValueForMissingStub: null, + ); + @override + void addTileOverlays(Set<_i4.TileOverlay>? tileOverlays) => + super.noSuchMethod( + Invocation.method( + #addTileOverlays, + [tileOverlays], + ), + returnValueForMissingStub: null, + ); + @override + void changeTileOverlays(Set<_i4.TileOverlay>? tileOverlays) => + super.noSuchMethod( + Invocation.method( + #changeTileOverlays, + [tileOverlays], + ), + returnValueForMissingStub: null, + ); + @override + void removeTileOverlays(Set<_i4.TileOverlayId>? tileOverlayIds) => + super.noSuchMethod( + Invocation.method( + #removeTileOverlays, + [tileOverlayIds], + ), + returnValueForMissingStub: null, + ); + @override + void clearTileCache(_i4.TileOverlayId? tileOverlayId) => super.noSuchMethod( + Invocation.method( + #clearTileCache, + [tileOverlayId], + ), + returnValueForMissingStub: null, + ); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.dart index c773596d9b30..36b4d11e07d0 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.dart @@ -14,12 +14,9 @@ import 'package:integration_test/integration_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +@GenerateNiceMocks(>[MockSpec()]) import 'google_maps_plugin_test.mocks.dart'; -@GenerateMocks([], customMocks: >[ - MockSpec(onMissingStub: OnMissingStub.returnDefault), -]) - /// Test GoogleMapsPlugin void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -208,28 +205,6 @@ void main() { }); }); - group('Noop methods:', () { - const int mapId = 0; - setUp(() { - plugin.debugSetMapById({mapId: controller}); - }); - // Options - testWidgets('updateTileOverlays', (WidgetTester tester) async { - final Future update = plugin.updateTileOverlays( - mapId: mapId, - newTileOverlays: {}, - ); - expect(update, completion(null)); - }); - testWidgets('updateTileOverlays', (WidgetTester tester) async { - final Future update = plugin.clearTileCache( - const TileOverlayId('any'), - mapId: mapId, - ); - expect(update, completion(null)); - }); - }); - // These methods only pass-through values from the plugin to the controller // so we verify them all together here... group('Pass-through methods:', () { @@ -287,6 +262,24 @@ void main() { verify(controller.updateCircles(expectedUpdates)); }); + // Tile Overlays + testWidgets('updateTileOverlays', (WidgetTester tester) async { + final Set expectedOverlays = { + const TileOverlay(tileOverlayId: TileOverlayId('overlay')) + }; + + await plugin.updateTileOverlays( + newTileOverlays: expectedOverlays, mapId: mapId); + + verify(controller.updateTileOverlays(expectedOverlays)); + }); + testWidgets('clearTileCache', (WidgetTester tester) async { + const TileOverlayId tileOverlayId = TileOverlayId('Dory'); + + await plugin.clearTileCache(tileOverlayId, mapId: mapId); + + verify(controller.clearTileCache(tileOverlayId)); + }); // Camera testWidgets('animateCamera', (WidgetTester tester) async { final CameraUpdate expectedUpdates = CameraUpdate.newLatLng( diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart index 36e6052a21cb..831bda161e84 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart @@ -126,6 +126,7 @@ class MockGoogleMapController extends _i1.Mock _i4.CirclesController? circles, _i4.PolygonsController? polygons, _i4.PolylinesController? polylines, + _i4.TileOverlaysController? tileOverlays, }) => super.noSuchMethod( Invocation.method( @@ -137,6 +138,7 @@ class MockGoogleMapController extends _i1.Mock #circles: circles, #polygons: polygons, #polylines: polylines, + #tileOverlays: tileOverlays, }, ), returnValueForMissingStub: null, @@ -286,6 +288,23 @@ class MockGoogleMapController extends _i1.Mock returnValueForMissingStub: null, ); @override + void updateTileOverlays(Set<_i2.TileOverlay>? newOverlays) => + super.noSuchMethod( + Invocation.method( + #updateTileOverlays, + [newOverlays], + ), + returnValueForMissingStub: null, + ); + @override + void clearTileCache(_i2.TileOverlayId? id) => super.noSuchMethod( + Invocation.method( + #clearTileCache, + [id], + ), + returnValueForMissingStub: null, + ); + @override void showInfoWindow(_i2.MarkerId? markerId) => super.noSuchMethod( Invocation.method( #showInfoWindow, diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlay_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlay_test.dart new file mode 100644 index 000000000000..29f902f7f1e0 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlay_test.dart @@ -0,0 +1,119 @@ +// Copyright 2013 The Flutter Authors. 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:convert'; +import 'dart:html' as html; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_maps/google_maps.dart' as gmaps; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:google_maps_flutter_web/google_maps_flutter_web.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'resources/tile16_base64.dart'; + +class NoTileProvider implements TileProvider { + const NoTileProvider(); + + @override + Future getTile(int x, int y, int? zoom) async => TileProvider.noTile; +} + +class TestTileProvider implements TileProvider { + const TestTileProvider(); + + @override + Future getTile(int x, int y, int? zoom) async => + Tile(16, 16, const Base64Decoder().convert(tile16Base64)); +} + +/// Test Overlays +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('TileOverlayController', () { + const TileOverlayId id = TileOverlayId(''); + + testWidgets('minimal initialization', (WidgetTester tester) async { + final TileOverlayController controller = TileOverlayController( + tileOverlay: const TileOverlay(tileOverlayId: id), + ); + + final gmaps.Size size = controller.gmMapType.tileSize!; + expect(size.width, TileOverlayController.logicalTileSize); + expect(size.height, TileOverlayController.logicalTileSize); + expect(controller.gmMapType.getTile!(gmaps.Point(0, 0), 0, html.document), + null); + }); + + testWidgets('produces image tiles', (WidgetTester tester) async { + final TileOverlayController controller = TileOverlayController( + tileOverlay: const TileOverlay( + tileOverlayId: id, + tileProvider: TestTileProvider(), + ), + ); + + final html.ImageElement img = + controller.gmMapType.getTile!(gmaps.Point(0, 0), 0, html.document)! + as html.ImageElement; + expect(img.naturalWidth, 0); + expect(img.naturalHeight, 0); + expect(img.hidden, true); + + // Wait until the image is fully loaded and decoded before re-reading its attributes. + await img.onLoad.first; + await img.decode(); + + expect(img.hidden, false); + expect(img.naturalWidth, 16); + expect(img.naturalHeight, 16); + }); + + testWidgets('update', (WidgetTester tester) async { + final TileOverlayController controller = TileOverlayController( + tileOverlay: const TileOverlay( + tileOverlayId: id, + tileProvider: NoTileProvider(), + ), + ); + { + final html.ImageElement img = + controller.gmMapType.getTile!(gmaps.Point(0, 0), 0, html.document)! + as html.ImageElement; + await null; // let `getTile` `then` complete + expect( + img.src, + isEmpty, + reason: 'The NoTileProvider never updates the img src', + ); + } + + controller.update(const TileOverlay( + tileOverlayId: id, + tileProvider: TestTileProvider(), + )); + { + final html.ImageElement img = + controller.gmMapType.getTile!(gmaps.Point(0, 0), 0, html.document)! + as html.ImageElement; + await img.onLoad.first; + expect( + img.src, + isNotEmpty, + reason: 'The img `src` should eventually become the Blob URL.', + ); + } + + controller.update(const TileOverlay(tileOverlayId: id)); + { + expect( + controller.gmMapType.getTile!(gmaps.Point(0, 0), 0, html.document), + null, + reason: 'Setting a null tileProvider should work.', + ); + } + }); + }); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlays_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlays_test.dart new file mode 100644 index 000000000000..8b6b34694f46 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlays_test.dart @@ -0,0 +1,172 @@ +// Copyright 2013 The Flutter Authors. 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:async'; +import 'dart:html' as html; + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_maps/google_maps.dart' as gmaps; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:google_maps_flutter_web/google_maps_flutter_web.dart' + hide GoogleMapController; +import 'package:integration_test/integration_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +@GenerateNiceMocks(>[MockSpec()]) +import 'overlays_test.mocks.dart'; + +MockTileProvider neverTileProvider() { + final MockTileProvider tileProvider = MockTileProvider(); + when(tileProvider.getTile(any, any, any)) + .thenAnswer((_) => Completer().future); + return tileProvider; +} + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('TileOverlaysController', () { + late TileOverlaysController controller; + late gmaps.GMap map; + late List tileProviders; + late List tileOverlays; + + /// Queries the current overlay map types for tiles at x = 0, y = 0, zoom = + /// 0. + void probeTiles() { + for (final gmaps.MapType? mapType in map.overlayMapTypes!.array!) { + mapType?.getTile!(gmaps.Point(0, 0), 0, html.document); + } + } + + setUp(() { + controller = TileOverlaysController(); + map = gmaps.GMap(html.DivElement()); + controller.googleMap = map; + + tileProviders = [ + for (int i = 0; i < 3; ++i) neverTileProvider() + ]; + + tileOverlays = [ + for (int i = 0; i < 3; ++i) + TileOverlay( + tileOverlayId: TileOverlayId('$i'), + tileProvider: tileProviders[i], + zIndex: i) + ]; + }); + + testWidgets('addTileOverlays', (WidgetTester tester) async { + controller.addTileOverlays({...tileOverlays}); + probeTiles(); + verifyInOrder([ + tileProviders[0].getTile(any, any, any), + tileProviders[1].getTile(any, any, any), + tileProviders[2].getTile(any, any, any), + ]); + verifyNoMoreInteractions(tileProviders[0]); + verifyNoMoreInteractions(tileProviders[1]); + verifyNoMoreInteractions(tileProviders[2]); + }); + + testWidgets('changeTileOverlays', (WidgetTester tester) async { + controller.addTileOverlays({...tileOverlays}); + + // Set overlay 0 visiblity to false; flip z ordering of 1 and 2, leaving 1 + // unchanged. + controller.changeTileOverlays({ + tileOverlays[0].copyWith(visibleParam: false), + tileOverlays[2].copyWith(zIndexParam: 0), + }); + + probeTiles(); + + verifyInOrder([ + tileProviders[2].getTile(any, any, any), + tileProviders[1].getTile(any, any, any), + ]); + verifyZeroInteractions(tileProviders[0]); + verifyNoMoreInteractions(tileProviders[1]); + verifyNoMoreInteractions(tileProviders[2]); + + // Re-enable overlay 0. + controller.changeTileOverlays( + {tileOverlays[0].copyWith(visibleParam: true)}); + + probeTiles(); + + verify(tileProviders[2].getTile(any, any, any)); + verifyInOrder([ + tileProviders[0].getTile(any, any, any), + tileProviders[1].getTile(any, any, any), + ]); + verifyNoMoreInteractions(tileProviders[0]); + verifyNoMoreInteractions(tileProviders[1]); + verifyNoMoreInteractions(tileProviders[2]); + }); + + testWidgets( + 'updating the z index of a hidden layer does not make it visible', + (WidgetTester tester) async { + controller.addTileOverlays({...tileOverlays}); + + controller.changeTileOverlays({ + tileOverlays[0].copyWith(zIndexParam: -1, visibleParam: false), + }); + + probeTiles(); + verifyZeroInteractions(tileProviders[0]); + }); + + testWidgets('removeTileOverlays', (WidgetTester tester) async { + controller.addTileOverlays({...tileOverlays}); + + controller.removeTileOverlays({ + tileOverlays[0].tileOverlayId, + tileOverlays[2].tileOverlayId, + }); + + probeTiles(); + + verify(tileProviders[1].getTile(any, any, any)); + verifyZeroInteractions(tileProviders[0]); + verifyZeroInteractions(tileProviders[2]); + }); + + testWidgets('clearTileCache', (WidgetTester tester) async { + final Completer controllerCompleter = + Completer(); + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: GoogleMap( + initialCameraPosition: const CameraPosition( + target: LatLng(43.3078, -5.6958), + zoom: 14, + ), + tileOverlays: {...tileOverlays.take(2)}, + onMapCreated: (GoogleMapController value) { + controllerCompleter.complete(value); + addTearDown(() => value.dispose()); + }, + )))); + + // This is needed to kick-off the rendering of the JS Map flutter widget + await tester.pump(); + final GoogleMapController controller = await controllerCompleter.future; + + await tester.pump(); + verify(tileProviders[0].getTile(any, any, any)); + verify(tileProviders[1].getTile(any, any, any)); + + await controller.clearTileCache(tileOverlays[0].tileOverlayId); + + await tester.pump(); + verify(tileProviders[0].getTile(any, any, any)); + verifyNoMoreInteractions(tileProviders[1]); + }); + }); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlays_test.mocks.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlays_test.mocks.dart new file mode 100644 index 000000000000..126f7c5dc77a --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/overlays_test.mocks.dart @@ -0,0 +1,77 @@ +// Mocks generated by Mockito 5.4.1 from annotations +// in google_maps_flutter_web_integration_tests/integration_test/overlays_test.dart. +// Do not manually edit this file. + +// @dart=2.19 + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:google_maps_flutter_platform_interface/src/types/types.dart' + as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeTile_0 extends _i1.SmartFake implements _i2.Tile { + _FakeTile_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [TileProvider]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTileProvider extends _i1.Mock implements _i2.TileProvider { + @override + _i3.Future<_i2.Tile> getTile( + int? x, + int? y, + int? zoom, + ) => + (super.noSuchMethod( + Invocation.method( + #getTile, + [ + x, + y, + zoom, + ], + ), + returnValue: _i3.Future<_i2.Tile>.value(_FakeTile_0( + this, + Invocation.method( + #getTile, + [ + x, + y, + zoom, + ], + ), + )), + returnValueForMissingStub: _i3.Future<_i2.Tile>.value(_FakeTile_0( + this, + Invocation.method( + #getTile, + [ + x, + y, + zoom, + ], + ), + )), + ) as _i3.Future<_i2.Tile>); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/resources/tile16_base64.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/resources/tile16_base64.dart new file mode 100644 index 000000000000..0728b17e48f6 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/resources/tile16_base64.dart @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// 16x16 transparent png. +const String tile16Base64 = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAA' + 'Cxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAATSURBVDhPYxgFo2AUjAIwYGAAAAQQAAGn' + 'RHxjAAAAAElFTkSuQmCC'; diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart index df0b8de4c4a1..65448abecd18 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart @@ -9,6 +9,7 @@ import 'dart:convert'; import 'dart:html'; import 'dart:js_util'; +import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -31,6 +32,8 @@ part 'src/google_maps_controller.dart'; part 'src/google_maps_flutter_web.dart'; part 'src/marker.dart'; part 'src/markers.dart'; +part 'src/overlay.dart'; +part 'src/overlays.dart'; part 'src/polygon.dart'; part 'src/polygons.dart'; part 'src/polyline.dart'; diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart index f49a6878df51..fbb194224053 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart @@ -25,11 +25,13 @@ class GoogleMapController { _polygons = mapObjects.polygons, _polylines = mapObjects.polylines, _circles = mapObjects.circles, + _tileOverlays = mapObjects.tileOverlays, _lastMapConfiguration = mapConfiguration { _circlesController = CirclesController(stream: _streamController); _polygonsController = PolygonsController(stream: _streamController); _polylinesController = PolylinesController(stream: _streamController); _markersController = MarkersController(stream: _streamController); + _tileOverlaysController = TileOverlaysController(); // Register the view factory that will hold the `_div` that holds the map in the DOM. // The `_div` needs to be created outside of the ViewFactory (and cached!) so we can @@ -53,6 +55,7 @@ class GoogleMapController { final Set _polygons; final Set _polylines; final Set _circles; + Set _tileOverlays; // The configuration passed by the user, before converting to gmaps. // Caching this allows us to re-create the map faithfully when needed. MapConfiguration _lastMapConfiguration = const MapConfiguration(); @@ -108,6 +111,7 @@ class GoogleMapController { PolygonsController? _polygonsController; PolylinesController? _polylinesController; MarkersController? _markersController; + TileOverlaysController? _tileOverlaysController; // Keeps track if _attachGeometryControllers has been called or not. bool _controllersBoundToMap = false; @@ -122,12 +126,14 @@ class GoogleMapController { CirclesController? circles, PolygonsController? polygons, PolylinesController? polylines, + TileOverlaysController? tileOverlays, }) { _overrideCreateMap = createMap; _markersController = markers ?? _markersController; _circlesController = circles ?? _circlesController; _polygonsController = polygons ?? _polygonsController; _polylinesController = polylines ?? _polylinesController; + _tileOverlaysController = tileOverlays ?? _tileOverlaysController; } DebugCreateMapFunction? _overrideCreateMap; @@ -182,13 +188,7 @@ class GoogleMapController { _attachGeometryControllers(map); // Now attach the geometry, traffic and any other layers... - _renderInitialGeometry( - markers: _markers, - circles: _circles, - polygons: _polygons, - polylines: _polylines, - ); - + _renderInitialGeometry(); _setTrafficLayer(map, _lastMapConfiguration.trafficEnabled ?? false); } @@ -241,22 +241,20 @@ class GoogleMapController { 'Cannot attach a map to a null PolylinesController instance.'); assert(_markersController != null, 'Cannot attach a map to a null MarkersController instance.'); + assert(_tileOverlaysController != null, + 'Cannot attach a map to a null TileOverlaysController instance.'); _circlesController!.bindToMap(_mapId, map); _polygonsController!.bindToMap(_mapId, map); _polylinesController!.bindToMap(_mapId, map); _markersController!.bindToMap(_mapId, map); + _tileOverlaysController!.bindToMap(_mapId, map); _controllersBoundToMap = true; } // Renders the initial sets of geometry. - void _renderInitialGeometry({ - Set markers = const {}, - Set circles = const {}, - Set polygons = const {}, - Set polylines = const {}, - }) { + void _renderInitialGeometry() { assert( _controllersBoundToMap, 'Geometry controllers must be bound to a map before any geometry can ' @@ -266,10 +264,11 @@ class GoogleMapController { // in the [_attachGeometryControllers] method, which ensures that all these // controllers below are *not* null. - _markersController!.addMarkers(markers); - _circlesController!.addCircles(circles); - _polygonsController!.addPolygons(polygons); - _polylinesController!.addPolylines(polylines); + _markersController!.addMarkers(_markers); + _circlesController!.addCircles(_circles); + _polygonsController!.addPolygons(_polygons); + _polylinesController!.addPolylines(_polylines); + _tileOverlaysController!.addTileOverlays(_tileOverlays); } // Merges new options coming from the plugin into _lastConfiguration. @@ -407,6 +406,25 @@ class GoogleMapController { _markersController?.removeMarkers(updates.markerIdsToRemove); } + /// Updates the set of [TileOverlay]s. + void updateTileOverlays(Set newOverlays) { + final MapsObjectUpdates updates = + MapsObjectUpdates.from(_tileOverlays, newOverlays, + objectName: 'tileOverlay'); + assert(_tileOverlaysController != null, + 'Cannot update tile overlays after dispose().'); + _tileOverlaysController?.addTileOverlays(updates.objectsToAdd); + _tileOverlaysController?.changeTileOverlays(updates.objectsToChange); + _tileOverlaysController + ?.removeTileOverlays(updates.objectIdsToRemove.cast()); + _tileOverlays = newOverlays; + } + + /// Clears the tile cache associated with the given [TileOverlayId]. + void clearTileCache(TileOverlayId id) { + _tileOverlaysController?.clearTileCache(id); + } + /// Shows the [InfoWindow] of the marker identified by its [MarkerId]. void showInfoWindow(MarkerId markerId) { assert(_markersController != null, @@ -439,6 +457,7 @@ class GoogleMapController { _polygonsController = null; _polylinesController = null; _markersController = null; + _tileOverlaysController = null; _streamController.close(); } } diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart index 049a6a25ded6..6b91e9481e34 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart @@ -95,7 +95,7 @@ class GoogleMapsPlugin extends GoogleMapsFlutterPlatform { required Set newTileOverlays, required int mapId, }) async { - return; // Noop for now! + _map(mapId).updateTileOverlays(newTileOverlays); } @override @@ -103,7 +103,7 @@ class GoogleMapsPlugin extends GoogleMapsFlutterPlatform { TileOverlayId tileOverlayId, { required int mapId, }) async { - return; // Noop for now! + _map(mapId).clearTileCache(tileOverlayId); } /// Applies the given `cameraUpdate` to the current viewport (with animation). diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/overlay.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/overlay.dart new file mode 100644 index 000000000000..86f5387910cd --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/overlay.dart @@ -0,0 +1,76 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of google_maps_flutter_web; + +/// This wraps a [TileOverlay] in a [gmaps.MapType]. +class TileOverlayController { + /// Creates a `TileOverlayController` that wraps a [TileOverlay] object and its corresponding [gmaps.MapType]. + TileOverlayController({ + required TileOverlay tileOverlay, + }) { + update(tileOverlay); + } + + /// The size in pixels of the (square) tiles passed to the Maps SDK. + /// + /// Even though the web supports any size, and rectangular tiles, for + /// for consistency with mobile, this is not configurable on the web. + /// (Both Android and iOS prefer square 256px tiles @ 1x DPI) + /// + /// For higher DPI screens, the Tile that is actually returned can be larger + /// than 256px square. + static const int logicalTileSize = 256; + + /// Updates the [gmaps.MapType] and cached properties with an updated + /// [TileOverlay]. + void update(TileOverlay tileOverlay) { + _tileOverlay = tileOverlay; + _gmMapType = gmaps.MapType() + ..tileSize = gmaps.Size(logicalTileSize, logicalTileSize) + ..getTile = _getTile; + } + + /// Renders a Tile for gmaps; delegating to the configured [TileProvider]. + HtmlElement? _getTile( + gmaps.Point? tileCoord, + num? zoom, + Document? ownerDocument, + ) { + if (_tileOverlay.tileProvider == null) { + return null; + } + + final ImageElement img = + ownerDocument!.createElement('img') as ImageElement; + img.width = img.height = logicalTileSize; + img.hidden = true; + img.setAttribute('decoding', 'async'); + + _tileOverlay.tileProvider! + .getTile(tileCoord!.x!.toInt(), tileCoord.y!.toInt(), zoom?.toInt()) + .then((Tile tile) { + if (tile.data == null) { + return; + } + // Using img lets us take advantage of native decoding. + final String src = Url.createObjectUrl(Blob([tile.data])); + img.src = src; + img.addEventListener('load', (_) { + img.hidden = false; + Url.revokeObjectUrl(src); + }); + }); + + return img; + } + + /// The [gmaps.MapType] produced by this controller. + gmaps.MapType get gmMapType => _gmMapType; + late gmaps.MapType _gmMapType; + + /// The [TileOverlay] providing data for this controller. + TileOverlay get tileOverlay => _tileOverlay; + late TileOverlay _tileOverlay; +} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/overlays.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/overlays.dart new file mode 100644 index 000000000000..aa6c19173aa4 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/overlays.dart @@ -0,0 +1,99 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of google_maps_flutter_web; + +/// This class manages all the [TileOverlayController]s associated to a [GoogleMapController]. +class TileOverlaysController extends GeometryController { + final Map _tileOverlays = + {}; + final List _visibleTileOverlays = + []; + + // Inserts `tileOverlayController` into the list of visible overlays, and the current [googleMap]. + // + // After insertion, the arrays stay sorted by ascending z-index. + void _insertZSorted(TileOverlayController tileOverlayController) { + final int index = _visibleTileOverlays.lowerBoundBy( + tileOverlayController, + (TileOverlayController c) => c.tileOverlay.zIndex); + + googleMap.overlayMapTypes!.insertAt(index, tileOverlayController.gmMapType); + _visibleTileOverlays.insert(index, tileOverlayController); + } + + // Removes `tileOverlayController` from the list of visible overlays. + void _remove(TileOverlayController tileOverlayController) { + final int index = _visibleTileOverlays.indexOf(tileOverlayController); + if (index < 0) { + return; + } + + googleMap.overlayMapTypes!.removeAt(index); + _visibleTileOverlays.removeAt(index); + } + + /// Adds new [TileOverlay]s to this controller. + /// + /// Wraps the [TileOverlay]s in corresponding [TileOverlayController]s. + void addTileOverlays(Set tileOverlaysToAdd) { + tileOverlaysToAdd.forEach(_addTileOverlay); + } + + void _addTileOverlay(TileOverlay tileOverlay) { + final TileOverlayController controller = TileOverlayController( + tileOverlay: tileOverlay, + ); + _tileOverlays[tileOverlay.tileOverlayId] = controller; + + if (tileOverlay.visible) { + _insertZSorted(controller); + } + } + + /// Updates [TileOverlay]s with new options. + void changeTileOverlays(Set tileOverlays) { + tileOverlays.forEach(_changeTileOverlay); + } + + void _changeTileOverlay(TileOverlay tileOverlay) { + final TileOverlayController controller = + _tileOverlays[tileOverlay.tileOverlayId]!; + + final bool wasVisible = controller.tileOverlay.visible; + final bool isVisible = tileOverlay.visible; + + controller.update(tileOverlay); + + if (wasVisible) { + _remove(controller); + } + if (isVisible) { + _insertZSorted(controller); + } + } + + /// Removes the tile overlays associated with the given [TileOverlayId]s. + void removeTileOverlays(Set tileOverlayIds) { + tileOverlayIds.forEach(_removeTileOverlay); + } + + void _removeTileOverlay(TileOverlayId tileOverlayId) { + final TileOverlayController? controller = + _tileOverlays.remove(tileOverlayId); + if (controller != null) { + _remove(controller); + } + } + + /// Invalidates the tile overlay associated with the given [TileOverlayId]. + void clearTileCache(TileOverlayId tileOverlayId) { + final TileOverlayController? controller = _tileOverlays[tileOverlayId]; + if (controller != null && controller.tileOverlay.visible) { + final int i = _visibleTileOverlays.indexOf(controller); + // This causes the map to reload the overlay. + googleMap.overlayMapTypes!.setAt(i, controller.gmMapType); + } + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml index f1eb09c6c57e..642c2e457419 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_web description: Web platform implementation of google_maps_flutter repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 0.5.2 +version: 0.5.3 environment: sdk: ">=2.18.0 <4.0.0" @@ -17,6 +17,7 @@ flutter: fileName: google_maps_flutter_web.dart dependencies: + collection: ^1.16.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/google_sign_in/google_sign_in/test/widgets_test.dart b/packages/google_sign_in/google_sign_in/test/widgets_test.dart index 5b4721114fcd..717edc3699ee 100644 --- a/packages/google_sign_in/google_sign_in/test/widgets_test.dart +++ b/packages/google_sign_in/google_sign_in/test/widgets_test.dart @@ -101,9 +101,8 @@ void main() { photoUrl: 'photoUrl', ); - // TODO(pdblasi-google): Update `window` usages to new API after 3.9.0 is in stable. https://github.com/flutter/flutter/issues/122912 - // ignore: deprecated_member_use - tester.binding.window.physicalSizeTestValue = const Size(100, 100); + tester.view.physicalSize = const Size(100, 100); + addTearDown(tester.view.reset); await HttpOverrides.runZoned( () async { diff --git a/packages/path_provider/path_provider_android/CHANGELOG.md b/packages/path_provider/path_provider_android/CHANGELOG.md index 816457564de8..f829dcc73b6f 100644 --- a/packages/path_provider/path_provider_android/CHANGELOG.md +++ b/packages/path_provider/path_provider_android/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 2.1.0 +* Adds getApplicationCachePath() for storing app-specific cache files. * Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. ## 2.0.27 diff --git a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java index 11cda6b42806..1bfa729157db 100644 --- a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java +++ b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/Messages.java @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v9.2.4), do not edit directly. +// Autogenerated from Pigeon (v9.2.5), do not edit directly. // See also: https://pub.dev/packages/pigeon package io.flutter.plugins.pathprovider; @@ -84,6 +84,9 @@ public interface PathProviderApi { @Nullable String getApplicationDocumentsPath(); + @Nullable + String getApplicationCachePath(); + @Nullable String getExternalStoragePath(); @@ -176,6 +179,31 @@ static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable PathProvid channel.setMessageHandler(null); } } + { + BinaryMessenger.TaskQueue taskQueue = binaryMessenger.makeBackgroundTaskQueue(); + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.PathProviderApi.getApplicationCachePath", + getCodec(), + taskQueue); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + String output = api.getApplicationCachePath(); + wrapped.add(0, output); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } { BinaryMessenger.TaskQueue taskQueue = binaryMessenger.makeBackgroundTaskQueue(); BasicMessageChannel channel = diff --git a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index 6e259cf5128f..4ce1ba06cfb5 100644 --- a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java @@ -66,6 +66,11 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { return getPathProviderApplicationDocumentsDirectory(); } + @Override + public @Nullable String getApplicationCachePath() { + return context.getCacheDir().getPath(); + } + @Override public @Nullable String getExternalStoragePath() { return getPathProviderStorageDirectory(); diff --git a/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart index ecd0b973343b..1403d932d292 100644 --- a/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart +++ b/packages/path_provider/path_provider_android/example/integration_test/path_provider_test.dart @@ -28,6 +28,12 @@ void main() { _verifySampleFile(result, 'applicationSupport'); }); + testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async { + final PathProviderPlatform provider = PathProviderPlatform.instance; + final String? result = await provider.getApplicationCachePath(); + _verifySampleFile(result, 'applicationCache'); + }); + testWidgets('getLibraryDirectory', (WidgetTester tester) async { final PathProviderPlatform provider = PathProviderPlatform.instance; expect(() => provider.getLibraryPath(), diff --git a/packages/path_provider/path_provider_android/example/lib/main.dart b/packages/path_provider/path_provider_android/example/lib/main.dart index d0bc13bc0643..79293e155c01 100644 --- a/packages/path_provider/path_provider_android/example/lib/main.dart +++ b/packages/path_provider/path_provider_android/example/lib/main.dart @@ -39,6 +39,7 @@ class _MyHomePageState extends State { Future? _tempDirectory; Future? _appSupportDirectory; Future? _appDocumentsDirectory; + Future? _appCacheDirectory; Future? _externalDocumentsDirectory; Future?>? _externalStorageDirectories; Future?>? _externalCacheDirectories; @@ -92,6 +93,12 @@ class _MyHomePageState extends State { }); } + void _requestAppCacheDirectory() { + setState(() { + _appCacheDirectory = provider.getApplicationCachePath(); + }); + } + void _requestExternalStorageDirectory() { setState(() { _externalDocumentsDirectory = provider.getExternalStoragePath(); @@ -147,6 +154,15 @@ class _MyHomePageState extends State { ), FutureBuilder( future: _appSupportDirectory, builder: _buildDirectory), + Padding( + padding: const EdgeInsets.all(16.0), + child: ElevatedButton( + onPressed: _requestAppCacheDirectory, + child: const Text('Get Application Cache Directory'), + ), + ), + FutureBuilder( + future: _appCacheDirectory, builder: _buildDirectory), Padding( padding: const EdgeInsets.all(16.0), child: ElevatedButton( diff --git a/packages/path_provider/path_provider_android/example/pubspec.yaml b/packages/path_provider/path_provider_android/example/pubspec.yaml index 852d1cd77128..df9d0e362689 100644 --- a/packages/path_provider/path_provider_android/example/pubspec.yaml +++ b/packages/path_provider/path_provider_android/example/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - path_provider_platform_interface: ^2.0.0 + path_provider_platform_interface: ^2.1.0 dev_dependencies: flutter_test: diff --git a/packages/path_provider/path_provider_android/lib/messages.g.dart b/packages/path_provider/path_provider_android/lib/messages.g.dart index ec5c1f9506fa..20d4368d5d44 100644 --- a/packages/path_provider/path_provider_android/lib/messages.g.dart +++ b/packages/path_provider/path_provider_android/lib/messages.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v9.2.4), do not edit directly. +// Autogenerated from Pigeon (v9.2.5), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -98,6 +98,27 @@ class PathProviderApi { } } + Future getApplicationCachePath() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PathProviderApi.getApplicationCachePath', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return (replyList[0] as String?); + } + } + Future getExternalStoragePath() async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.PathProviderApi.getExternalStoragePath', codec, diff --git a/packages/path_provider/path_provider_android/lib/path_provider_android.dart b/packages/path_provider/path_provider_android/lib/path_provider_android.dart index f5c74f540253..c65b0abc30b9 100644 --- a/packages/path_provider/path_provider_android/lib/path_provider_android.dart +++ b/packages/path_provider/path_provider_android/lib/path_provider_android.dart @@ -62,6 +62,11 @@ class PathProviderAndroid extends PathProviderPlatform { return _api.getApplicationDocumentsPath(); } + @override + Future getApplicationCachePath() { + return _api.getApplicationCachePath(); + } + @override Future getExternalStoragePath() { return _api.getExternalStoragePath(); diff --git a/packages/path_provider/path_provider_android/pigeons/messages.dart b/packages/path_provider/path_provider_android/pigeons/messages.dart index 96ad6343d3b0..6e4eb8f1956e 100644 --- a/packages/path_provider/path_provider_android/pigeons/messages.dart +++ b/packages/path_provider/path_provider_android/pigeons/messages.dart @@ -36,6 +36,8 @@ abstract class PathProviderApi { @TaskQueue(type: TaskQueueType.serialBackgroundThread) String? getApplicationDocumentsPath(); @TaskQueue(type: TaskQueueType.serialBackgroundThread) + String? getApplicationCachePath(); + @TaskQueue(type: TaskQueueType.serialBackgroundThread) String? getExternalStoragePath(); @TaskQueue(type: TaskQueueType.serialBackgroundThread) List getExternalCachePaths(); diff --git a/packages/path_provider/path_provider_android/pubspec.yaml b/packages/path_provider/path_provider_android/pubspec.yaml index ee8317394652..42c4ba1b1a1d 100644 --- a/packages/path_provider/path_provider_android/pubspec.yaml +++ b/packages/path_provider/path_provider_android/pubspec.yaml @@ -2,7 +2,7 @@ name: path_provider_android description: Android implementation of the path_provider plugin. repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 -version: 2.0.27 +version: 2.1.0 environment: sdk: ">=2.18.0 <4.0.0" @@ -20,7 +20,7 @@ flutter: dependencies: flutter: sdk: flutter - path_provider_platform_interface: ^2.0.1 + path_provider_platform_interface: ^2.1.0 dev_dependencies: flutter_test: diff --git a/packages/path_provider/path_provider_android/test/messages_test.g.dart b/packages/path_provider/path_provider_android/test/messages_test.g.dart index 515f6b549fe1..e18fc9699969 100644 --- a/packages/path_provider/path_provider_android/test/messages_test.g.dart +++ b/packages/path_provider/path_provider_android/test/messages_test.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v9.2.4), do not edit directly. +// Autogenerated from Pigeon (v9.2.5), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import // ignore_for_file: avoid_relative_lib_imports @@ -24,6 +24,8 @@ abstract class TestPathProviderApi { String? getApplicationDocumentsPath(); + String? getApplicationCachePath(); + String? getExternalStoragePath(); List getExternalCachePaths(); @@ -84,6 +86,23 @@ abstract class TestPathProviderApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PathProviderApi.getApplicationCachePath', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + // ignore message + final String? output = api.getApplicationCachePath(); + return [output]; + }); + } + } { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.PathProviderApi.getExternalStoragePath', codec, diff --git a/packages/path_provider/path_provider_android/test/path_provider_android_test.dart b/packages/path_provider/path_provider_android/test/path_provider_android_test.dart index e3011474a2a3..5f94da6c4f3c 100644 --- a/packages/path_provider/path_provider_android/test/path_provider_android_test.dart +++ b/packages/path_provider/path_provider_android/test/path_provider_android_test.dart @@ -12,6 +12,7 @@ const String kTemporaryPath = 'temporaryPath'; const String kApplicationSupportPath = 'applicationSupportPath'; const String kLibraryPath = 'libraryPath'; const String kApplicationDocumentsPath = 'applicationDocumentsPath'; +const String kApplicationCachePath = 'applicationCachePath'; const String kExternalCachePaths = 'externalCachePaths'; const String kExternalStoragePaths = 'externalStoragePaths'; const String kDownloadsPath = 'downloadsPath'; @@ -23,6 +24,9 @@ class _Api implements TestPathProviderApi { @override String? getApplicationSupportPath() => kApplicationSupportPath; + @override + String? getApplicationCachePath() => kApplicationCachePath; + @override List getExternalCachePaths() => [kExternalCachePaths]; @@ -58,6 +62,11 @@ void main() { expect(path, kApplicationSupportPath); }); + test('getApplicationCachePath', () async { + final String? path = await pathProvider.getApplicationCachePath(); + expect(path, kApplicationCachePath); + }); + test('getLibraryPath fails', () async { try { await pathProvider.getLibraryPath(); diff --git a/packages/path_provider/path_provider_foundation/CHANGELOG.md b/packages/path_provider/path_provider_foundation/CHANGELOG.md index 1bbba4de2215..0142c0408cbc 100644 --- a/packages/path_provider/path_provider_foundation/CHANGELOG.md +++ b/packages/path_provider/path_provider_foundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.0 + +* Adds getApplicationCachePath() for storing app-specific cache files. + ## 2.2.4 * Updates to the latest version of `pigeon`. diff --git a/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift b/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift index e2346b0f14b5..5530b8be026d 100644 --- a/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift +++ b/packages/path_provider/path_provider_foundation/darwin/Classes/PathProviderPlugin.swift @@ -25,12 +25,12 @@ public class PathProviderPlugin: NSObject, FlutterPlugin, PathProviderApi { func getDirectoryPath(type: DirectoryType) -> String? { var path = getDirectory(ofType: fileManagerDirectoryForType(type)) #if os(macOS) - // In a non-sandboxed app, this is a shared directory where applications are + // In a non-sandboxed app, these are shared directories where applications are // expected to use its bundle ID as a subdirectory. (For non-sandboxed apps, // adding the extra path is harmless). // This is not done for iOS, for compatibility with older versions of the // plugin. - if type == .applicationSupport { + if type == .applicationSupport || type == .applicationCache { if let basePath = path { let basePathURL = URL.init(fileURLWithPath: basePath) path = basePathURL.appendingPathComponent(Bundle.main.bundleIdentifier!).path @@ -49,6 +49,8 @@ public class PathProviderPlugin: NSObject, FlutterPlugin, PathProviderApi { /// Returns the FileManager constant corresponding to the given type. private func fileManagerDirectoryForType(_ type: DirectoryType) -> FileManager.SearchPathDirectory { switch type { + case .applicationCache: + return FileManager.SearchPathDirectory.cachesDirectory case .applicationDocuments: return FileManager.SearchPathDirectory.documentDirectory case .applicationSupport: diff --git a/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift b/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift index 402e14f2d32d..4af5ac366630 100644 --- a/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift +++ b/packages/path_provider/path_provider_foundation/darwin/Classes/messages.g.swift @@ -44,6 +44,7 @@ enum DirectoryType: Int { case downloads = 2 case library = 3 case temp = 4 + case applicationCache = 5 } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol PathProviderApi { diff --git a/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart index b67730a781fd..0d05745127aa 100644 --- a/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart +++ b/packages/path_provider/path_provider_foundation/example/integration_test/path_provider_test.dart @@ -29,6 +29,12 @@ void main() { _verifySampleFile(result, 'applicationSupport'); }); + testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async { + final PathProviderPlatform provider = PathProviderPlatform.instance; + final String? result = await provider.getApplicationCachePath(); + _verifySampleFile(result, 'applicationCache'); + }); + testWidgets('getLibraryDirectory', (WidgetTester tester) async { final PathProviderPlatform provider = PathProviderPlatform.instance; final String? result = await provider.getLibraryPath(); diff --git a/packages/path_provider/path_provider_foundation/example/lib/main.dart b/packages/path_provider/path_provider_foundation/example/lib/main.dart index 3e3a599f9198..c766ccf96e90 100644 --- a/packages/path_provider/path_provider_foundation/example/lib/main.dart +++ b/packages/path_provider/path_provider_foundation/example/lib/main.dart @@ -27,6 +27,7 @@ class _MyAppState extends State { String? _appSupportDirectory = 'Unknown'; String? _documentsDirectory = 'Unknown'; String? _containerDirectory = 'Unknown'; + String? _cacheDirectory = 'Unknown'; @override void initState() { @@ -42,6 +43,7 @@ class _MyAppState extends State { String? libraryDirectory; String? documentsDirectory; String? containerDirectory; + String? cacheDirectory; final PathProviderPlatform provider = PathProviderPlatform.instance; final PathProviderFoundation providerFoundation = PathProviderFoundation(); @@ -82,6 +84,12 @@ class _MyAppState extends State { 'Failed to get app group container directory: $exception'; } + try { + cacheDirectory = await provider.getApplicationCachePath(); + } catch (exception) { + cacheDirectory = 'Failed to get cache directory: $exception'; + } + setState(() { _tempDirectory = tempDirectory; _downloadsDirectory = downloadsDirectory; @@ -89,6 +97,7 @@ class _MyAppState extends State { _appSupportDirectory = appSupportDirectory; _documentsDirectory = documentsDirectory; _containerDirectory = containerDirectory; + _cacheDirectory = cacheDirectory; }); } @@ -108,6 +117,7 @@ class _MyAppState extends State { Text('Library Directory: $_libraryDirectory\n'), Text('Application Support Directory: $_appSupportDirectory\n'), Text('App Group Container Directory: $_containerDirectory\n'), + Text('Cache Directory: $_cacheDirectory\n'), ], ), ), diff --git a/packages/path_provider/path_provider_foundation/example/pubspec.yaml b/packages/path_provider/path_provider_foundation/example/pubspec.yaml index 65feace0df43..51bc61d822e1 100644 --- a/packages/path_provider/path_provider_foundation/example/pubspec.yaml +++ b/packages/path_provider/path_provider_foundation/example/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - path_provider_platform_interface: ^2.0.0 + path_provider_platform_interface: ^2.1.0 dev_dependencies: flutter_test: diff --git a/packages/path_provider/path_provider_foundation/lib/messages.g.dart b/packages/path_provider/path_provider_foundation/lib/messages.g.dart index 7893dbd25e6c..3fdbadd5ae25 100644 --- a/packages/path_provider/path_provider_foundation/lib/messages.g.dart +++ b/packages/path_provider/path_provider_foundation/lib/messages.g.dart @@ -17,6 +17,7 @@ enum DirectoryType { downloads, library, temp, + applicationCache, } class PathProviderApi { diff --git a/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart b/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart index 32bbf020ea9d..55e24c4f2592 100644 --- a/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart +++ b/packages/path_provider/path_provider_foundation/lib/path_provider_foundation.dart @@ -51,6 +51,18 @@ class PathProviderFoundation extends PathProviderPlatform { return _pathProvider.getDirectoryPath(DirectoryType.applicationDocuments); } + @override + Future getApplicationCachePath() async { + final String? path = + await _pathProvider.getDirectoryPath(DirectoryType.applicationCache); + if (path != null) { + // Ensure the directory exists before returning it, for consistency with + // other platforms. + await Directory(path).create(recursive: true); + } + return path; + } + @override Future getExternalStoragePath() async { throw UnsupportedError( diff --git a/packages/path_provider/path_provider_foundation/pigeons/messages.dart b/packages/path_provider/path_provider_foundation/pigeons/messages.dart index e3d9d0dc3b7d..ae4e7c144b35 100644 --- a/packages/path_provider/path_provider_foundation/pigeons/messages.dart +++ b/packages/path_provider/path_provider_foundation/pigeons/messages.dart @@ -16,6 +16,7 @@ enum DirectoryType { downloads, library, temp, + applicationCache, } @HostApi(dartHostTestHandler: 'TestPathProviderApi') diff --git a/packages/path_provider/path_provider_foundation/pubspec.yaml b/packages/path_provider/path_provider_foundation/pubspec.yaml index 936e182f263a..6117963b0162 100644 --- a/packages/path_provider/path_provider_foundation/pubspec.yaml +++ b/packages/path_provider/path_provider_foundation/pubspec.yaml @@ -2,7 +2,7 @@ name: path_provider_foundation description: iOS and macOS implementation of the path_provider plugin repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_foundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 -version: 2.2.4 +version: 2.3.0 environment: sdk: ">=2.18.0 <4.0.0" @@ -24,7 +24,7 @@ flutter: dependencies: flutter: sdk: flutter - path_provider_platform_interface: ^2.0.1 + path_provider_platform_interface: ^2.1.0 dev_dependencies: build_runner: ^2.3.2 diff --git a/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart b/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart index e8337a7e0948..e13e182a4132 100644 --- a/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart +++ b/packages/path_provider/path_provider_foundation/test/path_provider_foundation_test.dart @@ -98,6 +98,32 @@ void main() { expect(path, applicationDocumentsPath); }); + test('getApplicationCachePath', () async { + final PathProviderFoundation pathProvider = PathProviderFoundation(); + final String applicationCachePath = + p.join(testRoot.path, 'application', 'cache', 'path'); + when(mockApi.getDirectoryPath(DirectoryType.applicationCache)) + .thenReturn(applicationCachePath); + + final String? path = await pathProvider.getApplicationCachePath(); + + verify(mockApi.getDirectoryPath(DirectoryType.applicationCache)); + expect(path, applicationCachePath); + }); + + test('getApplicationCachePath creates the directory if necessary', + () async { + final PathProviderFoundation pathProvider = PathProviderFoundation(); + final String applicationCachePath = + p.join(testRoot.path, 'application', 'cache', 'path'); + when(mockApi.getDirectoryPath(DirectoryType.applicationCache)) + .thenReturn(applicationCachePath); + + final String? path = await pathProvider.getApplicationCachePath(); + + expect(Directory(path!).existsSync(), isTrue); + }); + test('getDownloadsPath', () async { final PathProviderFoundation pathProvider = PathProviderFoundation(); final String downloadsPath = p.join(testRoot.path, 'downloads', 'path'); diff --git a/packages/path_provider/path_provider_linux/CHANGELOG.md b/packages/path_provider/path_provider_linux/CHANGELOG.md index 7b4f83da3fd9..09a9d94a4558 100644 --- a/packages/path_provider/path_provider_linux/CHANGELOG.md +++ b/packages/path_provider/path_provider_linux/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.0 + +* Adds getApplicationCachePath() for storing app-specific cache files. + ## 2.1.11 * Removes obsolete null checks on non-nullable values. diff --git a/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart index 3bd644f69763..3353f5617ce8 100644 --- a/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart +++ b/packages/path_provider/path_provider_linux/example/integration_test/path_provider_test.dart @@ -36,6 +36,12 @@ void main() { final String? result = await provider.getApplicationSupportPath(); _verifySampleFile(result, 'applicationSupport'); }); + + testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async { + final PathProviderLinux provider = PathProviderLinux(); + final String? result = await provider.getApplicationCachePath(); + _verifySampleFile(result, 'applicationCache'); + }); } /// Verify a file called [name] in [directoryPath] by recreating it with test diff --git a/packages/path_provider/path_provider_linux/example/lib/main.dart b/packages/path_provider/path_provider_linux/example/lib/main.dart index 254360cae4ee..3cbb6915277f 100644 --- a/packages/path_provider/path_provider_linux/example/lib/main.dart +++ b/packages/path_provider/path_provider_linux/example/lib/main.dart @@ -23,6 +23,7 @@ class _MyAppState extends State { String? _tempDirectory = 'Unknown'; String? _downloadsDirectory = 'Unknown'; String? _appSupportDirectory = 'Unknown'; + String? _appCacheDirectory = 'Unknown'; String? _documentsDirectory = 'Unknown'; final PathProviderLinux _provider = PathProviderLinux(); @@ -37,6 +38,7 @@ class _MyAppState extends State { String? tempDirectory; String? downloadsDirectory; String? appSupportDirectory; + String? appCacheDirectory; String? documentsDirectory; // Platform messages may fail, so we use a try/catch PlatformException. try { @@ -61,6 +63,12 @@ class _MyAppState extends State { } on PlatformException { appSupportDirectory = 'Failed to get documents directory.'; } + + try { + appCacheDirectory = await _provider.getApplicationCachePath(); + } on PlatformException { + appCacheDirectory = 'Failed to get cache directory.'; + } // If the widget was removed from the tree while the asynchronous platform // message was in flight, we want to discard the reply rather than calling // setState to update our non-existent appearance. @@ -72,6 +80,7 @@ class _MyAppState extends State { _tempDirectory = tempDirectory; _downloadsDirectory = downloadsDirectory; _appSupportDirectory = appSupportDirectory; + _appCacheDirectory = appCacheDirectory; _documentsDirectory = documentsDirectory; }); } @@ -90,6 +99,7 @@ class _MyAppState extends State { Text('Documents Directory: $_documentsDirectory\n'), Text('Downloads Directory: $_downloadsDirectory\n'), Text('Application Support Directory: $_appSupportDirectory\n'), + Text('Application Cache Directory: $_appCacheDirectory\n'), ], ), ), diff --git a/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart b/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart index 1544dcea2984..59097114d3ad 100644 --- a/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart +++ b/packages/path_provider/path_provider_linux/lib/src/path_provider_linux.dart @@ -71,6 +71,16 @@ class PathProviderLinux extends PathProviderPlatform { return Future.value(xdg.getUserDirectory('DOCUMENTS')?.path); } + @override + Future getApplicationCachePath() async { + final Directory directory = + Directory(path.join(xdg.cacheHome.path, await _getId())); + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + return directory.path; + } + @override Future getDownloadsPath() { return Future.value(xdg.getUserDirectory('DOWNLOAD')?.path); diff --git a/packages/path_provider/path_provider_linux/pubspec.yaml b/packages/path_provider/path_provider_linux/pubspec.yaml index a72228fd93d4..b1c3e7fab8c3 100644 --- a/packages/path_provider/path_provider_linux/pubspec.yaml +++ b/packages/path_provider/path_provider_linux/pubspec.yaml @@ -2,7 +2,7 @@ name: path_provider_linux description: Linux implementation of the path_provider plugin repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_linux issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 -version: 2.1.11 +version: 2.2.0 environment: sdk: ">=2.18.0 <4.0.0" @@ -20,7 +20,7 @@ dependencies: flutter: sdk: flutter path: ^1.8.0 - path_provider_platform_interface: ^2.0.0 + path_provider_platform_interface: ^2.1.0 xdg_directories: ">=0.2.0 <2.0.0" dev_dependencies: diff --git a/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart b/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart index 1f567c00513d..b5dfcce15012 100644 --- a/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart +++ b/packages/path_provider/path_provider_linux/test/path_provider_linux_test.dart @@ -57,6 +57,13 @@ void main() { expect(await plugin.getApplicationDocumentsPath(), startsWith('/')); }); + test('getApplicationCachePath', () async { + final PathProviderPlatform plugin = PathProviderLinux.private( + executableName: 'path_provider_linux_test_binary'); + expect(await plugin.getApplicationCachePath(), + '${xdg.cacheHome.path}/path_provider_linux_test_binary'); + }); + test('getDownloadsPath', () async { final PathProviderPlatform plugin = PathProviderPlatform.instance; expect(await plugin.getDownloadsPath(), startsWith('/')); diff --git a/packages/path_provider/path_provider_platform_interface/CHANGELOG.md b/packages/path_provider/path_provider_platform_interface/CHANGELOG.md index f96711be4fdd..051c0e5323cf 100644 --- a/packages/path_provider/path_provider_platform_interface/CHANGELOG.md +++ b/packages/path_provider/path_provider_platform_interface/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 2.1.0 +* Adds getApplicationCachePath() for storing app-specific cache files. * Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. * Aligns Dart and Flutter SDK constraints. diff --git a/packages/path_provider/path_provider_platform_interface/lib/path_provider_platform_interface.dart b/packages/path_provider/path_provider_platform_interface/lib/path_provider_platform_interface.dart index 517ac74d8fa0..682d1ef0387d 100644 --- a/packages/path_provider/path_provider_platform_interface/lib/path_provider_platform_interface.dart +++ b/packages/path_provider/path_provider_platform_interface/lib/path_provider_platform_interface.dart @@ -62,6 +62,12 @@ abstract class PathProviderPlatform extends PlatformInterface { 'getApplicationDocumentsPath() has not been implemented.'); } + /// Path to a directory where application specific cache data can be stored. + Future getApplicationCachePath() { + throw UnimplementedError( + 'getApplicationCachePath() has not been implemented.'); + } + /// Path to a directory where the application may access top level storage. /// The current operating system should be determined before issuing this /// function call, as this functionality is only available on Android. diff --git a/packages/path_provider/path_provider_platform_interface/lib/src/method_channel_path_provider.dart b/packages/path_provider/path_provider_platform_interface/lib/src/method_channel_path_provider.dart index 991be55bce8c..02729f896168 100644 --- a/packages/path_provider/path_provider_platform_interface/lib/src/method_channel_path_provider.dart +++ b/packages/path_provider/path_provider_platform_interface/lib/src/method_channel_path_provider.dart @@ -52,6 +52,11 @@ class MethodChannelPathProvider extends PathProviderPlatform { .invokeMethod('getApplicationDocumentsDirectory'); } + @override + Future getApplicationCachePath() { + return methodChannel.invokeMethod('getApplicationCacheDirectory'); + } + @override Future getExternalStoragePath() { if (!_platform.isAndroid) { diff --git a/packages/path_provider/path_provider_platform_interface/pubspec.yaml b/packages/path_provider/path_provider_platform_interface/pubspec.yaml index 193bb85b94a4..44eb59aa4a66 100644 --- a/packages/path_provider/path_provider_platform_interface/pubspec.yaml +++ b/packages/path_provider/path_provider_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/path_provider issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.0.6 +version: 2.1.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/path_provider/path_provider_platform_interface/test/method_channel_path_provider_test.dart b/packages/path_provider/path_provider_platform_interface/test/method_channel_path_provider_test.dart index 035e7becb9ff..2c68ec574c8a 100644 --- a/packages/path_provider/path_provider_platform_interface/test/method_channel_path_provider_test.dart +++ b/packages/path_provider/path_provider_platform_interface/test/method_channel_path_provider_test.dart @@ -14,6 +14,7 @@ void main() { const String kApplicationSupportPath = 'applicationSupportPath'; const String kLibraryPath = 'libraryPath'; const String kApplicationDocumentsPath = 'applicationDocumentsPath'; + const String kApplicationCachePath = 'applicationCachePath'; const String kExternalCachePaths = 'externalCachePaths'; const String kExternalStoragePaths = 'externalStoragePaths'; const String kDownloadsPath = 'downloadsPath'; @@ -39,6 +40,8 @@ void main() { return kLibraryPath; case 'getApplicationDocumentsDirectory': return kApplicationDocumentsPath; + case 'getApplicationCacheDirectory': + return kApplicationCachePath; case 'getExternalStorageDirectories': return [kExternalStoragePaths]; case 'getExternalCacheDirectories': @@ -126,6 +129,18 @@ void main() { expect(path, kApplicationDocumentsPath); }); + test('getApplicationCachePath succeeds', () async { + final String? result = + await methodChannelPathProvider.getApplicationCachePath(); + expect( + log, + [ + isMethodCall('getApplicationCacheDirectory', arguments: null) + ], + ); + expect(result, kApplicationCachePath); + }); + test('getExternalCachePaths android succeeds', () async { final List? result = await methodChannelPathProvider.getExternalCachePaths(); diff --git a/packages/path_provider/path_provider_platform_interface/test/path_provider_platform_interface_test.dart b/packages/path_provider/path_provider_platform_interface/test/path_provider_platform_interface_test.dart new file mode 100644 index 000000000000..9d9bc851cef2 --- /dev/null +++ b/packages/path_provider/path_provider_platform_interface/test/path_provider_platform_interface_test.dart @@ -0,0 +1,29 @@ +// Copyright 2013 The Flutter Authors. 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:flutter_test/flutter_test.dart'; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; +import 'package:path_provider_platform_interface/src/method_channel_path_provider.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('$PathProviderPlatform', () { + test('$MethodChannelPathProvider is the default instance', () { + expect(PathProviderPlatform.instance, isA()); + }); + + test('getApplicationCachePath throws unimplemented error', () { + final ExtendsPathProviderPlatform pathProviderPlatform = + ExtendsPathProviderPlatform(); + + expect( + () => pathProviderPlatform.getApplicationCachePath(), + throwsUnimplementedError, + ); + }); + }); +} + +class ExtendsPathProviderPlatform extends PathProviderPlatform {} diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index 6011789c0c01..04a201f11280 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.0 + +* Adds getApplicationCachePath() for storing app-specific cache files. + ## 2.1.7 * Adds compatibility with `win32` 5.x. diff --git a/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart b/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart index a8285963adb6..0e900224be7a 100644 --- a/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart +++ b/packages/path_provider/path_provider_windows/example/integration_test/path_provider_test.dart @@ -28,6 +28,12 @@ void main() { _verifySampleFile(result, 'applicationSupport'); }); + testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async { + final PathProviderWindows provider = PathProviderWindows(); + final String? result = await provider.getApplicationCachePath(); + _verifySampleFile(result, 'applicationCache'); + }); + testWidgets('getDownloadsDirectory', (WidgetTester tester) async { final PathProviderWindows provider = PathProviderWindows(); final String? result = await provider.getDownloadsPath(); diff --git a/packages/path_provider/path_provider_windows/example/lib/main.dart b/packages/path_provider/path_provider_windows/example/lib/main.dart index e910732eb868..53e46e517d06 100644 --- a/packages/path_provider/path_provider_windows/example/lib/main.dart +++ b/packages/path_provider/path_provider_windows/example/lib/main.dart @@ -24,6 +24,7 @@ class _MyAppState extends State { String? _downloadsDirectory = 'Unknown'; String? _appSupportDirectory = 'Unknown'; String? _documentsDirectory = 'Unknown'; + String? _cacheDirectory = 'Unknown'; @override void initState() { @@ -37,6 +38,7 @@ class _MyAppState extends State { String? downloadsDirectory; String? appSupportDirectory; String? documentsDirectory; + String? cacheDirectory; final PathProviderWindows provider = PathProviderWindows(); try { @@ -62,11 +64,18 @@ class _MyAppState extends State { appSupportDirectory = 'Failed to get app support directory: $exception'; } + try { + cacheDirectory = await provider.getApplicationCachePath(); + } catch (exception) { + cacheDirectory = 'Failed to get cache directory: $exception'; + } + setState(() { _tempDirectory = tempDirectory; _downloadsDirectory = downloadsDirectory; _appSupportDirectory = appSupportDirectory; _documentsDirectory = documentsDirectory; + _cacheDirectory = cacheDirectory; }); } @@ -84,6 +93,7 @@ class _MyAppState extends State { Text('Documents Directory: $_documentsDirectory\n'), Text('Downloads Directory: $_downloadsDirectory\n'), Text('Application Support Directory: $_appSupportDirectory\n'), + Text('Cache Directory: $_cacheDirectory\n'), ], ), ), diff --git a/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart b/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart index 691d7a2da84b..2faa599a5341 100644 --- a/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart +++ b/packages/path_provider/path_provider_windows/lib/src/path_provider_windows_real.dart @@ -114,30 +114,17 @@ class PathProviderWindows extends PathProviderPlatform { } @override - Future getApplicationSupportPath() async { - final String? appDataRoot = - await getPath(WindowsKnownFolder.RoamingAppData); - if (appDataRoot == null) { - return null; - } - final Directory directory = Directory( - path.join(appDataRoot, _getApplicationSpecificSubdirectory())); - // Ensure that the directory exists if possible, since it will on other - // platforms. If the name is longer than MAXPATH, creating will fail, so - // skip that step; it's up to the client to decide what to do with the path - // in that case (e.g., using a short path). - if (directory.path.length <= MAX_PATH) { - if (!directory.existsSync()) { - await directory.create(recursive: true); - } - } - return directory.path; - } + Future getApplicationSupportPath() => + _createApplicationSubdirectory(WindowsKnownFolder.RoamingAppData); @override Future getApplicationDocumentsPath() => getPath(WindowsKnownFolder.Documents); + @override + Future getApplicationCachePath() => + _createApplicationSubdirectory(WindowsKnownFolder.LocalAppData); + @override Future getDownloadsPath() => getPath(WindowsKnownFolder.Downloads); @@ -256,4 +243,23 @@ class PathProviderWindows extends PathProviderPlatform { } return sanitized.isEmpty ? null : sanitized; } + + Future _createApplicationSubdirectory(String folderId) async { + final String? baseDir = await getPath(folderId); + if (baseDir == null) { + return null; + } + final Directory directory = + Directory(path.join(baseDir, _getApplicationSpecificSubdirectory())); + // Ensure that the directory exists if possible, since it will on other + // platforms. If the name is longer than MAXPATH, creating will fail, so + // skip that step; it's up to the client to decide what to do with the path + // in that case (e.g., using a short path). + if (directory.path.length <= MAX_PATH) { + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + } + return directory.path; + } } diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 4e00b93cd4f6..8062aa5604ee 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: path_provider_windows description: Windows implementation of the path_provider plugin repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_windows issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 -version: 2.1.7 +version: 2.2.0 environment: sdk: ">=2.18.0 <4.0.0" @@ -20,7 +20,7 @@ dependencies: flutter: sdk: flutter path: ^1.8.0 - path_provider_platform_interface: ^2.0.0 + path_provider_platform_interface: ^2.1.0 win32: ">=2.1.0 <6.0.0" dev_dependencies: diff --git a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart index 48e56406c14f..dd8fead6668c 100644 --- a/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart +++ b/packages/path_provider/path_provider_windows/test/path_provider_windows_test.dart @@ -165,6 +165,20 @@ void main() { expect(path, contains(r'Documents')); }, skip: !Platform.isWindows); + test('getApplicationCachePath', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': 'Amazing App', + }, encoding: encodingCP1252); + final String? path = await pathProvider.getApplicationCachePath(); + expect(path, isNotNull); + if (path != null) { + expect(path, endsWith(r'AppData\Local\A Company\Amazing App')); + expect(Directory(path).existsSync(), isTrue); + } + }, skip: !Platform.isWindows); + test('getDownloadsPath', () async { final PathProviderWindows pathProvider = PathProviderWindows(); final String? path = await pathProvider.getDownloadsPath(); diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.gitignore b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.gitignore deleted file mode 100644 index 0fa6b675c0a5..000000000000 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -/build/ - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.metadata b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.metadata deleted file mode 100644 index 5db57c1fab41..000000000000 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 6db3d61ed4a58ba89140d7fe1fd294b598cc29c5 - channel: master - -project_type: app diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/README.md b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/README.md deleted file mode 100644 index 3c52fc95e5c6..000000000000 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# flutter_unit_tests - -Unit test scaffold for null safe Flutter projects. diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/.gitignore b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/.gitignore deleted file mode 100644 index 955123f360f8..000000000000 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# TODO(stuartmorgan) Remove this file when these are no longer generated; -# see the TODO in _runFlutterUnitTests in test_suites.dart -async_handlers.gen.dart -host2flutter.gen.dart -list.gen.dart -void_arg_flutter.gen.dart -void_arg_host.gen.dart -voidflutter.gen.dart -voidhost.gen.dart diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/core_tests.gen.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/core_tests.gen.dart deleted file mode 100644 index 6c0ded63c251..000000000000 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/core_tests.gen.dart +++ /dev/null @@ -1,2738 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Autogenerated from Pigeon (v10.1.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import - -import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; - -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; -import 'package:flutter/services.dart'; - -enum AnEnum { - one, - two, - three, -} - -/// A class containing all supported types. -class AllTypes { - AllTypes({ - required this.aBool, - required this.anInt, - required this.anInt64, - required this.aDouble, - required this.aByteArray, - required this.a4ByteArray, - required this.a8ByteArray, - required this.aFloatArray, - required this.aList, - required this.aMap, - required this.anEnum, - required this.aString, - required this.anObject, - }); - - bool aBool; - - int anInt; - - int anInt64; - - double aDouble; - - Uint8List aByteArray; - - Int32List a4ByteArray; - - Int64List a8ByteArray; - - Float64List aFloatArray; - - List aList; - - Map aMap; - - AnEnum anEnum; - - String aString; - - Object anObject; - - Object encode() { - return [ - aBool, - anInt, - anInt64, - aDouble, - aByteArray, - a4ByteArray, - a8ByteArray, - aFloatArray, - aList, - aMap, - anEnum.index, - aString, - anObject, - ]; - } - - static AllTypes decode(Object result) { - result as List; - return AllTypes( - aBool: result[0]! as bool, - anInt: result[1]! as int, - anInt64: result[2]! as int, - aDouble: result[3]! as double, - aByteArray: result[4]! as Uint8List, - a4ByteArray: result[5]! as Int32List, - a8ByteArray: result[6]! as Int64List, - aFloatArray: result[7]! as Float64List, - aList: result[8]! as List, - aMap: result[9]! as Map, - anEnum: AnEnum.values[result[10]! as int], - aString: result[11]! as String, - anObject: result[12]!, - ); - } -} - -/// A class containing all supported nullable types. -class AllNullableTypes { - AllNullableTypes({ - this.aNullableBool, - this.aNullableInt, - this.aNullableInt64, - this.aNullableDouble, - this.aNullableByteArray, - this.aNullable4ByteArray, - this.aNullable8ByteArray, - this.aNullableFloatArray, - this.aNullableList, - this.aNullableMap, - this.nullableNestedList, - this.nullableMapWithAnnotations, - this.nullableMapWithObject, - this.aNullableEnum, - this.aNullableString, - this.aNullableObject, - }); - - bool? aNullableBool; - - int? aNullableInt; - - int? aNullableInt64; - - double? aNullableDouble; - - Uint8List? aNullableByteArray; - - Int32List? aNullable4ByteArray; - - Int64List? aNullable8ByteArray; - - Float64List? aNullableFloatArray; - - List? aNullableList; - - Map? aNullableMap; - - List?>? nullableNestedList; - - Map? nullableMapWithAnnotations; - - Map? nullableMapWithObject; - - AnEnum? aNullableEnum; - - String? aNullableString; - - Object? aNullableObject; - - Object encode() { - return [ - aNullableBool, - aNullableInt, - aNullableInt64, - aNullableDouble, - aNullableByteArray, - aNullable4ByteArray, - aNullable8ByteArray, - aNullableFloatArray, - aNullableList, - aNullableMap, - nullableNestedList, - nullableMapWithAnnotations, - nullableMapWithObject, - aNullableEnum?.index, - aNullableString, - aNullableObject, - ]; - } - - static AllNullableTypes decode(Object result) { - result as List; - return AllNullableTypes( - aNullableBool: result[0] as bool?, - aNullableInt: result[1] as int?, - aNullableInt64: result[2] as int?, - aNullableDouble: result[3] as double?, - aNullableByteArray: result[4] as Uint8List?, - aNullable4ByteArray: result[5] as Int32List?, - aNullable8ByteArray: result[6] as Int64List?, - aNullableFloatArray: result[7] as Float64List?, - aNullableList: result[8] as List?, - aNullableMap: result[9] as Map?, - nullableNestedList: (result[10] as List?)?.cast?>(), - nullableMapWithAnnotations: - (result[11] as Map?)?.cast(), - nullableMapWithObject: - (result[12] as Map?)?.cast(), - aNullableEnum: - result[13] != null ? AnEnum.values[result[13]! as int] : null, - aNullableString: result[14] as String?, - aNullableObject: result[15], - ); - } -} - -/// A class for testing nested class handling. -/// -/// This is needed to test nested nullable and non-nullable classes, -/// `AllNullableTypes` is non-nullable here as it is easier to instantiate -/// than `AllTypes` when testing doesn't require both (ie. testing null classes). -class AllClassesWrapper { - AllClassesWrapper({ - required this.allNullableTypes, - this.allTypes, - }); - - AllNullableTypes allNullableTypes; - - AllTypes? allTypes; - - Object encode() { - return [ - allNullableTypes.encode(), - allTypes?.encode(), - ]; - } - - static AllClassesWrapper decode(Object result) { - result as List; - return AllClassesWrapper( - allNullableTypes: AllNullableTypes.decode(result[0]! as List), - allTypes: result[1] != null - ? AllTypes.decode(result[1]! as List) - : null, - ); - } -} - -/// A data class containing a List, used in unit tests. -class TestMessage { - TestMessage({ - this.testList, - }); - - List? testList; - - Object encode() { - return [ - testList, - ]; - } - - static TestMessage decode(Object result) { - result as List; - return TestMessage( - testList: result[0] as List?, - ); - } -} - -class _HostIntegrationCoreApiCodec extends StandardMessageCodec { - const _HostIntegrationCoreApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is AllClassesWrapper) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is AllNullableTypes) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is AllTypes) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is TestMessage) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return AllClassesWrapper.decode(readValue(buffer)!); - case 129: - return AllNullableTypes.decode(readValue(buffer)!); - case 130: - return AllTypes.decode(readValue(buffer)!); - case 131: - return TestMessage.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - -/// The core interface that each host language plugin must implement in -/// platform_test integration tests. -class HostIntegrationCoreApi { - /// Constructor for [HostIntegrationCoreApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default - /// BinaryMessenger will be used which routes to the host platform. - HostIntegrationCoreApi({BinaryMessenger? binaryMessenger}) - : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; - - static const MessageCodec codec = _HostIntegrationCoreApiCodec(); - - /// A no-op function taking no arguments and returning no value, to sanity - /// test basic calling. - Future noop() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.noop', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } - - /// Returns the passed object, to test serialization and deserialization. - Future echoAllTypes(AllTypes arg_everything) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAllTypes', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_everything]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as AllTypes?)!; - } - } - - /// Returns an error, to test error handling. - Future throwError() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.throwError', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return replyList[0]; - } - } - - /// Returns an error from a void function, to test error handling. - Future throwErrorFromVoid() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.throwErrorFromVoid', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } - - /// Returns a Flutter error, to test error handling. - Future throwFlutterError() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.throwFlutterError', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return replyList[0]; - } - } - - /// Returns passed in int. - Future echoInt(int arg_anInt) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoInt', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anInt]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as int?)!; - } - } - - /// Returns passed in double. - Future echoDouble(double arg_aDouble) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoDouble', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aDouble]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as double?)!; - } - } - - /// Returns the passed in boolean. - Future echoBool(bool arg_aBool) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoBool', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aBool]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as bool?)!; - } - } - - /// Returns the passed in string. - Future echoString(String arg_aString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } - } - - /// Returns the passed in Uint8List. - Future echoUint8List(Uint8List arg_aUint8List) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoUint8List', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aUint8List]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Uint8List?)!; - } - } - - /// Returns the passed in generic Object. - Future echoObject(Object arg_anObject) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoObject', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anObject]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return replyList[0]!; - } - } - - /// Returns the passed list, to test serialization and deserialization. - Future> echoList(List arg_aList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoList', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as List?)!.cast(); - } - } - - /// Returns the passed map, to test serialization and deserialization. - Future> echoMap(Map arg_aMap) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoMap', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aMap]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Map?)!.cast(); - } - } - - /// Returns the passed map to test nested class serialization and deserialization. - Future echoClassWrapper( - AllClassesWrapper arg_wrapper) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoClassWrapper', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_wrapper]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as AllClassesWrapper?)!; - } - } - - /// Returns the passed object, to test serialization and deserialization. - Future echoAllNullableTypes( - AllNullableTypes? arg_everything) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAllNullableTypes', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_everything]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as AllNullableTypes?); - } - } - - /// Returns the inner `aString` value from the wrapped object, to test - /// sending of nested objects. - Future extractNestedNullableString( - AllClassesWrapper arg_wrapper) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.extractNestedNullableString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_wrapper]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as String?); - } - } - - /// Returns the inner `aString` value from the wrapped object, to test - /// sending of nested objects. - Future createNestedNullableString( - String? arg_nullableString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.createNestedNullableString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_nullableString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as AllClassesWrapper?)!; - } - } - - /// Returns passed in arguments of multiple types. - Future sendMultipleNullableTypes(bool? arg_aNullableBool, - int? arg_aNullableInt, String? arg_aNullableString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.sendMultipleNullableTypes', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send( - [arg_aNullableBool, arg_aNullableInt, arg_aNullableString]) - as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as AllNullableTypes?)!; - } - } - - /// Returns passed in int. - Future echoNullableInt(int? arg_aNullableInt) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableInt', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableInt]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as int?); - } - } - - /// Returns passed in double. - Future echoNullableDouble(double? arg_aNullableDouble) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableDouble', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableDouble]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as double?); - } - } - - /// Returns the passed in boolean. - Future echoNullableBool(bool? arg_aNullableBool) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableBool', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableBool]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as bool?); - } - } - - /// Returns the passed in string. - Future echoNullableString(String? arg_aNullableString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as String?); - } - } - - /// Returns the passed in Uint8List. - Future echoNullableUint8List( - Uint8List? arg_aNullableUint8List) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableUint8List', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableUint8List]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as Uint8List?); - } - } - - /// Returns the passed in generic Object. - Future echoNullableObject(Object? arg_aNullableObject) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableObject', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableObject]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return replyList[0]; - } - } - - /// Returns the passed list, to test serialization and deserialization. - Future?> echoNullableList( - List? arg_aNullableList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableList', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as List?)?.cast(); - } - } - - /// Returns the passed map, to test serialization and deserialization. - Future?> echoNullableMap( - Map? arg_aNullableMap) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoNullableMap', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aNullableMap]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as Map?)?.cast(); - } - } - - /// A no-op function taking no arguments and returning no value, to sanity - /// test basic asynchronous calling. - Future noopAsync() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.noopAsync', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } - - /// Returns passed in int asynchronously. - Future echoAsyncInt(int arg_anInt) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncInt', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anInt]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as int?)!; - } - } - - /// Returns passed in double asynchronously. - Future echoAsyncDouble(double arg_aDouble) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncDouble', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aDouble]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as double?)!; - } - } - - /// Returns the passed in boolean asynchronously. - Future echoAsyncBool(bool arg_aBool) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncBool', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aBool]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as bool?)!; - } - } - - /// Returns the passed string asynchronously. - Future echoAsyncString(String arg_aString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } - } - - /// Returns the passed in Uint8List asynchronously. - Future echoAsyncUint8List(Uint8List arg_aUint8List) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncUint8List', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aUint8List]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Uint8List?)!; - } - } - - /// Returns the passed in generic Object asynchronously. - Future echoAsyncObject(Object arg_anObject) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncObject', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anObject]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return replyList[0]!; - } - } - - /// Returns the passed list, to test serialization and deserialization asynchronously. - Future> echoAsyncList(List arg_aList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncList', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as List?)!.cast(); - } - } - - /// Returns the passed map, to test serialization and deserialization asynchronously. - Future> echoAsyncMap( - Map arg_aMap) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncMap', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aMap]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Map?)!.cast(); - } - } - - /// Responds with an error from an async function returning a value. - Future throwAsyncError() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.throwAsyncError', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return replyList[0]; - } - } - - /// Responds with an error from an async void function. - Future throwAsyncErrorFromVoid() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.throwAsyncErrorFromVoid', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } - - /// Responds with a Flutter error from an async function returning a value. - Future throwAsyncFlutterError() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.throwAsyncFlutterError', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return replyList[0]; - } - } - - /// Returns the passed object, to test async serialization and deserialization. - Future echoAsyncAllTypes(AllTypes arg_everything) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncAllTypes', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_everything]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as AllTypes?)!; - } - } - - /// Returns the passed object, to test serialization and deserialization. - Future echoAsyncNullableAllNullableTypes( - AllNullableTypes? arg_everything) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableAllNullableTypes', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_everything]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as AllNullableTypes?); - } - } - - /// Returns passed in int asynchronously. - Future echoAsyncNullableInt(int? arg_anInt) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableInt', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anInt]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as int?); - } - } - - /// Returns passed in double asynchronously. - Future echoAsyncNullableDouble(double? arg_aDouble) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableDouble', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aDouble]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as double?); - } - } - - /// Returns the passed in boolean asynchronously. - Future echoAsyncNullableBool(bool? arg_aBool) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableBool', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aBool]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as bool?); - } - } - - /// Returns the passed string asynchronously. - Future echoAsyncNullableString(String? arg_aString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as String?); - } - } - - /// Returns the passed in Uint8List asynchronously. - Future echoAsyncNullableUint8List( - Uint8List? arg_aUint8List) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableUint8List', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aUint8List]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as Uint8List?); - } - } - - /// Returns the passed in generic Object asynchronously. - Future echoAsyncNullableObject(Object? arg_anObject) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableObject', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anObject]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return replyList[0]; - } - } - - /// Returns the passed list, to test serialization and deserialization asynchronously. - Future?> echoAsyncNullableList(List? arg_aList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableList', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as List?)?.cast(); - } - } - - /// Returns the passed map, to test serialization and deserialization asynchronously. - Future?> echoAsyncNullableMap( - Map? arg_aMap) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.echoAsyncNullableMap', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aMap]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as Map?)?.cast(); - } - } - - Future callFlutterNoop() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterNoop', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } - - Future callFlutterThrowError() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterThrowError', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return replyList[0]; - } - } - - Future callFlutterThrowErrorFromVoid() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterThrowErrorFromVoid', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } - - Future callFlutterEchoAllTypes(AllTypes arg_everything) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoAllTypes', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_everything]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as AllTypes?)!; - } - } - - Future callFlutterSendMultipleNullableTypes( - bool? arg_aNullableBool, - int? arg_aNullableInt, - String? arg_aNullableString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterSendMultipleNullableTypes', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send( - [arg_aNullableBool, arg_aNullableInt, arg_aNullableString]) - as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as AllNullableTypes?)!; - } - } - - Future callFlutterEchoBool(bool arg_aBool) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoBool', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aBool]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as bool?)!; - } - } - - Future callFlutterEchoInt(int arg_anInt) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoInt', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anInt]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as int?)!; - } - } - - Future callFlutterEchoDouble(double arg_aDouble) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoDouble', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aDouble]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as double?)!; - } - } - - Future callFlutterEchoString(String arg_aString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } - } - - Future callFlutterEchoUint8List(Uint8List arg_aList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoUint8List', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Uint8List?)!; - } - } - - Future> callFlutterEchoList(List arg_aList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoList', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as List?)!.cast(); - } - } - - Future> callFlutterEchoMap( - Map arg_aMap) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoMap', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aMap]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Map?)!.cast(); - } - } - - Future callFlutterEchoNullableBool(bool? arg_aBool) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoNullableBool', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aBool]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as bool?); - } - } - - Future callFlutterEchoNullableInt(int? arg_anInt) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoNullableInt', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_anInt]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as int?); - } - } - - Future callFlutterEchoNullableDouble(double? arg_aDouble) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoNullableDouble', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aDouble]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as double?); - } - } - - Future callFlutterEchoNullableString(String? arg_aString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoNullableString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as String?); - } - } - - Future callFlutterEchoNullableUint8List( - Uint8List? arg_aList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoNullableUint8List', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as Uint8List?); - } - } - - Future?> callFlutterEchoNullableList( - List? arg_aList) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoNullableList', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aList]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as List?)?.cast(); - } - } - - Future?> callFlutterEchoNullableMap( - Map? arg_aMap) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostIntegrationCoreApi.callFlutterEchoNullableMap', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aMap]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as Map?)?.cast(); - } - } -} - -class _FlutterIntegrationCoreApiCodec extends StandardMessageCodec { - const _FlutterIntegrationCoreApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is AllClassesWrapper) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is AllNullableTypes) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is AllTypes) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is TestMessage) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return AllClassesWrapper.decode(readValue(buffer)!); - case 129: - return AllNullableTypes.decode(readValue(buffer)!); - case 130: - return AllTypes.decode(readValue(buffer)!); - case 131: - return TestMessage.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - -/// The core interface that the Dart platform_test code implements for host -/// integration tests to call into. -abstract class FlutterIntegrationCoreApi { - static const MessageCodec codec = _FlutterIntegrationCoreApiCodec(); - - /// A no-op function taking no arguments and returning no value, to sanity - /// test basic calling. - void noop(); - - /// Responds with an error from an async function returning a value. - Object? throwError(); - - /// Responds with an error from an async void function. - void throwErrorFromVoid(); - - /// Returns the passed object, to test serialization and deserialization. - AllTypes echoAllTypes(AllTypes everything); - - /// Returns the passed object, to test serialization and deserialization. - AllNullableTypes echoAllNullableTypes(AllNullableTypes everything); - - /// Returns passed in arguments of multiple types. - /// - /// Tests multiple-arity FlutterApi handling. - AllNullableTypes sendMultipleNullableTypes( - bool? aNullableBool, int? aNullableInt, String? aNullableString); - - /// Returns the passed boolean, to test serialization and deserialization. - bool echoBool(bool aBool); - - /// Returns the passed int, to test serialization and deserialization. - int echoInt(int anInt); - - /// Returns the passed double, to test serialization and deserialization. - double echoDouble(double aDouble); - - /// Returns the passed string, to test serialization and deserialization. - String echoString(String aString); - - /// Returns the passed byte list, to test serialization and deserialization. - Uint8List echoUint8List(Uint8List aList); - - /// Returns the passed list, to test serialization and deserialization. - List echoList(List aList); - - /// Returns the passed map, to test serialization and deserialization. - Map echoMap(Map aMap); - - /// Returns the passed boolean, to test serialization and deserialization. - bool? echoNullableBool(bool? aBool); - - /// Returns the passed int, to test serialization and deserialization. - int? echoNullableInt(int? anInt); - - /// Returns the passed double, to test serialization and deserialization. - double? echoNullableDouble(double? aDouble); - - /// Returns the passed string, to test serialization and deserialization. - String? echoNullableString(String? aString); - - /// Returns the passed byte list, to test serialization and deserialization. - Uint8List? echoNullableUint8List(Uint8List? aList); - - /// Returns the passed list, to test serialization and deserialization. - List? echoNullableList(List? aList); - - /// Returns the passed map, to test serialization and deserialization. - Map? echoNullableMap(Map? aMap); - - /// A no-op function taking no arguments and returning no value, to sanity - /// test basic asynchronous calling. - Future noopAsync(); - - /// Returns the passed in generic Object asynchronously. - Future echoAsyncString(String aString); - - static void setup(FlutterIntegrationCoreApi? api, - {BinaryMessenger? binaryMessenger}) { - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.noop', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - // ignore message - api.noop(); - return; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.throwError', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - // ignore message - final Object? output = api.throwError(); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.throwErrorFromVoid', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - // ignore message - api.throwErrorFromVoid(); - return; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAllTypes', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAllTypes was null.'); - final List args = (message as List?)!; - final AllTypes? arg_everything = (args[0] as AllTypes?); - assert(arg_everything != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAllTypes was null, expected non-null AllTypes.'); - final AllTypes output = api.echoAllTypes(arg_everything!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAllNullableTypes', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAllNullableTypes was null.'); - final List args = (message as List?)!; - final AllNullableTypes? arg_everything = - (args[0] as AllNullableTypes?); - assert(arg_everything != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAllNullableTypes was null, expected non-null AllNullableTypes.'); - final AllNullableTypes output = - api.echoAllNullableTypes(arg_everything!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.sendMultipleNullableTypes', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.sendMultipleNullableTypes was null.'); - final List args = (message as List?)!; - final bool? arg_aNullableBool = (args[0] as bool?); - final int? arg_aNullableInt = (args[1] as int?); - final String? arg_aNullableString = (args[2] as String?); - final AllNullableTypes output = api.sendMultipleNullableTypes( - arg_aNullableBool, arg_aNullableInt, arg_aNullableString); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoBool', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoBool was null.'); - final List args = (message as List?)!; - final bool? arg_aBool = (args[0] as bool?); - assert(arg_aBool != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoBool was null, expected non-null bool.'); - final bool output = api.echoBool(arg_aBool!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoInt', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoInt was null.'); - final List args = (message as List?)!; - final int? arg_anInt = (args[0] as int?); - assert(arg_anInt != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoInt was null, expected non-null int.'); - final int output = api.echoInt(arg_anInt!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoDouble', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoDouble was null.'); - final List args = (message as List?)!; - final double? arg_aDouble = (args[0] as double?); - assert(arg_aDouble != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoDouble was null, expected non-null double.'); - final double output = api.echoDouble(arg_aDouble!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoString', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoString was null.'); - final List args = (message as List?)!; - final String? arg_aString = (args[0] as String?); - assert(arg_aString != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoString was null, expected non-null String.'); - final String output = api.echoString(arg_aString!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoUint8List', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoUint8List was null.'); - final List args = (message as List?)!; - final Uint8List? arg_aList = (args[0] as Uint8List?); - assert(arg_aList != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoUint8List was null, expected non-null Uint8List.'); - final Uint8List output = api.echoUint8List(arg_aList!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoList', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoList was null.'); - final List args = (message as List?)!; - final List? arg_aList = - (args[0] as List?)?.cast(); - assert(arg_aList != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoList was null, expected non-null List.'); - final List output = api.echoList(arg_aList!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoMap', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoMap was null.'); - final List args = (message as List?)!; - final Map? arg_aMap = - (args[0] as Map?)?.cast(); - assert(arg_aMap != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoMap was null, expected non-null Map.'); - final Map output = api.echoMap(arg_aMap!); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableBool', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableBool was null.'); - final List args = (message as List?)!; - final bool? arg_aBool = (args[0] as bool?); - final bool? output = api.echoNullableBool(arg_aBool); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableInt', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableInt was null.'); - final List args = (message as List?)!; - final int? arg_anInt = (args[0] as int?); - final int? output = api.echoNullableInt(arg_anInt); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableDouble', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableDouble was null.'); - final List args = (message as List?)!; - final double? arg_aDouble = (args[0] as double?); - final double? output = api.echoNullableDouble(arg_aDouble); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableString', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableString was null.'); - final List args = (message as List?)!; - final String? arg_aString = (args[0] as String?); - final String? output = api.echoNullableString(arg_aString); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableUint8List', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableUint8List was null.'); - final List args = (message as List?)!; - final Uint8List? arg_aList = (args[0] as Uint8List?); - final Uint8List? output = api.echoNullableUint8List(arg_aList); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableList', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableList was null.'); - final List args = (message as List?)!; - final List? arg_aList = - (args[0] as List?)?.cast(); - final List? output = api.echoNullableList(arg_aList); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableMap', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoNullableMap was null.'); - final List args = (message as List?)!; - final Map? arg_aMap = - (args[0] as Map?)?.cast(); - final Map? output = api.echoNullableMap(arg_aMap); - return output; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.noopAsync', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - // ignore message - await api.noopAsync(); - return; - }); - } - } - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAsyncString', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAsyncString was null.'); - final List args = (message as List?)!; - final String? arg_aString = (args[0] as String?); - assert(arg_aString != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterIntegrationCoreApi.echoAsyncString was null, expected non-null String.'); - final String output = await api.echoAsyncString(arg_aString!); - return output; - }); - } - } - } -} - -/// An API that can be implemented for minimal, compile-only tests. -class HostTrivialApi { - /// Constructor for [HostTrivialApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default - /// BinaryMessenger will be used which routes to the host platform. - HostTrivialApi({BinaryMessenger? binaryMessenger}) - : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; - - static const MessageCodec codec = StandardMessageCodec(); - - Future noop() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostTrivialApi.noop', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } -} - -/// A simple API implemented in some unit tests. -class HostSmallApi { - /// Constructor for [HostSmallApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default - /// BinaryMessenger will be used which routes to the host platform. - HostSmallApi({BinaryMessenger? binaryMessenger}) - : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; - - static const MessageCodec codec = StandardMessageCodec(); - - Future echo(String arg_aString) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostSmallApi.echo', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_aString]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } - } - - Future voidVoid() async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.HostSmallApi.voidVoid', codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send(null) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } - } -} - -class _FlutterSmallApiCodec extends StandardMessageCodec { - const _FlutterSmallApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is TestMessage) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return TestMessage.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - -/// A simple API called in some unit tests. -abstract class FlutterSmallApi { - static const MessageCodec codec = _FlutterSmallApiCodec(); - - TestMessage echoWrappedList(TestMessage msg); - - static void setup(FlutterSmallApi? api, {BinaryMessenger? binaryMessenger}) { - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.FlutterSmallApi.echoWrappedList', - codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterSmallApi.echoWrappedList was null.'); - final List args = (message as List?)!; - final TestMessage? arg_msg = (args[0] as TestMessage?); - assert(arg_msg != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.FlutterSmallApi.echoWrappedList was null, expected non-null TestMessage.'); - final TestMessage output = api.echoWrappedList(arg_msg!); - return output; - }); - } - } - } -} diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/pubspec.yaml b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/pubspec.yaml deleted file mode 100644 index 843d473c896a..000000000000 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/pubspec.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: flutter_unit_tests -description: Unit test scaffold for null safe Flutter projects. -publish_to: none # Remove this line if you wish to publish to pub.dev -version: 1.0.0+1 -environment: - sdk: ">=2.18.0 <4.0.0" - flutter: ">=3.3.0" - -dependencies: - flutter: - sdk: flutter - -dev_dependencies: - build_runner: ^2.1.10 - flutter_test: - sdk: flutter - mockito: 5.4.1 - -flutter: - uses-material-design: true diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/.gitignore b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/.gitignore deleted file mode 100644 index 796ec975a2f7..000000000000 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# TODO(stuartmorgan): Remove this, so that review will show the effects of -# changes on generated files. This will need a way to avoid unnecessary churn, -# such as a flag to suppress version stamp generation. -*.gen.dart -# The following are files that are used in integration tests, which need to be -# checked in to avoid analysis failures. -!core_tests.gen.dart diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart new file mode 100644 index 000000000000..8b4a04e9e9e7 --- /dev/null +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart @@ -0,0 +1,52 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Autogenerated from Pigeon, do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +class BackgroundApi2Host { + /// Constructor for [BackgroundApi2Host]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + BackgroundApi2Host({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + Future add(int arg_x, int arg_y) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.pigeon_integration_tests.BackgroundApi2Host.add', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_x, arg_y]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as int?)!; + } + } +} diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart new file mode 100644 index 000000000000..31a240620740 --- /dev/null +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart @@ -0,0 +1,165 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Autogenerated from Pigeon, do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +/// This comment is to test enum documentation comments. +enum EnumState { + /// This comment is to test enum member (Pending) documentation comments. + Pending, + + /// This comment is to test enum member (Success) documentation comments. + Success, + + /// This comment is to test enum member (Error) documentation comments. + Error, +} + +/// This comment is to test class documentation comments. +class DataWithEnum { + DataWithEnum({ + this.state, + }); + + /// This comment is to test field documentation comments. + EnumState? state; + + Object encode() { + return [ + state?.index, + ]; + } + + static DataWithEnum decode(Object result) { + result as List; + return DataWithEnum( + state: result[0] != null ? EnumState.values[result[0]! as int] : null, + ); + } +} + +class _EnumApi2HostCodec extends StandardMessageCodec { + const _EnumApi2HostCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is DataWithEnum) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return DataWithEnum.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// This comment is to test api documentation comments. +class EnumApi2Host { + /// Constructor for [EnumApi2Host]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + EnumApi2Host({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _EnumApi2HostCodec(); + + /// This comment is to test method documentation comments. + Future echo(DataWithEnum arg_data) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.pigeon_integration_tests.EnumApi2Host.echo', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_data]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as DataWithEnum?)!; + } + } +} + +class _EnumApi2FlutterCodec extends StandardMessageCodec { + const _EnumApi2FlutterCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is DataWithEnum) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return DataWithEnum.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// This comment is to test api documentation comments. +abstract class EnumApi2Flutter { + static const MessageCodec codec = _EnumApi2FlutterCodec(); + + /// This comment is to test method documentation comments. + DataWithEnum echo(DataWithEnum data); + + static void setup(EnumApi2Flutter? api, {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.pigeon_integration_tests.EnumApi2Flutter.echo', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.EnumApi2Flutter.echo was null.'); + final List args = (message as List?)!; + final DataWithEnum? arg_data = (args[0] as DataWithEnum?); + assert(arg_data != null, + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.EnumApi2Flutter.echo was null, expected non-null DataWithEnum.'); + final DataWithEnum output = api.echo(arg_data!); + return output; + }); + } + } + } +} diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/flutter_unittests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart similarity index 95% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/flutter_unittests.gen.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart index d7dad85b2577..5dfb8b7e0370 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/flutter_unittests.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Autogenerated from Pigeon (v10.1.4), do not edit directly. +// Autogenerated from Pigeon, do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -150,7 +150,7 @@ class Api { Future search(FlutterSearchRequest arg_request) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.Api.search', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.Api.search', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_request]) as List?; @@ -178,7 +178,7 @@ class Api { Future doSearches( FlutterSearchRequests arg_request) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.Api.doSearches', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.Api.doSearches', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_request]) as List?; @@ -205,7 +205,7 @@ class Api { Future echo(FlutterSearchRequests arg_requests) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.Api.echo', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.Api.echo', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_requests]) as List?; @@ -232,7 +232,7 @@ class Api { Future anInt(int arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.Api.anInt', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.Api.anInt', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_value]) as List?; diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart new file mode 100644 index 000000000000..482bbfd4f20b --- /dev/null +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart @@ -0,0 +1,359 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Autogenerated from Pigeon, do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +/// This comment is to test enum documentation comments. +/// +/// This comment also tests multiple line comments. +/// +/// //////////////////////// +/// This comment also tests comments that start with '/' +/// //////////////////////// +enum MessageRequestState { + pending, + success, + failure, +} + +/// This comment is to test class documentation comments. +/// +/// This comment also tests multiple line comments. +class MessageSearchRequest { + MessageSearchRequest({ + this.query, + this.anInt, + this.aBool, + }); + + /// This comment is to test field documentation comments. + String? query; + + /// This comment is to test field documentation comments. + int? anInt; + + /// This comment is to test field documentation comments. + bool? aBool; + + Object encode() { + return [ + query, + anInt, + aBool, + ]; + } + + static MessageSearchRequest decode(Object result) { + result as List; + return MessageSearchRequest( + query: result[0] as String?, + anInt: result[1] as int?, + aBool: result[2] as bool?, + ); + } +} + +/// This comment is to test class documentation comments. +class MessageSearchReply { + MessageSearchReply({ + this.result, + this.error, + this.state, + }); + + /// This comment is to test field documentation comments. + /// + /// This comment also tests multiple line comments. + String? result; + + /// This comment is to test field documentation comments. + String? error; + + /// This comment is to test field documentation comments. + MessageRequestState? state; + + Object encode() { + return [ + result, + error, + state?.index, + ]; + } + + static MessageSearchReply decode(Object result) { + result as List; + return MessageSearchReply( + result: result[0] as String?, + error: result[1] as String?, + state: result[2] != null + ? MessageRequestState.values[result[2]! as int] + : null, + ); + } +} + +/// This comment is to test class documentation comments. +class MessageNested { + MessageNested({ + this.request, + }); + + /// This comment is to test field documentation comments. + MessageSearchRequest? request; + + Object encode() { + return [ + request?.encode(), + ]; + } + + static MessageNested decode(Object result) { + result as List; + return MessageNested( + request: result[0] != null + ? MessageSearchRequest.decode(result[0]! as List) + : null, + ); + } +} + +class _MessageApiCodec extends StandardMessageCodec { + const _MessageApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is MessageSearchReply) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is MessageSearchRequest) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return MessageSearchReply.decode(readValue(buffer)!); + case 129: + return MessageSearchRequest.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// This comment is to test api documentation comments. +/// +/// This comment also tests multiple line comments. +class MessageApi { + /// Constructor for [MessageApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + MessageApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _MessageApiCodec(); + + /// This comment is to test documentation comments. + /// + /// This comment also tests multiple line comments. + Future initialize() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.pigeon_integration_tests.MessageApi.initialize', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + /// This comment is to test method documentation comments. + Future search(MessageSearchRequest arg_request) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.pigeon_integration_tests.MessageApi.search', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_request]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as MessageSearchReply?)!; + } + } +} + +class _MessageNestedApiCodec extends StandardMessageCodec { + const _MessageNestedApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is MessageNested) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is MessageSearchReply) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is MessageSearchRequest) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return MessageNested.decode(readValue(buffer)!); + case 129: + return MessageSearchReply.decode(readValue(buffer)!); + case 130: + return MessageSearchRequest.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// This comment is to test api documentation comments. +class MessageNestedApi { + /// Constructor for [MessageNestedApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + MessageNestedApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _MessageNestedApiCodec(); + + /// This comment is to test method documentation comments. + /// + /// This comment also tests multiple line comments. + Future search(MessageNested arg_nested) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.pigeon_integration_tests.MessageNestedApi.search', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_nested]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as MessageSearchReply?)!; + } + } +} + +class _MessageFlutterSearchApiCodec extends StandardMessageCodec { + const _MessageFlutterSearchApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is MessageSearchReply) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is MessageSearchRequest) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return MessageSearchReply.decode(readValue(buffer)!); + case 129: + return MessageSearchRequest.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// This comment is to test api documentation comments. +abstract class MessageFlutterSearchApi { + static const MessageCodec codec = _MessageFlutterSearchApiCodec(); + + /// This comment is to test method documentation comments. + MessageSearchReply search(MessageSearchRequest request); + + static void setup(MessageFlutterSearchApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.pigeon_integration_tests.MessageFlutterSearchApi.search', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.MessageFlutterSearchApi.search was null.'); + final List args = (message as List?)!; + final MessageSearchRequest? arg_request = + (args[0] as MessageSearchRequest?); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.MessageFlutterSearchApi.search was null, expected non-null MessageSearchRequest.'); + final MessageSearchReply output = api.search(arg_request!); + return output; + }); + } + } + } +} diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/multiple_arity.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart similarity index 82% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/multiple_arity.gen.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart index 2b4c1746bae5..a73735fde7a0 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/multiple_arity.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Autogenerated from Pigeon (v10.1.4), do not edit directly. +// Autogenerated from Pigeon, do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -24,7 +24,7 @@ class MultipleArityHostApi { Future subtract(int arg_x, int arg_y) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.MultipleArityHostApi.subtract', + 'dev.flutter.pigeon.pigeon_integration_tests.MultipleArityHostApi.subtract', codec, binaryMessenger: _binaryMessenger); final List? replyList = @@ -60,7 +60,7 @@ abstract class MultipleArityFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.MultipleArityFlutterApi.subtract', + 'dev.flutter.pigeon.pigeon_integration_tests.MultipleArityFlutterApi.subtract', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -68,14 +68,14 @@ abstract class MultipleArityFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.MultipleArityFlutterApi.subtract was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.MultipleArityFlutterApi.subtract was null.'); final List args = (message as List?)!; final int? arg_x = (args[0] as int?); assert(arg_x != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.MultipleArityFlutterApi.subtract was null, expected non-null int.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.MultipleArityFlutterApi.subtract was null, expected non-null int.'); final int? arg_y = (args[1] as int?); assert(arg_y != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.MultipleArityFlutterApi.subtract was null, expected non-null int.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.MultipleArityFlutterApi.subtract was null, expected non-null int.'); final int output = api.subtract(arg_x!, arg_y!); return output; }); diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/non_null_fields.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart similarity index 93% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/non_null_fields.gen.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart index 8484653e4fa3..4fc0d6a59c76 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/non_null_fields.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Autogenerated from Pigeon (v10.1.4), do not edit directly. +// Autogenerated from Pigeon, do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -151,7 +151,7 @@ class NonNullFieldHostApi { Future search( NonNullFieldSearchRequest arg_nested) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NonNullFieldHostApi.search', + 'dev.flutter.pigeon.pigeon_integration_tests.NonNullFieldHostApi.search', codec, binaryMessenger: _binaryMessenger); final List? replyList = @@ -220,7 +220,7 @@ abstract class NonNullFieldFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NonNullFieldFlutterApi.search', + 'dev.flutter.pigeon.pigeon_integration_tests.NonNullFieldFlutterApi.search', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -228,12 +228,12 @@ abstract class NonNullFieldFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.NonNullFieldFlutterApi.search was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NonNullFieldFlutterApi.search was null.'); final List args = (message as List?)!; final NonNullFieldSearchRequest? arg_request = (args[0] as NonNullFieldSearchRequest?); assert(arg_request != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.NonNullFieldFlutterApi.search was null, expected non-null NonNullFieldSearchRequest.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NonNullFieldFlutterApi.search was null, expected non-null NonNullFieldSearchRequest.'); final NonNullFieldSearchReply output = api.search(arg_request!); return output; }); diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_fields.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart similarity index 92% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_fields.gen.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart index a0d790939fbb..145467832d9a 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_fields.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Autogenerated from Pigeon (v10.1.4), do not edit directly. +// Autogenerated from Pigeon, do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -129,7 +129,8 @@ class NullFieldsHostApi { Future search( NullFieldsSearchRequest arg_nested) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullFieldsHostApi.search', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.NullFieldsHostApi.search', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_nested]) as List?; @@ -192,7 +193,7 @@ abstract class NullFieldsFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullFieldsFlutterApi.search', + 'dev.flutter.pigeon.pigeon_integration_tests.NullFieldsFlutterApi.search', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -200,12 +201,12 @@ abstract class NullFieldsFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.NullFieldsFlutterApi.search was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NullFieldsFlutterApi.search was null.'); final List args = (message as List?)!; final NullFieldsSearchRequest? arg_request = (args[0] as NullFieldsSearchRequest?); assert(arg_request != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.NullFieldsFlutterApi.search was null, expected non-null NullFieldsSearchRequest.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NullFieldsFlutterApi.search was null, expected non-null NullFieldsSearchRequest.'); final NullFieldsSearchReply output = api.search(arg_request!); return output; }); diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/nullable_returns.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart similarity index 89% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/nullable_returns.gen.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart index 3f6602a30078..286c5d5f14cb 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/nullable_returns.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Autogenerated from Pigeon (v10.1.4), do not edit directly. +// Autogenerated from Pigeon, do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -24,7 +24,7 @@ class NullableReturnHostApi { Future doit() async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableReturnHostApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableReturnHostApi.doit', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send(null) as List?; @@ -54,7 +54,7 @@ abstract class NullableReturnFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableReturnFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableReturnFlutterApi.doit', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -82,7 +82,8 @@ class NullableArgHostApi { Future doit(int? arg_x) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableArgHostApi.doit', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.NullableArgHostApi.doit', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_x]) as List?; @@ -117,7 +118,7 @@ abstract class NullableArgFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableArgFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableArgFlutterApi.doit', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -125,7 +126,7 @@ abstract class NullableArgFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.NullableArgFlutterApi.doit was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NullableArgFlutterApi.doit was null.'); final List args = (message as List?)!; final int? arg_x = (args[0] as int?); final int output = api.doit(arg_x); @@ -148,7 +149,7 @@ class NullableCollectionReturnHostApi { Future?> doit() async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionReturnHostApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionReturnHostApi.doit', codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send(null) as List?; @@ -178,7 +179,7 @@ abstract class NullableCollectionReturnFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionReturnFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionReturnFlutterApi.doit', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -206,7 +207,7 @@ class NullableCollectionArgHostApi { Future> doit(List? arg_x) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionArgHostApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionArgHostApi.doit', codec, binaryMessenger: _binaryMessenger); final List? replyList = @@ -242,7 +243,7 @@ abstract class NullableCollectionArgFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionArgFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionArgFlutterApi.doit', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -250,7 +251,7 @@ abstract class NullableCollectionArgFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.NullableCollectionArgFlutterApi.doit was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionArgFlutterApi.doit was null.'); final List args = (message as List?)!; final List? arg_x = (args[0] as List?)?.cast(); diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart similarity index 79% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.gen.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart index 0a491ff13d24..ef12ee8243fa 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Autogenerated from Pigeon (v10.1.4), do not edit directly. +// Autogenerated from Pigeon, do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -24,7 +24,8 @@ class PrimitiveHostApi { Future anInt(int arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.anInt', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.anInt', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_value]) as List?; @@ -51,7 +52,8 @@ class PrimitiveHostApi { Future aBool(bool arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aBool', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aBool', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_value]) as List?; @@ -78,7 +80,8 @@ class PrimitiveHostApi { Future aString(String arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aString', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aString', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_value]) as List?; @@ -105,7 +108,8 @@ class PrimitiveHostApi { Future aDouble(double arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aDouble', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aDouble', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_value]) as List?; @@ -132,7 +136,8 @@ class PrimitiveHostApi { Future> aMap(Map arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aMap', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aMap', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_value]) as List?; @@ -159,7 +164,8 @@ class PrimitiveHostApi { Future> aList(List arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aList', codec, + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aList', + codec, binaryMessenger: _binaryMessenger); final List? replyList = await channel.send([arg_value]) as List?; @@ -186,7 +192,7 @@ class PrimitiveHostApi { Future anInt32List(Int32List arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.anInt32List', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.anInt32List', codec, binaryMessenger: _binaryMessenger); final List? replyList = @@ -214,7 +220,7 @@ class PrimitiveHostApi { Future> aBoolList(List arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aBoolList', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aBoolList', codec, binaryMessenger: _binaryMessenger); final List? replyList = @@ -242,7 +248,7 @@ class PrimitiveHostApi { Future> aStringIntMap(Map arg_value) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aStringIntMap', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aStringIntMap', codec, binaryMessenger: _binaryMessenger); final List? replyList = @@ -294,7 +300,7 @@ abstract class PrimitiveFlutterApi { {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.anInt', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -302,11 +308,11 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.anInt was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt was null.'); final List args = (message as List?)!; final int? arg_value = (args[0] as int?); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.anInt was null, expected non-null int.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt was null, expected non-null int.'); final int output = api.anInt(arg_value!); return output; }); @@ -314,7 +320,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aBool', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBool', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -322,11 +328,11 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aBool was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBool was null.'); final List args = (message as List?)!; final bool? arg_value = (args[0] as bool?); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aBool was null, expected non-null bool.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBool was null, expected non-null bool.'); final bool output = api.aBool(arg_value!); return output; }); @@ -334,7 +340,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aString', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aString', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -342,11 +348,11 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aString was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aString was null.'); final List args = (message as List?)!; final String? arg_value = (args[0] as String?); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aString was null, expected non-null String.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aString was null, expected non-null String.'); final String output = api.aString(arg_value!); return output; }); @@ -354,7 +360,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aDouble', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aDouble', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -362,11 +368,11 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aDouble was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aDouble was null.'); final List args = (message as List?)!; final double? arg_value = (args[0] as double?); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aDouble was null, expected non-null double.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aDouble was null, expected non-null double.'); final double output = api.aDouble(arg_value!); return output; }); @@ -374,7 +380,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aMap', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aMap', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -382,12 +388,12 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aMap was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aMap was null.'); final List args = (message as List?)!; final Map? arg_value = (args[0] as Map?); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aMap was null, expected non-null Map.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aMap was null, expected non-null Map.'); final Map output = api.aMap(arg_value!); return output; }); @@ -395,7 +401,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aList', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aList', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -403,11 +409,11 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aList was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aList was null.'); final List args = (message as List?)!; final List? arg_value = (args[0] as List?); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aList was null, expected non-null List.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aList was null, expected non-null List.'); final List output = api.aList(arg_value!); return output; }); @@ -415,7 +421,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.anInt32List', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt32List', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -423,11 +429,11 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.anInt32List was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt32List was null.'); final List args = (message as List?)!; final Int32List? arg_value = (args[0] as Int32List?); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.anInt32List was null, expected non-null Int32List.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt32List was null, expected non-null Int32List.'); final Int32List output = api.anInt32List(arg_value!); return output; }); @@ -435,7 +441,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aBoolList', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBoolList', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -443,12 +449,12 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aBoolList was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBoolList was null.'); final List args = (message as List?)!; final List? arg_value = (args[0] as List?)?.cast(); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aBoolList was null, expected non-null List.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBoolList was null, expected non-null List.'); final List output = api.aBoolList(arg_value!); return output; }); @@ -456,7 +462,7 @@ abstract class PrimitiveFlutterApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aStringIntMap', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aStringIntMap', codec, binaryMessenger: binaryMessenger); if (api == null) { @@ -464,12 +470,12 @@ abstract class PrimitiveFlutterApi { } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aStringIntMap was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aStringIntMap was null.'); final List args = (message as List?)!; final Map? arg_value = (args[0] as Map?)?.cast(); assert(arg_value != null, - 'Argument for dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aStringIntMap was null, expected non-null Map.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aStringIntMap was null, expected non-null Map.'); final Map output = api.aStringIntMap(arg_value!); return output; }); diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml b/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml index 742b00a1cf7e..0256dda07dd7 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml @@ -8,6 +8,7 @@ environment: flutter: ">=3.3.0" dependencies: + build_runner: ^2.1.10 flutter: sdk: flutter # These are normal dependencies rather than dev_dependencies because the @@ -17,3 +18,4 @@ dependencies: sdk: flutter integration_test: sdk: flutter + mockito: 5.4.1 diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/regenerate_mocks.sh b/packages/pigeon/platform_tests/shared_test_plugin_code/regenerate_mocks.sh similarity index 71% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/regenerate_mocks.sh rename to packages/pigeon/platform_tests/shared_test_plugin_code/regenerate_mocks.sh index cd1f670090dc..0cb7e0f805fe 100755 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/regenerate_mocks.sh +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/regenerate_mocks.sh @@ -2,4 +2,4 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -flutter pub run build_runner build --delete-conflicting-outputs +dart run build_runner build --delete-conflicting-outputs diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/multiple_arity_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/multiple_arity_test.dart similarity index 87% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/multiple_arity_test.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/multiple_arity_test.dart index 1c3d535460ab..d446a036f74a 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/multiple_arity_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/multiple_arity_test.dart @@ -4,9 +4,10 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_unit_tests/multiple_arity.gen.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'package:shared_test_plugin_code/src/generated/multiple_arity.gen.dart'; + import 'multiple_arity_test.mocks.dart'; @GenerateMocks([BinaryMessenger]) @@ -14,7 +15,7 @@ void main() { test('multiple arity', () async { final BinaryMessenger mockMessenger = MockBinaryMessenger(); when(mockMessenger.send( - 'dev.flutter.pigeon.flutter_unit_tests.MultipleArityHostApi.subtract', + 'dev.flutter.pigeon.pigeon_integration_tests.MultipleArityHostApi.subtract', any)) .thenAnswer((Invocation realInvocation) async { final Object input = MultipleArityHostApi.codec diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/multiple_arity_test.mocks.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/multiple_arity_test.mocks.dart similarity index 94% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/multiple_arity_test.mocks.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/multiple_arity_test.mocks.dart index 0214f7e7196c..58653ceb0608 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/multiple_arity_test.mocks.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/multiple_arity_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations -// in flutter_unit_tests/test/multiple_arity_test.dart. +// Mocks generated by Mockito 5.4.1 from annotations +// in shared_test_plugin_code/test/multiple_arity_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; import 'dart:typed_data' as _i4; diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/non_null_fields_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/non_null_fields_test.dart similarity index 83% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/non_null_fields_test.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/non_null_fields_test.dart index 34b4193d5718..bca236c840ab 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/non_null_fields_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/non_null_fields_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_unit_tests/non_null_fields.gen.dart'; +import 'package:shared_test_plugin_code/src/generated/non_null_fields.gen.dart'; void main() { test('test constructor', () { diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_fields_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_fields_test.dart similarity index 98% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_fields_test.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/null_fields_test.dart index ec75a8ea169d..112317a38950 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_fields_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_fields_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_unit_tests/null_fields.gen.dart'; +import 'package:shared_test_plugin_code/src/generated/null_fields.gen.dart'; void main() { test('test constructor with values', () { diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.dart similarity index 88% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.dart index 12bbf61f074b..ffa3063374b7 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.dart @@ -6,10 +6,10 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_unit_tests/flutter_unittests.gen.dart'; -import 'package:flutter_unit_tests/nullable_returns.gen.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'package:shared_test_plugin_code/src/generated/flutter_unittests.gen.dart'; +import 'package:shared_test_plugin_code/src/generated/nullable_returns.gen.dart'; import 'null_safe_test.mocks.dart'; import 'test_util.dart'; @@ -53,7 +53,7 @@ void main() { completer.complete(Api.codec.encodeMessage([reply])); final Future sendResult = completer.future; when(mockMessenger.send( - 'dev.flutter.pigeon.flutter_unit_tests.Api.search', any)) + 'dev.flutter.pigeon.pigeon_integration_tests.Api.search', any)) .thenAnswer((Invocation realInvocation) => sendResult); final Api api = Api(binaryMessenger: mockMessenger); final FlutterSearchReply readReply = await api.search(request); @@ -68,7 +68,7 @@ void main() { final BinaryMessenger mockMessenger = MockBinaryMessenger(); echoOneArgument( mockMessenger, - 'dev.flutter.pigeon.flutter_unit_tests.Api.echo', + 'dev.flutter.pigeon.pigeon_integration_tests.Api.echo', Api.codec, ); final Api api = Api(binaryMessenger: mockMessenger); @@ -81,7 +81,7 @@ void main() { final BinaryMessenger mockMessenger = MockBinaryMessenger(); echoOneArgument( mockMessenger, - 'dev.flutter.pigeon.flutter_unit_tests.Api.anInt', + 'dev.flutter.pigeon.pigeon_integration_tests.Api.anInt', Api.codec, ); final Api api = Api(binaryMessenger: mockMessenger); @@ -91,7 +91,8 @@ void main() { test('return null to nonnull', () async { final BinaryMessenger mockMessenger = MockBinaryMessenger(); - const String channel = 'dev.flutter.pigeon.flutter_unit_tests.Api.anInt'; + const String channel = + 'dev.flutter.pigeon.pigeon_integration_tests.Api.anInt'; when(mockMessenger.send(channel, any)) .thenAnswer((Invocation realInvocation) async { return Api.codec.encodeMessage([null]); @@ -104,7 +105,7 @@ void main() { test('send null parameter', () async { final BinaryMessenger mockMessenger = MockBinaryMessenger(); const String channel = - 'dev.flutter.pigeon.flutter_unit_tests.NullableArgHostApi.doit'; + 'dev.flutter.pigeon.pigeon_integration_tests.NullableArgHostApi.doit'; when(mockMessenger.send(channel, any)) .thenAnswer((Invocation realInvocation) async { return Api.codec.encodeMessage([123]); @@ -117,7 +118,7 @@ void main() { test('send null collection parameter', () async { final BinaryMessenger mockMessenger = MockBinaryMessenger(); const String channel = - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionArgHostApi.doit'; + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionArgHostApi.doit'; when(mockMessenger.send(channel, any)) .thenAnswer((Invocation realInvocation) async { return Api.codec.encodeMessage([ @@ -138,7 +139,7 @@ void main() { final Completer resultCompleter = Completer(); binding.defaultBinaryMessenger.handlePlatformMessage( - 'dev.flutter.pigeon.flutter_unit_tests.NullableArgFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableArgFlutterApi.doit', NullableArgFlutterApi.codec.encodeMessage([null]), (ByteData? data) { resultCompleter.complete( @@ -162,7 +163,7 @@ void main() { final Completer> resultCompleter = Completer>(); binding.defaultBinaryMessenger.handlePlatformMessage( - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionArgFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionArgFlutterApi.doit', NullableCollectionArgFlutterApi.codec.encodeMessage([null]), (ByteData? data) { resultCompleter.complete( @@ -182,7 +183,7 @@ void main() { test('receive null return', () async { final BinaryMessenger mockMessenger = MockBinaryMessenger(); const String channel = - 'dev.flutter.pigeon.flutter_unit_tests.NullableReturnHostApi.doit'; + 'dev.flutter.pigeon.pigeon_integration_tests.NullableReturnHostApi.doit'; when(mockMessenger.send(channel, any)) .thenAnswer((Invocation realInvocation) async { return NullableReturnHostApi.codec.encodeMessage([null]); @@ -195,7 +196,7 @@ void main() { test('receive null collection return', () async { final BinaryMessenger mockMessenger = MockBinaryMessenger(); const String channel = - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionReturnHostApi.doit'; + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionReturnHostApi.doit'; when(mockMessenger.send(channel, any)) .thenAnswer((Invocation realInvocation) async { return NullableCollectionReturnHostApi.codec @@ -215,7 +216,7 @@ void main() { final Completer resultCompleter = Completer(); unawaited(binding.defaultBinaryMessenger.handlePlatformMessage( - 'dev.flutter.pigeon.flutter_unit_tests.NullableReturnFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableReturnFlutterApi.doit', NullableReturnFlutterApi.codec.encodeMessage([]), (ByteData? data) { resultCompleter.complete(null); @@ -238,7 +239,7 @@ void main() { final Completer?> resultCompleter = Completer?>(); unawaited(binding.defaultBinaryMessenger.handlePlatformMessage( - 'dev.flutter.pigeon.flutter_unit_tests.NullableCollectionReturnFlutterApi.doit', + 'dev.flutter.pigeon.pigeon_integration_tests.NullableCollectionReturnFlutterApi.doit', NullableCollectionReturnFlutterApi.codec.encodeMessage([]), (ByteData? data) { resultCompleter.complete(null); diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.mocks.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.mocks.dart similarity index 94% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.mocks.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.mocks.dart index c48bb3fdb4a3..ce80f9ddf9c7 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.mocks.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.mocks.dart @@ -1,15 +1,18 @@ -// Mocks generated by Mockito 5.4.0 from annotations -// in flutter_unit_tests/test/null_safe_test.dart. +// Mocks generated by Mockito 5.4.1 from annotations +// in shared_test_plugin_code/test/null_safe_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; import 'dart:typed_data' as _i4; import 'dart:ui' as _i5; import 'package:flutter/services.dart' as _i2; -import 'package:flutter_unit_tests/nullable_returns.gen.dart' as _i6; import 'package:mockito/mockito.dart' as _i1; +import 'package:shared_test_plugin_code/src/generated/nullable_returns.gen.dart' + as _i6; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/primitive_test.dart similarity index 85% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/primitive_test.dart index 27763e3e2639..e024f9c60d8a 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/primitive_test.dart @@ -4,9 +4,9 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_unit_tests/primitive.gen.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'package:shared_test_plugin_code/src/generated/primitive.gen.dart'; import 'primitive_test.mocks.dart'; import 'test_util.dart'; @@ -17,7 +17,7 @@ void main() { final BinaryMessenger mockMessenger = MockBinaryMessenger(); echoOneArgument( mockMessenger, - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.anInt', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.anInt', PrimitiveHostApi.codec, ); final PrimitiveHostApi api = @@ -30,7 +30,7 @@ void main() { final BinaryMessenger mockMessenger = MockBinaryMessenger(); echoOneArgument( mockMessenger, - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aBoolList', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aBoolList', PrimitiveHostApi.codec, ); final PrimitiveHostApi api = @@ -44,7 +44,7 @@ void main() { final PrimitiveFlutterApi api = MockPrimitiveFlutterApi(); when(api.aBoolList([true, false])).thenReturn([]); when(mockMessenger.setMessageHandler( - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveFlutterApi.aBoolList', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBoolList', any)) .thenAnswer((Invocation realInvocation) { final MessageHandler? handler = @@ -61,7 +61,7 @@ void main() { final BinaryMessenger mockMessenger = MockBinaryMessenger(); echoOneArgument( mockMessenger, - 'dev.flutter.pigeon.flutter_unit_tests.PrimitiveHostApi.aStringIntMap', + 'dev.flutter.pigeon.pigeon_integration_tests.PrimitiveHostApi.aStringIntMap', PrimitiveHostApi.codec, ); final PrimitiveHostApi api = diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.mocks.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/primitive_test.mocks.dart similarity index 95% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.mocks.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/primitive_test.mocks.dart index 469f9d9bbec5..28578ce52081 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.mocks.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/primitive_test.mocks.dart @@ -1,15 +1,18 @@ -// Mocks generated by Mockito 5.4.0 from annotations -// in flutter_unit_tests/test/primitive_test.dart. +// Mocks generated by Mockito 5.4.1 from annotations +// in shared_test_plugin_code/test/primitive_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; import 'dart:typed_data' as _i4; import 'dart:ui' as _i5; import 'package:flutter/services.dart' as _i2; -import 'package:flutter_unit_tests/primitive.gen.dart' as _i6; import 'package:mockito/mockito.dart' as _i1; +import 'package:shared_test_plugin_code/src/generated/primitive.gen.dart' + as _i6; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/test_util.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/test_util.dart similarity index 100% rename from packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/test_util.dart rename to packages/pigeon/platform_tests/shared_test_plugin_code/test/test_util.dart diff --git a/packages/pigeon/tool/run_tests.dart b/packages/pigeon/tool/run_tests.dart index e593e15e9a3d..9b0ce7aecb94 100644 --- a/packages/pigeon/tool/run_tests.dart +++ b/packages/pigeon/tool/run_tests.dart @@ -160,8 +160,6 @@ Future> _modifiedFiles( Future main(List args) async { // Run most tests on Linux, since Linux tends to be the easiest and cheapest. const List linuxHostTests = [ - dartUnitTests, - flutterUnitTests, mockHandlerTests, commandLineTests, androidJavaUnitTests, @@ -198,6 +196,10 @@ Future main(List args) async { // See comments in macOSHostTests: iOSObjCIntegrationTests, iOSSwiftIntegrationTests, + // These are Dart unit tests, which are already run by the normal + // test-dart repo tools command. + dartUnitTests, + flutterUnitTests, ], ]); diff --git a/packages/pigeon/tool/shared/generation.dart b/packages/pigeon/tool/shared/generation.dart index 825f395e23ae..3b037304c654 100644 --- a/packages/pigeon/tool/shared/generation.dart +++ b/packages/pigeon/tool/shared/generation.dart @@ -60,6 +60,7 @@ Future generateTestPigeons({required String baseDir}) async { 'background_platform_channels', 'core_tests', 'enum', + 'flutter_unittests', // Only for Dart unit tests in shared_test_plugin_code 'message', 'multiple_arity', 'non_null_fields', diff --git a/packages/pigeon/tool/shared/test_suites.dart b/packages/pigeon/tool/shared/test_suites.dart index 338e4a9b691b..658c4c083fa2 100644 --- a/packages/pigeon/tool/shared/test_suites.dart +++ b/packages/pigeon/tool/shared/test_suites.dart @@ -187,21 +187,6 @@ Future _runDartUnitTests() async { return exitCode; } -/// Generates multiple dart files based on the jobs defined in [jobs] which is -/// in the format of (key: input pigeon file path, value: output dart file -/// path). -Future _generateDart(Map jobs) async { - for (final MapEntry job in jobs.entries) { - // TODO(gaaclarke): Make this run the jobs in parallel. A bug in Dart - // blocked this (https://github.com/dart-lang/pub/pull/3285). - final int result = await runPigeon(input: job.key, dartOut: job.value); - if (result != 0) { - return result; - } - } - return 0; -} - Future _analyzeFlutterUnitTests(String flutterUnitTestsPath) async { final String messagePath = '$flutterUnitTestsPath/lib/message.gen.dart'; final String messageTestPath = '$flutterUnitTestsPath/test/message_test.dart'; @@ -227,28 +212,7 @@ Future _analyzeFlutterUnitTests(String flutterUnitTestsPath) async { } Future _runFlutterUnitTests() async { - // TODO(stuartmorgan): Migrate Dart unit tests to use the generated output in - // shared_test_plugin_code instead of having multiple copies of generation. - const String flutterUnitTestsPath = - 'platform_tests/flutter_null_safe_unit_tests'; - // Files from the pigeons/ directory to generate output for. - const List inputPigeons = [ - 'flutter_unittests', - 'core_tests', - 'primitive', - 'multiple_arity', - 'non_null_fields', - 'null_fields', - 'nullable_returns', - ]; - final int generateCode = await _generateDart({ - for (final String name in inputPigeons) - 'pigeons/$name.dart': '$flutterUnitTestsPath/lib/$name.gen.dart' - }); - if (generateCode != 0) { - return generateCode; - } - + const String flutterUnitTestsPath = 'platform_tests/shared_test_plugin_code'; final int analyzeCode = await _analyzeFlutterUnitTests(flutterUnitTestsPath); if (analyzeCode != 0) { return analyzeCode;