11/* eslint css-modules/no-unused-class: off */
22
3- import { createContext , CSSProperties , forwardRef , HTMLAttributes , memo , useContext , useRef , useState } from "react"
3+ import { createContext , CSSProperties , forwardRef , HTMLAttributes , useRef , useState } from "react"
44
55import { VersionsIcon } from "@primer/octicons-react"
6- import classNames from "classnames"
7- import memoize from "memoize-one"
6+ import { DiffResult } from "objdiff-wasm"
87import AutoSizer from "react-virtualized-auto-sizer"
9- import { FixedSizeList , areEqual } from "react-window"
8+ import { FixedSizeList } from "react-window"
109
1110import * as api from "@/lib/api"
1211import { useSize } from "@/lib/hooks"
@@ -15,93 +14,10 @@ import { ThreeWayDiffBase, useCodeFontSize } from "@/lib/settings"
1514import Loading from "../loading.svg"
1615
1716import styles from "./Diff.module.scss"
17+ import * as AsmDiffer from "./DiffRowAsmDiffer"
18+ import * as Objdiff from "./DiffRowObjdiff"
1819import DragBar from "./DragBar"
19- import { Highlighter , useHighlighers } from "./Highlighter"
20-
21- const PADDING_TOP = 8
22- const PADDING_BOTTOM = 8
23-
24- // Regex for tokenizing lines for click-to-highlight purposes.
25- // Strings matched by the first regex group (spaces, punctuation)
26- // are treated as non-highlightable.
27- const RE_TOKEN = / ( [ \t , ( ) [ \] : ] + | ~ > ) | % (?: l o | h i ) \( [ ^ ) ] + \) | [ ^ \t , ( ) [ \] : ] + / g
28-
29- const SelectedSourceLineContext = createContext < number | null > ( null )
30-
31- function FormatDiffText ( { texts, highlighter } : {
32- texts : api . DiffText [ ]
33- highlighter : Highlighter
34- } ) {
35- return < > {
36- texts . map ( ( t , index1 ) =>
37- Array . from ( t . text . matchAll ( RE_TOKEN ) ) . map ( ( match , index2 ) => {
38- const text = match [ 0 ]
39- const isToken = ! match [ 1 ]
40- const key = index1 + "," + index2
41-
42- let className : string
43- if ( t . format == "rotation" ) {
44- className = styles [ `rotation${ t . index % 9 } ` ]
45- } else if ( t . format ) {
46- className = styles [ t . format ]
47- }
48-
49- return < span
50- key = { key }
51- className = { classNames ( className , {
52- [ styles . highlightable ] : isToken ,
53- [ styles . highlighted ] : ( highlighter . value === text ) ,
54- } ) }
55- onClick = { e => {
56- if ( isToken ) {
57- highlighter . select ( text )
58- e . stopPropagation ( )
59- }
60- } }
61- >
62- { text }
63- </ span >
64- } )
65- )
66- } </ >
67- }
68-
69- function DiffCell ( { cell, className, highlighter } : {
70- cell : api . DiffCell | undefined
71- className ?: string
72- highlighter : Highlighter
73- } ) {
74- const selectedSourceLine = useContext ( SelectedSourceLineContext )
75- const hasLineNo = typeof cell ?. src_line != "undefined"
76-
77- if ( ! cell )
78- return < div className = { classNames ( styles . cell , className ) } />
79-
80- return < div
81- className = { classNames ( styles . cell , className , {
82- [ styles . highlight ] : hasLineNo && cell . src_line == selectedSourceLine ,
83- } ) }
84- >
85- { hasLineNo && < span className = { styles . lineNumber } > { cell . src_line } </ span > }
86- < FormatDiffText texts = { cell . text } highlighter = { highlighter } />
87- </ div >
88- }
89-
90- const DiffRow = memo ( function DiffRow ( { data, index, style } : { data : DiffListData , index : number , style : CSSProperties } ) {
91- const row = data . diff ?. rows ?. [ index ]
92- return < li
93- className = { styles . row }
94- style = { {
95- ...style ,
96- top : `${ parseFloat ( style . top . toString ( ) ) + PADDING_TOP } px` ,
97- lineHeight : `${ style . height . toString ( ) } px` ,
98- } }
99- >
100- < DiffCell cell = { row . base } highlighter = { data . highlighters [ 0 ] } />
101- < DiffCell cell = { row . current } highlighter = { data . highlighters [ 1 ] } />
102- < DiffCell cell = { row . previous } highlighter = { data . highlighters [ 2 ] } />
103- </ li >
104- } , areEqual )
20+ import { useHighlighers } from "./Highlighter"
10521
10622// https://github.com/bvaughn/react-window#can-i-add-padding-to-the-top-and-bottom-of-a-list
10723const innerElementType = forwardRef < HTMLUListElement , HTMLAttributes < HTMLUListElement > > ( ( { style, ...rest } , ref ) => {
@@ -116,21 +32,26 @@ const innerElementType = forwardRef<HTMLUListElement, HTMLAttributes<HTMLUListEl
11632} )
11733innerElementType . displayName = "innerElementType"
11834
119- interface DiffListData {
120- diff : api . DiffOutput | null
121- highlighters : Highlighter [ ]
35+ const isAsmDifferOutput = ( diff : api . DiffOutput | DiffResult ) : diff is api . DiffOutput => {
36+ return Object . prototype . hasOwnProperty . call ( diff , "arch_str" )
12237}
12338
124- const createDiffListData = memoize ( (
125- diff : api . DiffOutput | null ,
126- highlighters : Highlighter [ ]
127- ) : DiffListData => {
128- return { diff, highlighters }
129- } )
130-
131- function DiffBody ( { diff, fontSize } : { diff : api . DiffOutput | null , fontSize : number | undefined } ) {
39+ function DiffBody ( { diff, diffLabel, fontSize } : { diff : api . DiffOutput | DiffResult | null , diffLabel : string | null , fontSize : number | undefined } ) {
13240 const { highlighters, setHighlightAll } = useHighlighers ( 3 )
133- const itemData = createDiffListData ( diff , highlighters )
41+
42+ if ( ! diff ) {
43+ return < div className = { styles . bodyContainer } />
44+ }
45+
46+ let itemData : AsmDiffer . DiffListData | Objdiff . DiffListData
47+ let DiffRow : typeof AsmDiffer . DiffRow | typeof Objdiff . DiffRow
48+ if ( isAsmDifferOutput ( diff ) ) {
49+ itemData = AsmDiffer . createDiffListData ( diff , diffLabel , highlighters )
50+ DiffRow = AsmDiffer . DiffRow
51+ } else {
52+ itemData = Objdiff . createDiffListData ( diff , diffLabel , highlighters )
53+ DiffRow = Objdiff . DiffRow
54+ }
13455
13556 return < div
13657 className = { styles . bodyContainer }
@@ -139,22 +60,22 @@ function DiffBody({ diff, fontSize }: { diff: api.DiffOutput | null, fontSize: n
13960 setHighlightAll ( null )
14061 } }
14162 >
142- { diff ?. rows && < AutoSizer >
63+ < AutoSizer >
14364 { ( { height, width } : { height : number | undefined , width :number | undefined } ) => (
14465 < FixedSizeList
14566 className = { styles . body }
146- itemCount = { diff . rows . length }
67+ itemCount = { itemData . itemCount }
14768 itemData = { itemData }
14869 itemSize = { ( fontSize ?? 12 ) * 1.33 }
14970 overscanCount = { 40 }
15071 width = { width }
15172 height = { height }
15273 innerElementType = { innerElementType }
15374 >
154- { DiffRow }
75+ { DiffRow as any }
15576 </ FixedSizeList >
15677 ) }
157- </ AutoSizer > }
78+ </ AutoSizer >
15879 </ div >
15980}
16081
@@ -173,8 +94,14 @@ function ThreeWayToggleButton({ enabled, setEnabled }: { enabled: boolean, setEn
17394 </ button >
17495}
17596
97+ export const PADDING_TOP = 8
98+ export const PADDING_BOTTOM = 8
99+
100+ export const SelectedSourceLineContext = createContext < number | null > ( null )
101+
176102export type Props = {
177- diff : api . DiffOutput | null
103+ diff : api . DiffOutput | DiffResult | null
104+ diffLabel : string | null
178105 isCompiling : boolean
179106 isCurrentOutdated : boolean
180107 threeWayDiffEnabled : boolean
@@ -183,7 +110,7 @@ export type Props = {
183110 selectedSourceLine : number | null
184111}
185112
186- export default function Diff ( { diff, isCompiling, isCurrentOutdated, threeWayDiffEnabled, setThreeWayDiffEnabled, threeWayDiffBase, selectedSourceLine } : Props ) {
113+ export default function Diff ( { diff, diffLabel , isCompiling, isCurrentOutdated, threeWayDiffEnabled, setThreeWayDiffEnabled, threeWayDiffBase, selectedSourceLine } : Props ) {
187114 const [ fontSize ] = useCodeFontSize ( )
188115
189116 const container = useSize < HTMLDivElement > ( )
@@ -245,7 +172,7 @@ export default function Diff({ diff, isCompiling, isCurrentOutdated, threeWayDif
245172 </ div > }
246173 </ div >
247174 < SelectedSourceLineContext . Provider value = { selectedSourceLine } >
248- < DiffBody diff = { diff } fontSize = { fontSize } />
175+ < DiffBody diff = { diff } diffLabel = { diffLabel } fontSize = { fontSize } />
249176 </ SelectedSourceLineContext . Provider >
250177 </ div >
251178}
0 commit comments