diff --git a/src/main/java/io/papermc/codebook/lvt/LvtAssignmentSuggester.java b/src/main/java/io/papermc/codebook/lvt/LvtAssignmentSuggester.java index f7c979f..4414979 100644 --- a/src/main/java/io/papermc/codebook/lvt/LvtAssignmentSuggester.java +++ b/src/main/java/io/papermc/codebook/lvt/LvtAssignmentSuggester.java @@ -22,6 +22,9 @@ package io.papermc.codebook.lvt; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Type; import org.objectweb.asm.tree.MethodInsnNode; @@ -36,6 +39,11 @@ private LvtAssignmentSuggester() {} return suggested; } + suggested = suggestNameForRandomSource(methodName, insn); + if (suggested != null) { + return suggested; + } + suggested = suggestNameFromGetter(methodName); if (suggested != null) { return suggested; @@ -80,6 +88,49 @@ public static String suggestNameFromRecord(final String methodName) { return methodName; } + private static @Nullable String suggestNameForRandomSource(final String methodName, final MethodInsnNode insn) { + if (!"net/minecraft/util/RandomSource".equals(insn.owner) || insn.desc == null) { + return null; + } + + if (!methodName.startsWith("next") || "next".equals(methodName)) { + return null; + } + + final Function, Predicate> equalsAny = strings -> s -> strings.stream().anyMatch(Predicate.isEqual(s)); + final @Nullable Predicate expectedNextWord = switch (Type.getReturnType(insn.desc).getDescriptor()) { + case "B" -> equalsAny.apply(Set.of("Byte")); + case "C" -> equalsAny.apply(Set.of("Char", "Character")); + case "D" -> equalsAny.apply(Set.of("Double")); + case "F" -> equalsAny.apply(Set.of("Float")); + case "I" -> equalsAny.apply(Set.of("Int", "Integer")); + case "L" -> equalsAny.apply(Set.of("Long")); + case "S" -> equalsAny.apply(Set.of("Short")); + case "Z" -> equalsAny.apply(Set.of("Bool", "Boolean")); + default -> null; + }; + if (expectedNextWord == null) { + return null; + } + + final StringBuilder nextWord = new StringBuilder(); + for (int i = "next".length(); i < methodName.length(); i++) { + final char ch = methodName.charAt(i); + if (nextWord.isEmpty()) { + nextWord.append(ch); + } else if (!Character.isUpperCase(ch)) { + nextWord.append(ch); + } else { + break; + } + } + + if (expectedNextWord.test(nextWord.toString())) { + return "random" + nextWord; + } + return null; + } + private static @Nullable String suggestNameFromGetter(final String methodName) { if (!methodName.startsWith("get") || methodName.equals("get")) { // If the method isn't `get` - or if the method is just `get` diff --git a/src/test/resources/io/papermc/codebook/lvt/LvtAssignmentSuggesterTest.csv b/src/test/resources/io/papermc/codebook/lvt/LvtAssignmentSuggesterTest.csv index 280827d..5786375 100644 --- a/src/test/resources/io/papermc/codebook/lvt/LvtAssignmentSuggesterTest.csv +++ b/src/test/resources/io/papermc/codebook/lvt/LvtAssignmentSuggesterTest.csv @@ -45,3 +45,11 @@ getOrCreate,io/paper/Paper,()Ljava/lang/String;, gettingBetter,io/paper/Paper,()Ljava/lang/String;, as,io/paper/paper,()Ljava/lang/String;, ass,io/paper/paper,()Ljava/lang/String;, +# random methods,,, +nextInt,net/minecraft/util/RandomSource,()I,randomInt +nextInteger,net/minecraft/util/RandomSource,()I,randomInteger +nextInt,net/minecraft/util/RandomSource,()L, +nextInt,io/paper/Paper,()I, +nextIntBetween,net/minecraft/util/RandomSource,(II)I,randomInt +nextIntBetween,net/minecraft/util/RandomSource,(II)L, +nextBoolean,net/minecraft/util/RandomSource,()Z,randomBoolean