mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add kotlin compatability to build file validation (#167143)
Fixes https://github.com/flutter/flutter/issues/161443 * adds a new gradle task like `javaVersion` named `kgpVersion` that prints the version of kgp. * adds gradle_utils.dart method for getting kgp version * * kgp method is moved to utilities and we attempt to use a plugin method before reflection. * adds methods or evaluating KGP + gradle and KGP + AGP compatibility. * * It turns out that we have been using incompatible versions that happen to work with the subset of kotlin we are using. * Uses new kgp methods in flutter analyze --suggestions as part of the existing agp/java/gradle compatibility matrix. * adds new tests for all new functionality * Adds comments to sections of the code I found could use them. * Modifies flutter gallery to use a compatible version of kotlin and update its lockfiles. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [X] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
This commit is contained in:
parent
d203008741
commit
f20bc39cc0
@ -113,35 +113,30 @@ org.glassfish.jaxb:jaxb-runtime:2.3.2=classpath
|
||||
org.glassfish.jaxb:txw2:2.3.2=classpath
|
||||
org.jdom:jdom2:2.0.6=classpath
|
||||
org.jetbrains.intellij.deps:trove4j:1.0.20200330=classpath
|
||||
org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-android-extensions:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-build-common:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-compiler-runner:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-daemon-client:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-native-utils:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-project-model:1.8.10=classpath
|
||||
org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-build-statistics:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-build-tools-api:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-compiler-runner:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-daemon-client:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-api:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-idea:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-model:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugins-bom:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-klib-commonizer-api:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-native-utils:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.9.20=classpath
|
||||
org.jetbrains.kotlin:kotlin-scripting-common:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-scripting-jvm:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.20=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.9.20=classpath
|
||||
org.jetbrains.kotlin:kotlin-tooling-core:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-util-io:1.8.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-util-klib:1.8.10=classpath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0=classpath
|
||||
org.jetbrains.kotlin:kotlin-tooling-core:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-util-io:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-util-klib-metadata:2.1.10=classpath
|
||||
org.jetbrains.kotlin:kotlin-util-klib:2.1.10=classpath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=classpath
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.4.0=classpath
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.0=classpath
|
||||
org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.4.0=classpath
|
||||
|
||||
@ -111,8 +111,8 @@ javax.annotation:javax.annotation-api:1.3.2=_internal-unified-test-platform-andr
|
||||
javax.inject:javax.inject:1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
junit:junit:4.12=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath
|
||||
junit:junit:4.13.2=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.12.22=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.22=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy-agent:1.14.10=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.14.10=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
net.java.dev.jna:jna-platform:5.6.0=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
net.java.dev.jna:jna:5.6.0=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
net.sf.kxml:kxml2:2.3.0=_internal-unified-test-platform-android-device-provider-ddmlib,debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
@ -144,8 +144,7 @@ org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4=_internal-unified-test-platf
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
org.jetbrains:annotations:13.0=_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle
|
||||
org.jetbrains:annotations:23.0.0=_internal-unified-test-platform-android-device-provider-ddmlib,debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
org.mockito:mockito-core:5.1.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
org.mockito:mockito-inline:5.1.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
org.mockito:mockito-core:5.8.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
org.objenesis:objenesis:3.3=debugUnitTestRuntimeClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:9.1=androidJacocoAnt
|
||||
org.ow2.asm:asm-commons:9.1=androidJacocoAnt
|
||||
|
||||
@ -30,7 +30,7 @@ androidx.savedstate:savedstate:1.2.1=debugAndroidTestCompileClasspath,debugAndro
|
||||
androidx.startup:startup-runtime:1.1.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
androidx.test.espresso:espresso-idling-resource:3.5.1=debugUnitTestRuntimeClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath
|
||||
androidx.test:annotation:1.0.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
androidx.test:core:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
androidx.test:core:1.4.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
androidx.test:monitor:1.6.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
androidx.tracing:tracing:1.2.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
androidx.versionedparcelable:versionedparcelable:1.1.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
|
||||
|
||||
@ -35,7 +35,7 @@ buildscript {
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "8.7.0" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.8.10" apply false
|
||||
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
|
||||
@ -12,8 +12,13 @@ import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
||||
|
||||
/**
|
||||
* Warns or errors on version ranges of dependencies required to build a Flutter Android app.
|
||||
*
|
||||
* For code that evaluates if dependencies are compatible with each other see
|
||||
* packages/flutter_tools/lib/src/android/gradle_utils.dart.
|
||||
*/
|
||||
object DependencyVersionChecker {
|
||||
// Logging constants.
|
||||
@VisibleForTesting internal const val GRADLE_NAME: String = "Gradle"
|
||||
@ -114,12 +119,12 @@ object DependencyVersionChecker {
|
||||
@JvmStatic fun checkDependencyVersions(project: Project) {
|
||||
project.extra.set(OUT_OF_SUPPORT_RANGE_PROPERTY, false)
|
||||
|
||||
checkGradleVersion(getGradleVersion(project), project)
|
||||
checkJavaVersion(getJavaVersion(), project)
|
||||
checkGradleVersion(VersionFetcher.getGradleVersion(project), project)
|
||||
checkJavaVersion(VersionFetcher.getJavaVersion(), project)
|
||||
|
||||
configureMinSdkCheck(project)
|
||||
|
||||
val agpVersion: AndroidPluginVersion? = getAGPVersion(project)
|
||||
val agpVersion: AndroidPluginVersion? = VersionFetcher.getAGPVersion(project)
|
||||
if (agpVersion != null) {
|
||||
checkAGPVersion(agpVersion, project)
|
||||
} else {
|
||||
@ -129,7 +134,7 @@ object DependencyVersionChecker {
|
||||
)
|
||||
}
|
||||
|
||||
val kgpVersion: Version? = getKGPVersion(project)
|
||||
val kgpVersion: Version? = VersionFetcher.getKGPVersion(project)
|
||||
if (kgpVersion != null) {
|
||||
checkKGPVersion(kgpVersion, project)
|
||||
}
|
||||
@ -176,7 +181,7 @@ object DependencyVersionChecker {
|
||||
project: Project,
|
||||
it: Variant
|
||||
): MinSdkVersion {
|
||||
val agpVersion: AndroidPluginVersion? = getAGPVersion(project)
|
||||
val agpVersion: AndroidPluginVersion? = VersionFetcher.getAGPVersion(project)
|
||||
return if (agpVersion != null && agpVersion.major >= 8 && agpVersion.minor >= 1) {
|
||||
MinSdkVersion(it.name, it.minSdk.apiLevel)
|
||||
} else {
|
||||
@ -184,54 +189,6 @@ object DependencyVersionChecker {
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api.invocation/-gradle/index.html#-837060600%2FFunctions%2F-1793262594
|
||||
@VisibleForTesting internal fun getGradleVersion(project: Project): Version {
|
||||
val untrimmedGradleVersion: String = project.gradle.gradleVersion
|
||||
// Trim to handle candidate gradle versions (example 7.6-rc-4). This means we treat all
|
||||
// candidate versions of gradle as the same as their base version
|
||||
// (i.e., "7.6"="7.6-rc-4").
|
||||
return Version.fromString(untrimmedGradleVersion.substringBefore('-'))
|
||||
}
|
||||
|
||||
// https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api/-java-version/index.html#-1790786897%2FFunctions%2F-1793262594
|
||||
@VisibleForTesting internal fun getJavaVersion(): JavaVersion = JavaVersion.current()
|
||||
|
||||
@VisibleForTesting internal fun getAGPVersion(project: Project): AndroidPluginVersion? {
|
||||
val androidPluginVersion: AndroidPluginVersion? =
|
||||
project.extensions
|
||||
.findByType(
|
||||
AndroidComponentsExtension::class.java
|
||||
)?.pluginVersion
|
||||
return androidPluginVersion
|
||||
}
|
||||
|
||||
// TODO(gmackall): AGP has a getKotlinAndroidPluginVersion(), and KGP has a
|
||||
// getKotlinPluginVersion(). Consider replacing this implementation with one of
|
||||
// those.
|
||||
@VisibleForTesting internal fun getKGPVersion(project: Project): Version? {
|
||||
val kotlinVersionProperty = "kotlin_version"
|
||||
val firstKotlinVersionFieldName = "pluginVersion"
|
||||
val secondKotlinVersionFieldName = "kotlinPluginVersion"
|
||||
// This property corresponds to application of the Kotlin Gradle plugin in the
|
||||
// top-level build.gradle file.
|
||||
if (project.hasProperty(kotlinVersionProperty)) {
|
||||
return Version.fromString(project.properties[kotlinVersionProperty] as String)
|
||||
}
|
||||
val kotlinPlugin =
|
||||
project.plugins
|
||||
.findPlugin(KotlinAndroidPluginWrapper::class.java)
|
||||
val versionField =
|
||||
kotlinPlugin?.javaClass?.kotlin?.members?.first {
|
||||
it.name == firstKotlinVersionFieldName || it.name == secondKotlinVersionFieldName
|
||||
}
|
||||
val versionString = versionField?.call(kotlinPlugin)
|
||||
return if (versionString == null) {
|
||||
null
|
||||
} else {
|
||||
Version.fromString(versionString as String)
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting internal fun getErrorMessage(
|
||||
dependencyName: String,
|
||||
versionString: String,
|
||||
@ -394,43 +351,6 @@ object DependencyVersionChecker {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class to parse the versions that are provided as plain strings (Gradle, Kotlin) and
|
||||
// perform easy comparisons. All versions will have a major, minor, and patch value. These values
|
||||
// default to 0 when they are not provided or are otherwise unparseable.
|
||||
// For example the version strings "8.2", "8.2.2hfd", and "8.2.0" would parse to the same version.
|
||||
internal class Version(
|
||||
val major: Int,
|
||||
val minor: Int,
|
||||
val patch: Int
|
||||
) : Comparable<Version> {
|
||||
companion object {
|
||||
fun fromString(version: String): Version {
|
||||
val asList: List<String> = version.split(".")
|
||||
val convertedToNumbers: List<Int> = asList.map { it.toIntOrNull() ?: 0 }
|
||||
return Version(
|
||||
major = convertedToNumbers.getOrElse(0) { 0 },
|
||||
minor = convertedToNumbers.getOrElse(1) { 0 },
|
||||
patch = convertedToNumbers.getOrElse(2) { 0 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun compareTo(other: Version): Int {
|
||||
if (major != other.major) {
|
||||
return major - other.major
|
||||
}
|
||||
if (minor != other.minor) {
|
||||
return minor - other.minor
|
||||
}
|
||||
if (patch != other.patch) {
|
||||
return patch - other.patch
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun toString(): String = "$major.$minor.$patch"
|
||||
}
|
||||
|
||||
// Custom error for when the dependency_version_checker.kts script finds a dependency out of
|
||||
// the defined support range.
|
||||
@VisibleForTesting internal class DependencyValidationException(
|
||||
|
||||
@ -314,6 +314,7 @@ class FlutterPlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
FlutterPluginUtils.addTaskForJavaVersion(projectToAddTasksTo)
|
||||
FlutterPluginUtils.addTaskForKGPVersion(projectToAddTasksTo)
|
||||
if (FlutterPluginUtils.isFlutterAppProject(projectToAddTasksTo)) {
|
||||
FlutterPluginUtils.addTaskForPrintBuildVariants(projectToAddTasksTo)
|
||||
FlutterPluginUtils.addTasksForOutputsAppLinkSettings(projectToAddTasksTo)
|
||||
|
||||
@ -12,7 +12,6 @@ import com.flutter.gradle.plugins.PluginHandler
|
||||
import groovy.lang.Closure
|
||||
import groovy.util.Node
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.UnknownTaskException
|
||||
@ -625,7 +624,7 @@ object FlutterPluginUtils {
|
||||
// build artifact, so we move it from that directory to within Flutter's build directory
|
||||
// to avoid polluting source directories with build artifacts.
|
||||
//
|
||||
// AGP explicitely recommends not setting the buildStagingDirectory to be within a build
|
||||
// AGP explicitly recommends not setting the buildStagingDirectory to be within a build
|
||||
// directory in
|
||||
// https://developer.android.com/reference/tools/gradle-api/8.3/null/com/android/build/api/dsl/Cmake#buildStagingDirectory(kotlin.Any),
|
||||
// but as we are not actually building anything (and are instead only tricking AGP into
|
||||
@ -675,7 +674,7 @@ object FlutterPluginUtils {
|
||||
if (!supportsBuildMode(project, flutterBuildMode)) {
|
||||
project.logger.quiet(
|
||||
"Project does not support Flutter build mode: $flutterBuildMode, " +
|
||||
"skipping adding flutter dependencies"
|
||||
"skipping adding Flutter dependencies"
|
||||
)
|
||||
return
|
||||
}
|
||||
@ -714,7 +713,7 @@ object FlutterPluginUtils {
|
||||
|
||||
// ------------------ Task adders (a subset of the above category)
|
||||
|
||||
// Add a task that can be called on flutter projects that prints the Java version used in Gradle.
|
||||
// Add a task that can be called on Flutter projects that prints the Java version used in Gradle.
|
||||
//
|
||||
// Format of the output of this task can be used in debugging what version of Java Gradle is using.
|
||||
// Not recommended for use in time sensitive commands like `flutter run` or `flutter build` as
|
||||
@ -726,7 +725,25 @@ object FlutterPluginUtils {
|
||||
description = "Print the current java version used by gradle. see: " +
|
||||
"https://docs.gradle.org/current/javadoc/org/gradle/api/JavaVersion.html"
|
||||
doLast {
|
||||
println(JavaVersion.current())
|
||||
println(VersionFetcher.getJavaVersion())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a task that can be called on Flutter projects that prints the KGP version used in
|
||||
// the project.
|
||||
//
|
||||
// Format of the output of this task can be used in debugging what version of KGP a
|
||||
// project is using.
|
||||
// Not recommended for use in time sensitive commands like `flutter run` or `flutter build` as
|
||||
// Gradle tasks are slower than we want. Particularly in light of https://github.com/flutter/flutter/issues/119196.
|
||||
@JvmStatic
|
||||
@JvmName("addTaskForKGPVersion")
|
||||
internal fun addTaskForKGPVersion(project: Project) {
|
||||
project.tasks.register("kgpVersion") {
|
||||
description = "Print the current kgp version used by the project."
|
||||
doLast {
|
||||
println("KGP Version: " + VersionFetcher.getKGPVersion(project).toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
121
packages/flutter_tools/gradle/src/main/kotlin/VersionFetcher.kt
Normal file
121
packages/flutter_tools/gradle/src/main/kotlin/VersionFetcher.kt
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
package com.flutter.gradle
|
||||
|
||||
import com.android.build.api.AndroidPluginVersion
|
||||
import com.android.build.api.variant.AndroidComponentsExtension
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
||||
|
||||
internal object VersionFetcher {
|
||||
/**
|
||||
* Returns the version of the JVM.
|
||||
*/
|
||||
internal fun getJavaVersion(): JavaVersion = JavaVersion.current()
|
||||
|
||||
/**
|
||||
* Returns the version of Gradle.
|
||||
*/
|
||||
internal fun getGradleVersion(project: Project): Version {
|
||||
// https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api.invocation/-gradle/index.html#-837060600%2FFunctions%2F-1793262594
|
||||
val untrimmedGradleVersion: String = project.gradle.gradleVersion
|
||||
// Trim to handle candidate gradle versions (example 7.6-rc-4). This means we treat all
|
||||
// candidate versions of gradle as the same as their base version
|
||||
// (i.e., "7.6"="7.6-rc-4").
|
||||
return Version.fromString(untrimmedGradleVersion.substringBefore('-'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the Android Gradle plugin.
|
||||
*/
|
||||
internal fun getAGPVersion(project: Project): AndroidPluginVersion? {
|
||||
val androidPluginVersion: AndroidPluginVersion? =
|
||||
project.extensions
|
||||
.findByType(
|
||||
AndroidComponentsExtension::class.java
|
||||
)?.pluginVersion
|
||||
return androidPluginVersion
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the Kotlin Gradle plugin.
|
||||
*/
|
||||
internal fun getKGPVersion(project: Project): Version? {
|
||||
// TODO(gmackall): AGP has a getKotlinAndroidPluginVersion(), and KGP has a
|
||||
// getKotlinPluginVersion(). Consider replacing this implementation with one of
|
||||
// those.
|
||||
val kotlinVersionProperty = "kotlin_version"
|
||||
val firstKotlinVersionFieldName = "pluginVersion"
|
||||
val secondKotlinVersionFieldName = "kotlinPluginVersion"
|
||||
// This property corresponds to application of the Kotlin Gradle plugin in the
|
||||
// top-level build.gradle file.
|
||||
if (project.hasProperty(kotlinVersionProperty)) {
|
||||
return Version.fromString(project.properties[kotlinVersionProperty] as String)
|
||||
}
|
||||
val kotlinPlugin =
|
||||
project.plugins
|
||||
.findPlugin(KotlinAndroidPluginWrapper::class.java)
|
||||
// Partial implementation of getKotlinPluginVersion from the comment above.
|
||||
var versionString: String? = kotlinPlugin?.pluginVersion
|
||||
if (!versionString.isNullOrEmpty()) {
|
||||
return Version.fromString(versionString)
|
||||
}
|
||||
// Fall back to reflection.
|
||||
val versionField =
|
||||
kotlinPlugin?.javaClass?.kotlin?.members?.firstOrNull {
|
||||
it.name == firstKotlinVersionFieldName || it.name == secondKotlinVersionFieldName
|
||||
}
|
||||
versionString = versionField?.call(kotlinPlugin) as String?
|
||||
return if (versionString == null) {
|
||||
null
|
||||
} else {
|
||||
Version.fromString(versionString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to parse the versions that are provided as plain strings (Gradle, Kotlin) and
|
||||
* perform easy comparisons. All versions will have a major, minor, and patch value. These values
|
||||
* default to 0 when they are not provided or are otherwise unparseable.
|
||||
* For example the version strings "8.2", "8.2.2hfd", and "8.2.0" would parse to the same version.
|
||||
*/
|
||||
internal class Version(
|
||||
val major: Int,
|
||||
val minor: Int,
|
||||
val patch: Int
|
||||
) : Comparable<Version> {
|
||||
companion object {
|
||||
fun fromString(version: String): Version {
|
||||
val asList: List<String> = version.split(".")
|
||||
val convertedToNumbers: List<Int> = asList.map { it.toIntOrNull() ?: 0 }
|
||||
return Version(
|
||||
major = convertedToNumbers.getOrElse(0) { 0 },
|
||||
minor = convertedToNumbers.getOrElse(1) { 0 },
|
||||
patch = convertedToNumbers.getOrElse(2) { 0 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun compareTo(other: Version): Int {
|
||||
if (major != other.major) {
|
||||
return major - other.major
|
||||
}
|
||||
if (minor != other.minor) {
|
||||
return minor - other.minor
|
||||
}
|
||||
if (patch != other.patch) {
|
||||
return patch - other.patch
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is Version && compareTo(other) == 0
|
||||
|
||||
override fun hashCode(): Int = major.hashCode() or minor.hashCode() or patch.hashCode()
|
||||
|
||||
override fun toString(): String = "$major.$minor.$patch"
|
||||
}
|
||||
@ -886,7 +886,7 @@ class FlutterPluginUtilsTest {
|
||||
verify(exactly = 1) {
|
||||
project.logger.quiet(
|
||||
"Project does not support Flutter build mode: debug, " +
|
||||
"skipping adding flutter dependencies"
|
||||
"skipping adding Flutter dependencies"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1049,6 +1049,24 @@ class FlutterPluginUtilsTest {
|
||||
}
|
||||
}
|
||||
|
||||
// addTaskForKGPVersion
|
||||
@Test
|
||||
fun `addTaskForKGPVersion adds task for KGP version`() {
|
||||
val project = mockk<Project>()
|
||||
every { project.tasks.register(any(), any<Action<Task>>()) } returns mockk()
|
||||
val captureSlot = slot<Action<Task>>()
|
||||
FlutterPluginUtils.addTaskForKGPVersion(project)
|
||||
verify { project.tasks.register("kgpVersion", capture(captureSlot)) }
|
||||
|
||||
val mockTask = mockk<Task>()
|
||||
every { mockTask.description = any() } returns Unit
|
||||
every { mockTask.doLast(any<Action<Task>>()) } returns mockk()
|
||||
captureSlot.captured.execute(mockTask)
|
||||
verify {
|
||||
mockTask.description = "Print the current kgp version used by the project."
|
||||
}
|
||||
}
|
||||
|
||||
// addTaskForPrintBuildVariants
|
||||
@Test
|
||||
fun `addTaskForPrintBuildVariants adds task for printing build variants`() {
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
package com.flutter.gradle
|
||||
|
||||
import com.android.build.api.AndroidPluginVersion
|
||||
import com.android.build.api.variant.AndroidComponentsExtension
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class VersionFetcherTest {
|
||||
// getGradleVersion
|
||||
@Test
|
||||
fun `getGradleVersion returns version when gradleVersion is set`() {
|
||||
val gradleVersion = Version(1, 9, 20)
|
||||
val project = mockk<Project>()
|
||||
every { project.gradle.gradleVersion } returns gradleVersion.toString()
|
||||
assertEquals(VersionFetcher.getGradleVersion(project), gradleVersion)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getGradleVersion returns version when gradleVersion has hyphen`() {
|
||||
val project = mockk<Project>()
|
||||
every { project.gradle.gradleVersion } returns "2.1.20-2"
|
||||
assertEquals(VersionFetcher.getGradleVersion(project), Version(2, 1, 20))
|
||||
}
|
||||
|
||||
// getAGPVersion
|
||||
@Test
|
||||
fun `getAGPVersion returns version when agpVersion is set`() {
|
||||
val agpVersion = AndroidPluginVersion(8, 3, 0)
|
||||
val project = mockk<Project>()
|
||||
val mockAndroidComponentsExtension = mockk<AndroidComponentsExtension<*, *, *>>()
|
||||
every { project.extensions.findByType(AndroidComponentsExtension::class.java) } returns mockAndroidComponentsExtension
|
||||
every { mockAndroidComponentsExtension.pluginVersion } returns agpVersion
|
||||
assertEquals(VersionFetcher.getAGPVersion(project).toString(), agpVersion.toString())
|
||||
}
|
||||
|
||||
// getKGPVersion
|
||||
@Test
|
||||
fun `getKGPVersion returns version when kotlin_version is set`() {
|
||||
val kgpVersion = Version(1, 9, 20)
|
||||
val project = mockk<Project>()
|
||||
every { project.hasProperty(eq("kotlin_version")) } returns true
|
||||
every { project.properties["kotlin_version"] } returns kgpVersion.toString()
|
||||
val result = VersionFetcher.getKGPVersion(project)
|
||||
assertEquals(kgpVersion, result!!)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getKGPVersion returns version from KotlinAndroidPluginWrapper`() {
|
||||
val kgpVersion = Version(1, 9, 20)
|
||||
val project = mockk<Project>()
|
||||
every { project.hasProperty(eq("kotlin_version")) } returns false
|
||||
every { project.plugins.findPlugin(KotlinAndroidPluginWrapper::class.java) } returns
|
||||
mockk<KotlinAndroidPluginWrapper> {
|
||||
every { pluginVersion } returns kgpVersion.toString()
|
||||
}
|
||||
val result = VersionFetcher.getKGPVersion(project)
|
||||
assertEquals(kgpVersion, result!!)
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ import 'package:unified_analytics/unified_analytics.dart';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/os.dart';
|
||||
import '../base/platform.dart';
|
||||
@ -62,6 +63,12 @@ const String oneMajorVersionHigherJavaVersion = '24';
|
||||
// flutter analyze --suggestions and does not imply broader flutter support.
|
||||
const String maxKnownAndSupportedGradleVersion = '8.12';
|
||||
|
||||
// Update this with new KGP versions come out including minor versions.
|
||||
//
|
||||
// Supported here means supported by the tooling for
|
||||
// flutter analyze --suggestions and does not imply broader flutter support.
|
||||
const String maxKnownAndSupportedKgpVersion = '2.1.20';
|
||||
|
||||
// Update this when new versions of AGP come out.
|
||||
//
|
||||
// Supported here means tooling is aware of this version's Java <-> AGP
|
||||
@ -72,12 +79,30 @@ const String maxKnownAndSupportedAgpVersion = '8.7.3';
|
||||
// Update this when new versions of AGP come out.
|
||||
const String maxKnownAgpVersion = '8.7.3';
|
||||
|
||||
// Supported here means tooling is aware of this versions
|
||||
// Java <-> AGP compatibility and does not imply broader flutter support.
|
||||
// For use in flutter see the code in:
|
||||
// flutter_tools/gradle/src/main/kotlin/DependencyVersionChecker.kt
|
||||
@visibleForTesting
|
||||
const String oldestConsideredAgpVersion = '3.3.0';
|
||||
|
||||
// Supported here means tooling is aware of this versions
|
||||
// gradle compatibility and does not imply broader flutter support.
|
||||
@visibleForTesting
|
||||
const String oldestConsideredGradleVersion = '4.10.1';
|
||||
|
||||
// Supported here means tooling is aware of this versions
|
||||
// gradle/AGP compatibility and does not imply broader flutter support.
|
||||
@visibleForTesting
|
||||
const String oldestDocumentedKgpCompatabilityVersion = '1.6.20';
|
||||
|
||||
// Oldest documented version of AGP that has a listed minimum
|
||||
// compatible Java version.
|
||||
const String oldestDocumentedJavaAgpCompatibilityVersion = '4.2';
|
||||
|
||||
// Constant used in [_buildAndroidGradlePluginRegExp] and
|
||||
// [_settingsAndroidGradlePluginRegExp] to identify the version section.
|
||||
// [_settingsAndroidGradlePluginRegExp] and [_kotlinGradlePluginRegExpFromId]
|
||||
// to identify the version section.
|
||||
const String _versionGroupName = 'version';
|
||||
|
||||
// AGP can be defined in the dependencies block of [build.gradle] or [build.gradle.kts].
|
||||
@ -103,6 +128,17 @@ final RegExp _androidGradlePluginRegExpFromId = RegExp(
|
||||
multiLine: true,
|
||||
);
|
||||
|
||||
// KGP is defined in several places this code only checks in plugins block
|
||||
// of [settings.gradle] and [settings.gradle.kts].
|
||||
// Expected content:
|
||||
// Groovy DSL - id "org.jetbrains.kotlin.android" version "{{kgpVersion}}"
|
||||
// Kotlin DSL - id("org.jetbrains.kotlin.android") version "{{kgpVersion}}"
|
||||
// ?<version> is used to name the version group which helps with extraction.
|
||||
final RegExp _kotlinGradlePluginRegExpFromId = RegExp(
|
||||
r"""[^\/]*s*id\s*\(?['"]org\.jetbrains\.kotlin\.android['"]\)?\s+version\s+['"](?<version>\d+(\.\d+){1,2})\)?""",
|
||||
multiLine: true,
|
||||
);
|
||||
|
||||
// Expected content format (with lines above and below).
|
||||
// Version can have 2 or 3 numbers.
|
||||
// 'distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip'
|
||||
@ -125,7 +161,8 @@ final RegExp tooOldMinSdkVersionMatch = RegExp(
|
||||
);
|
||||
|
||||
// From https://docs.gradle.org/current/userguide/command_line_interface.html#command_line_interface
|
||||
const String gradleVersionFlag = r'--version';
|
||||
// Flag to print the versions for gradle, kotlin dsl, groovy, etc.
|
||||
const String gradleVersionsFlag = r'--version';
|
||||
|
||||
// Directory under android/ that gradle uses to store gradle information.
|
||||
// Regularly used with [gradleWrapperDirectory] and
|
||||
@ -274,7 +311,7 @@ Future<String?> getGradleVersion(
|
||||
return gradleVersion;
|
||||
} else {
|
||||
// Did not find gradle zip url. Likely this is a bug in our parsing.
|
||||
logger.printWarning(_formatParseWarning(wrapperFileContent));
|
||||
logger.printWarning(_formatParseWarning(wrapperFileContent, type: 'gradle'));
|
||||
}
|
||||
} else {
|
||||
// If no distributionUrl log then treat as if there was no propertiesFile.
|
||||
@ -287,9 +324,10 @@ Future<String?> getGradleVersion(
|
||||
logger.printTrace('$propertiesFile does not exist falling back to system gradle');
|
||||
}
|
||||
// System installed Gradle version.
|
||||
// TODO(reidbaker): Modify this gradle execution to use gradlew.
|
||||
if (processManager.canRun('gradle')) {
|
||||
final String gradleVersionVerbose =
|
||||
(await processManager.run(<String>['gradle', gradleVersionFlag])).stdout as String;
|
||||
final String gradleVersionsVerbose =
|
||||
(await processManager.run(<String>['gradle', gradleVersionsFlag])).stdout as String;
|
||||
// Expected format:
|
||||
/*
|
||||
|
||||
@ -311,10 +349,10 @@ OS: Mac OS X 13.2.1 aarch64
|
||||
// Outer parentheticals `Gradle (...)` denote a grouping used to extract
|
||||
// the version number.
|
||||
final RegExp gradleVersionRegex = RegExp(r'Gradle\s+(\d+\.\d+(?:\.\d+)?)');
|
||||
final RegExpMatch? version = gradleVersionRegex.firstMatch(gradleVersionVerbose);
|
||||
final RegExpMatch? version = gradleVersionRegex.firstMatch(gradleVersionsVerbose);
|
||||
if (version == null) {
|
||||
// Most likely a bug in our parse implementation/regex.
|
||||
logger.printWarning(_formatParseWarning(gradleVersionVerbose));
|
||||
logger.printWarning(_formatParseWarning(gradleVersionsVerbose, type: 'gradle'));
|
||||
return null;
|
||||
}
|
||||
return version.group(1);
|
||||
@ -324,6 +362,80 @@ OS: Mac OS X 13.2.1 aarch64
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the Kotlin Gradle Plugin (KGP) version that the current project
|
||||
/// depends on if found, null otherwise.
|
||||
/// [directory] should be an android directory with a build.gradle file.
|
||||
Future<String?> getKgpVersion(
|
||||
Directory androidDirectory,
|
||||
Logger logger,
|
||||
ProcessManager processManager,
|
||||
) async {
|
||||
// Maintainers of the kotlin dsl and the kotlin gradle plugin are different.
|
||||
//
|
||||
// Android Docs refer to the kotlin gradle plugin with either the full name or KGP.
|
||||
// Kotlin docs refer to the kotlin gradle plugin as kotlin android plugin.
|
||||
//
|
||||
// gradle --version or ./gradlew --version will print the kotlin dsl version.
|
||||
// This version normally changes with the version of gradle.
|
||||
// https://github.com/gradle/gradle/blob/cefbee263181a924ac4efcaace6bda97a55bc0f7/platforms/core-runtime/gradle-cli/src/main/java/org/gradle/launcher/cli/DefaultCommandLineActionFactory.java#L260
|
||||
// This vesion is NOT the version of KGP that the project uses.
|
||||
//
|
||||
// Instead the kgpVersion task is a custom flutter task dynamiclly added that can
|
||||
// print the kgp version if gradle can run successfuly.
|
||||
|
||||
if (processManager.canRun('./gradlew', workingDirectory: androidDirectory.path)) {
|
||||
final ProcessResult command = await processManager.run(<String>[
|
||||
'./gradlew',
|
||||
'kgpVersion',
|
||||
'-q',
|
||||
], workingDirectory: androidDirectory.path);
|
||||
if (command.exitCode == 0) {
|
||||
final String kgpVersionOutput = command.stdout as String;
|
||||
|
||||
// See expected output defined in
|
||||
// flutter/packages/flutter_tools/gradle/src/main/kotlin/FlutterPluginUtils.kt addTaskForKGPVersion
|
||||
final RegExp kotlinVersionRegex = RegExp(r'KGP Version:\s+(\d+\.\d+(?:\.\d+)?)');
|
||||
final RegExpMatch? version = kotlinVersionRegex.firstMatch(kgpVersionOutput);
|
||||
if (version != null) {
|
||||
return version.group(1);
|
||||
}
|
||||
// Most likely a bug in our parse implementation/regex.
|
||||
logger.printWarning(_formatParseWarning(kgpVersionOutput, type: 'kotlin'));
|
||||
} else {
|
||||
logger.printTrace('Non zero exit code from gradle task kgpVersion.');
|
||||
}
|
||||
} else {
|
||||
logger.printTrace('Could not run gradle task kgpVersion.');
|
||||
}
|
||||
|
||||
// Project valiation code is regularly run on projects that can not build.
|
||||
// Because of that this code also attempts to search through known template
|
||||
// locations for kotlin versions.
|
||||
|
||||
logger.printTrace('Checking settings for kgp version.');
|
||||
File settingsFile = androidDirectory.childFile('settings.gradle');
|
||||
if (!settingsFile.existsSync()) {
|
||||
settingsFile = androidDirectory.childFile('settings.gradle.kts');
|
||||
}
|
||||
|
||||
if (settingsFile.existsSync()) {
|
||||
final String settingsFileContent = settingsFile.readAsStringSync();
|
||||
final RegExpMatch? settingsMatch = _kotlinGradlePluginRegExpFromId.firstMatch(
|
||||
settingsFileContent,
|
||||
);
|
||||
|
||||
if (settingsMatch != null) {
|
||||
final String? kgpVersion = settingsMatch.namedGroup(_versionGroupName);
|
||||
logger.printTrace('$settingsFile provides KGP version: $kgpVersion');
|
||||
return kgpVersion;
|
||||
}
|
||||
} else {
|
||||
logger.printTrace('No settings.gradle.kts');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the Android Gradle Plugin (AGP) version that the current project
|
||||
/// depends on when found, null otherwise.
|
||||
///
|
||||
@ -378,14 +490,198 @@ String? getAgpVersion(Directory androidDirectory, Logger logger) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String _formatParseWarning(String content) {
|
||||
return 'Could not parse gradle version from: \n'
|
||||
String _formatParseWarning(String content, {required String type}) {
|
||||
return 'Could not parse $type version from: \n'
|
||||
'$content \n'
|
||||
'If there is a version please look for an existing bug '
|
||||
'https://github.com/flutter/flutter/issues/'
|
||||
' and if one does not exist file a new issue.';
|
||||
}
|
||||
|
||||
// Validate that KGP and Gradle are compatible with each other.
|
||||
//
|
||||
// Returns true if versions are compatible.
|
||||
// Null or empty Gradle or KGP version returns false.
|
||||
// If compatibility cannot be evaluated returns false.
|
||||
// If versions are newer than the max known version a warning is logged and true
|
||||
// returned.
|
||||
//
|
||||
// Source of truth found here:
|
||||
// https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin
|
||||
bool validateGradleAndKGP(Logger logger, {required String? kgpV, required String? gradleV}) {
|
||||
if (gradleV == null || kgpV == null || gradleV.isEmpty || kgpV.isEmpty) {
|
||||
logger.printTrace('Gradle or KGP version unknown ($gradleV, $kgpV).');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isWithinVersionRange(gradleV, min: '0.0', max: oldestConsideredGradleVersion)) {
|
||||
logger.printTrace(
|
||||
'Gradle version $gradleV older than oldest considered $oldestConsideredGradleVersion',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isWithinVersionRange(
|
||||
kgpV,
|
||||
min: maxKnownAndSupportedKgpVersion,
|
||||
max: '100.100',
|
||||
inclusiveMin: false,
|
||||
)) {
|
||||
logger.printTrace(
|
||||
'Newer than known KGP version ($kgpV), gradle ($gradleV).'
|
||||
'\n Treating as valid configuration.',
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin
|
||||
// Documenation is non continuous, past versions are known to the
|
||||
// publishers of KGP. When covering version ranges beyond what is documented
|
||||
// add a comment with the documented value.
|
||||
// Continuous KGP version handling is prefered in case an emergency patch to a
|
||||
// past release is shipped this code will assume the version range that is closest.
|
||||
if (isWithinVersionRange(kgpV, min: '2.1.20', max: '2.1.20')) {
|
||||
// Documented max is 8.11, using 8.12 non inclusive covers patch versions.
|
||||
return isWithinVersionRange(gradleV, min: '7.6.3', max: '8.12', inclusiveMax: false);
|
||||
}
|
||||
if (isWithinVersionRange(kgpV, min: '2.1.0', max: '2.1.10')) {
|
||||
// Documented max is 8.10, using 8.11 non inclusive covers patch versions.
|
||||
return isWithinVersionRange(gradleV, min: '7.6.3', max: '8.11', inclusiveMax: false);
|
||||
}
|
||||
// Documented max is 2.0.21.
|
||||
if (isWithinVersionRange(kgpV, min: '2.0.20', max: '2.1', inclusiveMax: false)) {
|
||||
// Documented max is 8.5, using 8.9 non inclusive covers patch versions.
|
||||
// Kotlin Multiplatform can throw warnings on 8.8.
|
||||
return isWithinVersionRange(gradleV, min: '6.8.3', max: '8.9', inclusiveMax: false);
|
||||
}
|
||||
if (isWithinVersionRange(kgpV, min: '2.0', max: '2.0.20', inclusiveMax: false)) {
|
||||
// Documented max is 8.5, using 8.6 non inclusive covers patch versions.
|
||||
return isWithinVersionRange(gradleV, min: '6.8.3', max: '8.6', inclusiveMax: false);
|
||||
}
|
||||
// Documented max is 1.9.25.
|
||||
if (isWithinVersionRange(kgpV, min: '1.9.20', max: '2.0', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(gradleV, min: '6.8.3', max: '8.1.1');
|
||||
}
|
||||
// Documented max is 1.9.10.
|
||||
if (isWithinVersionRange(kgpV, min: '1.8.20', max: '1.9.20', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(gradleV, min: '6.8.3', max: '7.6.0');
|
||||
}
|
||||
// Documented max is 1.8.11.
|
||||
if (isWithinVersionRange(kgpV, min: '1.8.0', max: '1.8.20', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(gradleV, min: '6.8.3', max: '7.3.3');
|
||||
}
|
||||
// Documented max is 1.7.22.
|
||||
if (isWithinVersionRange(kgpV, min: '1.7.20', max: '1.8.0', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(gradleV, min: '6.7.1', max: '7.1.1');
|
||||
}
|
||||
// Documented max is 1.7.10.
|
||||
if (isWithinVersionRange(kgpV, min: '1.7.0', max: '1.7.20', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(gradleV, min: '6.7.1', max: '7.0.2');
|
||||
}
|
||||
// Documented max is 1.6.21.
|
||||
if (isWithinVersionRange(
|
||||
kgpV,
|
||||
min: oldestDocumentedKgpCompatabilityVersion,
|
||||
max: '1.7.0',
|
||||
inclusiveMax: false,
|
||||
)) {
|
||||
return isWithinVersionRange(gradleV, min: '6.1.1', max: '7.0.2');
|
||||
}
|
||||
|
||||
logger.printTrace('Unknown KGP-Gradle compatibility, KGP: $kgpV, Gradle: $gradleV');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate that KGP and AGP are compatible with each other.
|
||||
//
|
||||
// Returns true if versions are compatible.
|
||||
// Null or empty KGP or AGP version returns false.
|
||||
// If compatibility cannot be evaluated returns false.
|
||||
// If versions are newer than the max known version a warning is logged and true
|
||||
// returned.
|
||||
//
|
||||
// Source of truth found here:
|
||||
// https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin
|
||||
bool validateAgpAndKgp(Logger logger, {required String? kgpV, required String? agpV}) {
|
||||
if (agpV == null || kgpV == null || agpV.isEmpty || kgpV.isEmpty) {
|
||||
logger.printTrace('KGP or AGP version unknown ($kgpV, $agpV).');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isWithinVersionRange(agpV, min: '0.0', max: oldestConsideredAgpVersion)) {
|
||||
logger.printTrace(
|
||||
'AGP version ($agpV) older than oldest supported $oldestConsideredAgpVersion.',
|
||||
);
|
||||
}
|
||||
const String maxKnownAgpVersionWithFullKotinSupport = '8.7.2';
|
||||
|
||||
if (isWithinVersionRange(
|
||||
kgpV,
|
||||
min: maxKnownAndSupportedKgpVersion,
|
||||
max: '100.100',
|
||||
inclusiveMin: false,
|
||||
) ||
|
||||
isWithinVersionRange(
|
||||
agpV,
|
||||
min: maxKnownAgpVersionWithFullKotinSupport,
|
||||
max: '100.100',
|
||||
inclusiveMin: false,
|
||||
)) {
|
||||
logger.printTrace(
|
||||
'Newer than known KGP version ($kgpV), AGP ($agpV).'
|
||||
'\n Treating as valid configuration.',
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin
|
||||
// Documenation is non continuous, past versions are known to the
|
||||
// publishers of KGP. When covering version ranges beyond what is documented
|
||||
// add a comment with the documented value.
|
||||
// Continuous KGP version handling is prefered in case an emergency patch to a
|
||||
// past release is shipped this code will assume the version range that is closest.
|
||||
if (isWithinVersionRange(kgpV, min: '2.1.0', max: '2.1.20')) {
|
||||
return isWithinVersionRange(agpV, min: '7.3.1', max: '8.7.2');
|
||||
}
|
||||
// Documented max is 2.0.21
|
||||
if (isWithinVersionRange(kgpV, min: '2.0.20', max: '2.1.0', inclusiveMax: false)) {
|
||||
// Documented max is 8.5.
|
||||
return isWithinVersionRange(agpV, min: '7.1.3', max: '8.6', inclusiveMax: false);
|
||||
}
|
||||
// Documented max is 2.0.0.
|
||||
if (isWithinVersionRange(kgpV, min: '2.0.0', max: '2.0.20', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(agpV, min: '7.1.3', max: '8.3.1');
|
||||
}
|
||||
// Documented max is 1.9.25
|
||||
if (isWithinVersionRange(kgpV, min: '1.9.20', max: '2.0.0', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(agpV, min: '4.2.2', max: '8.1.0');
|
||||
}
|
||||
// Documented max is 1.9.10
|
||||
if (isWithinVersionRange(kgpV, min: '1.9.0', max: '1.9.20', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(agpV, min: '4.2.2', max: '7.4.0');
|
||||
}
|
||||
// Documented max is 1.8.22
|
||||
if (isWithinVersionRange(kgpV, min: '1.8.20', max: '1.9', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(agpV, min: '4.1.3', max: '7.4.0');
|
||||
}
|
||||
// Documented max is 1.8.11
|
||||
if (isWithinVersionRange(kgpV, min: '1.8.0', max: '1.8.20', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(agpV, min: '4.1.3', max: '7.2.1');
|
||||
}
|
||||
// Documented max is 1.7.22
|
||||
if (isWithinVersionRange(kgpV, min: '1.7.20', max: '1.8.0', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(agpV, min: '3.6.4', max: '7.0.4');
|
||||
}
|
||||
// Documented max is 1.7.10
|
||||
// Documented gap between 1.6.21 and 1.7.0.
|
||||
if (isWithinVersionRange(kgpV, min: '1.6.20', max: '1.7.20', inclusiveMax: false)) {
|
||||
return isWithinVersionRange(agpV, min: '3.4.3', max: '7.0.2');
|
||||
}
|
||||
|
||||
logger.printTrace('Unknown KGP-Gradle compatibility, KGP: $kgpV, AGP: $agpV');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate that Gradle version and AGP are compatible with each other.
|
||||
//
|
||||
// Returns true if versions are compatible.
|
||||
@ -399,23 +695,25 @@ String _formatParseWarning(String content) {
|
||||
// AGP has a minimum version of gradle required but no max starting at
|
||||
// AGP version 2.3.0+.
|
||||
bool validateGradleAndAgp(Logger logger, {required String? gradleV, required String? agpV}) {
|
||||
const String oldestSupportedAgpVersion = '3.3.0';
|
||||
const String oldestSupportedGradleVersion = '4.10.1';
|
||||
|
||||
if (gradleV == null || agpV == null) {
|
||||
logger.printTrace('Gradle version or AGP version unknown ($gradleV, $agpV).');
|
||||
return false;
|
||||
}
|
||||
|
||||
// First check if versions are too old.
|
||||
if (isWithinVersionRange(agpV, min: '0.0', max: oldestSupportedAgpVersion, inclusiveMax: false)) {
|
||||
if (isWithinVersionRange(
|
||||
agpV,
|
||||
min: '0.0',
|
||||
max: oldestConsideredAgpVersion,
|
||||
inclusiveMax: false,
|
||||
)) {
|
||||
logger.printTrace('AGP Version: $agpV is too old.');
|
||||
return false;
|
||||
}
|
||||
if (isWithinVersionRange(
|
||||
gradleV,
|
||||
min: '0.0',
|
||||
max: oldestSupportedGradleVersion,
|
||||
max: oldestConsideredGradleVersion,
|
||||
inclusiveMax: false,
|
||||
)) {
|
||||
logger.printTrace('Gradle Version: $gradleV is too old.');
|
||||
@ -499,7 +797,7 @@ bool validateGradleAndAgp(Logger logger, {required String? gradleV, required Str
|
||||
/// https://docs.gradle.org/current/userguide/compatibility.html#java
|
||||
bool validateJavaAndGradle(Logger logger, {required String? javaV, required String? gradleV}) {
|
||||
// https://docs.gradle.org/current/userguide/compatibility.html#java
|
||||
const String oldestSupportedJavaVersion = '1.8';
|
||||
const String oldestConsideredJavaVersion = '1.8';
|
||||
const String oldestDocumentedJavaGradleCompatibility = '2.0';
|
||||
|
||||
// Begin Java <-> Gradle validation.
|
||||
@ -513,7 +811,7 @@ bool validateJavaAndGradle(Logger logger, {required String? javaV, required Stri
|
||||
if (isWithinVersionRange(
|
||||
javaV,
|
||||
min: '1.1',
|
||||
max: oldestSupportedJavaVersion,
|
||||
max: oldestConsideredJavaVersion,
|
||||
inclusiveMax: false,
|
||||
)) {
|
||||
logger.printTrace('Java Version: $javaV is too old.');
|
||||
|
||||
@ -442,9 +442,9 @@ abstract class FlutterProjectPlatform {
|
||||
class AndroidProject extends FlutterProjectPlatform {
|
||||
AndroidProject._(this.parent);
|
||||
|
||||
// User facing string when java/gradle/agp versions are compatible.
|
||||
// User facing string when java/gradle/agp/kgp versions are compatible.
|
||||
@visibleForTesting
|
||||
static const String validJavaGradleAgpString = 'compatible java/gradle/agp';
|
||||
static const String validJavaGradleAgpKgpString = 'compatible java/gradle/agp/kgp';
|
||||
|
||||
// User facing link that describes compatibility between gradle and
|
||||
// android gradle plugin.
|
||||
@ -456,6 +456,11 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
static const String javaGradleCompatUrl =
|
||||
'https://docs.gradle.org/current/userguide/compatibility.html#java';
|
||||
|
||||
// User facing link that describes compatibility between KGP and Gradle
|
||||
// and AGP.
|
||||
static const String kgpCompatUrl =
|
||||
'https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin';
|
||||
|
||||
// User facing link that describes instructions for downloading
|
||||
// the latest version of Android Studio.
|
||||
static const String installAndroidStudioUrl = 'https://developer.android.com/studio/install';
|
||||
@ -681,7 +686,7 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
// Constructing ProjectValidatorResult happens here and not in
|
||||
// flutter_tools/lib/src/project_validator.dart because of the additional
|
||||
// Complexity of variable status values and error string formatting.
|
||||
const String visibleName = 'Java/Gradle/Android Gradle Plugin';
|
||||
const String visibleName = 'Java/Gradle/KGP/Android Gradle Plugin';
|
||||
final CompatibilityResult validJavaGradleAgpVersions = await hasValidJavaGradleAgpVersions();
|
||||
|
||||
return ProjectValidatorResult(
|
||||
@ -695,8 +700,8 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
}
|
||||
|
||||
/// Ensures Java SDK is compatible with the project's Gradle version and
|
||||
/// the project's Gradle version is compatible with the AGP version used
|
||||
/// in build.gradle.
|
||||
/// the project's Gradle version is compatible with the AGP version and
|
||||
/// kotlin version used in build.gradle.
|
||||
Future<CompatibilityResult> hasValidJavaGradleAgpVersions() async {
|
||||
final String? gradleVersion = await gradle.getGradleVersion(
|
||||
hostAppGradleRoot,
|
||||
@ -705,9 +710,14 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
);
|
||||
final String? agpVersion = gradle.getAgpVersion(hostAppGradleRoot, globals.logger);
|
||||
final String? javaVersion = versionToParsableString(globals.java?.version);
|
||||
final String? kgpVersion = await gradle.getKgpVersion(
|
||||
hostAppGradleRoot,
|
||||
globals.logger,
|
||||
globals.processManager,
|
||||
);
|
||||
|
||||
// Assume valid configuration.
|
||||
String description = validJavaGradleAgpString;
|
||||
String description = validJavaGradleAgpKgpString;
|
||||
|
||||
final bool compatibleGradleAgp = gradle.validateGradleAndAgp(
|
||||
globals.logger,
|
||||
@ -721,6 +731,18 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
gradleV: gradleVersion,
|
||||
);
|
||||
|
||||
final bool compatibleKgpGradle = gradle.validateGradleAndKGP(
|
||||
globals.logger,
|
||||
gradleV: gradleVersion,
|
||||
kgpV: kgpVersion,
|
||||
);
|
||||
|
||||
final bool compatibleAgpKgp = gradle.validateAgpAndKgp(
|
||||
globals.logger,
|
||||
agpV: agpVersion,
|
||||
kgpV: kgpVersion,
|
||||
);
|
||||
|
||||
// Begin description formatting.
|
||||
if (!compatibleGradleAgp) {
|
||||
final String gradleDescription =
|
||||
@ -745,7 +767,28 @@ See the link below for more information:
|
||||
$javaGradleCompatUrl
|
||||
''';
|
||||
}
|
||||
return CompatibilityResult(compatibleJavaGradle && compatibleGradleAgp, description);
|
||||
if (!compatibleKgpGradle) {
|
||||
description = '''
|
||||
${compatibleGradleAgp ? '' : description}
|
||||
Incompatible KGP/Gradle versions.
|
||||
Gradle Version: $gradleVersion, Kotlin Version: $kgpVersion\n
|
||||
See the link below for more information:
|
||||
$kgpCompatUrl
|
||||
''';
|
||||
}
|
||||
if (!compatibleAgpKgp) {
|
||||
description = '''
|
||||
${compatibleGradleAgp ? '' : description}
|
||||
Incompatible AGP/KGP versions.
|
||||
AGP Version: $agpVersion, KGP Version: $kgpVersion\n
|
||||
See the link below for more information:
|
||||
$kgpCompatUrl
|
||||
''';
|
||||
}
|
||||
return CompatibilityResult(
|
||||
compatibleJavaGradle && compatibleGradleAgp && compatibleKgpGradle && compatibleAgpKgp,
|
||||
description,
|
||||
);
|
||||
}
|
||||
|
||||
bool get isUsingGradle {
|
||||
|
||||
@ -332,7 +332,10 @@ OS: Mac OS X 13.2.1 aarch64
|
||||
final Directory androidDirectory = fileSystem.directory('/android')..createSync();
|
||||
final ProcessManager processManager =
|
||||
FakeProcessManager.empty()..addCommand(
|
||||
const FakeCommand(command: <String>['gradle', gradleVersionFlag], stdout: gradleOutput),
|
||||
const FakeCommand(
|
||||
command: <String>['gradle', gradleVersionsFlag],
|
||||
stdout: gradleOutput,
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
@ -347,7 +350,10 @@ OS: Mac OS X 13.2.1 aarch64
|
||||
final Directory androidDirectory = fileSystem.directory('/android')..createSync();
|
||||
final ProcessManager processManager =
|
||||
FakeProcessManager.empty()..addCommand(
|
||||
const FakeCommand(command: <String>['gradle', gradleVersionFlag], stdout: gradleOutput),
|
||||
const FakeCommand(
|
||||
command: <String>['gradle', gradleVersionsFlag],
|
||||
stdout: gradleOutput,
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
@ -708,6 +714,247 @@ dependencies {
|
||||
}
|
||||
});
|
||||
|
||||
FakeCommand createKgpVersionCommand(String kgpV) {
|
||||
return FakeCommand(
|
||||
command: const <String>['./gradlew', 'kgpVersion', '-q'],
|
||||
stdout: '''
|
||||
KGP Version: $kgpV
|
||||
''',
|
||||
);
|
||||
}
|
||||
|
||||
testWithoutContext('returns the KGP fetched from kgpVersion gradle task', () async {
|
||||
final Directory androidDirectory = fileSystem.directory('/android')..createSync();
|
||||
// Three numbered versions.
|
||||
const String kgpV2 = '1.8.22';
|
||||
final FakeProcessManager processManager2 = FakeProcessManager.list(<FakeCommand>[
|
||||
createKgpVersionCommand(kgpV2),
|
||||
]);
|
||||
expect(await getKgpVersion(androidDirectory, BufferLogger.test(), processManager2), kgpV2);
|
||||
// 2 numbered versions
|
||||
const String kgpV3 = '1.9';
|
||||
final FakeProcessManager processManager3 = FakeProcessManager.list(<FakeCommand>[
|
||||
createKgpVersionCommand(kgpV3),
|
||||
]);
|
||||
expect(await getKgpVersion(androidDirectory, BufferLogger.test(), processManager3), kgpV3);
|
||||
final FakeProcessManager processManagerNoGradle = FakeProcessManager.empty();
|
||||
processManagerNoGradle.excludedExecutables = <String>{'./gradlew'};
|
||||
expect(
|
||||
await getKgpVersion(androidDirectory, BufferLogger.test(), processManagerNoGradle),
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('returns the KGP version when in Kotlin settings as plugin', () async {
|
||||
final Directory androidDirectory = fileSystem.directory('/android')..createSync();
|
||||
// File must exist and cannot have kgp defined.
|
||||
androidDirectory.childFile('build.gradle.kts').writeAsStringSync(r'');
|
||||
androidDirectory.childFile('settings.gradle.kts').writeAsStringSync(r'''
|
||||
pluginManagement {
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
// Decoy value to ensure we ignore commented out lines.
|
||||
// id("org.jetbrains.kotlin.android") version "6.1.0" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
|
||||
}
|
||||
}
|
||||
''');
|
||||
final FakeProcessManager processManager = FakeProcessManager.empty();
|
||||
processManager.excludedExecutables = <String>{'./gradlew'};
|
||||
|
||||
expect(await getKgpVersion(androidDirectory, BufferLogger.test(), processManager), '1.8.22');
|
||||
});
|
||||
|
||||
group('validates kgp/gradle versions', () {
|
||||
final List<GradleKgpTestData> testData = <GradleKgpTestData>[
|
||||
// Values too new.
|
||||
GradleKgpTestData(true, kgpVersion: '3.0', gradleVersion: '99.99'),
|
||||
|
||||
// Template versions of Gradle/AGP.
|
||||
GradleKgpTestData(
|
||||
true,
|
||||
kgpVersion: templateKotlinGradlePluginVersion,
|
||||
// TODO(reidbaker): replace with templateDefaultGradleVersion.
|
||||
gradleVersion: '8.10',
|
||||
),
|
||||
|
||||
// Kotlin version at the edge of support window.
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.20', gradleVersion: '8.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.10', gradleVersion: '8.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.0.21', gradleVersion: '7.6.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.0.20', gradleVersion: '7.6.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.0', gradleVersion: '8.5'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.25', gradleVersion: '8.1.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.20', gradleVersion: '6.8.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.10', gradleVersion: '6.8.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.0', gradleVersion: '7.6.0'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.8.22', gradleVersion: '7.6.0'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.8.20', gradleVersion: '6.8.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.8.11', gradleVersion: '7.3.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.8.0', gradleVersion: '7.3.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.7.22', gradleVersion: '7.1.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.7.20', gradleVersion: '6.7.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.7.10', gradleVersion: '7.0.2'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.7.0', gradleVersion: '6.7.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.6.21', gradleVersion: '6.1.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.6.20', gradleVersion: '7.0.2'),
|
||||
// Gradle versions inspired by
|
||||
// https://developer.android.com/build/releases/gradle-plugin#expandable-1
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.20', gradleVersion: '8.11.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.10', gradleVersion: '8.10.2'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.10', gradleVersion: '8.9'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.5', gradleVersion: '8.7'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.0', gradleVersion: '8.7'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.0.20', gradleVersion: '8.6'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.0.1', gradleVersion: '8.4'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.0.0', gradleVersion: '8.2'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.25', gradleVersion: '8.0'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.10', gradleVersion: '7.6.0'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.7', gradleVersion: '7.5'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.8.21', gradleVersion: '7.4'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.9.0', gradleVersion: '7.3.3'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.8.0', gradleVersion: '7.2'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.7.0', gradleVersion: '7.0'),
|
||||
GradleKgpTestData(true, kgpVersion: '2.0.21', gradleVersion: '7.0'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.7.22', gradleVersion: '6.7.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.6.21', gradleVersion: '6.7.1'),
|
||||
GradleKgpTestData(true, kgpVersion: '1.6.21', gradleVersion: '6.5'),
|
||||
// Kotlin newer than max known.
|
||||
GradleKgpTestData(true, kgpVersion: '2.1.21', gradleVersion: '8.12.1'),
|
||||
// Kotlin too new for gradle version.
|
||||
GradleKgpTestData(false, kgpVersion: '2.1.20', gradleVersion: '7.6.2'),
|
||||
GradleKgpTestData(false, kgpVersion: '2.1.0', gradleVersion: '7.6.2'),
|
||||
GradleKgpTestData(false, kgpVersion: '2.0.20', gradleVersion: '6.8.2'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.9.0', gradleVersion: '6.8.2'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.8.0', gradleVersion: '6.8.2'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.7.22', gradleVersion: '6.7.0'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.7.0', gradleVersion: '6.1.1'),
|
||||
// Kotlin too old for gradle version.
|
||||
GradleKgpTestData(false, kgpVersion: '2.1.10', gradleVersion: '8.11.1'),
|
||||
GradleKgpTestData(false, kgpVersion: '2.1.0', gradleVersion: '8.11'),
|
||||
GradleKgpTestData(false, kgpVersion: '2.0.0', gradleVersion: '8.6'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.9.20', gradleVersion: '8.2'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.9.0', gradleVersion: '7.7'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.8.20', gradleVersion: '7.7'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.8.0', gradleVersion: '7.4'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.7.20', gradleVersion: '7.2'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.7.0', gradleVersion: '7.0.3'),
|
||||
GradleKgpTestData(false, kgpVersion: '1.6.20', gradleVersion: '7.0.3'),
|
||||
// Kotlin older than oldest supported.
|
||||
GradleKgpTestData(false, kgpVersion: '1.6.19', gradleVersion: '7.0.3'),
|
||||
// Gradle older than oldest supported.
|
||||
GradleKgpTestData(false, kgpVersion: '1.6.20', gradleVersion: '4.10'),
|
||||
// Null values:
|
||||
// ignore: avoid_redundant_argument_values
|
||||
GradleKgpTestData(false, kgpVersion: null, gradleVersion: '7.2'),
|
||||
// ignore: avoid_redundant_argument_values
|
||||
GradleKgpTestData(false, kgpVersion: '2.1', gradleVersion: null),
|
||||
// ignore: avoid_redundant_argument_values
|
||||
GradleKgpTestData(false, kgpVersion: '', gradleVersion: ''),
|
||||
// ignore: avoid_redundant_argument_values
|
||||
GradleKgpTestData(false, kgpVersion: null, gradleVersion: null),
|
||||
];
|
||||
for (final GradleKgpTestData data in testData) {
|
||||
test('(KGP, Gradle): (${data.kgpVersion}, ${data.gradleVersion})', () {
|
||||
expect(
|
||||
validateGradleAndKGP(
|
||||
BufferLogger.test(),
|
||||
gradleV: data.gradleVersion,
|
||||
kgpV: data.kgpVersion,
|
||||
),
|
||||
data.validPair ? isTrue : isFalse,
|
||||
reason: 'KGP: ${data.kgpVersion}, G: ${data.gradleVersion}',
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
group('validates KGP/AGP versions', () {
|
||||
final List<KgpAgpTestData> testData = <KgpAgpTestData>[
|
||||
// Values too new.
|
||||
KgpAgpTestData(true, kgpVersion: '3.0', agpVersion: '99.99'),
|
||||
|
||||
// Template versions of Gradle/AGP.
|
||||
KgpAgpTestData(
|
||||
true,
|
||||
kgpVersion: templateKotlinGradlePluginVersion,
|
||||
// TODO(reidbaker): Replace with templateAndroidGradlePluginVersion
|
||||
agpVersion: '8.7.2',
|
||||
),
|
||||
|
||||
// Kotlin version at the edge of support window.
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.20', agpVersion: '8.7.2'),
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.20', agpVersion: '7.3.1'),
|
||||
// AGP Versions not "fully supported" by kotlin
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.20', agpVersion: '8.9'),
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.20', agpVersion: '8.8'),
|
||||
// Gradle versions inspired by
|
||||
// https://developer.android.com/build/releases/gradle-plugin#expandable-1
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.5', agpVersion: '8.7'),
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.10', agpVersion: '8.6'),
|
||||
KgpAgpTestData(true, kgpVersion: '2.0.21', agpVersion: '8.5'),
|
||||
KgpAgpTestData(true, kgpVersion: '2.0.20', agpVersion: '8.4'),
|
||||
KgpAgpTestData(true, kgpVersion: '2.0', agpVersion: '8.3.1'),
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.5', agpVersion: '8.2'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.9.25', agpVersion: '8.1'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.9.20', agpVersion: '8.0'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.9.10', agpVersion: '7.4'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.8.20', agpVersion: '7.4'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.8.21', agpVersion: '7.3'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.8.11', agpVersion: '7.2.1'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.8.0', agpVersion: '7.2.1'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.8.0', agpVersion: '7.1'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.7.20', agpVersion: '7.0.4'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.7.22', agpVersion: '7.0'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.8.22', agpVersion: '4.2.0'),
|
||||
KgpAgpTestData(true, kgpVersion: '1.6.20', agpVersion: '4.1.0'),
|
||||
// Kotlin newer than max known.
|
||||
KgpAgpTestData(true, kgpVersion: '2.1.21', agpVersion: '8.7.2'),
|
||||
// Kotlin too new for AGP version.
|
||||
KgpAgpTestData(false, kgpVersion: '2.1.20', agpVersion: '7.3.0'),
|
||||
KgpAgpTestData(false, kgpVersion: '2.1.10', agpVersion: '7.3.0'),
|
||||
KgpAgpTestData(false, kgpVersion: '2.0.21', agpVersion: '7.1.2'),
|
||||
KgpAgpTestData(false, kgpVersion: '2.0.0', agpVersion: '7.1.2'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.9.25', agpVersion: '4.2.1'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.8.20', agpVersion: '4.1.2'),
|
||||
// Kotlin too old for gradle version.
|
||||
KgpAgpTestData(false, kgpVersion: '2.0.20', agpVersion: '8.7.2'),
|
||||
KgpAgpTestData(false, kgpVersion: '2.0.20', agpVersion: '8.6'),
|
||||
KgpAgpTestData(false, kgpVersion: '2.0.0', agpVersion: '8.4'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.9.20', agpVersion: '8.2'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.9.0', agpVersion: '7.5'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.8.20', agpVersion: '7.5'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.8.1', agpVersion: '7.3'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.7.20', agpVersion: '7.1'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.7.0', agpVersion: '7.0.3'),
|
||||
KgpAgpTestData(false, kgpVersion: '1.6.19', agpVersion: '7.0.3'),
|
||||
// Unknown values.
|
||||
KgpAgpTestData(
|
||||
false,
|
||||
kgpVersion: oldestDocumentedKgpCompatabilityVersion,
|
||||
agpVersion: oldestConsideredAgpVersion,
|
||||
),
|
||||
// Null values:
|
||||
// ignore: avoid_redundant_argument_values
|
||||
KgpAgpTestData(false, kgpVersion: null, agpVersion: '7.2'),
|
||||
// ignore: avoid_redundant_argument_values
|
||||
KgpAgpTestData(false, kgpVersion: '2.1', agpVersion: null),
|
||||
// ignore: avoid_redundant_argument_values
|
||||
KgpAgpTestData(false, kgpVersion: '', agpVersion: ''),
|
||||
// ignore: avoid_redundant_argument_values
|
||||
KgpAgpTestData(false, kgpVersion: null, agpVersion: null),
|
||||
];
|
||||
for (final KgpAgpTestData data in testData) {
|
||||
test('(KGP, AGP): (${data.kgpVersion}, ${data.agpVersion})', () {
|
||||
expect(
|
||||
validateAgpAndKgp(BufferLogger.test(), agpV: data.agpVersion, kgpV: data.kgpVersion),
|
||||
data.validPair ? isTrue : isFalse,
|
||||
reason: 'KGP: ${data.kgpVersion}, AGP: ${data.agpVersion}',
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
group('Parse gradle version from distribution url', () {
|
||||
testWithoutContext('null distribution url returns null version', () {
|
||||
expect(parseGradleVersionFromDistributionUrl(null), null);
|
||||
@ -1373,6 +1620,20 @@ class GradleAgpTestData {
|
||||
final bool validPair;
|
||||
}
|
||||
|
||||
class GradleKgpTestData {
|
||||
GradleKgpTestData(this.validPair, {this.gradleVersion, this.kgpVersion});
|
||||
final String? gradleVersion;
|
||||
final String? kgpVersion;
|
||||
final bool validPair;
|
||||
}
|
||||
|
||||
class KgpAgpTestData {
|
||||
KgpAgpTestData(this.validPair, {this.agpVersion, this.kgpVersion});
|
||||
final String? agpVersion;
|
||||
final String? kgpVersion;
|
||||
final bool validPair;
|
||||
}
|
||||
|
||||
class JavaGradleTestData {
|
||||
JavaGradleTestData(this.validPair, {this.javaVersion, this.gradleVersion});
|
||||
final String? gradleVersion;
|
||||
|
||||
@ -576,7 +576,7 @@ dependencies {
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
java = FakeJava(version: Version(17, 0, 2));
|
||||
processManager = FakeProcessManager.empty();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[createKgpVersionCommand('1.9.20')]);
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory.childDirectory(androidStudio.javaPath!).createSync();
|
||||
@ -604,7 +604,7 @@ dependencies {
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
java = FakeJava(version: const Version.withText(1, 8, 0, '1.8.0_242'));
|
||||
processManager = FakeProcessManager.empty();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[createKgpVersionCommand('1.7.20')]);
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory.childDirectory(androidStudio.javaPath!).createSync();
|
||||
@ -632,7 +632,7 @@ dependencies {
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.empty();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[createKgpVersionCommand('1.9.1')]);
|
||||
java = FakeJava(version: Version(11, 0, 14));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
@ -658,13 +658,14 @@ dependencies {
|
||||
const String javaV = '17.0.2';
|
||||
const String gradleV = '6.7.3';
|
||||
const String agpV = '7.2.0';
|
||||
const String kgpV = '2.1.0';
|
||||
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.empty();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[createKgpVersionCommand(kgpV)]);
|
||||
java = FakeJava(version: Version.parse(javaV));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
@ -682,7 +683,7 @@ dependencies {
|
||||
// Should not have the valid string
|
||||
expect(
|
||||
value.description,
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpString))),
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpKgpString))),
|
||||
);
|
||||
// On gradle/agp error print help url and gradle and agp versions.
|
||||
expect(value.description, contains(RegExp(AndroidProject.gradleAgpCompatUrl)));
|
||||
@ -692,6 +693,15 @@ dependencies {
|
||||
expect(value.description, contains(RegExp(AndroidProject.javaGradleCompatUrl)));
|
||||
expect(value.description, contains(RegExp(javaV)));
|
||||
expect(value.description, contains(RegExp(gradleV)));
|
||||
// On kgp/gradle eror print help url and kgp versions
|
||||
expect(value.description, contains(RegExp(kgpV)));
|
||||
expect(value.description, contains(RegExp('KGP/Gradle')));
|
||||
expect(value.description, contains(RegExp(AndroidProject.kgpCompatUrl)));
|
||||
// On agp/kgp error print help url and agp and kgp versions
|
||||
expect(value.description, contains(RegExp(agpV)));
|
||||
expect(value.description, contains(RegExp(kgpV)));
|
||||
expect(value.description, contains(RegExp('AGP/KGP')));
|
||||
expect(value.description, contains(RegExp(AndroidProject.kgpCompatUrl)));
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
@ -703,13 +713,14 @@ dependencies {
|
||||
const String javaV = '17.0.2';
|
||||
const String gradleV = '6.7.3';
|
||||
const String agpV = '4.2.0';
|
||||
const String kgpV = '1.7.22';
|
||||
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.empty();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[createKgpVersionCommand(kgpV)]);
|
||||
java = FakeJava(version: Version(17, 0, 2));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
@ -727,7 +738,7 @@ dependencies {
|
||||
// Should not have the valid string.
|
||||
expect(
|
||||
value.description,
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpString))),
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpKgpString))),
|
||||
);
|
||||
// On gradle/agp error print help url and java and gradle versions.
|
||||
expect(value.description, contains(RegExp(AndroidProject.javaGradleCompatUrl)));
|
||||
@ -747,7 +758,7 @@ dependencies {
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
java = FakeJava(version: Version(11, 0, 2));
|
||||
processManager = FakeProcessManager.empty();
|
||||
processManager = FakeProcessManager.any();
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory.childDirectory(androidStudio.javaPath!).createSync();
|
||||
@ -766,7 +777,7 @@ dependencies {
|
||||
// Should not have the valid string.
|
||||
expect(
|
||||
value.description,
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpString))),
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpKgpString))),
|
||||
);
|
||||
// On gradle/agp error print help url and gradle and agp versions.
|
||||
expect(value.description, contains(RegExp(AndroidProject.gradleAgpCompatUrl)));
|
||||
@ -779,6 +790,89 @@ dependencies {
|
||||
androidSdk: androidSdk,
|
||||
);
|
||||
});
|
||||
group('_', () {
|
||||
const String gradleV = '8.11';
|
||||
const String agpV = '8.7.2';
|
||||
const String kgpV = '2.1.10';
|
||||
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[createKgpVersionCommand(kgpV)]);
|
||||
java = FakeJava(version: Version(17, 0, 2));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory.childDirectory(androidStudio.javaPath!).createSync();
|
||||
_testInMemory(
|
||||
'incompatible kgp/gradle only',
|
||||
() async {
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: gradleV,
|
||||
agpV: agpV,
|
||||
);
|
||||
final CompatibilityResult value =
|
||||
await project!.android.hasValidJavaGradleAgpVersions();
|
||||
expect(value.success, isFalse);
|
||||
// Should not have the valid string.
|
||||
expect(
|
||||
value.description,
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpKgpString))),
|
||||
);
|
||||
// On gradle/agp error print help url and java and gradle versions.
|
||||
expect(value.description, contains(RegExp(AndroidProject.kgpCompatUrl)));
|
||||
expect(value.description, contains(RegExp(kgpV)));
|
||||
expect(value.description, contains(RegExp(gradleV)));
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
);
|
||||
});
|
||||
group('_', () {
|
||||
const String gradleV = '8.9';
|
||||
const String agpV = '8.7.2';
|
||||
const String kgpV = '2.0.20';
|
||||
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.list(<FakeCommand>[createKgpVersionCommand(kgpV)]);
|
||||
java = FakeJava(version: Version(17, 0, 2));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory.childDirectory(androidStudio.javaPath!).createSync();
|
||||
_testInMemory(
|
||||
'incompatible agp/kgp only',
|
||||
() async {
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: gradleV,
|
||||
agpV: agpV,
|
||||
);
|
||||
final CompatibilityResult value =
|
||||
await project!.android.hasValidJavaGradleAgpVersions();
|
||||
expect(value.success, isFalse);
|
||||
// Should not have the valid string.
|
||||
expect(
|
||||
value.description,
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpKgpString))),
|
||||
);
|
||||
// On gradle/agp error print help url and java and gradle versions.
|
||||
expect(value.description, contains(RegExp(kgpV)));
|
||||
expect(value.description, contains(RegExp(agpV)));
|
||||
expect(value.description, contains(RegExp('AGP/KGP')));
|
||||
expect(value.description, contains(RegExp(AndroidProject.kgpCompatUrl)));
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
);
|
||||
});
|
||||
group('_', () {
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
@ -786,7 +880,7 @@ dependencies {
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
java = FakeJava(version: Version(11, 0, 2));
|
||||
processManager = FakeProcessManager.empty();
|
||||
processManager = FakeProcessManager.any();
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk = FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory.childDirectory(androidStudio.javaPath!).createSync();
|
||||
@ -804,7 +898,7 @@ dependencies {
|
||||
// Should not have the valid string.
|
||||
expect(
|
||||
value.description,
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpString))),
|
||||
isNot(contains(RegExp(AndroidProject.validJavaGradleAgpKgpString))),
|
||||
);
|
||||
// On gradle/agp error print help url null value for agp.
|
||||
expect(value.description, contains(RegExp(AndroidProject.gradleAgpCompatUrl)));
|
||||
@ -1979,6 +2073,15 @@ flutter:
|
||||
return FlutterProject.fromDirectory(directory);
|
||||
}
|
||||
|
||||
FakeCommand createKgpVersionCommand(String kgpV) {
|
||||
return FakeCommand(
|
||||
command: const <String>['./gradlew', 'kgpVersion', '-q'],
|
||||
stdout: '''
|
||||
KGP Version: $kgpV
|
||||
''',
|
||||
);
|
||||
}
|
||||
|
||||
/// Executes the [testMethod] in a context where the file system
|
||||
/// is in memory.
|
||||
@isTest
|
||||
|
||||
@ -51,15 +51,15 @@ void main() {
|
||||
|
||||
const String expected =
|
||||
'\n'
|
||||
'┌───────────────────────────────────────────────────────────────────┐\n'
|
||||
'│ General Info │\n'
|
||||
'│ [✓] App Name: flutter_gallery │\n'
|
||||
'│ [✓] Supported Platforms: android, ios, web, macos, linux, windows │\n'
|
||||
'│ [✓] Is Flutter Package: yes │\n'
|
||||
'│ [✓] Uses Material Design: yes │\n'
|
||||
'│ [✓] Is Plugin: no │\n'
|
||||
'│ [✓] Java/Gradle/Android Gradle Plugin: ${AndroidProject.validJavaGradleAgpString} │\n'
|
||||
'└───────────────────────────────────────────────────────────────────┘\n';
|
||||
'┌───────────────────────────────────────────────────────────────────────────┐\n'
|
||||
'│ General Info │\n'
|
||||
'│ [✓] App Name: flutter_gallery │\n'
|
||||
'│ [✓] Supported Platforms: android, ios, web, macos, linux, windows │\n'
|
||||
'│ [✓] Is Flutter Package: yes │\n'
|
||||
'│ [✓] Uses Material Design: yes │\n'
|
||||
'│ [✓] Is Plugin: no │\n'
|
||||
'│ [✓] Java/Gradle/KGP/Android Gradle Plugin: ${AndroidProject.validJavaGradleAgpKgpString} │\n'
|
||||
'└───────────────────────────────────────────────────────────────────────────┘\n';
|
||||
|
||||
expect(loggerTest.statusText, contains(expected));
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user