diff options
author | modmuss50 <modmuss50@gmail.com> | 2021-10-11 13:47:16 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-11 13:47:16 +0100 |
commit | e2439b7f57a82c365d4726d068b68ea2eb606f78 (patch) | |
tree | 5cc78058c70e46e22d1ada1a4411c9356cbdf906 /src/main/java/net/fabricmc/loom/decompilers/fernflower | |
parent | 5315d3c5b24bcce47268ef8962c07aeb934b014b (diff) | |
download | architectury-loom-e2439b7f57a82c365d4726d068b68ea2eb606f78.tar.gz architectury-loom-e2439b7f57a82c365d4726d068b68ea2eb606f78.tar.bz2 architectury-loom-e2439b7f57a82c365d4726d068b68ea2eb606f78.zip |
Rewrite GenSources including full support for CFR. (#511)
* Rewrite CFR decompiler interface. Support javadoc
* CFR line numbers and fixes.
* Cleanup and fix
* Use WorkerExecutor to fork, massively cleans up the fernflower code, but does remove the fancy multithreaded logging.
* Use IPC to get logging back from the decompilers.
* Cleanup UnpickJarTask, fix leak in IPCServer
* Used published CFR build
* Handle older windows versions that do not support AF_UNIX.
* Fixes and basic unit test
* Improve memory handling of genSources
* Stop decompile worker JVM
Diffstat (limited to 'src/main/java/net/fabricmc/loom/decompilers/fernflower')
-rw-r--r-- | src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java | 163 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractForkedFFExecutor.java | 107 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricFernFlowerDecompiler.java | 39 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/decompilers/fernflower/FernflowerLogger.java (renamed from src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricForkedFFExecutor.java) | 64 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java | 70 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/decompilers/fernflower/ThreadIDFFLogger.java | 127 |
6 files changed, 76 insertions, 494 deletions
diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java deleted file mode 100644 index f059ed36..00000000 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2019-2021 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.decompilers.fernflower; - -import static java.text.MessageFormat.format; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Stack; -import java.util.function.Supplier; - -import org.gradle.api.Project; -import org.gradle.api.internal.project.ProjectInternal; -import org.gradle.api.logging.LogLevel; -import org.gradle.internal.logging.progress.ProgressLogger; -import org.gradle.internal.logging.progress.ProgressLoggerFactory; -import org.gradle.internal.service.ServiceRegistry; -import org.gradle.process.ExecResult; -import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; - -import net.fabricmc.loom.api.decompilers.DecompilationMetadata; -import net.fabricmc.loom.api.decompilers.LoomDecompiler; -import net.fabricmc.loom.util.ConsumingOutputStream; -import net.fabricmc.loom.util.OperatingSystem; - -public abstract class AbstractFernFlowerDecompiler implements LoomDecompiler { - private final Project project; - - protected AbstractFernFlowerDecompiler(Project project) { - this.project = project; - } - - public abstract Class<? extends AbstractForkedFFExecutor> fernFlowerExecutor(); - - @Override - public void decompile(Path compiledJar, Path sourcesDestination, Path linemapDestination, DecompilationMetadata metaData) { - if (!OperatingSystem.is64Bit()) { - throw new UnsupportedOperationException("FernFlower decompiler requires a 64bit JVM to run due to the memory requirements"); - } - - project.getLogging().captureStandardOutput(LogLevel.LIFECYCLE); - - Map<String, Object> options = new HashMap<>() {{ - put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1"); - put(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1"); - put(IFernflowerPreferences.REMOVE_SYNTHETIC, "1"); - put(IFernflowerPreferences.LOG_LEVEL, "trace"); - put(IFernflowerPreferences.THREADS, metaData.numberOfThreads()); - put(IFernflowerPreferences.INDENT_STRING, "\t"); - }}; - - List<String> args = new ArrayList<>(); - - options.forEach((k, v) -> args.add(format("-{0}={1}", k, v))); - args.add(absolutePathOf(compiledJar)); - args.add("-o=" + absolutePathOf(sourcesDestination)); - args.add("-l=" + absolutePathOf(linemapDestination)); - args.add("-m=" + absolutePathOf(metaData.javaDocs())); - - // TODO, Decompiler breaks on jemalloc, J9 module-info.class? - for (Path library : metaData.libraries()) { - args.add("-e=" + absolutePathOf(library)); - } - - ServiceRegistry registry = ((ProjectInternal) project).getServices(); - ProgressLoggerFactory factory = registry.get(ProgressLoggerFactory.class); - ProgressLogger progressGroup = factory.newOperation(getClass()).setDescription("Decompile"); - Supplier<ProgressLogger> loggerFactory = () -> { - ProgressLogger pl = factory.newOperation(getClass(), progressGroup); - pl.setDescription("decompile worker"); - pl.started(); - return pl; - }; - Stack<ProgressLogger> freeLoggers = new Stack<>(); - Map<String, ProgressLogger> inUseLoggers = new HashMap<>(); - - progressGroup.started(); - ExecResult result = ForkingJavaExec.javaexec( - project, - spec -> { - spec.getMainClass().set(fernFlowerExecutor().getName()); - spec.jvmArgs("-Xms200m", "-Xmx3G"); - spec.setArgs(args); - spec.setErrorOutput(new ConsumingOutputStream(line -> { - if (line.startsWith("Inconsistent inner class entries")) { - // Suppress this - return; - } - - System.err.println(line); - })); - spec.setStandardOutput(new ConsumingOutputStream(line -> { - if (line.startsWith("Listening for transport") || !line.contains("::")) { - System.out.println(line); - return; - } - - int sepIdx = line.indexOf("::"); - String id = line.substring(0, sepIdx).trim(); - String data = line.substring(sepIdx + 2).trim(); - - ProgressLogger logger = inUseLoggers.get(id); - - String[] segs = data.split(" "); - - if (segs[0].equals("waiting")) { - if (logger != null) { - logger.progress("Idle.."); - inUseLoggers.remove(id); - freeLoggers.push(logger); - } - } else { - if (logger == null) { - if (!freeLoggers.isEmpty()) { - logger = freeLoggers.pop(); - } else { - logger = loggerFactory.get(); - } - - inUseLoggers.put(id, logger); - } - - logger.progress(data); - } - })); - }); - inUseLoggers.values().forEach(ProgressLogger::completed); - freeLoggers.forEach(ProgressLogger::completed); - progressGroup.completed(); - - result.rethrowFailure(); - result.assertNormalExitValue(); - } - - private static String absolutePathOf(Path path) { - return path.toAbsolutePath().toString(); - } -} diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractForkedFFExecutor.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractForkedFFExecutor.java deleted file mode 100644 index 2435233e..00000000 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractForkedFFExecutor.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2019-2020 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.decompilers.fernflower; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * Entry point for Forked FernFlower task. - * Takes one parameter, a single file, each line is treated as command line input. - * Forces one input file. - * Forces one output file using '-o=/path/to/output' - * Created by covers1624 on 11/02/19. - * <p>Extending classes MUST have a standard "public static void main(args)". - * They may then call AbstractForkedFFExecutor#decompile for it to use the overridden AbstractForkedFFExecutor#runFF - * </p> - */ -public abstract class AbstractForkedFFExecutor { - public static void decompile(String[] args, AbstractForkedFFExecutor ffExecutor) { - Map<String, Object> options = new HashMap<>(); - File input = null; - File output = null; - File lineMap = null; - File mappings = null; - List<File> libraries = new ArrayList<>(); - - boolean isOption = true; - - for (String arg : args) { - if (isOption && arg.length() > 5 && arg.charAt(0) == '-' && arg.charAt(4) == '=') { - String value = arg.substring(5); - - if ("true".equalsIgnoreCase(value)) { - value = "1"; - } else if ("false".equalsIgnoreCase(value)) { - value = "0"; - } - - options.put(arg.substring(1, 4), value); - } else { - isOption = false; - - if (arg.startsWith("-e=")) { - libraries.add(new File(arg.substring(3))); - } else if (arg.startsWith("-o=")) { - if (output != null) { - throw new RuntimeException("Unable to set more than one output."); - } - - output = new File(arg.substring(3)); - } else if (arg.startsWith("-l=")) { - if (lineMap != null) { - throw new RuntimeException("Unable to set more than one lineMap file."); - } - - lineMap = new File(arg.substring(3)); - } else if (arg.startsWith("-m=")) { - if (mappings != null) { - throw new RuntimeException("Unable to use more than one mappings file."); - } - - mappings = new File(arg.substring(3)); - } else { - if (input != null) { - throw new RuntimeException("Unable to set more than one input."); - } - - input = new File(arg); - } - } - } - - Objects.requireNonNull(input, "Input not set."); - Objects.requireNonNull(output, "Output not set."); - Objects.requireNonNull(mappings, "Mappings not set."); - - ffExecutor.runFF(options, libraries, input, output, lineMap, mappings); - } - - public abstract void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap, File mappings); -} diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricFernFlowerDecompiler.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricFernFlowerDecompiler.java index b3663773..c3009448 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricFernFlowerDecompiler.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricFernFlowerDecompiler.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2018-2020 FabricMC + * Copyright (c) 2019-2021 FabricMC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,20 +24,43 @@ package net.fabricmc.loom.decompilers.fernflower; -import org.gradle.api.Project; +import java.nio.file.Path; +import java.util.Map; -public class FabricFernFlowerDecompiler extends AbstractFernFlowerDecompiler { - public FabricFernFlowerDecompiler(Project project) { - super(project); - } +import org.jetbrains.java.decompiler.main.Fernflower; +import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; +import org.jetbrains.java.decompiler.main.extern.IResultSaver; + +import net.fabricmc.fernflower.api.IFabricJavadocProvider; +import net.fabricmc.loom.api.decompilers.DecompilationMetadata; +import net.fabricmc.loom.api.decompilers.LoomDecompiler; +public final class FabricFernFlowerDecompiler implements LoomDecompiler { @Override public String name() { return "FabricFlower"; // Or something else? } @Override - public Class<? extends AbstractForkedFFExecutor> fernFlowerExecutor() { - return FabricForkedFFExecutor.class; + public void decompile(Path compiledJar, Path sourcesDestination, Path linemapDestination, DecompilationMetadata metaData) { + Map<String, Object> options = Map.of( + IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1", + IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", + IFernflowerPreferences.REMOVE_SYNTHETIC, "1", + IFernflowerPreferences.LOG_LEVEL, "trace", + IFernflowerPreferences.THREADS, String.valueOf(metaData.numberOfThreads()), + IFernflowerPreferences.INDENT_STRING, "\t", + IFabricJavadocProvider.PROPERTY_NAME, new TinyJavadocProvider(metaData.javaDocs().toFile()) + ); + + IResultSaver saver = new ThreadSafeResultSaver(sourcesDestination::toFile, linemapDestination::toFile); + Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, new FernflowerLogger(metaData.logger())); + + for (Path library : metaData.libraries()) { + ff.addLibrary(library.toFile()); + } + + ff.addSource(compiledJar.toFile()); + ff.decompileContext(); } } diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricForkedFFExecutor.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/FernflowerLogger.java index e88c8086..a98060e9 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/FabricForkedFFExecutor.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/FernflowerLogger.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2018-2020 FabricMC + * Copyright (c) 2021 FabricMC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,34 +24,60 @@ package net.fabricmc.loom.decompilers.fernflower; -import java.io.File; -import java.util.List; -import java.util.Map; +import java.io.IOException; -import org.jetbrains.java.decompiler.main.Fernflower; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; -import org.jetbrains.java.decompiler.main.extern.IResultSaver; -import net.fabricmc.fernflower.api.IFabricJavadocProvider; +import net.fabricmc.loom.util.IOStringConsumer; -public class FabricForkedFFExecutor extends AbstractForkedFFExecutor { - public static void main(String[] args) { - AbstractForkedFFExecutor.decompile(args, new FabricForkedFFExecutor()); +public class FernflowerLogger extends IFernflowerLogger { + private final IOStringConsumer logger; + + public FernflowerLogger(IOStringConsumer logger) { + this.logger = logger; } @Override - public void runFF(Map<String, Object> options, List<File> libraries, File input, File output, File lineMap, File mappings) { - options.put(IFabricJavadocProvider.PROPERTY_NAME, new TinyJavadocProvider(mappings)); + public void writeMessage(String message, Severity severity) { + if (message.contains("Inconsistent inner class entries for")) return; + System.err.println(message); + } - IResultSaver saver = new ThreadSafeResultSaver(() -> output, () -> lineMap); - IFernflowerLogger logger = new ThreadIDFFLogger(); - Fernflower ff = new Fernflower(FernFlowerUtils::getBytecode, saver, options, logger); + @Override + public void writeMessage(String message, Severity severity, Throwable t) { + writeMessage(message, severity); + } - for (File library : libraries) { - ff.addLibrary(library); + private void write(String data) { + try { + logger.accept(data); + } catch (IOException e) { + throw new RuntimeException("Failed to log", e); } + } + + @Override + public void startReadingClass(String className) { + write("Decompiling " + className); + } + + @Override + public void startClass(String className) { + write("Decompiling " + className); + } + + @Override + public void startWriteClass(String className) { + // Nope + } - ff.addSource(input); - ff.decompileContext(); + @Override + public void startMethod(String methodName) { + // Nope + } + + @Override + public void endMethod() { + // Nope } } diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java deleted file mode 100644 index bbcd80de..00000000 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ForkingJavaExec.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2016-2021 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.decompilers.fernflower; - -import java.net.URL; -import java.net.URLClassLoader; - -import org.gradle.api.Action; -import org.gradle.api.Project; -import org.gradle.api.artifacts.ConfigurationContainer; -import org.gradle.api.artifacts.dsl.DependencyHandler; -import org.gradle.api.file.FileCollection; -import org.gradle.process.ExecResult; -import org.gradle.process.JavaExecSpec; - -/** - * Simple utility class for a Task that wishes to execute a java process - * with the classpath of the gradle plugin plus groovy. - * - * <p>Created by covers1624 on 11/02/19. - */ -public class ForkingJavaExec { - public static ExecResult javaexec(Project project, Action<? super JavaExecSpec> action) { - return project.javaexec(spec -> { - spec.classpath(getClasspath(project)); - action.execute(spec); - }); - } - - private static Object getClasspath(Project project) { - if (System.getProperty("fabric.loom.test") != null) { - return getTestClasspath(); - } - - return getRuntimeClasspath(project.getRootProject().getPlugins().hasPlugin("fabric-loom") ? project.getRootProject() : project); - } - - private static FileCollection getRuntimeClasspath(Project project) { - ConfigurationContainer configurations = project.getBuildscript().getConfigurations(); - DependencyHandler handler = project.getDependencies(); - return configurations.getByName("classpath") - .plus(configurations.detachedConfiguration(handler.localGroovy())); - } - - private static URL[] getTestClasspath() { - return ((URLClassLoader) ForkingJavaExec.class.getClassLoader()).getURLs(); - } -} diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ThreadIDFFLogger.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/ThreadIDFFLogger.java deleted file mode 100644 index a7b617bc..00000000 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/ThreadIDFFLogger.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2019-2020 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.decompilers.fernflower; - -import java.io.PrintStream; -import java.text.MessageFormat; -import java.util.Stack; - -import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; - -/** - * This logger simply prints what each thread is doing - * to the console in a machine parsable way. - * - * <p>Created by covers1624 on 11/02/19. - */ -public class ThreadIDFFLogger extends IFernflowerLogger { - public final PrintStream stdOut; - public final PrintStream stdErr; - - private final ThreadLocal<Stack<String>> workingClass = ThreadLocal.withInitial(Stack::new); - private final ThreadLocal<Stack<String>> line = ThreadLocal.withInitial(Stack::new); - - public ThreadIDFFLogger() { - this(System.err, System.out); - } - - public ThreadIDFFLogger(PrintStream stdOut, PrintStream stdErr) { - this.stdOut = stdOut; - this.stdErr = stdErr; - } - - @Override - public void writeMessage(String message, Severity severity) { - System.err.println(message); - } - - @Override - public void writeMessage(String message, Severity severity, Throwable t) { - System.err.println(message); - t.printStackTrace(System.err); - } - - private void print() { - Thread thread = Thread.currentThread(); - long id = thread.getId(); - - if (line.get().isEmpty()) { - System.out.println(MessageFormat.format("{0} :: waiting", id)); - return; - } - - String line = this.line.get().peek(); - System.out.println(MessageFormat.format("{0} :: {1}", id, line).trim()); - } - - @Override - public void startReadingClass(String className) { - workingClass.get().push(className); - line.get().push("Decompiling " + className); - print(); - } - - @Override - public void startClass(String className) { - workingClass.get().push(className); - line.get().push("Decompiling " + className); - print(); - } - - @Override - public void startMethod(String methodName) { - // No need to print out methods - } - - @Override - public void endMethod() { - } - - @Override - public void endClass() { - line.get().pop(); - workingClass.get().pop(); - print(); - } - - @Override - public void startWriteClass(String className) { - line.get().push("Writing " + className); - print(); - } - - @Override - public void endWriteClass() { - line.get().pop(); - print(); - } - - @Override - public void endReadingClass() { - line.get().pop(); - workingClass.get().pop(); - print(); - } -} |