Skip to content

Commit

Permalink
Nested class and mapping saving bug fixes
Browse files Browse the repository at this point in the history
 - Fixed bugs related to nested classes
 - Fixed issue with moving classes twice
  • Loading branch information
Runemoro committed Dec 21, 2018
1 parent d615b69 commit d65e9d0
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 65 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group 'org.dimdev'
version '1.0.2'
version '1.0.3'

sourceCompatibility = 1.8

Expand Down
6 changes: 2 additions & 4 deletions src/main/java/org/dimdev/knit/MappingsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
import com.intellij.openapi.ui.Messages;
import cuchaz.enigma.mapping.Mappings;
import cuchaz.enigma.mapping.MappingsEnigmaReader;
import cuchaz.enigma.mapping.MappingsEnigmaWriter;
import cuchaz.enigma.throwables.MappingParseException;

import java.io.File;
import java.io.IOException;

public class MappingsService {
private final MappingsEnigmaReader mappingsReader = new MappingsEnigmaReader();
private final MappingsEnigmaWriter mappingsWriter = new MappingsEnigmaWriter();
private File mappingDirectory = null;
private Mappings mappings = null;

Expand All @@ -24,7 +22,7 @@ public void loadMappings(File mappingDirectory) {
mappings = new Mappings();

try {
mappingsReader.readDirectory(mappings, mappingDirectory);
mappings = mappingsReader.read(mappingDirectory);
} catch (MappingParseException e) {
Messages.showErrorDialog("Exception occured while parsing mappings: " + e, "Mapping Parse Error");
} catch (IOException e) {
Expand All @@ -38,7 +36,7 @@ public void saveMappings() {
}

try {
mappingsWriter.writeAsDirectory(mappingDirectory, mappings);
mappings.saveEnigmaMappings(mappingDirectory, true);
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
156 changes: 96 additions & 60 deletions src/main/java/org/dimdev/knit/RenameHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import cuchaz.enigma.mapping.*;
import cuchaz.enigma.throwables.MappingConflict;

import java.util.function.Supplier;

public class RenameHandler {
public static final String NO_PACKAGE_PREFIX = "nopackage/";
public static final int MAX_OBFUSCATED_NAME_LENGTH = 3;
private final MappingsService mappingsService = ServiceManager.getService(MappingsService.class);

public void handleRename(String oldName, PsiElement element) {
Expand All @@ -22,7 +23,13 @@ public void handleRename(String oldName, PsiElement element) {

ClassMapping mapping = getOrCreateClassMapping(oldName);
if (mapping != null) {
mappingsService.getMappings().setClassDeobfName(mapping, getClassName(clazz));
int dollarSignIndex = oldName.indexOf('$');
if (dollarSignIndex == -1) {
mappingsService.getMappings().setClassDeobfName(mapping, getClassName(clazz));
} else {
ClassMapping parent = getOrCreateClassMapping(oldName.substring(0, dollarSignIndex));
parent.setInnerClassName(mapping.getObfEntry(), clazz.getName());
}
}
}

Expand Down Expand Up @@ -73,23 +80,40 @@ public void handleRename(String oldName, PsiElement element) {
}

private ClassMapping getOrCreateClassMapping(String className) {
// Try getting deobfuscated class mapping
ClassMapping mapping = mappingsService.getMappings().getClassByDeobf(className);

// If that doesn't work, try getting obfuscated class mapping
if (mapping == null) {
mapping = mappingsService.getMappings().getClassByObf(className);
}

// If that doesn't work either, create a new class mapping
if (mapping == null && className.length() <= MAX_OBFUSCATED_NAME_LENGTH) {
try {
mapping = new ClassMapping(className);
mappingsService.getMappings().addClassMapping(mapping);
} catch (MappingConflict e) {
throw new IllegalStateException("Both getClassByDeobf and getClassByObf returned null yet addClassMapping " +
"threw a MappingConflict exception", e);
}
String[] parts = className.split("\\$");

// Get or create root mapping
ClassMapping mapping = coalesce(
() -> mappingsService.getMappings().getClassByDeobf(parts[0]),
() -> mappingsService.getMappings().getClassByObf(parts[0]),
() -> {
try {
ClassMapping newMapping = new ClassMapping(className);
mappingsService.getMappings().addClassMapping(newMapping);
return newMapping;
} catch (MappingConflict e) {
throw new IllegalStateException(e);
}
}
);

// Get or create subclass mappings
for (int i = 1; i < parts.length && mapping != null; i++) {
ClassMapping mapping_ = mapping;
int i_ = i;
mapping = coalesce(
() -> mapping_.getInnerClassByDeobf(parts[i_]),
() -> mapping_.getInnerClassByObfSimple(parts[i_]),
() -> {
try {
ClassMapping newMapping = new ClassMapping(className);
mapping_.addInnerClassMapping(newMapping);
return newMapping;
} catch (MappingConflict e) {
throw new IllegalStateException(e);
}
}
);
}

return mapping;
Expand All @@ -106,22 +130,16 @@ private MethodMapping getOrCreateMethodMapping(PsiMethod method, String actualNa
return null;
}

// Try getting deobfuscated method mapping
MethodDescriptor descriptor = obfuscateDescriptor(new MethodDescriptor(getDescriptor(method)));
MethodMapping mapping = classMapping.getMethodByDeobf(actualName, descriptor);

// If that doesn't work, try getting obfuscated method mapping
if (mapping == null) {
mapping = classMapping.getMethodByObf(actualName, descriptor);
}

// If that doesn't work either, create a new method mapping
if (mapping == null && actualName.length() <= MAX_OBFUSCATED_NAME_LENGTH) {
mapping = new MethodMapping(actualName, descriptor);
classMapping.addMethodMapping(mapping);
}

return mapping;
MethodDescriptor descriptor = new MethodDescriptor(getDescriptor(method)).remap(this::obfuscateClassName);
String actualName_ = actualName;
return coalesce(
() -> classMapping.getMethodByDeobf(actualName_, descriptor),
() -> classMapping.getMethodByObf(actualName_, descriptor),
() -> {
MethodMapping newMapping = new MethodMapping(actualName_, descriptor);
classMapping.addMethodMapping(newMapping);
return newMapping;
});
}

private FieldMapping getOrCreateFieldMapping(PsiField field, String actualName) {
Expand All @@ -131,36 +149,43 @@ private FieldMapping getOrCreateFieldMapping(PsiField field, String actualName)
return null;
}

// Try getting deobfuscated method mapping
TypeDescriptor descriptor = obfuscateDescriptor(new TypeDescriptor(getDescriptor(field.getType())));
FieldMapping mapping = classMapping.getFieldByDeobf(actualName, descriptor);
TypeDescriptor descriptor = new TypeDescriptor(getDescriptor(field.getType())).remap(this::obfuscateClassName);
return coalesce(
() -> classMapping.getFieldByDeobf(actualName, descriptor),
() -> classMapping.getFieldByObf(actualName, descriptor),
() -> {
FieldMapping newMapping = new FieldMapping(actualName, descriptor, actualName, Mappings.EntryModifier.UNCHANGED);
classMapping.addFieldMapping(newMapping);
return newMapping;
});
}

// If that doesn't work, try getting obfuscated method mapping
if (mapping == null) {
mapping = classMapping.getFieldByObf(actualName, descriptor);
}
private String obfuscateClassName(String className) {
StringBuilder obfuscatedName = new StringBuilder();

// If that doesn't work either, create a new field mapping
if (mapping == null && actualName.length() <= MAX_OBFUSCATED_NAME_LENGTH) {
mapping = new FieldMapping(actualName, descriptor, actualName, Mappings.EntryModifier.UNCHANGED);
classMapping.addFieldMapping(mapping);
}
String[] parts = className.split("\\$");

return mapping;
}
// Append root class
ClassMapping mapping = coalesce(
() -> mappingsService.getMappings().getClassByDeobf(parts[0]),
() -> mappingsService.getMappings().getClassByObf(parts[0])
);
obfuscatedName.append(mapping != null ? mapping.getObfFullName() : parts[0]);

public MethodDescriptor obfuscateDescriptor(MethodDescriptor descriptor) {
return descriptor.remap(className -> {
ClassMapping mapping = mappingsService.getMappings().getClassByDeobf(className);
return mapping != null ? mapping.getObfFullName() : className;
});
}
// Append inner classes
for (int i = 1; i < parts.length; i++) {
if (mapping != null) {
ClassMapping mapping_ = mapping;
int i_ = i;
mapping = coalesce(
() -> mapping_.getInnerClassByDeobf(parts[i_]),
() -> mapping_.getInnerClassByObfSimple(parts[i_])
);
}
obfuscatedName.append("$").append(mapping != null ? mapping.getObfSimpleName() : parts[i]);
}

public TypeDescriptor obfuscateDescriptor(TypeDescriptor descriptor) {
return descriptor.remap(clazzName -> {
ClassMapping mapping = mappingsService.getMappings().getClassByDeobf(clazzName);
return mapping != null ? mapping.getObfFullName() : clazzName;
});
return obfuscatedName.toString();
}

public static String getClassName(PsiClass element) {
Expand Down Expand Up @@ -194,4 +219,15 @@ public static String getDescriptor(PsiType type) {
public static String getDescriptor(PsiMethod method) {
return JVMNameUtil.getJVMSignature(method).getDisplayName(null);
}

@SafeVarargs
private static <T> T coalesce(Supplier<T>... suppliers) {
for (Supplier<T> supplier : suppliers) {
T item = supplier.get();
if (item != null) {
return item;
}
}
return null;
}
}
5 changes: 5 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@

<change-notes>
<![CDATA[
<b>1.0.3</b>
<ul>
<li>Fixed bugs related to nested classes</li>
<li>Fixed issue with moving classes twice</li>
</ul>
<b>1.0.2</b>
<ul>
<li>Fixed class mappings not being created</li>
Expand Down

0 comments on commit d65e9d0

Please sign in to comment.