Register instance creator for IdeProject

This commit is contained in:
Akash Yadav
2022-04-24 18:55:43 +05:30
parent 83f036fb2e
commit 3f0d94dc9f
12 changed files with 99 additions and 148 deletions
+1
View File
@@ -11,6 +11,7 @@
</profile>
</annotationProcessing>
<bytecodeTargetLevel target="1.7">
<module name="AndroidIDE.build-tools.tooling-api-plugin" target="11" />
<module name="AndroidIDE.google-java-format" target="1.8" />
<module name="AndroidIDE.gradle-tooling" target="1.8" />
<module name="AndroidIDE.gradle-tooling.plugin" target="1.8" />
Binary file not shown.
@@ -13,12 +13,14 @@ package org.eclipse.lsp4j.jsonrpc.json;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParseException;
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.IdeProject;
import com.itsaky.androidide.tooling.api.model.internal.DefaultIdeProject;
import org.eclipse.lsp4j.jsonrpc.MessageIssueException;
import org.eclipse.lsp4j.jsonrpc.json.adapters.CollectionTypeAdapter;
@@ -31,7 +33,6 @@ import org.eclipse.lsp4j.jsonrpc.messages.CancelParams;
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
import org.eclipse.lsp4j.jsonrpc.utils.IdeProjectInstanceCreator;
import java.io.IOException;
import java.io.Reader;
@@ -70,7 +71,9 @@ public class MessageJsonHandler {
.registerTypeAdapterFactory(new TupleTypeAdapters.TwoTypeAdapterFactory())
.registerTypeAdapterFactory(new EnumTypeAdapter.Factory())
.registerTypeAdapterFactory(new MessageTypeAdapter.Factory(this))
.registerTypeAdapter(IdeProject.class, new IdeProjectInstanceCreator());
.registerTypeAdapter(
IdeProject.class,
(InstanceCreator<IdeProject>) type -> new DefaultIdeProject());
}
/**
@@ -26,8 +26,6 @@ import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.google.gson.stream.MalformedJsonException;
import com.itsaky.androidide.tooling.api.model.IdeProject;
import com.itsaky.androidide.tooling.api.model.internal.DefaultIdeProject;
import org.eclipse.lsp4j.jsonrpc.MessageIssueException;
import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod;
@@ -45,7 +43,6 @@ import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage;
import java.io.EOFException;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
@@ -97,13 +94,9 @@ public class MessageTypeAdapter extends TypeAdapter<Message> {
} else {
out.name("result");
Object result = responseMessage.getResult();
if (result == null) writeNullValue(out);
else {
if (Proxy.isProxyClass(result.getClass())) {
LOG.debug("Copying IdeProject instance...");
result = copyProject((IdeProject) result);
}
if (result == null) {
writeNullValue(out);
} else {
gson.toJson(result, result.getClass(), out);
}
}
@@ -214,14 +207,6 @@ public class MessageTypeAdapter extends TypeAdapter<Message> {
out.setSerializeNulls(previousSerializeNulls);
}
private Object copyProject(IdeProject result) {
final var project = new DefaultIdeProject();
project.setProjectDir(result.getProjectDir());
project.setDisplayName(result.getDisplayName());
project.setPath(result.getPath());
return project;
}
/**
* Convert the json input into the result object corresponding to the call made by id.
*
@@ -1,49 +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 <https://www.gnu.org/licenses/>.
*/
package org.eclipse.lsp4j.jsonrpc.utils;
import com.itsaky.androidide.tooling.api.model.IdeProject;
import com.itsaky.androidide.tooling.api.model.internal.DefaultIdeProject;
/**
* Copies an {@link IdeProject}.
*
* <p><b>Why do we need this class? <br>
* </b>The actual {@link IdeProject} instance is created in the <b>AndroidIDEToolingApiPlugin</b>
* class, which is NOT executed in the same JVM instance as the JSONRpc classes. As a result, the
* object we get from the plugin is a {@link java.lang.reflect.Proxy Proxy}. Gson is not capable of
* serializing proxy classes. So, before writing messages to the remote endpoint, we first check if
* the object we are writing is a proxy or not. If it is, then the data being written to
* the remote endpoint is definitely an {@link IdeProject}. So we use this class to copy the data
* stored in that proxy object to create a new instance of the project object.
*
* <p><b>Why we cannot create a <code>copy()</code> function in {@link IdeProject} class itself?</b><br>
* I tried to do the same and found that the new project object created is also a proxy.
*
* @author Akash Yadav
*/
public class IdeProjectCopier {
public static IdeProject copy(IdeProject project) {
final var copy = new DefaultIdeProject();
copy.setPath(project.getPath());
copy.setProjectDir(project.getProjectDir());
copy.setDisplayName(project.getDisplayName());
return copy;
}
}
@@ -1,54 +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 <https://www.gnu.org/licenses/>.
*/
/*
* 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 org.eclipse.lsp4j.jsonrpc.utils;
import com.google.gson.InstanceCreator;
import com.itsaky.androidide.tooling.api.model.IdeProject;
import com.itsaky.androidide.tooling.api.model.internal.DefaultIdeProject;
import java.lang.reflect.Type;
/**
* As {@link IdeProject} is an interface, we need to implement an {@link InstanceCreator}.
*
* @author Akash Yadav
*/
public class IdeProjectInstanceCreator implements InstanceCreator<IdeProject> {
@Override
public IdeProject createInstance(Type type) {
return new DefaultIdeProject();
}
}
@@ -28,24 +28,26 @@ import java.io.Serializable
* @author Akash Yadav
*/
interface IdeProject : Serializable {
/**
* Get the path of this project. For example: ':app'.
*
* @return The path of this project.
*/
/** The path of this project. For example: ':app'. */
val path: String?
/**
* Get the display name of this project.
*
* @return The display name of this project.
*/
/** The display name of this project. */
val displayName: String?
/**
* Get the project directory of this project.
*
* @return The directory of this project.
*/
/** 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<IdeProject>
/**
* Dependencies of this project.
*/
val dependencies: List<ProjectDependency>
}
@@ -23,14 +23,15 @@ import java.io.File
* A project dependency. Holds data about the jar, sources and javadoc files of a dependency. Also
* some other useful metadata.
*
* If you do any changes here, please update IdeProjectCopier too.
*
* @author Akash Yadav
*/
class ProjectDependency(
private val group: String,
private val artifact: String,
private val version: String,
private val jar: File
) {
private val sourcesJar: File? = null
private val javadocJar: File? = null
class ProjectDependency {
var group: String? = null
var artifact: String? = null
var version: String? = null
var jar: File? = null
var sourcesJar: File? = null
var javadocJar: File? = null
}
@@ -0,0 +1,35 @@
/*
* 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.tooling.api.model
/**
* A task in an [IdeProject].
*
* @author Akash Yadav
*/
class ProjectTask {
//////////////////////////////////////////////////////////////////////////
//// Any changes made here must be reflected in IdeProjectCopier too ////
////////////////////////////////////////////////////////////////////////
var path: String? = null
var name: String? = null
var group: String? = null
var description: String? = null
}
@@ -18,12 +18,16 @@
package com.itsaky.androidide.tooling.api.model.internal
import com.itsaky.androidide.tooling.api.model.IdeProject
import com.itsaky.androidide.tooling.api.model.ProjectDependency
import java.io.File
/** @author Akash Yadav */
class DefaultIdeProject : IdeProject {
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<IdeProject> = mutableListOf()
override var dependencies: MutableList<ProjectDependency> = mutableListOf()
}
@@ -18,11 +18,15 @@
package com.itsaky.androidide.tooling.plugin;
import com.itsaky.androidide.tooling.api.model.IdeProject;
import com.itsaky.androidide.tooling.api.model.ProjectDependency;
import com.itsaky.androidide.tooling.api.model.internal.DefaultIdeProject;
import org.gradle.api.Project;
import org.gradle.tooling.provider.model.ToolingModelBuilder;
import java.util.ArrayList;
import java.util.List;
/**
* @author Akash Yadav
*/
@@ -44,5 +48,25 @@ public class IdeProjectModelBuilder implements ToolingModelBuilder {
ideProject.setPath(project.getPath());
ideProject.setDisplayName(project.getDisplayName());
ideProject.setProjectDir(project.getProjectDir());
ideProject.setBuildDir(project.getBuildDir());
ideProject.setBuildFile(project.getBuildFile());
ideProject.setDependencies(getDependencies(project));
ideProject.setSubProjects(getSubProjects(project));
}
private List<ProjectDependency> getDependencies(Project project) {
return null;
}
private List<IdeProject> getSubProjects(Project project) {
final var projects = new ArrayList<IdeProject>();
project.getSubprojects()
.forEach(
sub -> {
final var subProject = new DefaultIdeProject();
fillProjectDetails(sub, subProject);
projects.add(subProject);
});
return projects;
}
}
-1
View File
@@ -22,6 +22,5 @@ include ':build-tools:javac'
include ':build-tools:logger'
include ':build-tools:tooling-api'
include ':build-tools:tooling-api-impl'
include ':build-tools:tooling-api-plugin'
include ':build-tools:tooling-api-model'
include ':build-tools:jsonrpc'