Jonny Borges
Committed by GitHub

Merge pull request #579 from Grohden/chore/pipeline-analyzer

chore: add analyzer to PR check pipeline
@@ -20,8 +20,7 @@ jobs: @@ -20,8 +20,7 @@ jobs:
20 flutter-version: '1.20.2' 20 flutter-version: '1.20.2'
21 channel: 'stable' 21 channel: 'stable'
22 - run: flutter pub get 22 - run: flutter pub get
23 - # run static analys code  
24 - #- run: flutter analyze 23 + - run: flutter analyze
25 # run flutter widgets tests and unit tests 24 # run flutter widgets tests and unit tests
26 - run: flutter test --coverage 25 - run: flutter test --coverage
27 # Upload coverage reports to Codecov 26 # Upload coverage reports to Codecov
1 -include: package:effective_dart/analysis_options.yaml 1 +# Include option is buggy:
  2 +# https://github.com/flutter/flutter/issues/62591
  3 +# In case the include issue gets fixed, lines below INCLUDE_FIX
  4 +# can be removed
  5 +
  6 +# include: package:effective_dart/analysis_options.1.2.0.yaml
2 analyzer: 7 analyzer:
3 strong-mode: 8 strong-mode:
4 implicit-casts: false 9 implicit-casts: false
@@ -10,3 +15,71 @@ linter: @@ -10,3 +15,71 @@ linter:
10 # Desirable, but would be breaking changes: 15 # Desirable, but would be breaking changes:
11 avoid_positional_boolean_parameters: false 16 avoid_positional_boolean_parameters: false
12 constant_identifier_names: false 17 constant_identifier_names: false
  18 + include_file_not_found: false
  19 +
  20 + # INCLUDE_FIX (copy of effective dart 1.2.0)
  21 + # STYLE
  22 + camel_case_types: true
  23 + camel_case_extensions: true
  24 + library_names: true
  25 + file_names: true
  26 + library_prefixes: true
  27 + non_constant_identifier_names: true
  28 + directives_ordering: true
  29 + lines_longer_than_80_chars: true # avoid
  30 + curly_braces_in_flow_control_structures: true
  31 +
  32 + # DOCUMENTATION
  33 + slash_for_doc_comments: true
  34 + package_api_docs: true # prefer
  35 + #- comment_references # Unused because https://github.com/dart-lang/sdk/issues/36974
  36 +
  37 + # USAGE
  38 + implementation_imports: true
  39 + avoid_relative_lib_imports: true # prefer
  40 + prefer_relative_imports: true # prefer
  41 + prefer_adjacent_string_concatenation: true
  42 + prefer_interpolation_to_compose_strings: true # prefer
  43 + unnecessary_brace_in_string_interps: true # avoid
  44 + prefer_collection_literals: true
  45 + avoid_function_literals_in_foreach_calls: true # avoid
  46 + prefer_iterable_whereType: true
  47 + prefer_function_declarations_over_variables: true
  48 + unnecessary_lambdas: true
  49 + prefer_equal_for_default_values: true
  50 + avoid_init_to_null: true
  51 + unnecessary_getters_setters: true
  52 + #- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
  53 + #- prefer_expression_function_bodies # consider
  54 + unnecessary_this: true
  55 + prefer_initializing_formals: true
  56 + type_init_formals: true
  57 + empty_constructor_bodies: true
  58 + unnecessary_new: true
  59 + unnecessary_const: true
  60 + avoid_catches_without_on_clauses: true # avoid
  61 + avoid_catching_errors: true
  62 + use_rethrow_when_possible: true
  63 +
  64 + # DESIGN
  65 + use_to_and_as_if_applicable: true # prefer
  66 + one_member_abstracts: true # avoid
  67 + avoid_classes_with_only_static_members: true # avoid
  68 + prefer_mixin: true
  69 + prefer_final_fields: true # prefer
  70 + use_setters_to_change_properties: true
  71 + avoid_setters_without_getters: true
  72 + avoid_returning_null: true # avoid
  73 + avoid_returning_this: true # avoid
  74 + type_annotate_public_apis: true # prefer
  75 + #- prefer_typing_uninitialized_variables # consider
  76 + omit_local_variable_types: true # avoid
  77 + avoid_types_on_closure_parameters: true # avoid
  78 + avoid_return_types_on_setters: true # avoid
  79 + prefer_generic_function_type_aliases: true
  80 + avoid_private_typedef_functions: true # prefer
  81 + #- use_function_type_syntax_for_parameters # consider
  82 + hash_and_equals: true
  83 + avoid_equals_and_hash_code_on_mutable_classes: true # avoid
  84 + avoid_null_checks_in_equality_operators: true
  85 +
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 -import 'package:get_demo/routes/app_pages.dart'; 3 +
  4 +import 'routes/app_pages.dart';
4 import 'shared/logger/logger_utils.dart'; 5 import 'shared/logger/logger_utils.dart';
5 6
6 void main() { 7 void main() {
1 import 'package:dio/dio.dart'; 1 import 'package:dio/dio.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 -import 'package:get_demo/pages/home/domain/adapters/repository_adapter.dart';  
4 -import 'package:get_demo/pages/home/presentation/controllers/home_controller.dart'; 3 +
5 import '../data/home_repository.dart'; 4 import '../data/home_repository.dart';
  5 +import '../domain/adapters/repository_adapter.dart';
  6 +import '../presentation/controllers/home_controller.dart';
6 7
7 class HomeBinding extends Bindings { 8 class HomeBinding extends Bindings {
8 @override 9 @override
1 import 'package:dio/dio.dart'; 1 import 'package:dio/dio.dart';
2 -import 'package:get_demo/pages/home/domain/adapters/repository_adapter.dart';  
3 -import 'package:get_demo/pages/home/domain/entity/cases_model.dart'; 2 +
  3 +import '../domain/adapters/repository_adapter.dart';
  4 +import '../domain/entity/cases_model.dart';
4 5
5 class HomeRepository implements IHomeRepository { 6 class HomeRepository implements IHomeRepository {
6 HomeRepository({this.dio}); 7 HomeRepository({this.dio});
@@ -13,7 +14,7 @@ class HomeRepository implements IHomeRepository { @@ -13,7 +14,7 @@ class HomeRepository implements IHomeRepository {
13 final response = await dio.get("https://api.covid19api.com/summary"); 14 final response = await dio.get("https://api.covid19api.com/summary");
14 15
15 return CasesModel.fromJson(response.data as Map<String, dynamic>); 16 return CasesModel.fromJson(response.data as Map<String, dynamic>);
16 - } catch (e) { 17 + } on Exception catch (e) {
17 print(e.toString()); 18 print(e.toString());
18 return Future.error(e.toString()); 19 return Future.error(e.toString());
19 } 20 }
1 -import 'package:get_demo/pages/home/domain/entity/cases_model.dart'; 1 +import '../entity/cases_model.dart';
2 2
  3 +// ignore: one_member_abstracts
3 abstract class IHomeRepository { 4 abstract class IHomeRepository {
4 Future<CasesModel> getCases(); 5 Future<CasesModel> getCases();
5 } 6 }
1 import 'package:get/get.dart'; 1 import 'package:get/get.dart';
2 -import 'package:get_demo/pages/home/domain/adapters/repository_adapter.dart';  
3 -import 'package:get_demo/pages/home/domain/entity/cases_model.dart'; 2 +
  3 +import '../../domain/adapters/repository_adapter.dart';
  4 +import '../../domain/entity/cases_model.dart';
4 5
5 enum Status { loading, success, error } 6 enum Status { loading, success, error }
6 7
@@ -22,14 +23,16 @@ class HomeController extends GetxController { @@ -22,14 +23,16 @@ class HomeController extends GetxController {
22 23
23 /// fetch cases from Api 24 /// fetch cases from Api
24 Future<void> fetchDataFromApi() async { 25 Future<void> fetchDataFromApi() async {
25 - /// When the repository returns the value, change the status to success, and fill in "cases" 26 + /// When the repository returns the value, change the status to success,
  27 + /// and fill in "cases"
26 return homeRepository.getCases().then( 28 return homeRepository.getCases().then(
27 (data) { 29 (data) {
28 cases(data); 30 cases(data);
29 status(Status.success); 31 status(Status.success);
30 }, 32 },
31 33
32 - /// In case of error, print the error and change the status to Status.error 34 + /// In case of error, print the error and change the status
  35 + /// to Status.error
33 onError: (err) { 36 onError: (err) {
34 print("$err"); 37 print("$err");
35 return status(Status.error); 38 return status(Status.error);
1 import 'dart:ui'; 1 import 'dart:ui';
  2 +
2 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
3 import 'package:get/get.dart'; 4 import 'package:get/get.dart';
4 -import 'package:get_demo/pages/home/domain/entity/cases_model.dart'; 5 +
5 import '../controllers/home_controller.dart'; 6 import '../controllers/home_controller.dart';
6 7
7 class CountryView extends GetWidget<HomeController> { 8 class CountryView extends GetWidget<HomeController> {
@@ -30,7 +31,7 @@ class CountryView extends GetWidget<HomeController> { @@ -30,7 +31,7 @@ class CountryView extends GetWidget<HomeController> {
30 child: ListView.builder( 31 child: ListView.builder(
31 itemCount: controller.cases.value.countries.length, 32 itemCount: controller.cases.value.countries.length,
32 itemBuilder: (context, index) { 33 itemBuilder: (context, index) {
33 - Country country = controller.cases.value.countries[index]; 34 + final country = controller.cases.value.countries[index];
34 return ListTile( 35 return ListTile(
35 onTap: () { 36 onTap: () {
36 Get.toNamed('/details', arguments: country); 37 Get.toNamed('/details', arguments: country);
@@ -2,12 +2,13 @@ import 'dart:ui'; @@ -2,12 +2,13 @@ import 'dart:ui';
2 2
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
4 import 'package:get/get.dart'; 4 import 'package:get/get.dart';
5 -import 'package:get_demo/pages/home/domain/entity/cases_model.dart'; 5 +
  6 +import '../../domain/entity/cases_model.dart';
6 7
7 class DetailsView extends StatelessWidget { 8 class DetailsView extends StatelessWidget {
8 @override 9 @override
9 Widget build(BuildContext context) { 10 Widget build(BuildContext context) {
10 - Country country = Get.arguments as Country; 11 + final country = Get.arguments as Country;
11 return Container( 12 return Container(
12 decoration: BoxDecoration( 13 decoration: BoxDecoration(
13 image: DecorationImage( 14 image: DecorationImage(
@@ -2,7 +2,8 @@ import 'dart:ui'; @@ -2,7 +2,8 @@ import 'dart:ui';
2 2
3 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
4 import 'package:get/get.dart'; 4 import 'package:get/get.dart';
5 -import 'package:get_demo/pages/home/presentation/controllers/home_controller.dart'; 5 +
  6 +import '../controllers/home_controller.dart';
6 7
7 class HomeView extends GetView<HomeController> { 8 class HomeView extends GetView<HomeController> {
8 @override 9 @override
@@ -28,7 +29,7 @@ class HomeView extends GetView<HomeController> { @@ -28,7 +29,7 @@ class HomeView extends GetView<HomeController> {
28 body: Center( 29 body: Center(
29 child: Obx( 30 child: Obx(
30 () { 31 () {
31 - Status status = controller.status.value; 32 + final status = controller.status.value;
32 if (status == Status.loading) return CircularProgressIndicator(); 33 if (status == Status.loading) return CircularProgressIndicator();
33 if (status == Status.error) return Text('Error on connection :('); 34 if (status == Status.error) return Text('Error on connection :(');
34 return Column( 35 return Column(
1 import 'package:get/get.dart'; 1 import 'package:get/get.dart';
2 -import 'package:get_demo/pages/home/bindings/home_binding.dart';  
3 -import 'package:get_demo/pages/home/presentation/views/country_view.dart';  
4 -import 'package:get_demo/pages/home/presentation/views/details_view.dart';  
5 -import 'package:get_demo/pages/home/presentation/views/home_view.dart'; 2 +
  3 +import '../pages/home/bindings/home_binding.dart';
  4 +import '../pages/home/presentation/views/country_view.dart';
  5 +import '../pages/home/presentation/views/details_view.dart';
  6 +import '../pages/home/presentation/views/home_view.dart';
6 7
7 part 'app_routes.dart'; 8 part 'app_routes.dart';
8 9
  10 +// ignore: avoid_classes_with_only_static_members
9 class AppPages { 11 class AppPages {
10 static const INITIAL = Routes.HOME; 12 static const INITIAL = Routes.HOME;
11 13
1 class Logger { 1 class Logger {
2 // Sample of abstract logging function 2 // Sample of abstract logging function
3 static void write(String text, {bool isError = false}) { 3 static void write(String text, {bool isError = false}) {
4 - print('** ' + text + ' [' + isError.toString() + ']'); 4 + print('** $text [$isError]');
5 } 5 }
6 } 6 }
@@ -49,7 +49,7 @@ void main() { @@ -49,7 +49,7 @@ void main() {
49 binding.builder(); 49 binding.builder();
50 50
51 /// recover your controller 51 /// recover your controller
52 - HomeController controller = Get.find(); 52 + final controller = Get.find<HomeController>();
53 53
54 /// check if onInit was called 54 /// check if onInit was called
55 expect(controller.initialized, true); 55 expect(controller.initialized, true);
@@ -4,7 +4,8 @@ import 'dart:collection'; @@ -4,7 +4,8 @@ import 'dart:collection';
4 import '../rx_core/rx_interface.dart'; 4 import '../rx_core/rx_interface.dart';
5 5
6 6
7 -/// global object that registers against `GetX` and `Obx`, and allows the reactivity 7 +/// global object that registers against `GetX` and `Obx`, and allows the
  8 +/// reactivity
8 /// of those `Widgets` and Rx values. 9 /// of those `Widgets` and Rx values.
9 RxInterface getObs; 10 RxInterface getObs;
10 11
@@ -207,6 +208,9 @@ class RxBool extends _RxImpl<bool> { @@ -207,6 +208,9 @@ class RxBool extends _RxImpl<bool> {
207 208
208 /// Toggles the bool [value] between false and true. 209 /// Toggles the bool [value] between false and true.
209 /// A shortcut for `flag.value = !flag.value;` 210 /// A shortcut for `flag.value = !flag.value;`
  211 + /// FIXME: why return this? fluent interface is not
  212 + /// not really a dart thing since we have '..' operator
  213 + // ignore: avoid_returning_this
210 RxBool toggle() { 214 RxBool toggle() {
211 subject.add(_value = !_value); 215 subject.add(_value = !_value);
212 return this; 216 return this;
@@ -295,7 +299,8 @@ class RxInt extends _BaseRxNum<int> { @@ -295,7 +299,8 @@ class RxInt extends _BaseRxNum<int> {
295 } 299 }
296 300
297 301
298 -/// Foundation class used for custom `Types` outside the common native Dart types. 302 +/// Foundation class used for custom `Types` outside the common native Dart
  303 +/// types.
299 /// For example, any custom "Model" class, like User().obs will use `Rx` as 304 /// For example, any custom "Model" class, like User().obs will use `Rx` as
300 /// wrapper. 305 /// wrapper.
301 class Rx<T> extends _RxImpl<T> { 306 class Rx<T> extends _RxImpl<T> {
@@ -27,6 +27,7 @@ typedef GetStateUpdate = bool Function(); @@ -27,6 +27,7 @@ typedef GetStateUpdate = bool Function();
27 // TODO: check performance HIT for the extra method call. 27 // TODO: check performance HIT for the extra method call.
28 mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> { 28 mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> {
29 // To avoid the creation of an anonym function to be GC later. 29 // To avoid the creation of an anonym function to be GC later.
  30 + // ignore: prefer_function_declarations_over_variables
30 static final VoidCallback _stateCallback = () {}; 31 static final VoidCallback _stateCallback = () {};
31 32
32 /// Experimental method to replace setState((){}); 33 /// Experimental method to replace setState((){});
@@ -68,12 +69,11 @@ class GetxController extends DisposableInterface { @@ -68,12 +69,11 @@ class GetxController extends DisposableInterface {
68 // for (final rs in _updatersGroupIds[id]) rs(); 69 // for (final rs in _updatersGroupIds[id]) rs();
69 // } 70 // }
70 71
71 - ids.forEach((id) {  
72 -// _updatersIds[id]?.call(() {}); //<old>  
73 -// _updatersGroupIds[id]?.forEach((rs) => rs(() {})); //<old> 72 + for (final id in ids) {
74 _updatersIds[id]?.call(); 73 _updatersIds[id]?.call();
  74 + // ignore: avoid_function_literals_in_foreach_calls
75 _updatersGroupIds[id]?.forEach((rs) => rs()); 75 _updatersGroupIds[id]?.forEach((rs) => rs());
76 - }); 76 + }
77 } 77 }
78 } 78 }
79 79