diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 00000000..ceb5225d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,89 @@ +include: package:flutter_lints/flutter.yaml + +analyzer: + language: + strict-casts: true + strict-raw-types: true + errors: + deprecated_member_use_from_same_package: ignore + +linter: + rules: + - annotate_overrides + - avoid_annotating_with_dynamic + - avoid_empty_else + - avoid_function_literals_in_foreach_calls + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + - avoid_returning_null_for_void + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_types_as_parameter_names + - await_only_futures + - camel_case_extensions + - camel_case_types + - constant_identifier_names + - control_flow_in_finally + - curly_braces_in_flow_control_structures + - depend_on_referenced_packages + - empty_catches + - empty_constructor_bodies + - empty_statements + - exhaustive_cases + - file_names + - library_names + - library_prefixes + - library_private_types_in_public_api + - no_duplicate_case_values + - no_leading_underscores_for_library_prefixes + - no_leading_underscores_for_local_identifiers + - non_constant_identifier_names + - null_check_on_nullable_type_parameter + - null_closures + - overridden_fields + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_contains + - prefer_final_fields + - prefer_for_elements_to_map_fromIterable + - prefer_function_declarations_over_variables + - prefer_if_null_operators + - prefer_initializing_formals + - prefer_inlined_adds + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - prefer_is_not_operator + - prefer_iterable_whereType + - prefer_null_aware_operators + - prefer_spread_collections + - prefer_typing_uninitialized_variables + - prefer_void_to_null + - provide_deprecation_message + - recursive_getters + - slash_for_doc_comments + - type_init_formals + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_constructor_name + - unnecessary_getters_setters + - unnecessary_late + - unnecessary_new + - unnecessary_null_aware_assignments + - unnecessary_null_in_if_null_operators + - unnecessary_nullable_for_final_variable_declarations + - unnecessary_overrides + - unnecessary_string_escapes + - unnecessary_string_interpolations + - unnecessary_this + - unrelated_type_equality_checks + - use_function_type_syntax_for_parameters + - use_rethrow_when_possible + - valid_regexps + - void_checks \ No newline at end of file diff --git a/pay/analysis_options.yaml b/pay/analysis_options.yaml new file mode 100644 index 00000000..0caccc81 --- /dev/null +++ b/pay/analysis_options.yaml @@ -0,0 +1 @@ +include: ../analysis_options.yaml \ No newline at end of file diff --git a/pay/example/analysis_options.yaml b/pay/example/analysis_options.yaml new file mode 100644 index 00000000..fac60e24 --- /dev/null +++ b/pay/example/analysis_options.yaml @@ -0,0 +1 @@ +include: ../../analysis_options.yaml \ No newline at end of file diff --git a/pay/example/lib/main.dart b/pay/example/lib/main.dart index 62aef699..d6a92bcb 100644 --- a/pay/example/lib/main.dart +++ b/pay/example/lib/main.dart @@ -19,7 +19,7 @@ import 'package:pay/pay.dart'; import 'payment_configurations.dart' as payment_configurations; void main() { - runApp(PayMaterialApp()); + runApp(const PayMaterialApp()); } const _paymentItems = [ @@ -31,18 +31,20 @@ const _paymentItems = [ ]; class PayMaterialApp extends StatelessWidget { + const PayMaterialApp({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { - return MaterialApp( + return const MaterialApp( title: 'Pay for Flutter Demo', localizationsDelegates: [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], supportedLocales: [ - const Locale('en', ''), - const Locale('es', ''), - const Locale('de', ''), + Locale('en', ''), + Locale('es', ''), + Locale('de', ''), ], home: PaySampleApp(), ); @@ -50,10 +52,10 @@ class PayMaterialApp extends StatelessWidget { } class PaySampleApp extends StatefulWidget { - PaySampleApp({Key? key}) : super(key: key); + const PaySampleApp({Key? key}) : super(key: key); @override - _PaySampleAppState createState() => _PaySampleAppState(); + State createState() => _PaySampleAppState(); } class _PaySampleAppState extends State { diff --git a/pay/example/pubspec.yaml b/pay/example/pubspec.yaml index acad31da..a7be6a03 100644 --- a/pay/example/pubspec.yaml +++ b/pay/example/pubspec.yaml @@ -29,6 +29,8 @@ flutter: dependencies: flutter: sdk: flutter + flutter_localizations: + sdk: flutter pay: path: ../ @@ -45,5 +47,8 @@ dependency_overrides: path: ../../pay_platform_interface dev_dependencies: + flutter_test: + sdk: flutter integration_test: sdk: flutter + flutter_lints: ^2.0.2 diff --git a/pay/lib/src/pay.dart b/pay/lib/src/pay.dart index 703cb373..63759d3b 100644 --- a/pay/lib/src/pay.dart +++ b/pay/lib/src/pay.dart @@ -27,7 +27,7 @@ class Pay { Map? _configurations; // Future to keep track of asynchronous initialization items. - Future? _assetInitializationFuture; + Future? _assetInitializationFuture; /// Creates an instance with a dictionary of [_configurations] and /// instantiates the [_payPlatform] to communicate with the native platforms. @@ -43,7 +43,7 @@ class Pay { } /// Load the list of configurations from the assets. - Future _loadConfigAssets(List configurationAssets) async => + Future _loadConfigAssets(List configurationAssets) async => _configurations = Map.fromEntries(await Future.wait(configurationAssets .map((ca) => PaymentConfiguration.fromAsset(ca)) .map((c) async => MapEntry(((await c).provider), await c)))); @@ -78,7 +78,7 @@ class Pay { /// Verifies that the selected provider has been previously configured or /// throws otherwise. - Future throwIfProviderIsNotDefined(PayProvider provider) async { + Future throwIfProviderIsNotDefined(PayProvider provider) async { await _assetInitializationFuture; if (!_configurations!.containsKey(provider)) { throw ProviderNotConfiguredException( diff --git a/pay/lib/src/widgets/google_pay_button.dart b/pay/lib/src/widgets/google_pay_button.dart index 1d29a267..aa6dc794 100644 --- a/pay/lib/src/widgets/google_pay_button.dart +++ b/pay/lib/src/widgets/google_pay_button.dart @@ -24,8 +24,9 @@ class GooglePayButton extends PayButton { GooglePayButton({ Key? key, - @Deprecated('Prefer to use [paymentConfiguration]. Take a look at the readme to see examples') - String? paymentConfigurationAsset, + @Deprecated( + 'Prefer to use [paymentConfiguration]. Take a look at the readme to see examples') + String? paymentConfigurationAsset, PaymentConfiguration? paymentConfiguration, required void Function(Map result) onPaymentResult, required List paymentItems, diff --git a/pay/lib/src/widgets/pay_button.dart b/pay/lib/src/widgets/pay_button.dart index d708cac8..955b191d 100644 --- a/pay/lib/src/widgets/pay_button.dart +++ b/pay/lib/src/widgets/pay_button.dart @@ -55,8 +55,9 @@ abstract class PayButton extends StatefulWidget { PayButton( Key? key, this.buttonProvider, - @Deprecated('Prefer to use [paymentConfiguration]. Take a look at the readme to see examples') - final String? paymentConfigurationAsset, + @Deprecated( + 'Prefer to use [paymentConfiguration]. Take a look at the readme to see examples') + final String? paymentConfigurationAsset, final PaymentConfiguration? paymentConfiguration, this.onPaymentResult, this.width, @@ -103,7 +104,7 @@ abstract class PayButton extends StatefulWidget { _supportedPlatforms.contains(defaultTargetPlatform); @override - _PayButtonState createState() => _PayButtonState(); + State createState() => _PayButtonState(); } /// Button state that adds the widgets to the tree and holds the result of the @@ -173,7 +174,7 @@ class ButtonPlaceholder extends StatelessWidget { final Widget? child; final EdgeInsets margin; - ButtonPlaceholder({ + const ButtonPlaceholder({ Key? key, this.child, required this.margin, diff --git a/pay/pubspec.yaml b/pay/pubspec.yaml index 879ee225..517e3c48 100644 --- a/pay/pubspec.yaml +++ b/pay/pubspec.yaml @@ -43,4 +43,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.8 - pedantic: ^1.11.0 + flutter_lints: ^2.0.2 diff --git a/pay/test/pay_test.dart b/pay/test/pay_test.dart index 8de719dd..798527fb 100644 --- a/pay/test/pay_test.dart +++ b/pay/test/pay_test.dart @@ -31,7 +31,8 @@ String _fixtureAsset(String name) { Future> _testProfileLoader( String paymentConfigurationAsset) async => - jsonDecode(_fixtureAsset(paymentConfigurationAsset)); + jsonDecode(_fixtureAsset(paymentConfigurationAsset)) + as Map; void main() { TestWidgetsFlutterBinding.ensureInitialized(); diff --git a/pay_android/analysis_options.yaml b/pay_android/analysis_options.yaml new file mode 100644 index 00000000..0caccc81 --- /dev/null +++ b/pay_android/analysis_options.yaml @@ -0,0 +1 @@ +include: ../analysis_options.yaml \ No newline at end of file diff --git a/pay_android/lib/src/widgets/google_pay_button.dart b/pay_android/lib/src/widgets/google_pay_button.dart index 07990bd1..09c72a1a 100644 --- a/pay_android/lib/src/widgets/google_pay_button.dart +++ b/pay_android/lib/src/widgets/google_pay_button.dart @@ -1,4 +1,4 @@ -/// Copyright 2021 Google LLC +/// Copyright 2023 Google LLC /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -102,7 +102,7 @@ class RawGooglePayButton extends StatelessWidget { /// /// The path is generated based on the button type and style, and the /// language code of the [context], and is returned as a [String]. - String _assetPath(context) { + String _assetPath(BuildContext context) { final assetName = '${type.asset}.svg'; if ([GooglePayButtonType.plain].contains(type)) { return 'assets/$assetName'; diff --git a/pay_android/pubspec.yaml b/pay_android/pubspec.yaml index 2ac3c0c3..ae7a7e50 100644 --- a/pay_android/pubspec.yaml +++ b/pay_android/pubspec.yaml @@ -74,4 +74,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.8 - pedantic: ^1.11.0 + flutter_lints: ^2.0.2 diff --git a/pay_android/test/pay_button_test.dart b/pay_android/test/pay_button_test.dart index 46792053..7e8874aa 100644 --- a/pay_android/test/pay_button_test.dart +++ b/pay_android/test/pay_button_test.dart @@ -1,4 +1,4 @@ -/// Copyright 2021 Google LLC +/// Copyright 2023 Google LLC /// SPDX-License-Identifier: Apache-2.0 import 'package:flutter/material.dart'; @@ -13,7 +13,7 @@ void main() { testWidgets('defaults to type dark', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, - child: RawGooglePayButton(onPressed: () => null), + child: RawGooglePayButton(onPressed: () {}), )); expect( @@ -30,7 +30,7 @@ void main() { Directionality( textDirection: TextDirection.ltr, child: Center( - child: RawGooglePayButton(onPressed: () => null), + child: RawGooglePayButton(onPressed: () {}), ), ), ); diff --git a/pay_ios/analysis_options.yaml b/pay_ios/analysis_options.yaml new file mode 100644 index 00000000..0caccc81 --- /dev/null +++ b/pay_ios/analysis_options.yaml @@ -0,0 +1 @@ +include: ../analysis_options.yaml \ No newline at end of file diff --git a/pay_ios/pubspec.yaml b/pay_ios/pubspec.yaml index d45df5e4..771b639d 100644 --- a/pay_ios/pubspec.yaml +++ b/pay_ios/pubspec.yaml @@ -36,4 +36,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.8 - pedantic: ^1.11.0 \ No newline at end of file + flutter_lints: ^2.0.2 \ No newline at end of file diff --git a/pay_ios/test/pay_button_test.dart b/pay_ios/test/pay_button_test.dart index 4a7ab4f6..05827074 100644 --- a/pay_ios/test/pay_button_test.dart +++ b/pay_ios/test/pay_button_test.dart @@ -1,4 +1,4 @@ -/// Copyright 2021 Google LLC +/// Copyright 2023 Google LLC /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ void main() { testWidgets('defaults to type plan and black', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, - child: RawApplePayButton(onPressed: () => null), + child: RawApplePayButton(onPressed: () {}), )); expect( @@ -46,7 +46,7 @@ void main() { Directionality( textDirection: TextDirection.ltr, child: Center( - child: RawApplePayButton(onPressed: () => null), + child: RawApplePayButton(onPressed: () {}), ), ), ); diff --git a/pay_platform_interface/analysis_options.yaml b/pay_platform_interface/analysis_options.yaml new file mode 100644 index 00000000..0caccc81 --- /dev/null +++ b/pay_platform_interface/analysis_options.yaml @@ -0,0 +1 @@ +include: ../analysis_options.yaml \ No newline at end of file diff --git a/pay_platform_interface/lib/core/payment_configuration.dart b/pay_platform_interface/lib/core/payment_configuration.dart index d9debe63..ff1440d7 100644 --- a/pay_platform_interface/lib/core/payment_configuration.dart +++ b/pay_platform_interface/lib/core/payment_configuration.dart @@ -56,16 +56,16 @@ class PaymentConfiguration { PaymentConfiguration._(Map configuration) : assert(configuration.containsKey('provider')), assert(configuration.containsKey('data')), - assert(PayProviders.isValidProvider(configuration['provider'])), - provider = PayProviders.fromString(configuration['provider'])!, - _parameters = Configurations.buildParameters( - PayProviders.fromString(configuration['provider'])!, - configuration['data']); + assert( + PayProviders.isValidProvider(configuration['provider'] as String)), + provider = + PayProviders.fromString(configuration['provider'] as String)!, + _parameters = Configurations.extractParameters(configuration); /// Creates a [PaymentConfiguration] object from the /// [paymentConfigurationString] in JSON format. PaymentConfiguration.fromJsonString(String paymentConfigurationString) - : this._(jsonDecode(paymentConfigurationString)); + : this._(jsonDecode(paymentConfigurationString) as Map); /// Creates a [PaymentConfiguration] object wrapped in a [Future] from a /// configuration loaded from an external source. @@ -97,8 +97,8 @@ class PaymentConfiguration { /// caller. static Future> _defaultProfileLoader( String paymentConfigurationAsset) async => - await rootBundle.loadStructuredData( - 'assets/$paymentConfigurationAsset', (s) async => jsonDecode(s)); + await rootBundle.loadStructuredData('assets/$paymentConfigurationAsset', + (s) async => jsonDecode(s) as Map); /// Returns the core configuration map in this object. Future> parameterMap() async { diff --git a/pay_platform_interface/lib/core/payment_item.dart b/pay_platform_interface/lib/core/payment_item.dart index 32d88863..d3472661 100644 --- a/pay_platform_interface/lib/core/payment_item.dart +++ b/pay_platform_interface/lib/core/payment_item.dart @@ -1,4 +1,4 @@ -/// Copyright 2021 Google LLC +/// Copyright 2023 Google LLC /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/pay_platform_interface/lib/pay_channel.dart b/pay_platform_interface/lib/pay_channel.dart index f6ce03ad..9911f2c6 100644 --- a/pay_platform_interface/lib/pay_channel.dart +++ b/pay_platform_interface/lib/pay_channel.dart @@ -1,4 +1,4 @@ -/// Copyright 2021 Google LLC +/// Copyright 2023 Google LLC /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -44,7 +44,8 @@ class PayMethodChannel extends PayPlatform { @override Future userCanPay(PaymentConfiguration paymentConfiguration) async { return await _channel.invokeMethod( - 'userCanPay', jsonEncode(await paymentConfiguration.parameterMap())); + 'userCanPay', jsonEncode(await paymentConfiguration.parameterMap())) + as bool; } /// Shows the payment selector to complete the payment operation. @@ -61,8 +62,8 @@ class PayMethodChannel extends PayPlatform { final paymentResult = await _channel.invokeMethod('showPaymentSelector', { 'payment_profile': jsonEncode(await paymentConfiguration.parameterMap()), 'payment_items': paymentItems.map((item) => item.toMap()).toList(), - }); + }) as String; - return jsonDecode(paymentResult); + return jsonDecode(paymentResult) as Map; } } diff --git a/pay_platform_interface/lib/pay_platform_interface.dart b/pay_platform_interface/lib/pay_platform_interface.dart index f048ce9a..f8a0e3b6 100644 --- a/pay_platform_interface/lib/pay_platform_interface.dart +++ b/pay_platform_interface/lib/pay_platform_interface.dart @@ -1,4 +1,4 @@ -/// Copyright 2021 Google LLC +/// Copyright 2023 Google LLC /// SPDX-License-Identifier: Apache-2.0 import 'core/payment_configuration.dart'; diff --git a/pay_platform_interface/lib/util/configurations.dart b/pay_platform_interface/lib/util/configurations.dart index d6cf2ed7..f1ec526a 100644 --- a/pay_platform_interface/lib/util/configurations.dart +++ b/pay_platform_interface/lib/util/configurations.dart @@ -25,8 +25,13 @@ class Configurations { /// /// Takes the configuration included in [config] and returns and updated /// version of the object wrapped in a [Future] with additional metadata. - static Future> buildParameters( - PayProvider provider, Map configurationParams) async { + static Future> extractParameters( + Map configuration) async { + PayProvider provider = + PayProviders.fromString(configuration['provider'] as String)!; + Map configurationParams = + configuration['data'] as Map; + switch (provider) { case PayProvider.apple_pay: return configurationParams; @@ -50,9 +55,9 @@ class Configurations { } /// Retrieves package information from the `pubspec.yaml` file as a [Map]. - static Future _getPackageConfiguration() async { + static Future> _getPackageConfiguration() async { final configurationFile = await rootBundle .loadString('packages/pay_platform_interface/pubspec.yaml'); - return loadYaml(configurationFile); + return loadYaml(configurationFile) as Map; } } diff --git a/pay_platform_interface/pubspec.yaml b/pay_platform_interface/pubspec.yaml index af0c2cd1..72a16ace 100644 --- a/pay_platform_interface/pubspec.yaml +++ b/pay_platform_interface/pubspec.yaml @@ -33,4 +33,4 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - pedantic: ^1.11.0 + flutter_lints: ^2.0.2 diff --git a/pay_platform_interface/test/pay_channel_test.dart b/pay_platform_interface/test/pay_channel_test.dart index 8dc6d8f7..bc4f9450 100644 --- a/pay_platform_interface/test/pay_channel_test.dart +++ b/pay_platform_interface/test/pay_channel_test.dart @@ -1,4 +1,4 @@ -/// Copyright 2021 Google LLC +/// Copyright 2023 Google LLC /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -23,16 +23,16 @@ import 'package:pay_platform_interface/pay_channel.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - late final PayMethodChannel _mobilePlatform; + late final PayMethodChannel mobilePlatform; const channel = MethodChannel('plugins.flutter.io/pay_channel'); - const _providerApplePay = PayProvider.apple_pay; - final _payConfigString = - '{"provider": "${_providerApplePay.toSimpleString()}", "data": {}}'; - final _dummyConfig = PaymentConfiguration.fromJsonString(_payConfigString); + const providerApplePay = PayProvider.apple_pay; + final payConfigString = + '{"provider": "${providerApplePay.toSimpleString()}", "data": {}}'; + final dummyConfig = PaymentConfiguration.fromJsonString(payConfigString); setUpAll(() async { - _mobilePlatform = PayMethodChannel(); + mobilePlatform = PayMethodChannel(); }); group('Verify channel I/O for', () { @@ -43,7 +43,9 @@ void main() { }; setUp(() { - channel.setMockMethodCallHandler((MethodCall methodCall) async { + TestWidgetsFlutterBinding.ensureInitialized(); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { log.add(methodCall); final response = testResponses[methodCall.method]; if (response is Exception) { @@ -54,7 +56,7 @@ void main() { }); test('userCanPay', () async { - await _mobilePlatform.userCanPay(_dummyConfig); + await mobilePlatform.userCanPay(dummyConfig); expect( log, [isMethodCall('userCanPay', arguments: '{}')], @@ -62,7 +64,7 @@ void main() { }); test('showPaymentSelector', () async { - await _mobilePlatform.showPaymentSelector(_dummyConfig, []); + await mobilePlatform.showPaymentSelector(dummyConfig, []); expect( log, [ @@ -75,7 +77,8 @@ void main() { }); tearDown(() async { - channel.setMockMethodCallHandler(null); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, null); log.clear(); }); }); diff --git a/pay_platform_interface/test/payment_configuration_test.dart b/pay_platform_interface/test/payment_configuration_test.dart index 720147dd..39d95254 100644 --- a/pay_platform_interface/test/payment_configuration_test.dart +++ b/pay_platform_interface/test/payment_configuration_test.dart @@ -31,7 +31,8 @@ String _fixtureAsset(String name) { Future> _testProfileLoader( String paymentConfigurationAsset) async => - jsonDecode(_fixtureAsset(paymentConfigurationAsset)); + jsonDecode(_fixtureAsset(paymentConfigurationAsset)) + as Map; const PayProvider _providerGooglePay = PayProvider.google_pay; final String _payConfigString = @@ -67,7 +68,7 @@ void main() { expect(configParams['merchantInfo'].containsKey('softwareInfo'), isTrue); Map softwareInfo = - configParams['merchantInfo']['softwareInfo']; + configParams['merchantInfo']['softwareInfo'] as Map; expect(softwareInfo.containsKey('id'), isTrue); expect(softwareInfo.containsKey('version'), isTrue); });