2020
2121import net .fabricmc .tinyremapper .IMappingProvider .MappingAcceptor ;
2222import net .fabricmc .tinyremapper .IMappingProvider .Member ;
23- import net .fabricmc .tinyremapper .MemberInstance .MemberType ;
23+ import net .fabricmc .tinyremapper .api .TrClass ;
24+ import net .fabricmc .tinyremapper .api .TrEnvironment ;
25+ import net .fabricmc .tinyremapper .api .TrMember ;
26+ import net .fabricmc .tinyremapper .api .TrMember .MemberType ;
2427import org .objectweb .asm .*;
2528import org .objectweb .asm .commons .Remapper ;
2629import org .objectweb .asm .util .CheckClassAdapter ;
2730
28- import java .io .File ;
2931import java .io .IOException ;
3032import java .io .UncheckedIOException ;
3133import java .net .URI ;
3234import java .net .URISyntaxException ;
3335import java .nio .file .*;
3436import java .nio .file .attribute .BasicFileAttributes ;
35- import java .util .ArrayDeque ;
36- import java .util .ArrayList ;
37- import java .util .Collection ;
38- import java .util .Collections ;
39- import java .util .HashMap ;
40- import java .util .HashSet ;
41- import java .util .IdentityHashMap ;
42- import java .util .List ;
43- import java .util .Map ;
44- import java .util .Objects ;
45- import java .util .Optional ;
46- import java .util .Queue ;
47- import java .util .Set ;
48- import java .util .concurrent .CompletableFuture ;
49- import java .util .concurrent .ConcurrentHashMap ;
50- import java .util .concurrent .ExecutionException ;
51- import java .util .concurrent .ExecutorService ;
52- import java .util .concurrent .Executors ;
53- import java .util .concurrent .Future ;
54- import java .util .concurrent .TimeUnit ;
37+ import java .util .*;
38+ import java .util .concurrent .*;
5539import java .util .concurrent .atomic .AtomicReference ;
5640import java .util .function .BiConsumer ;
5741import java .util .function .Consumer ;
5842import java .util .stream .Collectors ;
59- import java .util .zip .ZipError ;
60-
61- import org .objectweb .asm .ClassReader ;
62- import org .objectweb .asm .ClassVisitor ;
63- import org .objectweb .asm .ClassWriter ;
64- import org .objectweb .asm .FieldVisitor ;
65- import org .objectweb .asm .MethodVisitor ;
66- import org .objectweb .asm .Opcodes ;
67- import org .objectweb .asm .commons .Remapper ;
68- import org .objectweb .asm .util .CheckClassAdapter ;
69-
70- import net .fabricmc .tinyremapper .IMappingProvider .MappingAcceptor ;
71- import net .fabricmc .tinyremapper .IMappingProvider .Member ;
72- import net .fabricmc .tinyremapper .api .TrClass ;
73- import net .fabricmc .tinyremapper .api .TrEnvironment ;
74- import net .fabricmc .tinyremapper .api .TrMember ;
75- import net .fabricmc .tinyremapper .api .TrMember .MemberType ;
7643
7744public class TinyRemapper {
7845 public static class Builder {
@@ -527,7 +494,9 @@ private void addClass(ClassInstance cls, Map<String, ClassInstance> out, boolean
527494 }
528495 } else {
529496 if (out == readClasses ) {
530- mergedClasspath = false ;
497+ for (MrjState value : mrjStates .values ()) {
498+ value .mergedClasspath = false ;
499+ }
531500 mappingsDirty = true ;
532501 }
533502
@@ -606,14 +575,14 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
606575 private interface MrjPath {
607576 byte [] bytes () throws IOException ;
608577
609- String pathOrNull ();
578+ Path pathOrNull ();
610579 }
611580
612581 private static class StaticMrjPath implements MrjPath {
613582 private final byte [] bytes ;
614- private final String path ;
583+ private final Path path ;
615584
616- public StaticMrjPath (byte [] bytes , String path ) {
585+ public StaticMrjPath (byte [] bytes , Path path ) {
617586 this .bytes = bytes ;
618587 this .path = path ;
619588 }
@@ -624,7 +593,7 @@ public byte[] bytes() {
624593 }
625594
626595 @ Override
627- public String pathOrNull () {
596+ public Path pathOrNull () {
628597 return path ;
629598 }
630599 }
@@ -649,52 +618,43 @@ public byte[] bytes() throws IOException {
649618 }
650619
651620 @ Override
652- public String pathOrNull () {
653- return path . toString () ;
621+ public Path pathOrNull () {
622+ return path ;
654623 }
655624 }
656625
657- private static int analyzeMrjVersion (MrjPath file , String name ) {
658- String pathOrNull = file .pathOrNull ();
659- if (pathOrNull == null ) {
660- return ClassInstance .MRJ_DEFAULT ;
661- }
662- if (File .separator .equals ("/" )) {
663- return analyzeMrjVersion (pathOrNull , name );
664- } else if (File .separator .equals ("\\ " )) {
665- return analyzeMrjVersion (pathOrNull .replace ('\\' , '/' ), name );
666- } else {
667- throw new RuntimeException ("Unknown file separator detected." );
668- }
626+ private static int analyzeMrjVersion (MrjPath file , String name ) {
627+ Path pathOrNull = file .pathOrNull ();
628+ if (pathOrNull == null ) {
629+ return ClassInstance .MRJ_DEFAULT ;
669630 }
631+ return analyzeMrjVersion (pathOrNull , name );
632+ }
670633
671- /**
672- * Determine the MRJ version of the supplied class file and name.
673- *
674- * <p>This assumes that the file path follows the usual META-INF/versions/{@code <version>}/pkg/for/cls.class form.
675- */
676- private static int analyzeMrjVersion (MrjPath file , String name ) {
677- assert file .getFileName ().toString ().endsWith (".class" );
634+ /**
635+ * Determine the MRJ version of the supplied class file and name.
636+ *
637+ * <p>This assumes that the file path follows the usual META-INF/versions/{@code <version>}/pkg/for/cls.class form.
638+ */
639+ private static int analyzeMrjVersion (Path file , String name ) {
640+ assert file .getFileName ().toString ().endsWith (".class" );
678641
679- int pkgCount = 0 ;
680- int pos = 0 ;
642+ int pkgCount = 0 ;
643+ int pos = 0 ;
681644
682- while ((pos = name .indexOf ('/' , pos ) + 1 ) > 0 ) {
683- pkgCount ++;
684- }
645+ while ((pos = name .indexOf ('/' , pos ) + 1 ) > 0 ) {
646+ pkgCount ++;
685647 }
686648
687- private static int analyzeMrjVersion (String file , String name ) {
688649 name = name + ".class" ;
689650
690- int pathNameCount = file .getNameCount ();
691- int pathNameOffset = pathNameCount - pkgCount - 1 ; // path index for root package
692-
651+ int pathNameCount = file .getNameCount ();
652+ int pathNameOffset = pathNameCount - pkgCount - 1 ; // path index for root package
693653
694- if (pathNameOffset >= 3
695- && file .getName (pathNameOffset - 3 ).toString ().equals ("META-INF" ) // root pkg is in META-INF/x/x
696- && file .getName (pathNameOffset - 2 ).toString ().equals ("versions" ) // root pkg is in META-INF/versions/x
697- && file .subpath (pathNameOffset , pathNameCount ).toString ().replace ('\\' , '/' ).regionMatches (0 , name , 0 , name .length ())) { // verify class name == path from root pkg dir, ignores suffix like .class
654+ if (pathNameOffset >= 3
655+ && file .getName (pathNameOffset - 3 ).toString ().equals ("META-INF" ) // root pkg is in META-INF/x/x
656+ && file .getName (pathNameOffset - 2 ).toString ().equals ("versions" ) // root pkg is in META-INF/versions/x
657+ && file .subpath (pathNameOffset , pathNameCount ).toString ().replace ('\\' , '/' ).regionMatches (0 , name , 0 , name .length ())) { // verify class name == path from root pkg dir, ignores suffix like .class
698658 try {
699659 return Integer .parseInt (file .getName (pathNameOffset - 1 ).toString ());
700660 } catch (NumberFormatException e ) {
@@ -752,7 +712,9 @@ private void loadMappings(boolean ignoreCached) {
752712 methodMap .clear ();
753713 methodArgMap .clear ();
754714 fieldMap .clear ();
755- unmergeClasses ();
715+ for (MrjState state : mrjStates .values ()) {
716+ unmergeClasses (state );
717+ }
756718
757719 mappingsDirty = true ;
758720 }
@@ -877,16 +839,16 @@ private void checkClassMappings() {
877839 }
878840
879841 private void unmergeClasses (MrjState state ) {
880- mergedClasspath = false ;
842+ state . mergedClasspath = false ;
881843 for (ClassInstance node : state .classes .values ()) {
882844 node .parents .clear ();
883845 node .children .clear ();
884846 }
885847 }
886848
887849 private void mergeClasspath (MrjState state ) {
888- if (mergedClasspath ) return ;
889- mergedClasspath = true ;
850+ if (state . mergedClasspath ) return ;
851+ state . mergedClasspath = true ;
890852 for (ClassInstance node : state .classes .values ()) {
891853 if (node .isInput ) continue ;
892854 assert node .getSuperName () != null ;
@@ -909,21 +871,21 @@ private void mergeClasspath(MrjState state) {
909871 }
910872 }
911873
912- private void mergeInput () {
913- for (ClassInstance node : classes .values ().parallelStream ()
874+ private void mergeInput (MrjState state ) {
875+ for (ClassInstance node : state . classes .values ().parallelStream ()
914876 .filter (node -> node .isInput )
915877 .collect (Collectors .toList ())) {
916878 assert node .getSuperName () != null ;
917879
918- ClassInstance parent = classes .get (node .getSuperName ());
880+ ClassInstance parent = state . classes .get (node .getSuperName ());
919881
920882 if (parent != null ) {
921883 node .parents .add (parent );
922884 parent .children .add (node );
923885 }
924886
925- for (String iface : node .getInterfaces ()) {
926- parent = classes . get ( iface ) ;
887+ for (ClassInstance interfaceInstance : node .getInterfaces ()) {
888+ parent = interfaceInstance ;
927889
928890 if (parent != null ) {
929891 node .parents .add (parent );
@@ -933,8 +895,8 @@ private void mergeInput() {
933895 }
934896 }
935897
936- private void unmergeInput () {
937- classes .values ().parallelStream ()
898+ private void unmergeInput (MrjState state ) {
899+ state . classes .values ().parallelStream ()
938900 .filter (node -> node .isInput )
939901 .flatMap (node -> node .parents .stream ())
940902 .distinct ()
@@ -944,7 +906,7 @@ private void unmergeInput() {
944906 private void propagate (MrjState state ) {
945907 if (skipPropagate ) return ;
946908 conflicts .clear ();
947- classes .values ().parallelStream ().forEach (value -> {
909+ state . classes .values ().parallelStream ().forEach (value -> {
948910 value .resolvedMembers = new ConcurrentHashMap <>();
949911 for (MemberInstance member : value .getMembers ()) {
950912 member .forceSetNewName (null );
@@ -1209,11 +1171,18 @@ private void fixMrjClasses(Set<Integer> newVersions) {
12091171 }
12101172
12111173 public void removeInput () {
1174+ for (MrjState state : mrjStates .values ()) {
1175+ removeInput (state );
1176+ }
1177+ }
1178+
1179+ public void removeInput (MrjState state ) {
12121180 synchronized (this ) {
1213- unmergeInput ();
1214- classes .values ().removeIf (node -> node .isInput );
1181+ unmergeInput (state );
1182+ state . classes .values ().removeIf (node -> node .isInput );
12151183 }
12161184 }
1185+
12171186 public void prepareClasses () {
12181187 synchronized (this ) {
12191188 _prepareClasses ();
@@ -1266,8 +1235,6 @@ private void refresh() {
12661235
12671236 _prepareClasses ();
12681237 loadMappings (!cacheMappings );
1269- mergeClasspath ();
1270- propagate ();
12711238 }
12721239
12731240 private void mrjRefresh (MrjState state ) {
@@ -1279,6 +1246,7 @@ private void mrjRefresh(MrjState state) {
12791246 assert state .classes .values ().stream ().map (ClassInstance ::getName ).distinct ().count () == state .classes .size ();
12801247
12811248 mergeInput (state );
1249+ mergeClasspath (state );
12821250 propagate (state );
12831251
12841252 for (StateProcessor processor : stateProcessors ) {
@@ -1531,6 +1499,7 @@ public void propagate(TrMember m, String newName) {
15311499 final int version ;
15321500 final Map <String , ClassInstance > classes = new HashMap <>();
15331501 final AsmRemapper remapper ;
1502+ boolean mergedClasspath = false ;
15341503 volatile boolean dirty = true ;
15351504 }
15361505
@@ -1588,7 +1557,6 @@ public boolean isMappingsDirty() {
15881557 private final int threadCount ;
15891558 private final ExecutorService threadPool ;
15901559
1591- private boolean mergedClasspath = false ;
15921560 private boolean mappingsDirty = true ;
15931561 private volatile boolean dirty = true ; // volatile to make the state debug asserts more reliable, shouldn't actually see concurrent modifications
15941562 private Map <ClassInstance , byte []> outputBuffer ;
0 commit comments