diff --git a/build.gradle b/build.gradle deleted file mode 100644 index ad1d6d1..0000000 --- a/build.gradle +++ /dev/null @@ -1,83 +0,0 @@ -plugins { - id 'java' - id 'maven-publish' -} - -group 'dev.xdark' -version '2.0.1' - -repositories { - mavenCentral() -} - -sourceSets { - java11 { - java { - srcDirs = ['src/main/java11'] - } - } - -} - -dependencies { - def junitVersion = '5.10.1' - testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" - testImplementation "org.junit.jupiter:junit-jupiter-engine:$junitVersion" - testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion" - - testImplementation 'org.ow2.asm:asm:9.5' - testImplementation 'org.ow2.asm:asm-tree:9.5' - - def annotationsVersion = '24.1.0' - compileOnly "org.jetbrains:annotations:$annotationsVersion" - testCompileOnly "org.jetbrains:annotations:$annotationsVersion" -} - -tasks.withType(JavaCompile).configureEach { - options.compilerArgs.addAll(['-parameters', '-g:lines,source,vars']) -} - -compileJava { - options.release.set(8) -} - -compileJava11Java { - options.release.set(11) -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(11)) - } -} - -jar { - manifest { - attributes "Multi-Release": 'true' - } - from sourceSets.java11.output -} - -test { - useJUnitPlatform() -} - -java { - withJavadocJar() - withSourcesJar() -} - -publishing { - repositories { - maven { - name = 'sources-repo' - url = 'file:///tmp/sources-repo' - } - } - publications { - maven(MavenPublication) { - from components.java - artifact sourcesJar - } - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..6dc67e6 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,36 @@ +plugins { + java + `maven-publish` +} + +group = "dev.xdark" +version = "2.1.0" + +repositories.mavenCentral() + +dependencies { + val junitVersion = "5.10.1" + testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion") + testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitVersion") + testImplementation("org.junit.jupiter:junit-jupiter-params:$junitVersion") + + val asmVersion = "9.7" + testImplementation("org.ow2.asm:asm:$asmVersion") + testImplementation("org.ow2.asm:asm-tree:$asmVersion") + + val annotationsVersion = "24.1.0" + compileOnly("org.jetbrains:annotations:$annotationsVersion") + testCompileOnly("org.jetbrains:annotations:$annotationsVersion") +} + +tasks.withType().configureEach { + options.compilerArgs.addAll(listOf("-parameters", "-g:lines,source,vars")) +} +tasks.withType().configureEach { + useJUnitPlatform() +} + +java { + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + withSourcesJar() +} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 365e609..0000000 --- a/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = 'jlinker' - diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..cc648f5 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "jlinker" diff --git a/src/main/java/dev/xdark/jlinker/Error.java b/src/main/java/dev/xdark/jlinker/Error.java index f06bc27..817815d 100755 --- a/src/main/java/dev/xdark/jlinker/Error.java +++ b/src/main/java/dev/xdark/jlinker/Error.java @@ -1,13 +1,14 @@ package dev.xdark.jlinker; +import org.jetbrains.annotations.NotNull; + import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; public final class Error implements Result { private static final List> ERRORS = Arrays.stream(FailureReason.values()) - .map(Error::new) - .collect(Collectors.toList()); + .>map(Error::new) + .toList(); private final FailureReason reason; Error(FailureReason reason) { @@ -15,16 +16,17 @@ public final class Error implements Result { } @Override - public V getValue() { - throw new UnsupportedOperationException(); + public @NotNull V value() { + throw new IllegalStateException(); } @Override - public FailureReason getFailureReason() { + public @NotNull FailureReason failureReason() { return reason; } static Error of(FailureReason reason) { + //noinspection unchecked return (Error) ERRORS.get(reason.ordinal()); } } diff --git a/src/main/java/dev/xdark/jlinker/JVMLinkResolver.java b/src/main/java/dev/xdark/jlinker/JVMLinkResolver.java index 0b191ab..05f5517 100644 --- a/src/main/java/dev/xdark/jlinker/JVMLinkResolver.java +++ b/src/main/java/dev/xdark/jlinker/JVMLinkResolver.java @@ -10,7 +10,7 @@ final class JVMLinkResolver implements LinkResolver { @Override - public Result resolveVirtualMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type) { + public @NotNull Result resolveVirtualMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type) { if (Modifier.isInterface(info.getAccessFlags())) { return Error.of(FailureReason.ACC_INTERFACE_SET); } @@ -22,7 +22,7 @@ public Result resolveVirtualMethod(@NotNull ClassInfo info, @NotNull } @Override - public Result resolveStaticMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type, boolean itf) { + public @NotNull Result resolveStaticMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type, boolean itf) { MethodInfo method; if (itf) { if (!Modifier.isInterface(info.getAccessFlags())) { @@ -45,16 +45,19 @@ public Result resolveStaticMethod(@NotNull ClassInfo info, @NotNull } @Override - public Result resolveSpecialMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type, boolean itf) { + public @NotNull Result resolveSpecialMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type, boolean itf) { if (Modifier.isInterface(info.getAccessFlags()) != itf) { return Error.of(itf ? FailureReason.ACC_INTERFACE_UNSET : FailureReason.ACC_INTERFACE_SET); } - MethodInfo method = itf ? uncachedInterfaceMethod(info, name, type) : uncachedLookupMethod(info, name, type); + MethodInfo method; + if (itf || (method = uncachedLookupMethod(info, name, type)) == null) { + method = uncachedInterfaceMethod(info, name, type); + } return checkVirtualMethod(method); } @Override - public Result resolveInterfaceMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type) { + public @NotNull Result resolveInterfaceMethod(@NotNull ClassInfo info, @NotNull String name, @NotNull MethodDescriptor type) { if (!Modifier.isInterface(info.getAccessFlags())) { return Error.of(FailureReason.ACC_INTERFACE_UNSET); } @@ -69,7 +72,7 @@ public Result resolveInterfaceMethod(@NotNull ClassInfo info, @NotNu } @Override - public Result resolveStaticField(@NotNull ClassInfo owner, @NotNull String name, @NotNull FieldDescriptor type) { + public @NotNull Result resolveStaticField(@NotNull ClassInfo owner, @NotNull String name, @NotNull FieldDescriptor type) { ClassInfo info = owner; FieldInfo field = null; while (owner != null) { @@ -93,7 +96,7 @@ public Result resolveStaticField(@NotNull ClassInfo owner, @NotNull S } @Override - public Result resolveVirtualField(@NotNull ClassInfo info, @NotNull String name, @NotNull FieldDescriptor type) { + public @NotNull Result resolveVirtualField(@NotNull ClassInfo info, @NotNull String name, @NotNull FieldDescriptor type) { while (info != null) { FieldInfo field = info.getField(name, type); if (field != null) { @@ -111,9 +114,8 @@ public Result resolveVirtualField(@NotNull ClassInfo info, @NotNull S MethodInfo uncachedLookupMethod(ClassInfo owner, String name, MethodDescriptor descriptor) { do { MethodInfo method = owner.getMethod(name, descriptor); - if (method != null) { + if (method != null) return method; - } } while ((owner = owner.getSuperclass()) != null); return null; } @@ -153,7 +155,6 @@ MethodInfo uncachedInterfaceMethod(ClassInfo owner, String name, MethodDescripto private V uncachedInterfaceLookup(ClassInfo info, String name, T desc, boolean guessAbstract, UncachedResolve resolve) { V guess = null; Deque queue = new ArrayDeque<>(); - queue.push(info); do { if (Modifier.isInterface(info.getAccessFlags())) { // Only check field/method if it's an interface. diff --git a/src/main/java/dev/xdark/jlinker/JVMRuntimeResolver.java b/src/main/java/dev/xdark/jlinker/JVMRuntimeResolver.java index 05565d9..48f2775 100644 --- a/src/main/java/dev/xdark/jlinker/JVMRuntimeResolver.java +++ b/src/main/java/dev/xdark/jlinker/JVMRuntimeResolver.java @@ -21,7 +21,7 @@ final class JVMRuntimeResolver implements RuntimeResolver { public @NotNull Result resolveVirtualMethod(@NotNull ClassInfo owner, @NotNull String name, @NotNull MethodDescriptor descriptor) { Result result = linkResolver.resolveVirtualMethod(owner, name, descriptor); if (result instanceof Success) { - if (Modifier.isAbstract(result.getValue().getAccessFlags())) { + if (Modifier.isAbstract(result.value().getAccessFlags())) { return Error.of(FailureReason.ACC_ABSTRACT_SET); } } diff --git a/src/main/java/dev/xdark/jlinker/LinkResolver.java b/src/main/java/dev/xdark/jlinker/LinkResolver.java index 1dfca34..453acc1 100644 --- a/src/main/java/dev/xdark/jlinker/LinkResolver.java +++ b/src/main/java/dev/xdark/jlinker/LinkResolver.java @@ -1,5 +1,6 @@ package dev.xdark.jlinker; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Modifier; @@ -20,6 +21,7 @@ public interface LinkResolver { * @param itf Whether the owner is an interface class. * @return Resolution result. */ + @NotNull Result resolveStaticMethod(@NotNull ClassInfo owner, @NotNull String name, @NotNull MethodDescriptor descriptor, boolean itf); /** @@ -30,6 +32,7 @@ public interface LinkResolver { * @param descriptor Method descriptor. * @return Resolution result. */ + @NotNull default Result resolveStaticMethod(@NotNull ClassInfo owner, @NotNull String name, @NotNull MethodDescriptor descriptor) { return resolveStaticMethod(owner, name, descriptor, Modifier.isInterface(owner.getAccessFlags())); } @@ -43,6 +46,7 @@ default Result resolveStaticMethod(@NotNull ClassInfo owner, @NotNul * @param itf Whether the owner is an interface class. * @return Resolution result. */ + @NotNull Result resolveSpecialMethod(@NotNull ClassInfo owner, @NotNull String name, @NotNull MethodDescriptor descriptor, boolean itf); /** @@ -53,6 +57,7 @@ default Result resolveStaticMethod(@NotNull ClassInfo owner, @NotNul * @param descriptor Method descriptor. * @return Resolution result. */ + @NotNull default Result resolveSpecialMethod(@NotNull ClassInfo owner, @NotNull String name, @NotNull MethodDescriptor descriptor) { return resolveSpecialMethod(owner, name, descriptor, Modifier.isInterface(owner.getAccessFlags())); } @@ -65,6 +70,7 @@ default Result resolveSpecialMethod(@NotNull ClassInfo owner, @NotNu * @param descriptor Method descriptor. * @return Resolution result. */ + @NotNull Result resolveVirtualMethod(@NotNull ClassInfo owner, @NotNull String name, @NotNull MethodDescriptor descriptor); /** @@ -75,6 +81,7 @@ default Result resolveSpecialMethod(@NotNull ClassInfo owner, @NotNu * @param descriptor Method descriptor. * @return Resolution result. */ + @NotNull Result resolveInterfaceMethod(@NotNull ClassInfo owner, @NotNull String name, @NotNull MethodDescriptor descriptor); /** @@ -85,6 +92,7 @@ default Result resolveSpecialMethod(@NotNull ClassInfo owner, @NotNu * @param descriptor Field descriptor. * @return Resolution result. */ + @NotNull Result resolveStaticField(@NotNull ClassInfo owner, @NotNull String name, @NotNull FieldDescriptor descriptor); /** @@ -95,11 +103,14 @@ default Result resolveSpecialMethod(@NotNull ClassInfo owner, @NotNu * @param descriptor Field descriptor. * @return Resolution result. */ + @NotNull Result resolveVirtualField(@NotNull ClassInfo owner, @NotNull String name, @NotNull FieldDescriptor descriptor); /** * @return JVM link resolver. */ + @NotNull + @Contract(pure = true) static LinkResolver jvm() { return new JVMLinkResolver(); } diff --git a/src/main/java/dev/xdark/jlinker/Result.java b/src/main/java/dev/xdark/jlinker/Result.java index 6e02292..188810a 100755 --- a/src/main/java/dev/xdark/jlinker/Result.java +++ b/src/main/java/dev/xdark/jlinker/Result.java @@ -1,8 +1,25 @@ package dev.xdark.jlinker; -public interface Result { +import org.jetbrains.annotations.NotNull; - V getValue(); +/** + * Resolution result. + * + * @author xDark + */ +public sealed interface Result permits Success, Error { - FailureReason getFailureReason(); + /** + * @return Resolution result. + * @throws IllegalStateException If in error state. + */ + @NotNull + V value(); + + /** + * @return Resolution result. + * @throws IllegalStateException If in success state. + */ + @NotNull + FailureReason failureReason(); } diff --git a/src/main/java/dev/xdark/jlinker/Success.java b/src/main/java/dev/xdark/jlinker/Success.java index a665183..471349b 100644 --- a/src/main/java/dev/xdark/jlinker/Success.java +++ b/src/main/java/dev/xdark/jlinker/Success.java @@ -18,12 +18,12 @@ public final class Success implements Result { } @Override - public @NotNull V getValue() { + public @NotNull V value() { return value; } @Override - public @NotNull FailureReason getFailureReason() { - throw new UnsupportedOperationException(); + public @NotNull FailureReason failureReason() { + throw new IllegalStateException(); } } diff --git a/src/main/java11/module-info.java b/src/main/java/module-info.java similarity index 56% rename from src/main/java11/module-info.java rename to src/main/java/module-info.java index 2c6a851..a249e36 100644 --- a/src/main/java11/module-info.java +++ b/src/main/java/module-info.java @@ -1,3 +1,4 @@ module dev.xdark.jlinker { exports dev.xdark.jlinker; + requires static org.jetbrains.annotations; } diff --git a/src/main/java11/dev/xdark/jlinker/Java11Hack.java b/src/main/java11/dev/xdark/jlinker/Java11Hack.java deleted file mode 100644 index ddf3fc1..0000000 --- a/src/main/java11/dev/xdark/jlinker/Java11Hack.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.xdark.jlinker; - -// TODO: java compiler refuses to generate module-info if there is nothing in the package -// Get rid of this somehow some day -final class Java11Hack { - private Java11Hack() { - throw new RuntimeException("For javac"); - } -} diff --git a/src/test/java/dev/xdark/jlinker/LinkResolverTest.java b/src/test/java/dev/xdark/jlinker/LinkResolverTest.java index 2173f9c..7723c55 100644 --- a/src/test/java/dev/xdark/jlinker/LinkResolverTest.java +++ b/src/test/java/dev/xdark/jlinker/LinkResolverTest.java @@ -61,7 +61,7 @@ public void testVirtualField() { private void doTest(String owner, String name, String desc, String expected, Resolve resolve) { Result result = resolve.resolve(linkResolver, provider.findClass(owner), name, new DescriptorString(desc)); testResult(result); - testMatch(result.getValue(), expected); + testMatch(result.value(), expected); } private void doTest(Class owner, String name, String desc, String expected, Resolve resolve) { @@ -74,7 +74,7 @@ private void doTest(Class owner, String name, String d private static void testResult(Result result) { if (result instanceof Error) { - fail(result.getFailureReason().name()); + fail(result.failureReason().name()); } } diff --git a/src/test/java/dev/xdark/jlinker/RuntimeResolverTest.java b/src/test/java/dev/xdark/jlinker/RuntimeResolverTest.java index f84563c..1d64223 100644 --- a/src/test/java/dev/xdark/jlinker/RuntimeResolverTest.java +++ b/src/test/java/dev/xdark/jlinker/RuntimeResolverTest.java @@ -26,7 +26,7 @@ public void testInterfaceMethod() { private void doTest(String owner, String name, String desc, String expected, Resolve resolve) { Result result = resolve.resolve(resolver, provider.findClass(owner), name, new DescriptorString(desc)); testResult(result); - testMatch(result.getValue(), expected); + testMatch(result.value(), expected); } private void doTest(Class owner, String name, String desc, String expected, Resolve resolve) { @@ -39,7 +39,7 @@ private void doTest(Class owner, String name, String desc, Class expected, private static void testResult(Result result) { if (result instanceof Error) { - fail(result.getFailureReason().name()); + fail(result.failureReason().name()); } }