From a01886a28310faa6825378f218b27934b2b23d8b Mon Sep 17 00:00:00 2001 From: Harsh Kapse Date: Wed, 9 Sep 2026 12:05:05 +0530 Subject: [PATCH] fix(render): badge every structural move and collapse nested move spans Move destinations were unreadable: most teal spans carried no L-number, nested fragments painted tag soup, and badges hid in dim grey. - serialize: emit highlight spans only for outermost moves - sbs/inline: badge decl/block/multiline moves in any hunk, single-line shifts only across hunks - sbs/inline: render badges in move-teal instead of dim overlay - goldens: 9 expected_ui fixtures regenerated (span reductions only) --- internal/inline/render.go | 47 +++---------- internal/inline/render_test.go | 3 +- internal/inline/slicer.go | 4 +- internal/serialize/spans.go | 63 ++++++++++++++++++ internal/serialize/spans_test.go | 18 +++++ internal/sidebyside/render.go | 59 ++-------------- internal/sidebyside/slicer.go | 2 +- .../c_redis_dict_resize/expected_ui.json.gz | Bin 392 -> 370 bytes .../expected_ui.json.gz | Bin 3752 -> 3744 bytes .../go_gin_using_keyed/expected_ui.json.gz | Bin 2730 -> 2706 bytes .../expected_ui.json.gz | Bin 8288 -> 8265 bytes .../expected_ui.json.gz | Bin 5925 -> 5906 bytes .../expected_ui.json.gz | Bin 7346 -> 7338 bytes .../expected_ui.json.gz | Bin 5763 -> 5738 bytes .../expected_ui.json.gz | Bin 1003 -> 1000 bytes 15 files changed, 102 insertions(+), 94 deletions(-) diff --git a/internal/inline/render.go b/internal/inline/render.go index 15e2b3a..114259a 100644 --- a/internal/inline/render.go +++ b/internal/inline/render.go @@ -6,8 +6,6 @@ import ( "fmt" "os" "path/filepath" - "slices" - "sort" "strconv" "strings" "unicode/utf8" @@ -74,7 +72,7 @@ func (s *inlineScratch) ensureCapacity(n int) { type hunkMoveMetadata struct { srcLine1Badges map[int]string // Line index -> " ➔ L..." dstLine1Badges map[int]string // Line index -> " ⤹ L..." - hunkHeaders map[int]string // Hunk index -> " (moved {from/to} L...[, modified])" + hunkHeaders map[int]string // Hunk index -> " (moved {from/to} L...)" } // Render formats the diff envelope as an inline diff with AST highlights and move markers. @@ -453,7 +451,7 @@ func Render(srcFile, dstFile string, srcBytes, dstBytes []byte, env *serialize.E lineRendered := renderLineWithSpans(l.text, leftSpansByLine[l.srcLineIdx], true, "left", opts.Color, scratch, peerDepictsEdit(leftToRight, rightSpansByLine, l.srcLineIdx)) if opts.Color { if badge != "" { - badge = color.Italic + color.OverlayFg + badge + color.Reset + badge = color.MoveFg + badge + color.Reset } if opts.LineNumbers { out.WriteString(gutter + lineRendered + badge + "\n") @@ -504,7 +502,7 @@ func Render(srcFile, dstFile string, srcBytes, dstBytes []byte, env *serialize.E lineRendered := renderLineWithSpans(l.text, rightSpansByLine[l.dstLineIdx], false, "right", opts.Color, scratch, peerDepictsEdit(rightToLeft, leftSpansByLine, l.dstLineIdx)) if opts.Color { if badge != "" { - badge = color.Italic + color.OverlayFg + badge + color.Reset + badge = color.MoveFg + badge + color.Reset } if opts.LineNumbers { out.WriteString(gutter + lineRendered + badge + "\n") @@ -662,19 +660,6 @@ func buildHunkMoveMetadata(actions []serialize.Action, hunks []interval, pairs [ return meta } - // Collect destination mutating byte offsets to check whether moved nodes were edited - var dstMutOffsets []uint32 - for _, a := range actions { - if a.Action == "insert" || a.Action == "update" || a.Action == "move_update" { - if a.DestStartByte != nil { - dstMutOffsets = append(dstMutOffsets, *a.DestStartByte) - } else if a.DestNode != nil { - dstMutOffsets = append(dstMutOffsets, a.DestNode.StartByte) - } - } - } - slices.Sort(dstMutOffsets) - // Index lines into hunks so we can tell if moves cross hunk boundaries srcLineToHunk := make(map[int]int) dstLineToHunk := make(map[int]int) @@ -699,15 +684,12 @@ func buildHunkMoveMetadata(actions []serialize.Action, hunks []interval, pairs [ sEnd, _ := serialize.ByteToLineCol(srcOffsets, a.Node.EndByte) var dStart, dEnd int - var dStartByte, dEndByte uint32 if a.DestStartByte != nil && a.DestEndByte != nil { dStart, _ = serialize.ByteToLineCol(dstOffsets, *a.DestStartByte) dEnd, _ = serialize.ByteToLineCol(dstOffsets, *a.DestEndByte) - dStartByte, dEndByte = *a.DestStartByte, *a.DestEndByte } else if a.DestNode != nil { dStart, _ = serialize.ByteToLineCol(dstOffsets, a.DestNode.StartByte) dEnd, _ = serialize.ByteToLineCol(dstOffsets, a.DestNode.EndByte) - dStartByte, dEndByte = a.DestNode.StartByte, a.DestNode.EndByte } else { continue } @@ -715,16 +697,7 @@ func buildHunkMoveMetadata(actions []serialize.Action, hunks []interval, pairs [ hSrc, inSrcHunk := srcLineToHunk[sStart] hDst, inDstHunk := dstLineToHunk[dStart] - // Omit annotations for moves staying within the same hunk - if inSrcHunk && inDstHunk && hSrc == hDst { - continue - } - - // Check if any mutations fall inside the destination range - idx := sort.Search(len(dstMutOffsets), func(i int) bool { - return dstMutOffsets[i] >= dStartByte - }) - isModified := idx < len(dstMutOffsets) && dstMutOffsets[idx] < dEndByte + // Teal alone doesn't say where it went, so badge every structural move. isDecl := r != nil && r.IsDeclaration(a.Node.Type) isBlock := r != nil && r.IsBlock(a.Node.Type) @@ -733,24 +706,24 @@ func buildHunkMoveMetadata(actions []serialize.Action, hunks []interval, pairs [ if !isDecl && !isBlock && !isMultiLine && !isStatement { continue } + // Same-hunk one-liners can see their destination on screen, so skip the badge. + if !isDecl && !isBlock && !isMultiLine && inSrcHunk && inDstHunk && hSrc == hDst { + continue + } if isDecl { // Top-level declaration moves are summarized directly in the hunk header sig := extractDeclarationSignature(a.Node, srcLines, sStart, sEnd) if sig == "declaration" { sig = extractDeclarationSignature(a.Node, dstLines, dStart, dEnd) } - modStr := "" - if isModified { - modStr = ", modified" - } if inSrcHunk && sig != "" { if _, exists := meta.hunkHeaders[hSrc]; !exists { - meta.hunkHeaders[hSrc] = fmt.Sprintf(" %s (moved to L%d%s)", sig, dStart+1, modStr) + meta.hunkHeaders[hSrc] = fmt.Sprintf(" %s (moved to L%d)", sig, dStart+1) } } if inDstHunk && sig != "" { if _, exists := meta.hunkHeaders[hDst]; !exists { - meta.hunkHeaders[hDst] = fmt.Sprintf(" %s (moved from L%d%s)", sig, sStart+1, modStr) + meta.hunkHeaders[hDst] = fmt.Sprintf(" %s (moved from L%d)", sig, sStart+1) } } } else { diff --git a/internal/inline/render_test.go b/internal/inline/render_test.go index 3867ca9..3e44210 100644 --- a/internal/inline/render_test.go +++ b/internal/inline/render_test.go @@ -202,7 +202,8 @@ func TestRender_Tier1_IntraHunkMoveCleanliness(t *testing.T) { got := Render("a.go", "b.go", src, dst, dr.Envelope, RenderOptions{Color: false, ContextLines: 3, LineNumbers: true}) - // Under Tier 1, intra-hunk moves suppress right-margin ghost text completely. + // One-line shifts in the same hunk don't get badges. You can already see + // where they went. if strings.Contains(got, "←") || strings.Contains(got, "➔") || strings.Contains(got, "⤹") || strings.Contains(got, "moved to line") { t.Errorf("expected zero right-margin trailing ghost annotations for intra-hunk move, got:\n%s", got) } diff --git a/internal/inline/slicer.go b/internal/inline/slicer.go index 42f4160..92cde7e 100644 --- a/internal/inline/slicer.go +++ b/internal/inline/slicer.go @@ -306,14 +306,14 @@ func sliceInlineLine( if len(chunks) > 0 { last := len(chunks) - 1 if colorMode { - chunks[last] = append(chunks[last], color.Italic+color.OverlayFg+badgeText+color.Reset...) + chunks[last] = append(chunks[last], color.MoveFg+badgeText+color.Reset...) } else { chunks[last] = append(chunks[last], badgeText...) } } else { var b []byte if colorMode { - b = append(b, color.Italic+color.OverlayFg+badgeText+color.Reset...) + b = append(b, color.MoveFg+badgeText+color.Reset...) } else { b = append(b, badgeText...) } diff --git a/internal/serialize/spans.go b/internal/serialize/spans.go index 4311e5d..a2c5c2f 100644 --- a/internal/serialize/spans.go +++ b/internal/serialize/spans.go @@ -59,6 +59,10 @@ func BuildHighlightSpans(fileBytes []byte, actions []Action, side string, extraS lineIndex := BuildLineIndex(fileBytes) spansByLine := make(map[int][]internalSpan) + // Only the outermost move of a relocated block gets spans. The nested + // ones would paint the same teal twice. + skipNestedMove := nestedMoveActions(actions, side) + for i := range actions { a := &actions[i] switch a.Action { @@ -84,6 +88,9 @@ func BuildHighlightSpans(fileBytes []byte, actions []Action, side string, extraS case "move": actType := "move" + if skipNestedMove[i] { + continue + } if side == "left" && a.Node != nil { parent := a.OldParent if parent == nil { @@ -270,6 +277,62 @@ func isOnlyNonCharacters(b []byte) bool { return true } +// nestedMoveActions finds moves buried inside a bigger move on the same side. +// Skipping them keeps a relocated block to one span instead of one per token. +func nestedMoveActions(actions []Action, side string) map[int]bool { + type byteRange struct { + idx int + s uint32 + e uint32 + } + var ranges []byteRange + for i := range actions { + a := &actions[i] + if a.Action != "move" { + continue + } + var s, e uint32 + var ok bool + if side == "left" && a.Node != nil { + s, e, ok = a.Node.StartByte, a.Node.EndByte, true + } else if side == "right" { + if a.DestStartByte != nil && a.DestEndByte != nil { + s, e, ok = *a.DestStartByte, *a.DestEndByte, true + } else if a.DestNode != nil { + s, e, ok = a.DestNode.StartByte, a.DestNode.EndByte, true + } + } + if !ok || e <= s { + continue + } + ranges = append(ranges, byteRange{idx: i, s: s, e: e}) + } + // Plain O(n^2) scan, there are never enough moves per file for this to matter. + slices.SortFunc(ranges, func(a, b byteRange) int { + return cmp.Or( + cmp.Compare(b.e-b.s, a.e-a.s), + cmp.Compare(a.s, b.s), + ) + }) + skip := make(map[int]bool) + var kept []byteRange + for _, r := range ranges { + contained := false + for _, k := range kept { + if k.s <= r.s && k.e >= r.e { + contained = true + break + } + } + if contained { + skip[r.idx] = true + continue + } + kept = append(kept, r) + } + return skip +} + func nodeRefsEqual(n1, n2 *NodeRef) bool { if n1 == n2 { return true diff --git a/internal/serialize/spans_test.go b/internal/serialize/spans_test.go index e2c8361..4ac3c85 100644 --- a/internal/serialize/spans_test.go +++ b/internal/serialize/spans_test.go @@ -429,3 +429,21 @@ func TestBuildHighlightSpansWithDelimiterSpan(t *testing.T) { t.Errorf("expected delimiter span on line 2 cols 0..1 action='delete', got %+v", leftSpans[1]) } } + +func TestNestedMoveActionsKeepsOutermost(t *testing.T) { + src := []byte("0123456789abcdef\n") + actions := []Action{ + {Action: "move", Node: &NodeRef{Tree: "before", Type: "block", StartByte: 0, EndByte: 16}}, + {Action: "move", Node: &NodeRef{Tree: "before", Type: "identifier", StartByte: 2, EndByte: 5}}, + {Action: "move", Node: &NodeRef{Tree: "before", Type: "identifier", StartByte: 10, EndByte: 12}}, + } + spans := BuildHighlightSpans(src, actions, "left") + for _, s := range spans { + if s.Action == "move" && s.ActionRef != nil && s.ActionRef.Node.StartByte != 0 { + t.Fatalf("expected only outermost move spans, got nested %+v", s) + } + } + if len(spans) == 0 { + t.Fatal("expected outermost move span, got none") + } +} diff --git a/internal/sidebyside/render.go b/internal/sidebyside/render.go index 67fb575..2c6e6eb 100644 --- a/internal/sidebyside/render.go +++ b/internal/sidebyside/render.go @@ -1,12 +1,9 @@ package sidebyside import ( - "cmp" "fmt" "io" "os" - "slices" - "sort" "strconv" "strings" @@ -738,27 +735,6 @@ func buildMoveBadges( r = rules.Get(lang.Name) } - type mutatingSpan struct { - startByte uint32 - endByte uint32 - } - var dstMutations []mutatingSpan - for _, a := range actions { - if a.Action == "insert" || a.Action == "delete" || a.Action == "update" || a.Action == "move_update" { - if a.Node != nil && a.Node.Tree == "after" { - dstMutations = append(dstMutations, mutatingSpan{startByte: a.Node.StartByte, endByte: a.Node.EndByte}) - } else if a.DestStartByte != nil && a.DestEndByte != nil { - dstMutations = append(dstMutations, mutatingSpan{startByte: *a.DestStartByte, endByte: *a.DestEndByte}) - } - } - } - slices.SortFunc(dstMutations, func(a, b mutatingSpan) int { - return cmp.Or( - cmp.Compare(a.startByte, b.startByte), - cmp.Compare(a.endByte, b.endByte), - ) - }) - type crossHunkMove struct { sStartLine int sEndLine int @@ -767,7 +743,6 @@ func buildMoveBadges( sHunk int dHunk int isDecl bool - nMut int } var crossMoves []crossHunkMove @@ -802,28 +777,7 @@ func buildMoveBadges( dHunk = -1 } - // Skip badges if the move stays within the same hunk and is close by. - lineDist := sStartLine - dStartLine - if lineDist < 0 { - lineDist = -lineDist - } - if sHunk != -1 && dHunk != -1 && sHunk == dHunk && lineDist < 10 { - continue - } - - // Count edits inside the moved node so we know if it was modified. - nMut := 0 - if dEndByte > dStartByte && len(dstMutations) > 0 { - idx := sort.Search(len(dstMutations), func(i int) bool { - return dstMutations[i].startByte >= dStartByte - }) - for idx < len(dstMutations) && dstMutations[idx].startByte < dEndByte { - if dstMutations[idx].endByte <= dEndByte { - nMut++ - } - idx++ - } - } + // Teal alone doesn't say where it went, so badge every structural move. isDecl := r != nil && r.IsDeclaration(a.Node.Type) isBlock := r != nil && r.IsBlock(a.Node.Type) @@ -832,6 +786,10 @@ func buildMoveBadges( if !isDecl && !isBlock && !isMultiLine && !isStatement { continue } + // Same-hunk one-liners can see their destination on screen, so skip the badge. + if !isDecl && !isBlock && !isMultiLine && sHunk != -1 && dHunk != -1 && sHunk == dHunk { + continue + } m := crossHunkMove{ sStartLine: sStartLine, @@ -841,7 +799,6 @@ func buildMoveBadges( sHunk: sHunk, dHunk: dHunk, isDecl: isDecl, - nMut: nMut, } crossMoves = append(crossMoves, m) } @@ -856,11 +813,7 @@ func buildMoveBadges( if m.dStartLine >= 0 && m.dStartLine < len(dstLines) { if _, exists := dstLineBadges[m.dStartLine]; !exists { - modStr := "" - if m.nMut > 0 { - modStr = ", modified" - } - dstLineBadges[m.dStartLine] = fmt.Sprintf(" ⤹ L%d%s", m.sStartLine+1, modStr) + dstLineBadges[m.dStartLine] = fmt.Sprintf(" ⤹ L%d", m.sStartLine+1) } } } diff --git a/internal/sidebyside/slicer.go b/internal/sidebyside/slicer.go index f4c4601..094ccb9 100644 --- a/internal/sidebyside/slicer.go +++ b/internal/sidebyside/slicer.go @@ -63,7 +63,7 @@ func (s *RenderScratch) SliceLineToChunks( // Put the move badge on the first chunk only. if isFirstChunk && badgeText != "" { if colorMode { - curChunk = append(curChunk, color.Italic+color.OverlayFg+badgeText+color.Reset...) + curChunk = append(curChunk, color.MoveFg+badgeText+color.Reset...) } else { curChunk = append(curChunk, badgeText...) } diff --git a/tests/testdata/c_redis_dict_resize/expected_ui.json.gz b/tests/testdata/c_redis_dict_resize/expected_ui.json.gz index 2a33e3ebc07fe8a5da7333df58e61a6350841a19..46fb5f2154f70f86d07df2ce78f490821c1da060 100644 GIT binary patch literal 370 zcmb2|=3oGW|5L79%sONs!uH^|o$HBGcI)R?qH3oarfl$G-r6+nUeDg&FEaj>d|4iy zAM(d`+0P%SNGik#c|^6Jj#MzudG z>vijwP6|p~xhy0yOVe~(nC9AuUEVMImX>;DPkR@7vJB2MXt$-NyT@Y)p06Q@%a0U3=IGO N-+JW!Ifb2p0RR~+!iN9= literal 392 zcmV;30eAi%iwFP!00000|CH6iYQjJe2H<<1V%c*F&PcTO@v8_S-qPjTp8L29@g}jnztpvT+P`=0p+BX5h`aDwgb*HoLs*sh z;`jes`6rc}3QIMo%2Lazv9!u*#nN?7*DS4bTC;SM(+x|ToHi`o=5$LnfF)eZxu}-_ zOsJTEOsJUvO{kiHO{kjyPNe7(n^Ola5XFKbp4?9>Y+(kT{Z~vZCQgOz)(HJ+& z?$oa;SyHh=#j55N(WuM4KMOnM&z0Er*K`^9?MyrCf=>@NlZy4Sb9FhH@HuS0?yE)p m^);B&CCpB<%+t4R^t-g?C-3bozJCG$0RR6{Xs>lc2mk<@RL{5o diff --git a/tests/testdata/c_redis_quadratic_search/expected_ui.json.gz b/tests/testdata/c_redis_quadratic_search/expected_ui.json.gz index 331401c06aa46b81688ed8f7b51b3838f599a903..17faf32fc77069bbf296c19fb64fcb016226d897 100644 GIT binary patch delta 2423 zcmY*beLT}^8<%Vhqhn9DVU5blOSCCVNJ=?%rbw|;t^AfeXh@_ETQASaiJwjVDtuN^ zoxDV6c6vd|kO92wpgCdj^z?W7CAXb0@nAB$Vda_%!PNMg3Ql}0%64^zW>Ok29QACa(6Q-G!@7Q6-EFl;i?^MSN>HuKH;tyMz%g+OM_H^bci!&Mh?e{;nc( z4Heb1D`)MeN;(8(jQi|gv{5Rjko6RR;EZ$TLK=P(vtDoYitWlr?Pe(8)t0K;>Dc5Y7^0O1jpp`gr?Y zlc{fQZ5_&b_Q24|a8ZKFQ>dt%y&+RV(+hrB)YQd(qOSWd6s@W%gK+vJj(TWswv<0S z5WheY`X}|kCWYE+wjkq!HDin71U|KQ_ygbNx7ZZ>)R%WBGX-~JpX5}JcT5Ikzob^* ztR6f!3y1ziJ+MnrF}Sg5hy8hb`H33lGRPOo3_$L1Uyt|dRx|aEEW6@+B{K-Q%Y8eZ zcDOJnKiqjSW)FBjd_$QyfYY!T5aiT^J6mG*f|Bq}8Nz+E7;;hu$^|}7Zf}seke=d( z8|txuC`S))#%1_MvK;GiPH;UA5a-we&Unlba1~Gs3L|LO$x|R|4Sbt?36`xP{e>%m z>#cw;I@gs{Q5*@xSYudVBJeI#7)z@mTXHY1gJH6rm_zp zfVI_QJq7waVKS|c?9M}Z!$V}DSmsSq<66XiL_m}C5hx{MIG`5L&k~-Y8BpA_RBDS% ze!4GgM)7T=Zz37v!y5l(2cUD;F-Pn$zk*wsOD_p8(pFMJE?wLLyHK7t(zhmo0uraP zIF4Dm48sFcnfjN7Su{V2`(@NNcsqsMB-=(>iT|m|&mM5fEn}A2W3s_#%mH<6Hb0#P zM^J7x(E~{C_^Kv@6@W+X2WHF)%uP_mdx zH$M1_9+Z!8KqScX`~Ihbz#_UTMq2`)K%Hh4!r~v5Hae0r-t7jzIjD_${3~fWk`3A$ z%XdRP2DZ>a1j@KYhki>b#b)tHQKK;M(*H>X0W&MU zN*Q92x5c;ju^gepI^}d-+CaYMm=Fx@*X@;Vh(Wdq^{#*8qT@4F7WRulShjD(aS7H6z*74sg&bx^pY&UJQ+37@HCn6}VQ)Mkw)Hm`432lV3_wogR?&y~vhIS2%zi;||JQC~a*5ArJT5vsgr1gp$bR!oc zqEN`rWExj-6DmX5LRKg<Ssf`91p&XE>K>ziX#n48SgZUTAKyu)S5_yJMGbkps#Ml;6>Sn}vbxH#ITf>iDgI=Q?j6aQ+c~P&rW!%^cEi!iCIKf8x zEXPR8iQ?sw@C{ds_O=#YUYjwqyEcNHxBZp#RPaT9!x_g@59opRah8~S25sS+_i&$^ z$#=hX4%v;m-T*qDeIN_6_h0OJudnD;Ya?zm#XXn;=YW#yAbBO=<^X`rvesr?9VO`{ z1+Fk~d@j!Ie4MGBoMvYO7*P|9#J07P<+bGWIBG_m>9W28z@{f+ zNe}MFirgR9ZMFCVT7_PU5aY%h10Y{CR=0z}-^!>*HXS2H8^mvEx+N_+qIE-cjGw*P zDYN1MC5JsXIKY$oXg|+PR|WL}m!xX_RPErnxRAFqFK@}<0Jq-<$n1*xq;3&#o~FJ{ ze)vyMJ zIT@*VwlB4_dMb)n)yw&GfYUNDw(i+%7q@DRJ27ojcnMMvW8W$8O=Hsh>6B(r zd~;|nQ8X7dI=Ap$31hV4*2lJ|Nt_yWX|k$t_P`ysbf%EE`hoS+M23fpQX1yPtM(e3 ldzmE_x$>&!_rEB&W85q!&P^zEAFTQLLz8nGasWNO{{TA7yq5p~ delta 2374 zcmY*WeLR!vA69G(QxS#@sg_0c8`Tn-KB>;{G)a_oQj%Ok<_r9+?gggRhlcc9LUvp{Q zZ@3>`nO+`K{c?3by00%znCeX)yDz|KAjIGf{bL#49kp59NPvS<5;CT@yHt!F2DH6@&5 z$5pZ?W-iaE=fED(w5WKpR(hA9l|llyFWRBsY+m7cv4xboIi2uT&{lPBu%|!Hfq9iRvi%uG!~pm#x3+$Zi%gfF8rfwqV)fM0JaF^g}51(9980 zwA>Yj2n&f|NzX&&p?G;w^PogNQF(U2;Uj7)?j$fRt=})6A`a^TR@j*8|=8ueaFRcZy5+o~UnANQ>6)ba8D8?Vjw< zofkoOP$ZP1lGow|5m4sP9+WwniWsB9S3?g_Hc%eQ2tDm$mN35|Y011+2xl_OvY3u} zy`~$W09`BSs;&vTlb-v`s~_^#wZ~kZ}Z*4~<2AH$c%04{HtTi(+5 zR2=l7+;|n)2IqyB6@)t$z9}lSG8ozDFoLvJOS-Dz%J8!4a7Q5k`Jk7gKhX0U{@*qa zo`E#B>(DO&pEZSGVa({$;^hoHR`y#)+(^1bBQtKL_QZ9RFevP4L2L0AM9z<0R-Ebe6*_u{r!^0#lg zv?QvH%#CnPi7;HzOkemr)pZSxn#+|1bJ4sal@sV{EuE?h#V3s752Yi_RC M?)Gv0U@fh`0Z_W5asU7T diff --git a/tests/testdata/go_gin_using_keyed/expected_ui.json.gz b/tests/testdata/go_gin_using_keyed/expected_ui.json.gz index 8b06a9b63f24fe728ffb513d21220d3d87361ebe..730cc4fca098527ffece155531dadfefa09e604a 100644 GIT binary patch literal 2706 zcmb7DdsI_r66dtCK8jeyTPP6OBduU;VI%Tr1LSNGQ4nKDcqkG|QbC{)BQFVXDR$L0 zlEiIMBLX=~>DT=h!W;JYrh{%hOVEpr5;JN`@rsj?0Iu^6saWH zz>8SxaAf_8UN|8mD;HQlKXbRUb8>(qUC`@0)dSjCvb29POKRfdX*}G*lmSn}feW)L zwR^2nI74+i}}(m$&^RCq9<7 ziPQ7-E-j}A%PQma*d$+#f^L2DPL6y{MAX%Y>v!UBl>-r?^EGwRHAhd5CRJ?vGIAR^ zuI1qD8e^i)M&CQ(0=A4=o`!GEt^U=asgmOd@giOwF9H{bs{!wTEpwjwNqMa}wibM# z6wh9OUiPqHhAvq%Ad00*$*{dKTj!ylnMly6<=unbBHnBQ8T>g8R}0EOGF%8t=H6dK zG}M3&`r!!aT4Rbxc?zzV)9!-96AjZe*8I?SW-Csbq8qML*3YF3(xPE6O+zh+)elEX zQO2htB^%buX>Fi!qJb*S(+$rWQo(78*%B*T=bjGIV&P0p)>Uw&9vdNj+lUe=3t+Zf z`yJRek@dNhs>9YP#d9dhvG#|SF9i*9EgOC&QlgBHBBfZpF=UJ?#js(SkG{E9oz?~# zbh*zY`si*of|{IFG$|SWE(YZIZ}0$_B2Dw-*%(Vj-Dlt~UG6?j)-}*YkByX?ead!` zTCTkZCiGwQwmKePkbU<=LIl^F{Fzc_UuxUaaP=WgQrLR96jYu3<>PHS2loov0g>`J zCa*IImUWIt_fIywbMDH|mU~k7FbckjE+*G~(WriF3(;SZKB#`nB>-pZ`~E_cMaR28 zS`tnb*lqRPcyF)Z$)8UJuU(A^N56-b1qTK|hqkW8AM5>lHTNUH2H;nems9FVhe%cz znT5>pFfjo`Mt_PP3xR^5uLP?E+`j_i}}Hen2>IqiRG*c|rOjd@qk#!<;7egk$p2 zt>{1P4~&9V2<=36e+3Q$9@YA3f0Xy5Hf)AsM?YG&KQJ0{6do7Z?F8t+x7Czul#Sti z;rGj#&CEE`KO!+Kv>q)Z1ja(XLaM~n9_n02*&J>aQFw)Uhk1!akHQq8!_bvsP%soF zJR;zR0Peuog3Xnb?cw)Hg_XBCS?8M)6(p-FW(jkgBqn0Y&sV!kvL!bmrnwGB3y%0b$RJAX@HQ!^sllICyb_k8f}(aJ@lZ^oL(edv{Wp($~B z+@dTuIWQyjHV2jSN(El0Axh=A!khI6?IDDqjpy8;~*6x5*o&*1K8vv%W>Vld_-uGD)1? z98L8mwPBFpw{J@PDu#YtpB?L6r^mXouULmWe{^zU}@n<_=-JzhdKhZwD_8^+v5fA)54hxy3n-)A3lJe*mi za=pQKL_niH9U9j*LVVCCze29jolhVdyyRIX$=l=8J-tuH9vVR+w;+N8Ht8(C{xsizewx+-&b{Ec6g$2SRUd0AU{Ho;QxD#x`=v;>>`E(cXq}49H!)1w z$TIx=^!E(8q&08hsj4>iMaXfS`_Y`#k;V`8JGYzKyJuj@kJ_d)s$HEn-PMo%hN}GW z+>4{n(`>p8wd@4{ZhHK6>C<(N9$KYWn&v{O(kD%$_Vpy@KhKu%s;bCJRfncwem7Tp nq=r*wToV`HKZNg6#EqHeeP^d?^H*9}m`r@f0n7EfEiC>6+1Y&q literal 2730 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 literal 8288 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 KBJ2=BApZ$pL7Jri diff --git a/tests/testdata/lua_neovim_fs_api_refactor/expected_ui.json.gz b/tests/testdata/lua_neovim_fs_api_refactor/expected_ui.json.gz index 4928ec039937eeafef9e8fc69276080bde34ce95..33b9af2191f3d96c5ba94b51e0b698e14381b25d 100644 GIT binary patch literal 5906 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 literal 5925 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 bt*767CwVn9ZL(y^%#5uvefMO-k|qBIGS9uq diff --git a/tests/testdata/lua_neovim_gen_help_html_change/expected_ui.json.gz b/tests/testdata/lua_neovim_gen_help_html_change/expected_ui.json.gz index 80c1ecb08fd76c9214bd4feb3a7967cbe54d9b44..1c5e8afd98993fecddccf32f15175e2f6927a605 100644 GIT binary patch literal 7338 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 literal 7346 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 Xm;0xr{3R+X)6+>b)DwdQ6_x)2XC-oZ literal 5763 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 delta 817 zcmV-11J3;D2kQraABzY8000000ROz$%T6mt5C-7ApJFs?kotb%RiX$XF#$`)MBuQA z^6n84^H)dx(_Ln9HVHa)%5(U-rmD+-AC_hP*xufcujln{SwHN0^Z7@o<9WM(I31tP zFWdRD-Yvf!mSy?+@3NSi{fGbl|NG7VqIQp37Ik~nv8dmXfXIJtsZX?%xEsfBkss;# zG;#j<@Q?I-BK#vgpD1I8PbK(AdOi{Uk)BV4f28LV;UDSwB=|>qJ_$aF`X%@$>X+b` zsGs;J>es}nUlXT(O`Q5Qaq8E^sb3SPeiF}<`pc90&D1ZU{xbDTar}OyG>PX)yiDSC z9M6;YKTqEOJb8crGwLtX`pM!)>nFo6^P3_3GOeF1S4Ubu8Gf18PljKi^;6(i=R06QP5p{ozo}oH)L(^P>R;hkC;hMT?M8gR*>9Q!hi`v4MphidcN`;2j+smmYbImF zn#mlohA%osHYvkb9V5Gx;meMhbYp8K?bw>GA0NK{(t6tdxZFPR+ZPEd{F(0xj%dP!eo>vWA)lzCIheOhk0H&P4B*{3DP`8 z7i>m>pwfRQ2Ef~A-@keSc+~{xD?`)mNIl`F^>}}N-`*}fQNFe7A9r0|^FYO*5^DQP z2bH1#*`U&-kuuT@VKS&Rl4MY6<{Rl)3Q0DoG--Xi@(M{Zs5A#48+!9yzSmUqcvg)P zhqG#wIGk0Z#Nn(OB@SoRAaOXWMtQ?oHA)=LszG9PKkd3QtB{ygPb}TYQBAnMpDCI= vOVcTJ`DS6duFbPVO`mUO@l`uQvvtki;m>h=_~+jM00960>EKV=I~@Q34+XC@