Removed the fixed AGP version restriction in Tooling API implementation

This commit is contained in:
Akash Yadav
2022-06-22 18:03:08 +05:30
parent 16be7f7961
commit c8bdc40e6f
9 changed files with 144 additions and 143 deletions
Binary file not shown.
@@ -86,13 +86,4 @@ compileTestKotlin {
kotlinOptions {
jvmTarget = "11"
}
}
test {
doFirst {
systemProperty "test.android.home", System.getenv ("ANDROID_HOME")
// jvmArgs '--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED'
}
println jvmArgs
}
@@ -37,7 +37,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class Main {
public static final String SUPPORTED_AGP_VERSION = "@AGP_VERSION@";
public static final String MIN_SUPPORTED_AGP_VERSION = "@AGP_VERSION@";
private static final ILogger LOG = newInstance("ToolingApiMain");
public static IToolingApiClient client;
public static Future<Void> future;
@@ -199,13 +199,14 @@ public class ProjectReader {
return null;
}
if (!versions.getAgp().equals(Main.SUPPORTED_AGP_VERSION)) {
if (versions.getAgp().compareTo(Main.MIN_SUPPORTED_AGP_VERSION) < 0) {
throw new UnsupportedOperationException(
"Android Gradle Plugin version "
+ versions.getAgp()
+ " is not supported by AndroidIDE. Please use version "
+ Main.SUPPORTED_AGP_VERSION
+ " to build this project.");
+ " 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.");
}
final var basicAndroid = controller.findModel(gradle, BasicAndroidProject.class);
@@ -213,7 +214,7 @@ public class ProjectReader {
System.err.println("Fetching project model...");
final var android = controller.findModel(gradle, AndroidProject.class);
final var module = buildAndroidModuleProject(gradle, android, basicAndroid.getProjectType());
module.setBootClassPaths (basicAndroid.getBootClasspath());
module.setBootClassPaths(basicAndroid.getBootClasspath());
module.setMainSourceSet(
basicAndroid.getMainSourceSet() == null
? null
@@ -46,136 +46,153 @@ import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class ToolingApiImplTest {
private val log = ILogger.newInstance(javaClass.simpleName)
@Test
fun testProjectInit() {
val client = TestClient()
val (server, project) = launchServer(client)
server.initialize(InitializeProjectMessage(getTestProject().absolutePath)).get()
verifyProjectProps(project, server)
}
private fun verifyProjectProps(project: IProject, server: IToolingApiServer) {
assertThat(project).isNotNull()
assertThat(project.type.get()).isEqualTo(IProject.Type.Gradle)
// As the returned project is just a proxy,
// project instanceOf IdeGradleProject will always return false
val isInitialized = server.isServerInitialized().get()
assertThat(isInitialized).isTrue()
val app = project.findByPath(":app").get()
assertThat(app).isNotNull()
assertThat(app).isInstanceOf(IdeAndroidModule::class.java)
assertThat((app as IdeAndroidModule).javaCompileOptions).isNotNull()
assertThat(app.javaCompileOptions.sourceCompatibility).isEqualTo("11")
assertThat(app.javaCompileOptions.targetCompatibility).isEqualTo("11")
assertThat(app.javaCompileOptions.isCoreLibraryDesugaringEnabled).isFalse()
assertThat(app.projectType).isEqualTo(APPLICATION)
assertThat(app.packageName).isEqualTo("com.itsaky.test.app")
assertThat(app.viewBindingOptions).isNotNull()
assertThat(app.viewBindingOptions!!.isEnabled).isTrue()
// There are always more than 100 tasks in an android module
// Also, the tasks must contain the user defined tasks
assertThat(app.tasks.size).isAtLeast(100)
assertThat(app.tasks.first { it.path == "${app.projectPath}:thisIsATestTask" }).isNotNull()
// This is not expected to be filled. Instead debugLibraries must be filled
@Suppress("DEPRECATION") assertThat(app.variantDependencies).isEmpty()
assertThat(app.debugLibraries).isNotEmpty()
// At least one project library
assertThat(app.debugLibraries.filter { it.type == PROJECT }).isNotEmpty()
val javaLibrary = project.findByPath(":java-library").get()
assertThat(javaLibrary).isNotNull()
assertThat(javaLibrary).isInstanceOf(IdeJavaModule::class.java)
assertThat(project.findByPath(":does-not-exist").get()).isNull()
}
private fun launchServer(client: IToolingApiClient): Pair<IToolingApiServer, IProject> {
val builder =
ProcessBuilder(
"java",
"--add-opens",
"java.base/java.lang=ALL-UNNAMED",
"--add-opens",
"java.base/java.util=ALL-UNNAMED",
"--add-opens",
"java.base/java.io=ALL-UNNAMED",
"-jar",
"./build/libs/tooling-api-all.jar"
)
val androidHome = findAndroidHome()
println("ANDROID_HOME=$androidHome")
builder.environment()["ANDROID_SDK_ROOT"] = androidHome
builder.environment()["ANDROID_HOME"] = androidHome
val proc = builder.start()
Thread(Reader(proc.errorStream)).start()
val launcher = ToolingApiLauncher.newClientLauncher(client, proc.inputStream, proc.outputStream)
launcher.startListening()
return launcher.remoteProxy as IToolingApiServer to launcher.remoteProxy as IProject
}
private fun findAndroidHome(): String {
var androidHome = System.getenv("ANDROID_HOME")
if (androidHome != null && androidHome.isNotBlank()) {
return androidHome
}
androidHome = System.getenv("ANDROID_SDK_ROOT")
if (androidHome != null && androidHome.isNotBlank()) {
return androidHome
}
val os = System.getProperty("os.name")
val home = System.getProperty("user.home")
return if (os.contains("Linux")) {
"$home/Android/Sdk"
} else {
"$home\\AppData\\Local\\Android\\Sdk"
}
}
private class TestClient : IToolingApiClient {
private val log = ILogger.newInstance(javaClass.simpleName)
@Test
fun testProjectInit() {
val client = TestClient()
val (server, project) = launchServer(client)
server.initialize(InitializeProjectMessage(getTestProject().absolutePath)).get()
verifyProjectProps(project, server)
override fun logMessage(line: LogLine) {
log.log(line.priority, line.formattedTagAndMessage())
}
private fun verifyProjectProps(project: IProject, server: IToolingApiServer) {
assertThat(project).isNotNull()
assertThat(project.type.get()).isEqualTo(IProject.Type.Gradle)
// As the returned project is just a proxy,
// project instanceOf IdeGradleProject will always return false
val isInitialized = server.isServerInitialized().get()
assertThat(isInitialized).isTrue()
val app = project.findByPath(":app").get()
assertThat(app).isNotNull()
assertThat(app).isInstanceOf(IdeAndroidModule::class.java)
assertThat((app as IdeAndroidModule).javaCompileOptions).isNotNull()
assertThat(app.javaCompileOptions.sourceCompatibility).isEqualTo("11")
assertThat(app.javaCompileOptions.targetCompatibility).isEqualTo("11")
assertThat(app.javaCompileOptions.isCoreLibraryDesugaringEnabled).isFalse()
assertThat(app.projectType).isEqualTo(APPLICATION)
assertThat(app.packageName).isEqualTo("com.itsaky.test.app")
assertThat(app.viewBindingOptions).isNotNull()
assertThat(app.viewBindingOptions!!.isEnabled).isTrue()
// There are always more than 100 tasks in an android module
// Also, the tasks must contain the user defined tasks
assertThat(app.tasks.size).isAtLeast(100)
assertThat(app.tasks.first { it.path == "${app.projectPath}:thisIsATestTask" }).isNotNull()
// This is not expected to be filled. Instead debugLibraries must be filled
@Suppress("DEPRECATION") assertThat(app.variantDependencies).isEmpty()
assertThat(app.debugLibraries).isNotEmpty()
// At least one project library
assertThat(app.debugLibraries.filter { it.type == PROJECT }).isNotEmpty()
val javaLibrary = project.findByPath(":java-library").get()
assertThat(javaLibrary).isNotNull()
assertThat(javaLibrary).isInstanceOf(IdeJavaModule::class.java)
assertThat(project.findByPath(":does-not-exist").get()).isNull()
override fun logOutput(line: String) {
log.debug(line.trim())
}
private fun launchServer(client: IToolingApiClient): Pair<IToolingApiServer, IProject> {
val builder =
ProcessBuilder(
"java",
"--add-opens",
"java.base/java.lang=ALL-UNNAMED",
"--add-opens",
"java.base/java.util=ALL-UNNAMED",
"--add-opens",
"java.base/java.io=ALL-UNNAMED",
"-jar",
"./build/libs/tooling-api-all.jar")
val androidHome = findAndroidHome()
builder.environment()["ANDROID_SDK_ROOT"] = androidHome
builder.environment()["ANDROID_HOME"] = androidHome
val proc = builder.start()
override fun prepareBuild() {}
override fun onBuildSuccessful(result: BuildResult) {}
override fun onBuildFailed(result: BuildResult) {}
Thread(Reader(proc.errorStream)).start()
val launcher =
ToolingApiLauncher.newClientLauncher(client, proc.inputStream, proc.outputStream)
override fun onProgressEvent(event: ProgressEvent) {}
launcher.startListening()
return launcher.remoteProxy as IToolingApiServer to launcher.remoteProxy as IProject
override fun getBuildArguments(): CompletableFuture<List<String>> {
return CompletableFuture.completedFuture(listOf("--stacktrace", "--info"))
}
private fun findAndroidHome(): String {
return System.getProperty("test.android.home")
}
override fun checkGradleWrapperAvailability(): CompletableFuture<GradleWrapperCheckResult> =
CompletableFuture.completedFuture(GradleWrapperCheckResult(true))
}
private class TestClient : IToolingApiClient {
private val log = ILogger.newInstance(javaClass.simpleName)
override fun logMessage(line: LogLine) {
log.log(line.priority, line.formattedTagAndMessage())
private class Reader(val input: InputStream) : Runnable {
private val log = ILogger.newInstance(javaClass.simpleName)
override fun run() {
try {
val reader = BufferedReader(InputStreamReader(input))
var line = reader.readLine()
while (line != null) {
log.debug(line)
line = reader.readLine()
}
override fun logOutput(line: String) {
log.debug(line.trim())
}
override fun prepareBuild() {}
override fun onBuildSuccessful(result: BuildResult) {}
override fun onBuildFailed(result: BuildResult) {}
override fun onProgressEvent(event: ProgressEvent) {}
override fun getBuildArguments(): CompletableFuture<List<String>> {
return CompletableFuture.completedFuture(emptyList())
}
override fun checkGradleWrapperAvailability(): CompletableFuture<GradleWrapperCheckResult> =
CompletableFuture.completedFuture(GradleWrapperCheckResult(true))
} catch (error: Throwable) {
log.error(error)
}
}
}
private class Reader(val input: InputStream) : Runnable {
private val log = ILogger.newInstance(javaClass.simpleName)
override fun run() {
try {
val reader = BufferedReader(InputStreamReader(input))
var line = reader.readLine()
while (line != null) {
log.debug(line)
line = reader.readLine()
}
} catch (error: Throwable) {
log.error(error)
}
}
}
fun Any.getTestProject(): File = File("./src/test/test-project")
fun Any.getTestProject(): File = File("./src/test/test-project")
fun Any.asJson(): String {
val builder = GsonBuilder()
ToolingApiLauncher.configureGson(builder)
return builder.create().toJson(this)
}
fun Any.asJson(): String {
val builder = GsonBuilder()
ToolingApiLauncher.configureGson(builder)
return builder.create().toJson(this)
}
}
@@ -1,6 +1,6 @@
buildscript {
ext {
build_gradle_version = '7.2.0'
build_gradle_version = '7.4.0-alpha05'
}
project.ext {
@@ -14,10 +14,6 @@ buildscript {
}
repositories {
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/google/' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
maven { url "https://clojars.org/repo/" }
google()
mavenLocal()
mavenCentral()
@@ -29,10 +25,6 @@ buildscript {
}
allprojects {
repositories {
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/google/' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
maven { url "https://clojars.org/repo/" }
mavenLocal()
mavenCentral()
google()
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-rc-1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
View File