diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/CsrgMappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/CsrgMappingFormat.java new file mode 100644 index 0000000..70e4c51 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/CsrgMappingFormat.java @@ -0,0 +1,25 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.CsrgMappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.CsrgMappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum CsrgMappingFormat implements MappingFormat.Classified { + INSTANCE; + + @Override + public @NotNull String getName() { + return "csrg"; + } + + @Override + public @NotNull CsrgMappingProcessor getProcessor() { + return CsrgMappingProcessor.INSTANCE; + } + + @Override + public @NotNull CsrgMappingGenerator getGenerator() { + return CsrgMappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/MappingFormats.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/MappingFormats.java index 6b23736..08c269c 100644 --- a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/MappingFormats.java +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/MappingFormats.java @@ -18,160 +18,21 @@ package cn.maxpixel.mcdecompiler.mapping.format; -import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; -import cn.maxpixel.mcdecompiler.mapping.PairedMapping; -import cn.maxpixel.mcdecompiler.mapping.generator.MappingGenerator; -import cn.maxpixel.mcdecompiler.mapping.generator.MappingGenerators; -import cn.maxpixel.mcdecompiler.mapping.processor.MappingProcessor; -import cn.maxpixel.mcdecompiler.mapping.processor.MappingProcessors; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectSets; -import org.jetbrains.annotations.NotNull; import java.util.Objects; import java.util.Set; public final class MappingFormats { - public static final MappingFormat.Classified SRG = new MappingFormat.Classified<>() { - @Override - public @NotNull String getName() { - return "srg"; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.SRG; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.SRG; - } - }; - - public static final MappingFormat.Classified CSRG = new MappingFormat.Classified<>() { - @Override - public @NotNull String getName() { - return "csrg"; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.CSRG; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.CSRG; - } - }; - - public static final MappingFormat.Classified TSRG_V1 = new MappingFormat.Classified<>() { - @Override - public @NotNull String getName() { - return "tsrg-v1"; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.TSRG_V1; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.TSRG_V1; - } - }; - - public static final MappingFormat.Classified TSRG_V2 = new MappingFormat.Classified<>() { - @Override - public @NotNull String getName() { - return "tsrg-v2"; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.TSRG_V2; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.TSRG_V2; - } - }; - - public static final MappingFormat.Classified PROGUARD = new MappingFormat.Classified<>() { - @Override - public @NotNull String getName() { - return "proguard"; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.PROGUARD; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.PROGUARD; - } - }; - - public static final MappingFormat.Classified TINY_V1 = new MappingFormat.Classified<>() {// TODO: support properties - @Override - public @NotNull String getName() { - return "tiny-v1"; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.TINY_V1; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.TINY_V1; - } - }; - - public static final MappingFormat.Classified TINY_V2 = new MappingFormat.Classified<>() { - @Override - public @NotNull String getName() { - return "tiny-v2"; - } - - @Override - public char getCommentChar() { - return '\0'; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.TINY_V2; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.TINY_V2; - } - }; - - public static final MappingFormat.Classified PDME = new MappingFormat.Classified<>() { - @Override - public @NotNull String getName() { - return "pdme"; - } - - @Override - public @NotNull MappingProcessor.Classified getProcessor() { - return MappingProcessors.PDME; - } - - @Override - public @NotNull MappingGenerator.Classified getGenerator() { - return MappingGenerators.PDME; - } - }; + public static final SrgMappingFormat SRG = SrgMappingFormat.INSTANCE; + public static final CsrgMappingFormat CSRG = CsrgMappingFormat.INSTANCE; + public static final TsrgV1MappingFormat TSRG_V1 = TsrgV1MappingFormat.INSTANCE; + public static final TsrgV2MappingFormat TSRG_V2 = TsrgV2MappingFormat.INSTANCE; + public static final ProguardMappingFormat PROGUARD = ProguardMappingFormat.INSTANCE; + public static final TinyV1MappingFormat TINY_V1 = TinyV1MappingFormat.INSTANCE; + public static final TinyV2MappingFormat TINY_V2 = TinyV2MappingFormat.INSTANCE; + public static final PdmeMappingFormat PDME = PdmeMappingFormat.INSTANCE; private static final Object2ObjectOpenHashMap> MAPPING_FORMATS = new Object2ObjectOpenHashMap<>(); diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/PdmeMappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/PdmeMappingFormat.java new file mode 100644 index 0000000..eee1615 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/PdmeMappingFormat.java @@ -0,0 +1,25 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.PdmeMappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.PdmeMappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum PdmeMappingFormat implements MappingFormat.Classified { + INSTANCE; + + @Override + public @NotNull String getName() { + return "pdme"; + } + + @Override + public @NotNull PdmeMappingProcessor getProcessor() { + return PdmeMappingProcessor.INSTANCE; + } + + @Override + public @NotNull PdmeMappingGenerator getGenerator() { + return PdmeMappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/ProguardMappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/ProguardMappingFormat.java new file mode 100644 index 0000000..917ab93 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/ProguardMappingFormat.java @@ -0,0 +1,25 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.ProguardMappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.ProguardMappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum ProguardMappingFormat implements MappingFormat.Classified { + INSTANCE; + + @Override + public @NotNull String getName() { + return "proguard"; + } + + @Override + public @NotNull ProguardMappingProcessor getProcessor() { + return ProguardMappingProcessor.INSTANCE; + } + + @Override + public @NotNull ProguardMappingGenerator getGenerator() { + return ProguardMappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/SrgMappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/SrgMappingFormat.java new file mode 100644 index 0000000..de49851 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/SrgMappingFormat.java @@ -0,0 +1,25 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.SrgMappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.SrgMappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum SrgMappingFormat implements MappingFormat.Classified { + INSTANCE; + + @Override + public @NotNull String getName() { + return "srg"; + } + + @Override + public @NotNull SrgMappingProcessor getProcessor() { + return SrgMappingProcessor.INSTANCE; + } + + @Override + public @NotNull SrgMappingGenerator getGenerator() { + return SrgMappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TinyV1MappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TinyV1MappingFormat.java new file mode 100644 index 0000000..df3ceea --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TinyV1MappingFormat.java @@ -0,0 +1,25 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.TinyV1MappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.TinyV1MappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum TinyV1MappingFormat implements MappingFormat.Classified {// TODO: support properties + INSTANCE; + + @Override + public @NotNull String getName() { + return "tiny-v1"; + } + + @Override + public @NotNull TinyV1MappingProcessor getProcessor() { + return TinyV1MappingProcessor.INSTANCE; + } + + @Override + public @NotNull TinyV1MappingGenerator getGenerator() { + return TinyV1MappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TinyV2MappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TinyV2MappingFormat.java new file mode 100644 index 0000000..15b10eb --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TinyV2MappingFormat.java @@ -0,0 +1,30 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.TinyV2MappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.TinyV2MappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum TinyV2MappingFormat implements MappingFormat.Classified { + INSTANCE; + + @Override + public @NotNull String getName() { + return "tiny-v2"; + } + + @Override + public char getCommentChar() { + return '\0'; + } + + @Override + public @NotNull TinyV2MappingProcessor getProcessor() { + return TinyV2MappingProcessor.INSTANCE; + } + + @Override + public @NotNull TinyV2MappingGenerator getGenerator() { + return TinyV2MappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TsrgV1MappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TsrgV1MappingFormat.java new file mode 100644 index 0000000..21c32ed --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TsrgV1MappingFormat.java @@ -0,0 +1,25 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.TsrgV1MappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.TsrgV1MappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum TsrgV1MappingFormat implements MappingFormat.Classified { + INSTANCE; + + @Override + public @NotNull String getName() { + return "tsrg-v1"; + } + + @Override + public @NotNull TsrgV1MappingProcessor getProcessor() { + return TsrgV1MappingProcessor.INSTANCE; + } + + @Override + public @NotNull TsrgV1MappingGenerator getGenerator() { + return TsrgV1MappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TsrgV2MappingFormat.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TsrgV2MappingFormat.java new file mode 100644 index 0000000..bf97de1 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/format/TsrgV2MappingFormat.java @@ -0,0 +1,25 @@ +package cn.maxpixel.mcdecompiler.mapping.format; + +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.generator.TsrgV2MappingGenerator; +import cn.maxpixel.mcdecompiler.mapping.processor.TsrgV2MappingProcessor; +import org.jetbrains.annotations.NotNull; + +public enum TsrgV2MappingFormat implements MappingFormat.Classified { + INSTANCE; + + @Override + public @NotNull String getName() { + return "tsrg-v2"; + } + + @Override + public @NotNull TsrgV2MappingProcessor getProcessor() { + return TsrgV2MappingProcessor.INSTANCE; + } + + @Override + public @NotNull TsrgV2MappingGenerator getGenerator() { + return TsrgV2MappingGenerator.INSTANCE; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/CsrgMappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/CsrgMappingGenerator.java new file mode 100644 index 0000000..fe14f42 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/CsrgMappingGenerator.java @@ -0,0 +1,50 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum CsrgMappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.CSRG; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; + mappings.classes.parallelStream().forEach(cls -> { + PairedMapping classMapping = cls.mapping; + synchronized (lines) { + lines.add(classMapping.unmappedName + ' ' + classMapping.mappedName); + } + cls.getFields().parallelStream().forEach(field -> { + MappingUtil.checkOwner(field.getOwned(), cls); + synchronized (lines) { + lines.add(classMapping.unmappedName + ' ' + field.unmappedName + ' ' + field.mappedName); + } + }); + cls.getMethods().parallelStream().forEach(method -> { + String unmappedDesc = MappingUtil.Paired.checkSlimSrgMethod(cls, method, remapper); + synchronized (lines) { + lines.add(classMapping.unmappedName + ' ' + method.unmappedName + ' ' + + unmappedDesc + ' ' + method.mappedName); + } + }); + }); + mappings.packages.parallelStream().forEach(pkg -> { + synchronized (lines) { + lines.add(pkg.unmappedName + "/ " + pkg.mappedName + '/'); + } + }); + return lines; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/MappingGenerators.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/MappingGenerators.java deleted file mode 100644 index 584361a..0000000 --- a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/MappingGenerators.java +++ /dev/null @@ -1,473 +0,0 @@ -/* - * MinecraftDecompiler. A tool/library to deobfuscate and decompile jars. - * Copyright (C) 2019-2024 MaxPixelStudios(XiaoPangxie732) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package cn.maxpixel.mcdecompiler.mapping.generator; - -import cn.maxpixel.mcdecompiler.common.util.NamingUtil; -import cn.maxpixel.mcdecompiler.common.util.Utils; -import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; -import cn.maxpixel.mcdecompiler.mapping.PairedMapping; -import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; -import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; -import cn.maxpixel.mcdecompiler.mapping.component.*; -import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; -import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; -import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; -import cn.maxpixel.mcdecompiler.mapping.trait.AccessTransformationTrait; -import cn.maxpixel.mcdecompiler.mapping.trait.InheritanceTrait; -import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; -import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; -import cn.maxpixel.mcdecompiler.mapping.util.TinyUtil; -import it.unimi.dsi.fastutil.ints.IntIterator; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectList; - -import java.util.Locale; - -public interface MappingGenerators { - MappingGenerator.Classified SRG = new MappingGenerator.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.SRG; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; - mappings.classes.parallelStream().forEach(cls -> { - PairedMapping classMapping = cls.mapping; - synchronized (lines) { - lines.add("CL: " + classMapping.unmappedName + " " + classMapping.mappedName); - } - cls.getFields().parallelStream().forEach(field -> { - MappingUtil.checkOwner(field.getOwned(), cls); - synchronized (lines) { - lines.add("FD: " + classMapping.unmappedName + '/' + field.unmappedName + ' ' + - classMapping.mappedName + '/' + field.mappedName); - } - }); - cls.getMethods().parallelStream().forEach(method -> { - MappingUtil.checkOwner(method.getOwned(), cls); - String unmappedDesc, mappedDesc; - if (method.hasComponent(Descriptor.class)) { - unmappedDesc = method.getComponent(Descriptor.class).unmappedDescriptor; - if (method.hasComponent(Descriptor.Mapped.class)) - mappedDesc = method.getComponent(Descriptor.Mapped.class).mappedDescriptor; - else if (remapper != null) mappedDesc = remapper.mapMethodDesc(unmappedDesc); - else throw new UnsupportedOperationException(); - } else if (method.hasComponent(Descriptor.Mapped.class)) { - mappedDesc = method.getComponent(Descriptor.Mapped.class).mappedDescriptor; - if (remapper != null) unmappedDesc = remapper.unmapMethodDesc(mappedDesc); - else throw new UnsupportedOperationException(); - } else throw new UnsupportedOperationException(); - synchronized (lines) { - lines.add("MD: " + classMapping.unmappedName + '/' + method.unmappedName + ' ' + unmappedDesc + ' ' + - classMapping.mappedName + '/' + method.mappedName + ' ' + mappedDesc); - } - }); - }); - mappings.packages.parallelStream().forEach(pkg -> { - synchronized(lines) { - lines.add("PK: " + pkg.unmappedName + ' ' + pkg.mappedName); - } - }); - return lines; - } - }; - - MappingGenerator.Classified CSRG = new MappingGenerator.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.CSRG; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; - mappings.classes.parallelStream().forEach(cls -> { - PairedMapping classMapping = cls.mapping; - synchronized (lines) { - lines.add(classMapping.unmappedName + ' ' + classMapping.mappedName); - } - cls.getFields().parallelStream().forEach(field -> { - MappingUtil.checkOwner(field.getOwned(), cls); - synchronized (lines) { - lines.add(classMapping.unmappedName + ' ' + field.unmappedName + ' ' + field.mappedName); - } - }); - cls.getMethods().parallelStream().forEach(method -> { - String unmappedDesc = MappingUtil.Paired.checkSlimSrgMethod(cls, method, remapper); - synchronized (lines) { - lines.add(classMapping.unmappedName + ' ' + method.unmappedName + ' ' + - unmappedDesc + ' ' + method.mappedName); - } - }); - }); - mappings.packages.parallelStream().forEach(pkg -> { - synchronized (lines) { - lines.add(pkg.unmappedName + "/ " + pkg.mappedName + '/'); - } - }); - return lines; - } - }; - - MappingGenerator.Classified TSRG_V1 = new MappingGenerator.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.TSRG_V1; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; - for (ClassMapping cls : mappings.classes) { - lines.add(cls.mapping.unmappedName + ' ' + cls.mapping.mappedName); - cls.getFields().parallelStream().forEach(field -> { - MappingUtil.checkOwner(field.getOwned(), cls); - synchronized (lines) { - lines.add('\t' + field.unmappedName + ' ' + field.mappedName); - } - }); - cls.getMethods().parallelStream().forEach(method -> { - String unmappedDesc = MappingUtil.Paired.checkSlimSrgMethod(cls, method, remapper); - synchronized (lines) { - lines.add('\t' + method.unmappedName + ' ' + unmappedDesc + ' ' + method.mappedName); - } - }); - } - mappings.packages.parallelStream().forEach(pkg -> { - synchronized (lines) { - lines.add(pkg.unmappedName + "/ " + pkg.mappedName + '/'); - } - }); - return lines; - } - - }; - - MappingGenerator.Classified TSRG_V2 = new MappingGenerator.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.TSRG_V2; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; - var namespaces = mappings.getTrait(NamespacedTrait.class).namespaces; - String namespace0 = namespaces.first(); - lines.add("tsrg2 " + String.join(" ", namespaces)); - for (ClassMapping cls : mappings.classes) { - lines.add(NamingUtil.concatNamespaces(namespaces, cls.mapping::getName, " ")); - cls.getFields().parallelStream().forEach(field -> { - MappingUtil.checkOwner(field.getOwned(), cls); - String names = NamingUtil.concatNamespaces(namespaces, field::getName, " "); - if (field.hasComponent(Descriptor.Namespaced.class)) synchronized (lines) { - genDescriptorLine(lines, namespace0, field, names); - } else synchronized (lines) { - lines.add('\t' + names); - } - }); - cls.getMethods().parallelStream().forEach(method -> { - if (!method.hasComponent(Descriptor.Namespaced.class)) throw new UnsupportedOperationException(); - MappingUtil.checkOwner(method.getOwned(), cls); - synchronized (lines) { - genDescriptorLine(lines, namespace0, method, NamingUtil.concatNamespaces(namespaces, - method::getName, " ")); - var si = method.getComponent(StaticIdentifiable.class); - if (si != null && si.isStatic) lines.add("\t\tstatic"); - if (method.hasComponent(LocalVariableTable.Namespaced.class)) { - LocalVariableTable.Namespaced lvt = method.getComponent(LocalVariableTable.Namespaced.class); - lvt.getLocalVariableIndexes().forEach(index -> { - String names = NamingUtil.concatNamespaces(namespaces, namespace -> { - String name = lvt.getLocalVariable(index).getName(namespace); - if(name != null && name.isBlank()) return "o"; - return name; - }, " "); - lines.add("\t\t" + index + ' ' + names); - }); - } - } - }); - } - mappings.packages.parallelStream().forEach(pkg -> { - synchronized (lines) { - lines.add(NamingUtil.concatNamespaces(namespaces, pkg::getName, " ")); - } - }); - return lines; - } - - private static void genDescriptorLine(ObjectArrayList lines, String namespace0, NamespacedMapping method, String names) { - Descriptor.Namespaced desc = method.getComponent(Descriptor.Namespaced.class); - if (!namespace0.equals(desc.descriptorNamespace)) throw new IllegalArgumentException(); - int i = names.indexOf(' '); - lines.add('\t' + names.substring(0, i + 1) + desc.unmappedDescriptor + names.substring(i)); - } - }; - - MappingGenerator.Classified PROGUARD = new MappingGenerator.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.PROGUARD; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty()) return lines; - for (ClassMapping cls : mappings.classes) { - PairedMapping mapping = cls.mapping; - lines.add(NamingUtil.asJavaName(mapping.mappedName) + " -> " + - NamingUtil.asJavaName(mapping.unmappedName) + ':'); - cls.getFields().parallelStream().forEach(field -> { - MappingUtil.checkOwner(field.getOwned(), cls); - String mappedDesc; - if (field.hasComponent(Descriptor.Mapped.class)) { - mappedDesc = field.getComponent(Descriptor.Mapped.class).mappedDescriptor; - } else if (remapper != null && field.hasComponent(Descriptor.class)) { - mappedDesc = remapper.mapDesc(field.getComponent(Descriptor.class).unmappedDescriptor); - } else throw new UnsupportedOperationException(); - synchronized (lines) { - lines.add(" " + NamingUtil.descriptor2Java(mappedDesc) + ' ' + field.mappedName + - " -> " + field.unmappedName); - } - }); - cls.getMethods().parallelStream().forEach(method -> { - MappingUtil.checkOwner(method.getOwned(), cls); - String mappedDesc; - if (method.hasComponent(Descriptor.Mapped.class)) { - mappedDesc = method.getComponent(Descriptor.Mapped.class).mappedDescriptor; - } else if (remapper != null && method.hasComponent(Descriptor.class)) { - mappedDesc = remapper.mapMethodDesc(method.getComponent(Descriptor.class).unmappedDescriptor); - } else throw new UnsupportedOperationException(); -// String args = String.join(",", Utils.mapArray(Type.getArgumentTypes(mappedDesc), -// String[]::new, Type::getClassName)); - StringBuilder args = new StringBuilder(mappedDesc.length()); - int end = mappedDesc.lastIndexOf(')'), last = 1; - for (int i = 1; i < end; i++) { - char c = mappedDesc.charAt(i); - if (c != '[') { - if (c == 'L') i = mappedDesc.indexOf(';', i); - args.append(NamingUtil.descriptor2Java(mappedDesc.substring(last, last = i + 1))).append(','); - } - } - args.deleteCharAt(args.length() - 1); - String ret = NamingUtil.descriptor2Java(mappedDesc.substring(end + 1)); - if (method.hasComponent(LineNumber.class)) { - LineNumber lineNumber = method.getComponent(LineNumber.class); - synchronized (lines) { - lines.add(" " + lineNumber.startLineNumber + ':' + lineNumber.endLineNumber + ':' + - ret + ' ' + method.mappedName + '(' + args + ") -> " + method.unmappedName); - } - } else synchronized (lines) { - lines.add(" " + ret + ' ' + method.mappedName + '(' + args + ") -> " + method.unmappedName); - } - }); - } - return lines; - } - }; - - MappingGenerator.Classified TINY_V1 = new MappingGenerator.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.TINY_V1; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty()) return lines; - var namespaces = mappings.getTrait(NamespacedTrait.class).namespaces; - String namespace0 = namespaces.first(); - lines.add("v1\t" + String.join("\t", namespaces)); - mappings.classes.parallelStream().forEach(cls -> { - NamespacedMapping classMapping = cls.mapping; - synchronized (lines) { - lines.add("CLASS\t" + NamingUtil.concatNamespaces(namespaces, classMapping::getName, "\t")); - } - cls.getFields().parallelStream().forEach(field -> { - String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, field); - synchronized (lines) { - lines.add("FIELD\t" + classMapping.getName(namespace0) + '\t' + desc + '\t' + - NamingUtil.concatNamespaces(namespaces, field::getName, "\t")); - } - }); - cls.getMethods().parallelStream().forEach(method -> { - String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, method); - synchronized (lines) { - lines.add("METHOD\t" + classMapping.getName(namespace0) + '\t' + desc + '\t' + - NamingUtil.concatNamespaces(namespaces, method::getName, "\t")); - } - }); - }); - return lines; - } - }; - - MappingGenerator.Classified TINY_V2 = new MappingGenerator.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.TINY_V2; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty()) return lines; - var namespaces = mappings.getTrait(NamespacedTrait.class).namespaces; - String namespace0 = namespaces.first(); - lines.add("tiny\t2\t0\t" + String.join("\t", namespaces)); - for (ClassMapping cls : mappings.classes) { - lines.add("c\t" + NamingUtil.concatNamespaces(namespaces, cls.mapping::getName, "\t")); - cls.getFields().parallelStream().forEach(field -> { - String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, field); - synchronized (lines) { - lines.add("\tf\t" + desc + '\t' + NamingUtil.concatNamespaces(namespaces, field::getName, "\t")); - if (field.hasComponent(Documented.class)) { - String doc = field.getComponent(Documented.class).getContentString(); - if (!doc.isBlank()) lines.add("\t\tc\t" + TinyUtil.escape(doc)); - } - } - }); - cls.getMethods().parallelStream().forEach(method -> { - String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, method); - synchronized (lines) { - lines.add("\tm\t" + desc + '\t' + NamingUtil.concatNamespaces(namespaces, method::getName, "\t")); - if (method.hasComponent(Documented.class)) { - String doc = method.getComponent(Documented.class).getContentString(); - if (!doc.isBlank()) lines.add("\t\tc\t" + TinyUtil.escape(doc)); - } - if (method.hasComponent(LocalVariableTable.Namespaced.class)) { - LocalVariableTable.Namespaced lvt = method.getComponent(LocalVariableTable.Namespaced.class); - boolean omittedThis = method.hasComponent(StaticIdentifiable.class) && - !method.getComponent(StaticIdentifiable.class).isStatic; - lvt.getLocalVariableIndexes().forEach(index -> { - NamespacedMapping localVariable = lvt.getLocalVariable(omittedThis ? index + 1 : index); - String names = NamingUtil.concatNamespaces(namespaces, namespace -> { - String name = localVariable.getName(namespace); - if(name == null || name.isBlank()) return ""; - return name; - }, "\t"); - lines.add("\t\tp\t" + index + '\t' + names); - if (localVariable.hasComponent(Documented.class)) { - String doc = localVariable.getComponent(Documented.class).getContentString(); - if (!doc.isBlank()) lines.add("\t\t\tc\t" + TinyUtil.escape(doc)); - } - }); - } - } - }); - } - return lines; - } - }; - - MappingGenerator.Classified PDME = new MappingGenerator.Classified<>() { - private static final String PARA = "¶"; - private static final String NIL = "nil"; - - @Override - public MappingFormat> getFormat() { - return MappingFormats.PDME; - } - - @Override - public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { - ObjectArrayList lines = new ObjectArrayList<>(); - if (mappings.classes.isEmpty()) return lines; - mappings.classes.parallelStream().forEach(classMapping -> { - PairedMapping cm = classMapping.mapping; - String unmapped = cm.getUnmappedName().replace('/', '.'); - String mapped = cm.getMappedName().replace('/', '.'); - String clsDoc = getDoc(cm); - synchronized (lines) { - lines.add(String.join(PARA, "Class", unmapped, mapped, NIL, NIL, clsDoc)); - } - classMapping.getFields().parallelStream().forEach(field -> { - String desc = field.getComponent(Descriptor.class).unmappedDescriptor; - String unmappedName = unmapped + '.' + field.getUnmappedName() + ':' + desc; - String doc = getDoc(field); - synchronized (lines) { - lines.add(String.join("Var", unmappedName, field.mappedName, NIL, NIL, doc)); - } - }); - classMapping.getMethods().parallelStream().forEach(method -> { - String desc = method.getComponent(Descriptor.class).unmappedDescriptor; - String unmappedName = unmapped + '.' + method.getUnmappedName() + desc; - String doc = getDoc(method); - synchronized (lines) { - lines.add(String.join(PARA, "Def", unmappedName, method.mappedName, NIL, NIL, doc)); - } - if (method.hasComponent(LocalVariableTable.Paired.class)) { - LocalVariableTable.Paired lvt = method.getComponent(LocalVariableTable.Paired.class); - IntIterator it = lvt.getLocalVariableIndexes().iterator(); - while (it.hasNext()) { - int index = it.nextInt(); - PairedMapping loc = lvt.getLocalVariable(index); - String line = String.join( - PARA, - "Param", - nilWhenBlank(loc.unmappedName), - nilWhenBlank(loc.mappedName), - unmappedName, - String.valueOf(index), - getDoc(loc) - ); - synchronized (lines) { - lines.add(line); - } - } - } - }); - }); - if (mappings.hasTrait(InheritanceTrait.class)) { - mappings.getTrait(InheritanceTrait.class).getMap().forEach((k, v) -> { - if (!v.isEmpty()) lines.add(String.join(PARA, "Include", k.replace('/', '.'), - String.join(",", Utils.mapArray(v.toArray(), String[]::new, - s -> ((String) s).replace('/', '.'))), NIL, NIL, "")); - }); - } - if (mappings.hasTrait(AccessTransformationTrait.class)) { - var map = mappings.getTrait(AccessTransformationTrait.class).getMap(); - map.object2IntEntrySet().fastForEach(e -> lines.add(String.join(PARA, "AccessFlag", - e.getKey().replace('/', '.'), formatHex(e.getIntValue()), NIL, NIL, ""))); - } - return lines; - } - - private static String nilWhenBlank(String s) { - return s == null || s.isBlank() ? NIL : s; - } - - private static String getDoc(PairedMapping m) { - return m.getComponentOptional(Documented.class).map(Documented::getContentString).orElse(""); - } - - private static String formatHex(int value) { - String s = Integer.toHexString(value).toUpperCase(Locale.ENGLISH); - return "0x" + "0".repeat(4 - s.length()) + s; - } - }; -} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/PdmeMappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/PdmeMappingGenerator.java new file mode 100644 index 0000000..1e016d7 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/PdmeMappingGenerator.java @@ -0,0 +1,107 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.common.util.Utils; +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.Descriptor; +import cn.maxpixel.mcdecompiler.mapping.component.Documented; +import cn.maxpixel.mcdecompiler.mapping.component.LocalVariableTable; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.trait.AccessTransformationTrait; +import cn.maxpixel.mcdecompiler.mapping.trait.InheritanceTrait; +import it.unimi.dsi.fastutil.ints.IntIterator; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +import java.util.Locale; + +public enum PdmeMappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + private static final String PARA = "¶"; + private static final String NIL = "nil"; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.PDME; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty()) return lines; + mappings.classes.parallelStream().forEach(classMapping -> { + PairedMapping cm = classMapping.mapping; + String unmapped = cm.getUnmappedName().replace('/', '.'); + String mapped = cm.getMappedName().replace('/', '.'); + String clsDoc = getDoc(cm); + synchronized (lines) { + lines.add(String.join(PARA, "Class", unmapped, mapped, NIL, NIL, clsDoc)); + } + classMapping.getFields().parallelStream().forEach(field -> { + String desc = field.getComponent(Descriptor.class).unmappedDescriptor; + String unmappedName = unmapped + '.' + field.getUnmappedName() + ':' + desc; + String doc = getDoc(field); + synchronized (lines) { + lines.add(String.join("Var", unmappedName, field.mappedName, NIL, NIL, doc)); + } + }); + classMapping.getMethods().parallelStream().forEach(method -> { + String desc = method.getComponent(Descriptor.class).unmappedDescriptor; + String unmappedName = unmapped + '.' + method.getUnmappedName() + desc; + String doc = getDoc(method); + synchronized (lines) { + lines.add(String.join(PARA, "Def", unmappedName, method.mappedName, NIL, NIL, doc)); + } + if (method.hasComponent(LocalVariableTable.Paired.class)) { + LocalVariableTable.Paired lvt = method.getComponent(LocalVariableTable.Paired.class); + IntIterator it = lvt.getLocalVariableIndexes().iterator(); + while (it.hasNext()) { + int index = it.nextInt(); + PairedMapping loc = lvt.getLocalVariable(index); + String line = String.join( + PARA, + "Param", + nilWhenBlank(loc.unmappedName), + nilWhenBlank(loc.mappedName), + unmappedName, + String.valueOf(index), + getDoc(loc) + ); + synchronized (lines) { + lines.add(line); + } + } + } + }); + }); + if (mappings.hasTrait(InheritanceTrait.class)) { + mappings.getTrait(InheritanceTrait.class).getMap().forEach((k, v) -> { + if (!v.isEmpty()) lines.add(String.join(PARA, "Include", k.replace('/', '.'), + String.join(",", Utils.mapArray(v.toArray(), String[]::new, + s -> ((String) s).replace('/', '.'))), NIL, NIL, "")); + }); + } + if (mappings.hasTrait(AccessTransformationTrait.class)) { + var map = mappings.getTrait(AccessTransformationTrait.class).getMap(); + map.object2IntEntrySet().fastForEach(e -> lines.add(String.join(PARA, "AccessFlag", + e.getKey().replace('/', '.'), formatHex(e.getIntValue()), NIL, NIL, ""))); + } + return lines; + } + + private static String nilWhenBlank(String s) { + return s == null || s.isBlank() ? NIL : s; + } + + private static String getDoc(PairedMapping m) { + return m.getComponentOptional(Documented.class).map(Documented::getContentString).orElse(""); + } + + private static String formatHex(int value) { + String s = Integer.toHexString(value).toUpperCase(Locale.ENGLISH); + return "0x" + "0".repeat(4 - s.length()) + s; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/ProguardMappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/ProguardMappingGenerator.java new file mode 100644 index 0000000..2752365 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/ProguardMappingGenerator.java @@ -0,0 +1,79 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.common.util.NamingUtil; +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.Descriptor; +import cn.maxpixel.mcdecompiler.mapping.component.LineNumber; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum ProguardMappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.PROGUARD; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty()) return lines; + for (ClassMapping cls : mappings.classes) { + PairedMapping mapping = cls.mapping; + lines.add(NamingUtil.asJavaName(mapping.mappedName) + " -> " + + NamingUtil.asJavaName(mapping.unmappedName) + ':'); + cls.getFields().parallelStream().forEach(field -> { + MappingUtil.checkOwner(field.getOwned(), cls); + String mappedDesc; + if (field.hasComponent(Descriptor.Mapped.class)) { + mappedDesc = field.getComponent(Descriptor.Mapped.class).mappedDescriptor; + } else if (remapper != null && field.hasComponent(Descriptor.class)) { + mappedDesc = remapper.mapDesc(field.getComponent(Descriptor.class).unmappedDescriptor); + } else throw new UnsupportedOperationException(); + synchronized (lines) { + lines.add(" " + NamingUtil.descriptor2Java(mappedDesc) + ' ' + field.mappedName + + " -> " + field.unmappedName); + } + }); + cls.getMethods().parallelStream().forEach(method -> { + MappingUtil.checkOwner(method.getOwned(), cls); + String mappedDesc; + if (method.hasComponent(Descriptor.Mapped.class)) { + mappedDesc = method.getComponent(Descriptor.Mapped.class).mappedDescriptor; + } else if (remapper != null && method.hasComponent(Descriptor.class)) { + mappedDesc = remapper.mapMethodDesc(method.getComponent(Descriptor.class).unmappedDescriptor); + } else throw new UnsupportedOperationException(); +// String args = String.join(",", Utils.mapArray(Type.getArgumentTypes(mappedDesc), +// String[]::new, Type::getClassName)); + StringBuilder args = new StringBuilder(mappedDesc.length()); + int end = mappedDesc.lastIndexOf(')'), last = 1; + for (int i = 1; i < end; i++) { + char c = mappedDesc.charAt(i); + if (c != '[') { + if (c == 'L') i = mappedDesc.indexOf(';', i); + args.append(NamingUtil.descriptor2Java(mappedDesc.substring(last, last = i + 1))).append(','); + } + } + args.deleteCharAt(args.length() - 1); + String ret = NamingUtil.descriptor2Java(mappedDesc.substring(end + 1)); + if (method.hasComponent(LineNumber.class)) { + LineNumber lineNumber = method.getComponent(LineNumber.class); + synchronized (lines) { + lines.add(" " + lineNumber.startLineNumber + ':' + lineNumber.endLineNumber + ':' + + ret + ' ' + method.mappedName + '(' + args + ") -> " + method.unmappedName); + } + } else synchronized (lines) { + lines.add(" " + ret + ' ' + method.mappedName + '(' + args + ") -> " + method.unmappedName); + } + }); + } + return lines; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/SrgMappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/SrgMappingGenerator.java new file mode 100644 index 0000000..2066cc9 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/SrgMappingGenerator.java @@ -0,0 +1,64 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.Descriptor; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum SrgMappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.SRG; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; + mappings.classes.parallelStream().forEach(cls -> { + PairedMapping classMapping = cls.mapping; + synchronized (lines) { + lines.add("CL: " + classMapping.unmappedName + " " + classMapping.mappedName); + } + cls.getFields().parallelStream().forEach(field -> { + MappingUtil.checkOwner(field.getOwned(), cls); + synchronized (lines) { + lines.add("FD: " + classMapping.unmappedName + '/' + field.unmappedName + ' ' + + classMapping.mappedName + '/' + field.mappedName); + } + }); + cls.getMethods().parallelStream().forEach(method -> { + MappingUtil.checkOwner(method.getOwned(), cls); + String unmappedDesc, mappedDesc; + if (method.hasComponent(Descriptor.class)) { + unmappedDesc = method.getComponent(Descriptor.class).unmappedDescriptor; + if (method.hasComponent(Descriptor.Mapped.class)) + mappedDesc = method.getComponent(Descriptor.Mapped.class).mappedDescriptor; + else if (remapper != null) mappedDesc = remapper.mapMethodDesc(unmappedDesc); + else throw new UnsupportedOperationException(); + } else if (method.hasComponent(Descriptor.Mapped.class)) { + mappedDesc = method.getComponent(Descriptor.Mapped.class).mappedDescriptor; + if (remapper != null) unmappedDesc = remapper.unmapMethodDesc(mappedDesc); + else throw new UnsupportedOperationException(); + } else throw new UnsupportedOperationException(); + synchronized (lines) { + lines.add("MD: " + classMapping.unmappedName + '/' + method.unmappedName + ' ' + unmappedDesc + ' ' + + classMapping.mappedName + '/' + method.mappedName + ' ' + mappedDesc); + } + }); + }); + mappings.packages.parallelStream().forEach(pkg -> { + synchronized(lines) { + lines.add("PK: " + pkg.unmappedName + ' ' + pkg.mappedName); + } + }); + return lines; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TinyV1MappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TinyV1MappingGenerator.java new file mode 100644 index 0000000..b40e5ae --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TinyV1MappingGenerator.java @@ -0,0 +1,51 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.common.util.NamingUtil; +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum TinyV1MappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TINY_V1; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty()) return lines; + var namespaces = mappings.getTrait(NamespacedTrait.class).namespaces; + String namespace0 = namespaces.first(); + lines.add("v1\t" + String.join("\t", namespaces)); + mappings.classes.parallelStream().forEach(cls -> { + NamespacedMapping classMapping = cls.mapping; + synchronized (lines) { + lines.add("CLASS\t" + NamingUtil.concatNamespaces(namespaces, classMapping::getName, "\t")); + } + cls.getFields().parallelStream().forEach(field -> { + String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, field); + synchronized (lines) { + lines.add("FIELD\t" + classMapping.getName(namespace0) + '\t' + desc + '\t' + + NamingUtil.concatNamespaces(namespaces, field::getName, "\t")); + } + }); + cls.getMethods().parallelStream().forEach(method -> { + String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, method); + synchronized (lines) { + lines.add("METHOD\t" + classMapping.getName(namespace0) + '\t' + desc + '\t' + + NamingUtil.concatNamespaces(namespaces, method::getName, "\t")); + } + }); + }); + return lines; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TinyV2MappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TinyV2MappingGenerator.java new file mode 100644 index 0000000..251bf4b --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TinyV2MappingGenerator.java @@ -0,0 +1,77 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.common.util.NamingUtil; +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.Documented; +import cn.maxpixel.mcdecompiler.mapping.component.LocalVariableTable; +import cn.maxpixel.mcdecompiler.mapping.component.StaticIdentifiable; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import cn.maxpixel.mcdecompiler.mapping.util.TinyUtil; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum TinyV2MappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TINY_V2; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty()) return lines; + var namespaces = mappings.getTrait(NamespacedTrait.class).namespaces; + String namespace0 = namespaces.first(); + lines.add("tiny\t2\t0\t" + String.join("\t", namespaces)); + for (ClassMapping cls : mappings.classes) { + lines.add("c\t" + NamingUtil.concatNamespaces(namespaces, cls.mapping::getName, "\t")); + cls.getFields().parallelStream().forEach(field -> { + String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, field); + synchronized (lines) { + lines.add("\tf\t" + desc + '\t' + NamingUtil.concatNamespaces(namespaces, field::getName, "\t")); + if (field.hasComponent(Documented.class)) { + String doc = field.getComponent(Documented.class).getContentString(); + if (!doc.isBlank()) lines.add("\t\tc\t" + TinyUtil.escape(doc)); + } + } + }); + cls.getMethods().parallelStream().forEach(method -> { + String desc = MappingUtil.Namespaced.checkTiny(namespace0, cls, method); + synchronized (lines) { + lines.add("\tm\t" + desc + '\t' + NamingUtil.concatNamespaces(namespaces, method::getName, "\t")); + if (method.hasComponent(Documented.class)) { + String doc = method.getComponent(Documented.class).getContentString(); + if (!doc.isBlank()) lines.add("\t\tc\t" + TinyUtil.escape(doc)); + } + if (method.hasComponent(LocalVariableTable.Namespaced.class)) { + LocalVariableTable.Namespaced lvt = method.getComponent(LocalVariableTable.Namespaced.class); + boolean omittedThis = method.hasComponent(StaticIdentifiable.class) && + !method.getComponent(StaticIdentifiable.class).isStatic; + lvt.getLocalVariableIndexes().forEach(index -> { + NamespacedMapping localVariable = lvt.getLocalVariable(omittedThis ? index + 1 : index); + String names = NamingUtil.concatNamespaces(namespaces, namespace -> { + String name = localVariable.getName(namespace); + if(name == null || name.isBlank()) return ""; + return name; + }, "\t"); + lines.add("\t\tp\t" + index + '\t' + names); + if (localVariable.hasComponent(Documented.class)) { + String doc = localVariable.getComponent(Documented.class).getContentString(); + if (!doc.isBlank()) lines.add("\t\t\tc\t" + TinyUtil.escape(doc)); + } + }); + } + } + }); + } + return lines; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TsrgV1MappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TsrgV1MappingGenerator.java new file mode 100644 index 0000000..d29a691 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TsrgV1MappingGenerator.java @@ -0,0 +1,47 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum TsrgV1MappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TSRG_V1; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; + for (ClassMapping cls : mappings.classes) { + lines.add(cls.mapping.unmappedName + ' ' + cls.mapping.mappedName); + cls.getFields().parallelStream().forEach(field -> { + MappingUtil.checkOwner(field.getOwned(), cls); + synchronized (lines) { + lines.add('\t' + field.unmappedName + ' ' + field.mappedName); + } + }); + cls.getMethods().parallelStream().forEach(method -> { + String unmappedDesc = MappingUtil.Paired.checkSlimSrgMethod(cls, method, remapper); + synchronized (lines) { + lines.add('\t' + method.unmappedName + ' ' + unmappedDesc + ' ' + method.mappedName); + } + }); + } + mappings.packages.parallelStream().forEach(pkg -> { + synchronized (lines) { + lines.add(pkg.unmappedName + "/ " + pkg.mappedName + '/'); + } + }); + return lines; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TsrgV2MappingGenerator.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TsrgV2MappingGenerator.java new file mode 100644 index 0000000..a9cf324 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/generator/TsrgV2MappingGenerator.java @@ -0,0 +1,80 @@ +package cn.maxpixel.mcdecompiler.mapping.generator; + +import cn.maxpixel.mcdecompiler.common.util.NamingUtil; +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.Descriptor; +import cn.maxpixel.mcdecompiler.mapping.component.LocalVariableTable; +import cn.maxpixel.mcdecompiler.mapping.component.StaticIdentifiable; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.remapper.ClassifiedMappingRemapper; +import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum TsrgV2MappingGenerator implements MappingGenerator.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TSRG_V2; + } + + @Override + public ObjectList generate(ClassifiedMapping mappings, ClassifiedMappingRemapper remapper) { + ObjectArrayList lines = new ObjectArrayList<>(); + if (mappings.classes.isEmpty() && mappings.packages.isEmpty()) return lines; + var namespaces = mappings.getTrait(NamespacedTrait.class).namespaces; + String namespace0 = namespaces.first(); + lines.add("tsrg2 " + String.join(" ", namespaces)); + for (ClassMapping cls : mappings.classes) { + lines.add(NamingUtil.concatNamespaces(namespaces, cls.mapping::getName, " ")); + cls.getFields().parallelStream().forEach(field -> { + MappingUtil.checkOwner(field.getOwned(), cls); + String names = NamingUtil.concatNamespaces(namespaces, field::getName, " "); + if (field.hasComponent(Descriptor.Namespaced.class)) synchronized (lines) { + genDescriptorLine(lines, namespace0, field, names); + } else synchronized (lines) { + lines.add('\t' + names); + } + }); + cls.getMethods().parallelStream().forEach(method -> { + if (!method.hasComponent(Descriptor.Namespaced.class)) throw new UnsupportedOperationException(); + MappingUtil.checkOwner(method.getOwned(), cls); + synchronized (lines) { + genDescriptorLine(lines, namespace0, method, NamingUtil.concatNamespaces(namespaces, + method::getName, " ")); + var si = method.getComponent(StaticIdentifiable.class); + if (si != null && si.isStatic) lines.add("\t\tstatic"); + if (method.hasComponent(LocalVariableTable.Namespaced.class)) { + LocalVariableTable.Namespaced lvt = method.getComponent(LocalVariableTable.Namespaced.class); + lvt.getLocalVariableIndexes().forEach(index -> { + String names = NamingUtil.concatNamespaces(namespaces, namespace -> { + String name = lvt.getLocalVariable(index).getName(namespace); + if(name != null && name.isBlank()) return "o"; + return name; + }, " "); + lines.add("\t\t" + index + ' ' + names); + }); + } + } + }); + } + mappings.packages.parallelStream().forEach(pkg -> { + synchronized (lines) { + lines.add(NamingUtil.concatNamespaces(namespaces, pkg::getName, " ")); + } + }); + return lines; + } + + private static void genDescriptorLine(ObjectArrayList lines, String namespace0, NamespacedMapping method, String names) { + Descriptor.Namespaced desc = method.getComponent(Descriptor.Namespaced.class); + if (!namespace0.equals(desc.descriptorNamespace)) throw new IllegalArgumentException(); + int i = names.indexOf(' '); + lines.add('\t' + names.substring(0, i + 1) + desc.unmappedDescriptor + names.substring(i)); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/CsrgMappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/CsrgMappingProcessor.java new file mode 100644 index 0000000..eea46fd --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/CsrgMappingProcessor.java @@ -0,0 +1,60 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum CsrgMappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.CSRG; + } + + @Override + public ClassifiedMapping process(ObjectList content) { + ClassifiedMapping mappings = new ClassifiedMapping<>(); + Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: unmapped name + content.parallelStream().forEach(s -> { + String[] sa = MappingUtil.split(s, ' '); + switch (sa.length) { + case 2 -> { // Class / Package + if (sa[0].charAt(sa[0].length() - 1) == '/') synchronized (mappings.packages) { + mappings.packages.add(new PairedMapping(sa[0].substring(0, sa[0].length() - 1), + sa[1].substring(0, sa[1].length() - 1))); + } else { + ClassMapping classMapping = new ClassMapping<>(new PairedMapping(sa[0], sa[1])); + synchronized (classes) { + classes.merge(classMapping.mapping.unmappedName, classMapping, (o, n) -> { + n.addFields(o.getFields()); + n.addMethods(o.getMethods()); + return n; + }); + } + } + } + case 3 -> { // Field + PairedMapping fieldMapping = MappingUtil.Paired.o(sa[1], sa[2]); + synchronized (classes) { + classes.computeIfAbsent(sa[0], MappingUtil.Paired.COMPUTE_DEFAULT_CLASS).addField(fieldMapping); + } + } + case 4 -> { // Method + PairedMapping methodMapping = MappingUtil.Paired.duo(sa[1], sa[3], sa[2]); + synchronized (classes) { + classes.computeIfAbsent(sa[0], MappingUtil.Paired.COMPUTE_DEFAULT_CLASS).addMethod(methodMapping); + } + } + default -> throw new IllegalArgumentException("Is this a CSRG mapping file?"); + } + }); + mappings.classes.addAll(classes.values()); + return mappings; + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/MappingProcessors.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/MappingProcessors.java deleted file mode 100644 index 1899e7e..0000000 --- a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/MappingProcessors.java +++ /dev/null @@ -1,589 +0,0 @@ -/* - * MinecraftDecompiler. A tool/library to deobfuscate and decompile jars. - * Copyright (C) 2019-2024 MaxPixelStudios(XiaoPangxie732) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package cn.maxpixel.mcdecompiler.mapping.processor; - -import cn.maxpixel.mcdecompiler.common.util.NamingUtil; -import cn.maxpixel.mcdecompiler.common.util.Utils; -import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; -import cn.maxpixel.mcdecompiler.mapping.PairedMapping; -import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; -import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; -import cn.maxpixel.mcdecompiler.mapping.component.Documented; -import cn.maxpixel.mcdecompiler.mapping.component.LocalVariableTable; -import cn.maxpixel.mcdecompiler.mapping.component.StaticIdentifiable; -import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; -import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; -import cn.maxpixel.mcdecompiler.mapping.trait.AccessTransformationTrait; -import cn.maxpixel.mcdecompiler.mapping.trait.InheritanceTrait; -import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; -import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; -import cn.maxpixel.mcdecompiler.mapping.util.TinyUtil; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectList; - -import java.util.Arrays; -import java.util.function.Function; - -public interface MappingProcessors { - MappingProcessor.Classified SRG = new MappingProcessor.Classified<>() { - private static final Function>> MAPPING_FUNC = s -> - k -> new ClassMapping<>(new PairedMapping(k, getClassName(s))); - - @Override - public MappingFormat> getFormat() { - return MappingFormats.SRG; - } - - @Override - public ClassifiedMapping process(ObjectList content) { - ClassifiedMapping mappings = new ClassifiedMapping<>(); - Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: unmapped name - content.parallelStream().forEach(s -> { - String[] strings = MappingUtil.split(s, ' '); - switch (strings[0]) { - case "CL:" -> { - ClassMapping classMapping = new ClassMapping<>(new PairedMapping(strings[1], strings[2])); - synchronized (classes) { - classes.putIfAbsent(strings[1], classMapping); - } - } - case "FD:" -> { - PairedMapping fieldMapping = MappingUtil.Paired.o(getName(strings[1]), getName(strings[2])); - String unmClassName = getClassName(strings[1]); - synchronized (classes) { - classes.computeIfAbsent(unmClassName, MAPPING_FUNC.apply(strings[2])) - .addField(fieldMapping); - } - } - case "MD:" -> { - PairedMapping methodMapping = MappingUtil.Paired.d2o(getName(strings[1]), getName(strings[3]), strings[2], strings[4]); - String unmClassName = getClassName(strings[1]); - synchronized (classes) { - classes.computeIfAbsent(unmClassName, MAPPING_FUNC.apply(strings[3])) - .addMethod(methodMapping); - } - } - case "PK:" -> { - synchronized (mappings.packages) { - mappings.packages.add(new PairedMapping(strings[1], strings[2])); - } - } - default -> throw new IllegalArgumentException("Is this a SRG mapping file?"); - } - }); - mappings.classes.addAll(classes.values()); - return mappings; - } - - private static String getClassName(String s) { - return s.substring(0, s.lastIndexOf('/')); - } - - private static String getName(String s) { - return s.substring(s.lastIndexOf('/') + 1); - } - }; - - MappingProcessor.Classified CSRG = new MappingProcessor.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.CSRG; - } - - @Override - public ClassifiedMapping process(ObjectList content) { - ClassifiedMapping mappings = new ClassifiedMapping<>(); - Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: unmapped name - content.parallelStream().forEach(s -> { - String[] sa = MappingUtil.split(s, ' '); - switch (sa.length) { - case 2 -> { // Class / Package - if (sa[0].charAt(sa[0].length() - 1) == '/') synchronized (mappings.packages) { - mappings.packages.add(new PairedMapping(sa[0].substring(0, sa[0].length() - 1), - sa[1].substring(0, sa[1].length() - 1))); - } else { - ClassMapping classMapping = new ClassMapping<>(new PairedMapping(sa[0], sa[1])); - synchronized (classes) { - classes.merge(classMapping.mapping.unmappedName, classMapping, (o, n) -> { - n.addFields(o.getFields()); - n.addMethods(o.getMethods()); - return n; - }); - } - } - } - case 3 -> { // Field - PairedMapping fieldMapping = MappingUtil.Paired.o(sa[1], sa[2]); - synchronized (classes) { - classes.computeIfAbsent(sa[0], MappingUtil.Paired.COMPUTE_DEFAULT_CLASS).addField(fieldMapping); - } - } - case 4 -> { // Method - PairedMapping methodMapping = MappingUtil.Paired.duo(sa[1], sa[3], sa[2]); - synchronized (classes) { - classes.computeIfAbsent(sa[0], MappingUtil.Paired.COMPUTE_DEFAULT_CLASS).addMethod(methodMapping); - } - } - default -> throw new IllegalArgumentException("Is this a CSRG mapping file?"); - } - }); - mappings.classes.addAll(classes.values()); - return mappings; - } - }; - - MappingProcessor.Classified TSRG_V1 = new MappingProcessor.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.TSRG_V1; - } - - @Override - public ClassifiedMapping process(ObjectList content) { - ClassifiedMapping mappings = new ClassifiedMapping<>(); - for (int i = 0, len = content.size(); i < len;) { - String[] sa = MappingUtil.split(content.get(i), ' '); - if (sa[0].charAt(0) != '\t') { - if (sa[0].charAt(sa[0].length() - 1) == '/') { - mappings.packages.add(new PairedMapping(sa[0].substring(0, sa[0].length() - 1), - sa[1].substring(0, sa[1].length() - 1))); - i++; - } else { - ClassMapping classMapping = new ClassMapping<>(new PairedMapping(sa[0], sa[1])); - i = processTree(i, len, content, classMapping); - mappings.classes.add(classMapping); - } - } else error(); - } - return mappings; - } - - private static int processTree(int index, int size, ObjectList content, ClassMapping classMapping) { - for (index = index + 1; index < size; index++) { - String s = content.get(index); - if (s.charAt(0) == '\t') { - String[] sa = MappingUtil.split(s, ' ', 1); - switch (sa.length) { - case 2 -> classMapping.addField(MappingUtil.Paired.o(sa[0], sa[1])); - case 3 -> classMapping.addMethod(MappingUtil.Paired.duo(sa[0], sa[2], sa[1])); - default -> error(); - } - } else break; - } - return index; - } - - private static void error() { - throw new IllegalArgumentException("Is this a TSRG v1 mapping file?"); - } - }; - - MappingProcessor.Classified TSRG_V2 = new MappingProcessor.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.TSRG_V2; - } - - @Override - public ClassifiedMapping process(ObjectList content) { - if(!content.get(0).startsWith("tsrg2")) error(); - String[] namespaces = MappingUtil.split(content.get(0), ' ', 6); - ClassifiedMapping mappings = new ClassifiedMapping<>(new NamespacedTrait(namespaces)); - for (int i = 1, len = content.size(); i < len; ) { - String[] sa = MappingUtil.split(content.get(i), ' '); - if (sa[0].charAt(0) != '\t') { - if (sa[0].charAt(sa[0].length() - 1) == '/') { - for (int j = 0; j < sa.length; j++) sa[j] = sa[j].substring(0, sa[j].length() - 1); - mappings.packages.add(new NamespacedMapping(namespaces, sa).setUnmappedNamespace(namespaces[0])); - i++; - } else { - ClassMapping classMapping = new ClassMapping<>(new NamespacedMapping(namespaces, sa) - .setUnmappedNamespace(namespaces[0])); - i = processTree(i, len, namespaces, content, classMapping); - mappings.classes.add(classMapping); - } - } else error(); - } - return mappings; - } - - private static int processTree(int index, int size, String[] namespaces, ObjectList content, - ClassMapping classMapping) { - for (index = index + 1; index < size; index++) { - String s = content.get(index); - if (s.charAt(0) == '\t') { - String[] sa = MappingUtil.split(s, ' ', 1); - switch (sa.length - namespaces.length) { - case 0 -> classMapping.addField(MappingUtil.Namespaced.o(namespaces, sa)); - case 1 -> { - String desc = sa[1]; - sa[1] = sa[0]; - if (desc.charAt(0) == '(') { - NamespacedMapping methodMapping = MappingUtil.Namespaced.slduo( - namespaces, sa, 1, namespaces[0], desc); - index = processTree1(index, size, namespaces, content, methodMapping); - classMapping.addMethod(methodMapping); - } else { - classMapping.addField(MappingUtil.Namespaced.duo(namespaces, - sa, 1, namespaces[0], desc)); - } - } - default -> error(); - } - } else break; - } - return index; - } - - private static int processTree1(int index, int size, String[] namespaces, ObjectList content, NamespacedMapping methodMapping) { - for (index = index + 1; index < size; index++) { - String s = content.get(index); - if (s.charAt(1) == '\t') { - if (s.equals("\t\tstatic")) methodMapping.getComponent(StaticIdentifiable.class).setStatic(true); - else { - String[] sa = MappingUtil.split(s, ' ', 2); - methodMapping.getComponent(LocalVariableTable.Namespaced.class) - .setLocalVariable(Integer.parseInt(sa[0]), new NamespacedMapping(namespaces, sa, 1)); - } - } else break; - } - return index - 1; - } - - private static void error() { - throw new IllegalArgumentException("Is this a TSRG v2 mapping file?"); - } - }; - - MappingProcessor.Classified PROGUARD = new MappingProcessor.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.PROGUARD; - } - - @Override - public ClassifiedMapping process(ObjectList content) { - ClassifiedMapping mappings = new ClassifiedMapping<>(); - for (int i = 0, len = content.size(); i < len; ) { - String s = content.get(i); - if (!s.startsWith(" ")) { - int splitIndex = s.indexOf(" -> "); - if (splitIndex <= 0) error(); - ClassMapping classMapping = new ClassMapping<>(new PairedMapping( - NamingUtil.asNativeName(s.substring(splitIndex + 4, s.length() - 1)), - NamingUtil.asNativeName(s.substring(0, splitIndex)) - )); - i = processTree(i, len, content, classMapping); - mappings.classes.add(classMapping); - } else error(); - } - return mappings; - } - - private static int processTree(int index, int size, ObjectList content, ClassMapping classMapping) { - for (index = index + 1; index < size; index++) { - String s = content.get(index); - if (s.startsWith(" ")) { - if (s.contains("(") && s.contains(")")) { - int lineNum = s.indexOf(':'); - int leftBracket = s.indexOf('('); - int rightBracket = s.lastIndexOf(')'); - StringBuilder descriptor = new StringBuilder("("); - int prev = leftBracket; - for (int next = s.indexOf(',', prev + 1); next > 0; - prev = next, next = s.indexOf(',', prev + 1)) { - descriptor.append(NamingUtil.java2Descriptor(s.substring(prev + 1, next))); - } - if (rightBracket - 1 != leftBracket) descriptor.append(NamingUtil.java2Descriptor(s.substring(prev + 1, rightBracket))); - if (lineNum > 0) { - int split1 = s.indexOf(' ', 11);// skip leading 4 spaces, descriptor name(at least 3 chars), and line number(at least 4 chars) - if (split1 < 0) error(); - int lineNum1 = s.indexOf(':', lineNum + 2); - if (lineNum1 < 0) error(); - classMapping.addMethod(MappingUtil.Paired.ldmo(s.substring(rightBracket + 5), s.substring(split1 + 1, leftBracket), - descriptor.append(')').append(NamingUtil.java2Descriptor(s.substring(lineNum1 + 1, split1))).toString(), - Integer.parseInt(s.substring(4, lineNum)), Integer.parseInt(s.substring(lineNum + 1, lineNum1)))); - } else { // no line number - int split1 = s.indexOf(' ', 7);// skip leading 4 spaces and descriptor name/line number(at least 3 chars) - if (split1 < 0) error(); - classMapping.addMethod(MappingUtil.Paired.dmo(s.substring(rightBracket + 5), s.substring(split1 + 1, leftBracket), - descriptor.append(')').append(NamingUtil.java2Descriptor(s.substring(4, split1))).toString())); - } - } else { - int split1 = s.indexOf(' ', 7);// skip leading 4 spaces and descriptor name(at least 3 chars) - if (split1 < 0) error(); - int split2 = s.indexOf(" -> ", split1 + 2);// skip split1(1 char) and mapped name(at least 1 char) - if (split2 < 0) error(); - classMapping.addField(MappingUtil.Paired.dmo(s.substring(split2 + 4), - s.substring(split1 + 1, split2), NamingUtil.java2Descriptor(s.substring(4, split1)))); - } - } else break; - } - return index; - } - - private static void error() { - throw new IllegalArgumentException("Is this a Proguard mapping file?"); - } - }; - - MappingProcessor.Classified TINY_V1 = new MappingProcessor.Classified<>() { - private static final Function>> MAPPING_FUNC = (namespaces) -> - key -> new ClassMapping<>(new NamespacedMapping(namespaces, copy(key, namespaces.length)).setUnmappedNamespace(namespaces[0])); - - private static String[] copy(String s, int count) { - String[] ret = new String[count]; - Arrays.fill(ret, s); - return ret; - } - - @Override - public MappingFormat> getFormat() { - return MappingFormats.TINY_V1; - } - - @Override - public ClassifiedMapping process(ObjectList content) {// TODO: Support properties - if (!content.get(0).startsWith("v1")) error(); - String[] namespaces = MappingUtil.split(content.get(0), '\t', 3); - ClassifiedMapping mappings = new ClassifiedMapping<>(new NamespacedTrait(namespaces)); - Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: the first namespace, usually unmapped name - String k = namespaces[0]; - content.parallelStream().skip(1).forEach(s -> { - String[] sa = MappingUtil.split(s, '\t'); - if (s.startsWith("CLASS")) { - ClassMapping classMapping = new ClassMapping<>(new NamespacedMapping(namespaces, sa, 1) - .setUnmappedNamespace(k)); - synchronized (classes) { - classes.merge(sa[1], classMapping, (o, n) -> n.addFields(o.getFields()).addMethods(o.getMethods())); - } - } else if (s.startsWith("FIELD")) { - NamespacedMapping fieldMapping = MappingUtil.Namespaced.duo(namespaces, sa, 3, k, sa[2]); - synchronized (classes) { - classes.computeIfAbsent(sa[1], MAPPING_FUNC.apply(namespaces)) - .addField(fieldMapping); - } - } else if (s.startsWith("METHOD")) { - NamespacedMapping methodMapping = MappingUtil.Namespaced.duo(namespaces, sa, 3, k, sa[2]); - synchronized (classes) { - classes.computeIfAbsent(sa[1], MAPPING_FUNC.apply(namespaces)) - .addMethod(methodMapping); - } - } else error(); - }); - mappings.classes.addAll(classes.values()); - return mappings; - } - - private static void error() { - throw new IllegalArgumentException("Is this a Tiny v1 mapping file?"); - } - }; - - MappingProcessor.Classified TINY_V2 = new MappingProcessor.Classified<>() { - @Override - public MappingFormat> getFormat() { - return MappingFormats.TINY_V2; - } - - @Override - public ClassifiedMapping process(ObjectList content) {// TODO: Support properties - if (!content.get(0).startsWith("tiny\t2\t0")) error(); - String[] namespaces = MappingUtil.split(content.get(0), '\t', 9); - ClassifiedMapping mappings = new ClassifiedMapping<>(new NamespacedTrait(namespaces)); - for (int i = 1, len = content.size(); i < len; ) { - String[] sa = MappingUtil.split(content.get(i), '\t'); - if (sa[0].length() == 1 && sa[0].charAt(0) == 'c') { - ClassMapping classMapping = new ClassMapping<>(MappingUtil.Namespaced.d(namespaces, sa, 1)); - i = processTree(i, len, namespaces, content, classMapping); - mappings.classes.add(classMapping); - } else error(); - } - return mappings; - } - - private static int processTree(int index, int size, String[] namespaces, ObjectList content, - ClassMapping classMapping) { - for (index = index + 1; index < size; index++) { - String s = content.get(index); - if (s.charAt(0) == '\t') { - String[] sa = MappingUtil.split(s, '\t', 3); - switch (s.charAt(1)) { - case 'c' -> classMapping.mapping.getComponent(Documented.class).setContentString(TinyUtil.unescape(sa[0])); - case 'f' -> { - NamespacedMapping fieldMapping = MappingUtil.Namespaced.dduo(namespaces, sa, 1, namespaces[0], sa[0]); - index = processTree1(index, size, namespaces, content, fieldMapping); - classMapping.addField(fieldMapping); - } - case 'm' -> { - NamespacedMapping methodMapping = MappingUtil.Namespaced.dlduo(namespaces, sa, 1, namespaces[0], sa[0]); - index = processTree1(index, size, namespaces, content, methodMapping); - classMapping.addMethod(methodMapping); - } - default -> error(); - } - } else break; - } - return index; - } - - private static int processTree1(int index, int size, String[] namespaces, ObjectList content, - NamespacedMapping mapping) { - for (index = index + 1; index < size; index++) { - String s = content.get(index); - if (s.charAt(1) == '\t' && s.charAt(0) == '\t') { - switch (s.charAt(2)) { - case 'c' -> mapping.getComponent(Documented.class).setContentString(TinyUtil.unescape(s, 4)); - case 'p' -> { - String[] sa = MappingUtil.split(s, '\t', 4); - NamespacedMapping localVariable = MappingUtil.Namespaced.d(namespaces, sa, 1); - mapping.getComponent(LocalVariableTable.Namespaced.class) - .setLocalVariable(Integer.parseInt(sa[0]), localVariable); - index = processTree2(index, size, content, localVariable); - } - default -> error(); - } - } else break; - } - return index - 1; - } - - private static int processTree2(int index, int size, ObjectList content, NamespacedMapping localVariable) { - if (++index < size) { - String s = content.get(index); - if (s.charAt(2) == '\t' && s.charAt(1) == '\t' && s.charAt(0) == '\t') { - if (s.charAt(3) == 'c') localVariable.getComponent(Documented.class).setContentString(TinyUtil.unescape(s, 5)); - else error(); - return index; - } - } - return index - 1; - } - - private static void error() { - throw new IllegalArgumentException("Is this a Tiny v2 mapping file?"); - } - }; - - MappingProcessor.Classified PDME = new MappingProcessor.Classified<>() { - private static final char PARA = '¶'; - - @Override - public MappingFormat> getFormat() { - return MappingFormats.PDME; - } - - @Override - public ClassifiedMapping process(ObjectList content) { - InheritanceTrait inheritanceMap = new InheritanceTrait(); - AccessTransformationTrait at = new AccessTransformationTrait(); - ClassifiedMapping mappings = new ClassifiedMapping<>(inheritanceMap, at); - Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: unmapped name - Object2ObjectOpenHashMap methodMap = new Object2ObjectOpenHashMap<>(); - for (String line : content) { - String[] parts = MappingUtil.split(line, PARA); - switch (parts[0]) { - case "Class" -> { - String unmapped = parts[1].replace('.', '/'); - String mapped = parts[2].replace('.', '/'); - classes.merge(unmapped, new ClassMapping<>(new PairedMapping(unmapped, mapped, new Documented(parts[5]))), (o, n) -> { - n.addFields(o.getFields()); - n.addMethods(o.getMethods()); - return n; - }); - } - case "Def" -> getMethod(parts[1], parts[2], parts[5], classes, methodMap); - case "Var" -> { - int lastDot = parts[1].lastIndexOf('.'); - String nameAndDesc = parts[1].substring(lastDot + 1); - int colon = nameAndDesc.indexOf(':'); - PairedMapping field = MappingUtil.Paired.duo(nameAndDesc.substring(0, colon), parts[2], - nameAndDesc.substring(colon + 1)); - field.addComponent(new Documented(parts[5])); - ClassMapping cm = classes.computeIfAbsent(parts[1].substring(0, lastDot) - .replace('.', '/'), MappingUtil.Paired.COMPUTE_DEFAULT_CLASS); - cm.addField(field); - } - case "Param" -> { - PairedMapping local = new PairedMapping(parts[1], parts[2]); - local.addComponent(new Documented(parts[5])); - PairedMapping method = getMethod(parts[3], null, null, classes, methodMap); - LocalVariableTable.Paired lvt = method.getOrCreateComponent(LocalVariableTable.Paired.class, - LocalVariableTable.Paired::new); - lvt.setLocalVariable(Integer.parseInt(parts[4]), local); - } - case "Include", "Incluir" -> inheritanceMap.put(parts[1].replace('.', '/'), - Utils.mapArray(MappingUtil.split(parts[2], ','), String[]::new, - s -> s.replace('.', '/'))); - case "AccessFlag", "BanderaDeAcceso" -> { - if (parts[1].contains(":")) { // field - } else if (parts[1].contains("(")) { // method - } else { // class - at.add(parts[1].replace('.', '/'), parts[2].startsWith("0x") ? - Integer.parseInt(parts[2].substring(2), 16) : Integer.parseInt(parts[2])); - } - } - } - } - mappings.classes.addAll(classes.values()); - for (var cm : mappings.classes) parseOuterClass(cm.mapping.unmappedName, classes); - return mappings; - } - - private static String parseOuterClass(String unmapped, Object2ObjectOpenHashMap> classes) { - ClassMapping cm = classes.get(unmapped); - String mapped = cm == null ? unmapped : cm.mapping.mappedName; - int lastDollar = unmapped.lastIndexOf('$'); - if (lastDollar < 0) return mapped; - String outer = unmapped.substring(0, lastDollar); - if (cm != null) { - if (mapped.contains("$")) return mapped; - String ret = parseOuterClass(outer, classes) + '$' + mapped; - cm.mapping.mappedName = ret; - return ret; - } - String ret = parseOuterClass(outer, classes) + '$' + unmapped.substring(lastDollar + 1); - classes.put(unmapped, new ClassMapping<>(new PairedMapping(unmapped, ret))); - return ret; - } - - private static PairedMapping getMethod(String original, String mapped, String docs, - Object2ObjectOpenHashMap> classes, - Object2ObjectOpenHashMap methodMap) { - return methodMap.compute(original, (s, old) -> { - if (old != null) { - if (docs != null) old.addComponent(new Documented(docs)); - if (mapped != null) old.mappedName = mapped; - return old; - } - int lastDot = s.lastIndexOf('.'); - String nameAndDesc = s.substring(lastDot + 1); - int bracket = nameAndDesc.indexOf('('); - String name = nameAndDesc.substring(0, bracket); - PairedMapping method = MappingUtil.Paired.duo(name, mapped == null ? name : mapped, - nameAndDesc.substring(bracket)); - if (docs != null) method.addComponent(new Documented(docs)); - ClassMapping cm = classes.computeIfAbsent(s.substring(0, lastDot) - .replace('.', '/'), MappingUtil.Paired.COMPUTE_DEFAULT_CLASS); - cm.addMethod(method); - return method; - }); - } - }; -} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/PdmeMappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/PdmeMappingProcessor.java new file mode 100644 index 0000000..e00eaa0 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/PdmeMappingProcessor.java @@ -0,0 +1,123 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.common.util.Utils; +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.Documented; +import cn.maxpixel.mcdecompiler.mapping.component.LocalVariableTable; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.trait.AccessTransformationTrait; +import cn.maxpixel.mcdecompiler.mapping.trait.InheritanceTrait; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum PdmeMappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + private static final char PARA = '¶'; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.PDME; + } + + @Override + public ClassifiedMapping process(ObjectList content) { + InheritanceTrait inheritanceMap = new InheritanceTrait(); + AccessTransformationTrait at = new AccessTransformationTrait(); + ClassifiedMapping mappings = new ClassifiedMapping<>(inheritanceMap, at); + Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: unmapped name + Object2ObjectOpenHashMap methodMap = new Object2ObjectOpenHashMap<>(); + for (String line : content) { + String[] parts = MappingUtil.split(line, PARA); + switch (parts[0]) { + case "Class" -> { + String unmapped = parts[1].replace('.', '/'); + String mapped = parts[2].replace('.', '/'); + classes.merge(unmapped, new ClassMapping<>(new PairedMapping(unmapped, mapped, new Documented(parts[5]))), (o, n) -> { + n.addFields(o.getFields()); + n.addMethods(o.getMethods()); + return n; + }); + } + case "Def" -> getMethod(parts[1], parts[2], parts[5], classes, methodMap); + case "Var" -> { + int lastDot = parts[1].lastIndexOf('.'); + String nameAndDesc = parts[1].substring(lastDot + 1); + int colon = nameAndDesc.indexOf(':'); + PairedMapping field = MappingUtil.Paired.duo(nameAndDesc.substring(0, colon), parts[2], + nameAndDesc.substring(colon + 1)); + field.addComponent(new Documented(parts[5])); + ClassMapping cm = classes.computeIfAbsent(parts[1].substring(0, lastDot) + .replace('.', '/'), MappingUtil.Paired.COMPUTE_DEFAULT_CLASS); + cm.addField(field); + } + case "Param" -> { + PairedMapping local = new PairedMapping(parts[1], parts[2]); + local.addComponent(new Documented(parts[5])); + PairedMapping method = getMethod(parts[3], null, null, classes, methodMap); + LocalVariableTable.Paired lvt = method.getOrCreateComponent(LocalVariableTable.Paired.class, + LocalVariableTable.Paired::new); + lvt.setLocalVariable(Integer.parseInt(parts[4]), local); + } + case "Include", "Incluir" -> inheritanceMap.put(parts[1].replace('.', '/'), + Utils.mapArray(MappingUtil.split(parts[2], ','), String[]::new, + s -> s.replace('.', '/'))); + case "AccessFlag", "BanderaDeAcceso" -> { + if (parts[1].contains(":")) { // field + } else if (parts[1].contains("(")) { // method + } else { // class + at.add(parts[1].replace('.', '/'), parts[2].startsWith("0x") ? + Integer.parseInt(parts[2].substring(2), 16) : Integer.parseInt(parts[2])); + } + } + } + } + mappings.classes.addAll(classes.values()); + for (var cm : mappings.classes) parseOuterClass(cm.mapping.unmappedName, classes); + return mappings; + } + + private static String parseOuterClass(String unmapped, Object2ObjectOpenHashMap> classes) { + ClassMapping cm = classes.get(unmapped); + String mapped = cm == null ? unmapped : cm.mapping.mappedName; + int lastDollar = unmapped.lastIndexOf('$'); + if (lastDollar < 0) return mapped; + String outer = unmapped.substring(0, lastDollar); + if (cm != null) { + if (mapped.contains("$")) return mapped; + String ret = parseOuterClass(outer, classes) + '$' + mapped; + cm.mapping.mappedName = ret; + return ret; + } + String ret = parseOuterClass(outer, classes) + '$' + unmapped.substring(lastDollar + 1); + classes.put(unmapped, new ClassMapping<>(new PairedMapping(unmapped, ret))); + return ret; + } + + private static PairedMapping getMethod(String original, String mapped, String docs, + Object2ObjectOpenHashMap> classes, + Object2ObjectOpenHashMap methodMap) { + return methodMap.compute(original, (s, old) -> { + if (old != null) { + if (docs != null) old.addComponent(new Documented(docs)); + if (mapped != null) old.mappedName = mapped; + return old; + } + int lastDot = s.lastIndexOf('.'); + String nameAndDesc = s.substring(lastDot + 1); + int bracket = nameAndDesc.indexOf('('); + String name = nameAndDesc.substring(0, bracket); + PairedMapping method = MappingUtil.Paired.duo(name, mapped == null ? name : mapped, + nameAndDesc.substring(bracket)); + if (docs != null) method.addComponent(new Documented(docs)); + ClassMapping cm = classes.computeIfAbsent(s.substring(0, lastDot) + .replace('.', '/'), MappingUtil.Paired.COMPUTE_DEFAULT_CLASS); + cm.addMethod(method); + return method; + }); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/ProguardMappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/ProguardMappingProcessor.java new file mode 100644 index 0000000..199eb97 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/ProguardMappingProcessor.java @@ -0,0 +1,84 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.common.util.NamingUtil; +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum ProguardMappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.PROGUARD; + } + + @Override + public ClassifiedMapping process(ObjectList content) { + ClassifiedMapping mappings = new ClassifiedMapping<>(); + for (int i = 0, len = content.size(); i < len; ) { + String s = content.get(i); + if (!s.startsWith(" ")) { + int splitIndex = s.indexOf(" -> "); + if (splitIndex <= 0) error(); + ClassMapping classMapping = new ClassMapping<>(new PairedMapping( + NamingUtil.asNativeName(s.substring(splitIndex + 4, s.length() - 1)), + NamingUtil.asNativeName(s.substring(0, splitIndex)) + )); + i = processTree(i, len, content, classMapping); + mappings.classes.add(classMapping); + } else error(); + } + return mappings; + } + + private static int processTree(int index, int size, ObjectList content, ClassMapping classMapping) { + for (index = index + 1; index < size; index++) { + String s = content.get(index); + if (s.startsWith(" ")) { + if (s.contains("(") && s.contains(")")) { + int lineNum = s.indexOf(':'); + int leftBracket = s.indexOf('('); + int rightBracket = s.lastIndexOf(')'); + StringBuilder descriptor = new StringBuilder("("); + int prev = leftBracket; + for (int next = s.indexOf(',', prev + 1); next > 0; + prev = next, next = s.indexOf(',', prev + 1)) { + descriptor.append(NamingUtil.java2Descriptor(s.substring(prev + 1, next))); + } + if (rightBracket - 1 != leftBracket) descriptor.append(NamingUtil.java2Descriptor(s.substring(prev + 1, rightBracket))); + if (lineNum > 0) { + int split1 = s.indexOf(' ', 11);// skip leading 4 spaces, descriptor name(at least 3 chars), and line number(at least 4 chars) + if (split1 < 0) error(); + int lineNum1 = s.indexOf(':', lineNum + 2); + if (lineNum1 < 0) error(); + classMapping.addMethod(MappingUtil.Paired.ldmo(s.substring(rightBracket + 5), s.substring(split1 + 1, leftBracket), + descriptor.append(')').append(NamingUtil.java2Descriptor(s.substring(lineNum1 + 1, split1))).toString(), + Integer.parseInt(s.substring(4, lineNum)), Integer.parseInt(s.substring(lineNum + 1, lineNum1)))); + } else { // no line number + int split1 = s.indexOf(' ', 7);// skip leading 4 spaces and descriptor name/line number(at least 3 chars) + if (split1 < 0) error(); + classMapping.addMethod(MappingUtil.Paired.dmo(s.substring(rightBracket + 5), s.substring(split1 + 1, leftBracket), + descriptor.append(')').append(NamingUtil.java2Descriptor(s.substring(4, split1))).toString())); + } + } else { + int split1 = s.indexOf(' ', 7);// skip leading 4 spaces and descriptor name(at least 3 chars) + if (split1 < 0) error(); + int split2 = s.indexOf(" -> ", split1 + 2);// skip split1(1 char) and mapped name(at least 1 char) + if (split2 < 0) error(); + classMapping.addField(MappingUtil.Paired.dmo(s.substring(split2 + 4), + s.substring(split1 + 1, split2), NamingUtil.java2Descriptor(s.substring(4, split1)))); + } + } else break; + } + return index; + } + + private static void error() { + throw new IllegalArgumentException("Is this a Proguard mapping file?"); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/SrgMappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/SrgMappingProcessor.java new file mode 100644 index 0000000..4a9f37e --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/SrgMappingProcessor.java @@ -0,0 +1,73 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectList; + +import java.util.function.Function; + +public enum SrgMappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + private static final Function>> MAPPING_FUNC = s -> + k -> new ClassMapping<>(new PairedMapping(k, getClassName(s))); + + @Override + public MappingFormat> getFormat() { + return MappingFormats.SRG; + } + + @Override + public ClassifiedMapping process(ObjectList content) { + ClassifiedMapping mappings = new ClassifiedMapping<>(); + Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: unmapped name + content.parallelStream().forEach(s -> { + String[] strings = MappingUtil.split(s, ' '); + switch (strings[0]) { + case "CL:" -> { + ClassMapping classMapping = new ClassMapping<>(new PairedMapping(strings[1], strings[2])); + synchronized (classes) { + classes.putIfAbsent(strings[1], classMapping); + } + } + case "FD:" -> { + PairedMapping fieldMapping = MappingUtil.Paired.o(getName(strings[1]), getName(strings[2])); + String unmClassName = getClassName(strings[1]); + synchronized (classes) { + classes.computeIfAbsent(unmClassName, MAPPING_FUNC.apply(strings[2])) + .addField(fieldMapping); + } + } + case "MD:" -> { + PairedMapping methodMapping = MappingUtil.Paired.d2o(getName(strings[1]), getName(strings[3]), strings[2], strings[4]); + String unmClassName = getClassName(strings[1]); + synchronized (classes) { + classes.computeIfAbsent(unmClassName, MAPPING_FUNC.apply(strings[3])) + .addMethod(methodMapping); + } + } + case "PK:" -> { + synchronized (mappings.packages) { + mappings.packages.add(new PairedMapping(strings[1], strings[2])); + } + } + default -> throw new IllegalArgumentException("Is this a SRG mapping file?"); + } + }); + mappings.classes.addAll(classes.values()); + return mappings; + } + + private static String getClassName(String s) { + return s.substring(0, s.lastIndexOf('/')); + } + + private static String getName(String s) { + return s.substring(s.lastIndexOf('/') + 1); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TinyV1MappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TinyV1MappingProcessor.java new file mode 100644 index 0000000..c0ffdc9 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TinyV1MappingProcessor.java @@ -0,0 +1,69 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectList; + +import java.util.Arrays; +import java.util.function.Function; + +public enum TinyV1MappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + private static final Function>> MAPPING_FUNC = (namespaces) -> + key -> new ClassMapping<>(new NamespacedMapping(namespaces, copy(key, namespaces.length)).setUnmappedNamespace(namespaces[0])); + + private static String[] copy(String s, int count) { + String[] ret = new String[count]; + Arrays.fill(ret, s); + return ret; + } + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TINY_V1; + } + + @Override + public ClassifiedMapping process(ObjectList content) {// TODO: Support properties + if (!content.get(0).startsWith("v1")) error(); + String[] namespaces = MappingUtil.split(content.get(0), '\t', 3); + ClassifiedMapping mappings = new ClassifiedMapping<>(new NamespacedTrait(namespaces)); + Object2ObjectOpenHashMap> classes = new Object2ObjectOpenHashMap<>(); // k: the first namespace, usually unmapped name + String k = namespaces[0]; + content.parallelStream().skip(1).forEach(s -> { + String[] sa = MappingUtil.split(s, '\t'); + if (s.startsWith("CLASS")) { + ClassMapping classMapping = new ClassMapping<>(new NamespacedMapping(namespaces, sa, 1) + .setUnmappedNamespace(k)); + synchronized (classes) { + classes.merge(sa[1], classMapping, (o, n) -> n.addFields(o.getFields()).addMethods(o.getMethods())); + } + } else if (s.startsWith("FIELD")) { + NamespacedMapping fieldMapping = MappingUtil.Namespaced.duo(namespaces, sa, 3, k, sa[2]); + synchronized (classes) { + classes.computeIfAbsent(sa[1], MAPPING_FUNC.apply(namespaces)) + .addField(fieldMapping); + } + } else if (s.startsWith("METHOD")) { + NamespacedMapping methodMapping = MappingUtil.Namespaced.duo(namespaces, sa, 3, k, sa[2]); + synchronized (classes) { + classes.computeIfAbsent(sa[1], MAPPING_FUNC.apply(namespaces)) + .addMethod(methodMapping); + } + } else error(); + }); + mappings.classes.addAll(classes.values()); + return mappings; + } + + private static void error() { + throw new IllegalArgumentException("Is this a Tiny v1 mapping file?"); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TinyV2MappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TinyV2MappingProcessor.java new file mode 100644 index 0000000..dc560e1 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TinyV2MappingProcessor.java @@ -0,0 +1,100 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.Documented; +import cn.maxpixel.mcdecompiler.mapping.component.LocalVariableTable; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import cn.maxpixel.mcdecompiler.mapping.util.TinyUtil; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum TinyV2MappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TINY_V2; + } + + @Override + public ClassifiedMapping process(ObjectList content) {// TODO: Support properties + if (!content.get(0).startsWith("tiny\t2\t0")) error(); + String[] namespaces = MappingUtil.split(content.get(0), '\t', 9); + ClassifiedMapping mappings = new ClassifiedMapping<>(new NamespacedTrait(namespaces)); + for (int i = 1, len = content.size(); i < len; ) { + String[] sa = MappingUtil.split(content.get(i), '\t'); + if (sa[0].length() == 1 && sa[0].charAt(0) == 'c') { + ClassMapping classMapping = new ClassMapping<>(MappingUtil.Namespaced.d(namespaces, sa, 1)); + i = processTree(i, len, namespaces, content, classMapping); + mappings.classes.add(classMapping); + } else error(); + } + return mappings; + } + + private static int processTree(int index, int size, String[] namespaces, ObjectList content, + ClassMapping classMapping) { + for (index = index + 1; index < size; index++) { + String s = content.get(index); + if (s.charAt(0) == '\t') { + String[] sa = MappingUtil.split(s, '\t', 3); + switch (s.charAt(1)) { + case 'c' -> classMapping.mapping.getComponent(Documented.class).setContentString(TinyUtil.unescape(sa[0])); + case 'f' -> { + NamespacedMapping fieldMapping = MappingUtil.Namespaced.dduo(namespaces, sa, 1, namespaces[0], sa[0]); + index = processTree1(index, size, namespaces, content, fieldMapping); + classMapping.addField(fieldMapping); + } + case 'm' -> { + NamespacedMapping methodMapping = MappingUtil.Namespaced.dlduo(namespaces, sa, 1, namespaces[0], sa[0]); + index = processTree1(index, size, namespaces, content, methodMapping); + classMapping.addMethod(methodMapping); + } + default -> error(); + } + } else break; + } + return index; + } + + private static int processTree1(int index, int size, String[] namespaces, ObjectList content, + NamespacedMapping mapping) { + for (index = index + 1; index < size; index++) { + String s = content.get(index); + if (s.charAt(1) == '\t' && s.charAt(0) == '\t') { + switch (s.charAt(2)) { + case 'c' -> mapping.getComponent(Documented.class).setContentString(TinyUtil.unescape(s, 4)); + case 'p' -> { + String[] sa = MappingUtil.split(s, '\t', 4); + NamespacedMapping localVariable = MappingUtil.Namespaced.d(namespaces, sa, 1); + mapping.getComponent(LocalVariableTable.Namespaced.class) + .setLocalVariable(Integer.parseInt(sa[0]), localVariable); + index = processTree2(index, size, content, localVariable); + } + default -> error(); + } + } else break; + } + return index - 1; + } + + private static int processTree2(int index, int size, ObjectList content, NamespacedMapping localVariable) { + if (++index < size) { + String s = content.get(index); + if (s.charAt(2) == '\t' && s.charAt(1) == '\t' && s.charAt(0) == '\t') { + if (s.charAt(3) == 'c') localVariable.getComponent(Documented.class).setContentString(TinyUtil.unescape(s, 5)); + else error(); + return index; + } + } + return index - 1; + } + + private static void error() { + throw new IllegalArgumentException("Is this a Tiny v2 mapping file?"); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TsrgV1MappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TsrgV1MappingProcessor.java new file mode 100644 index 0000000..f8f1b76 --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TsrgV1MappingProcessor.java @@ -0,0 +1,57 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.mapping.PairedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum TsrgV1MappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TSRG_V1; + } + + @Override + public ClassifiedMapping process(ObjectList content) { + ClassifiedMapping mappings = new ClassifiedMapping<>(); + for (int i = 0, len = content.size(); i < len;) { + String[] sa = MappingUtil.split(content.get(i), ' '); + if (sa[0].charAt(0) != '\t') { + if (sa[0].charAt(sa[0].length() - 1) == '/') { + mappings.packages.add(new PairedMapping(sa[0].substring(0, sa[0].length() - 1), + sa[1].substring(0, sa[1].length() - 1))); + i++; + } else { + ClassMapping classMapping = new ClassMapping<>(new PairedMapping(sa[0], sa[1])); + i = processTree(i, len, content, classMapping); + mappings.classes.add(classMapping); + } + } else error(); + } + return mappings; + } + + private static int processTree(int index, int size, ObjectList content, ClassMapping classMapping) { + for (index = index + 1; index < size; index++) { + String s = content.get(index); + if (s.charAt(0) == '\t') { + String[] sa = MappingUtil.split(s, ' ', 1); + switch (sa.length) { + case 2 -> classMapping.addField(MappingUtil.Paired.o(sa[0], sa[1])); + case 3 -> classMapping.addMethod(MappingUtil.Paired.duo(sa[0], sa[2], sa[1])); + default -> error(); + } + } else break; + } + return index; + } + + private static void error() { + throw new IllegalArgumentException("Is this a TSRG v1 mapping file?"); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TsrgV2MappingProcessor.java b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TsrgV2MappingProcessor.java new file mode 100644 index 0000000..f9f6d1c --- /dev/null +++ b/modules/mapping-api/src/main/java/cn/maxpixel/mcdecompiler/mapping/processor/TsrgV2MappingProcessor.java @@ -0,0 +1,91 @@ +package cn.maxpixel.mcdecompiler.mapping.processor; + +import cn.maxpixel.mcdecompiler.mapping.NamespacedMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassMapping; +import cn.maxpixel.mcdecompiler.mapping.collection.ClassifiedMapping; +import cn.maxpixel.mcdecompiler.mapping.component.LocalVariableTable; +import cn.maxpixel.mcdecompiler.mapping.component.StaticIdentifiable; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormat; +import cn.maxpixel.mcdecompiler.mapping.format.MappingFormats; +import cn.maxpixel.mcdecompiler.mapping.trait.NamespacedTrait; +import cn.maxpixel.mcdecompiler.mapping.util.MappingUtil; +import it.unimi.dsi.fastutil.objects.ObjectList; + +public enum TsrgV2MappingProcessor implements MappingProcessor.Classified { + INSTANCE; + + @Override + public MappingFormat> getFormat() { + return MappingFormats.TSRG_V2; + } + + @Override + public ClassifiedMapping process(ObjectList content) { + if(!content.get(0).startsWith("tsrg2")) error(); + String[] namespaces = MappingUtil.split(content.get(0), ' ', 6); + ClassifiedMapping mappings = new ClassifiedMapping<>(new NamespacedTrait(namespaces)); + for (int i = 1, len = content.size(); i < len; ) { + String[] sa = MappingUtil.split(content.get(i), ' '); + if (sa[0].charAt(0) != '\t') { + if (sa[0].charAt(sa[0].length() - 1) == '/') { + for (int j = 0; j < sa.length; j++) sa[j] = sa[j].substring(0, sa[j].length() - 1); + mappings.packages.add(new NamespacedMapping(namespaces, sa).setUnmappedNamespace(namespaces[0])); + i++; + } else { + ClassMapping classMapping = new ClassMapping<>(new NamespacedMapping(namespaces, sa) + .setUnmappedNamespace(namespaces[0])); + i = processTree(i, len, namespaces, content, classMapping); + mappings.classes.add(classMapping); + } + } else error(); + } + return mappings; + } + + private static int processTree(int index, int size, String[] namespaces, ObjectList content, + ClassMapping classMapping) { + for (index = index + 1; index < size; index++) { + String s = content.get(index); + if (s.charAt(0) == '\t') { + String[] sa = MappingUtil.split(s, ' ', 1); + switch (sa.length - namespaces.length) { + case 0 -> classMapping.addField(MappingUtil.Namespaced.o(namespaces, sa)); + case 1 -> { + String desc = sa[1]; + sa[1] = sa[0]; + if (desc.charAt(0) == '(') { + NamespacedMapping methodMapping = MappingUtil.Namespaced.slduo( + namespaces, sa, 1, namespaces[0], desc); + index = processTree1(index, size, namespaces, content, methodMapping); + classMapping.addMethod(methodMapping); + } else { + classMapping.addField(MappingUtil.Namespaced.duo(namespaces, + sa, 1, namespaces[0], desc)); + } + } + default -> error(); + } + } else break; + } + return index; + } + + private static int processTree1(int index, int size, String[] namespaces, ObjectList content, NamespacedMapping methodMapping) { + for (index = index + 1; index < size; index++) { + String s = content.get(index); + if (s.charAt(1) == '\t') { + if (s.equals("\t\tstatic")) methodMapping.getComponent(StaticIdentifiable.class).setStatic(true); + else { + String[] sa = MappingUtil.split(s, ' ', 2); + methodMapping.getComponent(LocalVariableTable.Namespaced.class) + .setLocalVariable(Integer.parseInt(sa[0]), new NamespacedMapping(namespaces, sa, 1)); + } + } else break; + } + return index - 1; + } + + private static void error() { + throw new IllegalArgumentException("Is this a TSRG v2 mapping file?"); + } +} \ No newline at end of file diff --git a/modules/mapping-api/src/test/java/cn/maxpixel/mcdecompiler/test/mappings/benchmark/MappingReadSpeed.java b/modules/mapping-api/src/test/java/cn/maxpixel/mcdecompiler/test/mappings/benchmark/MappingReadSpeed.java index 0ab8fc9..927da89 100644 --- a/modules/mapping-api/src/test/java/cn/maxpixel/mcdecompiler/test/mappings/benchmark/MappingReadSpeed.java +++ b/modules/mapping-api/src/test/java/cn/maxpixel/mcdecompiler/test/mappings/benchmark/MappingReadSpeed.java @@ -18,7 +18,7 @@ package cn.maxpixel.mcdecompiler.test.mappings.benchmark; -import cn.maxpixel.mcdecompiler.mapping.processor.MappingProcessors; +import cn.maxpixel.mcdecompiler.mapping.processor.*; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; @@ -68,36 +68,36 @@ public void test() throws RunnerException { @Benchmark public void readSrg(Blackhole bh) { - bh.consume(MappingProcessors.SRG.process(srg)); + bh.consume(SrgMappingProcessor.INSTANCE.process(srg)); } @Benchmark public void readCsrg(Blackhole bh) { - bh.consume(MappingProcessors.CSRG.process(csrg)); + bh.consume(CsrgMappingProcessor.INSTANCE.process(csrg)); } @Benchmark public void readTsrg(Blackhole bh) { - bh.consume(MappingProcessors.TSRG_V1.process(tsrg)); + bh.consume(TsrgV1MappingProcessor.INSTANCE.process(tsrg)); } @Benchmark public void readTsrgV2(Blackhole bh) { - bh.consume(MappingProcessors.TSRG_V2.process(tsrg2)); + bh.consume(TsrgV2MappingProcessor.INSTANCE.process(tsrg2)); } @Benchmark public void readProguard(Blackhole bh) { - bh.consume(MappingProcessors.PROGUARD.process(proguard)); + bh.consume(ProguardMappingProcessor.INSTANCE.process(proguard)); } @Benchmark public void readTinyV1(Blackhole bh) { - bh.consume(MappingProcessors.TINY_V1.process(tiny1)); + bh.consume(TinyV1MappingProcessor.INSTANCE.process(tiny1)); } @Benchmark public void readTinyV2(Blackhole bh) { - bh.consume(MappingProcessors.TINY_V2.process(tiny2)); + bh.consume(TinyV2MappingProcessor.INSTANCE.process(tiny2)); } }