diff --git a/raung-asm/src/main/java/io/github/skylot/raung/asm/impl/parser/directives/ClassDirectives.java b/raung-asm/src/main/java/io/github/skylot/raung/asm/impl/parser/directives/ClassDirectives.java index 8572fc5..9312669 100644 --- a/raung-asm/src/main/java/io/github/skylot/raung/asm/impl/parser/directives/ClassDirectives.java +++ b/raung-asm/src/main/java/io/github/skylot/raung/asm/impl/parser/directives/ClassDirectives.java @@ -12,6 +12,7 @@ import io.github.skylot.raung.asm.impl.utils.RaungAsmException; import io.github.skylot.raung.common.Directive; import io.github.skylot.raung.common.RaungAccessFlags.Scope; +import io.github.skylot.raung.common.utils.JavaVersion; import static io.github.skylot.raung.common.Directive.ANNOTATION; import static io.github.skylot.raung.common.Directive.AUTO; @@ -61,7 +62,22 @@ public static void process(Directive token, RaungParser parser, ClassData cw) { private static void processVersion(RaungParser parser, ClassData classData) { checkClassHeader(classData, VERSION); - classData.setVersion(parser.readInt()); + int clsVersion; + String version = ""; + try { + version = parser.readToken(); + int point = version.indexOf('.'); + if (point == -1) { + clsVersion = Integer.parseInt(version); + } else { + int major = Integer.parseInt(version.substring(0, point)); + int minor = Integer.parseInt(version.substring(point + 1)); + clsVersion = JavaVersion.getRaw(major, minor); + } + classData.setVersion(clsVersion); + } catch (Exception e) { + throw new RaungAsmException("Failed to parse class version number: " + version, e); + } parser.lineEnd(); } diff --git a/raung-disasm/src/main/java/io/github/skylot/raung/disasm/impl/utils/JavaVersion.java b/raung-common/src/main/java/io/github/skylot/raung/common/utils/JavaVersion.java similarity index 67% rename from raung-disasm/src/main/java/io/github/skylot/raung/disasm/impl/utils/JavaVersion.java rename to raung-common/src/main/java/io/github/skylot/raung/common/utils/JavaVersion.java index f5bb1da..82fa86f 100644 --- a/raung-disasm/src/main/java/io/github/skylot/raung/disasm/impl/utils/JavaVersion.java +++ b/raung-common/src/main/java/io/github/skylot/raung/common/utils/JavaVersion.java @@ -1,4 +1,4 @@ -package io.github.skylot.raung.disasm.impl.utils; +package io.github.skylot.raung.common.utils; import java.util.HashMap; import java.util.Map; @@ -7,7 +7,7 @@ public enum JavaVersion { JAVA_1_0_2(45, "1.0.2"), - JAVA_1_1(3 << 16 | 45, "1.1"), + JAVA_1_1(getRaw(45, 3), "1.1"), JAVA_1_2(46, "1.2"), JAVA_1_3(47, "1.3"), JAVA_1_4(48, "1.4"), @@ -25,7 +25,20 @@ public enum JavaVersion { JAVA_16(60, "16"), JAVA_17(61, "17"), JAVA_18(62, "18"), - JAVA_19(63, "19"); + JAVA_19(63, "19"), + JAVA_20(64, "20"), + JAVA_21(65, "21"); + + private static final Map MAP; + + static { + JavaVersion[] values = values(); + Map map = new HashMap<>(values.length); + for (JavaVersion value : values) { + map.put(value.rawVersion, value); + } + MAP = map; + } private final int rawVersion; private final String name; @@ -44,22 +57,23 @@ public String getName() { } public int getMajor() { - return rawVersion & 0xFFFF; + return getMajor(rawVersion); } public int getMinor() { - return (rawVersion & 0xFFFF0000) >> 16; + return getMinor(rawVersion); } - private static final Map MAP; + public static int getMajor(int rawVersion) { + return rawVersion & 0xFFFF; + } - static { - JavaVersion[] values = values(); - Map map = new HashMap<>(values.length); - for (JavaVersion value : values) { - map.put(value.rawVersion, value); - } - MAP = map; + public static int getMinor(int rawVersion) { + return (rawVersion & 0xFFFF0000) >> 16; + } + + public static int getRaw(int major, int minor) { + return minor << 16 | major; } public static final int PREVIEW_VERSION = 0xFFFF0000; @@ -70,14 +84,21 @@ public static boolean isPreview(int rawVersion) { public static String getNameStr(int rawVersion) { StringBuilder sb = new StringBuilder("Java "); + int major = getMajor(rawVersion); boolean preview = isPreview(rawVersion); - int searchVersion = preview ? rawVersion & 0xFFFF : rawVersion; + int searchVersion = preview ? major : rawVersion; JavaVersion version = MAP.get(searchVersion); if (version != null) { sb.append(version.name); } else { + if (!preview) { + int minor = getMinor(rawVersion); + if (minor != 0) { + return getNameStr(getRaw(major, 0)) + " (with unknown minor: " + minor + ')'; + } + } // try approximation :) - int verDiff = searchVersion - JAVA_18.rawVersion; + int verDiff = major - getMajor(JAVA_18.rawVersion); if (verDiff > 0) { sb.append(18 + verDiff).append(" (approximated)"); } else { @@ -90,6 +111,15 @@ public static String getNameStr(int rawVersion) { return sb.toString(); } + public static String formatVersionNumber(int rawVersion) { + int major = getMajor(rawVersion); + int minor = getMinor(rawVersion); + if (minor == 0) { + return Integer.toString(major); + } + return major + "." + minor; + } + @Nullable public static JavaVersion get(int rawVersion) { return MAP.get(rawVersion); diff --git a/raung-disasm/src/main/java/io/github/skylot/raung/disasm/impl/visitors/RaungClassVisitor.java b/raung-disasm/src/main/java/io/github/skylot/raung/disasm/impl/visitors/RaungClassVisitor.java index 5ed565e..57ed1f3 100644 --- a/raung-disasm/src/main/java/io/github/skylot/raung/disasm/impl/visitors/RaungClassVisitor.java +++ b/raung-disasm/src/main/java/io/github/skylot/raung/disasm/impl/visitors/RaungClassVisitor.java @@ -13,8 +13,8 @@ import io.github.skylot.raung.common.Directive; import io.github.skylot.raung.common.RaungAccessFlags; +import io.github.skylot.raung.common.utils.JavaVersion; import io.github.skylot.raung.disasm.impl.RaungDisasmBuilder; -import io.github.skylot.raung.disasm.impl.utils.JavaVersion; import io.github.skylot.raung.disasm.impl.utils.RaungTypes; import io.github.skylot.raung.disasm.impl.utils.RaungWriter; @@ -36,7 +36,8 @@ public RaungClassVisitor(RaungDisasmBuilder args) { @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - writer.add(Directive.VERSION.token()).space().add(version) + writer.add(Directive.VERSION.token()).space() + .add(JavaVersion.formatVersionNumber(version)) .add(" # ").add(JavaVersion.getNameStr(version)); writer.startLine(Directive.CLASS).add(RaungAccessFlags.format(access, CLASS)).add(name); if (!superName.equals("java/lang/Object")) { diff --git a/raung-disasm/src/test/java/io/github/skylot/raung/disasm/impl/utils/TestJavaVersion.java b/raung-disasm/src/test/java/io/github/skylot/raung/disasm/impl/utils/TestJavaVersion.java index 7289b93..8f7b2a9 100644 --- a/raung-disasm/src/test/java/io/github/skylot/raung/disasm/impl/utils/TestJavaVersion.java +++ b/raung-disasm/src/test/java/io/github/skylot/raung/disasm/impl/utils/TestJavaVersion.java @@ -2,12 +2,14 @@ import org.junit.jupiter.api.Test; -import static io.github.skylot.raung.disasm.impl.utils.JavaVersion.JAVA_17; -import static io.github.skylot.raung.disasm.impl.utils.JavaVersion.JAVA_19; -import static io.github.skylot.raung.disasm.impl.utils.JavaVersion.JAVA_1_1; -import static io.github.skylot.raung.disasm.impl.utils.JavaVersion.JAVA_8; -import static io.github.skylot.raung.disasm.impl.utils.JavaVersion.PREVIEW_VERSION; -import static io.github.skylot.raung.disasm.impl.utils.JavaVersion.getNameStr; +import io.github.skylot.raung.common.utils.JavaVersion; + +import static io.github.skylot.raung.common.utils.JavaVersion.JAVA_17; +import static io.github.skylot.raung.common.utils.JavaVersion.JAVA_1_1; +import static io.github.skylot.raung.common.utils.JavaVersion.JAVA_21; +import static io.github.skylot.raung.common.utils.JavaVersion.JAVA_8; +import static io.github.skylot.raung.common.utils.JavaVersion.PREVIEW_VERSION; +import static io.github.skylot.raung.common.utils.JavaVersion.getNameStr; import static org.assertj.core.api.Assertions.assertThat; class TestJavaVersion { @@ -17,10 +19,12 @@ public void various() { assertThat(getNameStr(JAVA_1_1.getRawVersion())).isEqualTo("Java 1.1"); assertThat(getNameStr(JAVA_8.getRawVersion())).isEqualTo("Java 8"); assertThat(getNameStr(JAVA_17.getRawVersion() | PREVIEW_VERSION)).isEqualTo("Java 17 preview"); - assertThat(getNameStr(JAVA_19.getRawVersion() + 1)).isEqualTo("Java 20 (approximated)"); - assertThat(getNameStr((JAVA_19.getRawVersion() + 2) | PREVIEW_VERSION)).isEqualTo("Java 21 (approximated) preview"); + assertThat(getNameStr(JAVA_21.getRawVersion() + 1)).isEqualTo("Java 22 (approximated)"); + assertThat(getNameStr((JAVA_21.getRawVersion() + 2) | PREVIEW_VERSION)).isEqualTo("Java 23 (approximated) preview"); assertThat(JAVA_1_1.getMajor()).isEqualTo(45); assertThat(JAVA_1_1.getMinor()).isEqualTo(3); + + assertThat(getNameStr(JavaVersion.getRaw(JAVA_17.getMajor(), 1))).isEqualTo("Java 17 (with unknown minor: 1)"); } } diff --git a/raung-tests/src/test/resources/raung/other/TestNewFrameType.raung b/raung-tests/src/test/resources/raung/other/TestNewFrameType.raung index 1a526d6..a05066a 100644 --- a/raung-tests/src/test/resources/raung/other/TestNewFrameType.raung +++ b/raung-tests/src/test/resources/raung/other/TestNewFrameType.raung @@ -1,4 +1,4 @@ -.version 196653 # Java 1.1 +.version 45.3 # Java 1.1 .class public final super b .field public static a [[B