Skip to content
This repository has been archived by the owner on Jun 8, 2024. It is now read-only.

Commit

Permalink
Improve debug output, update javapoet (#32)
Browse files Browse the repository at this point in the history
* Update gradle

* Fix test eclipse java compiler compatbility

* Always dump class name on errors, remove some streams, reformat

* Bump javapoet

* Update javapoet
  • Loading branch information
sfPlayer1 authored May 15, 2024
1 parent 6c09b18 commit eef318f
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 55 deletions.
5 changes: 3 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
plugins {
id 'java'
id 'eclipse'
id 'maven-publish'
id 'com.diffplug.spotless' version '5.8.2'
}

group 'net.fabricmc'
version '0.4.1'
version '0.4.2'

def ENV = System.getenv()
version = version + (ENV.GITHUB_ACTIONS ? "" : "+local")
Expand All @@ -19,7 +20,7 @@ repositories {
}

dependencies {
implementation 'net.fabricmc:javapoet:0.1.0'
implementation 'net.fabricmc:javapoet:0.1.1'
implementation 'net.fabricmc:mapping-io:0.4.0'

implementation 'org.ow2.asm:asm:9.7'
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
71 changes: 47 additions & 24 deletions src/main/java/net/fabricmc/mappingpoet/ClassBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@
*/
package net.fabricmc.mappingpoet;

import static net.fabricmc.mappingpoet.FieldBuilder.parseAnnotation;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import net.fabricmc.mappingpoet.signature.AnnotationAwareDescriptors;
import net.fabricmc.mappingpoet.signature.AnnotationAwareSignatures;
import net.fabricmc.mappingpoet.signature.ClassSignature;
import net.fabricmc.mappingpoet.signature.TypeAnnotationMapping;
import net.fabricmc.mappingpoet.signature.TypeAnnotationStorage;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypeReference;
Expand All @@ -36,20 +37,19 @@
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.MethodNode;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import static net.fabricmc.mappingpoet.FieldBuilder.parseAnnotation;
import net.fabricmc.mappingpoet.signature.AnnotationAwareDescriptors;
import net.fabricmc.mappingpoet.signature.AnnotationAwareSignatures;
import net.fabricmc.mappingpoet.signature.ClassSignature;
import net.fabricmc.mappingpoet.signature.TypeAnnotationMapping;
import net.fabricmc.mappingpoet.signature.TypeAnnotationStorage;

public class ClassBuilder {
static final Handle OBJ_MTH_BOOTSTRAP = new Handle(
Opcodes.H_INVOKESTATIC,
"java/lang/runtime/ObjectMethods",
"bootstrap",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;",
false
);
false);

private final MappingsStore mappings;
private final ClassNode classNode;
Expand Down Expand Up @@ -131,14 +131,17 @@ public void addMembers() {
}

private ClassSignature setupSignature() {
return classNode.signature == null ?
AnnotationAwareDescriptors.parse(classNode.superName, classNode.interfaces, typeAnnotations, environment) :
AnnotationAwareSignatures.parseClassSignature(classNode.signature, typeAnnotations, environment);
if (classNode.signature == null) {
return AnnotationAwareDescriptors.parse(classNode.superName, classNode.interfaces, typeAnnotations, environment);
} else {
return AnnotationAwareSignatures.parseClassSignature(classNode.signature, typeAnnotations, environment);
}
}

private TypeSpec.Builder setupBuilder() {
TypeSpec.Builder builder;
ClassName name = parseInternalName(classNode.name); // no type anno here

if (Modifier.isInterface(classNode.access)) {
if (classNode.interfaces.size() == 1 && classNode.interfaces.get(0).equals("java/lang/annotation/Annotation")) {
builder = TypeSpec.annotationBuilder(name);
Expand Down Expand Up @@ -172,18 +175,19 @@ private TypeSpec.Builder setupBuilder() {
return builder
.addModifiers(new ModifierBuilder(classNode.access)
.checkUnseal(classNode, environment)
.getModifiers(ModifierBuilder.getType(enumClass, recordClass))
);
.getModifiers(ModifierBuilder.getType(enumClass, recordClass)));
}

private void addInterfaces() {
if (annotationClass) {
return;
}

if (signature != null) {
builder.addSuperinterfaces(signature.superinterfaces());
return;
}

if (classNode.interfaces.isEmpty()) return;

for (String iFace : classNode.interfaces) {
Expand All @@ -201,34 +205,41 @@ private void addDirectAnnotations(List<AnnotationNode> regularAnnotations) {
if (regularAnnotations == null) {
return;
}

for (AnnotationNode annotation : regularAnnotations) {
builder.addAnnotation(parseAnnotation(annotation));
}
}

private void addMethods() {
if (classNode.methods == null) return;
methodsLoop:
for (MethodNode method : classNode.methods) {

methodsLoop: for (MethodNode method : classNode.methods) {
if ((method.access & Opcodes.ACC_SYNTHETIC) != 0 || (method.access & Opcodes.ACC_MANDATED) != 0) {
continue;
}

if (method.name.equals("<clinit>")) {
continue;
}

int formalParamStartIndex = 0;

if (enumClass) {
// Skip enum sugar methods
if (method.name.equals("values") && method.desc.equals("()[L" + classNode.name + ";")) {
continue;
}

if (method.name.equals("valueOf") && method.desc.equals("(Ljava/lang/String;)L" + classNode.name + ";")) {
continue;
}

if (method.name.equals("<init>")) {
formalParamStartIndex = 2; // 0 String 1 int
}
}

if (recordClass) {
// skip record sugars
if (method.name.equals("equals") && method.desc.equals("(Ljava/lang/Object;)Z")
Expand All @@ -244,17 +255,20 @@ private void addMethods() {

// todo test component getters
}

if (instanceInner) {
if (method.name.equals("<init>")) {
formalParamStartIndex = 1; // 0 this$0
}
}

builder.addMethod(new MethodBuilder(mappings, classNode, method, environment, receiverSignature, formalParamStartIndex).build());
}
}

private void addFields() {
if (classNode.fields == null) return;

for (FieldNode field : classNode.fields) {
if (recordClass && !Modifier.isStatic(field.access)) {
// proguard elevates record field access for direct record field gets
Expand All @@ -270,9 +284,11 @@ private void addFields() {

continue;
}

if ((field.access & Opcodes.ACC_SYNTHETIC) != 0 || (field.access & Opcodes.ACC_MANDATED) != 0) {
continue; // hide synthetic stuff
}

if ((field.access & Opcodes.ACC_ENUM) == 0) {
builder.addField(new FieldBuilder(mappings, classNode, field, environment).build());
} else {
Expand All @@ -288,6 +304,7 @@ private void addFields() {
.add(field.visibleTypeAnnotations)
.build().getBank(TypeReference.newTypeReference(TypeReference.FIELD))
.getCurrentAnnotations();

if (!annotations.isEmpty()) {
enumBuilder.addAnnotations(annotations); // no custom paths for annotations rip
}
Expand All @@ -301,6 +318,7 @@ private void addDirectAnnotations(TypeSpec.Builder builder, List<AnnotationNode>
if (regularAnnotations == null) {
return;
}

for (AnnotationNode annotation : regularAnnotations) {
builder.addAnnotation(parseAnnotation(annotation));
}
Expand All @@ -312,6 +330,7 @@ private void addJavaDoc() {

public void addInnerClass(ClassBuilder classBuilder) {
InnerClassNode innerClassNode = null;

if (classNode.innerClasses != null) {
for (InnerClassNode node : classNode.innerClasses) {
if (node.name.equals(classBuilder.classNode.name)) {
Expand Down Expand Up @@ -339,8 +358,8 @@ public void addInnerClass(ClassBuilder classBuilder) {
classBuilder.builder.modifiers.remove(javax.lang.model.element.Modifier.PUBLIC); // this modifier may come from class access
classBuilder.builder.addModifiers(new ModifierBuilder(innerClassNode.access)
.checkUnseal(classBuilder.classNode, environment)
.getModifiers(ModifierBuilder.getType(classBuilder.enumClass, classBuilder.recordClass))
);
.getModifiers(ModifierBuilder.getType(classBuilder.enumClass, classBuilder.recordClass)));

if (!Modifier.isStatic(innerClassNode.access)) {
classBuilder.instanceInner = true;
}
Expand All @@ -352,16 +371,19 @@ public void addInnerClass(ClassBuilder classBuilder) {
sb.append(innerClassNode.innerName); // append simple name

List<TypeVariableName> innerClassGenerics = classBuilder.signature.generics();

if (!innerClassGenerics.isEmpty()) {
sb.append("<");
for (TypeVariableName each : innerClassGenerics) {
sb.append("T").append(each.name).append(";");
}
sb.append(">");
}

classBuilder.receiverSignature = sb.toString();
}
}

innerClasses.add(classBuilder);
}

Expand All @@ -370,9 +392,10 @@ public String getClassName() {
}

public TypeSpec build() {
innerClasses.stream()
.map(ClassBuilder::build)
.forEach(builder::addType);
for (ClassBuilder innerCb : innerClasses) {
builder.addType(innerCb.build());
}

return builder.build();
}
}
53 changes: 27 additions & 26 deletions src/main/java/net/fabricmc/mappingpoet/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,6 @@
*/
package net.fabricmc.mappingpoet;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import net.fabricmc.mappingpoet.Environment.ClassNamePointer;
import net.fabricmc.mappingpoet.Environment.NestedClassInfo;
import net.fabricmc.mappingpoet.signature.ClassStaticContext;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InnerClassNode;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -50,6 +39,16 @@
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import com.squareup.javapoet.JavaFile;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InnerClassNode;

import net.fabricmc.mappingpoet.Environment.ClassNamePointer;
import net.fabricmc.mappingpoet.Environment.NestedClassInfo;

public class Main {

public static void main(String[] args) {
Expand All @@ -66,8 +65,8 @@ public static void main(String[] args) {
if (Files.exists(outputDirectory)) {
try (var stream = Files.walk(outputDirectory)) {
stream.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
.map(Path::toFile)
.forEach(File::delete);
}
}

Expand All @@ -94,20 +93,20 @@ public static void generate(Path mappings, Path inputJar, Path outputDirectory,
Map<String, ClassBuilder> classes = new HashMap<>();
forEachClass(inputJar, (classNode, environment) -> writeClass(mapping, classNode, classes, environment), librariesDir);

classes.values().stream()
.filter(classBuilder -> !classBuilder.getClassName().contains("$"))
.forEach(classBuilder -> {
int packageEnd = classBuilder.getClassName().lastIndexOf("/");
JavaFile javaFile = JavaFile.builder(packageEnd == -1 ? "" : classBuilder.getClassName().substring(0, packageEnd).replaceAll("/", "."), classBuilder.build())
.build();
try {
javaFile.writeTo(outputDirectory);
} catch (IOException e) {
throw new RuntimeException("Failed to write class", e);
}
});
for (ClassBuilder classBuilder : classes.values()) {
String name = classBuilder.getClassName();
if (name.contains("$")) continue;

try {
int packageEnd = classBuilder.getClassName().lastIndexOf("/");
String pkgName = packageEnd < 0 ? "" : classBuilder.getClassName().substring(0, packageEnd).replaceAll("/", ".");
JavaFile javaFile = JavaFile.builder(pkgName, classBuilder.build()).build();

javaFile.writeTo(outputDirectory);
} catch (Throwable t) {
throw new RuntimeException("Failed to process class "+name, t);
}
}
}

private static void forEachClass(Path jar, ClassNodeConsumer classNodeConsumer, Path librariesDir) {
Expand Down Expand Up @@ -170,7 +169,9 @@ private static void forEachClass(Path jar, ClassNodeConsumer classNodeConsumer,
//Sort all the classes making sure that inner classes come after the parent classes
classes.sort(Comparator.comparing(o -> o.name));

classes.forEach(node -> classNodeConsumer.accept(node, new Environment(supers, sealedClasses, nestedClasses)));
for (ClassNode node : classes) {
classNodeConsumer.accept(node, new Environment(supers, sealedClasses, nestedClasses));
}
}

private static void scanNestedClasses(Map<String, ClassNamePointer> classNames, Map<String, Environment.NestedClassInfo> instanceInnerClasses, Path librariesDir) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/net/fabricmc/mappingpoet/TestAnno.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@Target({ElementType.TYPE_USE, ElementType.FIELD})
public @interface TestAnno {
String value() default "";
}
2 changes: 1 addition & 1 deletion src/test/java/net/fabricmc/mappingpoet/TestOuter.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class InnerThree<E> {
class OuterTwo<T> {
static class InnerOne<G> {
class InnerTwo {
InnerTwo(InnerOne<G>net.fabricmc.mappingpoet.OuterTwo.InnerOne.this) {
InnerTwo(InnerOne<G>InnerOne.this) {

}

Expand Down

0 comments on commit eef318f

Please sign in to comment.