mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-11-14 07:42:05 +08:00
fix(tooling-api): warn user if the AGP version is greater than tested version
This commit is contained in:
@@ -26,6 +26,7 @@ dependencies {
|
||||
implementation(libs.google.guava)
|
||||
implementation(libs.google.gson)
|
||||
implementation(projects.logger)
|
||||
implementation(projects.buildInfo)
|
||||
|
||||
testImplementation(libs.tests.google.truth)
|
||||
testImplementation(libs.tests.junit)
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.utils
|
||||
|
||||
import com.itsaky.androidide.buildinfo.BuildInfo
|
||||
import java.util.Objects
|
||||
|
||||
/**
|
||||
* Represents a version of the Android Gradle Plugin
|
||||
*
|
||||
* Designed for plugin authors to compare the currently running plugin version, so implements
|
||||
* comparable.
|
||||
*
|
||||
* For example `AndroidPluginVersion(7, 0)` refers to Android Gradle Plugin version 7.0.0,
|
||||
* and `AndroidPluginVersion(7, 0, 1)` refers to Android Gradle Plugin version 7.0.1.
|
||||
*
|
||||
* The internal representation is normalized, so that `AndroidPluginVersion(7, 0)` equals
|
||||
* `AndroidPluginVersion(7, 0, 0)`
|
||||
*
|
||||
* Also supports preview versions through methods [alpha], [beta] and [rc] that return the more
|
||||
* specific version. For example `AndroidPluginVersion(7, 0).alpha(5)` refers to Android Gradle
|
||||
* Plugin version 7.0.0-alpha05. This is for use when developing using incubating APIs that have
|
||||
* changed between preview releases of the Android Gradle Plugin. Once those APIs are stable in a
|
||||
* stable version of Android Gradle Plugin, it's recommended to drop support for the preview versions.
|
||||
* For example, if a new API was introduced in 7.0.0-alpha05, you can test for that using
|
||||
*
|
||||
* ```if (androidComponents.pluginVersion >= AndroidPluginVersion(7.0).alpha(5)) { ... }```
|
||||
*
|
||||
* If that API is marked as stable in 7.0.0, drop support for the preview versions before it by
|
||||
* updating your condition to:
|
||||
*
|
||||
* ```if (androidComponents.pluginVersion >= AndroidPluginVersion(7.0)) { ... }```
|
||||
*/
|
||||
class AndroidPluginVersion private constructor(
|
||||
/**
|
||||
* The major version.
|
||||
*
|
||||
* e.g. 7 for Android Gradle Plugin Version 7.0.1
|
||||
*/
|
||||
val major: Int,
|
||||
/**
|
||||
* The minor version.
|
||||
*
|
||||
* e.g. 0 for Android Gradle Plugin Version 7.0.1
|
||||
*/
|
||||
val minor: Int,
|
||||
/**
|
||||
* The micro, or patch version.
|
||||
*
|
||||
* e.g. 1 for Android Gradle Plugin Version 7.0.1
|
||||
*/
|
||||
val micro: Int,
|
||||
private val _previewType: PreviewType,
|
||||
|
||||
/**
|
||||
* The preview version.
|
||||
*
|
||||
* e.g. 5 for Android Gradle Plugin Version 7.0.0-alpha05
|
||||
*/
|
||||
val preview: Int,
|
||||
) : Comparable<AndroidPluginVersion> {
|
||||
|
||||
init {
|
||||
require(
|
||||
major >= 0 && minor >= 0 && micro >= 0) { "Versions of the Android Gradle Plugin must not be negative" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of preview version.
|
||||
*
|
||||
* Null in the case of a stable version. One of 'alpha', 'beta', 'rc', 'dev' for preview versions.
|
||||
*
|
||||
* e.g. 'alpha' for Android Gradle Plugin Version 7.0.0-alpha05
|
||||
*/
|
||||
val previewType: String? get() = _previewType.publicName
|
||||
|
||||
/**
|
||||
* Create an AndroidPluginVersion with the given major and minor version.
|
||||
*
|
||||
* For example `AndroidPluginVersion(7, 0)` refers to Android Gradle Plugin version 7.0.0.
|
||||
*/
|
||||
constructor(major: Int, minor: Int) : this(major, minor, 0, PreviewType.FINAL, 0)
|
||||
|
||||
/**
|
||||
* Create an AndroidPluginVersion with the given major, minor and micro version.
|
||||
*
|
||||
* For example `AndroidPluginVersion(7, 0, 1)` refers to Android Gradle Plugin version 7.0.1.
|
||||
*/
|
||||
constructor(major: Int, minor: Int, micro: Int) : this(major, minor, micro, PreviewType.FINAL, 0)
|
||||
|
||||
private enum class PreviewType(val publicName: String?) {
|
||||
ALPHA("alpha"),
|
||||
BETA("beta"),
|
||||
RC("rc"),
|
||||
DEV("dev"),
|
||||
FINAL(null);
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun find(publicName: String?): PreviewType {
|
||||
if (publicName.isNullOrBlank()) {
|
||||
return FINAL
|
||||
}
|
||||
|
||||
return when (publicName) {
|
||||
ALPHA.publicName -> ALPHA
|
||||
BETA.publicName -> BETA
|
||||
RC.publicName -> RC
|
||||
DEV.publicName -> DEV
|
||||
else -> throw IllegalArgumentException("Unknown preview type '$publicName'")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* From a stable [AndroidPluginVersion] returns an alpha version.
|
||||
*
|
||||
* For example `AndroidPluginVersion(7, 0).alpha(5)` refers to Android Gradle Plugin version 7.0.0-alpha05.
|
||||
*/
|
||||
fun alpha(alpha: Int): AndroidPluginVersion {
|
||||
require(
|
||||
_previewType == PreviewType.FINAL) { "alpha(int) only expected to be called on final versions" }
|
||||
require(alpha >= 1) { "Alpha version must be at least 1" }
|
||||
return AndroidPluginVersion(major, minor, micro, PreviewType.ALPHA, preview = alpha)
|
||||
}
|
||||
|
||||
/**
|
||||
* From a stable [AndroidPluginVersion] returns a beta version.
|
||||
*
|
||||
* For example `AndroidPluginVersion(7, 0).beta(2)` refers to Android Gradle Plugin version 7.0.0-beta02.
|
||||
*/
|
||||
fun beta(beta: Int): AndroidPluginVersion {
|
||||
require(
|
||||
_previewType == PreviewType.FINAL) { "beta(int) only expected to be called on final versions" }
|
||||
require(beta >= 1) { "Beta version must be at least 1" }
|
||||
return AndroidPluginVersion(major, minor, micro, PreviewType.BETA, preview = beta)
|
||||
}
|
||||
|
||||
/**
|
||||
* From a stable [AndroidPluginVersion] returns a release candidate version.
|
||||
*
|
||||
* For example `AndroidPluginVersion(7, 0).rc(1)` refers to Android Gradle Plugin version 7.0.0-rc01.
|
||||
*/
|
||||
fun rc(rc: Int): AndroidPluginVersion {
|
||||
require(
|
||||
_previewType == PreviewType.FINAL) { "rc(int) only expected to be called on final versions" }
|
||||
require(rc >= 1) { "Release candidate version must be at least 1" }
|
||||
return AndroidPluginVersion(major, minor, micro, PreviewType.RC, preview = rc)
|
||||
}
|
||||
|
||||
/**
|
||||
* From a stable [AndroidPluginVersion] specify an internal development version.
|
||||
*
|
||||
* `-dev` versions are never publicly released, but this can be useful if you are
|
||||
* building the Android Gradle Plugin from source.
|
||||
*
|
||||
* For example `AndroidPluginVersion(7, 0).dev()` refers to Android Gradle Plugin version 7.0.0-dev.
|
||||
*/
|
||||
fun dev(): AndroidPluginVersion {
|
||||
return AndroidPluginVersion(major, minor, micro, PreviewType.DEV, preview = 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new [AndroidPluginVersion] from this version with the given values updated.
|
||||
*/
|
||||
fun update(
|
||||
major: Int = this.major,
|
||||
minor: Int = this.minor,
|
||||
micro: Int = this.micro,
|
||||
previewType: String? = this.previewType,
|
||||
preview: Int = this.preview
|
||||
): AndroidPluginVersion {
|
||||
return AndroidPluginVersion(major, minor, micro, PreviewType.find(previewType), preview)
|
||||
}
|
||||
|
||||
override fun compareTo(other: AndroidPluginVersion): Int {
|
||||
return comparator.compare(this, other)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is AndroidPluginVersion &&
|
||||
major == other.major &&
|
||||
minor == other.minor &&
|
||||
micro == other.micro &&
|
||||
_previewType == other._previewType &&
|
||||
preview == other.preview
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return Objects.hash(major, minor, micro, _previewType, preview)
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
"Android Gradle Plugin version ${toStringSimple()}"
|
||||
|
||||
fun toStringSimple(): String = "$major.$minor.$micro" +
|
||||
(if (previewType != null) "-$previewType" else "") +
|
||||
(if (preview > 0) preview else "")
|
||||
|
||||
companion object {
|
||||
|
||||
private val comparator: Comparator<AndroidPluginVersion> =
|
||||
Comparator.comparingInt<AndroidPluginVersion> { it.major }
|
||||
.thenComparingInt { it.minor }
|
||||
.thenComparingInt { it.micro }
|
||||
.thenComparingInt { it._previewType.ordinal }
|
||||
.thenComparingInt { it.preview }
|
||||
|
||||
/**
|
||||
* The minimum version of Android Gradle Plugin that is supported by AndroidIDE>
|
||||
*/
|
||||
@JvmField
|
||||
val MINIMUM_SUPPORTED = parse(BuildInfo.AGP_VERSION_MININUM)
|
||||
|
||||
/**
|
||||
* The version of Android Gradle Plugin that has been known to work with AndroidIDE>
|
||||
*/
|
||||
@JvmField
|
||||
val LATEST_TESTED = parse(BuildInfo.AGP_VERSION_LATEST)
|
||||
|
||||
/**
|
||||
* Parses the given AGP version and returns the [AndroidPluginVersion] representing the same.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun parse(version: String): AndroidPluginVersion {
|
||||
require(version.isNotBlank()) {
|
||||
"Invalid input '$version'"
|
||||
}
|
||||
|
||||
val regex = """^(\d+)(?:\.(\d+)(?:\.(\d+)(?:-([a-z]+)(\d+)?)?)?)?${'$'}""".toRegex()
|
||||
val match = checkNotNull(regex.find(version)) {
|
||||
"Failed to match input '$version'"
|
||||
}
|
||||
|
||||
return match.groupValues.run {
|
||||
val int = fun(index: Int, default: Int): Int =
|
||||
if (lastIndex >= index) this[index].let { if (it.isBlank()) 0 else it.toInt() } else default
|
||||
|
||||
val str = fun(index: Int, default: String) =
|
||||
if (lastIndex >= index) this[index] else default
|
||||
|
||||
val major = this[1].toInt()
|
||||
val minor = int(2, 0)
|
||||
val micro = int(3, 0)
|
||||
val previewType = str(4, "")
|
||||
val preview = int(5, 0)
|
||||
|
||||
return@run AndroidPluginVersion(major, minor, micro, PreviewType.find(previewType), preview)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,12 @@
|
||||
|
||||
@Suppress("JavaPluginLanguageLevel")
|
||||
plugins {
|
||||
id("java-library")
|
||||
id("org.jetbrains.kotlin.jvm")
|
||||
id("java-library")
|
||||
id("org.jetbrains.kotlin.jvm")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.common.jkotlin)
|
||||
api(libs.tooling.builderModel)
|
||||
implementation(libs.common.jkotlin)
|
||||
implementation(projects.buildInfo)
|
||||
api(libs.tooling.builderModel)
|
||||
}
|
||||
@@ -55,6 +55,7 @@ project.tasks.getByName("jar") {
|
||||
project.tasks.getByName("shadowJar") { finalizedBy("copyJar") }
|
||||
|
||||
dependencies {
|
||||
implementation(projects.shared)
|
||||
implementation(projects.subprojects.toolingApi)
|
||||
|
||||
implementation(libs.common.jkotlin)
|
||||
|
||||
-2
@@ -19,7 +19,6 @@ package com.itsaky.androidide.tooling.impl;
|
||||
|
||||
import static com.itsaky.androidide.utils.ILogger.newInstance;
|
||||
|
||||
import com.itsaky.androidide.buildinfo.BuildInfo;
|
||||
import com.itsaky.androidide.models.LogLine;
|
||||
import com.itsaky.androidide.tooling.api.IToolingApiClient;
|
||||
import com.itsaky.androidide.tooling.api.util.ToolingApiLauncher;
|
||||
@@ -39,7 +38,6 @@ import org.gradle.tooling.events.OperationType;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static final String MIN_SUPPORTED_AGP_VERSION = BuildInfo.AGP_VERSION_MININUM;
|
||||
private static final ILogger LOG = newInstance("ToolingApiMain");
|
||||
public static IToolingApiClient client;
|
||||
public static Future<Void> future;
|
||||
|
||||
+34
-10
@@ -18,8 +18,10 @@ package com.itsaky.androidide.tooling.impl.sync
|
||||
|
||||
import com.android.builder.model.v2.models.Versions
|
||||
import com.itsaky.androidide.tooling.api.messages.InitializeProjectParams
|
||||
import com.itsaky.androidide.tooling.impl.Main
|
||||
import com.itsaky.androidide.tooling.impl.util.StopWatch
|
||||
import com.itsaky.androidide.utils.AndroidPluginVersion
|
||||
import com.itsaky.androidide.utils.AndroidPluginVersion.Companion.LATEST_TESTED
|
||||
import com.itsaky.androidide.utils.AndroidPluginVersion.Companion.MINIMUM_SUPPORTED
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.LogUtils
|
||||
import org.gradle.api.Action
|
||||
@@ -27,6 +29,7 @@ import org.gradle.tooling.BuildController
|
||||
import org.gradle.tooling.UnknownModelException
|
||||
import org.gradle.tooling.UnsupportedVersionException
|
||||
import org.gradle.tooling.model.Model
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* Abstract class for [IModelBuilder] implementations.
|
||||
@@ -40,23 +43,44 @@ abstract class AbstractModelBuilder<P, R>(
|
||||
|
||||
companion object {
|
||||
|
||||
private val newerAgpWarned = AtomicBoolean(false)
|
||||
|
||||
/**
|
||||
* Checks the Android Gradle Plugin version from the given [Versions] model and compares
|
||||
* it with [Main.MIN_SUPPORTED_AGP_VERSION]. If the version is less than the [Main.MIN_SUPPORTED_AGP_VERSION],
|
||||
* throws an [UnsupportedOperationException].
|
||||
* it with [AndroidPluginVersion.MINIMUM_SUPPORTED] and [AndroidPluginVersion.LATEST_TESTED].
|
||||
*
|
||||
* If the version is less than the [AndroidPluginVersion.MINIMUM_SUPPORTED],
|
||||
* throws an [UnsupportedOperationException]. If the version is greater than the
|
||||
* [AndroidPluginVersion.LATEST_TESTED], warns the user.
|
||||
*
|
||||
* @param versions The [Versions] model.
|
||||
*/
|
||||
@JvmStatic
|
||||
protected fun assertMinimumAgp(versions: Versions) {
|
||||
if (versions.agp < Main.MIN_SUPPORTED_AGP_VERSION) {
|
||||
protected fun checkAgpVersion(versions: Versions) {
|
||||
|
||||
val agpVersion = AndroidPluginVersion.parse(versions.agp)
|
||||
|
||||
// The build should fail if the user is using an older version of AGP
|
||||
if (agpVersion < MINIMUM_SUPPORTED) {
|
||||
throw ModelBuilderException(
|
||||
"Android Gradle Plugin version "
|
||||
+ versions.agp
|
||||
agpVersion.toString()
|
||||
+ " is not supported by AndroidIDE. "
|
||||
+ "Please update your project to use at least v"
|
||||
+ Main.MIN_SUPPORTED_AGP_VERSION
|
||||
+ " of Android Gradle Plugin to build this project.")
|
||||
+ "Please update your project to use at least "
|
||||
+ MINIMUM_SUPPORTED
|
||||
+ " to build this project.")
|
||||
}
|
||||
|
||||
// Warn the user if the project is using a newer AGP version
|
||||
if (!newerAgpWarned.get() && agpVersion > LATEST_TESTED) {
|
||||
log()
|
||||
log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
log("You are using Android Gradle Plugin version that has not been tested with AndroidIDE.")
|
||||
log("Newer versions may not work properly!")
|
||||
log("Current version : ${agpVersion.toStringSimple()}")
|
||||
log("Latest tested : ${LATEST_TESTED.toStringSimple()}")
|
||||
log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
log()
|
||||
newerAgpWarned.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -31,6 +31,7 @@ class ModuleProjectModelBuilder(initializationParams: InitializeProjectParams) :
|
||||
override fun build(param: ModuleProjectModelBuilderParams): IModuleProject {
|
||||
val versions = getAndroidVersions(param.module, param.controller)
|
||||
return if (versions != null) {
|
||||
checkAgpVersion(versions)
|
||||
AndroidProjectModelBuilder(initializationParams)
|
||||
.build(Triple(param.controller, param.module, versions))
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class RootModelBuilder(initializationParams: InitializeProjectParams) :
|
||||
|
||||
val rootProject = if (rootProjectVersions != null) {
|
||||
// Root project is an Android project
|
||||
assertMinimumAgp(rootProjectVersions)
|
||||
checkAgpVersion(rootProjectVersions)
|
||||
AndroidProjectModelBuilder(initializationParams).build(Triple(controller, rootModule, rootProjectVersions))
|
||||
} else {
|
||||
GradleProjectModelBuilder(initializationParams).build(rootModule.gradleProject)
|
||||
|
||||
+65
-9
@@ -20,12 +20,14 @@ package com.itsaky.androidide.tooling.impl
|
||||
import com.android.builder.model.v2.ide.LibraryType
|
||||
import com.android.builder.model.v2.ide.ProjectType.APPLICATION
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.itsaky.androidide.buildinfo.BuildInfo
|
||||
import com.itsaky.androidide.tooling.api.IAndroidProject
|
||||
import com.itsaky.androidide.tooling.api.IJavaProject
|
||||
import com.itsaky.androidide.tooling.api.IProject
|
||||
import com.itsaky.androidide.tooling.api.IToolingApiServer
|
||||
import com.itsaky.androidide.tooling.api.ProjectType
|
||||
import com.itsaky.androidide.tooling.api.messages.InitializeProjectParams
|
||||
import com.itsaky.androidide.tooling.api.messages.result.InitializeResult
|
||||
import com.itsaky.androidide.tooling.api.models.AndroidProjectMetadata
|
||||
import com.itsaky.androidide.tooling.api.models.JavaModuleExternalDependency
|
||||
import com.itsaky.androidide.tooling.api.models.JavaModuleProjectDependency
|
||||
@@ -34,6 +36,7 @@ import com.itsaky.androidide.tooling.api.models.params.StringParameter
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher.MultiVersionTestClient
|
||||
import com.itsaky.androidide.utils.FileProvider
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
@@ -47,7 +50,7 @@ class MultiModuleAndroidProjectTest {
|
||||
@Test
|
||||
fun `test simple multi module project initialization`() {
|
||||
val (server, project) = ToolingApiTestLauncher().launchServer()
|
||||
server.initialize(InitializeProjectParams(FileProvider.testProjectRoot().pathString)).get()
|
||||
server.initializeTestProject()
|
||||
doAssertions(project, server)
|
||||
}
|
||||
|
||||
@@ -69,7 +72,7 @@ class MultiModuleAndroidProjectTest {
|
||||
|
||||
val app = project.asAndroidProject()
|
||||
assertThat(app).isNotNull()
|
||||
assertThat(app!!).isInstanceOf(IAndroidProject::class.java)
|
||||
assertThat(app).isInstanceOf(IAndroidProject::class.java)
|
||||
|
||||
var metadata = app.getMetadata().get() as AndroidProjectMetadata
|
||||
assertThat(metadata).isNotNull()
|
||||
@@ -107,7 +110,7 @@ class MultiModuleAndroidProjectTest {
|
||||
|
||||
val androidLib = project.asAndroidProject()
|
||||
assertThat(androidLib).isNotNull()
|
||||
assertThat(androidLib!!).isInstanceOf(IAndroidProject::class.java)
|
||||
assertThat(androidLib).isInstanceOf(IAndroidProject::class.java)
|
||||
// Make sure that transitive dependencies are included here because :android-library includes
|
||||
// :java-library project which further includes :another-java-libraries project with 'api'
|
||||
// configuration
|
||||
@@ -130,7 +133,7 @@ class MultiModuleAndroidProjectTest {
|
||||
|
||||
val javaLibrary = project.asJavaProject()
|
||||
assertThat(javaLibrary).isNotNull()
|
||||
assertThat(javaLibrary!!).isInstanceOf(IJavaProject::class.java)
|
||||
assertThat(javaLibrary).isInstanceOf(IJavaProject::class.java)
|
||||
|
||||
var javaMetadata = javaLibrary.getMetadata().get() as JavaProjectMetadata
|
||||
assertThat(javaMetadata.compilerSettings.javaSourceVersion).isEqualTo("11")
|
||||
@@ -162,14 +165,15 @@ class MultiModuleAndroidProjectTest {
|
||||
.filter { it.moduleName.endsWith("nested-java-library") }
|
||||
assertThat(nested).hasSize(2)
|
||||
assertThat(nested[0].projectPath).isNotEqualTo(nested[1].projectPath)
|
||||
assertThat(project.selectProject(StringParameter(":does-not-exist")).get().isSuccessful).isFalse()
|
||||
assertThat(
|
||||
project.selectProject(StringParameter(":does-not-exist")).get().isSuccessful).isFalse()
|
||||
|
||||
selectionResult = project.selectProject(StringParameter(":another-java-library")).get()
|
||||
assertThat(selectionResult.isSuccessful).isTrue()
|
||||
|
||||
val anotherJavaLib = project.asJavaProject()
|
||||
assertThat(anotherJavaLib).isNotNull()
|
||||
assertThat(anotherJavaLib!!).isInstanceOf(IJavaProject::class.java)
|
||||
assertThat(anotherJavaLib).isInstanceOf(IJavaProject::class.java)
|
||||
|
||||
javaMetadata = anotherJavaLib.getMetadata().get() as JavaProjectMetadata
|
||||
assertThat(javaMetadata.compilerSettings.javaSourceVersion).isEqualTo("1.8")
|
||||
@@ -188,8 +192,8 @@ class MultiModuleAndroidProjectTest {
|
||||
val versions =
|
||||
listOf(
|
||||
// AGP to Gradle
|
||||
"7.2.0" to "7.3.3",
|
||||
"8.0.2" to "8.2"
|
||||
BuildInfo.AGP_VERSION_MININUM to "7.3.3",
|
||||
BuildInfo.AGP_VERSION_LATEST to "8.2"
|
||||
)
|
||||
|
||||
val client = MultiVersionTestClient()
|
||||
@@ -197,13 +201,48 @@ class MultiModuleAndroidProjectTest {
|
||||
client.agpVersion = agpVersion
|
||||
client.gradleVersion = gradleVersion
|
||||
val (server, project) = ToolingApiTestLauncher().launchServer(client = client)
|
||||
server.initialize(InitializeProjectParams(FileProvider.testProjectRoot().pathString)).get()
|
||||
server.initializeTestProject()
|
||||
doAssertions(project = project, server = server)
|
||||
FileProvider.testProjectRoot().resolve(MultiVersionTestClient.buildFile).deleteExisting()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(CIOnlyException::class)
|
||||
fun `test CI-only latest tested AGP version warning`() {
|
||||
val log = CollectingLogger()
|
||||
val agpVersion = "8.1.1"
|
||||
val client = MultiVersionTestClient(agpVersion = agpVersion, gradleVersion = "8.2", log = log)
|
||||
val (server, _) = ToolingApiTestLauncher().launchServer(client = client, log = log)
|
||||
val result = server.initializeTestProject()
|
||||
val output = log.toString()
|
||||
|
||||
if (result?.isSuccessful != true) {
|
||||
// print the output if the initialization fails
|
||||
println(output)
|
||||
}
|
||||
|
||||
assertThat(result?.isSuccessful).isTrue()
|
||||
assertThat(output).contains(
|
||||
"You are using Android Gradle Plugin version that has not been tested with AndroidIDE.")
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(CIOnlyException::class)
|
||||
fun `test CI-only minimum AGP version failure`() {
|
||||
val log = CollectingLogger()
|
||||
val agpVersion = "7.1.0"
|
||||
val client = MultiVersionTestClient(agpVersion = agpVersion, log = log)
|
||||
val (server, _) = ToolingApiTestLauncher().launchServer(client = client, log = log)
|
||||
val result = server.initializeTestProject()
|
||||
assertThat(result?.isSuccessful).isFalse()
|
||||
|
||||
val output = log.toString()
|
||||
assertThat(output).contains(
|
||||
"Android Gradle Plugin version $agpVersion is not supported by AndroidIDE.")
|
||||
}
|
||||
|
||||
private fun ciOnlyTest(test: () -> Unit) {
|
||||
try {
|
||||
assertIsCI()
|
||||
@@ -225,5 +264,22 @@ class MultiModuleAndroidProjectTest {
|
||||
return System.getenv("TEST_TOOLING_API_IMPL").let { it == "true" }
|
||||
}
|
||||
|
||||
private fun IToolingApiServer.initializeTestProject(): InitializeResult? {
|
||||
return initialize(InitializeProjectParams(FileProvider.testProjectRoot().pathString)).get()
|
||||
}
|
||||
|
||||
internal class CollectingLogger() : ILogger(CollectingLogger::class.simpleName) {
|
||||
|
||||
private val string = StringBuilder()
|
||||
|
||||
override fun doLog(priority: Priority?, message: String?) {
|
||||
string.append("${message?.trim()}${System.lineSeparator()}")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return string.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private class CIOnlyException : IllegalStateException()
|
||||
}
|
||||
|
||||
+16
-8
@@ -62,6 +62,7 @@ class ToolingApiTestLauncher {
|
||||
|
||||
fun launchServer(
|
||||
client: IToolingApiClient = MultiVersionTestClient(),
|
||||
log: ILogger = ILogger.newInstance("BuildOutputLogger")
|
||||
): Pair<IToolingApiServer, IProject> {
|
||||
val builder = ProcessBuilder(createProcessCmd(FileProvider.implModule()
|
||||
.resolve("build/libs/tooling-api-all.jar").pathString))
|
||||
@@ -71,7 +72,7 @@ class ToolingApiTestLauncher {
|
||||
builder.environment()["ANDROID_HOME"] = androidHome
|
||||
val proc = builder.start()
|
||||
|
||||
Thread(Reader(proc.errorStream)).start()
|
||||
Thread(Reader(proc.errorStream, log)).start()
|
||||
val launcher =
|
||||
ToolingApiLauncher.newClientLauncher(client, proc.inputStream,
|
||||
proc.outputStream)
|
||||
@@ -113,7 +114,8 @@ class ToolingApiTestLauncher {
|
||||
class MultiVersionTestClient(
|
||||
private val projectDir: Path = FileProvider.testProjectRoot(),
|
||||
var agpVersion: String = DEFAULT_AGP_VERSION,
|
||||
var gradleVersion: String = DEFAULT_GRADLE_VERSION
|
||||
var gradleVersion: String = DEFAULT_GRADLE_VERSION,
|
||||
val log: ILogger = ILogger.newInstance(MultiVersionTestClient::class.simpleName)
|
||||
) : IToolingApiClient {
|
||||
|
||||
companion object {
|
||||
@@ -129,8 +131,6 @@ class ToolingApiTestLauncher {
|
||||
|
||||
const val GENERATED_FILE_WARNING =
|
||||
"DO NOT EDIT - Automatically generated file"
|
||||
|
||||
private val log = ILogger.newInstance("MultiVersionTestClient")
|
||||
}
|
||||
|
||||
override fun logMessage(line: LogLine) {
|
||||
@@ -156,8 +156,17 @@ class ToolingApiTestLauncher {
|
||||
candidate = "@@GRADLE_VERSION@@" to this.gradleVersion)
|
||||
}
|
||||
|
||||
override fun onBuildSuccessful(result: BuildResult) {}
|
||||
override fun onBuildFailed(result: BuildResult) {}
|
||||
override fun onBuildSuccessful(result: BuildResult) {
|
||||
onBuildResult(result)
|
||||
}
|
||||
override fun onBuildFailed(result: BuildResult) {
|
||||
onBuildResult(result)
|
||||
}
|
||||
|
||||
private fun onBuildResult(result: BuildResult) {
|
||||
projectDir.resolve(buildFile).deleteIfExists()
|
||||
projectDir.resolve(gradlewProps).deleteIfExists()
|
||||
}
|
||||
|
||||
override fun onProgressEvent(event: ProgressEvent) {}
|
||||
|
||||
@@ -199,9 +208,8 @@ class ToolingApiTestLauncher {
|
||||
}
|
||||
}
|
||||
|
||||
private class Reader(val input: InputStream) : Runnable {
|
||||
private class Reader(val input: InputStream, val log: ILogger) : Runnable {
|
||||
|
||||
private val log = ILogger.newInstance(javaClass.simpleName)
|
||||
override fun run() {
|
||||
try {
|
||||
val reader = BufferedReader(InputStreamReader(input))
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// DO NOT EDIT - Automatically generated file
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
build_gradle_version = "7.2.0"
|
||||
}
|
||||
|
||||
project.ext {
|
||||
compileSdk = 31
|
||||
buildTools = "31.0.0"
|
||||
appId = "com.itsaky.test.app"
|
||||
minSdk = 21
|
||||
targetSdk = 32
|
||||
versionCode = 100
|
||||
versionName = "1.0.0"
|
||||
}
|
||||
|
||||
repositories {
|
||||
google ()
|
||||
mavenLocal ()
|
||||
mavenCentral ()
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:$build_gradle_version"
|
||||
}
|
||||
|
||||
}
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenLocal ()
|
||||
mavenCentral ()
|
||||
google ()
|
||||
}
|
||||
}
|
||||
|
||||
task clean (type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
Reference in New Issue
Block a user