diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index cc16c8451..0034de2f5 100755
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -10,7 +10,7 @@
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 46c9d0484..06ac8f54d 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -141,7 +141,7 @@
-
+
diff --git a/app/src/main/assets/data/common/tooling-api-all.jar b/app/src/main/assets/data/common/tooling-api-all.jar
index 1dab5b2e6..7052b31ab 100644
Binary files a/app/src/main/assets/data/common/tooling-api-all.jar and b/app/src/main/assets/data/common/tooling-api-all.jar differ
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java
index 05aba9ed8..eb35b3a27 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java
@@ -20,7 +20,7 @@ import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.MalformedJsonException;
import com.itsaky.androidide.tooling.api.model.IAndroidProject;
-import com.itsaky.androidide.tooling.api.model.internal.DefaultAndroidProject;
+import com.itsaky.androidide.tooling.api.model.internal.DefaultAndroidModule;
import org.eclipse.lsp4j.jsonrpc.MessageIssueException;
import org.eclipse.lsp4j.jsonrpc.json.adapters.CollectionTypeAdapter;
@@ -70,10 +70,7 @@ public class MessageJsonHandler {
.registerTypeAdapterFactory(new EitherTypeAdapter.Factory())
.registerTypeAdapterFactory(new TupleTypeAdapters.TwoTypeAdapterFactory())
.registerTypeAdapterFactory(new EnumTypeAdapter.Factory())
- .registerTypeAdapterFactory(new MessageTypeAdapter.Factory(this))
- .registerTypeAdapter(
- IAndroidProject.class,
- (InstanceCreator) type -> new DefaultAndroidProject ());
+ .registerTypeAdapterFactory(new MessageTypeAdapter.Factory(this));
}
/**
diff --git a/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/ToolingApiServerImpl.kt b/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/ToolingApiServerImpl.kt
index 3b2aa7778..5572fe66f 100644
--- a/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/ToolingApiServerImpl.kt
+++ b/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/ToolingApiServerImpl.kt
@@ -20,7 +20,6 @@ package com.itsaky.androidide.tooling.impl
import com.itsaky.androidide.tooling.api.IToolingApiClient
import com.itsaky.androidide.tooling.api.IToolingApiServer
import com.itsaky.androidide.tooling.api.messages.InitializeProjectParams
-import com.itsaky.androidide.tooling.api.model.IAndroidProject
import com.itsaky.androidide.tooling.impl.util.InitScriptHandler
import com.itsaky.androidide.tooling.impl.util.ProjectReader
import com.itsaky.androidide.tooling.impl.util.StopWatch
diff --git a/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/IGradleProjectTypeAdapter.java b/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/IGradleProjectTypeAdapter.java
new file mode 100644
index 000000000..550d3e8a2
--- /dev/null
+++ b/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/IGradleProjectTypeAdapter.java
@@ -0,0 +1,66 @@
+/*
+ * 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.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.itsaky.androidide.tooling.api.model.IGradleProject;
+
+import java.lang.reflect.Type;
+
+/**
+ * Gson (de)serializer for {@link IGradleProject}.
+ *
+ * @author Akash Yadav
+ */
+public class IGradleProjectTypeAdapter
+ implements JsonSerializer, JsonDeserializer {
+
+ public static final String className = "className";
+ public static final String classInst = "classInst";
+
+ @Override
+ public JsonElement serialize(
+ IGradleProject src, Type typeOfSrc, JsonSerializationContext context) {
+ final var obj = new JsonObject();
+ obj.addProperty(className, src.getClass().getName());
+ obj.add(classInst, context.serialize(obj));
+ return obj;
+ }
+
+ @Override
+ public IGradleProject deserialize(
+ JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ final var obj = json.getAsJsonObject();
+ final var name = obj.get(className).getAsString();
+ final Class> klass;
+ try {
+ klass = Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ throw new JsonParseException(e);
+ }
+
+ return context.deserialize(obj.get(classInst), klass);
+ }
+}
diff --git a/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/ProjectReader.java b/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/ProjectReader.java
index 07aa9e84c..b2ad1e8b1 100644
--- a/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/ProjectReader.java
+++ b/build-tools/tooling-api-impl/src/main/java/com/itsaky/androidide/tooling/impl/util/ProjectReader.java
@@ -20,11 +20,9 @@ package com.itsaky.androidide.tooling.impl.util;
import static com.itsaky.androidide.utils.ILogger.newInstance;
import com.android.builder.model.v2.models.AndroidProject;
-import com.itsaky.androidide.tooling.api.model.IAndroidProject;
-import com.itsaky.androidide.tooling.api.model.internal.DefaultAndroidProject;
+import com.itsaky.androidide.tooling.api.model.IGradleProject;
import com.itsaky.androidide.utils.ILogger;
-import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.model.GradleProject;
@@ -35,34 +33,24 @@ public class ProjectReader {
private static final ILogger LOG = newInstance("test");
- public static IAndroidProject read(ProjectConnection connection) {
+ public static IGradleProject read(ProjectConnection connection) {
final var watch = new StopWatch("Read eclipse project from connection");
final var gradle = connection.getModel(GradleProject.class);
-
- LOG.debug(System.getenv());
- LOG.debug(System.getProperties());
- for (var sub : gradle.getChildren()) {
- var subConnection =
- GradleConnector.newConnector()
- .forProjectDirectory(sub.getProjectDirectory())
- .connect();
- final var modelBuilder =
- subConnection
- .model(AndroidProject.class)
- .withArguments("-Pandroid.injected.build.model.v2=true");
- final var project = modelBuilder.get();
- LOG.debug(project);
+ if (gradle == null) {
+ LOG.error("Cannot build model for", GradleProject.class);
+ return null;
}
+ final var android =
+ connection
+ .model(AndroidProject.class)
+ .withArguments("-Pandroid.injected.build.model.v2=true")
+ .get();
+ LOG.debug(android);
watch.log();
- // return read(project);
return null;
}
- public static IAndroidProject read(AndroidProject android) {
- final var project = new DefaultAndroidProject ();
- LOG.debug(android);
- return project;
- }
+ public static IGradleProject read(AndroidProject android) {}
}
diff --git a/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar b/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar
index acda8e9d1..d38310ed6 100644
Binary files a/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar and b/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar differ
diff --git a/build-tools/tooling-api-model/build.gradle b/build-tools/tooling-api-model/build.gradle
index 743dd41dd..722bc9d9e 100644
--- a/build-tools/tooling-api-model/build.gradle
+++ b/build-tools/tooling-api-model/build.gradle
@@ -21,9 +21,21 @@ plugins {
}
java {
- sourceCompatibility = JavaVersion.VERSION_1_7
- targetCompatibility = JavaVersion.VERSION_1_7
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
}
+
+repositories {
+ maven {
+ url 'https://repo.gradle.org/gradle/libs-releases/'
+ }
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
+ implementation 'com.android.tools.build:builder-model:7.1.3'
+}
+
task copyToTestDir (type: Copy) {
from "$project.buildDir.absolutePath/libs/tooling-api-model.jar"
into "${project.rootProject.findProject (":build-tools:tooling-api-impl").file ("src/test/test-home/.androidide/init").absolutePath}/"
@@ -41,9 +53,4 @@ project.tasks.jar {
outputs.upToDateWhen {
false
}
-}
-
-
-dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
\ No newline at end of file
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IAndroidModule.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IAndroidModule.kt
new file mode 100644
index 000000000..e6119d708
--- /dev/null
+++ b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IAndroidModule.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.api.model
+
+import com.android.builder.model.v2.models.AndroidProject
+
+/**
+ * A module in an [IAndroidProject].
+ *
+ * @author Akash Yadav
+ */
+interface IAndroidModule : IGradleProject, AndroidProject {}
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IAndroidProject.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IAndroidProject.kt
deleted file mode 100644
index 9984a0dd1..000000000
--- a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IAndroidProject.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.api.model
-
-import java.io.File
-import java.io.Serializable
-
-/**
- * Currently initialized project.
- *
- * The instance of this class is created from a [Proxy][java.lang.reflect.Proxy]. If you add any
- * property to this class, make sure you update the [IAndroidProject.copy] method too.
- *
- * @author Akash Yadav
- */
-interface IAndroidProject : Serializable {
- /** The path of this project. For example: ':app'. */
- val path: String?
-
- /** The display name of this project. */
- val displayName: String?
-
- /** The project directory of this project. */
- val projectDir: File?
-
- /** Get the build directory of this project. */
- val buildDir: File?
-
- /** The buildscript file (build.gradle) of this project. */
- val buildFile: File?
-
- /** Subprojects of this project. */
- val subProjects: List
-
- /**
- * Dependencies of this project.
- */
- val dependencies: List
-}
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultAndroidProject.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IGradleProject.kt
similarity index 53%
rename from build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultAndroidProject.kt
rename to build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IGradleProject.kt
index 0ce32b48a..a50385b49 100644
--- a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultAndroidProject.kt
+++ b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IGradleProject.kt
@@ -15,19 +15,33 @@
* along with AndroidIDE. If not, see .
*/
-package com.itsaky.androidide.tooling.api.model.internal
+package com.itsaky.androidide.tooling.api.model
-import com.itsaky.androidide.tooling.api.model.IAndroidProject
-import com.itsaky.androidide.tooling.api.model.ProjectDependency
import java.io.File
+import java.io.Serializable
-/** @author Akash Yadav */
-class DefaultAndroidProject : IAndroidProject {
- override var path: String? = null
- override var displayName: String? = null
- override var projectDir: File? = null
- override var buildDir: File? = null
- override var buildFile: File? = null
- override var subProjects: MutableList = mutableListOf()
- override var dependencies: MutableList = mutableListOf()
+/**
+ * An Gradle Project.
+ * @author Akash Yadav
+ */
+interface IGradleProject : Serializable {
+ val name: String
+ val description: String
+ val path: String
+ val projectDir: File
+ val buildDir: File
+ val buildScript: File
+
+ val parent: IGradleProject?
+ val subprojects: List
+ val tasks: List
+
+ val isAndroidModule: Boolean
+
+ /**
+ * Finds the project with the given project path.
+ *
+ * @return The found [IGradleProject] or `null`.
+ */
+ fun findByPath(path: String): IGradleProject?
}
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IGradleTask.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IGradleTask.kt
new file mode 100644
index 000000000..86b738703
--- /dev/null
+++ b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/IGradleTask.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.api.model
+
+/**
+ * A task in an [IGradleProject].
+ * @author Akash Yadav
+ */
+interface IGradleTask : ILaunchable {
+ val name: String
+ val description: String
+ val group: String
+ val path: String
+
+ val project: IGradleProject
+}
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/ILaunchable.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/ILaunchable.kt
new file mode 100644
index 000000000..ecc98b116
--- /dev/null
+++ b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/ILaunchable.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.api.model
+
+/**
+ * A launchable is an action that can be launched. For example, an [IGradleTask].
+ *
+ * @author Akash Yadav
+ */
+interface ILaunchable {
+ val displayName: String
+ val isPublic: Boolean
+}
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultAndroidModule.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultAndroidModule.kt
new file mode 100644
index 000000000..4b7fe4977
--- /dev/null
+++ b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultAndroidModule.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.api.model.internal
+
+import com.android.builder.model.v2.ide.AndroidGradlePluginProjectFlags
+import com.android.builder.model.v2.ide.JavaCompileOptions
+import com.android.builder.model.v2.ide.ProjectType
+import com.android.builder.model.v2.ide.SourceSetContainer
+import com.android.builder.model.v2.ide.Variant
+import com.android.builder.model.v2.ide.ViewBindingOptions
+import com.itsaky.androidide.tooling.api.model.IAndroidModule
+import com.itsaky.androidide.tooling.api.model.IGradleProject
+import com.itsaky.androidide.tooling.api.model.IGradleTask
+import java.io.File
+
+/**
+ * Default implementation of [IAndroidModule].
+ *
+ * @author Akash Yadav
+ */
+class DefaultAndroidModule(
+ override var name: String,
+ override var description: String,
+ override var path: String,
+ override var projectDir: File,
+ override var buildDir: File,
+ override var buildScript: File,
+ override var parent: IGradleProject?,
+ override var subprojects: List,
+ override var tasks: List,
+ override var androidTestNamespace: String?,
+ override var bootClasspath: Collection,
+ override var buildFolder: File,
+ override var buildName: String,
+ override var buildTypeSourceSets: Collection,
+ override var dynamicFeatures: Collection?,
+ override var flags: AndroidGradlePluginProjectFlags,
+ override var javaCompileOptions: JavaCompileOptions,
+ override var lintRuleJars: List,
+ override var mainSourceSet: SourceSetContainer,
+ override var namespace: String,
+ override var productFlavorSourceSets: Collection,
+ override var projectType: ProjectType,
+ override var resourcePrefix: String?,
+ override var testFixturesNamespace: String?,
+ override var variants: Collection,
+ override var viewBindingOptions: ViewBindingOptions?
+) :
+ DefaultGradleProject(
+ name, description, path, projectDir, buildDir, buildScript, parent, subprojects, tasks),
+ IAndroidModule {
+
+ override val isAndroidModule: Boolean = true
+
+ fun copy(): IAndroidModule {
+ return DefaultAndroidModule(
+ name,
+ description,
+ path,
+ projectDir,
+ buildDir,
+ buildScript,
+ parent,
+ subprojects,
+ tasks,
+ androidTestNamespace,
+ bootClasspath,
+ buildFolder,
+ buildName,
+ buildTypeSourceSets,
+ dynamicFeatures,
+ flags,
+ javaCompileOptions,
+ lintRuleJars,
+ mainSourceSet,
+ namespace,
+ productFlavorSourceSets,
+ projectType,
+ resourcePrefix,
+ testFixturesNamespace,
+ variants,
+ viewBindingOptions)
+ }
+}
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultGradleProject.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultGradleProject.kt
new file mode 100644
index 000000000..137b99234
--- /dev/null
+++ b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/DefaultGradleProject.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.api.model.internal
+
+import com.itsaky.androidide.tooling.api.model.IGradleProject
+import com.itsaky.androidide.tooling.api.model.IGradleTask
+import java.io.File
+
+/**
+ * Default implementation for [IGradleProject].
+ * @author Akash Yadav
+ */
+open class DefaultGradleProject(
+ override val name: String,
+ override val description: String,
+ override val path: String,
+ override val projectDir: File,
+ override val buildDir: File,
+ override val buildScript: File,
+ override val parent: IGradleProject?,
+ override val subprojects: List,
+ override val tasks: List,
+) : IGradleProject {
+
+ override val isAndroidModule: Boolean = false
+
+ override fun findByPath(path: String): IGradleProject? {
+ if (path == this.path) {
+ return this
+ }
+
+ for (sub in subprojects) {
+ val subSub = sub.findByPath(path)
+ if (subSub != null) {
+ return subSub
+ }
+ }
+
+ return null
+ }
+}
diff --git a/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/util/ProjectBuilder.kt b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/util/ProjectBuilder.kt
new file mode 100644
index 000000000..73db03ff8
--- /dev/null
+++ b/build-tools/tooling-api-model/src/main/java/com/itsaky/androidide/tooling/api/model/internal/util/ProjectBuilder.kt
@@ -0,0 +1,135 @@
+/*
+ * 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.api.model.internal.util
+
+import com.android.builder.model.v2.ide.AndroidGradlePluginProjectFlags
+import com.android.builder.model.v2.ide.AndroidGradlePluginProjectFlags.BooleanFlag
+import com.android.builder.model.v2.ide.JavaCompileOptions
+import com.android.builder.model.v2.ide.ProjectType
+import com.android.builder.model.v2.ide.ProjectType.APPLICATION
+import com.android.builder.model.v2.ide.SourceProvider
+import com.android.builder.model.v2.ide.SourceSetContainer
+import com.android.builder.model.v2.ide.Variant
+import com.android.builder.model.v2.ide.ViewBindingOptions
+import com.itsaky.androidide.tooling.api.model.IAndroidModule
+import com.itsaky.androidide.tooling.api.model.IGradleProject
+import com.itsaky.androidide.tooling.api.model.IGradleTask
+import com.itsaky.androidide.tooling.api.model.internal.DefaultAndroidModule
+import com.itsaky.androidide.tooling.api.model.internal.DefaultGradleProject
+import java.io.File
+
+/**
+ * Builds instances of [IAndroidProject]
+ *
+ * @author Akash Yadav
+ */
+class ProjectBuilder {
+ private var name: String = ""
+ private var description: String = ""
+ private var path: String = ""
+ private var projectDir: File = File("")
+ private var buildDir: File = File("")
+ private var buildScript: File = File("")
+ private var parent: IGradleProject? = null
+ private var subprojects: List = mutableListOf()
+ private var tasks: List = mutableListOf()
+ private var androidTestNamespace: String = ""
+ private var bootClasspath: Collection = mutableListOf()
+ private var buildFolder: File = File("")
+ private var buildName: String = ""
+ private var buildTypeSourceSets: Collection = mutableListOf()
+ private var dynamicFeatures: Collection? = mutableListOf()
+ private var flags: AndroidGradlePluginProjectFlags = NoOpAndroidGradlePluginProjectFlags()
+ private var javaCompileOptions: JavaCompileOptions = DefaultJavaCompileOptions()
+ private var lintRuleJars: List = mutableListOf()
+ private var mainSourceSet: SourceSetContainer = DefaultSourceSetContainer()
+ private var namespace: String = ""
+ private var productFlavorSourceSets: Collection = mutableListOf()
+ private var projectType: ProjectType = APPLICATION
+ private var resourcePrefix: String = ""
+ private var testFixturesNamespace: String = ""
+ private var variants: Collection = mutableListOf()
+ private var viewBindingOptions: ViewBindingOptions? = null
+
+ fun buildGradleProject(): IGradleProject {
+ return DefaultGradleProject(
+ name, description, path, projectDir, buildDir, buildScript, parent, subprojects, tasks)
+ }
+
+ fun buildAndroidModule(): IAndroidModule =
+ DefaultAndroidModule(
+ name,
+ description,
+ path,
+ projectDir,
+ buildDir,
+ buildScript,
+ parent,
+ subprojects,
+ tasks,
+ androidTestNamespace,
+ bootClasspath,
+ buildFolder,
+ buildName,
+ buildTypeSourceSets,
+ dynamicFeatures,
+ flags,
+ javaCompileOptions,
+ lintRuleJars,
+ mainSourceSet,
+ namespace,
+ productFlavorSourceSets,
+ projectType,
+ resourcePrefix,
+ testFixturesNamespace,
+ variants,
+ viewBindingOptions)
+
+ class NoOpAndroidGradlePluginProjectFlags : AndroidGradlePluginProjectFlags {
+ override val booleanFlagMap: Map = mutableMapOf()
+ }
+
+ class DefaultJavaCompileOptions : JavaCompileOptions {
+ override val encoding: String = "UTF-8"
+ override val isCoreLibraryDesugaringEnabled: Boolean = false
+ override val sourceCompatibility: String = "11"
+ override val targetCompatibility: String = "11"
+ }
+
+ class DefaultSourceSetContainer : SourceSetContainer {
+ override val androidTestSourceProvider: SourceProvider? = null
+ override val sourceProvider: SourceProvider = DefaultSourceProvider()
+ override val testFixturesSourceProvider: SourceProvider? = null
+ override val unitTestSourceProvider: SourceProvider? = null
+
+ class DefaultSourceProvider : SourceProvider {
+ override val aidlDirectories: Collection? = null
+ override val assetsDirectories: Collection? = null
+ override val javaDirectories = mutableListOf()
+ override val jniLibsDirectories: Collection = mutableListOf()
+ override val kotlinDirectories: Collection = mutableListOf()
+ override val manifestFile = File("")
+ override val mlModelsDirectories: Collection? = null
+ override val name: String = ""
+ override val renderscriptDirectories: Collection? = null
+ override val resDirectories: Collection? = null
+ override val resourcesDirectories: Collection = mutableListOf()
+ override val shadersDirectories: Collection? = null
+ }
+ }
+}
diff --git a/build-tools/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/IToolingApiServer.kt b/build-tools/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/IToolingApiServer.kt
index 0805a40ac..1a61eb8ba 100644
--- a/build-tools/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/IToolingApiServer.kt
+++ b/build-tools/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/IToolingApiServer.kt
@@ -18,7 +18,6 @@
package com.itsaky.androidide.tooling.api
import com.itsaky.androidide.tooling.api.messages.InitializeProjectParams
-import com.itsaky.androidide.tooling.api.model.IAndroidProject
import java.util.concurrent.*
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest
import org.eclipse.lsp4j.jsonrpc.services.JsonSegment