diff --git a/shared/src/main/java/com/itsaky/androidide/utils/AndroidPluginVersion.kt b/shared/src/main/java/com/itsaky/androidide/utils/AndroidPluginVersion.kt index 9905421f5..ebeb1827e 100644 --- a/shared/src/main/java/com/itsaky/androidide/utils/AndroidPluginVersion.kt +++ b/shared/src/main/java/com/itsaky/androidide/utils/AndroidPluginVersion.kt @@ -228,7 +228,7 @@ class AndroidPluginVersion private constructor( fun toStringSimple(): String = "$major.$minor.$micro" + (if (previewType != null) "-$previewType" else "") + - (if (preview > 0) preview else "") + (if (preview > 0) if(preview < 10) "0$preview" else preview else "") companion object { diff --git a/subprojects/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/sync/AbstractModelBuilder.kt b/subprojects/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/sync/AbstractModelBuilder.kt index db6ab14d4..102500ad2 100644 --- a/subprojects/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/sync/AbstractModelBuilder.kt +++ b/subprojects/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/sync/AbstractModelBuilder.kt @@ -22,8 +22,8 @@ import com.itsaky.androidide.builder.model.DefaultSyncIssue import com.itsaky.androidide.builder.model.IDESyncIssue import com.itsaky.androidide.tooling.api.messages.InitializeProjectParams import com.itsaky.androidide.tooling.impl.util.StopWatch +import com.itsaky.androidide.tooling.impl.util.ToolingProps 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 @@ -78,9 +78,9 @@ abstract class AbstractModelBuilder( } // Warn the user if the project is using a newer AGP version - if (!newerAgpWarned.get() && agpVersion > LATEST_TESTED) { + if (!newerAgpWarned.get() && agpVersion > ToolingProps.latestTestedAgpVersion) { val syncIssue = DefaultSyncIssue( - data = "${agpVersion.toStringSimple()}:${LATEST_TESTED.toStringSimple()}", + data = "${agpVersion.toStringSimple()}:${ToolingProps.latestTestedAgpVersion.toStringSimple()}", message = "You are using Android Gradle Plugin version that has not been tested with AndroidIDE.", multiLineMessage = null, severity = SyncIssue.SEVERITY_WARNING, diff --git a/subprojects/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/ToolingProps.kt b/subprojects/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/ToolingProps.kt new file mode 100644 index 000000000..353bfcb89 --- /dev/null +++ b/subprojects/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/ToolingProps.kt @@ -0,0 +1,45 @@ +/* + * 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 . + */ + +package com.itsaky.androidide.tooling.impl.util + +import com.itsaky.androidide.utils.AndroidPluginVersion + +/** + * System properties for configuring the toolign API. + * + * @author Akash Yadav + */ +object ToolingProps { + + val TESTING_IS_TEST_ENV = propName("testing", "isTestEnv") + val TESTING_LATEST_AGP_VERSION = propName("testing", "latestAgpVersion") + + val isTestEnv: Boolean + get() = System.getProperty(TESTING_IS_TEST_ENV).toBoolean() + + val latestTestedAgpVersion: AndroidPluginVersion + get() { + if (!isTestEnv) { + return AndroidPluginVersion.LATEST_TESTED + } + return System.getProperty(TESTING_LATEST_AGP_VERSION)?.let { AndroidPluginVersion.parse(it) } + ?: AndroidPluginVersion.LATEST_TESTED + } + + fun propName(cat: String, name: String) = "ide.tooling.$cat.$name" +} \ No newline at end of file diff --git a/subprojects/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/MultiModuleAndroidProjectTest.kt b/subprojects/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/MultiModuleAndroidProjectTest.kt index b715050e2..9d3b52547 100644 --- a/subprojects/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/MultiModuleAndroidProjectTest.kt +++ b/subprojects/tooling-api-impl/src/test/java/com/itsaky/androidide/tooling/impl/MultiModuleAndroidProjectTest.kt @@ -36,8 +36,10 @@ import com.itsaky.androidide.tooling.api.models.JavaProjectMetadata import com.itsaky.androidide.tooling.api.models.params.StringParameter import com.itsaky.androidide.tooling.events.ProgressEvent import com.itsaky.androidide.tooling.events.task.TaskStartEvent +import com.itsaky.androidide.tooling.impl.util.ToolingProps import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher.MultiVersionTestClient +import com.itsaky.androidide.utils.AndroidPluginVersion import com.itsaky.androidide.utils.FileProvider import com.itsaky.androidide.utils.ILogger import org.junit.Test @@ -45,8 +47,10 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import java.nio.file.Paths import java.util.concurrent.CompletableFuture +import kotlin.io.path.createDirectory import kotlin.io.path.createFile import kotlin.io.path.deleteIfExists +import kotlin.io.path.exists /** @author Akash Yadav */ @RunWith(JUnit4::class) @@ -69,7 +73,8 @@ class MultiModuleAndroidProjectTest { @Test fun `test project initialization with file path`() { - val path = FileProvider.projectRoot().resolve("build").resolve("should-be-directory.txt") + val path = FileProvider.projectRoot().resolve("build") + .also { if (!it.exists()) it.createDirectory() }.resolve("should-be-directory.txt") path.deleteIfExists() path.createFile() @@ -294,9 +299,16 @@ class MultiModuleAndroidProjectTest { fun `test CI-only latest tested AGP version warning`() { ciOnlyTest { val log = CollectingLogger() - val agpVersion = "8.1.1" - val client = MultiVersionTestClient(agpVersion = agpVersion, gradleVersion = "8.1", log = log) - val (_, project, result) = ToolingApiTestLauncher().launchServer(client = client, log = log) + val agpVersion = AndroidPluginVersion.parse(BuildInfo.AGP_VERSION_LATEST) + + val client = MultiVersionTestClient(agpVersion = agpVersion.toStringSimple(), + gradleVersion = "${agpVersion.major}.${agpVersion.minor}", log = log) + val (_, project, result) = ToolingApiTestLauncher().launchServer( + client = client, + log = log, + sysProps = mapOf( + ToolingProps.TESTING_LATEST_AGP_VERSION to MultiVersionTestClient.DEFAULT_AGP_VERSION) + ) val output = log.toString() if (result?.isSuccessful != true) { diff --git a/testing/tooling/src/main/java/com/itsaky/androidide/tooling/testing/ToolingApiTestLauncher.kt b/testing/tooling/src/main/java/com/itsaky/androidide/tooling/testing/ToolingApiTestLauncher.kt index 6f9f2fa3c..fddc0b37b 100644 --- a/testing/tooling/src/main/java/com/itsaky/androidide/tooling/testing/ToolingApiTestLauncher.kt +++ b/testing/tooling/src/main/java/com/itsaky/androidide/tooling/testing/ToolingApiTestLauncher.kt @@ -30,6 +30,7 @@ import com.itsaky.androidide.tooling.api.messages.result.InitializeResult import com.itsaky.androidide.tooling.api.messages.toLogLine import com.itsaky.androidide.tooling.api.util.ToolingApiLauncher import com.itsaky.androidide.tooling.events.ProgressEvent +import com.itsaky.androidide.tooling.impl.util.ToolingProps import com.itsaky.androidide.utils.FileProvider import com.itsaky.androidide.utils.ILogger import java.io.BufferedReader @@ -72,14 +73,23 @@ class ToolingApiTestLauncher { projectDir.pathString, client.gradleDistParams ), - log: ILogger = ILogger.newInstance("BuildOutputLogger") + log: ILogger = ILogger.newInstance("BuildOutputLogger"), + sysProps: Map = emptyMap(), + sysEnvs: Map = emptyMap() ): Triple { - val builder = ProcessBuilder(createProcessCmd(FileProvider.implModule() - .resolve("build/libs/tooling-api-all.jar").pathString)) + val cmdLine = createProcessCmd( + FileProvider.implModule() + .resolve("build/libs/tooling-api-all.jar").pathString, + sysProps + ) + + val builder = ProcessBuilder(cmdLine) val androidHome = findAndroidHome() - println("ANDROID_HOME=$androidHome") + builder.environment()["ANDROID_SDK_ROOT"] = androidHome builder.environment()["ANDROID_HOME"] = androidHome + builder.environment().putAll(sysEnvs) + val proc = builder.start() Thread(Reader(proc.errorStream, log)).start() @@ -95,7 +105,10 @@ class ToolingApiTestLauncher { return Triple(server, project, result) } - private fun createProcessCmd(jar: String): List { + private fun createProcessCmd( + jar: String, + sysProps: Map = emptyMap() + ): List { val cmd = mutableListOf("java") System.getenv("JAVA_HOME")?.let { val java = File(it, "bin/java") @@ -116,6 +129,12 @@ class ToolingApiTestLauncher { cmd.add("--add-exports=${export.key}/${export.value}=ALL-UNNAMED") } + cmd.add("-D${ToolingProps.TESTING_IS_TEST_ENV}=true") + + sysProps.forEach { (key, value) -> + cmd.add("-D$key=$value") + } + Collections.addAll(cmd, "-jar", jar) println( @@ -129,7 +148,7 @@ class ToolingApiTestLauncher { var agpVersion: String = DEFAULT_AGP_VERSION, var gradleVersion: String = DEFAULT_GRADLE_VERSION, private val log: ILogger = ILogger.newInstance(MultiVersionTestClient::class.simpleName), - private val extraArgs : List = emptyList(), + private val extraArgs: List = emptyList(), private var excludeUnresolvedDependency: Boolean = false ) : IToolingApiClient { @@ -193,7 +212,8 @@ class ToolingApiTestLauncher { override fun onProgressEvent(event: ProgressEvent) {} override fun getBuildArguments(): CompletableFuture> { - return CompletableFuture.completedFuture(mutableListOf("--stacktrace", "--info").also { it.addAll(extraArgs) }) + return CompletableFuture.completedFuture( + mutableListOf("--stacktrace", "--info").also { it.addAll(extraArgs) }) } override fun checkGradleWrapperAvailability(): CompletableFuture =