20
20
import java .util .Collection ;
21
21
import java .util .Comparator ;
22
22
import java .util .List ;
23
+ import java .util .Locale ;
23
24
24
25
import org .jetbrains .annotations .Nullable ;
25
26
33
34
34
35
/**
35
36
* Visitation order configuration for {@link MappingTreeView#accept(net.fabricmc.mappingio.MappingVisitor, VisitOrder)}.
37
+ *
38
+ * @apiNote The exposed comparison methods aim to produce the most human-friendly output,
39
+ * their sorting order is not guaranteed to be stable across library versions unless specified otherwise.
36
40
*/
37
41
public final class VisitOrder {
38
42
private VisitOrder () {
@@ -44,6 +48,11 @@ public static VisitOrder createByInputOrder() {
44
48
return new VisitOrder ();
45
49
}
46
50
51
+ /**
52
+ * Sorts classes by their source name, members by source name and descriptor, and locals by lv- and lvt-index.
53
+ *
54
+ * @apiNote The sorting order is not guaranteed to be stable across library versions.
55
+ */
47
56
public static VisitOrder createByName () {
48
57
return new VisitOrder ()
49
58
.classesBySrcName ()
@@ -65,6 +74,10 @@ public VisitOrder classesBySrcName() {
65
74
return classComparator (compareBySrcName ());
66
75
}
67
76
77
+ public VisitOrder classesBySrcNameShortFirst () {
78
+ return classComparator (compareBySrcNameShortFirst ());
79
+ }
80
+
68
81
public VisitOrder fieldComparator (Comparator <FieldMappingView > comparator ) {
69
82
this .fieldComparator = comparator ;
70
83
@@ -106,11 +119,16 @@ public VisitOrder methodVarComparator(Comparator<MethodVarMappingView> comparato
106
119
}
107
120
108
121
public VisitOrder methodVarsByLvtRowIndex () {
109
- return methodVarComparator (Comparator .comparingInt (MethodVarMappingView ::getLvIndex ).thenComparingInt (MethodVarMappingView ::getLvtRowIndex ));
122
+ return methodVarComparator (Comparator
123
+ .comparingInt (MethodVarMappingView ::getLvIndex )
124
+ .thenComparingInt (MethodVarMappingView ::getLvtRowIndex ));
110
125
}
111
126
112
127
public VisitOrder methodVarsByLvIndex () {
113
- return methodVarComparator (Comparator .comparingInt (MethodVarMappingView ::getLvIndex ).thenComparingInt (MethodVarMappingView ::getStartOpIdx ));
128
+ return methodVarComparator (Comparator
129
+ .comparingInt (MethodVarMappingView ::getLvIndex )
130
+ .thenComparingInt (MethodVarMappingView ::getStartOpIdx )
131
+ .thenComparingInt (MethodVarMappingView ::getEndOpIdx ));
114
132
}
115
133
116
134
public VisitOrder methodsFirst (boolean methodsFirst ) {
@@ -141,10 +159,16 @@ public VisitOrder methodVarsFirst() {
141
159
return methodVarsFirst (true );
142
160
}
143
161
144
- // customization helpers
162
+ // customization helpers (not guaranteed to be stable across versions)
145
163
146
164
public static <T extends ElementMappingView > Comparator <T > compareBySrcName () {
147
- return (a , b ) -> compare (a .getSrcName (), b .getSrcName ());
165
+ return (a , b ) -> {
166
+ if (a instanceof ClassMappingView || b instanceof ClassMappingView ) {
167
+ return compareNestaware (a .getSrcName (), b .getSrcName (), false );
168
+ } else {
169
+ return compare (a .getSrcName (), b .getSrcName ());
170
+ }
171
+ };
148
172
}
149
173
150
174
public static <T extends MemberMappingView > Comparator <T > compareBySrcNameDesc () {
@@ -156,41 +180,58 @@ public static <T extends MemberMappingView> Comparator<T> compareBySrcNameDesc()
156
180
}
157
181
158
182
public static <T extends ElementMappingView > Comparator <T > compareBySrcNameShortFirst () {
159
- return (a , b ) -> compareShortFirst (a .getSrcName (), b .getSrcName ());
183
+ return (a , b ) -> {
184
+ if (a instanceof ClassMappingView || b instanceof ClassMappingView ) {
185
+ return compareNestaware (a .getSrcName (), b .getSrcName (), true );
186
+ } else {
187
+ return compareShortFirst (a .getSrcName (), b .getSrcName ());
188
+ }
189
+ };
190
+ }
191
+
192
+ public static <T extends MemberMappingView > Comparator <T > compareBySrcNameDescShortFirst () {
193
+ return (a , b ) -> {
194
+ int cmp = compareShortFirst (a .getSrcName (), b .getSrcName ());
195
+
196
+ return cmp != 0 ? cmp : compare (a .getSrcDesc (), b .getSrcDesc ());
197
+ };
160
198
}
161
199
162
200
public static int compare (@ Nullable String a , @ Nullable String b ) {
163
201
if (a == null || b == null ) return compareNullLast (a , b );
164
202
165
- return a .compareTo (b );
203
+ return ALPHANUM .compare (a , b );
204
+ }
205
+
206
+ public static int compare (String a , int startA , int endA , String b , int startB , int endB ) {
207
+ return ALPHANUM .compare (a .substring (startA , endA ), b .substring (startB , endB ));
166
208
}
167
209
168
210
public static int compareShortFirst (@ Nullable String a , @ Nullable String b ) {
169
211
if (a == null || b == null ) return compareNullLast (a , b );
170
212
171
213
int cmp = a .length () - b .length ();
172
214
173
- return cmp != 0 ? cmp : a . compareTo ( b );
215
+ return cmp != 0 ? cmp : ALPHANUM . compare ( a , b );
174
216
}
175
217
176
218
public static int compareShortFirst (String a , int startA , int endA , String b , int startB , int endB ) {
177
219
int lenA = endA - startA ;
178
220
int ret = Integer .compare (lenA , endB - startB );
179
221
if (ret != 0 ) return ret ;
180
222
181
- for (int i = 0 ; i < lenA ; i ++) {
182
- char ca = a .charAt (startA + i );
183
- char cb = b .charAt (startB + i );
184
-
185
- if (ca != cb ) {
186
- return ca - cb ;
187
- }
188
- }
223
+ return ALPHANUM .compare (a .substring (startA , endA ), b .substring (startB , endB ));
224
+ }
189
225
190
- return 0 ;
226
+ public static int compareNestaware (@ Nullable String a , @ Nullable String b ) {
227
+ return compareNestaware (a , b , false );
191
228
}
192
229
193
230
public static int compareShortFirstNestaware (@ Nullable String a , @ Nullable String b ) {
231
+ return compareNestaware (a , b , true );
232
+ }
233
+
234
+ private static int compareNestaware (@ Nullable String a , @ Nullable String b , boolean shortFirst ) {
194
235
if (a == null || b == null ) {
195
236
return compareNullLast (a , b );
196
237
}
@@ -201,8 +242,11 @@ public static int compareShortFirstNestaware(@Nullable String a, @Nullable Strin
201
242
int endA = a .indexOf ('$' , pos );
202
243
int endB = b .indexOf ('$' , pos );
203
244
204
- int ret = compareShortFirst (a , pos , endA >= 0 ? endA : a .length (),
205
- b , pos , endB >= 0 ? endB : b .length ());
245
+ int ret = shortFirst
246
+ ? compareShortFirst (a , pos , endA >= 0 ? endA : a .length (),
247
+ b , pos , endB >= 0 ? endB : b .length ())
248
+ : compare (a , pos , endA >= 0 ? endA : a .length (),
249
+ b , pos , endB >= 0 ? endB : b .length ());
206
250
207
251
if (ret != 0 ) {
208
252
return ret ;
@@ -226,7 +270,7 @@ public static int compareNullLast(@Nullable String a, @Nullable String b) {
226
270
} else if (b == null ) { // only b null
227
271
return -1 ;
228
272
} else { // neither null
229
- return a . compareTo ( b );
273
+ return ALPHANUM . compare ( a , b );
230
274
}
231
275
}
232
276
@@ -269,6 +313,7 @@ public boolean isMethodVarsFirst() {
269
313
return methodVarsFirst ;
270
314
}
271
315
316
+ private static final AlphanumericComparator ALPHANUM = new AlphanumericComparator (Locale .ROOT );
272
317
private Comparator <ClassMappingView > classComparator ;
273
318
private Comparator <FieldMappingView > fieldComparator ;
274
319
private Comparator <MethodMappingView > methodComparator ;
0 commit comments