Skip to content

Commit b3a6959

Browse files
[local_auth] Convert to Kotlin gradle for the plugin build files (flutter#11169)
Following up from flutter#11127, this is the initial example of converting a plugin build, rather than an example app build, to Kotlin gradle. This conversion was done manually, but closely referencing the current plugin template files. It differs mostly in not having the parts that are specific to the use of Kotlin source files, since `local_auth` is still Java-only. Later (when we start adopting Kotlin Pigeon generation everywhere, for instance) some of the diffs relative to the template files will go away. Unlike flutter#11127 this did not require tool changes, as it turns out that the previous changes were enough to handle these files, but I did add more tests. As with flutter#11127 I did not attempt to comprehensively duplicate all Groovy tests, since we should be able to relatively quickly convert everything in the repo, and then pull out the Groovy support and update all the tests to Kotlin. Note that this does *not* convert the plugin's example app to Kotlin gradle, only the plugin itself. The example app for plugins are non-trivial enough (due to native tests) that they should be converted separately. This has the bonus effect of validating that the plugin migration didn't require any changes in the client app. Part of flutter/flutter#176065 ## Pre-Review Checklist [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
1 parent 43de301 commit b3a6959

6 files changed

Lines changed: 213 additions & 45 deletions

File tree

packages/local_auth/local_auth_android/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.7
2+
3+
* Updates build files from Groovy to Kotlin.
4+
15
## 2.0.6
26

37
* Bumps androidx.core:core from 1.17.0 to 1.18.0.

packages/local_auth/local_auth_android/android/build.gradle renamed to packages/local_auth/local_auth_android/android/build.gradle.kts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
group = 'io.flutter.plugins.localauth'
2-
version = '1.0-SNAPSHOT'
1+
group = "io.flutter.plugins.localauth"
2+
version = "1.0-SNAPSHOT"
33

44
buildscript {
55
repositories {
@@ -8,7 +8,7 @@ buildscript {
88
}
99

1010
dependencies {
11-
classpath 'com.android.tools.build:gradle:8.13.1'
11+
classpath("com.android.tools.build:gradle:8.13.1")
1212
}
1313
}
1414

@@ -19,37 +19,40 @@ rootProject.allprojects {
1919
}
2020
}
2121

22-
apply plugin: 'com.android.library'
22+
plugins {
23+
id("com.android.library")
24+
}
2325

2426
android {
2527
namespace = "io.flutter.plugins.localauth"
2628
compileSdk = flutter.compileSdkVersion
2729

2830
defaultConfig {
29-
minSdkVersion 24
30-
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
31+
minSdk = 24
32+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
3133
}
3234

3335
compileOptions {
3436
sourceCompatibility = JavaVersion.VERSION_17
3537
targetCompatibility = JavaVersion.VERSION_17
3638
}
3739

38-
lintOptions {
40+
lint {
3941
checkAllWarnings = true
4042
warningsAsErrors = true
41-
disable 'AndroidGradlePluginVersion', 'InvalidPackage', 'GradleDependency', 'NewerVersionAvailable'
43+
disable.addAll(setOf("AndroidGradlePluginVersion", "InvalidPackage", "GradleDependency", "NewerVersionAvailable"))
4244
}
4345

44-
4546
testOptions {
46-
unitTests.includeAndroidResources = true
47-
unitTests.returnDefaultValues = true
48-
unitTests.all {
49-
testLogging {
50-
events "passed", "skipped", "failed", "standardOut", "standardError"
51-
outputs.upToDateWhen {false}
52-
showStandardStreams = true
47+
unitTests {
48+
isIncludeAndroidResources = true
49+
isReturnDefaultValues = true
50+
all {
51+
it.outputs.upToDateWhen { false }
52+
it.testLogging {
53+
events("passed", "skipped", "failed", "standardOut", "standardError")
54+
showStandardStreams = true
55+
}
5356
}
5457
}
5558
}

packages/local_auth/local_auth_android/android/settings.gradle

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = "local_auth"

packages/local_auth/local_auth_android/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: local_auth_android
22
description: Android implementation of the local_auth plugin.
33
repository: https://github.com/flutter/packages/tree/main/packages/local_auth/local_auth_android
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+local_auth%22
5-
version: 2.0.6
5+
version: 2.0.7
66

77
environment:
88
sdk: ^3.9.0

script/tool/test/gradle_check_command_test.dart

Lines changed: 188 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ void main() {
1919
late Directory packagesDir;
2020
const groovyJavaIncompatabilityIndicator =
2121
'build.gradle must set an explicit Java compatibility version.';
22+
const kotlinJavaIncompatabilityIndicator =
23+
'build.gradle.kts must set an explicit Java compatibility version.';
2224

2325
setUp(() {
2426
final GitDir gitDir;
@@ -128,6 +130,101 @@ dependencies {
128130
''');
129131
}
130132

133+
/// Writes a fake android/build.gradle.kts file for plugin [package] with the
134+
/// given options.
135+
void writeFakeKotlinPluginBuildGradle(
136+
RepositoryPackage package, {
137+
bool includeLanguageVersion = false,
138+
bool includeSourceCompat = false,
139+
bool includeTargetCompat = false,
140+
bool commentSourceLanguage = false,
141+
bool includeNamespace = true,
142+
bool commentNamespace = false,
143+
bool warningsConfigured = true,
144+
String compileSdk = '36',
145+
bool includeKotlinOptions = true,
146+
bool commentKotlinOptions = false,
147+
bool useDeprecatedJvmTargetStyle = false,
148+
int jvmTargetValue = 17,
149+
int kotlinJvmValue = 17,
150+
}) {
151+
final File buildGradle = package
152+
.platformDirectory(FlutterPlatform.android)
153+
.childFile('build.gradle.kts');
154+
buildGradle.createSync(recursive: true);
155+
156+
const warningConfig = '''
157+
lint {
158+
checkAllWarnings = true
159+
warningsAsErrors = true
160+
disable.addAll(setOf("AndroidGradlePluginVersion", "InvalidPackage", "GradleDependency", "NewerVersionAvailable"))
161+
baseline = file("lint-baseline.xml")
162+
}
163+
''';
164+
final javaSection =
165+
'''
166+
java {
167+
toolchain {
168+
${commentSourceLanguage ? '// ' : ''}languageVersion = JavaLanguageVersion.of(8)
169+
}
170+
}
171+
172+
''';
173+
final sourceCompat =
174+
'${commentSourceLanguage ? '// ' : ''}sourceCompatibility = JavaVersion.VERSION_$jvmTargetValue';
175+
final targetCompat =
176+
'${commentSourceLanguage ? '// ' : ''}targetCompatibility = JavaVersion.VERSION_$jvmTargetValue';
177+
final namespace =
178+
' ${commentNamespace ? '// ' : ''}namespace = "$_defaultFakeNamespace"';
179+
final kotlinJvmTarget = useDeprecatedJvmTargetStyle
180+
? '$jvmTargetValue'
181+
: 'JavaVersion.VERSION_$kotlinJvmValue.toString()';
182+
final kotlinConfig =
183+
'''
184+
${commentKotlinOptions ? '//' : ''}kotlinOptions {
185+
${commentKotlinOptions ? '//' : ''}jvmTarget = $kotlinJvmTarget
186+
${commentKotlinOptions ? '//' : ''}}''';
187+
188+
buildGradle.writeAsStringSync('''
189+
group = "dev.flutter.plugins.fake"
190+
version = "1.0-SNAPSHOT"
191+
192+
buildscript {
193+
repositories {
194+
google()
195+
mavenCentral()
196+
}
197+
}
198+
199+
apply plugin: 'com.android.library'
200+
201+
${includeLanguageVersion ? javaSection : ''}
202+
android {
203+
${includeNamespace ? namespace : ''}
204+
compileSdk = $compileSdk
205+
206+
defaultConfig {
207+
minSdk = 30
208+
}
209+
${warningsConfigured ? warningConfig : ''}
210+
compileOptions {
211+
${includeSourceCompat ? sourceCompat : ''}
212+
${includeTargetCompat ? targetCompat : ''}
213+
}
214+
${includeKotlinOptions ? kotlinConfig : ''}
215+
testOptions {
216+
unitTests {
217+
isIncludeAndroidResources = true
218+
}
219+
}
220+
}
221+
222+
dependencies {
223+
implementation("fake.package:fake:1.0.0")
224+
}
225+
''');
226+
}
227+
131228
/// Writes a fake android/build.gradle file for an example [package] with the
132229
/// given options.
133230
// TODO(stuartmorgan): Once all packages are migrated to Kotlin, remove all
@@ -542,32 +639,65 @@ flutter {
542639
);
543640
});
544641

545-
test('fails when build.gradle has no java compatibility version', () async {
546-
final RepositoryPackage package = createFakePlugin(
547-
'a_plugin',
548-
packagesDir,
549-
examples: <String>[],
550-
);
551-
writeFakeGroovyPluginBuildGradle(package);
552-
writeFakeManifest(package);
642+
test(
643+
'fails when build.gradle has no java compatibility version - groovy',
644+
() async {
645+
final RepositoryPackage package = createFakePlugin(
646+
'a_plugin',
647+
packagesDir,
648+
examples: <String>[],
649+
);
650+
writeFakeGroovyPluginBuildGradle(package);
651+
writeFakeManifest(package);
553652

554-
Error? commandError;
555-
final List<String> output = await runCapturingPrint(
556-
runner,
557-
<String>['gradle-check'],
558-
errorHandler: (Error e) {
559-
commandError = e;
560-
},
561-
);
653+
Error? commandError;
654+
final List<String> output = await runCapturingPrint(
655+
runner,
656+
<String>['gradle-check'],
657+
errorHandler: (Error e) {
658+
commandError = e;
659+
},
660+
);
562661

563-
expect(commandError, isA<ToolExit>());
564-
expect(
565-
output,
566-
containsAllInOrder(<Matcher>[
567-
contains(groovyJavaIncompatabilityIndicator),
568-
]),
569-
);
570-
});
662+
expect(commandError, isA<ToolExit>());
663+
expect(
664+
output,
665+
containsAllInOrder(<Matcher>[
666+
contains(groovyJavaIncompatabilityIndicator),
667+
]),
668+
);
669+
},
670+
);
671+
672+
test(
673+
'fails when build.gradle has no java compatibility version - kotlin',
674+
() async {
675+
final RepositoryPackage package = createFakePlugin(
676+
'a_plugin',
677+
packagesDir,
678+
examples: <String>[],
679+
);
680+
writeFakeKotlinPluginBuildGradle(package);
681+
writeFakeManifest(package);
682+
683+
Error? commandError;
684+
final List<String> output = await runCapturingPrint(
685+
runner,
686+
<String>['gradle-check'],
687+
errorHandler: (Error e) {
688+
commandError = e;
689+
},
690+
);
691+
692+
expect(commandError, isA<ToolExit>());
693+
expect(
694+
output,
695+
containsAllInOrder(<Matcher>[
696+
contains(kotlinJavaIncompatabilityIndicator),
697+
]),
698+
);
699+
},
700+
);
571701

572702
test(
573703
'fails when sourceCompatibility is provided with out targetCompatibility',
@@ -774,7 +904,7 @@ flutter {
774904
test('does not require java version in examples - kotlin', () async {
775905
const pluginName = 'a_plugin';
776906
final RepositoryPackage package = createFakePlugin(pluginName, packagesDir);
777-
writeFakeGroovyPluginBuildGradle(package, includeLanguageVersion: true);
907+
writeFakeKotlinPluginBuildGradle(package, includeLanguageVersion: true);
778908
writeFakeManifest(package);
779909
final RepositoryPackage example = package.getExamples().first;
780910
writeFakeKotlinExampleBuildGradles(example, pluginName: pluginName);
@@ -888,7 +1018,7 @@ flutter {
8881018
},
8891019
);
8901020

891-
test('fails when namespace is missing', () async {
1021+
test('fails when namespace is missing - groovy', () async {
8921022
final RepositoryPackage package = createFakePlugin(
8931023
'a_plugin',
8941024
packagesDir,
@@ -919,6 +1049,37 @@ flutter {
9191049
);
9201050
});
9211051

1052+
test('fails when namespace is missing - kotlin', () async {
1053+
final RepositoryPackage package = createFakePlugin(
1054+
'a_plugin',
1055+
packagesDir,
1056+
examples: <String>[],
1057+
);
1058+
writeFakeKotlinPluginBuildGradle(
1059+
package,
1060+
includeLanguageVersion: true,
1061+
includeNamespace: false,
1062+
);
1063+
writeFakeManifest(package);
1064+
1065+
Error? commandError;
1066+
final List<String> output = await runCapturingPrint(
1067+
runner,
1068+
<String>['gradle-check'],
1069+
errorHandler: (Error e) {
1070+
commandError = e;
1071+
},
1072+
);
1073+
1074+
expect(commandError, isA<ToolExit>());
1075+
expect(
1076+
output,
1077+
containsAllInOrder(<Matcher>[
1078+
contains('build.gradle.kts must set a "namespace"'),
1079+
]),
1080+
);
1081+
});
1082+
9221083
test('fails when namespace is missing from example - groovy', () async {
9231084
const pluginName = 'a_plugin';
9241085
final RepositoryPackage package = createFakePlugin(pluginName, packagesDir);
@@ -953,7 +1114,7 @@ flutter {
9531114
test('fails when namespace is missing from example - kotlin', () async {
9541115
const pluginName = 'a_plugin';
9551116
final RepositoryPackage package = createFakePlugin(pluginName, packagesDir);
956-
writeFakeGroovyPluginBuildGradle(package, includeLanguageVersion: true);
1117+
writeFakeKotlinPluginBuildGradle(package, includeLanguageVersion: true);
9571118
writeFakeManifest(package);
9581119
final RepositoryPackage example = package.getExamples().first;
9591120
writeFakeKotlinExampleBuildGradles(

0 commit comments

Comments
 (0)