Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add general parameter naming #9

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 93 additions & 21 deletions src/main/java/de/oceanlabs/mcp/mcinjector/MCInjector.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
package de.oceanlabs.mcp.mcinjector;
import static joptsimple.internal.Reflection.invoke;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import de.oceanlabs.mcp.mcinjector.lvt.LVTNaming;
import joptsimple.OptionException;
Expand All @@ -30,7 +38,9 @@ public class MCInjector
private Path fileIn, fileOut;
private Path excIn, excOut;
private Path accIn, accOut;
private Path ctrIn, ctrOut;
private Path ctrIn;
private Path prmIn, prmOut;
private List<Path> classpath;
private LVTNaming lvt;

public MCInjector(Path fileIn, Path fileOut)
Expand Down Expand Up @@ -74,6 +84,11 @@ public void publish(LogRecord record)
return this;
}

private MCInjector classpath(List<Path> clsPath) {
this.classpath = clsPath;
return this;
}

public MCInjector exceptions(Path exc)
{
this.excIn = exc;
Expand Down Expand Up @@ -104,9 +119,15 @@ public MCInjector constructors(Path ctrs)
return this;
}

public MCInjector constructorsOut(Path out)
public MCInjector parameters(Path ctrs)
{
this.prmIn = ctrs;
return this;
}

public MCInjector parametersOut(Path out)
{
this.ctrOut = out;
this.prmOut = out;
return this;
}

Expand All @@ -121,9 +142,11 @@ public void process() throws IOException
{
MCInjectorImpl.process(fileIn, fileOut,
accIn, accOut,
ctrIn, ctrOut,
ctrIn,
excIn, excOut,
lvt);
prmIn, prmOut,
lvt,
classpath);
}

private static ValueConverter<Path> PATH_ARG = new ValueConverter<Path>()
Expand All @@ -143,6 +166,23 @@ public String valuePattern()
return null;
}
};
private static ValueConverter<Path[]> MULTIPATH_ARG = new ValueConverter<Path[]>()
{
public Path[] convert(String value )
{
return Arrays.stream(value.split(File.pathSeparator)).map(Paths::get).toArray(Path[]::new);
}

public Class<Path[]> valueType()
{
return Path[].class;
}

public String valuePattern()
{
return null;
}
};
private static ValueConverter<Level> LEVEL_ARG = new ValueConverter<Level>()
{
public Level convert( String value )
Expand All @@ -164,23 +204,42 @@ public String valuePattern()
public static void main(String[] args) throws Exception
{
OptionParser parser = new OptionParser();
OptionSpec<Void> help = parser.accepts("help") .forHelp();
OptionSpec<Void> ver = parser.accepts("version").forHelp();
OptionSpec<Path> in = parser.accepts("in") .withRequiredArg().withValuesConvertedBy(PATH_ARG).required();
OptionSpec<Path> out = parser.accepts("out") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> log = parser.accepts("log") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> exc = parser.accepts("exc") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> excOut = parser.accepts("excOut").withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> acc = parser.accepts("acc") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> accOut = parser.accepts("accOut").withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> ctr = parser.accepts("ctr") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> ctrOut = parser.accepts("ctrOut").withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Level> logLvl = parser.accepts("level") .withRequiredArg().withValuesConvertedBy(LEVEL_ARG).defaultsTo(Level.INFO);
OptionSpec<LVTNaming> lvt = parser.accepts("lvt").withRequiredArg().ofType(LVTNaming.class).defaultsTo(LVTNaming.STRIP);
OptionSpec<Void> help = parser.accepts("help") .forHelp();
OptionSpec<Void> ver = parser.accepts("version") .forHelp();
OptionSpec<Path> in = parser.accepts("in") .withRequiredArg().withValuesConvertedBy(PATH_ARG).required();
OptionSpec<Path> out = parser.accepts("out") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> cfg = parser.accepts("cfg") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> log = parser.accepts("log") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> exc = parser.accepts("exc") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> excOut = parser.accepts("excOut") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> acc = parser.accepts("acc") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> accOut = parser.accepts("accOut") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> ctr = parser.accepts("ctr") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> ctrOut = parser.accepts("ctrOut") .withRequiredArg().withValuesConvertedBy(PATH_ARG).describedAs("legacy, can't be used anymore");
OptionSpec<Path> prm = parser.accepts("prm") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Path> prmOut = parser.accepts("prmOut") .withRequiredArg().withValuesConvertedBy(PATH_ARG);
OptionSpec<Level> logLvl = parser.accepts("level") .withRequiredArg().withValuesConvertedBy(LEVEL_ARG).defaultsTo(Level.INFO);
OptionSpec<LVTNaming> lvt = parser.accepts("lvt") .withRequiredArg().ofType(LVTNaming.class).defaultsTo(LVTNaming.STRIP);
OptionSpec<Path[]> clsPath = parser.acceptsAll(Arrays.stream(new String[]{"classpath", "e"}).collect(Collectors.toList())).withRequiredArg().withValuesConvertedBy(MULTIPATH_ARG);

try
{
OptionSet o = parser.parse(args);
OptionSet o;
Set<Path> extraArgsFiles = new HashSet<>();
while (true) {
o = parser.parse(Stream.concat(Arrays.stream(args), extraArgsFiles.stream().flatMap(path -> {
try {
return Files.lines(path);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
})).toArray(String[]::new));
if (o.valuesOf(cfg).size() == extraArgsFiles.size()) {
break;
}
extraArgsFiles.addAll(o.valuesOf(cfg));
}
if (o.has(help))
{
System.out.println(VERSION);
Expand All @@ -192,6 +251,12 @@ else if (o.has(ver))
System.out.println(VERSION);
return;
}
else if (o.has(ctrOut))
{
System.out.println("ctrOut is using the legacy format and is no longer supported!");
return;
}


MCInjector.LOG.setUseParentHandlers(false);
MCInjector.LOG.setLevel(o.valueOf(logLvl));
Expand All @@ -205,21 +270,28 @@ else if (o.has(ver))
LOG.info("Access: " + o.valueOf(acc));
LOG.info(" " + o.valueOf(accOut));
LOG.info("Constructors: " + o.valueOf(ctr));
LOG.info(" " + o.valueOf(ctrOut));
LOG.info("Extra Params: " + o.valueOf(prm));
LOG.info(" " + o.valueOf(prmOut));
LOG.info("LVT: " + o.valueOf(lvt));
if (o.hasArgument(clsPath))
for(Path[] pp : o.valuesOf(clsPath))
for(Path p : pp)
LOG.info("Classpath: " + p);

try
{
new MCInjector(o.valueOf(in), o.valueOf(out))
.log()
.lvt(o.valueOf(lvt))
.log(o.valueOf(log))
.classpath(o.valuesOf(clsPath).stream().flatMap(Arrays::stream).collect(Collectors.toList()))
.exceptions(o.valueOf(exc))
.exceptionsOut(o.valueOf(excOut))
.access(o.valueOf(acc))
.accessOut(o.valueOf(accOut))
.constructors(o.valueOf(ctr))
.constructorsOut(o.valueOf(ctrOut))
.parameters(o.valueOf(prm))
.parametersOut(o.valueOf(prmOut))
.process();
}
catch (Exception e)
Expand Down
18 changes: 12 additions & 6 deletions src/main/java/de/oceanlabs/mcp/mcinjector/MCInjectorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import de.oceanlabs.mcp.mcinjector.data.Classpath;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
Expand All @@ -32,7 +33,7 @@
import de.oceanlabs.mcp.mcinjector.adaptors.InnerClassInitAdder;
import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer;
import de.oceanlabs.mcp.mcinjector.data.Access;
import de.oceanlabs.mcp.mcinjector.data.Constructors;
import de.oceanlabs.mcp.mcinjector.data.Parameters;
import de.oceanlabs.mcp.mcinjector.data.Exceptions;
import de.oceanlabs.mcp.mcinjector.lvt.LVTFernflower;
import de.oceanlabs.mcp.mcinjector.lvt.LVTLvt;
Expand All @@ -47,17 +48,22 @@ public class MCInjectorImpl
static void process(
Path in, Path out,
Path accIn, Path accOut,
Path ctrIn, Path ctrOut,
Path ctrIn,
Path excIn, Path excOut,
LVTNaming naming)
Path prmIn, Path prmOut,
LVTNaming naming,
List<Path> classpath)
throws IOException
{
if (accIn != null)
Access.INSTANCE.load(accIn);
if (prmIn != null)
Parameters.INSTANCE.load(prmIn);
if (ctrIn != null)
Constructors.INSTANCE.load(ctrIn);
Parameters.INSTANCE.loadLegacy(ctrIn);
if (excIn != null)
Exceptions.INSTANCE.load(excIn);
Classpath.INSTANCE.load(in, classpath);

MCInjector.LOG.info("Processing: " + in);
MCInjector.LOG.info(" Output: " + out);
Expand All @@ -69,8 +75,8 @@ static void process(

if (accOut != null)
Access.INSTANCE.dump(accOut);
if (ctrOut != null)
Constructors.INSTANCE.dump(ctrOut);
if (prmOut != null)
Parameters.INSTANCE.dump(prmOut);
if (excOut != null)
Exceptions.INSTANCE.dump(excOut);

Expand Down
40 changes: 36 additions & 4 deletions src/main/java/de/oceanlabs/mcp/mcinjector/adaptors/ApplyMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,28 @@
import java.util.Set;
import java.util.logging.Level;

import de.oceanlabs.mcp.mcinjector.data.Classpath;
import de.oceanlabs.mcp.mcinjector.data.Parameters;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;

import de.oceanlabs.mcp.mcinjector.MCInjector;
import de.oceanlabs.mcp.mcinjector.MCInjectorImpl;
import de.oceanlabs.mcp.mcinjector.data.Constructors;
import de.oceanlabs.mcp.mcinjector.data.Exceptions;

public class ApplyMap extends ClassVisitor
{
String className;
boolean isEnum;
MCInjectorImpl injector;

public ApplyMap(MCInjectorImpl injector, ClassVisitor cn)
Expand All @@ -39,6 +44,7 @@ public ApplyMap(MCInjectorImpl injector, ClassVisitor cn)
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
this.className = name;
isEnum = (access & Opcodes.ACC_ENUM) != 0;
super.visit(version, access, name, signature, superName, interfaces);
}

Expand Down Expand Up @@ -67,6 +73,7 @@ public void visitEnd()
super.visitEnd();
processLVT(className, name, desc, MCInjectorImpl.getMethodNode(mv));
}

};
}

Expand Down Expand Up @@ -95,25 +102,36 @@ private void processLVT(String cls, String name, String desc, MethodNode mn)
{
List<String> params = new ArrayList<>();
List<Type> types = new ArrayList<>();
boolean isStatic = true;

if ((mn.access & Opcodes.ACC_STATIC) == 0)
{
isStatic = false;
types.add(Type.getType("L" + cls + ";"));
params.add(0, "this");
}

types.addAll(Arrays.asList(Type.getArgumentTypes(mn.desc)));
List<Classpath.Method> potentialSupers = Classpath.INSTANCE.getTree().getInfo(className).getMethodInfo(name, desc).getOverrides();

if (potentialSupers.size() > 1) {
if (mn.visibleAnnotations == null) {
mn.visibleAnnotations = new ArrayList<>();
}
mn.visibleAnnotations.add(new AnnotationNode("java/lang/Override"));
}

//Skip anything with no params
if (types.size() == 0)
return;

MCInjector.LOG.fine(" Generating map:");
String nameFormat = "p_" + name + "_%d_";
String nameFormat = null;
if (name.matches("func_\\d+_.+")) // A srg name method params are just p_MethodID_ParamIndex_
nameFormat = "p_" + name.substring(5, name.indexOf('_', 5)) + "_%s_";
else if (name.equals("<init>")) // Every constructor is given a unique ID, try to load the ID from the map, if none is found assign a new one
nameFormat = "p_i" + Constructors.INSTANCE.getID(className, desc, types.size() > 1) + "_%s_";
else if(!isSynthetic(mn))
nameFormat = "p_" + Parameters.INSTANCE.getName(potentialSupers, cls, name, desc, types.size() > params.size()) + "_%s_"; //assign new name only if there are names remaining
else nameFormat = "p_%s_"; //don't really care about synthetics

for (int x = params.size(), y = x; x < types.size(); x++)
{
Expand Down Expand Up @@ -190,4 +208,18 @@ else if (tmp.getType() != AbstractInsnNode.LABEL)

Collections.sort(mn.localVariables, (o1, o2) -> o1.index < o2.index ? -1 : (o1.index == o2.index ? 0 : 1));
}

private boolean isSynthetic(MethodNode mn){
if ((mn.access & Opcodes.ACC_SYNTHETIC) != 0) return true;

//check for special case pursuant to JLS 13.1.7
Copy link
Author

@JoJoDeveloping JoJoDeveloping Aug 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

//which specifies that these are the one and only proper methods that may be generated and not be marked synthetic
if (isEnum && (mn.access & Opcodes.ACC_STATIC) != 0) {
if ("valueOf".equals(mn.name) && mn.desc.equals("(Ljava/lang/String;)L" + className + ";"))
return true;
if("values".equals(mn.name) && mn.desc.equals("()[L" + className + ";"))
return true;
}
return false;
}
}
Loading