Don't linemap Forge's own classes in GenerateSourcesTask

This commit is contained in:
Juuz
2022-09-07 03:54:26 +03:00
parent 8076b417b2
commit 7690e46e29
9 changed files with 387 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.linemap;
import java.io.IOException;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
/**
* A line map visitor that filters entries based on the class name.
*
* <p>If the {@code filter} returns false for class, its declaration and
* all contained line entries will be skipped.
*
* @author Juuz
*/
public final class LineMapClassFilter extends LineMapVisitor {
private final Predicate<String> filter;
private boolean active = true;
public LineMapClassFilter(@Nullable LineMapVisitor next, Predicate<String> filter) {
super(next);
this.filter = filter;
}
@Override
public void visitClass(String name, int max, int maxDest) throws IOException {
active = filter.test(name);
if (active) {
super.visitClass(name, max, maxDest);
}
}
@Override
public void visitLine(int src, int dest) throws IOException {
if (active) {
super.visitLine(src, dest);
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.linemap;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
/**
* A reader for line map files that in the format of {@link net.fabricmc.loom.decompilers.LineNumberRemapper}.
* {@linkplain #accept Accepts} a {@link LineMapVisitor} that processes the contents.
*
* @author Juuz
*/
public final class LineMapReader implements Closeable {
private final BufferedReader reader;
public LineMapReader(BufferedReader reader) {
this.reader = reader;
}
public void accept(LineMapVisitor visitor) throws IOException {
String line;
while ((line = reader.readLine()) != null) {
if (line.isBlank()) continue;
String[] parts = line.trim().split("\t");
try {
if (!line.startsWith("\t")) {
visitor.visitClass(parts[0], Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
} else {
visitor.visitLine(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
}
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
throw new RuntimeException("Could not parse line: " + line, e);
}
}
}
@Override
public void close() throws IOException {
reader.close();
}
}

View File

@@ -0,0 +1,92 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.linemap;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.UnaryOperator;
import org.jetbrains.annotations.Nullable;
/**
* A visitor for line mapping files that can be read with {@link net.fabricmc.loom.decompilers.LineNumberRemapper}.
*
* <p>Delegates by default to a {@code next} visitor if it's not null, like ASM's {@code ClassVisitor}.
*
* @author Juuz
*/
public abstract class LineMapVisitor {
private final LineMapVisitor next;
public LineMapVisitor(@Nullable LineMapVisitor next) {
this.next = next;
}
/**
* Visits a class declaration.
*
* @param name the internal class name (e.g. {@code a/b/C$Nested})
* @param max the original maximum line number in the class
* @param maxDest the new maximum line number in the class
*/
public void visitClass(String name, int max, int maxDest) throws IOException {
if (next != null) {
next.visitClass(name, max, maxDest);
}
}
/**
* Visits a line in the {@linkplain #visitClass previously visited class}.
*
* @param src the original line number
* @param dest the mapped line number
*/
public void visitLine(int src, int dest) throws IOException {
if (next != null) {
next.visitLine(src, dest);
}
}
/**
* Processes a line mapping file using an arbitrary visitor.
*
* @param path the path to the line mapping file
* @param visitorFactory a factory that creates a "filtering" line map visitor
*/
public static void process(Path path, UnaryOperator<LineMapVisitor> visitorFactory) throws IOException {
StringWriter sw = new StringWriter();
LineMapWriter writer = new LineMapWriter(sw);
LineMapVisitor visitor = visitorFactory.apply(writer);
try (LineMapReader reader = new LineMapReader(Files.newBufferedReader(path, StandardCharsets.UTF_8))) {
reader.accept(visitor);
}
Files.writeString(path, sw.toString(), StandardCharsets.UTF_8);
}
}

View File

@@ -0,0 +1,63 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.linemap;
import java.io.Closeable;
import java.io.IOException;
import java.io.Writer;
/**
* A writer for line maps in the format of {@link net.fabricmc.loom.decompilers.LineNumberRemapper}.
*
* @author Juuz
*/
public final class LineMapWriter extends LineMapVisitor implements Closeable {
private final Writer writer;
public LineMapWriter(Writer writer) {
super(null);
this.writer = writer;
}
@Override
public void visitClass(String name, int max, int maxDest) throws IOException {
writer.append(name)
.append('\t').append(Integer.toString(max))
.append('\t').append(Integer.toString(maxDest))
.append('\n');
}
@Override
public void visitLine(int src, int dest) throws IOException {
writer.append('\t').append(Integer.toString(src))
.append('\t').append(Integer.toString(dest))
.append('\n');
}
@Override
public void close() throws IOException {
writer.close();
}
}

View File

@@ -70,6 +70,8 @@ import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor;
import net.fabricmc.loom.configuration.processors.ModJavadocProcessor;
import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper;
import net.fabricmc.loom.decompilers.LineNumberRemapper;
import net.fabricmc.loom.decompilers.linemap.LineMapClassFilter;
import net.fabricmc.loom.decompilers.linemap.LineMapVisitor;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.FileSystemUtil;
import net.fabricmc.loom.util.IOStringConsumer;
@@ -174,6 +176,9 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
}
params.getClassPath().setFrom(getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES));
// Architectury
params.getForge().set(getExtension().isForge());
});
try {
@@ -223,6 +228,9 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
RegularFileProperty getIPCPath();
ConfigurableFileCollection getClassPath();
// Architectury
Property<Boolean> getForge();
}
public abstract static class DecompileAction implements WorkAction<DecompileParams> {
@@ -287,6 +295,16 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
}
if (Files.exists(linemap)) {
if (getParameters().getForge().get()) {
try {
// Remove Forge classes from linemap
// TODO: We should instead not decompile Forge's classes at all
LineMapVisitor.process(linemap, next -> new LineMapClassFilter(next, name -> !name.startsWith("net/minecraftforge/")));
} catch (IOException e) {
throw new UncheckedIOException("Failed to process linemap", e);
}
}
try {
// Line map the actually jar used to run the game, not the one used to decompile
remapLineNumbers(metadata.logger(), runtimeJar, linemap, linemapJar);

View File

@@ -0,0 +1,59 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 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.test.unit
import net.fabricmc.loom.decompilers.linemap.LineMapClassFilter
import net.fabricmc.loom.decompilers.linemap.LineMapReader
import net.fabricmc.loom.decompilers.linemap.LineMapWriter
import spock.lang.Specification
class LineMapTest extends Specification {
LineMapReader reader = new LineMapReader(LineMapTest.getResourceAsStream('/linemap/input.lmap').newReader('UTF-8'))
private String readExpected(String name) {
return LineMapTest.getResourceAsStream("/linemap/${name}.lmap")
.getText('UTF-8')
.replace('\r\n', '\n')
}
def "roundtrip"() {
when:
def sw = new StringWriter()
reader.accept(new LineMapWriter(sw))
reader.close()
then:
sw.toString() == readExpected('simpleOutput')
}
def "filter"() {
when:
def sw = new StringWriter()
def writer = new LineMapWriter(sw)
reader.accept(new LineMapClassFilter(writer, { it.startsWith('test/nested/') }))
reader.close()
then:
sw.toString() == readExpected('filteredOutput')
}
}

View File

@@ -0,0 +1,4 @@
test/nested/C 3 5
2 3
4 5
test/nested/D 0 0

View File

@@ -0,0 +1,11 @@
test/A 3 4
1 2
test/B 1 1
1 1
test/nested/C 3 5
2 3
4 5
test/nested/D 0 0

View File

@@ -0,0 +1,8 @@
test/A 3 4
1 2
test/B 1 1
1 1
test/nested/C 3 5
2 3
4 5
test/nested/D 0 0