Format mapping poet code

This commit is contained in:
modmuss50 2024-05-17 19:05:06 +01:00
parent 02bc5e4a81
commit 48cf4b54d0
20 changed files with 526 additions and 348 deletions

View File

@ -39,6 +39,7 @@ dependencies {
implementation "net.fabricmc:mappingpoet:$properties.mappingpoet_version" implementation "net.fabricmc:mappingpoet:$properties.mappingpoet_version"
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.2' implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.2'
implementation 'net.fabricmc:mapping-io:0.5.1' implementation 'net.fabricmc:mapping-io:0.5.1'
implementation 'net.fabricmc:javapoet:0.1.1'
// Contains a number of useful utilities we can re-use. // Contains a number of useful utilities we can re-use.
implementation ("net.fabricmc:fabric-loom:1.5.7") { implementation ("net.fabricmc:fabric-loom:1.5.7") {

View File

@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
import static net.fabricmc.mappingpoet.FieldBuilder.parseAnnotation; package net.fabricmc.filament.mappingpoet;
import static net.fabricmc.filament.mappingpoet.FieldBuilder.parseAnnotation;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
@ -37,11 +38,11 @@ import org.objectweb.asm.tree.InnerClassNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode; import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MethodNode;
import net.fabricmc.mappingpoet.signature.AnnotationAwareDescriptors; import net.fabricmc.filament.mappingpoet.signature.AnnotationAwareDescriptors;
import net.fabricmc.mappingpoet.signature.AnnotationAwareSignatures; import net.fabricmc.filament.mappingpoet.signature.AnnotationAwareSignatures;
import net.fabricmc.mappingpoet.signature.ClassSignature; import net.fabricmc.filament.mappingpoet.signature.ClassSignature;
import net.fabricmc.mappingpoet.signature.TypeAnnotationMapping; import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationMapping;
import net.fabricmc.mappingpoet.signature.TypeAnnotationStorage; import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationStorage;
public class ClassBuilder { public class ClassBuilder {
static final Handle OBJ_MTH_BOOTSTRAP = new Handle( static final Handle OBJ_MTH_BOOTSTRAP = new Handle(
@ -88,6 +89,7 @@ public class ClassBuilder {
ClassName currentClassName = null; ClassName currentClassName = null;
char ch; char ch;
do { do {
ch = index == internalName.length() ? ';' : internalName.charAt(index); ch = index == internalName.length() ? ';' : internalName.charAt(index);
@ -165,9 +167,11 @@ public class ClassBuilder {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(classNode.name); sb.append(classNode.name);
sb.append("<"); sb.append("<");
for (TypeVariableName each : signature.generics()) { for (TypeVariableName each : signature.generics()) {
sb.append("T").append(each.name).append(";"); sb.append("T").append(each.name).append(";");
} }
sb.append(">"); sb.append(">");
receiverSignature = sb.toString(); receiverSignature = sb.toString();
} }
@ -248,8 +252,9 @@ public class ClassBuilder {
for (AbstractInsnNode insn : method.instructions) { for (AbstractInsnNode insn : method.instructions) {
if (insn instanceof InvokeDynamicInsnNode indy if (insn instanceof InvokeDynamicInsnNode indy
&& indy.bsm.equals(OBJ_MTH_BOOTSTRAP) && indy.bsm.equals(OBJ_MTH_BOOTSTRAP)
&& indy.name.equals(method.name)) && indy.name.equals(method.name)) {
continue methodsLoop; continue methodsLoop;
}
} }
} }
@ -318,7 +323,7 @@ public class ClassBuilder {
if (regularAnnotations == null) { if (regularAnnotations == null) {
return; return;
} }
for (AnnotationNode annotation : regularAnnotations) { for (AnnotationNode annotation : regularAnnotations) {
builder.addAnnotation(parseAnnotation(annotation)); builder.addAnnotation(parseAnnotation(annotation));
} }
@ -363,6 +368,7 @@ public class ClassBuilder {
if (!Modifier.isStatic(innerClassNode.access)) { if (!Modifier.isStatic(innerClassNode.access)) {
classBuilder.instanceInner = true; classBuilder.instanceInner = true;
} }
// consider emit warning if this.instanceInner is true when classBuilder.instanceInner is false // consider emit warning if this.instanceInner is true when classBuilder.instanceInner is false
if (this.receiverSignature != null && classBuilder.instanceInner) { if (this.receiverSignature != null && classBuilder.instanceInner) {
@ -374,9 +380,11 @@ public class ClassBuilder {
if (!innerClassGenerics.isEmpty()) { if (!innerClassGenerics.isEmpty()) {
sb.append("<"); sb.append("<");
for (TypeVariableName each : innerClassGenerics) { for (TypeVariableName each : innerClassGenerics) {
sb.append("T").append(each.name).append(";"); sb.append("T").append(each.name).append(";");
} }
sb.append(">"); sb.append(">");
} }

View File

@ -13,15 +13,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
import com.squareup.javapoet.ClassName; package net.fabricmc.filament.mappingpoet;
import net.fabricmc.mappingpoet.signature.ClassStaticContext;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.squareup.javapoet.ClassName;
import net.fabricmc.filament.mappingpoet.signature.ClassStaticContext;
/** /**
* Represents an overall runtime environment, knows all inner class, * Represents an overall runtime environment, knows all inner class,
* super class, etc. information. * super class, etc. information.
@ -39,8 +41,9 @@ public record Environment(
public record ClassNamePointer(String simple, String outerClass) { public record ClassNamePointer(String simple, String outerClass) {
public ClassName toClassName(ClassName outerClassName) { public ClassName toClassName(ClassName outerClassName) {
if (simple == null) if (simple == null) {
return null; return null;
}
return outerClassName.nestedClass(simple); return outerClassName.nestedClass(simple);
} }

View File

@ -13,7 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
package net.fabricmc.filament.mappingpoet;
import java.util.AbstractMap;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ArrayTypeName; import com.squareup.javapoet.ArrayTypeName;
@ -23,12 +31,6 @@ import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeSpec;
import net.fabricmc.mappingpoet.signature.AnnotationAwareDescriptors;
import net.fabricmc.mappingpoet.signature.AnnotationAwareSignatures;
import net.fabricmc.mappingpoet.signature.ClassStaticContext;
import net.fabricmc.mappingpoet.signature.TypeAnnotationBank;
import net.fabricmc.mappingpoet.signature.TypeAnnotationMapping;
import net.fabricmc.mappingpoet.signature.TypeAnnotationStorage;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.TypePath; import org.objectweb.asm.TypePath;
@ -37,12 +39,12 @@ import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.FieldNode;
import java.util.AbstractMap; import net.fabricmc.filament.mappingpoet.signature.AnnotationAwareDescriptors;
import java.util.ArrayDeque; import net.fabricmc.filament.mappingpoet.signature.AnnotationAwareSignatures;
import java.util.Deque; import net.fabricmc.filament.mappingpoet.signature.ClassStaticContext;
import java.util.Iterator; import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationBank;
import java.util.List; import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationMapping;
import java.util.Map; import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationStorage;
public class FieldBuilder { public class FieldBuilder {
private final MappingsStore mappings; private final MappingsStore mappings;
@ -74,8 +76,10 @@ public class FieldBuilder {
ClassName annoClassName = (ClassName) typeFromDesc(annotation.desc); ClassName annoClassName = (ClassName) typeFromDesc(annotation.desc);
AnnotationSpec.Builder builder = AnnotationSpec.builder(annoClassName); AnnotationSpec.Builder builder = AnnotationSpec.builder(annoClassName);
List<Object> values = annotation.values; List<Object> values = annotation.values;
if (values != null) { if (values != null) {
Iterator<?> itr = values.iterator(); Iterator<?> itr = values.iterator();
while (itr.hasNext()) { while (itr.hasNext()) {
String key = (String) itr.next(); String key = (String) itr.next();
Object value = itr.next(); Object value = itr.next();
@ -92,24 +96,30 @@ public class FieldBuilder {
if (value instanceof List) { if (value instanceof List) {
return ((List<?>) value).stream().map(FieldBuilder::codeFromAnnoValue).collect(CodeBlock.joining(",", "{", "}")); return ((List<?>) value).stream().map(FieldBuilder::codeFromAnnoValue).collect(CodeBlock.joining(",", "{", "}"));
} }
if (value instanceof Character || value instanceof Number || value instanceof Boolean) { if (value instanceof Character || value instanceof Number || value instanceof Boolean) {
return CodeBlock.builder().add("$L", value).build(); return CodeBlock.builder().add("$L", value).build();
} }
if (value instanceof String) { if (value instanceof String) {
return CodeBlock.builder().add("$S", value).build(); return CodeBlock.builder().add("$S", value).build();
} }
if (value instanceof String[]) { if (value instanceof String[]) {
String[] arr = (String[]) value; String[] arr = (String[]) value;
ClassName enumClassName = (ClassName) typeFromDesc(arr[0]); ClassName enumClassName = (ClassName) typeFromDesc(arr[0]);
String valueName = arr[1]; String valueName = arr[1];
return CodeBlock.builder().add("$T.$L", enumClassName, valueName).build(); return CodeBlock.builder().add("$T.$L", enumClassName, valueName).build();
} }
if (value instanceof Type) { if (value instanceof Type) {
return CodeBlock.builder().add("$T.class", typeFromDesc(((Type) value).getDescriptor())).build(); return CodeBlock.builder().add("$T.class", typeFromDesc(((Type) value).getDescriptor())).build();
} }
if (value instanceof AnnotationNode) { if (value instanceof AnnotationNode) {
return CodeBlock.builder().add(parseAnnotation((AnnotationNode) value).toString()).build(); return CodeBlock.builder().add(parseAnnotation((AnnotationNode) value).toString()).build();
} }
throw new IllegalArgumentException(String.format("Don't know how to convert \"%s\" into annotation value", value)); throw new IllegalArgumentException(String.format("Don't know how to convert \"%s\" into annotation value", value));
} }
@ -120,6 +130,7 @@ public class FieldBuilder {
public static Map.Entry<Integer, TypeName> parseType(final String desc, final int start) { public static Map.Entry<Integer, TypeName> parseType(final String desc, final int start) {
int index = start; int index = start;
int arrayLevel = 0; int arrayLevel = 0;
while (desc.charAt(index) == '[') { while (desc.charAt(index) == '[') {
arrayLevel++; arrayLevel++;
index++; index++;
@ -127,90 +138,91 @@ public class FieldBuilder {
TypeName current; TypeName current;
switch (desc.charAt(index)) { switch (desc.charAt(index)) {
case 'B': { case 'B': {
current = TypeName.BYTE; current = TypeName.BYTE;
index++; index++;
break; break;
} }
case 'C': { case 'C': {
current = TypeName.CHAR; current = TypeName.CHAR;
index++; index++;
break; break;
} }
case 'D': { case 'D': {
current = TypeName.DOUBLE; current = TypeName.DOUBLE;
index++; index++;
break; break;
} }
case 'F': { case 'F': {
current = TypeName.FLOAT; current = TypeName.FLOAT;
index++; index++;
break; break;
} }
case 'I': { case 'I': {
current = TypeName.INT; current = TypeName.INT;
index++; index++;
break; break;
} }
case 'J': { case 'J': {
current = TypeName.LONG; current = TypeName.LONG;
index++; index++;
break; break;
} }
case 'S': { case 'S': {
current = TypeName.SHORT; current = TypeName.SHORT;
index++; index++;
break; break;
} }
case 'Z': { case 'Z': {
current = TypeName.BOOLEAN; current = TypeName.BOOLEAN;
index++; index++;
break; break;
} }
case 'V': { case 'V': {
current = TypeName.VOID; current = TypeName.VOID;
index++; index++;
break; break;
} }
case 'L': { case 'L': {
int classNameSeparator = index; int classNameSeparator = index;
index++; index++;
int nameStart = index; int nameStart = index;
ClassName currentClassName = null; ClassName currentClassName = null;
char ch; char ch;
do {
ch = desc.charAt(index);
if (ch == '$' || ch == ';') { do {
// collect class name ch = desc.charAt(index);
if (currentClassName == null) {
String packageName = nameStart < classNameSeparator ? desc.substring(nameStart, classNameSeparator).replace('/', '.') : ""; if (ch == '$' || ch == ';') {
String simpleName = desc.substring(classNameSeparator + 1, index); // collect class name
currentClassName = ClassName.get(packageName, simpleName); if (currentClassName == null) {
} else { String packageName = nameStart < classNameSeparator ? desc.substring(nameStart, classNameSeparator).replace('/', '.') : "";
String simpleName = desc.substring(classNameSeparator + 1, index); String simpleName = desc.substring(classNameSeparator + 1, index);
currentClassName = currentClassName.nestedClass(simpleName); currentClassName = ClassName.get(packageName, simpleName);
} } else {
String simpleName = desc.substring(classNameSeparator + 1, index);
currentClassName = currentClassName.nestedClass(simpleName);
} }
if (ch == '/' || ch == '$') {
// Start of simple name
classNameSeparator = index;
}
index++;
} while (ch != ';');
if (currentClassName == null) {
throw invalidDesc(desc, index);
} }
current = currentClassName; if (ch == '/' || ch == '$') {
break; // Start of simple name
} classNameSeparator = index;
default: }
index++;
} while (ch != ';');
if (currentClassName == null) {
throw invalidDesc(desc, index); throw invalidDesc(desc, index);
}
current = currentClassName;
break;
}
default:
throw invalidDesc(desc, index);
} }
for (int i = 0; i < arrayLevel; i++) { for (int i = 0; i < arrayLevel; i++) {
@ -223,6 +235,7 @@ public class FieldBuilder {
public static Map.Entry<Integer, TypeName> parseAnnotatedType(final String desc, final int start, TypeAnnotationBank annotations, ClassStaticContext context) { public static Map.Entry<Integer, TypeName> parseAnnotatedType(final String desc, final int start, TypeAnnotationBank annotations, ClassStaticContext context) {
int index = start; int index = start;
Deque<List<AnnotationSpec>> arrayAnnos = new ArrayDeque<>(); Deque<List<AnnotationSpec>> arrayAnnos = new ArrayDeque<>();
while (desc.charAt(index) == '[') { while (desc.charAt(index) == '[') {
arrayAnnos.push(annotations.getCurrentAnnotations()); arrayAnnos.push(annotations.getCurrentAnnotations());
annotations = annotations.advance(TypePath.ARRAY_ELEMENT, 0); annotations = annotations.advance(TypePath.ARRAY_ELEMENT, 0);
@ -231,106 +244,108 @@ public class FieldBuilder {
TypeName current; TypeName current;
switch (desc.charAt(index)) { switch (desc.charAt(index)) {
case 'B': { case 'B': {
current = TypeName.BYTE; current = TypeName.BYTE;
index++; index++;
break; break;
} }
case 'C': { case 'C': {
current = TypeName.CHAR; current = TypeName.CHAR;
index++; index++;
break; break;
} }
case 'D': { case 'D': {
current = TypeName.DOUBLE; current = TypeName.DOUBLE;
index++; index++;
break; break;
} }
case 'F': { case 'F': {
current = TypeName.FLOAT; current = TypeName.FLOAT;
index++; index++;
break; break;
} }
case 'I': { case 'I': {
current = TypeName.INT; current = TypeName.INT;
index++; index++;
break; break;
} }
case 'J': { case 'J': {
current = TypeName.LONG; current = TypeName.LONG;
index++; index++;
break; break;
} }
case 'S': { case 'S': {
current = TypeName.SHORT; current = TypeName.SHORT;
index++; index++;
break; break;
} }
case 'Z': { case 'Z': {
current = TypeName.BOOLEAN; current = TypeName.BOOLEAN;
index++; index++;
break; break;
} }
case 'V': { case 'V': {
current = TypeName.VOID; current = TypeName.VOID;
index++; index++;
break; break;
} }
case 'L': { case 'L': {
int classNameSeparator = index; int classNameSeparator = index;
index++; index++;
int nameStart = index; int nameStart = index;
ClassName currentClassName = null; ClassName currentClassName = null;
boolean instanceInner = false; boolean instanceInner = false;
char ch; char ch;
do {
ch = desc.charAt(index);
if (ch == '$' || ch == ';') { do {
// collect class name ch = desc.charAt(index);
if (currentClassName == null) {
String packageName = nameStart < classNameSeparator ? desc.substring(nameStart, classNameSeparator).replace('/', '.') : "";
String simpleName = desc.substring(classNameSeparator + 1, index);
currentClassName = ClassName.get(packageName, simpleName);
} else {
String simpleName = desc.substring(classNameSeparator + 1, index);
if (!instanceInner && context.isInstanceInner(desc.substring(nameStart, index))) { if (ch == '$' || ch == ';') {
instanceInner = true; // collect class name
} if (currentClassName == null) {
String packageName = nameStart < classNameSeparator ? desc.substring(nameStart, classNameSeparator).replace('/', '.') : "";
String simpleName = desc.substring(classNameSeparator + 1, index);
currentClassName = ClassName.get(packageName, simpleName);
} else {
String simpleName = desc.substring(classNameSeparator + 1, index);
currentClassName = currentClassName.nestedClass(simpleName); if (!instanceInner && context.isInstanceInner(desc.substring(nameStart, index))) {
instanceInner = true;
}
if (instanceInner) { currentClassName = currentClassName.nestedClass(simpleName);
currentClassName = AnnotationAwareDescriptors.annotate(currentClassName, annotations);
annotations = annotations.advance(TypePath.INNER_TYPE, 0); if (instanceInner) {
} currentClassName = AnnotationAwareDescriptors.annotate(currentClassName, annotations);
annotations = annotations.advance(TypePath.INNER_TYPE, 0);
} }
} }
if (ch == '/' || ch == '$') {
// Start of simple name
classNameSeparator = index;
}
index++;
} while (ch != ';');
if (currentClassName == null) {
throw invalidDesc(desc, index);
} }
current = currentClassName; if (ch == '/' || ch == '$') {
break; // Start of simple name
} classNameSeparator = index;
default: }
index++;
} while (ch != ';');
if (currentClassName == null) {
throw invalidDesc(desc, index); throw invalidDesc(desc, index);
}
current = currentClassName;
break;
}
default:
throw invalidDesc(desc, index);
} }
while (!arrayAnnos.isEmpty()) { while (!arrayAnnos.isEmpty()) {
current = ArrayTypeName.of(current); current = ArrayTypeName.of(current);
List<AnnotationSpec> currentAnnos = arrayAnnos.pop(); List<AnnotationSpec> currentAnnos = arrayAnnos.pop();
if (!currentAnnos.isEmpty()) { if (!currentAnnos.isEmpty()) {
current = current.annotated(currentAnnos); current = current.annotated(currentAnnos);
} }
@ -346,31 +361,34 @@ public class FieldBuilder {
@Deprecated // use typeFromDesc, non-recursive @Deprecated // use typeFromDesc, non-recursive
public static TypeName getFieldType(String desc) { public static TypeName getFieldType(String desc) {
switch (desc) { switch (desc) {
case "B": case "B":
return TypeName.BYTE; return TypeName.BYTE;
case "C": case "C":
return TypeName.CHAR; return TypeName.CHAR;
case "S": case "S":
return TypeName.SHORT; return TypeName.SHORT;
case "Z": case "Z":
return TypeName.BOOLEAN; return TypeName.BOOLEAN;
case "I": case "I":
return TypeName.INT; return TypeName.INT;
case "J": case "J":
return TypeName.LONG; return TypeName.LONG;
case "F": case "F":
return TypeName.FLOAT; return TypeName.FLOAT;
case "D": case "D":
return TypeName.DOUBLE; return TypeName.DOUBLE;
case "V": case "V":
return TypeName.VOID; return TypeName.VOID;
} }
if (desc.startsWith("[")) { if (desc.startsWith("[")) {
return ArrayTypeName.of(getFieldType(desc.substring(1))); return ArrayTypeName.of(getFieldType(desc.substring(1)));
} }
if (desc.startsWith("L")) { if (desc.startsWith("L")) {
return ClassBuilder.parseInternalName(desc.substring(1).substring(0, desc.length() - 2)); return ClassBuilder.parseInternalName(desc.substring(1).substring(0, desc.length() - 2));
} }
throw new UnsupportedOperationException("Unknown field type" + desc); throw new UnsupportedOperationException("Unknown field type" + desc);
} }
@ -388,56 +406,65 @@ public class FieldBuilder {
private CodeBlock makeInitializer(String desc) { private CodeBlock makeInitializer(String desc) {
// fake initializers exclude fields from constant values // fake initializers exclude fields from constant values
switch (desc.charAt(0)) { switch (desc.charAt(0)) {
case 'B': case 'B':
if (fieldNode.value instanceof Integer) { if (fieldNode.value instanceof Integer) {
return CodeBlock.builder().add("(byte) $L", fieldNode.value).build(); return CodeBlock.builder().add("(byte) $L", fieldNode.value).build();
} }
// fake initializer falls through
case 'C': // fake initializer falls through
if (fieldNode.value instanceof Integer) { case 'C':
int value = (int) fieldNode.value; if (fieldNode.value instanceof Integer) {
char c = (char) value; int value = (int) fieldNode.value;
return printChar(CodeBlock.builder(), c, value).build(); char c = (char) value;
} return printChar(CodeBlock.builder(), c, value).build();
// fake initializer falls through }
case 'D':
if (fieldNode.value instanceof Double) { // fake initializer falls through
return CodeBlock.builder().add("$LD", fieldNode.value).build(); case 'D':
} if (fieldNode.value instanceof Double) {
// fake initializer falls through return CodeBlock.builder().add("$LD", fieldNode.value).build();
case 'I': }
if (fieldNode.value instanceof Integer) {
return CodeBlock.builder().add("$L", fieldNode.value).build(); // fake initializer falls through
} case 'I':
// fake initializer falls through if (fieldNode.value instanceof Integer) {
case 'J': return CodeBlock.builder().add("$L", fieldNode.value).build();
if (fieldNode.value instanceof Long) { }
return CodeBlock.builder().add("$LL", fieldNode.value).build();
} // fake initializer falls through
// fake initializer falls through case 'J':
case 'S': if (fieldNode.value instanceof Long) {
if (fieldNode.value instanceof Integer) { return CodeBlock.builder().add("$LL", fieldNode.value).build();
return CodeBlock.builder().add("(short) $L", fieldNode.value).build(); }
}
return CodeBlock.builder().add("java.lang.Byte.parseByte(\"dummy\")").build(); // fake initializer falls through
case 'F': case 'S':
if (fieldNode.value instanceof Float) { if (fieldNode.value instanceof Integer) {
return CodeBlock.builder().add("$LF", fieldNode.value).build(); return CodeBlock.builder().add("(short) $L", fieldNode.value).build();
} }
return CodeBlock.builder().add("java.lang.Float.parseFloat(\"dummy\")").build();
case 'Z': return CodeBlock.builder().add("java.lang.Byte.parseByte(\"dummy\")").build();
if (fieldNode.value instanceof Integer) { case 'F':
return CodeBlock.builder().add("$L", ((int) fieldNode.value) != 0).build(); if (fieldNode.value instanceof Float) {
} return CodeBlock.builder().add("$LF", fieldNode.value).build();
return CodeBlock.builder().add("java.lang.Boolean.parseBoolean(\"dummy\")").build(); }
return CodeBlock.builder().add("java.lang.Float.parseFloat(\"dummy\")").build();
case 'Z':
if (fieldNode.value instanceof Integer) {
return CodeBlock.builder().add("$L", ((int) fieldNode.value) != 0).build();
}
return CodeBlock.builder().add("java.lang.Boolean.parseBoolean(\"dummy\")").build();
} }
if (desc.equals("Ljava/lang/String;") && fieldNode.value instanceof String) { if (desc.equals("Ljava/lang/String;") && fieldNode.value instanceof String) {
return CodeBlock.builder().add("$S", fieldNode.value).build(); return CodeBlock.builder().add("$S", fieldNode.value).build();
} }
return CodeBlock.builder().add(desc.equals("Ljava/lang/String;") ? "java.lang.String.valueOf(\"dummy\")" : "null").build(); return CodeBlock.builder().add(desc.equals("Ljava/lang/String;") ? "java.lang.String.valueOf(\"dummy\")" : "null").build();
} }
private static CodeBlock.Builder printChar(CodeBlock.Builder builder, char c, int value) { private static CodeBlock.Builder printChar(CodeBlock.Builder builder, char c, int value) {
if (!Character.isValidCodePoint(value) || !Character.isDefined(value)) { if (!Character.isValidCodePoint(value) || !Character.isDefined(value)) {
return builder.add("(char) $L", value); return builder.add("(char) $L", value);
@ -446,20 +473,20 @@ public class FieldBuilder {
// See https://docs.oracle.com/javase/specs/jls/se16/html/jls-3.html#jls-EscapeSequence // See https://docs.oracle.com/javase/specs/jls/se16/html/jls-3.html#jls-EscapeSequence
// ignore space or ", just use direct in those cases // ignore space or ", just use direct in those cases
switch (c) { switch (c) {
case '\b': case '\b':
return builder.add("'\\b'"); return builder.add("'\\b'");
case '\t': case '\t':
return builder.add("'\\t'"); return builder.add("'\\t'");
case '\n': case '\n':
return builder.add("'\\n'"); return builder.add("'\\n'");
case '\f': case '\f':
return builder.add("'\\f'"); return builder.add("'\\f'");
case '\r': case '\r':
return builder.add("'\\r'"); return builder.add("'\\r'");
case '\'': case '\'':
return builder.add("'\\''"); return builder.add("'\\''");
case '\\': case '\\':
return builder.add("'\\\\'"); return builder.add("'\\\\'");
} }
return builder.add("'$L'", c); return builder.add("'$L'", c);
@ -482,6 +509,7 @@ public class FieldBuilder {
if (regularAnnotations == null) { if (regularAnnotations == null) {
return; return;
} }
for (AnnotationNode annotation : regularAnnotations) { for (AnnotationNode annotation : regularAnnotations) {
builder.addAnnotation(parseAnnotation(annotation)); builder.addAnnotation(parseAnnotation(annotation));
} }
@ -496,6 +524,7 @@ public class FieldBuilder {
if (regularAnnotations == null) { if (regularAnnotations == null) {
return; return;
} }
for (AnnotationNode annotation : regularAnnotations) { for (AnnotationNode annotation : regularAnnotations) {
paramBuilder.addAnnotation(parseAnnotation(annotation)); paramBuilder.addAnnotation(parseAnnotation(annotation));
} }
@ -505,6 +534,7 @@ public class FieldBuilder {
if (fieldNode.signature != null) { if (fieldNode.signature != null) {
return AnnotationAwareSignatures.parseFieldSignature(fieldNode.signature, annotations, context); return AnnotationAwareSignatures.parseFieldSignature(fieldNode.signature, annotations, context);
} }
return parseAnnotatedType(fieldNode.desc, 0, annotations.getBank(TypeReference.newTypeReference(TypeReference.FIELD)), context).getValue(); return parseAnnotatedType(fieldNode.desc, 0, annotations.getBank(TypeReference.newTypeReference(TypeReference.FIELD)), context).getValue();
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
package net.fabricmc.filament.mappingpoet;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -46,16 +47,16 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InnerClassNode; import org.objectweb.asm.tree.InnerClassNode;
import net.fabricmc.mappingpoet.Environment.ClassNamePointer; import net.fabricmc.filament.mappingpoet.Environment.ClassNamePointer;
import net.fabricmc.mappingpoet.Environment.NestedClassInfo; import net.fabricmc.filament.mappingpoet.Environment.NestedClassInfo;
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
if (args.length != 3 && args.length != 4) { if (args.length != 3 && args.length != 4) {
System.out.println("<mappings> <inputJar> <outputDir> [<librariesDir>]"); System.out.println("<mappings> <inputJar> <outputDir> [<librariesDir>]");
return; return;
} }
Path mappings = Paths.get(args[0]); Path mappings = Paths.get(args[0]);
Path inputJar = Paths.get(args[1]); Path inputJar = Paths.get(args[1]);
Path outputDirectory = Paths.get(args[2]); Path outputDirectory = Paths.get(args[2]);
@ -65,8 +66,8 @@ public class Main {
if (Files.exists(outputDirectory)) { if (Files.exists(outputDirectory)) {
try (var stream = Files.walk(outputDirectory)) { try (var stream = Files.walk(outputDirectory)) {
stream.sorted(Comparator.reverseOrder()) stream.sorted(Comparator.reverseOrder())
.map(Path::toFile) .map(Path::toFile)
.forEach(File::delete); .forEach(File::delete);
} }
} }
@ -121,7 +122,7 @@ public class Main {
scanNestedClasses(classNames, nestedClasses, librariesDir); scanNestedClasses(classNames, nestedClasses, librariesDir);
} }
try (final JarFile jarFile = new JarFile(jar.toFile())) { try (JarFile jarFile = new JarFile(jar.toFile())) {
Enumeration<JarEntry> entryEnumerator = jarFile.entries(); Enumeration<JarEntry> entryEnumerator = jarFile.entries();
while (entryEnumerator.hasMoreElements()) { while (entryEnumerator.hasMoreElements()) {
@ -136,12 +137,15 @@ public class Main {
ClassNode classNode = new ClassNode(); ClassNode classNode = new ClassNode();
reader.accept(classNode, ClassReader.SKIP_CODE); reader.accept(classNode, ClassReader.SKIP_CODE);
List<String> superNames = new ArrayList<>(); List<String> superNames = new ArrayList<>();
if (classNode.superName != null && !classNode.superName.equals("java/lang/Object")) { if (classNode.superName != null && !classNode.superName.equals("java/lang/Object")) {
superNames.add(classNode.superName); superNames.add(classNode.superName);
} }
if (classNode.interfaces != null) { if (classNode.interfaces != null) {
superNames.addAll(classNode.interfaces); superNames.addAll(classNode.interfaces);
} }
if (!superNames.isEmpty()) { if (!superNames.isEmpty()) {
supers.put(classNode.name, superNames); supers.put(classNode.name, superNames);
} }
@ -183,7 +187,7 @@ public class Main {
return FileVisitResult.CONTINUE; return FileVisitResult.CONTINUE;
} }
try (final JarFile jarFile = new JarFile(file.toFile())) { try (JarFile jarFile = new JarFile(file.toFile())) {
Enumeration<JarEntry> entryEnumerator = jarFile.entries(); Enumeration<JarEntry> entryEnumerator = jarFile.entries();
while (entryEnumerator.hasMoreElements()) { while (entryEnumerator.hasMoreElements()) {
@ -198,7 +202,8 @@ public class Main {
reader.accept(new ClassVisitor(Opcodes.ASM9) { reader.accept(new ClassVisitor(Opcodes.ASM9) {
@Override @Override
public void visitInnerClass(String name, String outerName, String simpleName, int access) { public void visitInnerClass(String name, String outerName, String simpleName, int access) {
instanceInnerClasses.put(name, new Environment.NestedClassInfo(outerName, !Modifier.isStatic(access), simpleName)); instanceInnerClasses.put(name, new NestedClassInfo(outerName, !Modifier.isStatic(access), simpleName));
if (outerName != null) { if (outerName != null) {
classNames.put(name, new ClassNamePointer(simpleName, outerName)); classNames.put(name, new ClassNamePointer(simpleName, outerName));
} }
@ -234,11 +239,14 @@ public class Main {
private static void writeClass(MappingsStore mappings, ClassNode classNode, Map<String, ClassBuilder> existingClasses, Environment environment) { private static void writeClass(MappingsStore mappings, ClassNode classNode, Map<String, ClassBuilder> existingClasses, Environment environment) {
// TODO make sure named jar has valid InnerClasses, use that info instead // TODO make sure named jar has valid InnerClasses, use that info instead
String name = classNode.name; String name = classNode.name;
{ {
//Block anonymous class and their nested classes //Block anonymous class and their nested classes
int lastSearch = name.length(); int lastSearch = name.length();
while (lastSearch != -1) { while (lastSearch != -1) {
lastSearch = name.lastIndexOf('$', lastSearch - 1); lastSearch = name.lastIndexOf('$', lastSearch - 1);
// names starting with digit is illegal java // names starting with digit is illegal java
if (isDigit(name.charAt(lastSearch + 1))) { if (isDigit(name.charAt(lastSearch + 1))) {
return; return;
@ -251,15 +259,16 @@ public class Main {
if (name.contains("$")) { if (name.contains("$")) {
String parentClass = name.substring(0, name.lastIndexOf("$")); String parentClass = name.substring(0, name.lastIndexOf("$"));
if (!existingClasses.containsKey(parentClass)) { if (!existingClasses.containsKey(parentClass)) {
throw new RuntimeException("Could not find parent class: " + parentClass + " for " + classNode.name); throw new RuntimeException("Could not find parent class: " + parentClass + " for " + classNode.name);
} }
existingClasses.get(parentClass).addInnerClass(classBuilder); existingClasses.get(parentClass).addInnerClass(classBuilder);
} }
classBuilder.addMembers(); classBuilder.addMembers();
existingClasses.put(name, classBuilder); existingClasses.put(name, classBuilder);
} }
@FunctionalInterface @FunctionalInterface

View File

@ -13,7 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
package net.fabricmc.filament.mappingpoet;
import static net.fabricmc.mappingio.tree.MappingTreeView.SRC_NAMESPACE_ID;
import java.io.IOException;
import java.nio.file.Path;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.List;
import java.util.Map;
import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
@ -24,14 +33,6 @@ import net.fabricmc.mappingio.tree.MappingTreeView.ElementMappingView;
import net.fabricmc.mappingio.tree.MappingTreeView.MethodMappingView; import net.fabricmc.mappingio.tree.MappingTreeView.MethodMappingView;
import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree;
import java.io.IOException;
import java.nio.file.Path;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.List;
import java.util.Map;
import static net.fabricmc.mappingio.tree.MappingTreeView.SRC_NAMESPACE_ID;
//Taken from loom //Taken from loom
public class MappingsStore { public class MappingsStore {
private final MappingTreeView tree; private final MappingTreeView tree;
@ -44,16 +45,19 @@ public class MappingsStore {
private static MappingTreeView readMappings(Path input) { private static MappingTreeView readMappings(Path input) {
var tree = new MemoryMappingTree(); var tree = new MemoryMappingTree();
try { try {
MappingReader.read(input, MappingFormat.TINY_2, new MappingSourceNsSwitch(tree, "named")); MappingReader.read(input, MappingFormat.TINY_2_FILE, new MappingSourceNsSwitch(tree, "named"));
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Failed to read mappings", e); throw new RuntimeException("Failed to read mappings", e);
} }
return tree; return tree;
} }
private void addDoc(ElementMappingView element, DocAdder adder) { private void addDoc(ElementMappingView element, DocAdder adder) {
String doc = element.getComment(); String doc = element.getComment();
if (doc != null) { if (doc != null) {
adder.addJavadoc("$L", doc); adder.addJavadoc("$L", doc);
} }
@ -61,11 +65,14 @@ public class MappingsStore {
public void addClassDoc(DocAdder adder, String className) { public void addClassDoc(DocAdder adder, String className) {
var classDef = tree.getClass(className); var classDef = tree.getClass(className);
if (classDef == null) { if (classDef == null) {
return; return;
} }
addDoc(classDef, adder); addDoc(classDef, adder);
adder.addJavadoc("\n"); adder.addJavadoc("\n");
for (int id = SRC_NAMESPACE_ID; id < maxNamespace; id++) { for (int id = SRC_NAMESPACE_ID; id < maxNamespace; id++) {
String transformedName = classDef.getName(id); String transformedName = classDef.getName(id);
adder.addJavadoc("@mapping {@literal $L:$L}\n", tree.getNamespaceName(id), transformedName); adder.addJavadoc("@mapping {@literal $L:$L}\n", tree.getNamespaceName(id), transformedName);
@ -74,17 +81,20 @@ public class MappingsStore {
public void addFieldDoc(DocAdder addJavadoc, String owner, String name, String desc) { public void addFieldDoc(DocAdder addJavadoc, String owner, String name, String desc) {
var classDef = tree.getClass(owner); var classDef = tree.getClass(owner);
if (classDef == null) { if (classDef == null) {
return; return;
} }
var fieldDef = classDef.getField(name, desc); var fieldDef = classDef.getField(name, desc);
if (fieldDef == null) { if (fieldDef == null) {
return; return;
} }
addDoc(fieldDef, addJavadoc); addDoc(fieldDef, addJavadoc);
addJavadoc.addJavadoc("\n"); addJavadoc.addJavadoc("\n");
for (int id = SRC_NAMESPACE_ID; id < maxNamespace; id++) { for (int id = SRC_NAMESPACE_ID; id < maxNamespace; id++) {
String transformedName = fieldDef.getName(id); String transformedName = fieldDef.getName(id);
String mixinForm = "L" + classDef.getName(id) + ";" + transformedName + ":" + fieldDef.getDesc(id); String mixinForm = "L" + classDef.getName(id) + ";" + transformedName + ":" + fieldDef.getDesc(id);
@ -94,11 +104,14 @@ public class MappingsStore {
public Map.Entry<String, String> getParamNameAndDoc(Environment environment, String owner, String name, String desc, int index) { public Map.Entry<String, String> getParamNameAndDoc(Environment environment, String owner, String name, String desc, int index) {
var found = searchMethod(environment, owner, name, desc); var found = searchMethod(environment, owner, name, desc);
if (found != null) { if (found != null) {
var methodDef = found.getValue(); var methodDef = found.getValue();
if (methodDef.getArgs().isEmpty()) { if (methodDef.getArgs().isEmpty()) {
return null; return null;
} }
return methodDef.getArgs().stream() return methodDef.getArgs().stream()
.filter(param -> param.getLvIndex() == index) .filter(param -> param.getLvIndex() == index)
// Map.entry() is null-hostile // Map.entry() is null-hostile
@ -106,17 +119,20 @@ public class MappingsStore {
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
return null; return null;
} }
public void addMethodDoc(DocAdder adder, Environment environment, String owner, String name, String desc) { public void addMethodDoc(DocAdder adder, Environment environment, String owner, String name, String desc) {
var found = searchMethod(environment, owner, name, desc); var found = searchMethod(environment, owner, name, desc);
if (found == null) { if (found == null) {
return; return;
} }
var methodDef = found.getValue(); var methodDef = found.getValue();
var ownerDef = found.getKey(); var ownerDef = found.getKey();
if (!ownerDef.equals(methodDef.getOwner())) { if (!ownerDef.equals(methodDef.getOwner())) {
adder.addJavadoc("{@inheritDoc}"); adder.addJavadoc("{@inheritDoc}");
} else { } else {
@ -124,6 +140,7 @@ public class MappingsStore {
} }
adder.addJavadoc("\n"); adder.addJavadoc("\n");
for (int id = SRC_NAMESPACE_ID; id < maxNamespace; id++) { for (int id = SRC_NAMESPACE_ID; id < maxNamespace; id++) {
String transformedName = methodDef.getName(id); String transformedName = methodDef.getName(id);
String mixinForm = "L" + ownerDef.getName(id) + ";" + transformedName + methodDef.getDesc(id); String mixinForm = "L" + ownerDef.getName(id) + ";" + transformedName + methodDef.getDesc(id);
@ -134,16 +151,19 @@ public class MappingsStore {
private Map.Entry<ClassMappingView, MethodMappingView> searchMethod(Environment environment, String owner, String name, String desc) { private Map.Entry<ClassMappingView, MethodMappingView> searchMethod(Environment environment, String owner, String name, String desc) {
var classDef = tree.getClass(owner); var classDef = tree.getClass(owner);
if (classDef == null) if (classDef == null) {
return null; return null;
}
var methodDef = classDef.getMethod(name, desc); var methodDef = classDef.getMethod(name, desc);
if (methodDef != null)
return Map.entry(methodDef.getOwner(), methodDef);
if (methodDef != null) {
return Map.entry(methodDef.getOwner(), methodDef);
}
for (String superName : environment.superTypes().getOrDefault(owner, List.of())) { for (String superName : environment.superTypes().getOrDefault(owner, List.of())) {
var ret = searchMethod(environment, superName, name, desc); var ret = searchMethod(environment, superName, name, desc);
if (ret != null) { if (ret != null) {
return ret; return ret;
} }

View File

@ -13,23 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
import com.squareup.javapoet.MethodSpec; package net.fabricmc.filament.mappingpoet;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import net.fabricmc.mappingpoet.signature.AnnotationAwareDescriptors;
import net.fabricmc.mappingpoet.signature.AnnotationAwareSignatures;
import net.fabricmc.mappingpoet.signature.MethodSignature;
import net.fabricmc.mappingpoet.signature.TypeAnnotationBank;
import net.fabricmc.mappingpoet.signature.TypeAnnotationMapping;
import net.fabricmc.mappingpoet.signature.TypeAnnotationStorage;
import org.objectweb.asm.TypeReference;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import javax.lang.model.element.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -39,6 +25,23 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.lang.model.element.Modifier;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import org.objectweb.asm.TypeReference;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import net.fabricmc.filament.mappingpoet.signature.AnnotationAwareDescriptors;
import net.fabricmc.filament.mappingpoet.signature.AnnotationAwareSignatures;
import net.fabricmc.filament.mappingpoet.signature.MethodSignature;
import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationBank;
import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationMapping;
import net.fabricmc.filament.mappingpoet.signature.TypeAnnotationStorage;
public class MethodBuilder { public class MethodBuilder {
private static final Set<String> RESERVED_KEYWORDS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( private static final Set<String> RESERVED_KEYWORDS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue",
@ -83,6 +86,7 @@ public class MethodBuilder {
if (regularAnnotations == null || regularAnnotations.length <= index) { if (regularAnnotations == null || regularAnnotations.length <= index) {
return; return;
} }
addDirectAnnotations(builder, regularAnnotations[index]); addDirectAnnotations(builder, regularAnnotations[index]);
} }
@ -90,6 +94,7 @@ public class MethodBuilder {
if (regularAnnotations == null) { if (regularAnnotations == null) {
return; return;
} }
for (AnnotationNode annotation : regularAnnotations) { for (AnnotationNode annotation : regularAnnotations) {
builder.addAnnotation(FieldBuilder.parseAnnotation(annotation)); builder.addAnnotation(FieldBuilder.parseAnnotation(annotation));
} }
@ -104,8 +109,10 @@ public class MethodBuilder {
usedNames.add(suggestedName); usedNames.add(suggestedName);
return suggestedName; return suggestedName;
} }
int t = 2; int t = 2;
String currentSuggestion = suggestedName + t; String currentSuggestion = suggestedName + t;
while (usedNames.contains(currentSuggestion)) { while (usedNames.contains(currentSuggestion)) {
t++; t++;
currentSuggestion = suggestedName + t; currentSuggestion = suggestedName + t;
@ -122,22 +129,29 @@ public class MethodBuilder {
int newEnd = str.length(); int newEnd = str.length();
int ltStart; int ltStart;
ltStart = str.indexOf('<', newStart); ltStart = str.indexOf('<', newStart);
if (ltStart != -1 && ltStart < newEnd) { if (ltStart != -1 && ltStart < newEnd) {
newEnd = ltStart; newEnd = ltStart;
} }
ltStart = str.indexOf('[', newStart); ltStart = str.indexOf('[', newStart);
if (ltStart != -1 && ltStart < newEnd) { if (ltStart != -1 && ltStart < newEnd) {
newEnd = ltStart; newEnd = ltStart;
} }
int dotEnd; int dotEnd;
if ((dotEnd = str.lastIndexOf(".", newEnd)) != -1) { if ((dotEnd = str.lastIndexOf(".", newEnd)) != -1) {
newStart = dotEnd + 1; newStart = dotEnd + 1;
} }
str = Character.toLowerCase(str.charAt(newStart)) + str.substring(newStart + 1, newEnd); str = Character.toLowerCase(str.charAt(newStart)) + str.substring(newStart + 1, newEnd);
if (str.equals("boolean")) { if (str.equals("boolean")) {
str = "bool"; str = "bool";
} }
return str; return str;
} }
@ -165,6 +179,7 @@ public class MethodBuilder {
if (regularAnnotations == null) { if (regularAnnotations == null) {
return; return;
} }
for (AnnotationNode annotation : regularAnnotations) { for (AnnotationNode annotation : regularAnnotations) {
builder.addAnnotation(FieldBuilder.parseAnnotation(annotation)); builder.addAnnotation(FieldBuilder.parseAnnotation(annotation));
} }
@ -177,6 +192,7 @@ public class MethodBuilder {
} }
TypeName typeName; TypeName typeName;
if (signature != null) { if (signature != null) {
typeName = signature.result(); typeName = signature.result();
} else { } else {
@ -185,6 +201,7 @@ public class MethodBuilder {
} }
builder.returns(typeName); builder.returns(typeName);
if (typeName != TypeName.VOID && !builder.modifiers.contains(Modifier.ABSTRACT)) { if (typeName != TypeName.VOID && !builder.modifiers.contains(Modifier.ABSTRACT)) {
builder.addStatement("throw new RuntimeException()"); builder.addStatement("throw new RuntimeException()");
} else if (methodNode.annotationDefault != null) { } else if (methodNode.annotationDefault != null) {
@ -202,8 +219,10 @@ public class MethodBuilder {
// generate receiver param for type annos // generate receiver param for type annos
TypeAnnotationBank receiverAnnos = typeAnnotations.getBank(TypeReference.newTypeReference(TypeReference.METHOD_RECEIVER)); TypeAnnotationBank receiverAnnos = typeAnnotations.getBank(TypeReference.newTypeReference(TypeReference.METHOD_RECEIVER));
if (!receiverAnnos.isEmpty()) { if (!receiverAnnos.isEmpty()) {
ParameterSpec.Builder receiverBuilder; ParameterSpec.Builder receiverBuilder;
// only instance inner class ctor can have receivers // only instance inner class ctor can have receivers
if (methodNode.name.equals("<init>")) { if (methodNode.name.equals("<init>")) {
TypeName annotatedReceiver = AnnotationAwareSignatures.parseSignature("L" + receiverSignature.substring(0, receiverSignature.lastIndexOf('.')) + ";", receiverAnnos, environment); TypeName annotatedReceiver = AnnotationAwareSignatures.parseSignature("L" + receiverSignature.substring(0, receiverSignature.lastIndexOf('.')) + ";", receiverAnnos, environment);
@ -217,6 +236,7 @@ public class MethodBuilder {
TypeName annotatedReceiver = AnnotationAwareSignatures.parseSignature("L" + receiverSignature + ";", receiverAnnos, environment); TypeName annotatedReceiver = AnnotationAwareSignatures.parseSignature("L" + receiverSignature + ";", receiverAnnos, environment);
receiverBuilder = ParameterSpec.builder(annotatedReceiver, "this"); receiverBuilder = ParameterSpec.builder(annotatedReceiver, "this");
} }
// receiver param cannot have its jd/param anno except type use anno // receiver param cannot have its jd/param anno except type use anno
builder.addParameter(receiverBuilder.build()); builder.addParameter(receiverBuilder.build());
} }
@ -224,12 +244,15 @@ public class MethodBuilder {
List<AnnotationNode>[] visibleParameterAnnotations = methodNode.visibleParameterAnnotations; List<AnnotationNode>[] visibleParameterAnnotations = methodNode.visibleParameterAnnotations;
List<AnnotationNode>[] invisibleParameterAnnotations = methodNode.invisibleParameterAnnotations; List<AnnotationNode>[] invisibleParameterAnnotations = methodNode.invisibleParameterAnnotations;
int index = 0; int index = 0;
for (ParamType paramType : paramTypes) { for (ParamType paramType : paramTypes) {
paramType.fillName(usedParamNames); paramType.fillName(usedParamNames);
ParameterSpec.Builder paramBuilder = ParameterSpec.builder(paramType.type, paramType.name, paramType.modifiers); ParameterSpec.Builder paramBuilder = ParameterSpec.builder(paramType.type, paramType.name, paramType.modifiers);
if (paramType.comment != null) { if (paramType.comment != null) {
paramBuilder.addJavadoc(paramType.comment + "\n"); paramBuilder.addJavadoc(paramType.comment + "\n");
} }
addDirectAnnotations(paramBuilder, visibleParameterAnnotations, index); addDirectAnnotations(paramBuilder, visibleParameterAnnotations, index);
addDirectAnnotations(paramBuilder, invisibleParameterAnnotations, index); addDirectAnnotations(paramBuilder, invisibleParameterAnnotations, index);
builder.addParameter(paramBuilder.build()); builder.addParameter(paramBuilder.build());
@ -246,9 +269,11 @@ public class MethodBuilder {
if (desc.charAt(index) != '(') { if (desc.charAt(index) != '(') {
throw invalidMethodDesc(desc, index); throw invalidMethodDesc(desc, index);
} }
index++; // consume '(' index++; // consume '('
Iterator<TypeName> signatureParamIterator = signature == null ? Collections.emptyIterator() : signature.parameters().iterator(); Iterator<TypeName> signatureParamIterator = signature == null ? Collections.emptyIterator() : signature.parameters().iterator();
while (desc.charAt(index) != ')') { while (desc.charAt(index) != ')') {
int oldIndex = index; int oldIndex = index;
Map.Entry<Integer, TypeName> parsedParam = FieldBuilder.parseType(desc, index); Map.Entry<Integer, TypeName> parsedParam = FieldBuilder.parseType(desc, index);
@ -257,19 +282,25 @@ public class MethodBuilder {
if (paramIndex >= formalParamStartIndex) { // skip guessed synthetic/implicit params if (paramIndex >= formalParamStartIndex) { // skip guessed synthetic/implicit params
TypeName parsedType; TypeName parsedType;
if (signatureParamIterator.hasNext()) { if (signatureParamIterator.hasNext()) {
parsedType = signatureParamIterator.next(); parsedType = signatureParamIterator.next();
} else { } else {
parsedType = AnnotationAwareDescriptors.parseDesc(desc.substring(oldIndex, index), typeAnnotations.getBank(TypeReference.newFormalParameterReference(paramIndex - formalParamStartIndex)), environment); parsedType = AnnotationAwareDescriptors.parseDesc(desc.substring(oldIndex, index), typeAnnotations.getBank(TypeReference.newFormalParameterReference(paramIndex - formalParamStartIndex)), environment);
} }
paramTypes.add(new ParamType(mappings.getParamNameAndDoc(environment, classNode.name, methodNode.name, methodNode.desc, slot), parsedType, usedParamNames, slot)); paramTypes.add(new ParamType(mappings.getParamNameAndDoc(environment, classNode.name, methodNode.name, methodNode.desc, slot), parsedType, usedParamNames, slot));
} }
slot++; slot++;
if (nonAnnotatedParsedType.equals(TypeName.DOUBLE) || nonAnnotatedParsedType.equals(TypeName.LONG)) { if (nonAnnotatedParsedType.equals(TypeName.DOUBLE) || nonAnnotatedParsedType.equals(TypeName.LONG)) {
slot++; slot++;
} }
paramIndex++; paramIndex++;
} }
/* bruh, we don't care about return type /* bruh, we don't care about return type
index++; // consume ')' index++; // consume ')'
Map.Entry<Integer, TypeName> parsedReturn = FieldBuilder.parseType(desc, index); Map.Entry<Integer, TypeName> parsedReturn = FieldBuilder.parseType(desc, index);
@ -283,11 +314,15 @@ public class MethodBuilder {
for (TypeName each : signature.thrown()) { for (TypeName each : signature.thrown()) {
builder.addException(each); builder.addException(each);
} }
return; return;
} }
List<String> exceptions = methodNode.exceptions; List<String> exceptions = methodNode.exceptions;
if (exceptions != null) { if (exceptions != null) {
int index = 0; int index = 0;
for (String internalName : exceptions) { for (String internalName : exceptions) {
builder.addException(AnnotationAwareDescriptors.parseType(internalName, typeAnnotations.getBank(TypeReference.newExceptionReference(index)), environment)); builder.addException(AnnotationAwareDescriptors.parseType(internalName, typeAnnotations.getBank(TypeReference.newExceptionReference(index)), environment));
index++; index++;
@ -309,8 +344,9 @@ public class MethodBuilder {
private final Modifier[] modifiers; private final Modifier[] modifiers;
private String name; private String name;
public ParamType(Map.Entry<String, String> nameAndDoc, TypeName type, Set<String> usedNames, int slot) { ParamType(Map.Entry<String, String> nameAndDoc, TypeName type, Set<String> usedNames, int slot) {
this.name = nameAndDoc != null ? nameAndDoc.getKey() : null; this.name = nameAndDoc != null ? nameAndDoc.getKey() : null;
if (this.name != null) { if (this.name != null) {
if (usedNames.contains(this.name)) { if (usedNames.contains(this.name)) {
System.err.printf("Overridden parameter name detected in %s %s %s slot %d, resetting%n", classNode.name, methodNode.name, methodNode.desc, slot); System.err.printf("Overridden parameter name detected in %s %s %s slot %d, resetting%n", classNode.name, methodNode.name, methodNode.desc, slot);
@ -319,6 +355,7 @@ public class MethodBuilder {
usedNames.add(this.name); usedNames.add(this.name);
} }
} }
this.comment = nameAndDoc == null ? null : nameAndDoc.getValue(); this.comment = nameAndDoc == null ? null : nameAndDoc.getValue();
this.type = type; this.type = type;
this.modifiers = new ModifierBuilder(0) this.modifiers = new ModifierBuilder(0)
@ -329,6 +366,7 @@ public class MethodBuilder {
if (name != null) { if (name != null) {
return; return;
} }
name = reserveValidName(suggestName(type), usedNames); name = reserveValidName(suggestName(type), usedNames);
} }
} }

View File

@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
import org.objectweb.asm.tree.ClassNode; package net.fabricmc.filament.mappingpoet;
import javax.lang.model.element.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ModifierBuilder { import javax.lang.model.element.Modifier;
import org.objectweb.asm.tree.ClassNode;
public class ModifierBuilder {
private final int access; private final int access;
private boolean needsUnseal; private boolean needsUnseal;
@ -48,7 +49,6 @@ public class ModifierBuilder {
needsUnseal = true; needsUnseal = true;
} }
return this; return this;
} }
@ -59,6 +59,7 @@ public class ModifierBuilder {
if (java.lang.reflect.Modifier.isFinal(access)) { if (java.lang.reflect.Modifier.isFinal(access)) {
modifiers.add(Modifier.FINAL); modifiers.add(Modifier.FINAL);
} }
return modifiers.toArray(new Modifier[]{}); return modifiers.toArray(new Modifier[]{});
} }
@ -73,9 +74,11 @@ public class ModifierBuilder {
if (java.lang.reflect.Modifier.isAbstract(access) && type != Type.ENUM) { if (java.lang.reflect.Modifier.isAbstract(access) && type != Type.ENUM) {
modifiers.add(Modifier.ABSTRACT); modifiers.add(Modifier.ABSTRACT);
} }
if (java.lang.reflect.Modifier.isStatic(access)) { if (java.lang.reflect.Modifier.isStatic(access)) {
modifiers.add(Modifier.STATIC); modifiers.add(Modifier.STATIC);
} }
if (!java.lang.reflect.Modifier.isAbstract(access) && !java.lang.reflect.Modifier.isStatic(access) && type == Type.METHOD) { if (!java.lang.reflect.Modifier.isAbstract(access) && !java.lang.reflect.Modifier.isStatic(access) && type == Type.METHOD) {
modifiers.add(Modifier.DEFAULT); modifiers.add(Modifier.DEFAULT);
} }
@ -83,18 +86,23 @@ public class ModifierBuilder {
if (java.lang.reflect.Modifier.isFinal(access) && type != Type.ENUM && type != Type.RECORD) { if (java.lang.reflect.Modifier.isFinal(access) && type != Type.ENUM && type != Type.RECORD) {
modifiers.add(Modifier.FINAL); modifiers.add(Modifier.FINAL);
} }
if (java.lang.reflect.Modifier.isTransient(access) && type == Type.FIELD) { if (java.lang.reflect.Modifier.isTransient(access) && type == Type.FIELD) {
modifiers.add(Modifier.TRANSIENT); modifiers.add(Modifier.TRANSIENT);
} }
if (java.lang.reflect.Modifier.isVolatile(access) && type == Type.FIELD) { if (java.lang.reflect.Modifier.isVolatile(access) && type == Type.FIELD) {
modifiers.add(Modifier.VOLATILE); modifiers.add(Modifier.VOLATILE);
} }
if (java.lang.reflect.Modifier.isSynchronized(access) && type == Type.METHOD) { if (java.lang.reflect.Modifier.isSynchronized(access) && type == Type.METHOD) {
modifiers.add(Modifier.SYNCHRONIZED); modifiers.add(Modifier.SYNCHRONIZED);
} }
if (java.lang.reflect.Modifier.isNative(access) && type == Type.METHOD) { if (java.lang.reflect.Modifier.isNative(access) && type == Type.METHOD) {
modifiers.add(Modifier.NATIVE); modifiers.add(Modifier.NATIVE);
} }
if (java.lang.reflect.Modifier.isStrict(access)) { if (java.lang.reflect.Modifier.isStrict(access)) {
modifiers.add(Modifier.STRICTFP); // obsolete as of Java 17 modifiers.add(Modifier.STRICTFP); // obsolete as of Java 17
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet;
package net.fabricmc.filament.mappingpoet;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.Collections; import java.util.Collections;
@ -30,27 +31,30 @@ import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeVariableName; import com.squareup.javapoet.TypeVariableName;
import com.squareup.javapoet.WildcardTypeName; import com.squareup.javapoet.WildcardTypeName;
import net.fabricmc.mappingpoet.signature.ClassSignature; import net.fabricmc.filament.mappingpoet.signature.ClassSignature;
import net.fabricmc.mappingpoet.signature.MethodSignature; import net.fabricmc.filament.mappingpoet.signature.MethodSignature;
public final class Signatures { public final class Signatures {
public static ClassSignature parseClassSignature(final String signature) { public static ClassSignature parseClassSignature(final String signature) {
// <A:Labc.Def:Ljava.util.Iterable<Ljava/lang.Object;>;B:Ljava/lang/Object>Ljava/lang/Object; etc etc // <A:Labc.Def:Ljava.util.Iterable<Ljava/lang.Object;>;B:Ljava/lang/Object>Ljava/lang/Object; etc etc
int index = 0; int index = 0;
char ch; char ch;
List<TypeVariableName> generics = Collections.emptyList(); List<TypeVariableName> generics = Collections.emptyList();
if (signature.charAt(0) == '<') { if (signature.charAt(0) == '<') {
// parse generic decl // parse generic decl
index++; // consume '<' index++; // consume '<'
// parse type params e.g. <A, B> // parse type params e.g. <A, B>
generics = new LinkedList<>(); generics = new LinkedList<>();
while ((ch = signature.charAt(index)) != '>') { while ((ch = signature.charAt(index)) != '>') {
int genericNameStart = index; int genericNameStart = index;
if (ch == ':') { if (ch == ':') {
throw errorAt(signature, index); throw errorAt(signature, index);
} }
do { do {
index++; index++;
} while (signature.charAt(index) != ':'); } while (signature.charAt(index) != ':');
@ -59,14 +63,17 @@ public final class Signatures {
List<TypeName> bounds = new LinkedList<>(); List<TypeName> bounds = new LinkedList<>();
boolean classBound = true; boolean classBound = true;
while (signature.charAt(index) == ':') { while (signature.charAt(index) == ':') {
// parse bounds // parse bounds
index++; // consume ':' index++; // consume ':'
if (classBound && signature.charAt(index) == ':') { if (classBound && signature.charAt(index) == ':') {
// No class bound, only interface bounds, so '::' // No class bound, only interface bounds, so '::'
classBound = false; classBound = false;
continue; continue;
} }
classBound = false; classBound = false;
Map.Entry<Integer, TypeName> bound = parseParameterizedType(signature, index); Map.Entry<Integer, TypeName> bound = parseParameterizedType(signature, index);
index = bound.getKey(); index = bound.getKey();
@ -80,6 +87,7 @@ public final class Signatures {
} }
LinkedList<TypeName> supers = new LinkedList<>(); LinkedList<TypeName> supers = new LinkedList<>();
while (index < signature.length()) { while (index < signature.length()) {
Map.Entry<Integer, TypeName> bound = parseParameterizedType(signature, index); Map.Entry<Integer, TypeName> bound = parseParameterizedType(signature, index);
index = bound.getKey(); index = bound.getKey();
@ -93,17 +101,21 @@ public final class Signatures {
int index = 0; int index = 0;
char ch; char ch;
List<TypeVariableName> generics = Collections.emptyList(); List<TypeVariableName> generics = Collections.emptyList();
if (signature.charAt(0) == '<') { if (signature.charAt(0) == '<') {
// parse generic decl // parse generic decl
index++; // consume '<' index++; // consume '<'
// parse type params e.g. <A, B> // parse type params e.g. <A, B>
generics = new LinkedList<>(); generics = new LinkedList<>();
while ((ch = signature.charAt(index)) != '>') { while ((ch = signature.charAt(index)) != '>') {
int genericNameStart = index; int genericNameStart = index;
if (ch == ':') { if (ch == ':') {
throw errorAt(signature, index); throw errorAt(signature, index);
} }
do { do {
index++; index++;
} while (signature.charAt(index) != ':'); } while (signature.charAt(index) != ':');
@ -112,14 +124,17 @@ public final class Signatures {
List<TypeName> bounds = new LinkedList<>(); List<TypeName> bounds = new LinkedList<>();
boolean classBound = true; boolean classBound = true;
while (signature.charAt(index) == ':') { while (signature.charAt(index) == ':') {
// parse bounds // parse bounds
index++; // consume ':' index++; // consume ':'
if (classBound && signature.charAt(index) == ':') { if (classBound && signature.charAt(index) == ':') {
// No class bound, only interface bounds, so '::' // No class bound, only interface bounds, so '::'
classBound = false; classBound = false;
continue; continue;
} }
classBound = false; classBound = false;
Map.Entry<Integer, TypeName> bound = parseParameterizedType(signature, index); Map.Entry<Integer, TypeName> bound = parseParameterizedType(signature, index);
index = bound.getKey(); index = bound.getKey();
@ -135,9 +150,11 @@ public final class Signatures {
if (signature.charAt(index) != '(') { if (signature.charAt(index) != '(') {
throw errorAt(signature, index); throw errorAt(signature, index);
} }
index++; // consume '(' index++; // consume '('
LinkedList<TypeName> params = new LinkedList<>(); LinkedList<TypeName> params = new LinkedList<>();
while (signature.charAt(index) != ')') { while (signature.charAt(index) != ')') {
Map.Entry<Integer, TypeName> param = parseParameterizedType(signature, index); Map.Entry<Integer, TypeName> param = parseParameterizedType(signature, index);
index = param.getKey(); index = param.getKey();
@ -147,6 +164,7 @@ public final class Signatures {
index++; // consume ')' index++; // consume ')'
TypeName returnType; TypeName returnType;
if (signature.charAt(index) == 'V') { if (signature.charAt(index) == 'V') {
returnType = TypeName.VOID; returnType = TypeName.VOID;
index++; index++;
@ -157,6 +175,7 @@ public final class Signatures {
} }
LinkedList<TypeName> thrown = new LinkedList<>(); LinkedList<TypeName> thrown = new LinkedList<>();
while (index < signature.length() && signature.charAt(index) == '^') { while (index < signature.length() && signature.charAt(index) == '^') {
index++; // consume '^' index++; // consume '^'
Map.Entry<Integer, TypeName> parsedThrown = parseParameterizedType(signature, index); Map.Entry<Integer, TypeName> parsedThrown = parseParameterizedType(signature, index);
@ -175,6 +194,7 @@ public final class Signatures {
GenericStack stack = new GenericStack(); GenericStack stack = new GenericStack();
int index = startOffset; int index = startOffset;
// the loop parses a type and try to quit levels if possible // the loop parses a type and try to quit levels if possible
do { do {
char ch = signature.charAt(index); char ch = signature.charAt(index);
@ -208,6 +228,7 @@ public final class Signatures {
if (parseExactType) { if (parseExactType) {
int arrayLevel = 0; int arrayLevel = 0;
while ((ch = signature.charAt(index)) == '[') { while ((ch = signature.charAt(index)) == '[') {
index++; index++;
arrayLevel++; arrayLevel++;
@ -230,9 +251,11 @@ public final class Signatures {
case 'T': { case 'T': {
// "TE;" for <E> // "TE;" for <E>
int nameStart = index; int nameStart = index;
while (signature.charAt(index) != ';') { while (signature.charAt(index) != ';') {
index++; index++;
} }
String typeVarName = signature.substring(nameStart, index); String typeVarName = signature.substring(nameStart, index);
stack.add(TypeVariableName.get(typeVarName), arrayLevel, bounded, extendsBound); stack.add(TypeVariableName.get(typeVarName), arrayLevel, bounded, extendsBound);
index++; // read ending ";" index++; // read ending ";"
@ -245,6 +268,7 @@ public final class Signatures {
int nameStart = index; int nameStart = index;
ClassName currentClass = null; ClassName currentClass = null;
int nextSimpleNamePrev = -1; int nextSimpleNamePrev = -1;
do { do {
ch = signature.charAt(index); ch = signature.charAt(index);
@ -252,6 +276,7 @@ public final class Signatures {
if (currentClass != null) { if (currentClass != null) {
throw errorAt(signature, index); throw errorAt(signature, index);
} }
nextSimpleNamePrev = index; nextSimpleNamePrev = index;
} }
@ -264,6 +289,7 @@ public final class Signatures {
String simpleName = signature.substring(nextSimpleNamePrev + 1, index); String simpleName = signature.substring(nextSimpleNamePrev + 1, index);
currentClass = currentClass.nestedClass(simpleName); currentClass = currentClass.nestedClass(simpleName);
} }
nextSimpleNamePrev = index; nextSimpleNamePrev = index;
} }
@ -271,6 +297,7 @@ public final class Signatures {
} while (ch != '<' && ch != ';'); } while (ch != '<' && ch != ';');
assert currentClass != null; assert currentClass != null;
if (ch == ';') { if (ch == ';') {
stack.add(currentClass, arrayLevel, bounded, extendsBound); stack.add(currentClass, arrayLevel, bounded, extendsBound);
} }
@ -278,6 +305,7 @@ public final class Signatures {
if (ch == '<') { if (ch == '<') {
stack.push(Frame.ofClass(currentClass), arrayLevel, bounded, extendsBound); stack.push(Frame.ofClass(currentClass), arrayLevel, bounded, extendsBound);
} }
break; break;
} }
default: { default: {
@ -288,6 +316,7 @@ public final class Signatures {
// quit generics // quit generics
quitLoop: quitLoop:
while (stack.canQuit() && signature.charAt(index) == '>') { while (stack.canQuit() && signature.charAt(index) == '>') {
// pop // pop
stack.popFrame(); stack.popFrame();
@ -298,6 +327,7 @@ public final class Signatures {
if (ch != '.') { if (ch != '.') {
throw errorAt(signature, index); throw errorAt(signature, index);
} }
index++; index++;
int innerNameStart = index; int innerNameStart = index;
final int checkIndex = index; final int checkIndex = index;
@ -309,10 +339,13 @@ public final class Signatures {
while (true) { while (true) {
ch = signature.charAt(index); ch = signature.charAt(index);
if (ch == '.' || ch == ';' || ch == '<') { if (ch == '.' || ch == ';' || ch == '<') {
String simpleName = signature.substring(innerNameStart, index); String simpleName = signature.substring(innerNameStart, index);
if (ch == '.' || ch == ';') { if (ch == '.' || ch == ';') {
stack.tweakLast(name -> ((ParameterizedTypeName) name).nestedClass(simpleName)); stack.tweakLast(name -> ((ParameterizedTypeName) name).nestedClass(simpleName));
if (ch == ';') { if (ch == ';') {
index++; index++;
break; break;
@ -329,9 +362,7 @@ public final class Signatures {
} else { } else {
index++; index++;
} }
} }
} while (stack.canQuit()); } while (stack.canQuit());
assert stack.deque.size() == 1; assert stack.deque.size() == 1;
@ -345,9 +376,11 @@ public final class Signatures {
public static TypeName wrap(TypeName component, int level, boolean bounded, boolean extendsBound) { public static TypeName wrap(TypeName component, int level, boolean bounded, boolean extendsBound) {
TypeName ret = component; TypeName ret = component;
for (int i = 0; i < level; i++) { for (int i = 0; i < level; i++) {
ret = ArrayTypeName.of(ret); ret = ArrayTypeName.of(ret);
} }
return bounded ? extendsBound ? WildcardTypeName.subtypeOf(ret) : WildcardTypeName.supertypeOf(ret) : ret; return bounded ? extendsBound ? WildcardTypeName.subtypeOf(ret) : WildcardTypeName.supertypeOf(ret) : ret;
} }
@ -372,6 +405,7 @@ public final class Signatures {
case 'Z': case 'Z':
return TypeName.BOOLEAN; return TypeName.BOOLEAN;
} }
throw new IllegalArgumentException("Invalid primitive " + c); throw new IllegalArgumentException("Invalid primitive " + c);
} }
@ -390,6 +424,7 @@ public final class Signatures {
if (parameters.size() != 1) { if (parameters.size() != 1) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
return parameters.get(0); return parameters.get(0);
}; };
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.jd;
package net.fabricmc.filament.mappingpoet.jd;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
@ -30,7 +31,6 @@ import jdk.javadoc.doclet.Taglet;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class MappingTaglet implements Taglet { public final class MappingTaglet implements Taglet {
public MappingTaglet() { public MappingTaglet() {
// Required by javadoc // Required by javadoc
} }
@ -59,9 +59,11 @@ public final class MappingTaglet implements Taglet {
builder.append("<thead>\n"); builder.append("<thead>\n");
builder.append("<th>Namespace</th>\n"); builder.append("<th>Namespace</th>\n");
builder.append("<th>Name</th>\n"); builder.append("<th>Name</th>\n");
if (!typeDecl) { if (!typeDecl) {
builder.append("<th>Mixin selector</th>\n"); builder.append("<th>Mixin selector</th>\n");
} }
builder.append("</thead>\n"); builder.append("</thead>\n");
builder.append("<tbody>\n"); builder.append("<tbody>\n");
@ -71,9 +73,11 @@ public final class MappingTaglet implements Taglet {
builder.append("<tr>\n"); builder.append("<tr>\n");
builder.append(String.format("<td>%s</td>\n", escaped(ans[0]))); builder.append(String.format("<td>%s</td>\n", escaped(ans[0])));
builder.append(String.format("<td><span class=\"copyable\"><code>%s</code></span></td>\n", escaped(ans[1]))); builder.append(String.format("<td><span class=\"copyable\"><code>%s</code></span></td>\n", escaped(ans[1])));
if (!typeDecl) { if (!typeDecl) {
builder.append(String.format("<td><span class=\"copyable\"><code>%s</code></span></td>\n", escaped(ans[2]))); builder.append(String.format("<td><span class=\"copyable\"><code>%s</code></span></td>\n", escaped(ans[2])));
} }
builder.append("</tr>\n"); builder.append("</tr>\n");
} }
@ -86,14 +90,17 @@ public final class MappingTaglet implements Taglet {
private static String escaped(String original) { private static String escaped(String original) {
StringBuilder builder = new StringBuilder(original.length()); StringBuilder builder = new StringBuilder(original.length());
final int len = original.length(); final int len = original.length();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
char c = original.charAt(i); char c = original.charAt(i);
if (c > 127 || c == '"' || c == '\'' || c == '<' || c == '>' || c == '&') { if (c > 127 || c == '"' || c == '\'' || c == '<' || c == '>' || c == '&') {
builder.append("&#").append((int) c).append(";"); builder.append("&#").append((int) c).append(";");
} else { } else {
builder.append(c); builder.append(c);
} }
} }
return builder.toString(); return builder.toString();
} }
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -31,10 +32,9 @@ import com.squareup.javapoet.TypeName;
import org.objectweb.asm.TypePath; import org.objectweb.asm.TypePath;
import org.objectweb.asm.TypeReference; import org.objectweb.asm.TypeReference;
import net.fabricmc.mappingpoet.Signatures; import net.fabricmc.filament.mappingpoet.Signatures;
public final class AnnotationAwareDescriptors { public final class AnnotationAwareDescriptors {
private AnnotationAwareDescriptors() { private AnnotationAwareDescriptors() {
} }
@ -43,6 +43,7 @@ public final class AnnotationAwareDescriptors {
ClassName superName = parseType(rawSuper, mapping.getBank(TypeReference.newSuperTypeReference(-1)), context); ClassName superName = parseType(rawSuper, mapping.getBank(TypeReference.newSuperTypeReference(-1)), context);
List<TypeName> interfaces = new ArrayList<>(rawInterfaces.size()); List<TypeName> interfaces = new ArrayList<>(rawInterfaces.size());
for (ListIterator<String> itr = rawInterfaces.listIterator(); itr.hasNext(); ) { for (ListIterator<String> itr = rawInterfaces.listIterator(); itr.hasNext(); ) {
int i = itr.nextIndex(); int i = itr.nextIndex();
String item = itr.next(); String item = itr.next();
@ -59,12 +60,14 @@ public final class AnnotationAwareDescriptors {
Deque<List<AnnotationSpec>> arrayAnnotations = new ArrayDeque<>(); Deque<List<AnnotationSpec>> arrayAnnotations = new ArrayDeque<>();
int len = desc.length(); int len = desc.length();
int index; int index;
for (index = 0; (index < len) && (desc.charAt(index) == '['); index++) { for (index = 0; (index < len) && (desc.charAt(index) == '['); index++) {
arrayAnnotations.push(bank.getCurrentAnnotations()); arrayAnnotations.push(bank.getCurrentAnnotations());
bank = bank.advance(TypePath.ARRAY_ELEMENT, 0); bank = bank.advance(TypePath.ARRAY_ELEMENT, 0);
} }
TypeName current; TypeName current;
if (len - index == 1) { if (len - index == 1) {
current = annotate(Signatures.getPrimitive(desc.charAt(index)), bank); current = annotate(Signatures.getPrimitive(desc.charAt(index)), bank);
} else { } else {
@ -72,9 +75,11 @@ public final class AnnotationAwareDescriptors {
assert desc.charAt(index) == 'L' && desc.charAt(len - 1) == ';'; assert desc.charAt(index) == 'L' && desc.charAt(len - 1) == ';';
current = parseType(desc.substring(index + 1, len - 1), bank, context); current = parseType(desc.substring(index + 1, len - 1), bank, context);
} }
while (!arrayAnnotations.isEmpty()) { while (!arrayAnnotations.isEmpty()) {
current = ArrayTypeName.of(current); current = ArrayTypeName.of(current);
List<AnnotationSpec> specs = arrayAnnotations.pop(); List<AnnotationSpec> specs = arrayAnnotations.pop();
if (!specs.isEmpty()) { if (!specs.isEmpty()) {
current = current.annotated(specs); current = current.annotated(specs);
} }
@ -101,10 +106,12 @@ public final class AnnotationAwareDescriptors {
if (internalName.startsWith("L") && internalName.endsWith(";")) { if (internalName.startsWith("L") && internalName.endsWith(";")) {
throw new AssertionError(internalName); throw new AssertionError(internalName);
} }
int slice = internalName.lastIndexOf('/'); int slice = internalName.lastIndexOf('/');
String packageSt = slice < 0 ? "" : internalName.substring(0, slice).replace('/', '.'); String packageSt = slice < 0 ? "" : internalName.substring(0, slice).replace('/', '.');
int moneySign = internalName.indexOf('$', slice + 1); int moneySign = internalName.indexOf('$', slice + 1);
if (moneySign == -1) { if (moneySign == -1) {
return new AbstractMap.SimpleImmutableEntry<>(ClassName.get(packageSt, internalName.substring(slice + 1)), bank); return new AbstractMap.SimpleImmutableEntry<>(ClassName.get(packageSt, internalName.substring(slice + 1)), bank);
} }
@ -113,8 +120,10 @@ public final class AnnotationAwareDescriptors {
final int len = internalName.length(); final int len = internalName.length();
boolean enteredInner = false; boolean enteredInner = false;
for (int i = moneySign; i < len; ) { for (int i = moneySign; i < len; ) {
int t = internalName.indexOf('$', i + 1); int t = internalName.indexOf('$', i + 1);
if (t < 0) { if (t < 0) {
t = len; t = len;
} }

View File

@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeName;
import org.objectweb.asm.TypeReference; import org.objectweb.asm.TypeReference;
import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureReader;
public final class AnnotationAwareSignatures { public final class AnnotationAwareSignatures {
private AnnotationAwareSignatures() { private AnnotationAwareSignatures() {
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import java.util.List; import java.util.List;
@ -22,6 +23,5 @@ import com.squareup.javapoet.TypeVariableName;
// no more a class signature but general super info about class // no more a class signature but general super info about class
public record ClassSignature(List<TypeVariableName> generics, TypeName superclass, public record ClassSignature(List<TypeVariableName> generics, TypeName superclass,
List<TypeName> superinterfaces) { List<TypeName> superinterfaces) {
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
/** /**
* A context to retrieve if a class is an instance inner class. Useful for * A context to retrieve if a class is an instance inner class. Useful for
@ -22,7 +23,6 @@ package net.fabricmc.mappingpoet.signature;
* an example in JVM Specification 15.</a> * an example in JVM Specification 15.</a>
*/ */
public interface ClassStaticContext { public interface ClassStaticContext {
/** /**
* Returns if this class is an instance inner class. * Returns if this class is an instance inner class.
* *

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import java.util.List; import java.util.List;
@ -23,5 +24,4 @@ import com.squareup.javapoet.TypeVariableName;
public record MethodSignature(List<TypeVariableName> generics, public record MethodSignature(List<TypeVariableName> generics,
List<TypeName> parameters, TypeName result, List<TypeName> parameters, TypeName result,
List<TypeName> thrown) { List<TypeName> thrown) {
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import java.util.ArrayList; import java.util.ArrayList;
@ -24,7 +25,6 @@ import org.objectweb.asm.TypeReference;
import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureVisitor;
public final class PoetClassMethodSignatureVisitor extends SignatureVisitor { public final class PoetClassMethodSignatureVisitor extends SignatureVisitor {
private final TypeAnnotationMapping mapping; private final TypeAnnotationMapping mapping;
private final ClassStaticContext context; private final ClassStaticContext context;
private final boolean forClass; private final boolean forClass;
@ -91,8 +91,8 @@ public final class PoetClassMethodSignatureVisitor extends SignatureVisitor {
private SignatureVisitor visitLowerBound() { private SignatureVisitor visitLowerBound() {
collectLowerBound(); collectLowerBound();
TypeAnnotationBank bank = mapping.getBank(TypeReference.newTypeParameterBoundReference(forClass ? TypeAnnotationBank bank = mapping.getBank(TypeReference.newTypeParameterBoundReference(forClass
TypeReference.CLASS_TYPE_PARAMETER_BOUND : TypeReference.METHOD_TYPE_PARAMETER_BOUND, generics.size(), ? TypeReference.CLASS_TYPE_PARAMETER_BOUND : TypeReference.METHOD_TYPE_PARAMETER_BOUND, generics.size(),
currentGenericBounds.size())); currentGenericBounds.size()));
return pendingLowerBound = new PoetTypeSignatureWriter(bank, context); return pendingLowerBound = new PoetTypeSignatureWriter(bank, context);
} }

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
@ -29,7 +30,7 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath; import org.objectweb.asm.TypePath;
import org.objectweb.asm.signature.SignatureVisitor; import org.objectweb.asm.signature.SignatureVisitor;
import net.fabricmc.mappingpoet.Signatures; import net.fabricmc.filament.mappingpoet.Signatures;
/** /**
* A type signature to javapoet visitor. * A type signature to javapoet visitor.
@ -39,7 +40,6 @@ import net.fabricmc.mappingpoet.Signatures;
* can be defined.</p> * can be defined.</p>
*/ */
public final class PoetTypeSignatureWriter extends SignatureVisitor { public final class PoetTypeSignatureWriter extends SignatureVisitor {
private final ClassStaticContext context; private final ClassStaticContext context;
private final ArrayList<TypeName> params = new ArrayList<>(); private final ArrayList<TypeName> params = new ArrayList<>();
private /* NonNull */ TypeAnnotationBank storage; // mutable private /* NonNull */ TypeAnnotationBank storage; // mutable
@ -132,6 +132,7 @@ public final class PoetTypeSignatureWriter extends SignatureVisitor {
} else { } else {
currentType = ((ClassName) currentType).nestedClass(nestedClassName); currentType = ((ClassName) currentType).nestedClass(nestedClassName);
} }
nestedClassName = null; nestedClassName = null;
} }
@ -150,10 +151,10 @@ public final class PoetTypeSignatureWriter extends SignatureVisitor {
if (activeTypeArgument != null) { if (activeTypeArgument != null) {
TypeName hold = activeTypeArgument.compute(); TypeName hold = activeTypeArgument.compute();
TypeName used = switch (activeTypeArgumentKind) { TypeName used = switch (activeTypeArgumentKind) {
case SignatureVisitor.EXTENDS -> WildcardTypeName.subtypeOf(hold); case SignatureVisitor.EXTENDS -> WildcardTypeName.subtypeOf(hold);
case SignatureVisitor.SUPER -> WildcardTypeName.supertypeOf(hold); case SignatureVisitor.SUPER -> WildcardTypeName.supertypeOf(hold);
case SignatureVisitor.INSTANCEOF -> hold; case SignatureVisitor.INSTANCEOF -> hold;
default -> throw new IllegalStateException(String.format("Illegal type argument wildcard %s", activeTypeArgumentKind)); default -> throw new IllegalStateException(String.format("Illegal type argument wildcard %s", activeTypeArgumentKind));
}; };
used = AnnotationAwareDescriptors.annotate(used, storage.advance(TypePath.TYPE_ARGUMENT, params.size())); used = AnnotationAwareDescriptors.annotate(used, storage.advance(TypePath.TYPE_ARGUMENT, params.size()));

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import org.objectweb.asm.TypeReference; import org.objectweb.asm.TypeReference;
@ -21,7 +22,6 @@ import org.objectweb.asm.TypeReference;
* The collection of type annotations from a bytecode structure that stores type annotations. * The collection of type annotations from a bytecode structure that stores type annotations.
*/ */
public interface TypeAnnotationMapping { public interface TypeAnnotationMapping {
TypeAnnotationMapping EMPTY = reference -> TypeAnnotationBank.EMPTY; TypeAnnotationMapping EMPTY = reference -> TypeAnnotationBank.EMPTY;
// implNote: TypeReference is not a pojo! No equals or hash! // implNote: TypeReference is not a pojo! No equals or hash!

View File

@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.mappingpoet.signature;
package net.fabricmc.filament.mappingpoet.signature;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -25,10 +26,9 @@ import org.objectweb.asm.TypePath;
import org.objectweb.asm.TypeReference; import org.objectweb.asm.TypeReference;
import org.objectweb.asm.tree.TypeAnnotationNode; import org.objectweb.asm.tree.TypeAnnotationNode;
import net.fabricmc.mappingpoet.FieldBuilder; import net.fabricmc.filament.mappingpoet.FieldBuilder;
public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeAnnotationBank { public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeAnnotationBank {
private final int[] targets; // target type and info, only exist in mapping version private final int[] targets; // target type and info, only exist in mapping version
private final String[] paths; private final String[] paths;
private final AnnotationSpec[] contents; private final AnnotationSpec[] contents;
@ -51,15 +51,18 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
static int comparePath(TypePath left, TypePath right) { static int comparePath(TypePath left, TypePath right) {
int len = Math.min(left.getLength(), right.getLength()); int len = Math.min(left.getLength(), right.getLength());
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
int leftStep = left.getStep(i); int leftStep = left.getStep(i);
int rightStep = right.getStep(i); int rightStep = right.getStep(i);
if (leftStep != rightStep) { if (leftStep != rightStep) {
return Integer.compare(leftStep, rightStep); return Integer.compare(leftStep, rightStep);
} }
int leftStepArg = left.getStepArgument(i); int leftStepArg = left.getStepArgument(i);
int rightStepArg = right.getStepArgument(i); int rightStepArg = right.getStepArgument(i);
if (leftStepArg != rightStepArg) { if (leftStepArg != rightStepArg) {
return Integer.compare(leftStepArg, rightStepArg); return Integer.compare(leftStepArg, rightStepArg);
} }
@ -97,14 +100,15 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
String hiCheck = check.substring(0, check.length() - 1).concat(Character.toString((char) (check.charAt(check.length() - 1) + 1))); String hiCheck = check.substring(0, check.length() - 1).concat(Character.toString((char) (check.charAt(check.length() - 1) + 1)));
int low = Arrays.binarySearch(paths, startIndex, endIndex, check); int low = Arrays.binarySearch(paths, startIndex, endIndex, check);
if (low < 0) { if (low < 0) {
low = -(low + 1); low = -(low + 1);
} }
// exclusive hi // exclusive hi
int hi = Arrays.binarySearch(paths, startIndex, endIndex, hiCheck); int hi = Arrays.binarySearch(paths, startIndex, endIndex, hiCheck);
if (hi < 0) { if (hi < 0) {
hi = -(hi + 1); hi = -(hi + 1);
} }
@ -119,6 +123,7 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
} }
int hi = Arrays.binarySearch(paths, startIndex, endIndex, currentPath + '\u0000'); int hi = Arrays.binarySearch(paths, startIndex, endIndex, currentPath + '\u0000');
if (hi < 0) { if (hi < 0) {
hi = -(hi + 1); hi = -(hi + 1);
} }
@ -140,12 +145,14 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
int target = reference.getValue(); int target = reference.getValue();
// inclusive low // inclusive low
int low = Arrays.binarySearch(targets, startIndex, endIndex, target); int low = Arrays.binarySearch(targets, startIndex, endIndex, target);
if (low < 0) { if (low < 0) {
low = -(low + 1); low = -(low + 1);
} }
// exclusive hi // exclusive hi
int hi = Arrays.binarySearch(targets, startIndex, endIndex, target + 1); int hi = Arrays.binarySearch(targets, startIndex, endIndex, target + 1);
if (hi < 0) { if (hi < 0) {
hi = -(hi + 1); hi = -(hi + 1);
} }
@ -154,7 +161,6 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
} }
public static final class Builder { public static final class Builder {
final List<Entry> entries = new ArrayList<>(); final List<Entry> entries = new ArrayList<>();
Builder() { Builder() {
@ -169,9 +175,11 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
if (nodes == null) { if (nodes == null) {
return this; // thanks asm return this; // thanks asm
} }
for (TypeAnnotationNode node : nodes) { for (TypeAnnotationNode node : nodes) {
entries.add(new Entry(node.typeRef, node.typePath == null ? "" : node.typePath.toString(), FieldBuilder.parseAnnotation(node))); entries.add(new Entry(node.typeRef, node.typePath == null ? "" : node.typePath.toString(), FieldBuilder.parseAnnotation(node)));
} }
return this; return this;
} }
@ -184,6 +192,7 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
AnnotationSpec[] contents = new AnnotationSpec[len]; AnnotationSpec[] contents = new AnnotationSpec[len];
Iterator<Entry> itr = this.entries.iterator(); Iterator<Entry> itr = this.entries.iterator();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Entry entry = itr.next(); Entry entry = itr.next();
targets[i] = entry.target; targets[i] = entry.target;
@ -212,6 +221,5 @@ public final class TypeAnnotationStorage implements TypeAnnotationMapping, TypeA
return path.compareTo(o.path); return path.compareTo(o.path);
} }
} }
} }
} }