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

package renamer improvements #235

Open
wants to merge 4 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
11 changes: 9 additions & 2 deletions enigma-swing/src/main/java/org/quiltmc/enigma/gui/Gui.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ public class Gui {
public final JFileChooser exportJarFileChooser;
public final SearchDialog searchDialog;

public Gui(EnigmaProfile profile, Set<EditableType> editableTypes, boolean visible) {
private final boolean testEnvironment;

public Gui(EnigmaProfile profile, Set<EditableType> editableTypes, boolean testEnvironment) {
this.dockerManager = new DockerManager(this);
this.mainWindow = new MainWindow(this, Enigma.NAME);
this.centerPanel = new JPanel(new BorderLayout());
Expand All @@ -126,14 +128,15 @@ public Gui(EnigmaProfile profile, Set<EditableType> editableTypes, boolean visib
this.connectionStatusLabel = new JLabel();
this.notificationManager = new NotificationManager(this);
this.searchDialog = new SearchDialog(this);
this.testEnvironment = testEnvironment;

this.showsProgressBars = true;

this.setupUi();

LanguageUtil.addListener(this::retranslateUi);

this.mainWindow.setVisible(visible);
this.mainWindow.setVisible(!testEnvironment);
}

private void setupDockers() {
Expand Down Expand Up @@ -273,6 +276,10 @@ public Set<EditableType> getEditableTypes() {
return this.editableTypes;
}

public boolean isTestEnvironment() {
return this.testEnvironment;
}

public void addCrash(Throwable t) {
this.crashHistory.add(t);
this.menuBar.prepareCrashHistoryMenu();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public static void main(String[] args) throws IOException {

KeyBinds.loadConfig();

Gui gui = new Gui(parsedProfile, editables, true);
Gui gui = new Gui(parsedProfile, editables, false);
GuiController controller = gui.getController();

if (options.has("hide-progress-bars")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@ private void onRenamePackage(PackageRenamer.Mode mode) {
}
}

String input = JOptionPane.showInputDialog(this.gui.getFrame(), I18n.translate("popup_menu.class_selector.package_rename.title"), pathString.toString());
String title = switch (mode) {
case MOVE -> I18n.translateFormatted("popup_menu.class_selector.package_rename.move_title", pathString.toString());
case REFACTOR -> I18n.translateFormatted("popup_menu.class_selector.package_rename.rename_title", pathString.toString());
};

String input = JOptionPane.showInputDialog(this.gui.getFrame(), title, pathString.toString());
if (input != null) {
this.createPackageRenamer(mode).renamePackage(pathString.toString(), input);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@
import org.quiltmc.enigma.util.validation.Message;
import org.quiltmc.enigma.util.validation.ValidationContext;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.tree.TreeNode;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -143,7 +150,7 @@ public CompletableFuture<Void> renamePackage(String path, String input) {
String[] oldPackageNames = path.split("/");
String[] newPackageNames = input.split("/");

Map<String, Runnable> renameStack = new HashMap<>();
Map<String, ClassRename> renameStack = new HashMap<>();

return ProgressDialog.runOffThread(this.gui, listener -> {
listener.init(1, I18n.translate("popup_menu.class_selector.package_rename.discovering"));
Expand All @@ -163,10 +170,20 @@ public CompletableFuture<Void> renamePackage(String path, String input) {
}
}

boolean confirmed = false;
int i = 0;
for (var entry : renameStack.entrySet()) {
if (!confirmed && !this.gui.isTestEnvironment()) {
int continueOperation = JOptionPane.showConfirmDialog(this.gui.getFrame(), buildConfirmationPanel(renameStack));
if (continueOperation != JOptionPane.YES_OPTION) {
return;
} else {
confirmed = true;
}
}

listener.step(i, I18n.translateFormatted("popup_menu.class_selector.package_rename.renaming_class", entry.getKey()));
entry.getValue().run();
entry.getValue().executeRename();
i++;
}

Expand All @@ -178,10 +195,54 @@ public CompletableFuture<Void> renamePackage(String path, String input) {
});
}

private void handleNode(int divergenceIndex, boolean rename, String[] oldPackageNames, String[] newPackageNames, Map<String, Runnable> renameStack, TreeNode node) {
private static JPanel buildConfirmationPanel(Map<String, ClassRename> renameStack) {
JPanel panel = new JPanel(new BorderLayout());
int truncationThreshold = 50;

var sampleRenameLines = collectSampleRenames(truncationThreshold, renameStack);
JTextArea text = new JTextArea(multilineify(false, sampleRenameLines));
text.setEditable(false);
JScrollPane sampleRenames = new JScrollPane(text);
sampleRenames.setPreferredSize(new Dimension(ScaleUtil.scale(400), ScaleUtil.scale(100)));

String changesString = I18n.translate("popup_menu.class_selector.package_rename.changes_to_apply") + (sampleRenameLines.length == truncationThreshold ? " (" + I18n.translate("popup_menu.class_selector.package_rename.truncated") + ")" : "");
panel.add(BorderLayout.NORTH, new JLabel(multilineify(true, I18n.translate("popup_menu.class_selector.package_rename.confirm_rename"), changesString)));
panel.add(sampleRenames, BorderLayout.CENTER);

return panel;
}

private static String multilineify(boolean html, String... lines) {
StringBuilder builder = new StringBuilder(html ? "<html>" : "");

for (int i = 0; i < lines.length; i++) {
builder.append(lines[i]).append(i == lines.length - 1 ? "" : (html ? "<br>" : "\n"));
}

return builder.append(html ? "</html>" : "").toString();
}

private static String[] collectSampleRenames(int truncationThreshold, Map<String, ClassRename> renameStack) {
int max = Math.min(renameStack.size(), truncationThreshold);
int index = 0;

String[] builder = new String[max];
for (Map.Entry<String, ClassRename> entry : renameStack.entrySet()) {
builder[index] = entry.getKey() + " -> " + entry.getValue().getNewName();
index++;

if (index >= max) {
return builder;
}
}

throw new RuntimeException("failed to collect sample renames!");
}

private void handleNode(int divergenceIndex, boolean rename, String[] oldPackageNames, String[] newPackageNames, Map<String, ClassRename> renameStack, TreeNode node) {
if (node instanceof ClassSelectorClassNode classNode && rename) {
String oldName = classNode.getDeobfEntry().getFullName();
int finalPackageIndex = divergenceIndex - 1;
int finalPackageIndex = divergenceIndex == 0 ? 0 : divergenceIndex - 1;

// skips all classes that do not match the exact package being renamed
if (this.mode == Mode.MOVE) {
Expand All @@ -190,59 +251,72 @@ private void handleNode(int divergenceIndex, boolean rename, String[] oldPackage
}
}

renameStack.put(oldName, () -> {
String[] split = oldName.split("/");
StringBuilder newPackages = new StringBuilder();

if (oldPackageNames.length <= newPackageNames.length) {
for (int i = finalPackageIndex; i < newPackageNames.length; i++) {
if (i >= 0) {
if (i < oldPackageNames.length && i < split.length && oldPackageNames[i].equals(split[i])) {
split[i] = newPackageNames[i];
} else {
newPackages.append("/").append(newPackageNames[i]);
renameStack.put(oldName, new ClassRename() {
private String cachedNewName = null;

@Override
public void executeRename() {
String newName = this.cachedNewName == null ? this.getNewName() : this.cachedNewName;

// ignore warnings, we don't want to bother the user with every individual package created
PackageRenamer.this.gui.getController().applyChange(new ValidationContext(PackageRenamer.this.gui.getNotificationManager(), false), EntryChange.modify(classNode.getObfEntry()).withDeobfName(newName), false);
}

@Override
public String getNewName() {
String[] split = oldName.split("/");
StringBuilder newPackages = new StringBuilder();

if (oldPackageNames.length <= newPackageNames.length) {
for (int i = finalPackageIndex; i < newPackageNames.length; i++) {
if (i >= 0) {
if (i < oldPackageNames.length && i < split.length && oldPackageNames[i].equals(split[i])) {
split[i] = newPackageNames[i];
} else {
newPackages.append("/").append(newPackageNames[i]);
}
}
}
}
} else {
for (int i = 0; i < oldPackageNames.length; i++) {
if (i > newPackageNames.length - 1 || !oldPackageNames[i].equals(newPackageNames[i])) {
StringBuilder string = new StringBuilder();
} else {
for (int i = 0; i < oldPackageNames.length; i++) {
if (i > newPackageNames.length - 1 || !oldPackageNames[i].equals(newPackageNames[i])) {
StringBuilder string = new StringBuilder();

// append preceding old package names
for (int j = 0; j <= i - 1; j++) {
appendSlash(string);
string.append(oldPackageNames[j]);
}
// append preceding old package names
for (int j = 0; j <= i - 1; j++) {
appendSlash(string);
string.append(oldPackageNames[j]);
}

// append new package names
for (int j = i; j < newPackageNames.length; j++) {
appendSlash(string);
string.append(newPackageNames[j]);
}
// append new package names
for (int j = i; j < newPackageNames.length; j++) {
appendSlash(string);
string.append(newPackageNames[j]);
}

// append the remaining old package names
for (int j = i - 1 + oldPackageNames.length; j < split.length - 1; j++) {
appendSlash(string);
string.append(split[j]);
}

// append the remaining old package names
for (int j = i - 1 + oldPackageNames.length; j < split.length - 1; j++) {
appendSlash(string);
string.append(split[j]);
string.append(classNode.getDeobfEntry().getSimpleName());
split = string.toString().split("/");
break;
}

appendSlash(string);
string.append(classNode.getDeobfEntry().getSimpleName());
split = string.toString().split("/");
break;
}
}
}

// append new packages to last package
if (!newPackages.toString().isBlank()) {
split[finalPackageIndex] = split[finalPackageIndex] + newPackages;
}
// append new packages to last package
if (!newPackages.toString().isBlank()) {
split[finalPackageIndex] = split[finalPackageIndex] + newPackages;
}

String newName = String.join("/", split);
// ignore warnings, we don't want to bother the user with every individual package created
this.gui.getController().applyChange(new ValidationContext(this.gui.getNotificationManager(), false), EntryChange.modify(classNode.getObfEntry()).withDeobfName(newName), false);
String newName = String.join("/", split);
this.cachedNewName = newName;
return newName;
}
});
} else if (node instanceof ClassSelectorPackageNode packageNode) {
String packageName = packageNode.getPackageName().substring(packageNode.getPackageName().lastIndexOf("/") + 1);
Expand All @@ -268,9 +342,9 @@ private void handleNode(int divergenceIndex, boolean rename, String[] oldPackage
}
}

if (packageName.equals(newPackageNames[index])) {
if (newPackageNames.length - 1 >= index && packageName.equals(newPackageNames[index])) {
this.handlePackage(index, false, oldPackageNames, newPackageNames, renameStack, packageNode);
} else if (packageName.equals(oldPackageNames[index])) {
} else if (oldPackageNames.length - 1 >= index && packageName.equals(oldPackageNames[index])) {
this.handlePackage(index, true, oldPackageNames, newPackageNames, renameStack, packageNode);
}
}
Expand All @@ -282,7 +356,7 @@ private static void appendSlash(StringBuilder string) {
}
}

private void handlePackage(int divergenceIndex, boolean rename, String[] oldPackageNames, String[] newPackageNames, Map<String, Runnable> renameStack, TreeNode node) {
private void handlePackage(int divergenceIndex, boolean rename, String[] oldPackageNames, String[] newPackageNames, Map<String, ClassRename> renameStack, TreeNode node) {
if (!rename) {
divergenceIndex++;
}
Expand All @@ -291,4 +365,10 @@ private void handlePackage(int divergenceIndex, boolean rename, String[] oldPack
this.handleNode(divergenceIndex, rename, oldPackageNames, newPackageNames, renameStack, node.getChildAt(j));
}
}

private interface ClassRename {
void executeRename();

String getNewName();
}
}
Loading
Loading