mirror of
https://github.com/zaaarf/lillero-mapper.git
synced 2024-11-22 21:04:49 +01:00
feat: rewrote the mapper api to make more sense
This commit is contained in:
parent
ea030e54b9
commit
fa6c73faf0
12 changed files with 221 additions and 249 deletions
|
@ -1,9 +1,9 @@
|
||||||
package ftbsc.lll.exceptions;
|
package ftbsc.lll.exceptions;
|
||||||
|
|
||||||
import ftbsc.lll.mapper.IMapper;
|
import ftbsc.lll.mapper.IMappingFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown upon failure to find the requested mapping within a loaded {@link IMapper}.
|
* Thrown upon failure to find the requested mapping within a loaded {@link IMappingFormat}.
|
||||||
*/
|
*/
|
||||||
public class MappingNotFoundException extends RuntimeException {
|
public class MappingNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
package ftbsc.lll.mapper;
|
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.MappingNotFoundException;
|
|
||||||
import ftbsc.lll.mapper.tools.data.ClassData;
|
|
||||||
import ftbsc.lll.mapper.tools.data.FieldData;
|
|
||||||
import ftbsc.lll.mapper.tools.data.MethodData;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A default implementation of {@link IMapper} meant to
|
|
||||||
* recycle as much code as possible.
|
|
||||||
*/
|
|
||||||
public abstract class AbstractMapper implements IMapper {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link Map} tying each plain class name to its class data.
|
|
||||||
*/
|
|
||||||
protected final Map<String, ClassData> mappings = new HashMap<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
this.mappings.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IMapper getInverted() {
|
|
||||||
AbstractMapper inverted = newInstance();
|
|
||||||
this.mappings.forEach((name, data) -> {
|
|
||||||
ClassData reverse = data.generateReverseMappings(this);
|
|
||||||
inverted.mappings.put(data.nameMapped, reverse);
|
|
||||||
});
|
|
||||||
return inverted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of this type of mapper.
|
|
||||||
* @return the new, empty instance
|
|
||||||
*/
|
|
||||||
protected abstract AbstractMapper newInstance();
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClassData getClassData(String name) throws MappingNotFoundException {
|
|
||||||
ClassData data = this.mappings.get(name.replace('.', '/'));
|
|
||||||
if(data == null)
|
|
||||||
throw new MappingNotFoundException("class", name);
|
|
||||||
else return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodData getMethodData(String parent, String name, String descriptor) throws MappingNotFoundException {
|
|
||||||
return this.getClassData(parent).mapMethod(name, descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FieldData getFieldData(String parent, String name) throws MappingNotFoundException {
|
|
||||||
return this.getClassData(parent).mapField(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, ClassData> getRawMappings() {
|
|
||||||
return this.mappings;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
package ftbsc.lll.mapper;
|
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.MalformedMappingsException;
|
|
||||||
import ftbsc.lll.exceptions.MappingNotFoundException;
|
|
||||||
import ftbsc.lll.mapper.tools.data.ClassData;
|
|
||||||
import ftbsc.lll.mapper.tools.data.FieldData;
|
|
||||||
import ftbsc.lll.mapper.tools.data.MethodData;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The shared interface between all mappers.
|
|
||||||
*/
|
|
||||||
public interface IMapper {
|
|
||||||
/**
|
|
||||||
* Checks whether this mapper can process the given lines.
|
|
||||||
* @param lines the lines to read
|
|
||||||
* @return whether this type of mapper can process these lines
|
|
||||||
*/
|
|
||||||
boolean claim(List<String> lines);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a priority for this implementation: the higher the number,
|
|
||||||
* the higher the priority.
|
|
||||||
* This is used to resolve conflicts when multiple mappers attempt to
|
|
||||||
* {@link #claim(List) claim} a given mapping file.
|
|
||||||
* @return the priority
|
|
||||||
*/
|
|
||||||
default int priority() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the {@link IMapper} given the lines, ignoring errors depending on the
|
|
||||||
* given ignoreErrors flag.
|
|
||||||
* @param lines the lines to read
|
|
||||||
* @param ignoreErrors try to ignore errors and keep going
|
|
||||||
* @throws MalformedMappingsException if an error is encountered and ignoreErrors is false
|
|
||||||
*/
|
|
||||||
void populate(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds an {@link IMapper} that functions in reverse to this one (i.e. one that
|
|
||||||
* considers as "mapped" what this one considers plain, and vice versa).
|
|
||||||
* @return the inverted mapper
|
|
||||||
*/
|
|
||||||
IMapper getInverted();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Completely resets the mapper, clearing it of all existing mappings.
|
|
||||||
*/
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the {@link ClassData}
|
|
||||||
* @param name the plain internal name of the desired class
|
|
||||||
* @return the obfuscated name of the class
|
|
||||||
* @throws MappingNotFoundException if no mapping is found
|
|
||||||
*/
|
|
||||||
ClassData getClassData(String name) throws MappingNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the obfuscated name of a class member (field or method).
|
|
||||||
* @param parent the plain internal name of the parent class
|
|
||||||
* @param name the field name
|
|
||||||
* @param descriptor the descriptor of the member (only for methods)
|
|
||||||
* @return the obfuscated name of the given member
|
|
||||||
* @throws MappingNotFoundException if no mapping is found
|
|
||||||
*/
|
|
||||||
MethodData getMethodData(String parent, String name, String descriptor) throws MappingNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the obfuscated name of a class member (field or method).
|
|
||||||
* @param parent the plain internal name of the parent class
|
|
||||||
* @param name the field name
|
|
||||||
* @return the obfuscated name of the given member
|
|
||||||
* @throws MappingNotFoundException if no mapping is found
|
|
||||||
*/
|
|
||||||
FieldData getFieldData(String parent, String name) throws MappingNotFoundException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the "raw mappings" from an {@link IMapper}.
|
|
||||||
* @return a map tying each {@link ClassData} to the class' plain name
|
|
||||||
*/
|
|
||||||
Map<String, ClassData> getRawMappings();
|
|
||||||
}
|
|
49
src/main/java/ftbsc/lll/mapper/IMappingFormat.java
Normal file
49
src/main/java/ftbsc/lll/mapper/IMappingFormat.java
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package ftbsc.lll.mapper;
|
||||||
|
|
||||||
|
import ftbsc.lll.exceptions.MalformedMappingsException;
|
||||||
|
import ftbsc.lll.mapper.tools.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shared interface between all mappers.
|
||||||
|
*/
|
||||||
|
public interface IMappingFormat {
|
||||||
|
/**
|
||||||
|
* Checks whether this mapper can process the given lines.
|
||||||
|
* @param lines the lines to read
|
||||||
|
* @return whether this type of mapper can process these lines
|
||||||
|
*/
|
||||||
|
boolean claim(List<String> lines);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a priority for this implementation: the higher the number,
|
||||||
|
* the higher the priority.
|
||||||
|
* This is used to resolve conflicts when multiple mappers attempt to
|
||||||
|
* {@link #claim(List) claim} a given mapping file.
|
||||||
|
* @return the priority
|
||||||
|
*/
|
||||||
|
default int priority() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Mapper} given the lines, ignoring errors depending on the given flag.
|
||||||
|
* @param lines the lines to read
|
||||||
|
* @param ignoreErrors try to ignore errors and keep going
|
||||||
|
* @return the {@link Mapper}
|
||||||
|
* @throws MalformedMappingsException if an error is encountered and ignoreErrors is false
|
||||||
|
*/
|
||||||
|
Mapper getMapper(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Mapper} given the lines, ignoring errors depending on the given flag, and
|
||||||
|
* returns its inverted form.
|
||||||
|
* @param lines the lines to read
|
||||||
|
* @param ignoreErrors try to ignore errors and keep going
|
||||||
|
* @throws MalformedMappingsException if an error is encountered and ignoreErrors is false
|
||||||
|
*/
|
||||||
|
default Mapper getInvertedMapper(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
||||||
|
return this.getMapper(lines, ignoreErrors).getInverted();
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main class of the mapper library. It loads all the
|
* The main class of the mapper library. It loads all the
|
||||||
* valid {@link IMapper}s and gets information from them.
|
* valid {@link IMappingFormat}s and gets information from them.
|
||||||
*/
|
*/
|
||||||
public class MapperProvider {
|
public class MapperProvider {
|
||||||
/**
|
/**
|
||||||
|
@ -30,14 +30,14 @@ public class MapperProvider {
|
||||||
/**
|
/**
|
||||||
* A {@link Set} containing all the loaded mapper classes.
|
* A {@link Set} containing all the loaded mapper classes.
|
||||||
*/
|
*/
|
||||||
private Set<Class<? extends IMapper>> loadedMappers = null;
|
private Set<Class<? extends IMappingFormat>> loadedMappers = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the mapper classes into a {@link Set}.
|
* Loads the mapper classes into a {@link Set}.
|
||||||
*/
|
*/
|
||||||
private void loadMappers() {
|
private void loadMappers() {
|
||||||
this.loadedMappers = new HashSet<>();
|
this.loadedMappers = new HashSet<>();
|
||||||
for(IMapper mapper: ServiceLoader.load(IMapper.class))
|
for(IMappingFormat mapper: ServiceLoader.load(IMappingFormat.class))
|
||||||
this.loadedMappers.add(mapper.getClass());
|
this.loadedMappers.add(mapper.getClass());
|
||||||
if(this.loadedMappers.isEmpty())
|
if(this.loadedMappers.isEmpty())
|
||||||
throw new RuntimeException("Something went wrong: no mapper types were loaded successfully!");
|
throw new RuntimeException("Something went wrong: no mapper types were loaded successfully!");
|
||||||
|
@ -48,9 +48,9 @@ public class MapperProvider {
|
||||||
* attempts to load the resource at given location and to populate a mapper with
|
* attempts to load the resource at given location and to populate a mapper with
|
||||||
* its data.
|
* its data.
|
||||||
* @param data the file as a list of strings
|
* @param data the file as a list of strings
|
||||||
* @return a {@link IMapper} (populating it is left to the user)
|
* @return a {@link IMappingFormat} (populating it is left to the user)
|
||||||
*/
|
*/
|
||||||
public static IMapper getMapper(List<String> data) {
|
public static IMappingFormat getMapper(List<String> data) {
|
||||||
if(getInstance().loadedMappers == null)
|
if(getInstance().loadedMappers == null)
|
||||||
getInstance().loadMappers();
|
getInstance().loadMappers();
|
||||||
return getInstance().loadedMappers.stream()
|
return getInstance().loadedMappers.stream()
|
||||||
|
@ -60,7 +60,7 @@ public class MapperProvider {
|
||||||
} catch(ReflectiveOperationException ignored) {}
|
} catch(ReflectiveOperationException ignored) {}
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}).filter(m -> m.claim(data))
|
}).filter(m -> m.claim(data))
|
||||||
.max(Comparator.comparingInt(IMapper::priority))
|
.max(Comparator.comparingInt(IMappingFormat::priority))
|
||||||
.orElseThrow(InvalidResourceException::new);
|
.orElseThrow(InvalidResourceException::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ package ftbsc.lll.mapper.impl;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import ftbsc.lll.exceptions.MalformedMappingsException;
|
import ftbsc.lll.exceptions.MalformedMappingsException;
|
||||||
import ftbsc.lll.mapper.AbstractMapper;
|
import ftbsc.lll.mapper.IMappingFormat;
|
||||||
import ftbsc.lll.mapper.IMapper;
|
|
||||||
import ftbsc.lll.mapper.MapperProvider;
|
import ftbsc.lll.mapper.MapperProvider;
|
||||||
|
import ftbsc.lll.mapper.tools.Mapper;
|
||||||
import ftbsc.lll.mapper.tools.MappingUtils;
|
import ftbsc.lll.mapper.tools.MappingUtils;
|
||||||
import ftbsc.lll.mapper.tools.data.ClassData;
|
import ftbsc.lll.mapper.tools.data.ClassData;
|
||||||
|
|
||||||
|
@ -15,21 +15,22 @@ import java.util.List;
|
||||||
* Special mapper type that actually resolves to an ordered
|
* Special mapper type that actually resolves to an ordered
|
||||||
* sequence of mappers applied one after the other.
|
* sequence of mappers applied one after the other.
|
||||||
*/
|
*/
|
||||||
@AutoService(IMapper.class)
|
@AutoService(IMappingFormat.class)
|
||||||
public class MultiMapper extends AbstractMapper {
|
public class MultiMapper implements IMappingFormat {
|
||||||
@Override
|
@Override
|
||||||
public boolean claim(List<String> lines) {
|
public boolean claim(List<String> lines) {
|
||||||
return lines.get(0).equals("lll multimapper");
|
return lines.get(0).equals("lll multimapper");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void populate(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
public Mapper getMapper(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
||||||
List<IMapper> mapperList = new ArrayList<>();
|
Mapper result = new Mapper();
|
||||||
|
List<Mapper> mapperList = new ArrayList<>();
|
||||||
|
|
||||||
for(int i = 1; i < lines.size(); i++) {
|
for(int i = 1; i < lines.size(); i++) {
|
||||||
List<String> data = MapperProvider.fetchFromLocalOrRemote(lines.get(i));
|
List<String> data = MapperProvider.fetchFromLocalOrRemote(lines.get(i));
|
||||||
IMapper mapper = MapperProvider.getMapper(data);
|
IMappingFormat format = MapperProvider.getMapper(data);
|
||||||
mapper.populate(data, ignoreErrors);
|
mapperList.add(format.getMapper(data, ignoreErrors));
|
||||||
mapperList.add(mapper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapperList.get(0).getRawMappings().forEach((name, data) -> {
|
mapperList.get(0).getRawMappings().forEach((name, data) -> {
|
||||||
|
@ -41,7 +42,7 @@ public class MultiMapper extends AbstractMapper {
|
||||||
|
|
||||||
data.getMethods().forEach((signature, methodData) -> {
|
data.getMethods().forEach((signature, methodData) -> {
|
||||||
for(int i = 1; i < mapperList.size(); i++) {
|
for(int i = 1; i < mapperList.size(); i++) {
|
||||||
IMapper mapper = mapperList.get(i);
|
Mapper mapper = mapperList.get(i);
|
||||||
methodData = mapper.getMethodData(methodData.parentClass.nameMapped, methodData.nameMapped,
|
methodData = mapper.getMethodData(methodData.parentClass.nameMapped, methodData.nameMapped,
|
||||||
MappingUtils.mapMethodDescriptor(methodData.signature.descriptor, mapper, false));
|
MappingUtils.mapMethodDescriptor(methodData.signature.descriptor, mapper, false));
|
||||||
}
|
}
|
||||||
|
@ -54,12 +55,9 @@ public class MultiMapper extends AbstractMapper {
|
||||||
sumData.addField(fieldName, fieldData.nameMapped, fieldData.descriptor);
|
sumData.addField(fieldName, fieldData.nameMapped, fieldData.descriptor);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.mappings.put(sumData.name, sumData);
|
result.getRawMappings().put(sumData.name, sumData);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
return result;
|
||||||
protected AbstractMapper newInstance() {
|
|
||||||
return new MultiMapper();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,17 @@ package ftbsc.lll.mapper.impl;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import ftbsc.lll.exceptions.MalformedMappingsException;
|
import ftbsc.lll.exceptions.MalformedMappingsException;
|
||||||
import ftbsc.lll.mapper.AbstractMapper;
|
import ftbsc.lll.mapper.IMappingFormat;
|
||||||
import ftbsc.lll.mapper.IMapper;
|
import ftbsc.lll.mapper.tools.Mapper;
|
||||||
import ftbsc.lll.mapper.tools.data.ClassData;
|
import ftbsc.lll.mapper.tools.data.ClassData;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link IMapper} capable of parsing SRG mappings.
|
* A {@link IMappingFormat} capable of parsing SRG mappings.
|
||||||
*/
|
*/
|
||||||
@AutoService(IMapper.class)
|
@AutoService(IMappingFormat.class)
|
||||||
public class SRGMapper extends AbstractMapper {
|
public class SRGMapper implements IMappingFormat {
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link Map} tying each obfuscated name to its class data.
|
|
||||||
* Done this way because SRG files provide mapped descriptors in advance,
|
|
||||||
* so we can populate this right a way in a less expensive way.
|
|
||||||
*/
|
|
||||||
private final Map<String, ClassData> mappingsInverted = new HashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean claim(List<String> lines) {
|
public boolean claim(List<String> lines) {
|
||||||
|
@ -33,33 +23,47 @@ public class SRGMapper extends AbstractMapper {
|
||||||
|| firstLineTokens[0].equals("FD:"));
|
|| firstLineTokens[0].equals("FD:"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void populate(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
* Builds the two mappers, and returns one of the two depending on the flag.
|
||||||
|
* Since the SRG format contains descriptor mappings, it's possible to process
|
||||||
|
* this right away.
|
||||||
|
* @param lines the lines to read
|
||||||
|
* @param ignoreErrors try to ignore errors and keep going
|
||||||
|
* @param inverted whether it should return the inverted one
|
||||||
|
* @return the {@link Mapper}, inverted depending on the flag
|
||||||
|
* @throws MalformedMappingsException if an error is encountered and ignoreErrors is false
|
||||||
|
*/
|
||||||
|
protected Mapper buildMapper(List<String> lines, boolean ignoreErrors, boolean inverted) throws MalformedMappingsException {
|
||||||
|
Mapper mapper = new Mapper();
|
||||||
|
Mapper invertedMapper = new Mapper();
|
||||||
for(int i = 0; i < lines.size(); i++) {
|
for(int i = 0; i < lines.size(); i++) {
|
||||||
String[] tokens = lines.get(i).trim().split(" ");
|
String[] tokens = lines.get(i).trim().split(" ");
|
||||||
switch(tokens[0]) {
|
switch(tokens[0]) {
|
||||||
case "CL:":
|
case "CL:":
|
||||||
if(tokens.length != 3)
|
if(tokens.length != 3)
|
||||||
break;
|
break;
|
||||||
this.registerClass(tokens[1], tokens[2]);
|
this.registerClass(mapper, invertedMapper, tokens[1], tokens[2]);
|
||||||
continue;
|
continue;
|
||||||
case "MD:":
|
case "MD:":
|
||||||
case "FD:":
|
case "FD:":
|
||||||
if(this.processMemberTokens(tokens))
|
if(this.processMemberTokens(mapper, invertedMapper, tokens))
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!ignoreErrors)
|
if(!ignoreErrors)
|
||||||
throw new MalformedMappingsException(i, "wrong number of space-separated tokens");
|
throw new MalformedMappingsException(i, "wrong number of space-separated tokens");
|
||||||
}
|
}
|
||||||
|
return inverted ? invertedMapper : mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a line, broken up into tokens.
|
* Processes a line, broken up into tokens.
|
||||||
|
* @param mapper the {@link Mapper} with normal mappings
|
||||||
|
* @param invertedMapper the {@link Mapper} with inverted mappings
|
||||||
* @param tokens the tokens
|
* @param tokens the tokens
|
||||||
* @return whether it was a valid mapping
|
* @return whether it was a valid mapping
|
||||||
*/
|
*/
|
||||||
private boolean processMemberTokens(String[] tokens) {
|
private boolean processMemberTokens(Mapper mapper, Mapper invertedMapper, String[] tokens) {
|
||||||
boolean field;
|
boolean field;
|
||||||
if(tokens[0].equals("MD:")) {
|
if(tokens[0].equals("MD:")) {
|
||||||
if(tokens.length != 5)
|
if(tokens.length != 5)
|
||||||
|
@ -78,25 +82,29 @@ public class SRGMapper extends AbstractMapper {
|
||||||
split = tokens[obfPosition].split("/");
|
split = tokens[obfPosition].split("/");
|
||||||
String memberNameObf = split[split.length - 1];
|
String memberNameObf = split[split.length - 1];
|
||||||
String parentObf = tokens[obfPosition].substring(0, tokens[obfPosition].length() - split[split.length - 1].length() - 1);
|
String parentObf = tokens[obfPosition].substring(0, tokens[obfPosition].length() - split[split.length - 1].length() - 1);
|
||||||
if(field) this.registerMember(parent, parentObf, memberName, memberNameObf, null, null);
|
this.registerMember(mapper, invertedMapper, parent, parentObf, memberName, memberNameObf,
|
||||||
else this.registerMember(parent, parentObf, memberName, memberNameObf, tokens[2], tokens[4]);
|
field ? null : tokens[2], field ? null : tokens[4]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a class in the mapper, if it isn't already.
|
* Registers a class in the mapper, if it isn't already.
|
||||||
|
* @param mapper the {@link Mapper} with normal mappings
|
||||||
|
* @param invertedMapper the {@link Mapper} with inverted mappings
|
||||||
* @param name the name
|
* @param name the name
|
||||||
* @param nameMapped the mapped name
|
* @param nameMapped the mapped name
|
||||||
*/
|
*/
|
||||||
private void registerClass(String name, String nameMapped) {
|
private void registerClass(Mapper mapper, Mapper invertedMapper, String name, String nameMapped) {
|
||||||
if(this.mappings.containsKey(name))
|
if(mapper.getRawMappings().containsKey(name))
|
||||||
return;
|
return;
|
||||||
this.mappings.put(name, new ClassData(name, nameMapped));
|
mapper.getRawMappings().put(name, new ClassData(name, nameMapped));
|
||||||
this.mappingsInverted.put(nameMapped, new ClassData(nameMapped, name));
|
invertedMapper.getRawMappings().put(nameMapped, new ClassData(nameMapped, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a class member. The descriptors should be null for fields.
|
* Registers a class member. The descriptors should be null for fields.
|
||||||
|
* @param mapper the {@link Mapper} with normal mappings
|
||||||
|
* @param invertedMapper the {@link Mapper} with inverted mappings
|
||||||
* @param parent the parent's plain internal name
|
* @param parent the parent's plain internal name
|
||||||
* @param parentMapped the parent's mapped internal name
|
* @param parentMapped the parent's mapped internal name
|
||||||
* @param name the member's plain name
|
* @param name the member's plain name
|
||||||
|
@ -104,11 +112,12 @@ public class SRGMapper extends AbstractMapper {
|
||||||
* @param descriptor the member's plain descriptor, may be null
|
* @param descriptor the member's plain descriptor, may be null
|
||||||
* @param descriptorMapped the member's mapped descriptor, may be null
|
* @param descriptorMapped the member's mapped descriptor, may be null
|
||||||
*/
|
*/
|
||||||
private void registerMember(String parent, String parentMapped, String name, String nameMapped,
|
private void registerMember(Mapper mapper, Mapper invertedMapper, String parent,
|
||||||
|
String parentMapped, String name, String nameMapped,
|
||||||
String descriptor, String descriptorMapped) {
|
String descriptor, String descriptorMapped) {
|
||||||
this.registerClass(parent, parentMapped);
|
this.registerClass(mapper, invertedMapper, parent, parentMapped);
|
||||||
ClassData data = this.mappings.get(parent);
|
ClassData data = mapper.getClassData(parent);
|
||||||
ClassData dataReverse = this.mappings.get(data.nameMapped);
|
ClassData dataReverse = invertedMapper.getClassData(data.nameMapped);
|
||||||
if(descriptor == null || descriptorMapped == null) {
|
if(descriptor == null || descriptorMapped == null) {
|
||||||
//field
|
//field
|
||||||
data.addField(name, nameMapped);
|
data.addField(name, nameMapped);
|
||||||
|
@ -121,15 +130,12 @@ public class SRGMapper extends AbstractMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IMapper getInverted() {
|
public Mapper getMapper(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
||||||
SRGMapper inverted = new SRGMapper();
|
return this.buildMapper(lines, ignoreErrors, false);
|
||||||
inverted.mappings.putAll(this.mappingsInverted);
|
|
||||||
inverted.mappingsInverted.putAll(this.mappings); //in case some weirdo calls getInverted() twice
|
|
||||||
return inverted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractMapper newInstance() { //not really used but whatever
|
public Mapper getInvertedMapper(List<String> lines, boolean ignoreErrors) {
|
||||||
return new SRGMapper();
|
return this.buildMapper(lines, ignoreErrors, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,20 +2,20 @@ package ftbsc.lll.mapper.impl;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import ftbsc.lll.exceptions.MalformedMappingsException;
|
import ftbsc.lll.exceptions.MalformedMappingsException;
|
||||||
import ftbsc.lll.mapper.AbstractMapper;
|
import ftbsc.lll.mapper.IMappingFormat;
|
||||||
import ftbsc.lll.mapper.IMapper;
|
import ftbsc.lll.mapper.tools.Mapper;
|
||||||
import ftbsc.lll.mapper.tools.data.ClassData;
|
import ftbsc.lll.mapper.tools.data.ClassData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link IMapper} capable of parsing TSRG (an intermediary
|
* A {@link IMappingFormat} capable of parsing TSRG (an intermediary
|
||||||
* format used by Forge) files.
|
* format used by Forge) files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@AutoService(IMapper.class)
|
@AutoService(IMappingFormat.class)
|
||||||
public class TSRGMapper extends AbstractMapper {
|
public class TSRGMapper implements IMappingFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean claim(List<String> lines) {
|
public boolean claim(List<String> lines) {
|
||||||
|
@ -24,7 +24,8 @@ public class TSRGMapper extends AbstractMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void populate(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
public Mapper getMapper(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
||||||
|
Mapper result = new Mapper();
|
||||||
String currentClass = "";
|
String currentClass = "";
|
||||||
for(int i = 1; i < lines.size(); i++) { //start from 1 to skip header
|
for(int i = 1; i < lines.size(); i++) { //start from 1 to skip header
|
||||||
String currentLine = lines.get(i);
|
String currentLine = lines.get(i);
|
||||||
|
@ -32,22 +33,18 @@ public class TSRGMapper extends AbstractMapper {
|
||||||
String[] tokens = currentLine.trim().split(" ");
|
String[] tokens = currentLine.trim().split(" ");
|
||||||
if(isMember) {
|
if(isMember) {
|
||||||
if(tokens.length == 2) //field
|
if(tokens.length == 2) //field
|
||||||
this.mappings.get(currentClass).addField(tokens[0], tokens[1]);
|
result.getClassData(currentClass).addField(tokens[0], tokens[1]);
|
||||||
else if(tokens.length == 3)//method
|
else if(tokens.length == 3)//method
|
||||||
this.mappings.get(currentClass).addMethod(tokens[0], tokens[2], tokens[1]); //add child
|
result.getClassData(currentClass).addMethod(tokens[0], tokens[2], tokens[1]); //add child
|
||||||
else if(!ignoreErrors) throw new MalformedMappingsException(i, "wrong number of space-separated tokens");
|
else if(!ignoreErrors) throw new MalformedMappingsException(i, "wrong number of space-separated tokens");
|
||||||
} else {
|
} else {
|
||||||
if(tokens.length == 2) {
|
if(tokens.length == 2) {
|
||||||
ClassData s = new ClassData(tokens[0], tokens[1]);
|
ClassData s = new ClassData(tokens[0], tokens[1]);
|
||||||
currentClass = s.name;
|
currentClass = s.name;
|
||||||
this.mappings.put(s.name, s);
|
result.getRawMappings().put(s.name, s);
|
||||||
} else if(!ignoreErrors) throw new MalformedMappingsException(i, "wrong number of space-separated tokens");
|
} else if(!ignoreErrors) throw new MalformedMappingsException(i, "wrong number of space-separated tokens");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return result;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractMapper newInstance() {
|
|
||||||
return new TSRGMapper();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,18 @@ package ftbsc.lll.mapper.impl;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import ftbsc.lll.exceptions.MalformedMappingsException;
|
import ftbsc.lll.exceptions.MalformedMappingsException;
|
||||||
import ftbsc.lll.mapper.AbstractMapper;
|
import ftbsc.lll.mapper.IMappingFormat;
|
||||||
import ftbsc.lll.mapper.IMapper;
|
import ftbsc.lll.mapper.tools.Mapper;
|
||||||
import ftbsc.lll.mapper.tools.data.ClassData;
|
import ftbsc.lll.mapper.tools.data.ClassData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link IMapper} capable of parsing TinyV2 mappings
|
* A {@link IMappingFormat} capable of parsing TinyV2 mappings.
|
||||||
*/
|
*/
|
||||||
@AutoService(IMapper.class)
|
@AutoService(IMappingFormat.class)
|
||||||
public class TinyV2Mapper extends AbstractMapper {
|
public class TinyV2Mapper implements IMappingFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean claim(List<String> lines) {
|
public boolean claim(List<String> lines) {
|
||||||
|
@ -22,7 +22,8 @@ public class TinyV2Mapper extends AbstractMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void populate(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
public Mapper getMapper(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
|
||||||
|
Mapper result = new Mapper();
|
||||||
String currentClass = "";
|
String currentClass = "";
|
||||||
for(int i = 1; i < lines.size(); i++) {
|
for(int i = 1; i < lines.size(); i++) {
|
||||||
String currentLine = lines.get(i);
|
String currentLine = lines.get(i);
|
||||||
|
@ -32,7 +33,7 @@ public class TinyV2Mapper extends AbstractMapper {
|
||||||
case 0: //classes
|
case 0: //classes
|
||||||
if(tokens.length == 3) {
|
if(tokens.length == 3) {
|
||||||
if(tokens[0].charAt(0) == 'c') {
|
if(tokens[0].charAt(0) == 'c') {
|
||||||
this.mappings.put(tokens[1], new ClassData(tokens[1], tokens[2]));
|
result.getRawMappings().put(tokens[1], new ClassData(tokens[1], tokens[2]));
|
||||||
currentClass = tokens[1];
|
currentClass = tokens[1];
|
||||||
} else if(!ignoreErrors)
|
} else if(!ignoreErrors)
|
||||||
throw new MalformedMappingsException(i, "root-level element must be class");
|
throw new MalformedMappingsException(i, "root-level element must be class");
|
||||||
|
@ -48,12 +49,12 @@ public class TinyV2Mapper extends AbstractMapper {
|
||||||
case 'm': //methods
|
case 'm': //methods
|
||||||
if(tokens.length == 4)
|
if(tokens.length == 4)
|
||||||
break;
|
break;
|
||||||
this.mappings.get(currentClass).addMethod(tokens[2], tokens[3], tokens[1]);
|
result.getClassData(currentClass).addMethod(tokens[2], tokens[3], tokens[1]);
|
||||||
continue;
|
continue;
|
||||||
case 'f': //fields
|
case 'f': //fields
|
||||||
if(tokens.length == 4)
|
if(tokens.length == 4)
|
||||||
break;
|
break;
|
||||||
this.mappings.get(currentClass).addField(tokens[2], tokens[3], tokens[1]);
|
result.getClassData(currentClass).addField(tokens[2], tokens[3], tokens[1]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -61,12 +62,8 @@ public class TinyV2Mapper extends AbstractMapper {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!ignoreErrors)
|
if(!ignoreErrors)
|
||||||
throw new MalformedMappingsException(i, "wrong number of space-separated tokens");
|
throw new MalformedMappingsException(i, "wrong number of tab-separated tokens");
|
||||||
}
|
}
|
||||||
}
|
return result;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractMapper newInstance() {
|
|
||||||
return new TinyV2Mapper();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
78
src/main/java/ftbsc/lll/mapper/tools/Mapper.java
Normal file
78
src/main/java/ftbsc/lll/mapper/tools/Mapper.java
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package ftbsc.lll.mapper.tools;
|
||||||
|
|
||||||
|
import ftbsc.lll.exceptions.MappingNotFoundException;
|
||||||
|
import ftbsc.lll.mapper.tools.data.ClassData;
|
||||||
|
import ftbsc.lll.mapper.tools.data.FieldData;
|
||||||
|
import ftbsc.lll.mapper.tools.data.MethodData;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object containing parsed mapping data, which can
|
||||||
|
* apply a conversion as requested.
|
||||||
|
*/
|
||||||
|
public class Mapper {
|
||||||
|
/**
|
||||||
|
* A {@link Map} tying each plain class name to its class data.
|
||||||
|
*/
|
||||||
|
protected final Map<String, ClassData> mappings = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link ClassData} given the plain name.
|
||||||
|
* @param name the plain internal name of the desired class
|
||||||
|
* @return the mapped name of the class
|
||||||
|
* @throws MappingNotFoundException if no mapping is found
|
||||||
|
*/
|
||||||
|
public ClassData getClassData(String name) throws MappingNotFoundException {
|
||||||
|
ClassData data = this.mappings.get(name.replace('.', '/'));
|
||||||
|
if(data == null)
|
||||||
|
throw new MappingNotFoundException("class", name);
|
||||||
|
else return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mapped name of a method
|
||||||
|
* @param parent the plain internal name of the parent class
|
||||||
|
* @param name the plain method name
|
||||||
|
* @param descriptor the descriptor of the method
|
||||||
|
* @return the mapped name of the given member
|
||||||
|
* @throws MappingNotFoundException if no mapping is found
|
||||||
|
*/
|
||||||
|
public MethodData getMethodData(String parent, String name, String descriptor) throws MappingNotFoundException {
|
||||||
|
return this.getClassData(parent).mapMethod(name, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mapped name of a field.
|
||||||
|
* @param parent the plain internal name of the parent class
|
||||||
|
* @param name the field's plain name
|
||||||
|
* @return the mapped name of the requested field
|
||||||
|
* @throws MappingNotFoundException if no mapping is found
|
||||||
|
*/
|
||||||
|
public FieldData getFieldData(String parent, String name) throws MappingNotFoundException {
|
||||||
|
return this.getClassData(parent).mapField(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the "raw mappings".
|
||||||
|
* @return a {@link Map} tying each {@link ClassData} to the class' plain name
|
||||||
|
*/
|
||||||
|
public Map<String, ClassData> getRawMappings() {
|
||||||
|
return this.mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a new {@link Mapper} that functions in reverse to this one (i.e. one that
|
||||||
|
* considers as "mapped" what this one considers plain, and vice versa).
|
||||||
|
* @return the inverted mapper
|
||||||
|
*/
|
||||||
|
public Mapper getInverted() {
|
||||||
|
Mapper inverted = new Mapper();
|
||||||
|
this.mappings.forEach((name, data) -> {
|
||||||
|
ClassData reverse = data.generateReverseMappings(this);
|
||||||
|
inverted.mappings.put(data.nameMapped, reverse);
|
||||||
|
});
|
||||||
|
return inverted;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package ftbsc.lll.mapper.tools;
|
package ftbsc.lll.mapper.tools;
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.MappingNotFoundException;
|
import ftbsc.lll.exceptions.MappingNotFoundException;
|
||||||
import ftbsc.lll.mapper.IMapper;
|
|
||||||
import ftbsc.lll.tools.DescriptorBuilder;
|
import ftbsc.lll.tools.DescriptorBuilder;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
@ -14,11 +13,11 @@ public class MappingUtils {
|
||||||
/**
|
/**
|
||||||
* Maps a method descriptor, replacing its class references with their mapped counterparts.
|
* Maps a method descriptor, replacing its class references with their mapped counterparts.
|
||||||
* @param descriptor a {@link String} containing the descriptor
|
* @param descriptor a {@link String} containing the descriptor
|
||||||
* @param mapper the {@link IMapper} to use for the process
|
* @param mapper the {@link Mapper} to use for the process
|
||||||
* @param reverse if true it uses the inverted mapper rather than the normal one
|
* @param reverse if true it uses the inverted mapper rather than the normal one
|
||||||
* @return the mapped descriptor
|
* @return the mapped descriptor
|
||||||
*/
|
*/
|
||||||
public static String mapMethodDescriptor(String descriptor, IMapper mapper, boolean reverse) {
|
public static String mapMethodDescriptor(String descriptor, Mapper mapper, boolean reverse) {
|
||||||
Type method = Type.getMethodType(descriptor);
|
Type method = Type.getMethodType(descriptor);
|
||||||
Type[] arguments = method.getArgumentTypes();
|
Type[] arguments = method.getArgumentTypes();
|
||||||
Type returnType = method.getReturnType();
|
Type returnType = method.getReturnType();
|
||||||
|
@ -31,13 +30,13 @@ public class MappingUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a {@link Type} and a valid {@link IMapper} it returns its mapped counterpart.
|
* Given a {@link Type} and a valid {@link Mapper} it returns its mapped counterpart.
|
||||||
* @param type the type in question
|
* @param type the type in question
|
||||||
* @param mapper the {@link IMapper} to use for the process
|
* @param mapper the {@link Mapper} to use for the process
|
||||||
* @param reverse if true it uses the inverted mapper rather than the normal one
|
* @param reverse if true it uses the inverted mapper rather than the normal one
|
||||||
* @return the mapped type
|
* @return the mapped type
|
||||||
*/
|
*/
|
||||||
public static Type mapType(Type type, IMapper mapper, boolean reverse) {
|
public static Type mapType(Type type, Mapper mapper, boolean reverse) {
|
||||||
//unwrap arrays
|
//unwrap arrays
|
||||||
Type unwrapped = type;
|
Type unwrapped = type;
|
||||||
int arrayLevel = 0;
|
int arrayLevel = 0;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package ftbsc.lll.mapper.tools.data;
|
package ftbsc.lll.mapper.tools.data;
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.MappingNotFoundException;
|
import ftbsc.lll.exceptions.MappingNotFoundException;
|
||||||
import ftbsc.lll.mapper.IMapper;
|
import ftbsc.lll.mapper.tools.Mapper;
|
||||||
import ftbsc.lll.mapper.tools.MappingUtils;
|
import ftbsc.lll.mapper.tools.MappingUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -85,7 +85,7 @@ public class ClassData {
|
||||||
* @param mapper the mapper that generated this data
|
* @param mapper the mapper that generated this data
|
||||||
* @return a ClassData representing the inverted mappings
|
* @return a ClassData representing the inverted mappings
|
||||||
*/
|
*/
|
||||||
public ClassData generateReverseMappings(IMapper mapper) {
|
public ClassData generateReverseMappings(Mapper mapper) {
|
||||||
ClassData reverse = new ClassData(this.nameMapped, this.name);
|
ClassData reverse = new ClassData(this.nameMapped, this.name);
|
||||||
this.methods.forEach((signature, data) -> reverse.addMethod(nameMapped, signature.name,
|
this.methods.forEach((signature, data) -> reverse.addMethod(nameMapped, signature.name,
|
||||||
MappingUtils.mapMethodDescriptor(signature.descriptor, mapper, false)));
|
MappingUtils.mapMethodDescriptor(signature.descriptor, mapper, false)));
|
||||||
|
|
Loading…
Reference in a new issue