naive codegen implementation
Some checks failed
Publish to snapshot maven / build (push) Failing after 1m15s
Some checks failed
Publish to snapshot maven / build (push) Failing after 1m15s
This commit is contained in:
parent
7023128e45
commit
ba83b48e81
3
library/gen/build.gradle.kts
Normal file
3
library/gen/build.gradle.kts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
dependencies {
|
||||||
|
implementation("net.bytebuddy:byte-buddy:1.14.17")
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package dev.frogmc.froglib.gen.api;
|
||||||
|
|
||||||
|
import net.bytebuddy.ByteBuddy;
|
||||||
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
import net.bytebuddy.implementation.MethodCall;
|
||||||
|
import net.bytebuddy.matcher.ElementMatchers;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code AbstractCodegenBuilder} is a template for creating Builder patterned classes that create anonymous, dynamic classes.
|
||||||
|
* @param <T> The superclass of the classes that will be generated.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractCodegenBuilder<T> {
|
||||||
|
/**
|
||||||
|
* Represents the class builder.
|
||||||
|
*/
|
||||||
|
protected DynamicType.Builder<?> dt;
|
||||||
|
/**
|
||||||
|
* Represents the arguments that will be provided to the dynamic classes constructor.
|
||||||
|
*/
|
||||||
|
protected Object[] args; // TODO this seems bad?
|
||||||
|
/**
|
||||||
|
* Represents the fields that this dynamic class will contain.
|
||||||
|
*/
|
||||||
|
protected Map<String, Object> fields; // TODO this is really bad, probably just figure out how to actually properly add fields
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new AbstractCodegenBuilder. Subclasses should provide their own public constructor.
|
||||||
|
*/
|
||||||
|
protected AbstractCodegenBuilder() {
|
||||||
|
this.dt = new ByteBuddy()
|
||||||
|
.subclass((Class<T>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides a method of the superclass in the dynamically-generated class.
|
||||||
|
* @param method The signature of the method to override.
|
||||||
|
* @param body A {@link FunctionalInterface} representing the body of the new overridden method.
|
||||||
|
*/
|
||||||
|
protected void overrideMethod(String method, Callable<?> body) throws NoSuchMethodException { // TODO handle instead of throwing
|
||||||
|
this.dt = this.dt.method(ElementMatchers.anyOf(((Class<T>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]).getDeclaredMethod(method))) // FIXME i literally have no idea if this works lmao
|
||||||
|
.intercept(MethodCall.call(body));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the dynamic class as well as a singleton instance of it. Subclasses should provide their own public {@code build} method.
|
||||||
|
* @return The singleton instance of the dynamic class.
|
||||||
|
*/
|
||||||
|
protected T build() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { // TODO handle instead of throwing
|
||||||
|
if(this.fields.containsValue(null)) {
|
||||||
|
throw new IllegalAccessException();
|
||||||
|
}
|
||||||
|
return (T) this.dt
|
||||||
|
.make()
|
||||||
|
.load(getClass().getClassLoader())
|
||||||
|
.getLoaded() // TODO we might want to return this instead?
|
||||||
|
.getDeclaredConstructor()
|
||||||
|
.newInstance(this.args);
|
||||||
|
}
|
||||||
|
}
|
22
library/gen/src/main/resources/frog.mod.toml
Normal file
22
library/gen/src/main/resources/frog.mod.toml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[frog]
|
||||||
|
format_version = "1.0.0"
|
||||||
|
|
||||||
|
[frog.mod]
|
||||||
|
id = "froglib_gen"
|
||||||
|
name = "FrogLib Data and Code Generation"
|
||||||
|
version = "$version"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
credits = [
|
||||||
|
{ name = "FrogMC Team", roles = ["author"] }
|
||||||
|
]
|
||||||
|
|
||||||
|
[frog.dependencies]
|
||||||
|
depends = [
|
||||||
|
{ id = "minecraft", versions = "~$game_version", name = "Minecraft" }
|
||||||
|
]
|
||||||
|
|
||||||
|
[frog.extensions]
|
||||||
|
prelaunch = "net.frogmc.froglib.gen.impl.FrogGenPrelaunch"
|
||||||
|
mixin = [
|
||||||
|
"froglib.gen.mixins.json"
|
||||||
|
]
|
16
library/gen/src/main/resources/froglib.gen.mixins.json
Normal file
16
library/gen/src/main/resources/froglib.gen.mixins.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"minVersion": "0.8",
|
||||||
|
"package": "dev.frogmc.froglib.gen.impl.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_21",
|
||||||
|
"mixins": [
|
||||||
|
],
|
||||||
|
"server": [
|
||||||
|
],
|
||||||
|
"client": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,3 +27,5 @@ include("library:registries")
|
||||||
findProject(":library:registries")?.name = "registries"
|
findProject(":library:registries")?.name = "registries"
|
||||||
include("library:player")
|
include("library:player")
|
||||||
findProject(":library:player")?.name = "player"
|
findProject(":library:player")?.name = "player"
|
||||||
|
include("library:gen")
|
||||||
|
findProject(":library:gen")?.name = "gen"
|
||||||
|
|
Loading…
Reference in a new issue