From af2896b199ecc3cc5e1ed3000b009f65fc05c9cd Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Wed, 18 Aug 2021 06:51:10 -0700 Subject: [PATCH] [flutter_plugin_tools] Add a command to lint Android code (#4206) Adds a new `lint-android` command to run `gradlew lint` on Android plugins. Also standardizes the names of the Cirrus tasks that run all the build and platform-specific (i.e., not Dart unit test) tests for each platform, as they were getting unnecessarily long and complex in some cases. Fixes https://github.com/flutter/flutter/issues/87071 --- .cirrus.yml | 23 +- packages/android_alarm_manager/CHANGELOG.md | 1 + .../android/build.gradle | 2 + .../android/lint-baseline.xml | 59 +++ packages/android_intent/CHANGELOG.md | 1 + packages/android_intent/android/build.gradle | 1 + packages/battery/battery/CHANGELOG.md | 1 + packages/battery/battery/android/build.gradle | 1 + packages/camera/camera/CHANGELOG.md | 4 + packages/camera/camera/android/build.gradle | 2 + .../camera/camera/android/lint-baseline.xml | 114 +++++ .../connectivity/connectivity/CHANGELOG.md | 1 + .../connectivity/android/build.gradle | 1 + packages/device_info/device_info/CHANGELOG.md | 1 + .../device_info/android/build.gradle | 1 + packages/espresso/CHANGELOG.md | 4 + packages/espresso/android/build.gradle | 2 + packages/espresso/android/lint-baseline.xml | 389 ++++++++++++++++++ .../CHANGELOG.md | 4 + .../android/build.gradle | 1 + .../google_maps_flutter/android/build.gradle | 1 + .../google_sign_in/CHANGELOG.md | 4 + .../google_sign_in/android/build.gradle | 1 + .../image_picker/image_picker/CHANGELOG.md | 4 + .../image_picker/android/build.gradle | 1 + .../in_app_purchase_android/CHANGELOG.md | 8 +- .../android/build.gradle | 1 + packages/local_auth/CHANGELOG.md | 4 + packages/local_auth/android/build.gradle | 2 + packages/local_auth/android/lint-baseline.xml | 59 +++ packages/package_info/CHANGELOG.md | 1 + packages/package_info/android/build.gradle | 1 + .../path_provider/path_provider/CHANGELOG.md | 4 + .../path_provider/android/build.gradle | 1 + .../quick_actions/quick_actions/CHANGELOG.md | 4 + .../quick_actions/android/build.gradle | 1 + packages/sensors/CHANGELOG.md | 1 + packages/sensors/android/build.gradle | 1 + packages/share/CHANGELOG.md | 1 + packages/share/android/build.gradle | 1 + .../shared_preferences/CHANGELOG.md | 1 + .../shared_preferences/android/build.gradle | 2 + .../android/lint-baseline.xml | 81 ++++ .../url_launcher/url_launcher/CHANGELOG.md | 4 + .../url_launcher/android/build.gradle | 1 + .../video_player/video_player/CHANGELOG.md | 4 + .../video_player/android/build.gradle | 1 + .../webview_flutter/CHANGELOG.md | 4 + .../webview_flutter/android/build.gradle | 1 + .../wifi_info_flutter/CHANGELOG.md | 4 + .../wifi_info_flutter/android/build.gradle | 1 + script/tool/CHANGELOG.md | 1 + script/tool/lib/src/common/gradle.dart | 57 +++ script/tool/lib/src/common/xcode.dart | 2 +- .../lib/src/firebase_test_lab_command.dart | 46 +-- script/tool/lib/src/lint_android_command.dart | 61 +++ script/tool/lib/src/main.dart | 2 + script/tool/lib/src/native_test_command.dart | 29 +- script/tool/test/common/gradle_test.dart | 179 ++++++++ .../tool/test/lint_android_command_test.dart | 158 +++++++ 60 files changed, 1306 insertions(+), 47 deletions(-) create mode 100644 packages/android_alarm_manager/android/lint-baseline.xml create mode 100644 packages/camera/camera/android/lint-baseline.xml create mode 100644 packages/espresso/android/lint-baseline.xml create mode 100644 packages/local_auth/android/lint-baseline.xml create mode 100644 packages/shared_preferences/shared_preferences/android/lint-baseline.xml create mode 100644 script/tool/lib/src/common/gradle.dart create mode 100644 script/tool/lib/src/lint_android_command.dart create mode 100644 script/tool/test/common/gradle_test.dart create mode 100644 script/tool/test/lint_android_command_test.dart diff --git a/.cirrus.yml b/.cirrus.yml index ffdd71daebc4..d830a2a15913 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -119,7 +119,7 @@ task: setup_script: - flutter config --enable-linux-desktop << : *BUILD_ALL_PLUGINS_APP_TEMPLATE - - name: build-linux+drive-examples + - name: linux-build+platform-tests env: matrix: CHANNEL: "master" @@ -146,7 +146,7 @@ task: memory: 12G matrix: ### Android tasks ### - - name: build-apks+android-unit+firebase-test-lab + - name: android-build+platform-tests env: matrix: PLUGIN_SHARDING: "--shardIndex 0 --shardCount 4" @@ -165,6 +165,13 @@ task: - export CIRRUS_CHANGE_MESSAGE="" - export CIRRUS_COMMIT_MESSAGE="" - ./script/tool_runner.sh build-examples --apk + lint_script: + # Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they + # might include non-ASCII characters which makes Gradle crash. + # TODO(stuartmorgan): See https://github.com/flutter/flutter/issues/24935 + - export CIRRUS_CHANGE_MESSAGE="" + - export CIRRUS_COMMIT_MESSAGE="" + - ./script/tool_runner.sh lint-android # must come after build-examples native_unit_test_script: # Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they # might include non-ASCII characters which makes Gradle crash. @@ -186,8 +193,14 @@ task: - else - echo "This user does not have permission to run Firebase Test Lab tests." - fi + # Upload the full lint results to Cirrus to display in the results UI. + always: + android-lint_artifacts: + path: "**/reports/lint-results-debug.xml" + type: text/xml + format: android-lint ### Web tasks ### - - name: build-web+drive-examples + - name: web-build+platform-tests env: matrix: CHANNEL: "master" @@ -220,7 +233,7 @@ task: CHANNEL: "master" CHANNEL: "stable" << : *BUILD_ALL_PLUGINS_APP_TEMPLATE - - name: build-ipas+drive-examples + - name: ios-build+platform-tests env: PATH: $PATH:/usr/local/bin matrix: @@ -256,7 +269,7 @@ task: setup_script: - flutter config --enable-macos-desktop << : *BUILD_ALL_PLUGINS_APP_TEMPLATE - - name: build-macos+drive-examples + - name: macos-build+platform-tests env: matrix: CHANNEL: "master" diff --git a/packages/android_alarm_manager/CHANGELOG.md b/packages/android_alarm_manager/CHANGELOG.md index 71f47cede66e..d53b932e3f0f 100644 --- a/packages/android_alarm_manager/CHANGELOG.md +++ b/packages/android_alarm_manager/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove support for the V1 Android embedding. +* Updated Android lint settings. ## 2.0.2 diff --git a/packages/android_alarm_manager/android/build.gradle b/packages/android_alarm_manager/android/build.gradle index be741097f362..b173137786a9 100644 --- a/packages/android_alarm_manager/android/build.gradle +++ b/packages/android_alarm_manager/android/build.gradle @@ -38,6 +38,8 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' + baseline file("lint-baseline.xml") } diff --git a/packages/android_alarm_manager/android/lint-baseline.xml b/packages/android_alarm_manager/android/lint-baseline.xml new file mode 100644 index 000000000000..de588614fdb2 --- /dev/null +++ b/packages/android_alarm_manager/android/lint-baseline.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/android_intent/CHANGELOG.md b/packages/android_intent/CHANGELOG.md index 71428c53cea8..82cd5db3e4e4 100644 --- a/packages/android_intent/CHANGELOG.md +++ b/packages/android_intent/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove references to the V1 Android embedding. +* Updated Android lint settings. ## 2.0.2 diff --git a/packages/android_intent/android/build.gradle b/packages/android_intent/android/build.gradle index b0238b7db4f3..e8b9f3810146 100644 --- a/packages/android_intent/android/build.gradle +++ b/packages/android_intent/android/build.gradle @@ -35,6 +35,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/battery/battery/CHANGELOG.md b/packages/battery/battery/CHANGELOG.md index 8590e646564e..ddc912d2ba2a 100644 --- a/packages/battery/battery/CHANGELOG.md +++ b/packages/battery/battery/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove references to the Android v1 embedding. +* Updated Android lint settings. ## 2.0.3 diff --git a/packages/battery/battery/android/build.gradle b/packages/battery/battery/android/build.gradle index 1e484897c2ad..14f503813f7e 100644 --- a/packages/battery/battery/android/build.gradle +++ b/packages/battery/battery/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index d455ddb2fad1..694898092d7a 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 0.8.1+7 * Fix device orientation sometimes not affecting the camera preview orientation. diff --git a/packages/camera/camera/android/build.gradle b/packages/camera/camera/android/build.gradle index 6ceed97c9a17..9bbafb653ef8 100644 --- a/packages/camera/camera/android/build.gradle +++ b/packages/camera/camera/android/build.gradle @@ -35,6 +35,8 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' + baseline file("lint-baseline.xml") } compileOptions { sourceCompatibility = '1.8' diff --git a/packages/camera/camera/android/lint-baseline.xml b/packages/camera/camera/android/lint-baseline.xml new file mode 100644 index 000000000000..4ddaafa87988 --- /dev/null +++ b/packages/camera/camera/android/lint-baseline.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/connectivity/connectivity/CHANGELOG.md b/packages/connectivity/connectivity/CHANGELOG.md index 58047482fcb7..f5489692bee9 100644 --- a/packages/connectivity/connectivity/CHANGELOG.md +++ b/packages/connectivity/connectivity/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove references to the Android V1 embedding. +* Updated Android lint settings. ## 3.0.6 diff --git a/packages/connectivity/connectivity/android/build.gradle b/packages/connectivity/connectivity/android/build.gradle index 53a390bd74f0..983f29b142de 100644 --- a/packages/connectivity/connectivity/android/build.gradle +++ b/packages/connectivity/connectivity/android/build.gradle @@ -35,6 +35,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/device_info/device_info/CHANGELOG.md b/packages/device_info/device_info/CHANGELOG.md index 669423cc4efb..97349d450cf1 100644 --- a/packages/device_info/device_info/CHANGELOG.md +++ b/packages/device_info/device_info/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove references to the Android V1 embedding. +* Updated Android lint settings. ## 2.0.2 diff --git a/packages/device_info/device_info/android/build.gradle b/packages/device_info/device_info/android/build.gradle index 51ec2a7fb567..ed89da419d4a 100644 --- a/packages/device_info/device_info/android/build.gradle +++ b/packages/device_info/device_info/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/espresso/CHANGELOG.md b/packages/espresso/CHANGELOG.md index 10e5ae59f71a..e00ea7065ce0 100644 --- a/packages/espresso/CHANGELOG.md +++ b/packages/espresso/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 0.1.0+3 * Remove references to the Android v1 embedding. diff --git a/packages/espresso/android/build.gradle b/packages/espresso/android/build.gradle index 8cd54811afa0..da0cd2ebfee8 100644 --- a/packages/espresso/android/build.gradle +++ b/packages/espresso/android/build.gradle @@ -30,6 +30,8 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' + baseline file("lint-baseline.xml") } diff --git a/packages/espresso/android/lint-baseline.xml b/packages/espresso/android/lint-baseline.xml new file mode 100644 index 000000000000..19b349f044bf --- /dev/null +++ b/packages/espresso/android/lint-baseline.xml @@ -0,0 +1,389 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/flutter_plugin_android_lifecycle/CHANGELOG.md b/packages/flutter_plugin_android_lifecycle/CHANGELOG.md index 6a05ed01e2de..7e567d8cce5c 100644 --- a/packages/flutter_plugin_android_lifecycle/CHANGELOG.md +++ b/packages/flutter_plugin_android_lifecycle/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 2.0.3 * Remove references to the Android V1 embedding. diff --git a/packages/flutter_plugin_android_lifecycle/android/build.gradle b/packages/flutter_plugin_android_lifecycle/android/build.gradle index ba3a54b235e6..5a584b4e366f 100644 --- a/packages/flutter_plugin_android_lifecycle/android/build.gradle +++ b/packages/flutter_plugin_android_lifecycle/android/build.gradle @@ -31,6 +31,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } dependencies { diff --git a/packages/google_maps_flutter/google_maps_flutter/android/build.gradle b/packages/google_maps_flutter/google_maps_flutter/android/build.gradle index 6c5ea76ae61e..e3cf6ffe8818 100644 --- a/packages/google_maps_flutter/google_maps_flutter/android/build.gradle +++ b/packages/google_maps_flutter/google_maps_flutter/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } dependencies { diff --git a/packages/google_sign_in/google_sign_in/CHANGELOG.md b/packages/google_sign_in/google_sign_in/CHANGELOG.md index e4207de117fa..8ac07ae1793b 100644 --- a/packages/google_sign_in/google_sign_in/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 5.0.7 * Mark iOS arm64 simulators as unsupported. diff --git a/packages/google_sign_in/google_sign_in/android/build.gradle b/packages/google_sign_in/google_sign_in/android/build.gradle index 7d1825defa84..ea98b315f147 100644 --- a/packages/google_sign_in/google_sign_in/android/build.gradle +++ b/packages/google_sign_in/google_sign_in/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md index 9d89389cb105..4f21ed3cc398 100644 --- a/packages/image_picker/image_picker/CHANGELOG.md +++ b/packages/image_picker/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 0.8.3+2 * Fix using Camera as image source on Android 11+ diff --git a/packages/image_picker/image_picker/android/build.gradle b/packages/image_picker/image_picker/android/build.gradle index 607b3c1523a1..1e6439e6a4eb 100755 --- a/packages/image_picker/image_picker/android/build.gradle +++ b/packages/image_picker/image_picker/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } dependencies { implementation 'androidx.core:core:1.0.2' diff --git a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md index d67d1efd61b5..60dae1be6d86 100644 --- a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md @@ -1,8 +1,12 @@ -# 0.1.4+4 +## NEXT + +* Updated Android lint settings. + +## 0.1.4+4 * Removed dependency on the `test` package. -# 0.1.4+3 +## 0.1.4+3 - Updated installation instructions in README. diff --git a/packages/in_app_purchase/in_app_purchase_android/android/build.gradle b/packages/in_app_purchase/in_app_purchase_android/android/build.gradle index 349f9eeb734c..656f7c34bf7a 100644 --- a/packages/in_app_purchase/in_app_purchase_android/android/build.gradle +++ b/packages/in_app_purchase/in_app_purchase_android/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 diff --git a/packages/local_auth/CHANGELOG.md b/packages/local_auth/CHANGELOG.md index c33fa7778b94..c0d04fb5688a 100644 --- a/packages/local_auth/CHANGELOG.md +++ b/packages/local_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 1.1.7 * Remove references to the Android V1 embedding. diff --git a/packages/local_auth/android/build.gradle b/packages/local_auth/android/build.gradle index 4fcb77cf6c98..dc282e78ced0 100644 --- a/packages/local_auth/android/build.gradle +++ b/packages/local_auth/android/build.gradle @@ -30,6 +30,8 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' + baseline file("lint-baseline.xml") } diff --git a/packages/local_auth/android/lint-baseline.xml b/packages/local_auth/android/lint-baseline.xml new file mode 100644 index 000000000000..e89eaadb3e6d --- /dev/null +++ b/packages/local_auth/android/lint-baseline.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/package_info/CHANGELOG.md b/packages/package_info/CHANGELOG.md index 2ec20b3fe775..0fe91175cf6b 100644 --- a/packages/package_info/CHANGELOG.md +++ b/packages/package_info/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove references to the Android v1 embedding. +* Updated Android lint settings. ## 2.0.2 diff --git a/packages/package_info/android/build.gradle b/packages/package_info/android/build.gradle index d2846f260556..e21d911ff490 100644 --- a/packages/package_info/android/build.gradle +++ b/packages/package_info/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/path_provider/path_provider/CHANGELOG.md b/packages/path_provider/path_provider/CHANGELOG.md index 5e08c520dcd7..ba7bb3dc7ada 100644 --- a/packages/path_provider/path_provider/CHANGELOG.md +++ b/packages/path_provider/path_provider/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 2.0.3 * Add iOS unit test target. diff --git a/packages/path_provider/path_provider/android/build.gradle b/packages/path_provider/path_provider/android/build.gradle index db2c79c15796..3458140bd0eb 100644 --- a/packages/path_provider/path_provider/android/build.gradle +++ b/packages/path_provider/path_provider/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } android { compileOptions { diff --git a/packages/quick_actions/quick_actions/CHANGELOG.md b/packages/quick_actions/quick_actions/CHANGELOG.md index 5d040f4fd74e..9087c2807061 100644 --- a/packages/quick_actions/quick_actions/CHANGELOG.md +++ b/packages/quick_actions/quick_actions/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 0.6.0+5 * Support only calling initialize once. diff --git a/packages/quick_actions/quick_actions/android/build.gradle b/packages/quick_actions/quick_actions/android/build.gradle index 0bce642f3e60..ec3f84eab4cf 100644 --- a/packages/quick_actions/quick_actions/android/build.gradle +++ b/packages/quick_actions/quick_actions/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } dependencies { diff --git a/packages/sensors/CHANGELOG.md b/packages/sensors/CHANGELOG.md index 5ac0943333fa..acea470855fb 100644 --- a/packages/sensors/CHANGELOG.md +++ b/packages/sensors/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove references to the Android V1 embedding. +* Updated Android lint settings. ## 2.0.3 diff --git a/packages/sensors/android/build.gradle b/packages/sensors/android/build.gradle index a16ebd2ee459..7e1087764dee 100644 --- a/packages/sensors/android/build.gradle +++ b/packages/sensors/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/share/CHANGELOG.md b/packages/share/CHANGELOG.md index 9074f59f05b7..c9a468d925a7 100644 --- a/packages/share/CHANGELOG.md +++ b/packages/share/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Remove references to the Android V1 embedding. +* Updated Android lint settings. ## 2.0.4 diff --git a/packages/share/android/build.gradle b/packages/share/android/build.gradle index 1b95bf592fb6..b2ea363a3e11 100644 --- a/packages/share/android/build.gradle +++ b/packages/share/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } dependencies { diff --git a/packages/shared_preferences/shared_preferences/CHANGELOG.md b/packages/shared_preferences/shared_preferences/CHANGELOG.md index 3476f4eff3f0..48abf9ad4045 100644 --- a/packages/shared_preferences/shared_preferences/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Add iOS unit test target. +* Updated Android lint settings. ## 2.0.6 diff --git a/packages/shared_preferences/shared_preferences/android/build.gradle b/packages/shared_preferences/shared_preferences/android/build.gradle index 6a66eba508fb..9284f1c36143 100644 --- a/packages/shared_preferences/shared_preferences/android/build.gradle +++ b/packages/shared_preferences/shared_preferences/android/build.gradle @@ -38,6 +38,8 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' + baseline file("lint-baseline.xml") } dependencies { testImplementation 'junit:junit:4.12' diff --git a/packages/shared_preferences/shared_preferences/android/lint-baseline.xml b/packages/shared_preferences/shared_preferences/android/lint-baseline.xml new file mode 100644 index 000000000000..6b2f35f5a151 --- /dev/null +++ b/packages/shared_preferences/shared_preferences/android/lint-baseline.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/url_launcher/url_launcher/CHANGELOG.md b/packages/url_launcher/url_launcher/CHANGELOG.md index dc67a2142ec2..237f0b139475 100644 --- a/packages/url_launcher/url_launcher/CHANGELOG.md +++ b/packages/url_launcher/url_launcher/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 6.0.10 * Remove references to the Android v1 embedding. diff --git a/packages/url_launcher/url_launcher/android/build.gradle b/packages/url_launcher/url_launcher/android/build.gradle index 5dd7e773a1ca..d374d40534c3 100644 --- a/packages/url_launcher/url_launcher/android/build.gradle +++ b/packages/url_launcher/url_launcher/android/build.gradle @@ -30,6 +30,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index f2029622f0ee..f07bb5f66f8c 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 2.1.14 * Removed dependency on the `flutter_test` package. diff --git a/packages/video_player/video_player/android/build.gradle b/packages/video_player/video_player/android/build.gradle index f2f18bff9798..9d9984439370 100644 --- a/packages/video_player/video_player/android/build.gradle +++ b/packages/video_player/video_player/android/build.gradle @@ -35,6 +35,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } android { compileOptions { diff --git a/packages/webview_flutter/webview_flutter/CHANGELOG.md b/packages/webview_flutter/webview_flutter/CHANGELOG.md index df7d9cb87457..361bfd24f3af 100644 --- a/packages/webview_flutter/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 2.0.12 * Improved the documentation on using the different Android Platform View modes. diff --git a/packages/webview_flutter/webview_flutter/android/build.gradle b/packages/webview_flutter/webview_flutter/android/build.gradle index cd1b4188a1eb..4a164317c60f 100644 --- a/packages/webview_flutter/webview_flutter/android/build.gradle +++ b/packages/webview_flutter/webview_flutter/android/build.gradle @@ -31,6 +31,7 @@ android { lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } dependencies { diff --git a/packages/wifi_info_flutter/wifi_info_flutter/CHANGELOG.md b/packages/wifi_info_flutter/wifi_info_flutter/CHANGELOG.md index 925745faa22a..86f3f67af103 100644 --- a/packages/wifi_info_flutter/wifi_info_flutter/CHANGELOG.md +++ b/packages/wifi_info_flutter/wifi_info_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updated Android lint settings. + ## 2.0.2 * Update README to point to Plus Plugins version. diff --git a/packages/wifi_info_flutter/wifi_info_flutter/android/build.gradle b/packages/wifi_info_flutter/wifi_info_flutter/android/build.gradle index 2b5a8a7fc209..661ee82da4d0 100644 --- a/packages/wifi_info_flutter/wifi_info_flutter/android/build.gradle +++ b/packages/wifi_info_flutter/wifi_info_flutter/android/build.gradle @@ -29,6 +29,7 @@ android { } lintOptions { disable 'InvalidPackage' + disable 'GradleDependency' } diff --git a/script/tool/CHANGELOG.md b/script/tool/CHANGELOG.md index 267019fe7359..87917d63d3fc 100644 --- a/script/tool/CHANGELOG.md +++ b/script/tool/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT - Added Android native integration test support to `native-test`. +- Added a new `android-lint` command to lint Android plugin native code. ## 0.5.0 diff --git a/script/tool/lib/src/common/gradle.dart b/script/tool/lib/src/common/gradle.dart new file mode 100644 index 000000000000..e7214bf29714 --- /dev/null +++ b/script/tool/lib/src/common/gradle.dart @@ -0,0 +1,57 @@ +// 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:file/file.dart'; +import 'package:platform/platform.dart'; + +import 'process_runner.dart'; + +const String _gradleWrapperWindows = 'gradlew.bat'; +const String _gradleWrapperNonWindows = 'gradlew'; + +/// A utility class for interacting with Gradle projects. +class GradleProject { + /// Creates an instance that runs commands for [project] with the given + /// [processRunner]. + /// + /// If [log] is true, commands run by this instance will long various status + /// messages. + GradleProject( + this.flutterProject, { + this.processRunner = const ProcessRunner(), + this.platform = const LocalPlatform(), + }); + + /// The directory of a Flutter project to run Gradle commands in. + final Directory flutterProject; + + /// The [ProcessRunner] used to run commands. Overridable for testing. + final ProcessRunner processRunner; + + /// The platform that commands are being run on. + final Platform platform; + + /// The project's 'android' directory. + Directory get androidDirectory => flutterProject.childDirectory('android'); + + /// The path to the Gradle wrapper file for the project. + File get gradleWrapper => androidDirectory.childFile( + platform.isWindows ? _gradleWrapperWindows : _gradleWrapperNonWindows); + + /// Whether or not the project is ready to have Gradle commands run on it + /// (i.e., whether the `flutter` tool has generated the necessary files). + bool isConfigured() => gradleWrapper.existsSync(); + + /// Runs a `gradlew` command with the given parameters. + Future runCommand( + String target, { + List arguments = const [], + }) { + return processRunner.runAndStream( + gradleWrapper.path, + [target, ...arguments], + workingDir: androidDirectory, + ); + } +} diff --git a/script/tool/lib/src/common/xcode.dart b/script/tool/lib/src/common/xcode.dart index d6bbae419eda..83f681bcb492 100644 --- a/script/tool/lib/src/common/xcode.dart +++ b/script/tool/lib/src/common/xcode.dart @@ -15,7 +15,7 @@ const String _xcRunCommand = 'xcrun'; /// A utility class for interacting with the installed version of Xcode. class Xcode { - /// Creates an instance that runs commends with the given [processRunner]. + /// Creates an instance that runs commands with the given [processRunner]. /// /// If [log] is true, commands run by this instance will long various status /// messages. diff --git a/script/tool/lib/src/firebase_test_lab_command.dart b/script/tool/lib/src/firebase_test_lab_command.dart index 8459f6c70153..fd2de97be4b3 100644 --- a/script/tool/lib/src/firebase_test_lab_command.dart +++ b/script/tool/lib/src/firebase_test_lab_command.dart @@ -10,6 +10,7 @@ import 'package:platform/platform.dart'; import 'package:uuid/uuid.dart'; import 'common/core.dart'; +import 'common/gradle.dart'; import 'common/package_looping_command.dart'; import 'common/process_runner.dart'; @@ -74,8 +75,6 @@ class FirebaseTestLabCommand extends PackageLoopingCommand { 'Runs tests in test_instrumentation folder using the ' 'instrumentation_test package.'; - static const String _gradleWrapper = 'gradlew'; - bool _firebaseProjectConfigured = false; Future _configureFirebaseProject() async { @@ -138,13 +137,15 @@ class FirebaseTestLabCommand extends PackageLoopingCommand { } // Ensures that gradle wrapper exists - if (!await _ensureGradleWrapperExists(androidDirectory)) { + final GradleProject project = GradleProject(exampleDirectory, + processRunner: processRunner, platform: platform); + if (!await _ensureGradleWrapperExists(project)) { return PackageResult.fail(['Unable to build example apk']); } await _configureFirebaseProject(); - if (!await _runGradle(androidDirectory, 'app:assembleAndroidTest')) { + if (!await _runGradle(project, 'app:assembleAndroidTest')) { return PackageResult.fail(['Unable to assemble androidTest']); } @@ -156,8 +157,7 @@ class FirebaseTestLabCommand extends PackageLoopingCommand { for (final File test in _findIntegrationTestFiles(package)) { final String testName = getRelativePosixPath(test, from: package); print('Testing $testName...'); - if (!await _runGradle(androidDirectory, 'app:assembleDebug', - testFile: test)) { + if (!await _runGradle(project, 'app:assembleDebug', testFile: test)) { printError('Could not build $testName'); errors.add('$testName failed to build'); continue; @@ -204,12 +204,12 @@ class FirebaseTestLabCommand extends PackageLoopingCommand { : PackageResult.fail(errors); } - /// Checks that 'gradlew' exists in [androidDirectory], and if not runs a + /// Checks that Gradle has been configured for [project], and if not runs a /// Flutter build to generate it. /// /// Returns true if either gradlew was already present, or the build succeeds. - Future _ensureGradleWrapperExists(Directory androidDirectory) async { - if (!androidDirectory.childFile(_gradleWrapper).existsSync()) { + Future _ensureGradleWrapperExists(GradleProject project) async { + if (!project.isConfigured()) { print('Running flutter build apk...'); final String experiment = getStringArg(kEnableExperiment); final int exitCode = await processRunner.runAndStream( @@ -219,7 +219,7 @@ class FirebaseTestLabCommand extends PackageLoopingCommand { 'apk', if (experiment.isNotEmpty) '--enable-experiment=$experiment', ], - workingDir: androidDirectory); + workingDir: project.androidDirectory); if (exitCode != 0) { return false; @@ -228,15 +228,15 @@ class FirebaseTestLabCommand extends PackageLoopingCommand { return true; } - /// Builds [target] using 'gradlew' in the given [directory]. Assumes - /// 'gradlew' already exists. + /// Builds [target] using Gradle in the given [project]. Assumes Gradle is + /// already configured. /// /// [testFile] optionally does the Flutter build with the given test file as /// the build target. /// /// Returns true if the command succeeds. Future _runGradle( - Directory directory, + GradleProject project, String target, { File? testFile, }) async { @@ -245,17 +245,15 @@ class FirebaseTestLabCommand extends PackageLoopingCommand { ? Uri.encodeComponent('--enable-experiment=$experiment') : null; - final int exitCode = await processRunner.runAndStream( - directory.childFile(_gradleWrapper).path, - [ - target, - '-Pverbose=true', - if (testFile != null) '-Ptarget=${testFile.path}', - if (extraOptions != null) '-Pextra-front-end-options=$extraOptions', - if (extraOptions != null) - '-Pextra-gen-snapshot-options=$extraOptions', - ], - workingDir: directory); + final int exitCode = await project.runCommand( + target, + arguments: [ + '-Pverbose=true', + if (testFile != null) '-Ptarget=${testFile.path}', + if (extraOptions != null) '-Pextra-front-end-options=$extraOptions', + if (extraOptions != null) '-Pextra-gen-snapshot-options=$extraOptions', + ], + ); if (exitCode != 0) { return false; diff --git a/script/tool/lib/src/lint_android_command.dart b/script/tool/lib/src/lint_android_command.dart new file mode 100644 index 000000000000..be6c6ed32415 --- /dev/null +++ b/script/tool/lib/src/lint_android_command.dart @@ -0,0 +1,61 @@ +// 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:file/file.dart'; +import 'package:flutter_plugin_tools/src/common/plugin_utils.dart'; +import 'package:platform/platform.dart'; + +import 'common/core.dart'; +import 'common/gradle.dart'; +import 'common/package_looping_command.dart'; +import 'common/process_runner.dart'; + +/// Lint the CocoaPod podspecs and run unit tests. +/// +/// See https://guides.cocoapods.org/terminal/commands.html#pod_lib_lint. +class LintAndroidCommand extends PackageLoopingCommand { + /// Creates an instance of the linter command. + LintAndroidCommand( + Directory packagesDir, { + ProcessRunner processRunner = const ProcessRunner(), + Platform platform = const LocalPlatform(), + }) : super(packagesDir, processRunner: processRunner, platform: platform); + + @override + final String name = 'lint-android'; + + @override + final String description = 'Runs "gradlew lint" on Android plugins.\n\n' + 'Requires the example to have been build at least once before running.'; + + @override + Future runForPackage(Directory package) async { + if (!pluginSupportsPlatform(kPlatformAndroid, package, + requiredMode: PlatformSupport.inline)) { + return PackageResult.skip( + 'Plugin does not have an Android implemenatation.'); + } + + final Directory exampleDirectory = package.childDirectory('example'); + final GradleProject project = GradleProject(exampleDirectory, + processRunner: processRunner, platform: platform); + + if (!project.isConfigured()) { + return PackageResult.fail(['Build example before linting']); + } + + final String packageName = package.basename; + + // Only lint one build mode to avoid extra work. + // Only lint the plugin project itself, to avoid failing due to errors in + // dependencies. + // + // TODO(stuartmorgan): Consider adding an XML parser to read and summarize + // all results. Currently, only the first three errors will be shown inline, + // and the rest have to be checked via the CI-uploaded artifact. + final int exitCode = await project.runCommand('$packageName:lintDebug'); + + return exitCode == 0 ? PackageResult.success() : PackageResult.fail(); + } +} diff --git a/script/tool/lib/src/main.dart b/script/tool/lib/src/main.dart index 6001c5df7f0a..e70cba24cc5e 100644 --- a/script/tool/lib/src/main.dart +++ b/script/tool/lib/src/main.dart @@ -16,6 +16,7 @@ import 'drive_examples_command.dart'; import 'firebase_test_lab_command.dart'; import 'format_command.dart'; import 'license_check_command.dart'; +import 'lint_android_command.dart'; import 'lint_podspecs_command.dart'; import 'list_command.dart'; import 'native_test_command.dart'; @@ -51,6 +52,7 @@ void main(List args) { ..addCommand(FirebaseTestLabCommand(packagesDir)) ..addCommand(FormatCommand(packagesDir)) ..addCommand(LicenseCheckCommand(packagesDir)) + ..addCommand(LintAndroidCommand(packagesDir)) ..addCommand(LintPodspecsCommand(packagesDir)) ..addCommand(ListCommand(packagesDir)) ..addCommand(NativeTestCommand(packagesDir)) diff --git a/script/tool/lib/src/native_test_command.dart b/script/tool/lib/src/native_test_command.dart index 9fc6a2912ccc..0bd2ab45f634 100644 --- a/script/tool/lib/src/native_test_command.dart +++ b/script/tool/lib/src/native_test_command.dart @@ -6,6 +6,7 @@ import 'package:file/file.dart'; import 'package:platform/platform.dart'; import 'common/core.dart'; +import 'common/gradle.dart'; import 'common/package_looping_command.dart'; import 'common/plugin_utils.dart'; import 'common/process_runner.dart'; @@ -47,8 +48,6 @@ class NativeTestCommand extends PackageLoopingCommand { help: 'Runs native integration (UI) tests', defaultsTo: true); } - static const String _gradleWrapper = 'gradlew'; - // The device destination flags for iOS tests. List _iosDestinationFlags = []; @@ -243,9 +242,12 @@ this command. final String exampleName = getPackageDescription(example); _printRunningExampleTestsMessage(example, 'Android'); - final Directory androidDirectory = example.childDirectory('android'); - final File gradleFile = androidDirectory.childFile(_gradleWrapper); - if (!gradleFile.existsSync()) { + final GradleProject project = GradleProject( + example, + processRunner: processRunner, + platform: platform, + ); + if (!project.isConfigured()) { printError('ERROR: Run "flutter build apk" on $exampleName, or run ' 'this tool\'s "build-examples --apk" command, ' 'before executing tests.'); @@ -256,9 +258,7 @@ this command. if (runUnitTests) { print('Running unit tests...'); - final int exitCode = await processRunner.runAndStream( - gradleFile.path, ['testDebugUnitTest'], - workingDir: androidDirectory); + final int exitCode = await project.runCommand('testDebugUnitTest'); if (exitCode != 0) { printError('$exampleName unit tests failed.'); failed = true; @@ -275,13 +275,12 @@ this command. 'notAnnotation=io.flutter.plugins.DartIntegrationTest'; print('Running integration tests...'); - final int exitCode = await processRunner.runAndStream( - gradleFile.path, - [ - 'app:connectedAndroidTest', - '-Pandroid.testInstrumentationRunnerArguments.$filter', - ], - workingDir: androidDirectory); + final int exitCode = await project.runCommand( + 'app:connectedAndroidTest', + arguments: [ + '-Pandroid.testInstrumentationRunnerArguments.$filter', + ], + ); if (exitCode != 0) { printError('$exampleName integration tests failed.'); failed = true; diff --git a/script/tool/test/common/gradle_test.dart b/script/tool/test/common/gradle_test.dart new file mode 100644 index 000000000000..c24887d3d469 --- /dev/null +++ b/script/tool/test/common/gradle_test.dart @@ -0,0 +1,179 @@ +// 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:io' as io; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:flutter_plugin_tools/src/common/gradle.dart'; +import 'package:test/test.dart'; + +import '../mocks.dart'; +import '../util.dart'; + +void main() { + late FileSystem fileSystem; + late RecordingProcessRunner processRunner; + + setUp(() { + fileSystem = MemoryFileSystem(); + processRunner = RecordingProcessRunner(); + }); + + group('isConfigured', () { + test('reports true when configured on Windows', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/gradlew.bat']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isWindows: true), + ); + + expect(project.isConfigured(), true); + }); + + test('reports true when configured on non-Windows', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/gradlew']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isMacOS: true), + ); + + expect(project.isConfigured(), true); + }); + + test('reports false when not configured on Windows', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/foo']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isWindows: true), + ); + + expect(project.isConfigured(), false); + }); + + test('reports true when configured on non-Windows', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/foo']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isMacOS: true), + ); + + expect(project.isConfigured(), false); + }); + }); + + group('runXcodeBuild', () { + test('runs without arguments', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/gradlew']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isMacOS: true), + ); + + final int exitCode = await project.runCommand('foo'); + + expect(exitCode, 0); + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + plugin.childDirectory('android').childFile('gradlew').path, + const [ + 'foo', + ], + plugin.childDirectory('android').path), + ])); + }); + + test('runs with arguments', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/gradlew']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isMacOS: true), + ); + + final int exitCode = await project.runCommand( + 'foo', + arguments: ['--bar', '--baz'], + ); + + expect(exitCode, 0); + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + plugin.childDirectory('android').childFile('gradlew').path, + const [ + 'foo', + '--bar', + '--baz', + ], + plugin.childDirectory('android').path), + ])); + }); + + test('runs with the correct wrapper on Windows', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/gradlew.bat']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isWindows: true), + ); + + final int exitCode = await project.runCommand('foo'); + + expect(exitCode, 0); + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + plugin.childDirectory('android').childFile('gradlew.bat').path, + const [ + 'foo', + ], + plugin.childDirectory('android').path), + ])); + }); + + test('returns error codes', () async { + final Directory plugin = createFakePlugin( + 'plugin', fileSystem.directory('/'), + extraFiles: ['android/gradlew.bat']); + final GradleProject project = GradleProject( + plugin, + processRunner: processRunner, + platform: MockPlatform(isWindows: true), + ); + + processRunner.mockProcessesForExecutable[project.gradleWrapper.path] = + [ + MockProcess.failing(), + ]; + + final int exitCode = await project.runCommand('foo'); + + expect(exitCode, 1); + }); + }); +} diff --git a/script/tool/test/lint_android_command_test.dart b/script/tool/test/lint_android_command_test.dart new file mode 100644 index 000000000000..05ead220c15b --- /dev/null +++ b/script/tool/test/lint_android_command_test.dart @@ -0,0 +1,158 @@ +// 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:io' as io; + +import 'package:args/command_runner.dart'; +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:flutter_plugin_tools/src/common/core.dart'; +import 'package:flutter_plugin_tools/src/common/plugin_utils.dart'; +import 'package:flutter_plugin_tools/src/lint_android_command.dart'; +import 'package:test/test.dart'; + +import 'mocks.dart'; +import 'util.dart'; + +void main() { + group('$LintAndroidCommand', () { + FileSystem fileSystem; + late Directory packagesDir; + late CommandRunner runner; + late MockPlatform mockPlatform; + late RecordingProcessRunner processRunner; + + setUp(() { + fileSystem = MemoryFileSystem(style: FileSystemStyle.posix); + packagesDir = createPackagesDirectory(fileSystem: fileSystem); + mockPlatform = MockPlatform(); + processRunner = RecordingProcessRunner(); + final LintAndroidCommand command = LintAndroidCommand( + packagesDir, + processRunner: processRunner, + platform: mockPlatform, + ); + + runner = CommandRunner( + 'lint_android_test', 'Test for $LintAndroidCommand'); + runner.addCommand(command); + }); + + test('runs gradle lint', () async { + final Directory pluginDir = + createFakePlugin('plugin1', packagesDir, extraFiles: [ + 'example/android/gradlew', + ], platformSupport: { + kPlatformAndroid: PlatformSupport.inline + }); + + final Directory androidDir = + pluginDir.childDirectory('example').childDirectory('android'); + + final List output = + await runCapturingPrint(runner, ['lint-android']); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + androidDir.childFile('gradlew').path, + const ['plugin1:lintDebug'], + androidDir.path, + ), + ]), + ); + + expect( + output, + containsAllInOrder([ + contains('Running for plugin1'), + contains('No issues found!'), + ])); + }); + + test('fails if gradlew is missing', () async { + createFakePlugin('plugin1', packagesDir, + platformSupport: { + kPlatformAndroid: PlatformSupport.inline + }); + + Error? commandError; + final List output = await runCapturingPrint( + runner, ['lint-android'], errorHandler: (Error e) { + commandError = e; + }); + + expect(commandError, isA()); + expect( + output, + containsAllInOrder( + [ + contains('Build example before linting'), + ], + )); + }); + + test('fails if linting finds issues', () async { + createFakePlugin('plugin1', packagesDir, + platformSupport: { + kPlatformAndroid: PlatformSupport.inline + }); + + processRunner.mockProcessesForExecutable['gradlew'] = [ + MockProcess.failing(), + ]; + + Error? commandError; + final List output = await runCapturingPrint( + runner, ['lint-android'], errorHandler: (Error e) { + commandError = e; + }); + + expect(commandError, isA()); + expect( + output, + containsAllInOrder( + [ + contains('Build example before linting'), + ], + )); + }); + + test('skips non-Android plugins', () async { + createFakePlugin('plugin1', packagesDir); + + final List output = + await runCapturingPrint(runner, ['lint-android']); + + expect( + output, + containsAllInOrder( + [ + contains( + 'SKIPPING: Plugin does not have an Android implemenatation.') + ], + )); + }); + + test('skips non-inline plugins', () async { + createFakePlugin('plugin1', packagesDir, + platformSupport: { + kPlatformAndroid: PlatformSupport.federated + }); + + final List output = + await runCapturingPrint(runner, ['lint-android']); + + expect( + output, + containsAllInOrder( + [ + contains( + 'SKIPPING: Plugin does not have an Android implemenatation.') + ], + )); + }); + }); +}