From 9bc6538ef4cb6cf5a0509c7b11bec880e2baf252 Mon Sep 17 00:00:00 2001 From: NebelNidas <48808497+NebelNidas@users.noreply.github.com> Date: Sun, 10 Mar 2024 19:49:58 +0100 Subject: [PATCH 1/2] Startup args (#25) * Add support for startup args * Add CLI args for mappings Support: - importing mappings - hiding unmapped classes on side A - not saving unmapped classes' matches Also move ProjectConfig instantiation to a Builder * Use better error message when plugin discovery fails * Fix oversight with method args and vars * Don't import side A mappings on side B * Use better error message when plugin discovery fails * Handle methods with inherited mapped names correctly * Fix NPEs --- src/main/java/matcher/Main.java | 4 +- src/main/java/matcher/Matcher.java | 11 +- src/main/java/matcher/PluginLoader.java | 57 +++-- src/main/java/matcher/config/Config.java | 25 +- .../java/matcher/config/ProjectConfig.java | 142 ++++++++++-- src/main/java/matcher/gui/Gui.java | 216 +++++++++++++++++- src/main/java/matcher/gui/IGuiComponent.java | 2 +- src/main/java/matcher/gui/MatchPaneDst.java | 2 +- src/main/java/matcher/gui/MatchPaneSrc.java | 36 ++- src/main/java/matcher/gui/menu/FileMenu.java | 48 +--- .../java/matcher/gui/menu/NewProjectPane.java | 22 +- src/main/java/matcher/gui/menu/ViewMenu.java | 1 + src/main/java/matcher/mapping/Mappings.java | 58 +---- src/main/java/matcher/serdes/MatchesIo.java | 33 ++- .../java/matcher/type/ClassEnvironment.java | 14 +- src/main/java/matcher/type/ClassInstance.java | 15 +- .../java/matcher/type/MethodInstance.java | 94 +++++++- .../java/matcher/type/ParentInstance.java | 5 + 18 files changed, 599 insertions(+), 186 deletions(-) create mode 100644 src/main/java/matcher/type/ParentInstance.java diff --git a/src/main/java/matcher/Main.java b/src/main/java/matcher/Main.java index e5cbf134..50614ddc 100644 --- a/src/main/java/matcher/Main.java +++ b/src/main/java/matcher/Main.java @@ -7,8 +7,8 @@ public class Main { public static void main(String[] args) { - Config.init(); - PluginLoader.run(); + Config.init(args); + PluginLoader.run(args); Application.launch(Gui.class, args); } } diff --git a/src/main/java/matcher/Matcher.java b/src/main/java/matcher/Matcher.java index 5c99baff..09136564 100644 --- a/src/main/java/matcher/Matcher.java +++ b/src/main/java/matcher/Matcher.java @@ -103,8 +103,15 @@ public void initFromMatches(List inputDirs, List classPathA = resolvePaths(inputDirs, cpFilesA); List classPathB = resolvePaths(inputDirs, cpFilesB); - ProjectConfig config = new ProjectConfig(pathsA, pathsB, classPathA, classPathB, sharedClassPath, false, - nonObfuscatedClassPatternA, nonObfuscatedClassPatternB, nonObfuscatedMemberPatternA, nonObfuscatedMemberPatternB); + ProjectConfig config = new ProjectConfig.Builder(pathsA, pathsB) + .classPathA(new ArrayList<>(classPathA)) + .classPathB(new ArrayList<>(classPathB)) + .sharedClassPath(new ArrayList<>(sharedClassPath)) + .nonObfuscatedClassPatternA(nonObfuscatedClassPatternA) + .nonObfuscatedClassPatternB(nonObfuscatedClassPatternB) + .nonObfuscatedMemberPatternA(nonObfuscatedMemberPatternA) + .nonObfuscatedMemberPatternB(nonObfuscatedMemberPatternB) + .build(); if (!config.isValid()) throw new IOException("invalid config"); Config.setProjectConfig(config); Config.saveAsLast(); diff --git a/src/main/java/matcher/PluginLoader.java b/src/main/java/matcher/PluginLoader.java index 1433d38d..8ca378a4 100644 --- a/src/main/java/matcher/PluginLoader.java +++ b/src/main/java/matcher/PluginLoader.java @@ -8,34 +8,57 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.ServiceLoader; import java.util.stream.Collectors; import java.util.stream.Stream; class PluginLoader { - public static void run() { - Path pluginFolder = Paths.get("plugins"); - URL[] urls = new URL[0]; - - if (Files.isDirectory(pluginFolder)) { - try (Stream stream = Files.list(pluginFolder)) { - urls = stream - .filter(p -> p.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".jar")) - .map(p -> { - try { - return p.toUri().toURL(); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - }) - .collect(Collectors.toList()).toArray(urls); + public static void run(String[] args) { + List pluginPaths = new ArrayList<>(); + pluginPaths.add(Paths.get("plugins")); + + for (int i = 0; i < args.length; i++) { + switch (args[i]) { + case "--additional-plugins": + while (i+1 < args.length && !args[i+1].startsWith("--")) { + pluginPaths.add(Path.of(args[++i])); + } + + break; + } + } + + List urls = new ArrayList<>(); + + for (Path path : pluginPaths) { + try { + if (Files.isDirectory(path)) { + Stream stream = Files.list(path); + urls.addAll(stream + .filter(p -> p.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".jar")) + .map(p -> { + try { + return p.toUri().toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + }) + .collect(Collectors.toList())); + stream.close(); + } else if (path.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".jar")) { + urls.add(path.toUri().toURL()); + } else { + System.err.println("No plugin(s) found at " + path.toFile().getCanonicalPath()); + } } catch (IOException e) { throw new UncheckedIOException(e); } } - URLClassLoader cl = new URLClassLoader(urls); + URLClassLoader cl = new URLClassLoader(urls.toArray(new URL[0])); ServiceLoader pluginLoader = ServiceLoader.load(Plugin.class, cl); diff --git a/src/main/java/matcher/config/Config.java b/src/main/java/matcher/config/Config.java index 1603c523..77d445d8 100644 --- a/src/main/java/matcher/config/Config.java +++ b/src/main/java/matcher/config/Config.java @@ -10,14 +10,14 @@ import java.util.prefs.Preferences; public class Config { - public static void init() { + public static void init(String[] args) { Preferences prefs = Preferences.userRoot(); // in ~/.java/.userPrefs try { if (prefs.nodeExists(userPrefFolder)) { prefs = prefs.node(userPrefFolder); - if (prefs.nodeExists(lastProjectSetupKey)) setProjectConfig(new ProjectConfig(prefs.node(lastProjectSetupKey))); + if (prefs.nodeExists(lastProjectSetupKey)) setProjectConfig(new ProjectConfig.Builder(prefs.node(lastProjectSetupKey)).build()); setInputDirs(loadList(prefs, lastInputDirsKey, Config::deserializePath)); setVerifyInputFiles(prefs.getBoolean(lastVerifyInputFilesKey, true)); setUidConfig(new UidConfig(prefs)); @@ -26,6 +26,22 @@ public static void init() { } catch (BackingStoreException e) { // ignored } + + for (int i = 0; i < args.length; i++) { + switch (args[i]) { + case "--theme": + String themeId = args[++i]; + Theme theme = Theme.getById(themeId); + + if (theme == null) { + System.err.println("Startup arg '--theme' couldn't be applied, as there exists no theme with ID " + themeId + "!"); + } else { + setTheme(theme); + } + + break; + } + } } private Config() { } @@ -78,11 +94,10 @@ public static boolean setUidConfig(UidConfig config) { public static void setTheme(Theme value) { if (value != null) { theme = value; - saveTheme(); } } - private static void saveTheme() { + public static void saveTheme() { Preferences root = Preferences.userRoot().node(userPrefFolder); try { @@ -140,7 +155,7 @@ static Path deserializePath(String path) { private static final String lastVerifyInputFilesKey = "last-verify-input-files"; private static final String themeKey = "theme"; - private static ProjectConfig projectConfig = new ProjectConfig(); + private static ProjectConfig projectConfig = ProjectConfig.EMPTY; private static final List inputDirs = new ArrayList<>(); private static boolean verifyInputFiles = true; private static UidConfig uidConfig = new UidConfig(); diff --git a/src/main/java/matcher/config/ProjectConfig.java b/src/main/java/matcher/config/ProjectConfig.java index dd09c022..11059c36 100644 --- a/src/main/java/matcher/config/ProjectConfig.java +++ b/src/main/java/matcher/config/ProjectConfig.java @@ -9,24 +9,109 @@ import java.util.regex.PatternSyntaxException; public class ProjectConfig { - public ProjectConfig() { - this(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), false, "", "", "", ""); - } + public static class Builder { + public Builder(List pathsA, List pathsB) { + this.pathsA = pathsA; + this.pathsB = pathsB; + } + + Builder(Preferences prefs) throws BackingStoreException { + pathsA = Config.loadList(prefs, pathsAKey, Config::deserializePath); + pathsB = Config.loadList(prefs, pathsBKey, Config::deserializePath); + classPathA = Config.loadList(prefs, classPathAKey, Config::deserializePath); + classPathB = Config.loadList(prefs, classPathBKey, Config::deserializePath); + sharedClassPath = Config.loadList(prefs, pathsSharedKey, Config::deserializePath); + inputsBeforeClassPath = prefs.getBoolean(inputsBeforeClassPathKey, false); + + String storedMappingsPathA = prefs.get(mappingsPathAKey, null); + String storedMappingsPathB = prefs.get(mappingsPathBKey, null); + mappingsPathA = storedMappingsPathA == null ? null : Path.of(storedMappingsPathA); + mappingsPathB = storedMappingsPathB == null ? null : Path.of(storedMappingsPathB); + saveUnmappedMatches = prefs.getBoolean(inputsBeforeClassPathKey, false); + + nonObfuscatedClassPatternA = prefs.get(nonObfuscatedClassPatternAKey, ""); + nonObfuscatedClassPatternB = prefs.get(nonObfuscatedClassPatternBKey, ""); + nonObfuscatedMemberPatternA = prefs.get(nonObfuscatedMemberPatternAKey, ""); + nonObfuscatedMemberPatternB = prefs.get(nonObfuscatedMemberPatternBKey, ""); + } + + public Builder classPathA(List classPathA) { + this.classPathA = classPathA; + return this; + } + + public Builder classPathB(List classPathB) { + this.classPathB = classPathB; + return this; + } - ProjectConfig(Preferences prefs) throws BackingStoreException { - this(Config.loadList(prefs, pathsAKey, Config::deserializePath), - Config.loadList(prefs, pathsBKey, Config::deserializePath), - Config.loadList(prefs, classPathAKey, Config::deserializePath), - Config.loadList(prefs, classPathBKey, Config::deserializePath), - Config.loadList(prefs, pathsSharedKey, Config::deserializePath), - prefs.getBoolean(inputsBeforeClassPathKey, false), - prefs.get(nonObfuscatedClassPatternAKey, ""), - prefs.get(nonObfuscatedClassPatternBKey, ""), - prefs.get(nonObfuscatedMemberPatternAKey, ""), - prefs.get(nonObfuscatedMemberPatternBKey, "")); + public Builder sharedClassPath(List sharedClassPath) { + this.sharedClassPath = sharedClassPath; + return this; + } + + public Builder inputsBeforeClassPath(boolean inputsBeforeClassPath) { + this.inputsBeforeClassPath = inputsBeforeClassPath; + return this; + } + + public Builder mappingsPathA(Path mappingsPathA) { + this.mappingsPathA = mappingsPathA; + return this; + } + + public Builder mappingsPathB(Path mappingsPathB) { + this.mappingsPathB = mappingsPathB; + return this; + } + + public Builder saveUnmappedMatches(boolean saveUnmappedMatches) { + this.saveUnmappedMatches = saveUnmappedMatches; + return this; + } + + public Builder nonObfuscatedClassPatternA(String nonObfuscatedClassPatternA) { + this.nonObfuscatedClassPatternA = nonObfuscatedClassPatternA; + return this; + } + + public Builder nonObfuscatedClassPatternB(String nonObfuscatedClassPatternB) { + this.nonObfuscatedClassPatternB = nonObfuscatedClassPatternB; + return this; + } + + public Builder nonObfuscatedMemberPatternA(String nonObfuscatedMemberPatternA) { + this.nonObfuscatedMemberPatternA = nonObfuscatedMemberPatternA; + return this; + } + + public Builder nonObfuscatedMemberPatternB(String nonObfuscatedMemberPatternB) { + this.nonObfuscatedMemberPatternB = nonObfuscatedMemberPatternB; + return this; + } + + public ProjectConfig build() { + return new ProjectConfig(pathsA, pathsB, classPathA, classPathB, sharedClassPath, inputsBeforeClassPath, mappingsPathA, mappingsPathB, saveUnmappedMatches, + nonObfuscatedClassPatternA, nonObfuscatedClassPatternB, nonObfuscatedMemberPatternA, nonObfuscatedMemberPatternB); + } + + protected final List pathsA; + protected final List pathsB; + protected List classPathA; + protected List classPathB; + protected List sharedClassPath; + protected boolean inputsBeforeClassPath; + protected Path mappingsPathA; + protected Path mappingsPathB; + protected boolean saveUnmappedMatches = true; + protected String nonObfuscatedClassPatternA; + protected String nonObfuscatedClassPatternB; + protected String nonObfuscatedMemberPatternA; + protected String nonObfuscatedMemberPatternB; } - public ProjectConfig(List pathsA, List pathsB, List classPathA, List classPathB, List sharedClassPath, boolean inputsBeforeClassPath, + private ProjectConfig(List pathsA, List pathsB, List classPathA, List classPathB, + List sharedClassPath, boolean inputsBeforeClassPath, Path mappingsPathA, Path mappingsPathB, boolean saveUnmappedMatches, String nonObfuscatedClassesPatternA, String nonObfuscatedClassesPatternB, String nonObfuscatedMemberPatternA, String nonObfuscatedMemberPatternB) { this.pathsA = pathsA; this.pathsB = pathsB; @@ -34,6 +119,9 @@ public ProjectConfig(List pathsA, List pathsB, List classPathA this.classPathB = classPathB; this.sharedClassPath = sharedClassPath; this.inputsBeforeClassPath = inputsBeforeClassPath; + this.mappingsPathA = mappingsPathA; + this.mappingsPathB = mappingsPathB; + this.saveUnmappedMatches = saveUnmappedMatches; this.nonObfuscatedClassPatternA = nonObfuscatedClassesPatternA; this.nonObfuscatedClassPatternB = nonObfuscatedClassesPatternB; this.nonObfuscatedMemberPatternA = nonObfuscatedMemberPatternA; @@ -64,6 +152,18 @@ public boolean hasInputsBeforeClassPath() { return inputsBeforeClassPath; } + public Path getMappingsPathA() { + return mappingsPathA; + } + + public Path getMappingsPathB() { + return mappingsPathB; + } + + public boolean isSaveUnmappedMatches() { + return saveUnmappedMatches; + } + public String getNonObfuscatedClassPatternA() { return nonObfuscatedClassPatternA; } @@ -117,18 +217,27 @@ void save(Preferences prefs) throws BackingStoreException { Config.saveList(prefs.node(classPathBKey), classPathB); Config.saveList(prefs.node(pathsSharedKey), sharedClassPath); prefs.putBoolean(inputsBeforeClassPathKey, inputsBeforeClassPath); + if (mappingsPathA != null) prefs.put(mappingsPathAKey, mappingsPathA.toString()); + if (mappingsPathB != null) prefs.put(mappingsPathBKey, mappingsPathB.toString()); + prefs.putBoolean(saveUnmappedMatchesKey, saveUnmappedMatches); prefs.put(nonObfuscatedClassPatternAKey, nonObfuscatedClassPatternA); prefs.put(nonObfuscatedClassPatternBKey, nonObfuscatedClassPatternB); prefs.put(nonObfuscatedMemberPatternAKey, nonObfuscatedMemberPatternA); prefs.put(nonObfuscatedMemberPatternBKey, nonObfuscatedMemberPatternB); } + public static final ProjectConfig EMPTY = new ProjectConfig(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), + false, null, null, true, "", "", "", ""); + private static final String pathsAKey = "paths-a"; private static final String pathsBKey = "paths-b"; private static final String classPathAKey = "class-path-a"; private static final String classPathBKey = "class-path-b"; private static final String pathsSharedKey = "paths-shared"; private static final String inputsBeforeClassPathKey = "inputs-before-classpath"; + private static final String mappingsPathAKey = "mappings-path-a"; + private static final String mappingsPathBKey = "mappings-path-b"; + private static final String saveUnmappedMatchesKey = "save-unmapped-matches"; private static final String nonObfuscatedClassPatternAKey = "non-obfuscated-class-pattern-a"; private static final String nonObfuscatedClassPatternBKey = "non-obfuscated-class-pattern-b"; private static final String nonObfuscatedMemberPatternAKey = "non-obfuscated-member-pattern-a"; @@ -139,6 +248,9 @@ void save(Preferences prefs) throws BackingStoreException { private final List classPathA; private final List classPathB; private final List sharedClassPath; + private final Path mappingsPathA; + private final Path mappingsPathB; + private final boolean saveUnmappedMatches; private final boolean inputsBeforeClassPath; private final String nonObfuscatedClassPatternA; private final String nonObfuscatedClassPatternB; diff --git a/src/main/java/matcher/gui/Gui.java b/src/main/java/matcher/gui/Gui.java index 19269ac1..f7b5564e 100644 --- a/src/main/java/matcher/gui/Gui.java +++ b/src/main/java/matcher/gui/Gui.java @@ -1,6 +1,7 @@ package matcher.gui; import java.io.File; +import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; @@ -19,10 +20,12 @@ import javafx.application.Platform; import javafx.concurrent.Task; import javafx.geometry.Insets; +import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; import javafx.scene.control.Label; import javafx.scene.control.ProgressBar; import javafx.scene.layout.ColumnConstraints; @@ -38,12 +41,18 @@ import javafx.stage.StageStyle; import javafx.stage.Window; +import net.fabricmc.mappingio.MappingReader; + import matcher.Matcher; import matcher.NameType; import matcher.config.Config; +import matcher.config.ProjectConfig; import matcher.config.Theme; import matcher.gui.IGuiComponent.ViewChangeCause; import matcher.gui.menu.MainMenuBar; +import matcher.gui.menu.NewProjectPane; +import matcher.mapping.MappingField; +import matcher.mapping.Mappings; import matcher.srcprocess.BuiltinDecompiler; import matcher.type.ClassEnvironment; import matcher.type.MatchType; @@ -97,6 +106,7 @@ public void start(Stage stage) { stage.show(); border.requestFocus(); + handleStartupArgs(getParameters().getRaw()); } @Override @@ -104,6 +114,195 @@ public void stop() throws Exception { threadPool.shutdown(); } + private void handleStartupArgs(List args) { + List inputsA = new ArrayList<>(); + List inputsB = new ArrayList<>(); + List classPathA = new ArrayList<>(); + List classPathB = new ArrayList<>(); + List sharedClassPath = new ArrayList<>(); + boolean inputsBeforeClassPath = false; + Path mappingsPathA = null; + Path mappingsPathB = null; + boolean saveUnmappedMatches = true; + String nonObfuscatedClassPatternA = ""; + String nonObfuscatedClassPatternB = ""; + String nonObfuscatedMemberPatternA = ""; + String nonObfuscatedMemberPatternB = ""; + boolean validProjectConfigArgPresent = false; + + for (int i = 0; i < args.size(); i++) { + switch (args.get(i)) { + // ProjectConfig args + + case "--inputs-a": + while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + inputsA.add(Path.of(args.get(++i))); + validProjectConfigArgPresent = true; + } + + break; + case "--inputs-b": + while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + inputsB.add(Path.of(args.get(++i))); + validProjectConfigArgPresent = true; + } + + break; + case "--classpath-a": + while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + classPathA.add(Path.of(args.get(++i))); + validProjectConfigArgPresent = true; + } + + break; + case "--classpath-b": + while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + classPathB.add(Path.of(args.get(++i))); + validProjectConfigArgPresent = true; + } + + break; + case "--shared-classpath": + while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + sharedClassPath.add(Path.of(args.get(++i))); + validProjectConfigArgPresent = true; + } + + break; + case "--mappings-a": + mappingsPathA = Path.of(args.get(++i)); + validProjectConfigArgPresent = true; + break; + case "--mappings-b": + mappingsPathB = Path.of(args.get(++i)); + validProjectConfigArgPresent = true; + break; + case "--dont-save-unmapped-matches": + saveUnmappedMatches = false; + validProjectConfigArgPresent = true; + break; + case "--inputs-before-classpath": + inputsBeforeClassPath = true; + validProjectConfigArgPresent = true; + break; + case "--non-obfuscated-class-pattern-a": + nonObfuscatedClassPatternA = args.get(++i); + validProjectConfigArgPresent = true; + break; + case "--non-obfuscated-class-pattern-b": + nonObfuscatedClassPatternB = args.get(++i); + validProjectConfigArgPresent = true; + break; + case "--non-obfuscated-member-pattern-a": + nonObfuscatedMemberPatternA = args.get(++i); + validProjectConfigArgPresent = true; + break; + case "--non-obfuscated-member-pattern-b": + nonObfuscatedMemberPatternB = args.get(++i); + validProjectConfigArgPresent = true; + break; + + // GUI args + + case "--hide-unmapped-a": + hideUnmappedA = true; + break; + } + } + + if (!validProjectConfigArgPresent) return; + + ProjectConfig config = new ProjectConfig.Builder(inputsA, inputsB) + .classPathA(new ArrayList<>(classPathA)) + .classPathB(new ArrayList<>(classPathB)) + .sharedClassPath(new ArrayList<>(sharedClassPath)) + .inputsBeforeClassPath(inputsBeforeClassPath) + .mappingsPathA(mappingsPathA) + .mappingsPathB(mappingsPathB) + .saveUnmappedMatches(saveUnmappedMatches) + .nonObfuscatedClassPatternA(nonObfuscatedClassPatternA) + .nonObfuscatedClassPatternB(nonObfuscatedClassPatternB) + .nonObfuscatedMemberPatternA(nonObfuscatedMemberPatternA) + .nonObfuscatedMemberPatternB(nonObfuscatedMemberPatternB) + .build(); + + newProject(config, inputsA.isEmpty() || inputsB.isEmpty()); + } + + public CompletableFuture newProject(ProjectConfig config, boolean showConfigDialog) { + ProjectConfig newConfig; + + if (showConfigDialog) { + Dialog dialog = new Dialog<>(); + //dialog.initModality(Modality.APPLICATION_MODAL); + dialog.setResizable(true); + dialog.setTitle("Project configuration"); + dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); + + Node okButton = dialog.getDialogPane().lookupButton(ButtonType.OK); + NewProjectPane content = new NewProjectPane(config, dialog.getOwner(), okButton); + + dialog.getDialogPane().setContent(content); + dialog.setResultConverter(button -> button == ButtonType.OK ? content.createConfig() : null); + + newConfig = dialog.showAndWait().orElse(null); + if (newConfig == null || !newConfig.isValid()) return CompletableFuture.completedFuture(false); + } else { + newConfig = config; + } + + Config.setProjectConfig(newConfig); + Config.saveAsLast(); + + matcher.reset(); + onProjectChange(); + + CompletableFuture ret = new CompletableFuture<>(); + + runProgressTask("Initializing files...", + progressReceiver -> { + matcher.init(newConfig, progressReceiver); + ret.complete(true); + }, + () -> { + if (newConfig.getMappingsPathA() != null) { + Path mappingsPath = newConfig.getMappingsPathA(); + + try { + List namespaces = MappingReader.getNamespaces(mappingsPath, null); + Mappings.load(mappingsPath, null, + namespaces.get(0), namespaces.get(1), + MappingField.PLAIN, MappingField.MAPPED, + env.getEnvA(), true); + } catch (IOException e) { + e.printStackTrace(); + } + } + + if (newConfig.getMappingsPathB() != null) { + Path mappingsPath = newConfig.getMappingsPathB(); + + try { + List namespaces = MappingReader.getNamespaces(mappingsPath, null); + Mappings.load(mappingsPath, null, + namespaces.get(0), namespaces.get(1), + MappingField.PLAIN, MappingField.MAPPED, + env.getEnvB(), true); + } catch (IOException e) { + e.printStackTrace(); + } + } + + onProjectChange(); + }, + exc -> { + exc.printStackTrace(); + ret.completeExceptionally(exc); + }); + + return ret; + } + public ClassEnvironment getEnv() { return env; } @@ -189,7 +388,21 @@ public void setShowNonInputs(boolean showNonInputs) { this.showNonInputs = showNonInputs; for (IGuiComponent c : components) { - c.onViewChange(ViewChangeCause.SHOW_NON_INPUTS_TOGGLED); + c.onViewChange(ViewChangeCause.DISPLAY_CLASSES_CHANGED); + } + } + + public boolean isHideUnmappedA() { + return hideUnmappedA; + } + + public void setHideUnmappedA(boolean hideUnmappedA) { + if (this.hideUnmappedA == hideUnmappedA) return; + + this.hideUnmappedA = hideUnmappedA; + + for (IGuiComponent c : components) { + c.onViewChange(ViewChangeCause.DISPLAY_CLASSES_CHANGED); } } @@ -445,6 +658,7 @@ public enum SortKey { private boolean sortMatchesAlphabetically; private boolean useClassTreeView; private boolean showNonInputs; + private boolean hideUnmappedA; private boolean useDiffColors; private Theme lastSwitchedToTheme; diff --git a/src/main/java/matcher/gui/IGuiComponent.java b/src/main/java/matcher/gui/IGuiComponent.java index aedba952..807e0dc6 100644 --- a/src/main/java/matcher/gui/IGuiComponent.java +++ b/src/main/java/matcher/gui/IGuiComponent.java @@ -26,7 +26,7 @@ default void onMatchListRefresh() { } enum ViewChangeCause { SORTING_CHANGED, CLASS_TREE_VIEW_TOGGLED, - SHOW_NON_INPUTS_TOGGLED, + DISPLAY_CLASSES_CHANGED, THEME_CHANGED, DIFF_COLORS_TOGGLED, NAME_TYPE_CHANGED, diff --git a/src/main/java/matcher/gui/MatchPaneDst.java b/src/main/java/matcher/gui/MatchPaneDst.java index ed810a45..a6b34fdc 100644 --- a/src/main/java/matcher/gui/MatchPaneDst.java +++ b/src/main/java/matcher/gui/MatchPaneDst.java @@ -276,7 +276,7 @@ public void onProjectChange() { @Override public void onViewChange(ViewChangeCause cause) { switch (cause) { - case SHOW_NON_INPUTS_TOGGLED: + case DISPLAY_CLASSES_CHANGED: cmpClasses = gui.getEnv().getDisplayClassesB(!gui.isShowNonInputs()); break; diff --git a/src/main/java/matcher/gui/MatchPaneSrc.java b/src/main/java/matcher/gui/MatchPaneSrc.java index 341fe41c..18fc6124 100644 --- a/src/main/java/matcher/gui/MatchPaneSrc.java +++ b/src/main/java/matcher/gui/MatchPaneSrc.java @@ -368,12 +368,20 @@ public void onClassSelect(ClassInstance cls) { items.clear(); if (cls != null) { - for (MethodInstance m : cls.getMethods()) { - if (m.isReal()) items.add(m); + for (MethodInstance mth : cls.getMethods()) { + if (!mth.isReal() || (gui.isHideUnmappedA() && !mth.hasNonInheritedMappedName() && !mth.hasMappedChildren())) { + continue; + } + + items.add(mth); } - for (FieldInstance m : cls.getFields()) { - if (m.isReal()) items.add(m); + for (FieldInstance fld : cls.getFields()) { + if (!fld.isReal() || (gui.isHideUnmappedA() && !fld.hasMappedName())) { + continue; + } + + items.add(fld); } items.sort(getMemberComparator()); @@ -388,12 +396,20 @@ public void onMethodSelect(MethodInstance method) { items.clear(); if (method != null) { - for (MethodVarInstance m : method.getArgs()) { - items.add(m); + for (MethodVarInstance arg : method.getArgs()) { + if (gui.isHideUnmappedA() && !arg.hasMappedName()) { + continue; + } + + items.add(arg); } - for (MethodVarInstance m : method.getVars()) { - items.add(m); + for (MethodVarInstance var : method.getVars()) { + if (gui.isHideUnmappedA() && !var.hasMappedName()) { + continue; + } + + items.add(var); } items.sort(getVarComparator()); @@ -480,7 +496,7 @@ public void onViewChange(ViewChangeCause cause) { updateLists(true, true); break; - case SHOW_NON_INPUTS_TOGGLED: + case DISPLAY_CLASSES_CHANGED: updateLists(true, false); break; @@ -506,7 +522,7 @@ private void updateLists(boolean updateContents, boolean resortMembers) { suppressChangeEvents = true; - List classes = updateContents ? gui.getEnv().getDisplayClassesA(!gui.isShowNonInputs()) : null; + List classes = updateContents ? gui.getEnv().getDisplayClassesA(!gui.isShowNonInputs(), gui.isHideUnmappedA()) : null; if (useClassTree) { updateClassTree(classes, clsComparator, selClass); diff --git a/src/main/java/matcher/gui/menu/FileMenu.java b/src/main/java/matcher/gui/menu/FileMenu.java index 8a1f93dc..c64541c3 100644 --- a/src/main/java/matcher/gui/menu/FileMenu.java +++ b/src/main/java/matcher/gui/menu/FileMenu.java @@ -10,7 +10,6 @@ import java.util.List; import java.util.Locale; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; import javafx.application.Platform; @@ -30,7 +29,6 @@ import matcher.Util; import matcher.config.Config; -import matcher.config.ProjectConfig; import matcher.gui.Gui; import matcher.gui.Gui.SelectedFile; import matcher.gui.menu.LoadMappingsPane.MappingsLoadSettings; @@ -102,51 +100,7 @@ private void init() { } private void newProject() { - newProject(Config.getProjectConfig(), true); - } - - public CompletableFuture newProject(ProjectConfig config, boolean showConfigDialog) { - ProjectConfig newConfig; - - if (showConfigDialog) { - Dialog dialog = new Dialog<>(); - //dialog.initModality(Modality.APPLICATION_MODAL); - dialog.setResizable(true); - dialog.setTitle("Project configuration"); - dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); - - Node okButton = dialog.getDialogPane().lookupButton(ButtonType.OK); - NewProjectPane content = new NewProjectPane(config, dialog.getOwner(), okButton); - - dialog.getDialogPane().setContent(content); - dialog.setResultConverter(button -> button == ButtonType.OK ? content.createConfig() : null); - - newConfig = dialog.showAndWait().orElse(null); - if (newConfig == null || !newConfig.isValid()) return CompletableFuture.completedFuture(false); - } else { - newConfig = config; - } - - Config.setProjectConfig(newConfig); - Config.saveAsLast(); - - gui.getMatcher().reset(); - gui.onProjectChange(); - - CompletableFuture ret = new CompletableFuture<>(); - - gui.runProgressTask("Initializing files...", - progressReceiver -> { - gui.getMatcher().init(newConfig, progressReceiver); - ret.complete(true); - }, - () -> gui.onProjectChange(), - exc -> { - exc.printStackTrace(); - ret.completeExceptionally(exc); - }); - - return ret; + gui.newProject(Config.getProjectConfig(), true); } private void loadProject() { diff --git a/src/main/java/matcher/gui/menu/NewProjectPane.java b/src/main/java/matcher/gui/menu/NewProjectPane.java index 229bd0a7..518761d4 100644 --- a/src/main/java/matcher/gui/menu/NewProjectPane.java +++ b/src/main/java/matcher/gui/menu/NewProjectPane.java @@ -41,7 +41,7 @@ import matcher.gui.GuiUtil; public class NewProjectPane extends GridPane { - NewProjectPane(ProjectConfig config, Window window, Node okButton) { + public NewProjectPane(ProjectConfig config, Window window, Node okButton) { this.window = window; this.okButton = okButton; @@ -310,16 +310,16 @@ private Node createMiscPane() { } public ProjectConfig createConfig() { - return new ProjectConfig(new ArrayList<>(pathsA), - new ArrayList<>(pathsB), - new ArrayList<>(classPathA), - new ArrayList<>(classPathB), - new ArrayList<>(sharedClassPath), - inputsBeforeClassPath, - nonObfuscatedClassPatternA.getText(), - nonObfuscatedClassPatternB.getText(), - nonObfuscatedMemberPatternA.getText(), - nonObfuscatedMemberPatternB.getText()); + return new ProjectConfig.Builder(new ArrayList<>(pathsA), new ArrayList<>(pathsB)) + .classPathA(new ArrayList<>(classPathA)) + .classPathB(new ArrayList<>(classPathB)) + .sharedClassPath(new ArrayList<>(sharedClassPath)) + .inputsBeforeClassPath(inputsBeforeClassPath) + .nonObfuscatedClassPatternA(nonObfuscatedClassPatternA.getText()) + .nonObfuscatedClassPatternB(nonObfuscatedClassPatternB.getText()) + .nonObfuscatedMemberPatternA(nonObfuscatedMemberPatternA.getText()) + .nonObfuscatedMemberPatternB(nonObfuscatedMemberPatternB.getText()) + .build(); } private final Window window; diff --git a/src/main/java/matcher/gui/menu/ViewMenu.java b/src/main/java/matcher/gui/menu/ViewMenu.java index 50935888..c8c33676 100644 --- a/src/main/java/matcher/gui/menu/ViewMenu.java +++ b/src/main/java/matcher/gui/menu/ViewMenu.java @@ -129,6 +129,7 @@ private void init() { radioMenuItem.setOnAction(event -> { Config.setTheme(theme); + Config.saveTheme(); gui.updateCss(); }); } diff --git a/src/main/java/matcher/mapping/Mappings.java b/src/main/java/matcher/mapping/Mappings.java index 0194a08f..6556d781 100644 --- a/src/main/java/matcher/mapping/Mappings.java +++ b/src/main/java/matcher/mapping/Mappings.java @@ -1,17 +1,13 @@ package matcher.mapping; import java.io.IOException; -import java.net.URI; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; -import org.objectweb.asm.tree.MethodNode; - import net.fabricmc.mappingio.FlatMappingVisitor; import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingReader; @@ -827,62 +823,10 @@ private static boolean shouldExportAny(FieldInstance[] fields, MappingFormat for private static boolean shouldExportName(MethodInstance method, MappingsExportVerbosity verbosity, boolean forAnyInput, Set> exportedHierarchies) { return verbosity == MappingsExportVerbosity.FULL || method.getAllHierarchyMembers().size() == 1 - || (method.getParents().isEmpty() || forAnyInput && isAnyInputRoot(method)) + || (method.getParents().isEmpty() || forAnyInput && method.isAnyInputRoot()) && (verbosity == MappingsExportVerbosity.ROOTS || !exportedHierarchies.contains(method.getAllHierarchyMembers())); // FIXME: forAnyInput + minimal needs to use an exportedHierarchies set per origin } - private static boolean isAnyInputRoot(MethodInstance method) { - ClassInstance cls = method.getCls(); - String name = method.getName(); - String desc = method.getDesc(); - - // check if each origin that supplies this method has a parent within the same origin - - for (int i = 0; i < cls.getAsmNodes().length; i++) { - for (MethodNode m : cls.getAsmNodes()[i].methods) { - if (m.name.equals(method.getName()) - && m.desc.equals(method.getDesc())) { - if (!hasParentMethod(name, desc, method.getParents(), cls.getAsmNodeOrigin(i))) { - return true; - } else { - break; - } - } - } - } - - return false; - } - - private static boolean hasParentMethod(String name, String desc, Collection parents, URI reqOrigin) { - // check direct parents (must supply the method from the required origin) - - for (MethodInstance parent : parents) { - ClassInstance parentCls = parent.getCls(); - - for (int i = 0; i < parentCls.getAsmNodes().length; i++) { - if (parentCls.getAsmNodeOrigin(i).equals(reqOrigin)) { - for (MethodNode m : parentCls.getAsmNodes()[i].methods) { - if (m.name.equals(name) - && m.desc.equals(desc)) { - return true; - } - } - } - } - } - - // check indirect parents recursively - - for (MethodInstance parent : parents) { - if (!parent.getParents().isEmpty() && hasParentMethod(name, desc, parent.getParents(), reqOrigin)) { - return true; - } - } - - return false; - } - public static void clear(ClassEnv env) { for (ClassInstance cls : env.getClasses()) { if (!cls.isReal()) continue; diff --git a/src/main/java/matcher/serdes/MatchesIo.java b/src/main/java/matcher/serdes/MatchesIo.java index 92043b43..eeba90a7 100644 --- a/src/main/java/matcher/serdes/MatchesIo.java +++ b/src/main/java/matcher/serdes/MatchesIo.java @@ -16,6 +16,7 @@ import java.util.function.DoubleConsumer; import matcher.Matcher; +import matcher.config.Config; import matcher.type.ClassEnvironment; import matcher.type.ClassInstance; import matcher.type.FieldInstance; @@ -338,13 +339,15 @@ public static boolean write(Matcher matcher, Path path) throws IOException { List classes = new ArrayList<>(); for (ClassInstance cls : env.getClassesA()) { - if (cls.isReal() && (cls.hasMatch() || !cls.isMatchable())) { + if (cls.isReal() && (cls.hasMatch() || !cls.isMatchable()) + && (Config.getProjectConfig().isSaveUnmappedMatches() || cls.hasMappedName() || cls.hasMappedChildren())) { classes.add(cls); } } for (ClassInstance cls : env.getClassesB()) { - if (cls.isReal() && !cls.isMatchable()) { + if (cls.isReal() && !cls.isMatchable() + && (Config.getProjectConfig().isSaveUnmappedMatches() || cls.hasMappedName() || cls.hasMappedChildren())) { classes.add(cls); } } @@ -434,26 +437,32 @@ private static void writeClass(ClassInstance cls, char side, Writer out) throws out.write(cls.getMatch().getId()); out.write('\n'); + boolean saveUnmapped = Config.getProjectConfig().isSaveUnmappedMatches(); + for (MethodInstance method : cls.getMethods()) { - if (method.hasMatch() || !method.isMatchable()) { + if ((method.hasMatch() || !method.isMatchable()) + && (saveUnmapped || method.hasNonInheritedMappedName() || method.hasMappedChildren())) { writeMethod(method, 'a', out); } } for (FieldInstance field : cls.getFields()) { - if (field.hasMatch() || !field.isMatchable()) { + if ((field.hasMatch() || !field.isMatchable()) + && (saveUnmapped || field.hasMappedName())) { writeMemberMain(field, 'a', out); } } for (MethodInstance method : cls.getMatch().getMethods()) { - if (!method.isMatchable()) { + if (!method.isMatchable() + && (saveUnmapped || method.hasNonInheritedMappedName() || method.hasMappedChildren())) { writeMethod(method, 'b', out); } } for (FieldInstance field : cls.getMatch().getFields()) { - if (!field.isMatchable()) { + if (!field.isMatchable() + && (saveUnmapped || field.hasMappedName())) { writeMemberMain(field, 'b', out); } } @@ -471,27 +480,31 @@ private static void writeClass(ClassInstance cls, char side, Writer out) throws private static void writeMethod(MethodInstance method, char side, Writer out) throws IOException { writeMemberMain(method, side, out); + boolean saveUnmapped = Config.getProjectConfig().isSaveUnmappedMatches(); + if (method.hasMatch()) { for (MethodVarInstance arg : method.getArgs()) { - if (arg.hasMatch() || !arg.isMatchable()) { + if ((arg.hasMatch() || !arg.isMatchable()) + && (saveUnmapped || arg.hasMappedName())) { writeVar(arg, 'a', out); } } for (MethodVarInstance var : method.getVars()) { - if (var.hasMatch() || !var.isMatchable()) { + if ((var.hasMatch() || !var.isMatchable()) + && (saveUnmapped || var.hasMappedName())) { writeVar(var, 'a', out); } } for (MethodVarInstance arg : method.getMatch().getArgs()) { - if (!arg.isMatchable()) { + if (!arg.isMatchable() && (saveUnmapped || arg.hasMappedName())) { writeVar(arg, 'b', out); } } for (MethodVarInstance var : method.getMatch().getVars()) { - if (!var.isMatchable()) { + if (!var.isMatchable() && (saveUnmapped || var.hasMappedName())) { writeVar(var, 'b', out); } } diff --git a/src/main/java/matcher/type/ClassEnvironment.java b/src/main/java/matcher/type/ClassEnvironment.java index 7bb0cd9b..a6e2ae0b 100644 --- a/src/main/java/matcher/type/ClassEnvironment.java +++ b/src/main/java/matcher/type/ClassEnvironment.java @@ -267,19 +267,23 @@ public Collection getClassesB() { return extractorB.getClasses(); } - public List getDisplayClassesA(boolean inputsOnly) { - return getDisplayClasses(extractorA, inputsOnly); + public List getDisplayClassesA(boolean inputsOnly, boolean mappedOnly) { + return getDisplayClasses(extractorA, inputsOnly, mappedOnly); } public List getDisplayClassesB(boolean inputsOnly) { - return getDisplayClasses(extractorB, inputsOnly); + return getDisplayClasses(extractorB, inputsOnly, false); } - private static List getDisplayClasses(ClassFeatureExtractor extractor, boolean inputsOnly) { + private static List getDisplayClasses(ClassFeatureExtractor extractor, boolean inputsOnly, boolean mappedOnly) { List ret = new ArrayList<>(); for (ClassInstance cls : extractor.getClasses()) { - if (!cls.isReal() || inputsOnly && !cls.isInput()) continue; + if (!cls.isReal() + || (inputsOnly && !cls.isInput()) + || (mappedOnly && !cls.hasMappedName() && !cls.hasMappedChildren())) { + continue; + } ret.add(cls); } diff --git a/src/main/java/matcher/type/ClassInstance.java b/src/main/java/matcher/type/ClassInstance.java index 9ff8e480..30ce62db 100644 --- a/src/main/java/matcher/type/ClassInstance.java +++ b/src/main/java/matcher/type/ClassInstance.java @@ -27,7 +27,7 @@ import matcher.classifier.ClassifierUtil; import matcher.type.Signature.ClassSignature; -public final class ClassInstance implements Matchable { +public final class ClassInstance implements ParentInstance, Matchable { /** * Create a shared unknown class. */ @@ -917,6 +917,19 @@ public void setMappedName(String mappedName) { this.mappedName = mappedName; } + @Override + public boolean hasMappedChildren() { + for (MethodInstance mth : methods) { + if (mth.hasNonInheritedMappedName() || mth.hasMappedChildren()) return true; + } + + for (FieldInstance fld : fields) { + if (fld.hasMappedName()) return true; + } + + return false; + } + @Override public String getMappedComment() { if (mappedComment != null) { diff --git a/src/main/java/matcher/type/MethodInstance.java b/src/main/java/matcher/type/MethodInstance.java index bed14aaa..8b74f04b 100644 --- a/src/main/java/matcher/type/MethodInstance.java +++ b/src/main/java/matcher/type/MethodInstance.java @@ -1,6 +1,8 @@ package matcher.type; +import java.net.URI; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -18,7 +20,7 @@ import matcher.classifier.ClassifierUtil; import matcher.type.Signature.MethodSignature; -public final class MethodInstance extends MemberInstance { +public final class MethodInstance extends MemberInstance implements ParentInstance { /** * Create a shared unknown method. */ @@ -341,6 +343,94 @@ public boolean hasAllArgsMapped() { return true; } + @Override + public boolean hasMappedChildren() { + for (MethodVarInstance arg : args) { + if (arg.hasMappedName()) return true; + } + + for (MethodVarInstance var : vars) { + if (var.hasMappedName()) return true; + } + + return false; + } + + public boolean hasNonInheritedMappedName() { + return !hasParentMethod() && hasMappedName(); + } + + public boolean hasParentMethod() { + if (hasParentMethod != null) return hasParentMethod; + + return hasParentMethod = checkAncestry(AncestryCheck.HAS_PARENT_METHOD); + } + + public boolean isAnyInputRoot() { + if (anyInputRoot != null) return anyInputRoot; + + return anyInputRoot = checkAncestry(AncestryCheck.IS_ANY_INPUT_ROOT); + } + + enum AncestryCheck { + HAS_PARENT_METHOD, + IS_ANY_INPUT_ROOT + } + + private boolean checkAncestry(AncestryCheck checkType) { + // check if each origin that supplies this method has a parent within the same origin + + for (int i = 0; i < cls.getAsmNodes().length; i++) { + for (MethodNode m : cls.getAsmNodes()[i].methods) { + if (m.name.equals(getName()) && m.desc.equals(getDesc())) { + boolean parentFound = hasParentMethod(getParents(), cls.getAsmNodeOrigin(i)); + + if (parentFound && checkType == AncestryCheck.HAS_PARENT_METHOD) { + return true; + } else if (parentFound && checkType == AncestryCheck.IS_ANY_INPUT_ROOT) { + break; + } else if (!parentFound && checkType == AncestryCheck.IS_ANY_INPUT_ROOT) { + return true; + } + } + } + } + + return false; + } + + private boolean hasParentMethod(Collection parents, URI reqOrigin) { + // check direct parents (must supply the method from the required origin) + + for (MethodInstance parent : parents) { + ClassInstance parentCls = parent.getCls(); + + if (parentCls.getAsmNodes() == null) { + continue; + } + + for (int i = 0; i < parentCls.getAsmNodes().length; i++) { + if (parentCls.getAsmNodeOrigin(i).equals(reqOrigin)) { + for (MethodNode m : parentCls.getAsmNodes()[i].methods) { + if (m.name.equals(getName()) && m.desc.equals(getDesc())) { + return true; + } + } + } + } + } + + // check indirect parents recursively + + for (MethodInstance parent : parents) { + if (!parent.getParents().isEmpty() && hasParentMethod(parent.getParents(), reqOrigin)) { + return true; + } + } + + return false; + } + public ClassInstance getRetType() { return retType; } @@ -490,6 +580,8 @@ public static String getId(String name, String desc) { final MethodSignature signature; private final MethodNode asmNode; + Boolean hasParentMethod; + Boolean anyInputRoot; MethodType type = MethodType.UNKNOWN; final Set refsIn = Util.newIdentityHashSet(); diff --git a/src/main/java/matcher/type/ParentInstance.java b/src/main/java/matcher/type/ParentInstance.java new file mode 100644 index 00000000..ee24eb83 --- /dev/null +++ b/src/main/java/matcher/type/ParentInstance.java @@ -0,0 +1,5 @@ +package matcher.type; + +public interface ParentInstance { + boolean hasMappedChildren(); +} From da3d2b973079c5c5d341017fdaebb4fbc63b4956 Mon Sep 17 00:00:00 2001 From: NebelNidas <48808497+NebelNidas@users.noreply.github.com> Date: Sun, 10 Mar 2024 19:50:06 +0100 Subject: [PATCH 2/2] Use proper logging library (#29) * Use Log4j for logging * Address PR feedback * Switch to SLF4J and Tinylog * Log more details while in dev-env * Switch spammy log lines to `trace` level * Address reviews * Don't use dedicated logging thread --- build.gradle | 7 + gradle.properties | 2 + src/main/java/matcher/Matcher.java | 26 ++- src/main/java/matcher/Util.java | 3 +- .../matcher/classifier/ClassClassifier.java | 2 +- .../matcher/classifier/ClassifierUtil.java | 18 +- src/main/java/matcher/gui/MatchPaneDst.java | 17 +- src/main/java/matcher/gui/MatchPaneSrc.java | 3 +- src/main/java/matcher/gui/menu/UidMenu.java | 2 +- src/main/java/matcher/gui/tab/WebViewTab.java | 2 +- .../matcher/mapping/MappingPropagator.java | 9 +- src/main/java/matcher/mapping/Mappings.java | 39 ++-- src/main/java/matcher/serdes/MatchesIo.java | 33 +-- src/main/java/matcher/srcprocess/Cfr.java | 21 +- src/main/java/matcher/srcprocess/Procyon.java | 5 +- .../java/matcher/srcprocess/SrcDecorator.java | 11 +- .../java/matcher/srcprocess/Vineflower.java | 3 +- src/main/java/matcher/type/Analysis.java | 192 +++++++++--------- .../java/matcher/type/ClassEnvironment.java | 3 +- .../matcher/type/ClassFeatureExtractor.java | 7 +- src/main/java/module-info.java | 1 + src/main/resources/tinylog-dev.properties | 3 + src/main/resources/tinylog.properties | 3 + 23 files changed, 226 insertions(+), 186 deletions(-) create mode 100644 src/main/resources/tinylog-dev.properties create mode 100644 src/main/resources/tinylog.properties diff --git a/build.gradle b/build.gradle index e74c8882..55a51f9d 100644 --- a/build.gradle +++ b/build.gradle @@ -57,6 +57,7 @@ javafx { dependencies { api "org.ow2.asm:asm:${asm_version}" api "org.ow2.asm:asm-tree:${asm_version}" + api "org.slf4j:slf4j-api:${slf4j_version}" api "net.fabricmc:mapping-io:${mappingio_version}" implementation "org.ow2.asm:asm-commons:${asm_version}" implementation "org.ow2.asm:asm-util:${asm_version}" @@ -64,6 +65,8 @@ dependencies { implementation "net.fabricmc:cfr:${fabric_cfr_version}" implementation "org.vineflower:vineflower:${vineflower_version}" implementation "org.bitbucket.mstrobel:procyon-compilertools:${procyon_version}" + runtimeOnly "org.tinylog:tinylog-impl:${tinylog_version}" + runtimeOnly "org.tinylog:slf4j-tinylog:${tinylog_version}" // JavaFX for all platforms (needed for cross-platform fat jar) runtimeOnly "org.openjfx:javafx-base:${javafx_version}:win" @@ -101,6 +104,10 @@ application { mainClass = 'matcher.Main' } +jar { + processResources.exclude('tinylog-dev.properties') +} + publishing { publications { mavenJava(MavenPublication) { diff --git a/gradle.properties b/gradle.properties index 2c775d7f..1bbdf7a5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,3 +18,5 @@ mappingio_version = 0.5.0 javaparser_version = 3.25.6 javafx_version = 21.0.1 checkstyle_version = 10.12.5 +slf4j_version = 2.0.12 +tinylog_version = 2.7.0 diff --git a/src/main/java/matcher/Matcher.java b/src/main/java/matcher/Matcher.java index 09136564..121b604b 100644 --- a/src/main/java/matcher/Matcher.java +++ b/src/main/java/matcher/Matcher.java @@ -26,6 +26,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import matcher.classifier.ClassClassifier; import matcher.classifier.ClassifierLevel; import matcher.classifier.FieldClassifier; @@ -173,7 +176,7 @@ public void match(ClassInstance a, ClassInstance b) { if (a.getArrayDimensions() != b.getArrayDimensions()) throw new IllegalArgumentException("the classes don't have the same amount of array dimensions"); if (a.getMatch() == b) return; - System.out.println("match class "+a+" -> "+b+(a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.debug("Matching class {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); if (a.getMatch() != null) { a.getMatch().setMatch(null); @@ -300,7 +303,7 @@ public void match(MethodInstance a, MethodInstance b) { if (a.getCls().getMatch() != b.getCls()) throw new IllegalArgumentException("the methods don't belong to the same class"); if (a.getMatch() == b) return; - System.out.println("match method "+a+" -> "+b+(a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.debug("Matching method {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); Set membersA = a.getAllHierarchyMembers(); Set membersB = b.getAllHierarchyMembers(); @@ -369,7 +372,7 @@ public void match(FieldInstance a, FieldInstance b) { if (a.getCls().getMatch() != b.getCls()) throw new IllegalArgumentException("the methods don't belong to the same class"); if (a.getMatch() == b) return; - System.out.println("match field "+a+" -> "+b+(a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.debug("Matching field {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); if (a.getMatch() != null) a.getMatch().setMatch(null); if (b.getMatch() != null) b.getMatch().setMatch(null); @@ -387,7 +390,7 @@ public void match(MethodVarInstance a, MethodVarInstance b) { if (a.isArg() != b.isArg()) throw new IllegalArgumentException("the method vars are not of the same kind"); if (a.getMatch() == b) return; - System.out.println("match method arg "+a+" -> "+b+(a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.debug("Matching method arg {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); if (a.getMatch() != null) a.getMatch().setMatch(null); if (b.getMatch() != null) b.getMatch().setMatch(null); @@ -402,7 +405,7 @@ public void unmatch(ClassInstance cls) { if (cls == null) throw new NullPointerException("null class"); if (cls.getMatch() == null) return; - System.out.println("unmatch class "+cls+" (was "+cls.getMatch()+")"+(cls.hasMappedName() ? " ("+cls.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.debug("Unmatching class {} (was {}){}", cls, cls.getMatch(), (cls.hasMappedName() ? " ("+cls.getName(NameType.MAPPED_PLAIN)+")" : "")); cls.getMatch().setMatch(null); cls.setMatch(null); @@ -424,7 +427,7 @@ public void unmatch(MemberInstance m) { if (m == null) throw new NullPointerException("null member"); if (m.getMatch() == null) return; - System.out.println("unmatch member "+m+" (was "+m.getMatch()+")"+(m.hasMappedName() ? " ("+m.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.debug("Unmatching member {} (was {}){}", m, m.getMatch(), (m.hasMappedName() ? " ("+m.getName(NameType.MAPPED_PLAIN)+")" : "")); if (m instanceof MethodInstance) { for (MethodVarInstance arg : ((MethodInstance) m).getArgs()) { @@ -452,7 +455,7 @@ public void unmatch(MethodVarInstance a) { if (a == null) throw new NullPointerException("null method var"); if (a.getMatch() == null) return; - System.out.println("unmatch method var "+a+" (was "+a.getMatch()+")"+(a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.debug("Unmatching method var {} (was {}){}", a, a.getMatch(), (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); a.getMatch().setMatch(null); a.setMatch(null); @@ -531,7 +534,7 @@ public boolean autoMatchClasses(ClassifierLevel level, double absThreshold, doub match(entry.getKey(), entry.getValue()); } - System.out.println("Auto matched "+matches.size()+" classes ("+(classes.size() - matches.size())+" unmatched, "+env.getClassesA().size()+" total)"); + LOGGER.info("Auto matched {} classes ({} unmatched, {} total)", matches.size(), (classes.size() - matches.size()), env.getClassesA().size()); return !matches.isEmpty(); } @@ -577,7 +580,7 @@ public boolean autoMatchMethods(ClassifierLevel level, double absThreshold, doub match(entry.getKey(), entry.getValue()); } - System.out.println("Auto matched "+matches.size()+" methods ("+totalUnmatched.get()+" unmatched)"); + LOGGER.info("Auto matched {} methods ({} unmatched)", matches.size(), totalUnmatched.get()); return !matches.isEmpty(); } @@ -598,7 +601,7 @@ public boolean autoMatchFields(ClassifierLevel level, double absThreshold, doubl match(entry.getKey(), entry.getValue()); } - System.out.println("Auto matched "+matches.size()+" fields ("+totalUnmatched.get()+" unmatched)"); + LOGGER.info("Auto matched {} fields ({} unmatched)", matches.size(), totalUnmatched.get()); return !matches.isEmpty(); } @@ -713,7 +716,7 @@ private boolean autoMatchMethodVars(boolean isArg, Function int compareInsns(AbstractInsnNode insnA, AbstractInsnNode ins implB.getOwner(), implB.getName(), implB.getDesc(), Util.isCallToInterface(implB), env) ? COMPARED_SIMILAR : COMPARED_DISTINCT; default: - System.out.println("unexpected impl tag: "+implA.getTag()); + Matcher.LOGGER.warn("Unexpected impl tag: {}", implA.getTag()); } } else if (!Util.isIrrelevantBsm(a.bsm)) { - System.out.printf("unknown invokedynamic bsm: %s/%s%s (tag=%d iif=%b)%n", a.bsm.getOwner(), a.bsm.getName(), a.bsm.getDesc(), a.bsm.getTag(), a.bsm.isInterface()); + Matcher.LOGGER.warn("Unknown invokedynamic bsm: {}/{}{} (tag={} iif={})", + a.bsm.getOwner(), a.bsm.getName(), a.bsm.getDesc(), a.bsm.getTag(), a.bsm.isInterface()); } // TODO: implement @@ -622,10 +624,10 @@ private static int[] mapLists(T listA, T listB, ListElementRetriever int[] mapLists(T listA, T listB, ListElementRetriever= COMPARED_DISTINCT) { assert c - keepCost == COMPARED_DISTINCT; - //System.out.printf("%d/%d rep %s -> %s%n", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); + //Matcher.LOGGER.debug("{}/{} rep {} -> {}", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); ret[i - 1] = -1; } else { - //System.out.printf("%d/%d eq %s - %s%n", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); + //Matcher.LOGGER.debug("{}/{} eq {} - {}", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); ret[i - 1] = j - 1; /*U e = elementRetriever.apply(listA, i - 1); @@ -658,11 +660,11 @@ private static int[] mapLists(T listA, T listB, ListElementRetriever stack, RankResult for (String part : parts) { String op = part.toLowerCase(Locale.ENGLISH); - //System.out.printf("stack: %s, op: %s%n", stack, op); + //Matcher.LOGGER.debug("stack: {}, op: {}", stack, op); byte opTypeA = OP_TYPE_NONE; byte opTypeB = OP_TYPE_NONE; @@ -489,7 +490,7 @@ private Boolean evalFilter(List stack, RankResult if (type == OP_TYPE_NONE) continue; if (stack.isEmpty()) { - System.err.println("stack underflow"); + Matcher.LOGGER.error("Stack underflow"); return null; } @@ -504,7 +505,7 @@ private Boolean evalFilter(List stack, RankResult || type == OP_TYPE_COMPARABLE && operand instanceof Comparable; if (!valid) { - System.err.println("invalid operand type"); + Matcher.LOGGER.debug("Invalid operand type"); return null; } @@ -516,7 +517,7 @@ private Boolean evalFilter(List stack, RankResult ClassInstance cls = env.getClsByName((String) operand); if (cls == null) { - System.err.println("unknown class "+operand); + Matcher.LOGGER.debug("Unknown class {}", operand); return null; } else { operand = cls; @@ -530,7 +531,7 @@ private Boolean evalFilter(List stack, RankResult } } - //System.out.printf("opA: %s, opB: %s%n", opA, opB); + //Matcher.LOGGER.debug("opA: {}, opB: {}", opA, opB); switch (op) { case "a": @@ -609,16 +610,16 @@ private Boolean evalFilter(List stack, RankResult } } - //System.out.printf("res stack: %s%n", stack); + //Matcher.LOGGER.debug("Res stack: {}", stack); if (stack.isEmpty() || stack.size() > 2) { - System.err.println("no result"); + Matcher.LOGGER.info("No result found"); return null; } else if (stack.size() == 1) { if (stack.get(0) instanceof Boolean) { return (Boolean) stack.get(0); } else { - System.err.println("invalid result"); + Matcher.LOGGER.error("Invalid result"); return null; } } else { // 2 elements on the stack, use equals diff --git a/src/main/java/matcher/gui/MatchPaneSrc.java b/src/main/java/matcher/gui/MatchPaneSrc.java index 18fc6124..47ee5203 100644 --- a/src/main/java/matcher/gui/MatchPaneSrc.java +++ b/src/main/java/matcher/gui/MatchPaneSrc.java @@ -29,6 +29,7 @@ import javafx.scene.control.TreeView; import javafx.scene.paint.Color; +import matcher.Matcher; import matcher.NameType; import matcher.Util; import matcher.config.Config; @@ -123,7 +124,7 @@ private void retrieveCellTextColors() { try { css = parser.parse(Config.getTheme().getUrl().toURI().toURL()); } catch (IOException | URISyntaxException e) { - System.err.println("CSS parsing failed"); + Matcher.LOGGER.error("CSS parsing failed", e); return; } diff --git a/src/main/java/matcher/gui/menu/UidMenu.java b/src/main/java/matcher/gui/menu/UidMenu.java index 37b04b01..84df5d9d 100644 --- a/src/main/java/matcher/gui/menu/UidMenu.java +++ b/src/main/java/matcher/gui/menu/UidMenu.java @@ -318,7 +318,7 @@ private void assignMissing() { } } - System.out.printf("uids assigned: %d class, %d method, %d field%n", + Matcher.LOGGER.info("UIDs assigned: {} class, {} method, {} field", nextClassUid - env.nextClassUid, nextMethodUid - env.nextMethodUid, nextFieldUid - env.nextFieldUid); diff --git a/src/main/java/matcher/gui/tab/WebViewTab.java b/src/main/java/matcher/gui/tab/WebViewTab.java index 555faa22..d5e75b3a 100644 --- a/src/main/java/matcher/gui/tab/WebViewTab.java +++ b/src/main/java/matcher/gui/tab/WebViewTab.java @@ -46,7 +46,7 @@ protected void displayHtml(String html) { html = template.replace("%text%", html) .replace("%theme_path%", Config.getTheme().getUrl().toExternalForm()); - // System.out.println(html); + //Matcher.LOGGER.debug(html); webView.getEngine().loadContent(html); } diff --git a/src/main/java/matcher/mapping/MappingPropagator.java b/src/main/java/matcher/mapping/MappingPropagator.java index f908ed1e..5aab9841 100644 --- a/src/main/java/matcher/mapping/MappingPropagator.java +++ b/src/main/java/matcher/mapping/MappingPropagator.java @@ -4,6 +4,7 @@ import java.util.Set; import java.util.function.DoubleConsumer; +import matcher.Matcher; import matcher.NameType; import matcher.Util; import matcher.type.ClassEnvironment; @@ -87,7 +88,7 @@ public static boolean propagateNames(ClassEnvironment env, DoubleConsumer progre } } - System.out.printf("Propagated %d method names, %d method arg names.", propagatedMethodNames, propagatedArgNames); + Matcher.LOGGER.info("Propagated {} method names and {} method arg names", propagatedMethodNames, propagatedArgNames); return propagatedMethodNames > 0 || propagatedArgNames > 0; } @@ -114,10 +115,10 @@ public static boolean fixRecordMemberNames(ClassEnvironment env, NameType nameTy if (linkedMethod.isNameObfuscated() && (!field.isNameObfuscated() || !linkedMethod.hasMappedName() || field.hasMappedName())) { - System.out.println("copy record component name for method "+linkedMethod+" from field "+field+" -> "+fieldName); + Matcher.LOGGER.debug("Copying record component name for method {} from field {} -> {}", linkedMethod, field, fieldName); linkedMethod.setMappedName(fieldName); } else { - System.out.println("copy record component name for field "+field+" from method "+linkedMethod+" -> "+methodName); + Matcher.LOGGER.debug("Copying record component name for field {} from method {} -> {}", field, linkedMethod, methodName); field.setMappedName(methodName); } @@ -125,7 +126,7 @@ public static boolean fixRecordMemberNames(ClassEnvironment env, NameType nameTy } } - System.out.printf("Fixed %d names.%n", modified); + Matcher.LOGGER.info("Fixed {} record names.", modified); return modified > 0; } diff --git a/src/main/java/matcher/mapping/Mappings.java b/src/main/java/matcher/mapping/Mappings.java index 6556d781..81d2867b 100644 --- a/src/main/java/matcher/mapping/Mappings.java +++ b/src/main/java/matcher/mapping/Mappings.java @@ -17,6 +17,7 @@ import net.fabricmc.mappingio.adapter.RegularAsFlatMappingVisitor; import net.fabricmc.mappingio.format.MappingFormat; +import matcher.Matcher; import matcher.NameType; import matcher.Util; import matcher.type.ClassEnv; @@ -80,7 +81,7 @@ public boolean visitClass(String srcName) { cur = cls = findClass(srcName, fieldSource, env); if (cls == null) { - if (warnedClasses.add(srcName)) System.out.println("can't find mapped class "+srcName); + if (warnedClasses.add(srcName)) Matcher.LOGGER.warn("Can't find mapped class {}", srcName); return false; } @@ -96,7 +97,7 @@ public boolean visitMethod(String srcName, String srcDesc) { cur = method = cls.getMethod(srcName, srcDesc, fieldSource.type); if (method == null || !method.isReal()) { - System.out.printf("can't find mapped method %s/%s%s%n", + Matcher.LOGGER.warn("Can't find mapped method {}/{}{}", cls.getName(fieldSource.type), srcName, srcDesc); return false; } @@ -132,28 +133,28 @@ public boolean visitMethodVar(int asmIndex, int lvIndex, int startOpIdx, int end private MethodVarInstance getMethodVar(int varIndex, int lvIndex, int startOpIdx, int asmIndex, boolean isArg) { if (isArg && varIndex < -1 || varIndex >= method.getArgs().length) { - System.out.println("invalid var index "+varIndex+" for method "+method); + Matcher.LOGGER.warn("Invalid var index {} for method {}", varIndex, method); } else if (lvIndex < -1 || lvIndex >= (isArg ? method.getArgs() : method.getVars()).length * 2 + 1) { - System.out.println("invalid lv index "+lvIndex+" for method "+method); + Matcher.LOGGER.warn("Invalid lv index {} for method {}", lvIndex, method); } else if (asmIndex < -1) { - System.out.println("invalid lv asm index "+asmIndex+" for method "+method); + Matcher.LOGGER.warn("Invalid lv asm index {} for method {}", asmIndex, method); } else { if (!isArg || varIndex == -1) { if (asmIndex >= 0) { varIndex = findVarIndexByAsm(isArg ? method.getArgs() : method.getVars(), asmIndex); if (varIndex == -1) { - System.out.println("invalid lv asm index "+asmIndex+" for method "+method); + Matcher.LOGGER.warn("Invalid lv asm index {} for method {}", asmIndex, method); return null; } } else if (lvIndex <= -1) { - System.out.println("missing arg+lvt index "+lvIndex+" for method "+method); + Matcher.LOGGER.warn("Missing arg+lvt index {} for method {}", lvIndex, method); return null; } else { varIndex = findVarIndexByLv(isArg ? method.getArgs() : method.getVars(), lvIndex, startOpIdx); if (varIndex == -1) { - System.out.println("invalid lv index "+lvIndex+" for method "+method); + Matcher.LOGGER.warn("Invalid lv index {} for method {}", lvIndex, method); return null; } } @@ -162,12 +163,12 @@ private MethodVarInstance getMethodVar(int varIndex, int lvIndex, int startOpIdx MethodVarInstance var = isArg ? method.getArg(varIndex) : method.getVar(varIndex); if (lvIndex != -1 && var.getLvIndex() != lvIndex) { - System.out.println("mismatched lv index "+lvIndex+" for method "+method); + Matcher.LOGGER.warn("Mismatched lv index {} for method {}", lvIndex, method); return null; } if (asmIndex != -1 && var.getAsmIndex() != asmIndex) { - System.out.println("mismatched lv asm index "+asmIndex+" for method "+method); + Matcher.LOGGER.warn("Mismatched lv asm index {} for method {}", asmIndex, method); return null; } @@ -186,7 +187,7 @@ public boolean visitField(String srcName, String srcDesc) { cur = field = cls.getField(srcName, srcDesc, fieldSource.type); if (field == null || !field.isReal()) { - System.out.println("can't find mapped field "+cls.getName(fieldSource.type)+"/"+srcName); + Matcher.LOGGER.warn("Can't find mapped field {}/{}", cls.getName(fieldSource.type), srcName); return false; } @@ -225,7 +226,7 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam String prefix = env.getGlobal().classUidPrefix; if (!name.startsWith(prefix)) { - System.out.println("Invalid uid class name "+name); + Matcher.LOGGER.warn("Invalid uid class name {}", name); return; } else { int innerNameStart = name.lastIndexOf('$') + 1; @@ -235,7 +236,7 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam int subPrefixStart = prefix.lastIndexOf('/') + 1; if (!name.startsWith(prefix.substring(subPrefixStart), innerNameStart)) { - System.out.println("Invalid uid class name "+name); + Matcher.LOGGER.warn("Invalid uid class name {}", name); return; } else { uidStr = name.substring(innerNameStart + prefix.length() - subPrefixStart); @@ -247,7 +248,7 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam int uid = Integer.parseInt(uidStr); if (uid < 0) { - System.out.println("Invalid class uid "+uid); + Matcher.LOGGER.warn("Invalid class uid {}", uid); return; } else if (cls.getUid() < 0 || cls.getUid() > uid || replace) { cls.setUid(uid); @@ -283,13 +284,13 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam String prefix = env.getGlobal().fieldUidPrefix; if (!name.startsWith(prefix)) { - System.out.println("Invalid uid field name "+name); + Matcher.LOGGER.warn("Invalid uid field name {}", name); return; } else { int uid = Integer.parseInt(name.substring(prefix.length())); if (uid < 0) { - System.out.println("Invalid field uid "+uid); + Matcher.LOGGER.warn("Invalid field uid {}", uid); return; } else if (field.getUid() < 0 || field.getUid() > uid || replace) { for (FieldInstance f : field.getAllHierarchyMembers()) { @@ -327,13 +328,13 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam String prefix = env.getGlobal().methodUidPrefix; if (!name.startsWith(prefix)) { - System.out.println("Invalid uid method name "+name); + Matcher.LOGGER.warn("Invalid uid method name {}", name); return; } else { int uid = Integer.parseInt(name.substring(prefix.length())); if (uid < 0) { - System.out.println("Invalid method uid "+uid); + Matcher.LOGGER.warn("Invalid method uid {}", uid); return; } else if (method.getUid() < 0 || method.getUid() > uid || replace) { for (MethodInstance m : method.getAllHierarchyMembers()) { @@ -410,7 +411,7 @@ public void visitComment(MappedElementKind targetKind, String comment) { throw t; } - System.out.printf("Loaded mappings for %d classes, %d methods (%d args, %d vars) and %d fields (comments: %d/%d/%d).%n", + Matcher.LOGGER.info("Loaded mappings for {} classes, {} methods ({} args, {} vars) and {} fields (comments: {}/{}/{}).", dstNameCounts[MatchableKind.CLASS.ordinal()], dstNameCounts[MatchableKind.METHOD.ordinal()], dstNameCounts[MatchableKind.METHOD_ARG.ordinal()], diff --git a/src/main/java/matcher/serdes/MatchesIo.java b/src/main/java/matcher/serdes/MatchesIo.java index eeba90a7..01b58a75 100644 --- a/src/main/java/matcher/serdes/MatchesIo.java +++ b/src/main/java/matcher/serdes/MatchesIo.java @@ -168,12 +168,12 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M ClassInstance target; if (currentClass == null) { - System.err.println("Unknown a class "+idA); + Matcher.LOGGER.warn("Unknown a class {}", idA); } else if ((target = env.getLocalClsByIdB(idB)) == null) { - System.err.println("Unknown b class "+idA); + Matcher.LOGGER.warn("Unknown b class {}", idA); currentClass = null; } else if (!currentClass.isMatchable() || !target.isMatchable()) { - System.err.println("Unmatchable a/b class "+idA+"/"+idB); + Matcher.LOGGER.warn("Unmatchable a/b class {}/{}", idA, idB); currentClass = null; } else { currentClass.setMatchable(true); @@ -190,7 +190,7 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M currentMethod = null; if (cls == null) { - System.err.println("Unknown "+side+" class "+id); + Matcher.LOGGER.warn("Unknown {} class {}", side, id); } else { if (cls.hasMatch()) matcher.unmatch(cls); cls.setMatchable(false); @@ -209,11 +209,11 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M MethodInstance b; if (a == null) { - System.err.println("Unknown a method "+idA+" in class "+currentClass); + Matcher.LOGGER.warn("Unknown a method {} in class {}", idA, currentClass); } else if ((b = currentClass.getMatch().getMethod(idB)) == null) { - System.err.println("Unknown b method "+idB+" in class "+currentClass.getMatch()); + Matcher.LOGGER.warn("Unknown b method {} in class {}", idB, currentClass.getMatch()); } else if (!a.isMatchable() || !b.isMatchable()) { - System.err.println("Unmatchable a/b method "+idA+"/"+idB); + Matcher.LOGGER.warn("Unmatchable a/b method {}/{}", idA, idB); currentMethod = null; } else { a.setMatchable(true); @@ -225,11 +225,11 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M FieldInstance b; if (a == null) { - System.err.println("Unknown a field "+idA+" in class "+currentClass); + Matcher.LOGGER.warn("Unknown a field {} in class {}", idA, currentClass); } else if ((b = currentClass.getMatch().getField(idB)) == null) { - System.err.println("Unknown b field "+idB+" in class "+currentClass.getMatch()); + Matcher.LOGGER.warn("Unknown b field {} in class {}", idB, currentClass.getMatch()); } else if (!a.isMatchable() || !b.isMatchable()) { - System.err.println("Unmatchable a/b field "+idA+"/"+idB); + Matcher.LOGGER.warn("Unmatchable a/b field {}/{}", idA, idB); } else { a.setMatchable(true); b.setMatchable(true); @@ -249,12 +249,12 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M MemberInstance member = line.charAt(1) == 'm' ? cls.getMethod(id) : cls.getField(id); if (member == null) { - System.err.println("Unknown member "+id+" in class "+cls); + Matcher.LOGGER.warn("Unknown member {} in class {}", id, cls); } else { if (member.hasMatch()) matcher.unmatch(member); if (!member.setMatchable(false)) { - System.err.printf("can't mark %s as unmatchable, already matched?%n", member); + Matcher.LOGGER.warn("Can't mark {} as unmatchable, already matched?", member); } } } else if (line.startsWith("\t\tma\t") || line.startsWith("\t\tmv\t")) { // method arg or method var @@ -281,11 +281,12 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M } if (idxA < 0 || idxA >= varsA.length) { - System.err.println("Unknown a method "+type+" "+idxA+" in method "+currentMethod); + Matcher.LOGGER.warn("Unknown a method {} {} in method {}", type, idxA, currentMethod); } else if (idxB < 0 || idxB >= varsB.length) { - System.err.println("Unknown b method "+type+" "+idxB+" in method "+matchedMethod); + Matcher.LOGGER.warn("Unknown b method {} {} in method {}", type, idxB, matchedMethod); } else if (!varsA[idxA].isMatchable() || !varsB[idxB].isMatchable()) { - System.err.println("Unmatchable a/b method "+type+" "+idxA+"/"+idxB+" in method "+currentMethod+"/"+matchedMethod); + Matcher.LOGGER.warn("Unmatchable a/b method {} {}/{} in method {}/{}", + type, idxA, idxB, currentMethod, matchedMethod); currentMethod = null; } else { varsA[idxA].setMatchable(true); @@ -315,7 +316,7 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M } if (idx < 0 || idx >= vars.length) { - System.err.println("Unknown a method "+type+" "+idx+" in method "+method); + Matcher.LOGGER.warn("Unknown a method {} {} in method {}", type, idx, method); continue; } else { MethodVarInstance var = vars[idx]; diff --git a/src/main/java/matcher/srcprocess/Cfr.java b/src/main/java/matcher/srcprocess/Cfr.java index 4edff929..2f00d994 100644 --- a/src/main/java/matcher/srcprocess/Cfr.java +++ b/src/main/java/matcher/srcprocess/Cfr.java @@ -13,6 +13,7 @@ import org.benf.cfr.reader.api.OutputSinkFactory; import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; +import matcher.Matcher; import matcher.NameType; import matcher.type.ClassFeatureExtractor; import matcher.type.ClassInstance; @@ -43,12 +44,12 @@ private static class Source implements ClassFileSource { @Override public void informAnalysisRelativePathDetail(String usePath, String classFilePath) { - //System.out.printf("informAnalysisRelativePathDetail %s %s%n", usePath, classFilePath); + //Matcher.LOGGER.debug("informAnalysisRelativePathDetail {} {}", usePath, classFilePath); } @Override public Collection addJar(String jarPath) { - System.out.printf("addJar %s%n", jarPath); + Matcher.LOGGER.debug("addJar {}", jarPath); throw new UnsupportedOperationException(); } @@ -61,7 +62,7 @@ public String getPossiblyRenamedPath(String path) { @Override public Pair getClassFileContent(String path) throws IOException { if (!path.endsWith(fileSuffix)) { - System.out.printf("getClassFileContent invalid path: %s%n", path); + Matcher.LOGGER.debug("getClassFileContent invalid path: {}", path); throw new NoSuchFileException(path); } @@ -69,12 +70,12 @@ public Pair getClassFileContent(String path) throws IOException ClassInstance cls = env.getClsByName(clsName, nameType); if (cls == null) { - System.out.printf("getClassFileContent missing cls: %s%n", clsName); + Matcher.LOGGER.debug("getClassFileContent missing cls: {}", clsName); throw new NoSuchFileException(path); } if (cls.getAsmNodes() == null) { - System.out.printf("getClassFileContent unknown cls: %s%n", clsName); + Matcher.LOGGER.debug("getClassFileContent unknown cls: {}", clsName); throw new NoSuchFileException(path); } @@ -97,16 +98,16 @@ public List getSupportedSinks(SinkType sinkType, Collection OutputSinkFactory.Sink getSink(SinkType sinkType, SinkClass sinkClass) { switch (sinkType) { case EXCEPTION: - return str -> System.out.println("e "+str); + return str -> Matcher.LOGGER.error("CFR exception: {}", str); case JAVA: return sb::append; case PROGRESS: - return str -> System.out.println("p "+str); + return str -> Matcher.LOGGER.debug("CFR progress: {}", str); case SUMMARY: - return str -> System.out.println("s "+str); + return str -> Matcher.LOGGER.debug("CFR summary: {}", str); default: - System.out.println("unknown sink type: "+sinkType); - return str -> System.out.println("* "+str); + Matcher.LOGGER.debug("Unknown CFR sink type: {}", sinkType); + return str -> Matcher.LOGGER.debug("{}", str); } } diff --git a/src/main/java/matcher/srcprocess/Procyon.java b/src/main/java/matcher/srcprocess/Procyon.java index 08639f24..a2914d5f 100644 --- a/src/main/java/matcher/srcprocess/Procyon.java +++ b/src/main/java/matcher/srcprocess/Procyon.java @@ -10,6 +10,7 @@ import com.strobel.decompiler.DecompilerSettings; import com.strobel.decompiler.PlainTextOutput; +import matcher.Matcher; import matcher.NameType; import matcher.type.ClassFeatureExtractor; import matcher.type.ClassInstance; @@ -42,7 +43,7 @@ public boolean tryLoadType(String internalName, Buffer buffer) { if (cls == null) { if (checkWarn(internalName)) { - System.out.printf("missing cls: %s%n", internalName); + Matcher.LOGGER.debug("Missing cls: {}", internalName); } return false; @@ -50,7 +51,7 @@ public boolean tryLoadType(String internalName, Buffer buffer) { if (cls.getAsmNodes() == null) { if (checkWarn(internalName)) { - System.out.printf("unknown cls: %s%n", internalName); + Matcher.LOGGER.debug("Unknown cls: {}", internalName); } return false; diff --git a/src/main/java/matcher/srcprocess/SrcDecorator.java b/src/main/java/matcher/srcprocess/SrcDecorator.java index b31a3c43..f694af43 100644 --- a/src/main/java/matcher/srcprocess/SrcDecorator.java +++ b/src/main/java/matcher/srcprocess/SrcDecorator.java @@ -29,6 +29,7 @@ import com.github.javaparser.ast.comments.JavadocComment; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; +import matcher.Matcher; import matcher.NameType; import matcher.type.ClassInstance; import matcher.type.FieldInstance; @@ -174,7 +175,7 @@ private static String tryFixCodeFormat(String src, List problems) { } private static String moveStatement(String source, Range slice, Position to) { - System.out.println("Shifting " + slice + " to " + to); + Matcher.LOGGER.debug("Shifting " + slice + " to " + to); //Remember that lines are counted from 1 not 0, so the indexes have to be offset backwards List lines = new BufferedReader(new StringReader(source)).lines().collect(Collectors.toList()); @@ -284,7 +285,7 @@ public void visit(EnumDeclaration n, TypeResolver resolver) { private void visitCls(TypeDeclaration n, TypeResolver resolver) { ClassInstance cls = resolver.getCls(n); - //System.out.println("cls "+n.getName().getIdentifier()+" = "+cls+" at "+n.getRange()); + // Matcher.LOGGER.debug("cls {} = {} at {}", n.getName().getIdentifier(), cls, n.getRange()); if (cls != null) { handleComment(cls.getMappedComment(), n); @@ -296,7 +297,7 @@ private void visitCls(TypeDeclaration n, TypeResolver resolver) { @Override public void visit(ConstructorDeclaration n, TypeResolver resolver) { MethodInstance m = resolver.getMethod(n); - //System.out.println("ctor "+n.getName().getIdentifier()+" = "+m+" at "+n.getRange()); + // Matcher.LOGGER.debug("ctor {} = {} at {}", n.getName().getIdentifier(), m, n.getRange()); if (m != null) { handleMethodComment(m, n, resolver); @@ -316,7 +317,7 @@ public void visit(ConstructorDeclaration n, TypeResolver resolver) { @Override public void visit(MethodDeclaration n, TypeResolver resolver) { MethodInstance m = resolver.getMethod(n); - //System.out.println("mth "+n.getName().getIdentifier()+" = "+m+" at "+n.getRange()); + // Matcher.LOGGER.debug("mth {}, = {} at {}", n.getName().getIdentifier(), m, n.getRange()); if (m != null) { handleMethodComment(m, n, resolver); @@ -336,7 +337,7 @@ public void visit(FieldDeclaration n, TypeResolver resolver) { for (VariableDeclarator var : n.getVariables()) { FieldInstance f = resolver.getField(var); - //System.out.println("fld "+v.getName().getIdentifier()+" = "+f+" at "+v.getRange()); + // Matcher.LOGGER.debug("fld {} = {} at {}", v.getName().getIdentifier(), f, v.getRange()); if (f != null) { if (f.getMappedComment() != null) { diff --git a/src/main/java/matcher/srcprocess/Vineflower.java b/src/main/java/matcher/srcprocess/Vineflower.java index 81ffe027..78efffcb 100644 --- a/src/main/java/matcher/srcprocess/Vineflower.java +++ b/src/main/java/matcher/srcprocess/Vineflower.java @@ -18,6 +18,7 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IResultSaver; +import matcher.Matcher; import matcher.NameType; import matcher.type.ClassFeatureExtractor; import matcher.type.ClassInstance; @@ -124,7 +125,7 @@ public void begin() { } @Override public void acceptClass(String qualifiedName, String fileName, String content, int[] mapping) { - if (DEBUG) System.out.printf("acceptClass(%s, %s, %s, %s)%n", qualifiedName, fileName, content, Arrays.toString(mapping)); + if (DEBUG) Matcher.LOGGER.debug("acceptClass({}, {}, {}, {})", qualifiedName, fileName, content, Arrays.toString(mapping)); results.put(qualifiedName, content); } diff --git a/src/main/java/matcher/type/Analysis.java b/src/main/java/matcher/type/Analysis.java index 2d417e30..53d9666e 100644 --- a/src/main/java/matcher/type/Analysis.java +++ b/src/main/java/matcher/type/Analysis.java @@ -1,6 +1,5 @@ package matcher.type; -import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayDeque; @@ -48,6 +47,7 @@ import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceMethodVisitor; +import matcher.Matcher; import matcher.NameType; import matcher.Util; @@ -56,7 +56,7 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { MethodNode asmNode = method.getAsmNode(); if (asmNode == null || (asmNode.access & Opcodes.ACC_ABSTRACT) != 0 || asmNode.instructions.size() == 0) return; - System.out.println(method.getDisplayName(NameType.MAPPED_PLAIN, true)); + Matcher.LOGGER.debug(method.getDisplayName(NameType.MAPPED_PLAIN, true)); dump(asmNode); StateRecorder rec = new StateRecorder(method, common); @@ -737,14 +737,14 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { } } - rec.dump(il, System.out); + rec.dump(il); BitSet entryPoints = getEntryPoints(asmNode, exitPoints); applyTryCatchExits(asmNode, entryPoints, exitPoints); addDirectExits(il, entryPoints, exitPoints); purgeLocals(il, rec, entryPoints, exitPoints); - rec.dump(il, System.out); + rec.dump(il); createLocalVariables(il, rec, entryPoints, exitPoints, asmNode.localVariables); } @@ -1144,12 +1144,12 @@ private static List createLocalVariables(InsnList il, StateRe lvToVar = null; - System.out.println("Local vars raw:"); + Matcher.LOGGER.debug("Local vars raw:"); for (int i = 0; i < varCount; i++) { ExecState state = rec.getState(startIndices[i]); - System.out.printf(" %d: LV %d @ %d - %d: %s\t\t(%s)%n", + Matcher.LOGGER.debug(" {}: LV {} @ {} - {}: {}\t\t({})", i, varToLv[i], startIndices[i], endIndices[i], state.locals[varToLv[i]].toString(), rec.varSources[state.localVarIds[varToLv[i]] - 1].name()); } @@ -1255,12 +1255,12 @@ private static List createLocalVariables(InsnList il, StateRe } } - System.out.println("Local vars:"); + Matcher.LOGGER.debug("Local vars:"); for (int i = 0; i < varCount; i++) { ExecState state = rec.getState(startIndices[i]); - System.out.printf(" %d: LV %d @ %d - %d: %s\t\t(%s)%n", + Matcher.LOGGER.debug(" {}: LV {} @ {} - {}: {}\t\t({})", i, varToLv[i], startIndices[i], endIndices[i], state.locals[varToLv[i]].toString(), rec.varSources[state.localVarIds[varToLv[i]] - 1].name()); } @@ -1282,14 +1282,15 @@ private static List createLocalVariables(InsnList il, StateRe } if (!mismatch) { - System.out.println("Existing vars matched!"); + Matcher.LOGGER.debug("Existing vars matched!"); } else { - System.out.println("Existing vars mismatch:"); + Matcher.LOGGER.debug("Existing vars mismatch:"); for (int i = 0; i < orig.size(); i++) { LocalVariableNode lvn = orig.get(i); - System.out.printf(" %d: LV %d @ %d - %d: %s%n", i, lvn.index, il.indexOf(lvn.start), il.indexOf(lvn.end) - 1, lvn.desc); + Matcher.LOGGER.debug(" {}: LV {} @ {} - {}: {}", + i, lvn.index, il.indexOf(lvn.start), il.indexOf(lvn.end) - 1, lvn.desc); } } } @@ -1717,70 +1718,72 @@ public int getNextVarId(VarSource source) { return ++nextVarId; } - public void dump(InsnList il, PrintStream ps) { + public void dump(InsnList il) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < states.length; i++) { ExecState state = states[i]; - ps.print(i); - ps.print(": "); + sb.append(i); + sb.append(": "); if (state != null) { - dumpVars(state.locals, state.localVarIds, ps); - ps.print(" | "); - dumpVars(state.stack, state.stackVarIds, ps); + dumpVars(state.locals, state.localVarIds, sb); + sb.append(" | "); + dumpVars(state.stack, state.stackVarIds, sb); } else { - ps.print(""); + sb.append(""); } - ps.print(" "); + sb.append(' '); AbstractInsnNode ain = il.get(i); int op = ain.getOpcode(); if (op != -1) { - ps.print(Printer.OPCODES[ain.getOpcode()]); + sb.append(Printer.OPCODES[ain.getOpcode()]); } switch (ain.getType()) { case AbstractInsnNode.INSN: break; case AbstractInsnNode.INT_INSN: - ps.print(' '); + sb.append(' '); if (op == Opcodes.BIPUSH || op == Opcodes.SIPUSH) { - ps.print(((IntInsnNode) ain).operand); + sb.append(((IntInsnNode) ain).operand); } else { - ps.print(Printer.TYPES[((IntInsnNode) ain).operand]); + sb.append(Printer.TYPES[((IntInsnNode) ain).operand]); } break; case AbstractInsnNode.VAR_INSN: - ps.print(' '); - ps.print(((VarInsnNode) ain).var); + sb.append(' '); + sb.append(((VarInsnNode) ain).var); break; case AbstractInsnNode.TYPE_INSN: - ps.print(' '); - ps.print(((TypeInsnNode) ain).desc); + sb.append(' '); + sb.append(((TypeInsnNode) ain).desc); break; case AbstractInsnNode.FIELD_INSN: { FieldInsnNode in = (FieldInsnNode) ain; - ps.print(' '); - ps.print(in.owner); - ps.print('/'); - ps.print(in.name); - ps.print(' '); - ps.print(in.desc); + sb.append(' '); + sb.append(in.owner); + sb.append('/'); + sb.append(in.name); + sb.append(' '); + sb.append(in.desc); break; } case AbstractInsnNode.METHOD_INSN: { MethodInsnNode in = (MethodInsnNode) ain; - ps.print(' '); - ps.print(in.owner); - ps.print('/'); - ps.print(in.name); - ps.print(in.desc); - ps.print(" itf="); - ps.print(in.itf); + sb.append(' '); + sb.append(in.owner); + sb.append('/'); + sb.append(in.name); + sb.append(in.desc); + sb.append(" itf="); + sb.append(in.itf); break; } case AbstractInsnNode.INVOKE_DYNAMIC_INSN: { @@ -1789,108 +1792,111 @@ public void dump(InsnList il, PrintStream ps) { break; } case AbstractInsnNode.JUMP_INSN: - ps.print(' '); - ps.print(il.indexOf(((JumpInsnNode) ain).label)); + sb.append(' '); + sb.append(il.indexOf(((JumpInsnNode) ain).label)); break; case AbstractInsnNode.LDC_INSN: - ps.print(' '); - ps.print(((LdcInsnNode) ain).cst); + sb.append(' '); + sb.append(((LdcInsnNode) ain).cst); break; case AbstractInsnNode.IINC_INSN: - ps.print(' '); - ps.print(((IincInsnNode) ain).var); - ps.print(' '); - ps.print(((IincInsnNode) ain).incr); + sb.append(' '); + sb.append(((IincInsnNode) ain).var); + sb.append(' '); + sb.append(((IincInsnNode) ain).incr); break; case AbstractInsnNode.TABLESWITCH_INSN: { TableSwitchInsnNode in = (TableSwitchInsnNode) ain; - ps.print(" min="); - ps.print(in.min); - ps.print(" max="); - ps.print(in.max); - ps.print(" def="); - ps.print(il.indexOf(in.dflt)); + sb.append(" min="); + sb.append(in.min); + sb.append(" max="); + sb.append(in.max); + sb.append(" def="); + sb.append(il.indexOf(in.dflt)); for (int j = 0; j < in.labels.size(); j++) { - ps.print(' '); - ps.print(il.indexOf(in.labels.get(j))); + sb.append(' '); + sb.append(il.indexOf(in.labels.get(j))); } break; } case AbstractInsnNode.LOOKUPSWITCH_INSN: { LookupSwitchInsnNode in = (LookupSwitchInsnNode) ain; - ps.print(" def="); - ps.print(il.indexOf(in.dflt)); + sb.append(" def="); + sb.append(il.indexOf(in.dflt)); for (int j = 0; j < in.keys.size(); j++) { - ps.print(' '); - ps.print(in.keys.get(j)); - ps.print('='); - ps.print(il.indexOf(in.labels.get(j))); + sb.append(' '); + sb.append(in.keys.get(j)); + sb.append('='); + sb.append(il.indexOf(in.labels.get(j))); } break; } case AbstractInsnNode.MULTIANEWARRAY_INSN: { MultiANewArrayInsnNode in = (MultiANewArrayInsnNode) ain; - ps.print(' '); - ps.print(in.desc); - ps.print(" dims="); - ps.print(in.dims); + sb.append(' '); + sb.append(in.desc); + sb.append(" dims="); + sb.append(in.dims); break; } case AbstractInsnNode.LABEL: - ps.print("LABEL "); - ps.print(i); + sb.append("LABEL "); + sb.append(i); break; case AbstractInsnNode.FRAME: - ps.print("FRAME"); + sb.append("FRAME"); break; case AbstractInsnNode.LINE: - ps.print("LINE "); - ps.print(((LineNumberNode) ain).line); + sb.append("LINE "); + sb.append(((LineNumberNode) ain).line); break; default: throw new UnsupportedOperationException("unknown insn: "+ain); } - ps.println(); + sb.append('\n'); } + + Matcher.LOGGER.debug(sb.toString()); } - private void dumpVars(ClassInstance[] types, int[] ids, PrintStream ps) { - ps.print('['); + private void dumpVars(ClassInstance[] types, int[] ids, StringBuilder sb) { + sb.append('['); for (int i = 0; i < types.length; i++) { - if (i != 0) ps.print(", "); + if (i != 0) sb.append(", "); ClassInstance type = types[i]; int id = ids[i]; if (id == 0) { if (type == common.TOP) { - ps.print("TOP"); + sb.append("TOP"); } else { assert type == null; - ps.print("X"); + sb.append("X"); } } else { assert type != null; assert type != common.TOP; - ps.print(getMappedVarId(id)); - ps.print(':'); + sb.append(getMappedVarId(id)); + sb.append(':'); if (type != common.NULL) { - ps.print(type.toString()); + sb.append(type.toString()); } else { - ps.print("null"); + sb.append("null"); } } } - ps.print(']'); + sb.append(']'); + Matcher.LOGGER.debug(sb.toString()); } final ExecState[] states; // state at the start of every instruction index @@ -1974,7 +1980,7 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) AbstractInsnNode fieldWrite = null; //dump(method.asmNode); - //System.out.println("\n------------------------\n"); + //Matcher.LOGGER.debug("\n------------------------\n"); for (Iterator it = il.iterator(); it.hasNext(); ) { AbstractInsnNode aInsn = it.next(); @@ -2078,10 +2084,10 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) in = il.get(pos); initIl.add(in); - /*System.out.print(pos+": "); + /*Matcher.LOGGER.debug(pos+": "); il.get(pos).accept(visitor); - System.out.print(textifier.getText().get(0)); + Matcher.LOGGER.debug(textifier.getText().get(0)); textifier.getText().clear();*/ pos++; @@ -2092,7 +2098,7 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) /* int pos = fieldWritePos; for (int i = 0; i < 100; i++) { - System.out.println(i+" ("+pos+"):"); + Matcher.LOGGER.debug(i+" ("+pos+"):"); Frame frame = frames[pos]; Frame nextFrame = frames[pos + 1]; @@ -2102,24 +2108,24 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) SourceValue value = frame.getStack(frame.getStackSize() - 1); if (value.insns.isEmpty()) { - System.out.println("empty"); + Matcher.LOGGER.debug("empty"); break; } for (AbstractInsnNode ain : value.insns) { ain.accept(visitor); - System.out.print(textifier.getText().get(0)); + Matcher.LOGGER.debug(textifier.getText().get(0)); textifier.getText().clear(); } pos = method.asmNode.instructions.indexOf(value.insns.iterator().next()); }*/ - /*System.out.println(frame); - System.out.println("\n------------------------\n"); + /*Matcher.LOGGER.debug(frame); + Matcher.LOGGER.debug("\n------------------------\n"); dump(frame.getStack(frame.getStackSize() - 1).insns);*/ - //System.out.println(); + //Matcher.LOGGER.debug(); } private static int getStackDemand(AbstractInsnNode ain, Frame frame) { @@ -2386,7 +2392,7 @@ private static void dump(MethodNode method) { textifier.print(pw); } - System.out.println(writer.toString()); + Matcher.LOGGER.debug(writer.toString()); } private static void dump(Iterable il) { @@ -2404,6 +2410,6 @@ private static void dump(Iterable il) { textifier.print(pw); } - System.out.println(writer.toString()); + Matcher.LOGGER.debug(writer.toString()); } } diff --git a/src/main/java/matcher/type/ClassEnvironment.java b/src/main/java/matcher/type/ClassEnvironment.java index a6e2ae0b..edf79759 100644 --- a/src/main/java/matcher/type/ClassEnvironment.java +++ b/src/main/java/matcher/type/ClassEnvironment.java @@ -33,6 +33,7 @@ import org.objectweb.asm.tree.InnerClassNode; import org.objectweb.asm.tree.MethodNode; +import matcher.Matcher; import matcher.NameType; import matcher.Util; import matcher.classifier.ClassifierUtil; @@ -586,7 +587,7 @@ private static void addOuterClass(ClassInstance cls, String name, boolean create outerClass = cls.getEnv().getCreateClassInstance(ClassInstance.getId(name), createUnknown); if (outerClass == null) { - System.err.println("missing outer cls: "+name+" for "+cls); + Matcher.LOGGER.trace("Missing outer cls: {} for {}", name, cls); return; } } diff --git a/src/main/java/matcher/type/ClassFeatureExtractor.java b/src/main/java/matcher/type/ClassFeatureExtractor.java index 605ba5be..dcafb6f7 100644 --- a/src/main/java/matcher/type/ClassFeatureExtractor.java +++ b/src/main/java/matcher/type/ClassFeatureExtractor.java @@ -28,6 +28,7 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.TypeInsnNode; +import matcher.Matcher; import matcher.NameType; import matcher.Util; import matcher.type.Analysis.CommonClasses; @@ -240,7 +241,7 @@ private void processClassB(ClassInstance cls) { private void processMethodInsns(MethodInstance method) { if (!method.isReal()) { // artificial method to capture calls to types with incomplete/unknown hierarchy/super type method info - System.out.println("skipping empty method "+method); + Matcher.LOGGER.debug("Skipping empty method {}", method); return; } @@ -303,7 +304,7 @@ private void processMethodInsns(MethodInstance method) { Util.isCallToInterface(impl), impl.getTag() == Opcodes.H_INVOKESTATIC); break; default: - System.out.println("unexpected impl tag: "+impl.getTag()); + Matcher.LOGGER.warn("Unexpected impl tag: {}", impl.getTag()); } break; @@ -328,7 +329,7 @@ private MethodInstance resolveMethod(String owner, String name, String desc, boo MethodInstance ret = cls.resolveMethod(name, desc, toInterface); if (ret == null && create) { - System.out.printf("creating synthetic method %s/%s%s%n", owner, name, desc); + Matcher.LOGGER.trace("Creating synthetic method {}/{}{}", owner, name, desc); ret = new MethodInstance(cls, name, desc, isStatic); cls.addMethod(ret); diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index d6a200d7..c5f2b99c 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -11,6 +11,7 @@ exports matcher.bcremap; exports matcher.serdes; + requires transitive org.slf4j; requires cfr; requires com.github.javaparser.core; requires org.vineflower.vineflower; diff --git a/src/main/resources/tinylog-dev.properties b/src/main/resources/tinylog-dev.properties new file mode 100644 index 00000000..5688dfda --- /dev/null +++ b/src/main/resources/tinylog-dev.properties @@ -0,0 +1,3 @@ +writer = console +writer.format = {date: HH:mm:ss.SSS} [{thread}/{level}]: {message} +writer.level = debug diff --git a/src/main/resources/tinylog.properties b/src/main/resources/tinylog.properties new file mode 100644 index 00000000..d90124ce --- /dev/null +++ b/src/main/resources/tinylog.properties @@ -0,0 +1,3 @@ +writer = console +writer.format = {date: HH:mm:ss} [{level}]: {message} +writer.level = info