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"
|
||||
include("library:player")
|
||||
findProject(":library:player")?.name = "player"
|
||||
include("library:gen")
|
||||
findProject(":library:gen")?.name = "gen"
|
||||
|
|
Loading…
Reference in a new issue