From 2f775b1c97c84271ce38d5d49169063b38a91c84 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Mon, 2 Dec 2019 13:29:50 +0000 Subject: [PATCH] parameters docs Co-authored-by: mentlerd --- .../task/fernflower/ForkedFFExecutor.java | 11 ++ .../task/fernflower/TinyJavadocProvider.java | 129 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 src/main/java/net/fabricmc/loom/task/fernflower/TinyJavadocProvider.java diff --git a/src/main/java/net/fabricmc/loom/task/fernflower/ForkedFFExecutor.java b/src/main/java/net/fabricmc/loom/task/fernflower/ForkedFFExecutor.java index b2374b3..b60de1c 100644 --- a/src/main/java/net/fabricmc/loom/task/fernflower/ForkedFFExecutor.java +++ b/src/main/java/net/fabricmc/loom/task/fernflower/ForkedFFExecutor.java @@ -36,6 +36,8 @@ 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; + /** * Entry point for Forked FernFlower task. * Takes one parameter, a single file, each line is treated as command line input. @@ -49,6 +51,7 @@ public class ForkedFFExecutor { File input = null; File output = null; File lineMap = null; + File mappings = null; List libraries = new ArrayList<>(); int numThreads = 0; @@ -82,6 +85,12 @@ public class ForkedFFExecutor { } 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 (arg.startsWith("-t=")) { numThreads = Integer.parseInt(arg.substring(3)); } else { @@ -96,7 +105,9 @@ public class ForkedFFExecutor { Objects.requireNonNull(input, "Input not set."); Objects.requireNonNull(output, "Output not set."); + Objects.requireNonNull(mappings, "Mappings not set."); + options.put(IFabricJavadocProvider.PROPERTY_NAME, new TinyJavadocProvider(mappings)); runFF(options, libraries, input, output, lineMap); } diff --git a/src/main/java/net/fabricmc/loom/task/fernflower/TinyJavadocProvider.java b/src/main/java/net/fabricmc/loom/task/fernflower/TinyJavadocProvider.java new file mode 100644 index 0000000..0e49d01 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/task/fernflower/TinyJavadocProvider.java @@ -0,0 +1,129 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 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.task.fernflower; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jetbrains.java.decompiler.struct.StructClass; +import org.jetbrains.java.decompiler.struct.StructField; +import org.jetbrains.java.decompiler.struct.StructMethod; + +import net.fabricmc.fernflower.api.IFabricJavadocProvider; +import net.fabricmc.mapping.tree.ClassDef; +import net.fabricmc.mapping.tree.FieldDef; +import net.fabricmc.mapping.tree.MethodDef; +import net.fabricmc.mapping.tree.ParameterDef; +import net.fabricmc.mapping.tree.TinyMappingFactory; +import net.fabricmc.mapping.tree.TinyTree; +import net.fabricmc.mappings.EntryTriple; + +public class TinyJavadocProvider implements IFabricJavadocProvider { + private final Map classes = new HashMap<>(); + private final Map fields = new HashMap<>(); + private final Map methods = new HashMap<>(); + + private final String namespace = "named"; + + public TinyJavadocProvider(File tinyFile) { + final TinyTree mappings = readMappings(tinyFile); + + for (ClassDef classDef : mappings.getClasses()) { + final String className = classDef.getName(namespace); + classes.put(className, classDef); + + for (FieldDef fieldDef : classDef.getFields()) { + fields.put(new EntryTriple(className, fieldDef.getName(namespace), fieldDef.getDescriptor(namespace)), fieldDef); + } + + for (MethodDef methodDef : classDef.getMethods()) { + methods.put(new EntryTriple(className, methodDef.getName(namespace), methodDef.getDescriptor(namespace)), methodDef); + } + } + } + + @Override + public String getClassDoc(StructClass structClass) { + ClassDef classDef = classes.get(structClass.qualifiedName); + return classDef != null ? classDef.getComment() : null; + } + + @Override + public String getFieldDoc(StructClass structClass, StructField structField) { + FieldDef fieldDef = fields.get(new EntryTriple(structClass.qualifiedName, structField.getName(), structField.getDescriptor())); + return fieldDef != null ? fieldDef.getComment() : null; + } + + @Override + public String getMethodDoc(StructClass structClass, StructMethod structMethod) { + MethodDef methodDef = methods.get(new EntryTriple(structClass.qualifiedName, structMethod.getName(), structMethod.getDescriptor())); + + if (methodDef != null) { + List parts = new ArrayList<>(); + + if (methodDef.getComment() != null) { + parts.add(methodDef.getComment()); + } + + boolean addedParam = false; + + for (ParameterDef param : methodDef.getParameters()) { + String comment = param.getComment(); + + if (comment != null) { + if (!addedParam && methodDef.getComment() != null) { + //Add a blank line before params when the method has a comment + parts.add(""); + addedParam = true; + } + + parts.add(String.format("@param %s %s", param.getName(namespace), comment)); + } + } + + if (parts.isEmpty()) { + return null; + } + + return String.join("\n", parts); + } + + return null; + } + + private static TinyTree readMappings(File input) { + try (BufferedReader reader = Files.newBufferedReader(input.toPath())) { + return TinyMappingFactory.loadWithDetection(reader); + } catch (IOException e) { + throw new RuntimeException("Failed to read mappings", e); + } + } +}