[config-compiler-plugin] Keep original bytes for non-config classes
This commit is contained in:
parent
f434e8843a
commit
55bfa434ec
@ -27,3 +27,10 @@ allprojects {
|
||||
compileOnly("io.gitlab.jfronny:commons-gson:$rootProject.commons_version")
|
||||
}
|
||||
}
|
||||
|
||||
task copyVersionNumber {
|
||||
doLast {
|
||||
java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new java.awt.datatransfer.StringSelection("$version"), null)
|
||||
println("Copied version number: $version")
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@ dependencies {
|
||||
implementation("io.gitlab.jfronny:commons-gson:$rootProject.commons_version")
|
||||
implementation("org.ow2.asm:asm:9.3")
|
||||
implementation("org.ow2.asm:asm-commons:9.3")
|
||||
implementation("org.ow2.asm:asm-util:9.3")
|
||||
implementation(project(":libjf-config-core-v1")) {
|
||||
transitive(false)
|
||||
}
|
||||
|
@ -3,16 +3,17 @@ package io.gitlab.jfronny.libjf.config.plugin;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.libjf.config.plugin.asm.ConfigInjectClassTransformer;
|
||||
import io.gitlab.jfronny.libjf.config.plugin.asm.NotAConfigClassException;
|
||||
import io.gitlab.jfronny.libjf.config.plugin.fmj.FabricModJsonTransformer;
|
||||
import io.gitlab.jfronny.libjf.config.plugin.util.*;
|
||||
import org.apache.tools.zip.*;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.objectweb.asm.*;
|
||||
import org.objectweb.asm.util.CheckClassAdapter;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class StreamAction {
|
||||
@ -39,7 +40,7 @@ public class StreamAction {
|
||||
} else {
|
||||
return visitFile(details);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
throw new GradleException("Could not add " + details + " to ZIP " + zipFile, e);
|
||||
}
|
||||
}
|
||||
@ -103,7 +104,7 @@ public class StreamAction {
|
||||
copyArchiveEntry(archiveFilePath, archive);
|
||||
}
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
} catch (Throwable e) {
|
||||
throw new GradleException("Could not read archive entry " + archiveFilePath.getPathString(), e);
|
||||
}
|
||||
}
|
||||
@ -136,25 +137,29 @@ public class StreamAction {
|
||||
private void processClass(RelativeArchivePath file, ZipFile archive) throws IOException {
|
||||
ZipEntry zipEntry = new ZipEntry(file.getPathString());
|
||||
addParentDirectories(new RelativeArchivePath(zipEntry));
|
||||
processClass(archive.getInputStream(file.entry), file.getPathString(), file.entry.getTime());
|
||||
processClass(archive.getInputStream(file.entry).readAllBytes(), file.getPathString(), file.entry.getTime());
|
||||
}
|
||||
|
||||
private void processClass(FileCopyDetails details) throws IOException {
|
||||
try (InputStream is = new BufferedInputStream(new FileInputStream(details.getFile()))) {
|
||||
processClass(is, details.getPath(), details.getLastModified());
|
||||
try (InputStream is = new FileInputStream(details.getFile())) {
|
||||
processClass(is.readAllBytes(), details.getPath(), details.getLastModified());
|
||||
}
|
||||
}
|
||||
|
||||
private void processClass(InputStream classInputStream, String path, long lastModified) throws IOException {
|
||||
final ClassReader reader = new ClassReader(classInputStream);
|
||||
private void processClass(byte[] klazz, String path, long lastModified) throws IOException {
|
||||
try {
|
||||
final ClassReader reader = new ClassReader(klazz);
|
||||
final ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
|
||||
reader.accept(new CheckClassAdapter(
|
||||
new ConfigInjectClassTransformer(modId, writer, knownConfigClasses)
|
||||
), ClassReader.EXPAND_FRAMES);
|
||||
final ConfigInjectClassTransformer transformer = new ConfigInjectClassTransformer(modId, writer, knownConfigClasses);
|
||||
reader.accept(transformer, ClassReader.EXPAND_FRAMES);
|
||||
klazz = writer.toByteArray();
|
||||
} catch (NotAConfigClassException notAConfigClass) {
|
||||
// Use original bytes
|
||||
}
|
||||
ZipEntry archiveEntry = new ZipEntry(path);
|
||||
archiveEntry.setTime(getArchiveTimeFor(lastModified));
|
||||
zipOutStr.putNextEntry(archiveEntry);
|
||||
zipOutStr.write(writer.toByteArray());
|
||||
zipOutStr.write(klazz);
|
||||
zipOutStr.closeEntry();
|
||||
}
|
||||
|
||||
@ -165,7 +170,7 @@ public class StreamAction {
|
||||
}
|
||||
|
||||
private void processFMJ(FileCopyDetails details) throws IOException {
|
||||
try (InputStream is = new BufferedInputStream(new FileInputStream(details.getFile()))) {
|
||||
try (InputStream is = new FileInputStream(details.getFile())) {
|
||||
processFMJ(is, details.getPath(), details.getLastModified());
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,23 @@ public class ConfigInjectClassTransformer extends ClassVisitor {
|
||||
private final List<String> verifiers = new LinkedList<>();
|
||||
private final List<DiscoveredValue> values = new LinkedList<>();
|
||||
private boolean initFound = false;
|
||||
private TransformerMode mode = TransformerMode.OTHER;
|
||||
private TransformerMode mode;
|
||||
|
||||
public boolean isCategory() {
|
||||
return mode == TransformerMode.CONFIG_CATEGORY || isConfig();
|
||||
}
|
||||
|
||||
public void ensureCategory() {
|
||||
if (!isCategory()) throw new NotAConfigClassException();
|
||||
}
|
||||
|
||||
public boolean isConfig() {
|
||||
return mode == TransformerMode.CONFIG_ROOT;
|
||||
}
|
||||
|
||||
public boolean isOther() {
|
||||
return mode == TransformerMode.OTHER;
|
||||
}
|
||||
|
||||
public ConfigInjectClassTransformer(String modId, ClassVisitor cw, Set<Type> knownConfigClasses) {
|
||||
super(ASM9, cw);
|
||||
@ -52,29 +68,31 @@ public class ConfigInjectClassTransformer extends ClassVisitor {
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||
if (descriptor.equals(Type.getDescriptor(Category.class)) && mode == TransformerMode.OTHER) {
|
||||
if (mode == null) throw new IllegalStateException("Attempted to visit annotation before class");
|
||||
if (descriptor.equals(Type.getDescriptor(Category.class)) && isOther()) {
|
||||
mode = TransformerMode.CONFIG_CATEGORY;
|
||||
return new AnnotationMetaGatheringVisitor(super.visitAnnotation(descriptor, visible), referencedConfigs);
|
||||
}
|
||||
if (descriptor.equals(Type.getDescriptor(JfConfig.class)) && mode == TransformerMode.OTHER) {
|
||||
else if (descriptor.equals(Type.getDescriptor(JfConfig.class)) && isOther()) {
|
||||
mode = TransformerMode.CONFIG_ROOT;
|
||||
knownConfigClasses.add(current);
|
||||
return new AnnotationMetaGatheringVisitor(super.visitAnnotation(descriptor, visible), referencedConfigs);
|
||||
}
|
||||
} else {
|
||||
return super.visitAnnotation(descriptor, visible);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNestMember(String nestMember) {
|
||||
if (mode != TransformerMode.OTHER) {
|
||||
ensureCategory();
|
||||
categories.add(nestMember);
|
||||
}
|
||||
super.visitNestMember(nestMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
if (mode == TransformerMode.CONFIG_ROOT) {
|
||||
ensureCategory();
|
||||
if (isConfig()) {
|
||||
if ("<clinit>".equals(name)) {
|
||||
initFound = true;
|
||||
return new ClInitInjectVisitor(
|
||||
@ -85,11 +103,9 @@ public class ConfigInjectClassTransformer extends ClassVisitor {
|
||||
);
|
||||
}
|
||||
}
|
||||
if (mode != TransformerMode.OTHER) {
|
||||
if (name.startsWith(PREFIX)) {
|
||||
throw new GradleException("This class declares methods generated by this plugin manually. Do not transform classes twice!");
|
||||
}
|
||||
}
|
||||
if ((access & ACC_STATIC) == ACC_STATIC) {
|
||||
// Possibly add verifier or preset
|
||||
return new MethodMetaGatheringVisitor(
|
||||
@ -101,6 +117,7 @@ public class ConfigInjectClassTransformer extends ClassVisitor {
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
|
||||
ensureCategory();
|
||||
if ((access & ACC_STATIC) == ACC_STATIC) {
|
||||
return new FieldMetaGatheringVisitor(super.visitField(access, name, descriptor, signature, value), name, values, Type.getType(descriptor));
|
||||
}
|
||||
@ -109,7 +126,8 @@ public class ConfigInjectClassTransformer extends ClassVisitor {
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
if (mode == TransformerMode.CONFIG_ROOT) {
|
||||
ensureCategory();
|
||||
if (isConfig()) {
|
||||
if (!initFound) {
|
||||
// Generate <clinit> if missing
|
||||
GeneratorAdapter2 m = method(ACC_PRIVATE | ACC_STATIC, CLINIT, "()V", null, null);
|
||||
@ -150,9 +168,8 @@ public class ConfigInjectClassTransformer extends ClassVisitor {
|
||||
m.endMethod();
|
||||
}
|
||||
}
|
||||
if (mode != TransformerMode.OTHER) {
|
||||
boolean root = mode == TransformerMode.CONFIG_ROOT;
|
||||
Type builderType = root ? CONFIG_BUILDER_TYPE : CATEGORY_BUILDER_TYPE;
|
||||
{
|
||||
Type builderType = isConfig() ? CONFIG_BUILDER_TYPE : CATEGORY_BUILDER_TYPE;
|
||||
GeneratorAdapter2 m = method(ACC_PRIVATE | ACC_STATIC, BUILDER_ROOT, getMethodDescriptor(builderType, builderType), null, null);
|
||||
m.loadArg(0);
|
||||
for (String name : referencedConfigs) {
|
||||
@ -195,10 +212,9 @@ public class ConfigInjectClassTransformer extends ClassVisitor {
|
||||
}
|
||||
|
||||
public void dslInvoke(GeneratorAdapter m, String name, Type returnType, Type... arguments) {
|
||||
boolean root = mode == TransformerMode.CONFIG_ROOT;
|
||||
Type builderType = root ? CONFIG_BUILDER_TYPE : CATEGORY_BUILDER_TYPE;
|
||||
Type builderType = isConfig() ? CONFIG_BUILDER_TYPE : CATEGORY_BUILDER_TYPE;
|
||||
m.invokeInterface(builderType, new Method(name, returnType, arguments));
|
||||
if (root) m.checkCast(CONFIG_BUILDER_TYPE);
|
||||
if (isConfig()) m.checkCast(CONFIG_BUILDER_TYPE);
|
||||
}
|
||||
|
||||
private String camelCase(String s) {
|
||||
|
@ -0,0 +1,7 @@
|
||||
package io.gitlab.jfronny.libjf.config.plugin.asm;
|
||||
|
||||
public class NotAConfigClassException extends RuntimeException {
|
||||
public NotAConfigClassException() {
|
||||
super("This class is not a config class and should not be modified");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user