-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsorter.test.ts
More file actions
437 lines (399 loc) · 13.9 KB
/
Copy pathsorter.test.ts
File metadata and controls
437 lines (399 loc) · 13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
import { JavaMethodSorter, JavaParser, SortingOptions } from '../sorter';
/**
* Simple test runner for sorter logic
*/
function runTests(): void {
console.log('Running sorter tests...\n');
let passed = 0;
let failed = 0;
// Test 1: JavaParser - Extract class name
try {
const source = `public class TestClass { }`;
const parser = new JavaParser(source);
const result = parser.parse();
if (result?.name === 'TestClass') {
console.log('✓ Test 1 passed: JavaParser extracts class name');
passed++;
} else {
console.log('✗ Test 1 failed: JavaParser class name extraction');
failed++;
}
} catch (e) {
console.log('✗ Test 1 failed with error:', e);
failed++;
}
// Test 2: JavaParser - Parse simple class with methods
try {
const source = `
public class MyClass {
public void methodA() {
System.out.println("A");
}
private void methodB() {
System.out.println("B");
}
}`;
const parser = new JavaParser(source);
const result = parser.parse();
if (result && result.methods.length === 2) {
console.log('✓ Test 2 passed: JavaParser finds 2 methods');
passed++;
} else {
console.log('✗ Test 2 failed: Expected 2 methods, got', result?.methods.length);
failed++;
}
} catch (e) {
console.log('✗ Test 2 failed with error:', e);
failed++;
}
// Test 3: JavaMethodSorter - Sort by access level
try {
const source = `
public class MyClass {
private void privateMethod() {
System.out.println("private");
}
public void publicMethod() {
System.out.println("public");
}
}`;
const options: SortingOptions = {
sortingStrategy: 'depth-first',
applyWorkingListHeuristics: true,
respectBeforeAfterRelation: false,
clusterOverloadedMethods: false,
clusterGetterSetter: false,
separateByAccessLevel: true,
separateConstructors: true,
applyLexicalOrdering: false
};
const sorter = new JavaMethodSorter(options);
const sorted = sorter.sort(source);
// Public method should come before private method
const publicIdx = sorted.indexOf('publicMethod');
const privateIdx = sorted.indexOf('privateMethod');
if (publicIdx < privateIdx) {
console.log('✓ Test 3 passed: Methods sorted by access level');
passed++;
} else {
console.log('✗ Test 3 failed: Public method should come before private');
failed++;
}
} catch (e) {
console.log('✗ Test 3 failed with error:', e);
failed++;
}
// Test 4: JavaMethodSorter - Constructor separation
try {
const source = `
public class MyClass {
public void regularMethod() {
System.out.println("regular");
}
public MyClass() {
System.out.println("constructor");
}
}`;
const options: SortingOptions = {
sortingStrategy: 'depth-first',
applyWorkingListHeuristics: true,
respectBeforeAfterRelation: false,
clusterOverloadedMethods: false,
clusterGetterSetter: false,
separateByAccessLevel: true,
separateConstructors: true,
applyLexicalOrdering: false
};
const sorter = new JavaMethodSorter(options);
const sorted = sorter.sort(source);
// Constructor should come before regular method
const constructorIdx = sorted.indexOf('public MyClass()');
const regularIdx = sorted.indexOf('regularMethod');
if (constructorIdx < regularIdx) {
console.log('✓ Test 4 passed: Constructor comes before regular methods');
passed++;
} else {
console.log('✗ Test 4 failed: Constructor should come before regular methods');
failed++;
}
} catch (e) {
console.log('✗ Test 4 failed with error:', e);
failed++;
}
// Test 5: JavaMethodSorter - Shuffle randomly
try {
const source = `
public class MyClass {
public void methodA() { }
public void methodB() { }
public void methodC() { }
public void methodD() { }
public void methodE() { }
}`;
const options: SortingOptions = {
sortingStrategy: 'depth-first',
applyWorkingListHeuristics: false,
respectBeforeAfterRelation: false,
clusterOverloadedMethods: false,
clusterGetterSetter: false,
separateByAccessLevel: false,
separateConstructors: false,
applyLexicalOrdering: false
};
const sorter = new JavaMethodSorter(options);
// Shuffle multiple times and check that at least one is different
let foundDifferent = false;
for (let i = 0; i < 10; i++) {
const shuffled = sorter.shuffleRandomly(source);
if (shuffled !== source) {
foundDifferent = true;
break;
}
}
if (foundDifferent) {
console.log('✓ Test 5 passed: Shuffle produces different output');
passed++;
} else {
console.log('✗ Test 5 failed: Shuffle did not produce different output');
failed++;
}
} catch (e) {
console.log('✗ Test 5 failed with error:', e);
failed++;
}
// Test 6: JavaParser - Skips static initializer blocks
try {
const source = `
public class MyClass {
static {
System.out.println("Static block");
}
public void methodA() {
System.out.println("A");
}
}`;
const parser = new JavaParser(source);
const result = parser.parse();
// Should only find methodA, not println from static block
if (result && result.methods.length === 1 && result.methods[0].name === 'methodA') {
console.log('✓ Test 6 passed: JavaParser skips static initializer blocks');
passed++;
} else {
console.log('✗ Test 6 failed: Expected 1 method (methodA), got', result?.methods.map(m => m.name));
failed++;
}
} catch (e) {
console.log('✗ Test 6 failed with error:', e);
failed++;
}
// Test 7: JavaParser - Skips instance initializer blocks
try {
const source = `
public class MyClass {
{
System.out.println("Instance block");
}
public void methodA() {
System.out.println("A");
}
}`;
const parser = new JavaParser(source);
const result = parser.parse();
// Should only find methodA, not println from instance block
if (result && result.methods.length === 1 && result.methods[0].name === 'methodA') {
console.log('✓ Test 7 passed: JavaParser skips instance initializer blocks');
passed++;
} else {
console.log('✗ Test 7 failed: Expected 1 method (methodA), got', result?.methods.map(m => m.name));
failed++;
}
} catch (e) {
console.log('✗ Test 7 failed with error:', e);
failed++;
}
// Test 8: JavaParser - Skips inner class methods
try {
const source = `
public class MyClass {
public void outerMethod() {
System.out.println("Outer");
}
public static class Inner {
public void innerMethod() {
System.out.println("Inner");
}
}
}`;
const parser = new JavaParser(source);
const result = parser.parse();
// Should only find outerMethod, not innerMethod from inner class
if (result && result.methods.length === 1 && result.methods[0].name === 'outerMethod') {
console.log('✓ Test 8 passed: JavaParser skips inner class methods');
passed++;
} else {
console.log('✗ Test 8 failed: Expected 1 method (outerMethod), got', result?.methods.map(m => m.name));
failed++;
}
} catch (e) {
console.log('✗ Test 8 failed with error:', e);
failed++;
}
// Test 9: JavaMethodSorter - Preserves inner classes in output
try {
const source = `
public class MyClass {
public void outerMethod() {
System.out.println("Outer");
}
public static class Inner {
public void innerMethod() {
System.out.println("Inner");
}
}
}`;
const options: SortingOptions = {
sortingStrategy: 'depth-first',
applyWorkingListHeuristics: false,
respectBeforeAfterRelation: false,
clusterOverloadedMethods: false,
clusterGetterSetter: false,
separateByAccessLevel: false,
separateConstructors: false,
applyLexicalOrdering: false
};
const sorter = new JavaMethodSorter(options);
const sorted = sorter.sort(source);
// The inner class should be preserved in the output
if (sorted.includes('public static class Inner') && sorted.includes('innerMethod')) {
console.log('✓ Test 9 passed: Inner classes preserved in output');
passed++;
} else {
console.log('✗ Test 9 failed: Inner class not preserved in output');
failed++;
}
} catch (e) {
console.log('✗ Test 9 failed with error:', e);
failed++;
}
// Test 10: JavaMethodSorter - Preserves static and instance initializer blocks
try {
const source = `
public class MyClass {
static {
System.out.println("Static block");
}
{
System.out.println("Instance block");
}
public void methodA() {
System.out.println("A");
}
}`;
const options: SortingOptions = {
sortingStrategy: 'depth-first',
applyWorkingListHeuristics: false,
respectBeforeAfterRelation: false,
clusterOverloadedMethods: false,
clusterGetterSetter: false,
separateByAccessLevel: false,
separateConstructors: false,
applyLexicalOrdering: false
};
const sorter = new JavaMethodSorter(options);
const sorted = sorter.sort(source);
// Both initializer blocks should be preserved
if (sorted.includes('static {') &&
sorted.includes('System.out.println("Static block")') &&
sorted.includes('System.out.println("Instance block")')) {
console.log('✓ Test 10 passed: Initializer blocks preserved in output');
passed++;
} else {
console.log('✗ Test 10 failed: Initializer blocks not preserved');
failed++;
}
} catch (e) {
console.log('✗ Test 10 failed with error:', e);
failed++;
}
// Test 11: Comment indentation is preserved after sorting
try {
const source = `public class MyClass {
// 静态方法
public static void log(String msg) {
System.out.println("LOG: " + msg);
}
// 受保护方法
protected void finalizeTask() {
System.out.println("Finalize");
}
}`;
const options: SortingOptions = {
sortingStrategy: 'depth-first',
applyWorkingListHeuristics: false,
respectBeforeAfterRelation: false,
clusterOverloadedMethods: false,
clusterGetterSetter: false,
separateByAccessLevel: false,
separateConstructors: false,
applyLexicalOrdering: false
};
const sorter = new JavaMethodSorter(options);
const sorted = sorter.sort(source);
// Comments should maintain their indentation (4 spaces before //)
if (sorted.includes(' // 静态方法') && sorted.includes(' // 受保护方法')) {
console.log('✓ Test 11 passed: Comment indentation is preserved');
passed++;
} else {
console.log('✗ Test 11 failed: Comment indentation not preserved');
console.log('Sorted output:', sorted);
failed++;
}
} catch (e) {
console.log('✗ Test 11 failed with error:', e);
failed++;
}
// Test 12: No double blank lines between methods after sorting
try {
const source = `public class MyClass {
protected void methodA() {
System.out.println("A");
}
private void methodB() {
System.out.println("B");
}
}`;
const options: SortingOptions = {
sortingStrategy: 'depth-first',
applyWorkingListHeuristics: false,
respectBeforeAfterRelation: false,
clusterOverloadedMethods: false,
clusterGetterSetter: false,
separateByAccessLevel: true,
separateConstructors: false,
applyLexicalOrdering: false
};
const sorter = new JavaMethodSorter(options);
const sorted = sorter.sort(source);
// Should not have triple newlines (two blank lines) between methods
// Check that closing braces are followed by at most one blank line
const hasDoubleBlankLines = /\}\n\n\n/.test(sorted);
if (!hasDoubleBlankLines) {
console.log('✓ Test 12 passed: No double blank lines between methods');
passed++;
} else {
console.log('✗ Test 12 failed: Found double blank lines between methods');
console.log('Sorted output:', sorted);
failed++;
}
} catch (e) {
console.log('✗ Test 12 failed with error:', e);
failed++;
}
console.log(`\nResults: ${passed} passed, ${failed} failed`);
}
// Export for use in tests
export { runTests };
// Run if executed directly
if (require.main === module) {
runTests();
}