Skip to content

Commit

Permalink
Handle fluent getters for primitive return types (#9)
Browse files Browse the repository at this point in the history
Co-authored-by: MiniDigger | Martin <[email protected]>
  • Loading branch information
Machine-Maker and MiniDigger authored Jan 14, 2024
1 parent 71c74c5 commit f21db75
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ private String suggestNameFromClassType(final ClassType type) throws IOException
// TODO Try to determine name from signature, rather than just descriptor
final @Nullable ClassData typeClass = this.context.getContextProvider().findClass(type);
if (typeClass != null) {
if (typeClass.doesExtendOrImplement(this.listClass) && !typeClass.name().startsWith("net/minecraft/nbt/")) { // exclude nbt lists
if (typeClass.doesExtendOrImplement(this.listClass)
&& !typeClass.name().startsWith("net/minecraft/nbt/")) { // exclude nbt lists
return "list";
} else if (typeClass.doesExtendOrImplement(this.setClass)) {
return "set";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import dev.denwav.hypo.model.data.MethodData;
import dev.denwav.hypo.model.data.MethodDescriptor;
import dev.denwav.hypo.model.data.types.JvmType;
import io.papermc.codebook.lvt.suggestion.FluentGetterSuggester;
import io.papermc.codebook.lvt.suggestion.GenericSuggester;
import io.papermc.codebook.lvt.suggestion.LvtSuggester;
import io.papermc.codebook.lvt.suggestion.MathSuggester;
Expand Down Expand Up @@ -76,6 +77,7 @@ public final class RootLvtSuggester extends AbstractModule implements LvtSuggest
SingleVerbSuggester.class,
VerbPrefixBooleanSuggester.class,
SingleVerbBooleanSuggester.class,
FluentGetterSuggester.class,
RecordComponentSuggester.class,
GenericSuggester.class);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* codebook is a remapper utility for the PaperMC project.
*
* Copyright (c) 2023 Kyle Wood (DenWav)
* Contributors
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 3 only, no later versions.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/

package io.papermc.codebook.lvt.suggestion;

import dev.denwav.hypo.model.data.types.PrimitiveType;
import io.papermc.codebook.lvt.suggestion.context.ContainerContext;
import io.papermc.codebook.lvt.suggestion.context.method.MethodCallContext;
import io.papermc.codebook.lvt.suggestion.context.method.MethodInsnContext;
import java.io.IOException;
import java.util.Set;
import java.util.function.IntPredicate;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;

public class FluentGetterSuggester implements LvtSuggester {

private static final Set<String> ignored = Set.of(
"byteValue",
"shortValue",
"intValue",
"longValue",
"floatValue",
"doubleValue",
"booleanValue",
"charValue",
"get");

// 3 instructions, load "this" local var, getfield, return - TODO maybe if there is a CAST,
private static final IntPredicate[] OPCODES_IN_ORDER = new IntPredicate[] {
i -> i == Opcodes.ALOAD, i -> i == Opcodes.GETFIELD, i -> i >= Opcodes.IRETURN && i <= Opcodes.RETURN
};

@Override
public @Nullable String suggestFromMethod(
final MethodCallContext call, final MethodInsnContext insn, final ContainerContext container)
throws IOException {
// I think it's best to only work with primitive types here, as other types should already have names
// and this dramatically cuts down on the number of methods analyzed because we aren't filtering by
// method name
if (!(call.data().returnType() instanceof PrimitiveType)
|| !call.data().params().isEmpty()) {
return null;
}
int opcodeIndex = 0;
final InsnList instructions = call.node().instructions;
if (instructions.size() == 0) {
return null;
}
for (final AbstractInsnNode methodInsn : instructions) {
if (methodInsn.getOpcode() == -1) {
continue;
}
if (opcodeIndex == OPCODES_IN_ORDER.length) {
break; // matched the correct order
}
if (OPCODES_IN_ORDER[opcodeIndex].test(methodInsn.getOpcode())) {
opcodeIndex++;
} else {
return null;
}
}
if (call.data().isStatic()) { // limit static matches
if ("java/lang/System".equals(insn.node().owner) && "currentTimeMillis".equals(insn.node().name)) {
return "currentTimeMillis";
}
} else {
final String name = call.data().name();
if (ignored.contains(name)) {
return null;
}
return name;
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
Expand Down Expand Up @@ -125,6 +127,10 @@ void testSuggester(
when(method.param(anyInt())).thenCallRealMethod();
when(method.returnType()).thenCallRealMethod();

final MethodNode node = new MethodNode(Opcodes.ASM9, methodName, methodDescriptor, null, null);
node.instructions = new InsnList();
when(method.getNode()).thenReturn(node);

if (methodOwner.equals(HypoModelUtil.normalizedClassName(RANDOM_SOURCE_TYPE.asInternalName()))) {
when(owner.doesExtendOrImplement(this.randomSourceClass)).thenReturn(true);
} else {
Expand Down

0 comments on commit f21db75

Please sign in to comment.