Skip to content

Commit d110b8b

Browse files
authored
ref(issues): improve similar issues stacktrace diff (#97645)
1 parent 4c4eec3 commit d110b8b

File tree

3 files changed

+60
-14
lines changed

3 files changed

+60
-14
lines changed

static/app/components/issueDiff/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class IssueDiff extends Component<Props, State> {
172172
key={i}
173173
base={value}
174174
target={targetEvent[i] ?? ''}
175-
type="words"
175+
type="lines"
176176
/>
177177
))}
178178
</StyledIssueDiff>

static/app/components/replays/diff/replayTextDiff.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export function ReplayTextDiff() {
5252
</After>
5353
</ContentSliderDiff.Header>
5454
<SplitDiffScrollWrapper>
55-
<SplitDiff base={leftBody ?? ''} target={rightBody ?? ''} type="words" />
55+
<SplitDiff base={leftBody ?? ''} target={rightBody ?? ''} type="lines" />
5656
</SplitDiffScrollWrapper>
5757
</Container>
5858
);

static/app/components/splitDiff.tsx

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {useMemo} from 'react';
12
import styled from '@emotion/styled';
23
import type {Change} from 'diff';
34
import {diffChars, diffLines, diffWords} from 'diff';
@@ -23,31 +24,76 @@ type Props = {
2324
type?: keyof typeof diffFnMap;
2425
};
2526

27+
// this function splits the lines from diffLines into words that are diffed
28+
function getDisplayData(
29+
line: Change[],
30+
highlightAdded: Change | undefined,
31+
highlightRemoved: Change | undefined
32+
): Change[] {
33+
if (!highlightAdded && !highlightRemoved) {
34+
return line;
35+
}
36+
37+
const leftText = line.reduce(
38+
(acc, result) => (result.added ? acc : acc + result.value),
39+
''
40+
);
41+
const rightText = line.reduce(
42+
(acc, result) => (result.removed ? acc : acc + result.value),
43+
''
44+
);
45+
46+
if (!leftText && !rightText) {
47+
return line;
48+
}
49+
50+
return diffWords(leftText, rightText);
51+
}
52+
2653
function SplitDiff({className, type = 'lines', base, target}: Props) {
2754
const diffFn = diffFnMap[type];
2855

29-
const baseLines = base.split('\n');
30-
const targetLines = target.split('\n');
31-
const [largerArray] =
32-
baseLines.length > targetLines.length
33-
? [baseLines, targetLines]
34-
: [targetLines, baseLines];
35-
const results = largerArray.map((_line, index) =>
36-
diffFn(baseLines[index] || '', targetLines[index] || '', {newlineIsToken: true})
37-
);
56+
const results = diffFn(base, target, {newlineIsToken: true});
57+
58+
// split one change that includes multiple lines into one change per line (for formatting)
59+
const groupedChanges = useMemo((): Change[][] => {
60+
let currentLine: Change[] = [];
61+
const processedLines: Change[][] = [];
62+
for (const change of results) {
63+
const lines = change.value.split('\n');
64+
for (let i = 0; i < lines.length; i++) {
65+
const lineValue = lines[i];
66+
if (lineValue !== undefined && lineValue !== '') {
67+
currentLine.push({
68+
value: lineValue,
69+
added: change.added,
70+
removed: change.removed,
71+
});
72+
}
73+
if (i < lines.length - 1) {
74+
processedLines.push(currentLine);
75+
currentLine = [];
76+
}
77+
}
78+
}
79+
if (currentLine.length > 0) {
80+
processedLines.push(currentLine);
81+
}
82+
return processedLines;
83+
}, [results]);
3884

3985
return (
4086
<SplitTable className={className} data-test-id="split-diff">
4187
<SplitBody>
42-
{results.map((line, j) => {
88+
{groupedChanges.map((line, j) => {
4389
const highlightAdded = line.find(result => result.added);
4490
const highlightRemoved = line.find(result => result.removed);
4591

4692
return (
4793
<tr key={j}>
4894
<Cell isRemoved={highlightRemoved}>
4995
<Line>
50-
{line
96+
{getDisplayData(line, highlightAdded, highlightRemoved)
5197
.filter(result => !result.added)
5298
.map((result, i) => (
5399
<Word key={i} isRemoved={result.removed}>
@@ -61,7 +107,7 @@ function SplitDiff({className, type = 'lines', base, target}: Props) {
61107

62108
<Cell isAdded={highlightAdded}>
63109
<Line>
64-
{line
110+
{getDisplayData(line, highlightAdded, highlightRemoved)
65111
.filter(result => !result.removed)
66112
.map((result, i) => (
67113
<Word key={i} isAdded={result.added}>

0 commit comments

Comments
 (0)