[cli] fix check --fix crash on overlapping diagnostic edits#389
[cli] fix check --fix crash on overlapping diagnostic edits#389
check --fix crash on overlapping diagnostic edits#389Conversation
Replace `TextDocument.applyEdits()` (which throws on overlapping edits) with a custom `applyDiagnosticFixes()` that processes each diagnostic atomically — if any edit from a diagnostic overlaps with an already-accepted edit, the entire diagnostic is skipped and retried in the next iteration. Also ensures `--error-format=json` is passed last to moc so user-provided flags like `--error-format=human` don't break the fix pipeline. Made-with: Cursor
Benchmark Resultsbench/1-buffer-vector-add.bench.mo
|
| 10 | 10000 | 1000000 | |
|---|---|---|---|
| Buffer | 9_557 |
5_687_594 |
525_783_888 |
| Vector | 13_525 |
4_378_612 |
417_864_498 |
Heap
| 10 | 10000 | 1000000 | |
|---|---|---|---|
| Buffer | 272 B |
272 B |
272 B |
| Vector | 272 B |
272 B |
272 B |
Garbage Collection
| 10 | 10000 | 1000000 | |
|---|---|---|---|
| Buffer | 1.09 KiB |
143.28 KiB |
12.02 MiB |
| Vector | 1.09 KiB |
45.65 KiB |
3.86 MiB |
bench/2-vector-buffer-add.bench.mo $({\color{green}-10.02\%})$
Add
Add items one-by-one
Instructions:
Heap:
Stable Memory:
Garbage Collection:
Instructions
| 10 | 10000 | 1000000 | |
|---|---|---|---|
| Vector | 13_525 |
4_378_966 |
417_886_092 |
| Buffer | 9_557 |
5_686_886 |
525_781_056 |
Heap
| 10 | 10000 | 1000000 | |
|---|---|---|---|
| Vector | 272 B |
272 B |
272 B |
| Buffer | 272 B |
272 B |
272 B |
Garbage Collection
| 10 | 10000 | 1000000 | |
|---|---|---|---|
| Vector | 1.09 KiB |
45.65 KiB |
3.86 MiB |
| Buffer | 1.09 KiB |
143.28 KiB |
12.02 MiB |
bench/array.bench.mo $({\color{green}-17.47\%})$
Array
arr arr
Instructions:
Heap:
Stable Memory:
Garbage Collection:
Instructions
| 100k x1 | reset1 | 100k x3 | reset2 | 100k x4 | reset3 | |
|---|---|---|---|---|---|---|
| Array | 13_502_096 |
3_335 |
27_003_270 |
3_809 |
54_004_127 |
4_283 |
Heap
| 100k x1 | reset1 | 100k x3 | reset2 | 100k x4 | reset3 | |
|---|---|---|---|---|---|---|
| Array | 390.9 KiB |
-390.37 KiB |
390.9 KiB |
-390.37 KiB |
390.9 KiB |
-390.37 KiB |
Garbage Collection
| 100k x1 | reset1 | 100k x3 | reset2 | 100k x4 | reset3 | |
|---|---|---|---|---|---|---|
| Array | 360 B |
390.97 KiB |
391 KiB |
390.97 KiB |
1.14 MiB |
390.97 KiB |
bench/prng.bench.mo $({\color{gray}0\%})$
Prng
Benchmark N next calls for different PRNGs
Instructions:
Heap:
Stable Memory:
Garbage Collection:
Instructions
| 10 | 100 | 1000 | 10000 | |
|---|---|---|---|---|
| Seiran128 | 1_694 | 15_194 | 150_194 | 1_500_194 |
| SFC64 | 2_802 | 28_962 | 288_557 | 2_882_655 |
| SFC32 | 2_383 | 23_825 | 237_026 | 2_379_333 |
Heap
| 10 | 100 | 1000 | 10000 | |
|---|---|---|---|---|
| Seiran128 | 272 B | 272 B | 272 B | 272 B |
| SFC64 | 308 B | 272 B | 272 B | 272 B |
| SFC32 | 280 B | 280 B | 272 B | 272 B |
Garbage Collection
| 10 | 100 | 1000 | 10000 | |
|---|---|---|---|---|
| Seiran128 | 296 B | 296 B | 296 B | 296 B |
| SFC64 | 536 B | 4.98 KiB | 47.16 KiB | 469.04 KiB |
| SFC32 | 376 B | 1.78 KiB | 15.39 KiB | 156.11 KiB |
bench/removeLast.bench.mo $({\color{green}-10.90\%})$
Remove items using removeLast
Vector and buffer are initialized with 100k items and then 70k items are removed one-by-one.
Instructions:
Heap:
Stable Memory:
Garbage Collection:
Instructions
| remove 70k | |
|---|---|
| Vector | 27_707_716 |
| Buffer | 29_236_977 |
Heap
| remove 70k | |
|---|---|
| Vector | -136.8 KiB |
| Buffer | -269.76 KiB |
Garbage Collection
| remove 70k | |
|---|---|
| Vector | 139.45 KiB |
| Buffer | 540.43 KiB |
bench/stable-memory.bench.mo $({\color{green}-134.03\%})$
Stable Memory and Region
Grow Region and store blobs in it
Instructions:
Heap:
Stable Memory:
Garbage Collection:
Instructions
| Region (fill 1/100) | Region (fill 1/50) | StableMemory | |
|---|---|---|---|
| 10 pages | 2_626_997 |
10_496_318 |
2_693 |
| 100 pages | 52_466_985 |
104_914_818 |
2_698 |
| 256 pages | 134_273_950 |
268_574_799 |
3_246 |
Heap
| Region (fill 1/100) | Region (fill 1/50) | StableMemory | |
|---|---|---|---|
| 10 pages | 272 B |
272 B |
276 B |
| 100 pages | 272 B |
272 B |
272 B |
| 256 pages | 272 B |
272 B |
276 B |
Garbage Collection
| Region (fill 1/100) | Region (fill 1/50) | StableMemory | |
|---|---|---|---|
| 10 pages | 208.34 KiB |
832.38 KiB |
336 B |
| 100 pages | 4.06 MiB |
8.13 MiB |
340 B |
| 256 pages | 10.4 MiB |
20.8 MiB |
340 B |
Stable Memory
| Region (fill 1/100) | Region (fill 1/50) | StableMemory | |
|---|---|---|---|
| 10 pages | 8 MiB |
8 MiB |
8 MiB |
| 100 pages | 8 MiB |
8 MiB |
0 B |
| 256 pages | 16 MiB |
16 MiB |
16 MiB |
- Updated the `edit-suggestions` test to reflect changes in expected fixes. - Added a new test for handling overlapping edits, ensuring correct application of fixes. - Modified the `edit-suggestions.mo` file to remove unnecessary code and improve clarity. - Introduced a new `overlapping.mo` file to specifically test overlapping fix scenarios. These changes improve the robustness of the autofix feature by ensuring it can handle complex cases effectively.
|
|
||
| exports[`check --fix M0236: fix output 1`] = ` | ||
| "Fixed run/M0236.mo (2 fixes: M0236) | ||
| "Fixed run/M0236.mo (1 fix: M0236) |
There was a problem hiding this comment.
we changed how we count fixes:
moc returns multiple partial edits for a single diagnostic, now we count it as one
| do { | ||
| let ar = [1, 2, 3]; | ||
| let _ = Array.filter<Nat>( | ||
| Array.filter<Nat>(ar, func(x) { x > 0 }), |
There was a problem hiding this comment.
previously it was throwing an exception, because of overlapping edits -- here this line was both changed and removed. Now we pick one and fix the other in the next iteration
Summary
TextDocument.applyEdits()with a customapplyDiagnosticFixes()that processes each diagnostic atomically — if any edit overlaps with an already-accepted edit, the entire diagnostic is skipped and retried in the next iteration--error-format=jsonis passed last tomocso user-provided flags don't break the fix pipelineArray.filter<Nat>()calls (overlapping fixable errors)--error-format=humannot breaking--fixTest plan
Array.filter<Nat>()correctly fixed toar.filter(f).filter(f)--error-format=humanregression test passes