@theia/scm 1.48.3 → 1.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/decorations/scm-decorations-service.d.ts +9 -3
- package/lib/browser/decorations/scm-decorations-service.d.ts.map +1 -1
- package/lib/browser/decorations/scm-decorations-service.js +50 -30
- package/lib/browser/decorations/scm-decorations-service.js.map +1 -1
- package/lib/browser/dirty-diff/content-lines.d.ts +2 -0
- package/lib/browser/dirty-diff/content-lines.d.ts.map +1 -1
- package/lib/browser/dirty-diff/content-lines.js +7 -0
- package/lib/browser/dirty-diff/content-lines.js.map +1 -1
- package/lib/browser/dirty-diff/diff-computer.d.ts +23 -14
- package/lib/browser/dirty-diff/diff-computer.d.ts.map +1 -1
- package/lib/browser/dirty-diff/diff-computer.js +91 -27
- package/lib/browser/dirty-diff/diff-computer.js.map +1 -1
- package/lib/browser/dirty-diff/diff-computer.spec.js +120 -52
- package/lib/browser/dirty-diff/diff-computer.spec.js.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-decorator.d.ts +5 -3
- package/lib/browser/dirty-diff/dirty-diff-decorator.d.ts.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-decorator.js +14 -7
- package/lib/browser/dirty-diff/dirty-diff-decorator.js.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-module.d.ts.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-module.js +9 -0
- package/lib/browser/dirty-diff/dirty-diff-module.js.map +1 -1
- package/lib/browser/dirty-diff/dirty-diff-navigator.d.ts +49 -0
- package/lib/browser/dirty-diff/dirty-diff-navigator.d.ts.map +1 -0
- package/lib/browser/dirty-diff/dirty-diff-navigator.js +292 -0
- package/lib/browser/dirty-diff/dirty-diff-navigator.js.map +1 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.d.ts +47 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.d.ts.map +1 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.js +320 -0
- package/lib/browser/dirty-diff/dirty-diff-widget.js.map +1 -0
- package/lib/browser/scm-colors.d.ts +6 -0
- package/lib/browser/scm-colors.d.ts.map +1 -0
- package/lib/browser/scm-colors.js +25 -0
- package/lib/browser/scm-colors.js.map +1 -0
- package/lib/browser/scm-contribution.d.ts +20 -6
- package/lib/browser/scm-contribution.d.ts.map +1 -1
- package/lib/browser/scm-contribution.js +112 -22
- package/lib/browser/scm-contribution.js.map +1 -1
- package/lib/browser/scm-tree-widget.js +1 -1
- package/lib/browser/scm-tree-widget.js.map +1 -1
- package/package.json +8 -6
- package/src/browser/decorations/scm-decorations-service.ts +60 -36
- package/src/browser/dirty-diff/content-lines.ts +9 -0
- package/src/browser/dirty-diff/diff-computer.spec.ts +120 -52
- package/src/browser/dirty-diff/diff-computer.ts +88 -40
- package/src/browser/dirty-diff/dirty-diff-decorator.ts +17 -10
- package/src/browser/dirty-diff/dirty-diff-module.ts +9 -0
- package/src/browser/dirty-diff/dirty-diff-navigator.ts +288 -0
- package/src/browser/dirty-diff/dirty-diff-widget.ts +364 -0
- package/src/browser/scm-colors.ts +21 -0
- package/src/browser/scm-contribution.ts +97 -6
- package/src/browser/scm-tree-widget.tsx +1 -1
- package/src/browser/style/dirty-diff-decorator.css +2 -1
|
@@ -42,9 +42,12 @@ describe('dirty-diff-computer', () => {
|
|
|
42
42
|
],
|
|
43
43
|
);
|
|
44
44
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
changes: [
|
|
46
|
+
{
|
|
47
|
+
previousRange: { start: 1, end: 2 },
|
|
48
|
+
currentRange: { start: 1, end: 1 },
|
|
49
|
+
},
|
|
50
|
+
],
|
|
48
51
|
});
|
|
49
52
|
});
|
|
50
53
|
|
|
@@ -56,22 +59,29 @@ describe('dirty-diff-computer', () => {
|
|
|
56
59
|
sequenceOfN(2),
|
|
57
60
|
);
|
|
58
61
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
changes: [
|
|
63
|
+
{
|
|
64
|
+
previousRange: { start: 2, end: 2 + lines },
|
|
65
|
+
currentRange: { start: 2, end: 2 },
|
|
66
|
+
},
|
|
67
|
+
],
|
|
62
68
|
});
|
|
63
69
|
});
|
|
64
70
|
});
|
|
65
71
|
|
|
66
72
|
it('remove all lines', () => {
|
|
73
|
+
const numberOfLines = 10;
|
|
67
74
|
const dirtyDiff = computeDirtyDiff(
|
|
68
|
-
sequenceOfN(
|
|
75
|
+
sequenceOfN(numberOfLines, () => 'TO-BE-REMOVED'),
|
|
69
76
|
['']
|
|
70
77
|
);
|
|
71
78
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
changes: [
|
|
80
|
+
{
|
|
81
|
+
previousRange: { start: 0, end: numberOfLines },
|
|
82
|
+
currentRange: { start: 0, end: 0 },
|
|
83
|
+
},
|
|
84
|
+
],
|
|
75
85
|
});
|
|
76
86
|
});
|
|
77
87
|
|
|
@@ -83,9 +93,12 @@ describe('dirty-diff-computer', () => {
|
|
|
83
93
|
sequenceOfN(2),
|
|
84
94
|
);
|
|
85
95
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
changes: [
|
|
97
|
+
{
|
|
98
|
+
previousRange: { start: 0, end: lines },
|
|
99
|
+
currentRange: { start: 0, end: 0 },
|
|
100
|
+
},
|
|
101
|
+
],
|
|
89
102
|
});
|
|
90
103
|
});
|
|
91
104
|
});
|
|
@@ -96,9 +109,12 @@ describe('dirty-diff-computer', () => {
|
|
|
96
109
|
const modified = insertIntoArray(previous, 2, ...sequenceOfN(lines, () => 'ADDED LINE'));
|
|
97
110
|
const dirtyDiff = computeDirtyDiff(previous, modified);
|
|
98
111
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
changes: [
|
|
113
|
+
{
|
|
114
|
+
previousRange: { start: 2, end: 2 },
|
|
115
|
+
currentRange: { start: 2, end: 2 + lines },
|
|
116
|
+
},
|
|
117
|
+
],
|
|
102
118
|
});
|
|
103
119
|
});
|
|
104
120
|
});
|
|
@@ -111,9 +127,12 @@ describe('dirty-diff-computer', () => {
|
|
|
111
127
|
.concat(sequenceOfN(2))
|
|
112
128
|
);
|
|
113
129
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
130
|
+
changes: [
|
|
131
|
+
{
|
|
132
|
+
previousRange: { start: 0, end: 0 },
|
|
133
|
+
currentRange: { start: 0, end: lines },
|
|
134
|
+
},
|
|
135
|
+
],
|
|
117
136
|
});
|
|
118
137
|
});
|
|
119
138
|
});
|
|
@@ -125,9 +144,12 @@ describe('dirty-diff-computer', () => {
|
|
|
125
144
|
sequenceOfN(numberOfLines, () => 'ADDED LINE')
|
|
126
145
|
);
|
|
127
146
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
147
|
+
changes: [
|
|
148
|
+
{
|
|
149
|
+
previousRange: { start: 0, end: 0 },
|
|
150
|
+
currentRange: { start: 0, end: numberOfLines },
|
|
151
|
+
},
|
|
152
|
+
],
|
|
131
153
|
});
|
|
132
154
|
});
|
|
133
155
|
|
|
@@ -145,9 +167,12 @@ describe('dirty-diff-computer', () => {
|
|
|
145
167
|
]
|
|
146
168
|
);
|
|
147
169
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
170
|
+
changes: [
|
|
171
|
+
{
|
|
172
|
+
previousRange: { start: 1, end: 1 },
|
|
173
|
+
currentRange: { start: 1, end: 3 },
|
|
174
|
+
},
|
|
175
|
+
],
|
|
151
176
|
});
|
|
152
177
|
});
|
|
153
178
|
|
|
@@ -162,9 +187,12 @@ describe('dirty-diff-computer', () => {
|
|
|
162
187
|
]
|
|
163
188
|
);
|
|
164
189
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
190
|
+
changes: [
|
|
191
|
+
{
|
|
192
|
+
previousRange: { start: 1, end: 1 },
|
|
193
|
+
currentRange: { start: 1, end: 2 },
|
|
194
|
+
},
|
|
195
|
+
],
|
|
168
196
|
});
|
|
169
197
|
});
|
|
170
198
|
|
|
@@ -176,9 +204,12 @@ describe('dirty-diff-computer', () => {
|
|
|
176
204
|
.concat(new Array(lines).map(() => ''))
|
|
177
205
|
);
|
|
178
206
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
207
|
+
changes: [
|
|
208
|
+
{
|
|
209
|
+
previousRange: { start: 2, end: 2 },
|
|
210
|
+
currentRange: { start: 2, end: 2 + lines },
|
|
211
|
+
},
|
|
212
|
+
],
|
|
182
213
|
});
|
|
183
214
|
});
|
|
184
215
|
});
|
|
@@ -200,9 +231,12 @@ describe('dirty-diff-computer', () => {
|
|
|
200
231
|
]
|
|
201
232
|
);
|
|
202
233
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
234
|
+
changes: [
|
|
235
|
+
{
|
|
236
|
+
previousRange: { start: 1, end: 1 },
|
|
237
|
+
currentRange: { start: 1, end: 6 },
|
|
238
|
+
},
|
|
239
|
+
],
|
|
206
240
|
});
|
|
207
241
|
});
|
|
208
242
|
|
|
@@ -213,9 +247,12 @@ describe('dirty-diff-computer', () => {
|
|
|
213
247
|
['0'].concat(sequenceOfN(lines, () => 'ADDED LINE'))
|
|
214
248
|
);
|
|
215
249
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
250
|
+
changes: [
|
|
251
|
+
{
|
|
252
|
+
previousRange: { start: 1, end: 1 },
|
|
253
|
+
currentRange: { start: 1, end: lines + 1 },
|
|
254
|
+
},
|
|
255
|
+
],
|
|
219
256
|
});
|
|
220
257
|
});
|
|
221
258
|
});
|
|
@@ -234,9 +271,12 @@ describe('dirty-diff-computer', () => {
|
|
|
234
271
|
]
|
|
235
272
|
);
|
|
236
273
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
274
|
+
changes: [
|
|
275
|
+
{
|
|
276
|
+
previousRange: { start: 1, end: 2 },
|
|
277
|
+
currentRange: { start: 1, end: 2 },
|
|
278
|
+
},
|
|
279
|
+
],
|
|
240
280
|
});
|
|
241
281
|
});
|
|
242
282
|
|
|
@@ -247,9 +287,12 @@ describe('dirty-diff-computer', () => {
|
|
|
247
287
|
sequenceOfN(numberOfLines, () => 'MODIFIED')
|
|
248
288
|
);
|
|
249
289
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
290
|
+
changes: [
|
|
291
|
+
{
|
|
292
|
+
previousRange: { start: 0, end: numberOfLines },
|
|
293
|
+
currentRange: { start: 0, end: numberOfLines },
|
|
294
|
+
},
|
|
295
|
+
],
|
|
253
296
|
});
|
|
254
297
|
});
|
|
255
298
|
|
|
@@ -268,9 +311,12 @@ describe('dirty-diff-computer', () => {
|
|
|
268
311
|
]
|
|
269
312
|
);
|
|
270
313
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
314
|
+
changes: [
|
|
315
|
+
{
|
|
316
|
+
previousRange: { start: 1, end: 4 },
|
|
317
|
+
currentRange: { start: 1, end: 3 },
|
|
318
|
+
},
|
|
319
|
+
],
|
|
274
320
|
});
|
|
275
321
|
});
|
|
276
322
|
|
|
@@ -305,9 +351,20 @@ describe('dirty-diff-computer', () => {
|
|
|
305
351
|
]
|
|
306
352
|
);
|
|
307
353
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
354
|
+
changes: [
|
|
355
|
+
{
|
|
356
|
+
previousRange: { start: 0, end: 1 },
|
|
357
|
+
currentRange: { start: 0, end: 1 },
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
previousRange: { start: 4, end: 5 },
|
|
361
|
+
currentRange: { start: 4, end: 4 },
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
previousRange: { start: 11, end: 11 },
|
|
365
|
+
currentRange: { start: 10, end: 12 },
|
|
366
|
+
},
|
|
367
|
+
],
|
|
311
368
|
});
|
|
312
369
|
});
|
|
313
370
|
|
|
@@ -340,9 +397,20 @@ describe('dirty-diff-computer', () => {
|
|
|
340
397
|
''
|
|
341
398
|
]);
|
|
342
399
|
expect(dirtyDiff).to.be.deep.equal(<DirtyDiff>{
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
400
|
+
changes: [
|
|
401
|
+
{
|
|
402
|
+
previousRange: { start: 5, end: 5 },
|
|
403
|
+
currentRange: { start: 5, end: 6 },
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
previousRange: { start: 8, end: 8 },
|
|
407
|
+
currentRange: { start: 9, end: 10 },
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
previousRange: { start: 9, end: 10 },
|
|
411
|
+
currentRange: { start: 12, end: 12 },
|
|
412
|
+
},
|
|
413
|
+
],
|
|
346
414
|
});
|
|
347
415
|
});
|
|
348
416
|
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import * as jsdiff from 'diff';
|
|
18
18
|
import { ContentLinesArrayLike } from './content-lines';
|
|
19
|
+
import { Position, Range, uinteger } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
19
20
|
|
|
20
21
|
export class DiffComputer {
|
|
21
22
|
|
|
@@ -25,52 +26,52 @@ export class DiffComputer {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
computeDirtyDiff(previous: ContentLinesArrayLike, current: ContentLinesArrayLike): DirtyDiff {
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
let
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const next = changes[i + 1];
|
|
29
|
+
const changes: Change[] = [];
|
|
30
|
+
const diffResult = this.computeDiff(previous, current);
|
|
31
|
+
let currentRevisionLine = -1;
|
|
32
|
+
let previousRevisionLine = -1;
|
|
33
|
+
for (let i = 0; i < diffResult.length; i++) {
|
|
34
|
+
const change = diffResult[i];
|
|
35
|
+
const next = diffResult[i + 1];
|
|
36
36
|
if (change.added) {
|
|
37
37
|
// case: addition
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
added.push(<LineRange>{ start, end });
|
|
41
|
-
lastLine = end;
|
|
38
|
+
changes.push({ previousRange: LineRange.createEmptyLineRange(previousRevisionLine + 1), currentRange: toLineRange(change) });
|
|
39
|
+
currentRevisionLine += change.count!;
|
|
42
40
|
} else if (change.removed && next && next.added) {
|
|
43
41
|
const isFirstChange = i === 0;
|
|
44
|
-
const isLastChange = i ===
|
|
42
|
+
const isLastChange = i === diffResult.length - 2;
|
|
45
43
|
const isNextEmptyLine = next.value.length > 0 && current[next.value[0]].length === 0;
|
|
46
44
|
const isPrevEmptyLine = change.value.length > 0 && previous[change.value[0]].length === 0;
|
|
47
45
|
|
|
48
46
|
if (isFirstChange && isNextEmptyLine) {
|
|
49
47
|
// special case: removing at the beginning
|
|
50
|
-
|
|
48
|
+
changes.push({ previousRange: toLineRange(change), currentRange: LineRange.createEmptyLineRange(0) });
|
|
49
|
+
previousRevisionLine += change.count!;
|
|
51
50
|
} else if (isFirstChange && isPrevEmptyLine) {
|
|
52
51
|
// special case: adding at the beginning
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
added.push(<LineRange>{ start, end });
|
|
56
|
-
lastLine = end;
|
|
52
|
+
changes.push({ previousRange: LineRange.createEmptyLineRange(0), currentRange: toLineRange(next) });
|
|
53
|
+
currentRevisionLine += next.count!;
|
|
57
54
|
} else if (isLastChange && isNextEmptyLine) {
|
|
58
|
-
|
|
55
|
+
changes.push({ previousRange: toLineRange(change), currentRange: LineRange.createEmptyLineRange(currentRevisionLine + 2) });
|
|
56
|
+
previousRevisionLine += change.count!;
|
|
59
57
|
} else {
|
|
60
58
|
// default case is a modification
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
lastLine = end;
|
|
59
|
+
changes.push({ previousRange: toLineRange(change), currentRange: toLineRange(next) });
|
|
60
|
+
currentRevisionLine += next.count!;
|
|
61
|
+
previousRevisionLine += change.count!;
|
|
65
62
|
}
|
|
66
63
|
i++; // consume next eagerly
|
|
67
64
|
} else if (change.removed && !(next && next.added)) {
|
|
68
|
-
|
|
65
|
+
// case: removal
|
|
66
|
+
changes.push({ previousRange: toLineRange(change), currentRange: LineRange.createEmptyLineRange(currentRevisionLine + 1) });
|
|
67
|
+
previousRevisionLine += change.count!;
|
|
69
68
|
} else {
|
|
70
|
-
|
|
69
|
+
// case: unchanged region
|
|
70
|
+
currentRevisionLine += change.count!;
|
|
71
|
+
previousRevisionLine += change.count!;
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
|
-
return
|
|
74
|
+
return { changes };
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
}
|
|
@@ -101,6 +102,11 @@ function diffArrays(oldArr: ContentLinesArrayLike, newArr: ContentLinesArrayLike
|
|
|
101
102
|
return arrayDiff.diff(oldArr as any, newArr as any) as any;
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
function toLineRange({ value }: DiffResult): LineRange {
|
|
106
|
+
const [start, end] = value;
|
|
107
|
+
return LineRange.create(start, end + 1);
|
|
108
|
+
}
|
|
109
|
+
|
|
104
110
|
export interface DiffResult {
|
|
105
111
|
value: [number, number];
|
|
106
112
|
count?: number;
|
|
@@ -109,21 +115,63 @@ export interface DiffResult {
|
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
export interface DirtyDiff {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
readonly changes: readonly Change[];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface Change {
|
|
122
|
+
readonly previousRange: LineRange;
|
|
123
|
+
readonly currentRange: LineRange;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export namespace Change {
|
|
127
|
+
export function isAddition(change: Change): boolean {
|
|
128
|
+
return LineRange.isEmpty(change.previousRange);
|
|
129
|
+
}
|
|
130
|
+
export function isRemoval(change: Change): boolean {
|
|
131
|
+
return LineRange.isEmpty(change.currentRange);
|
|
132
|
+
}
|
|
133
|
+
export function isModification(change: Change): boolean {
|
|
134
|
+
return !isAddition(change) && !isRemoval(change);
|
|
135
|
+
}
|
|
124
136
|
}
|
|
125
137
|
|
|
126
138
|
export interface LineRange {
|
|
127
|
-
start: number;
|
|
128
|
-
end: number;
|
|
139
|
+
readonly start: number;
|
|
140
|
+
readonly end: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export namespace LineRange {
|
|
144
|
+
export function create(start: number, end: number): LineRange {
|
|
145
|
+
if (start < 0 || end < 0 || start > end) {
|
|
146
|
+
throw new Error(`Invalid line range: { start: ${start}, end: ${end} }`);
|
|
147
|
+
}
|
|
148
|
+
return { start, end };
|
|
149
|
+
}
|
|
150
|
+
export function createSingleLineRange(line: number): LineRange {
|
|
151
|
+
return create(line, line + 1);
|
|
152
|
+
}
|
|
153
|
+
export function createEmptyLineRange(line: number): LineRange {
|
|
154
|
+
return create(line, line);
|
|
155
|
+
}
|
|
156
|
+
export function isEmpty(range: LineRange): boolean {
|
|
157
|
+
return range.start === range.end;
|
|
158
|
+
}
|
|
159
|
+
export function getStartPosition(range: LineRange): Position {
|
|
160
|
+
if (isEmpty(range)) {
|
|
161
|
+
return getEndPosition(range);
|
|
162
|
+
}
|
|
163
|
+
return Position.create(range.start, 0);
|
|
164
|
+
}
|
|
165
|
+
export function getEndPosition(range: LineRange): Position {
|
|
166
|
+
if (range.end < 1) {
|
|
167
|
+
return Position.create(0, 0);
|
|
168
|
+
}
|
|
169
|
+
return Position.create(range.end - 1, uinteger.MAX_VALUE);
|
|
170
|
+
}
|
|
171
|
+
export function toRange(range: LineRange): Range {
|
|
172
|
+
return Range.create(getStartPosition(range), getEndPosition(range));
|
|
173
|
+
}
|
|
174
|
+
export function getLineCount(range: LineRange): number {
|
|
175
|
+
return range.end - range.start;
|
|
176
|
+
}
|
|
129
177
|
}
|
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
import { injectable } from '@theia/core/shared/inversify';
|
|
18
18
|
import {
|
|
19
|
-
Range,
|
|
20
|
-
Position,
|
|
21
19
|
EditorDecoration,
|
|
22
20
|
EditorDecorationOptions,
|
|
23
21
|
OverviewRulerLane,
|
|
@@ -25,7 +23,8 @@ import {
|
|
|
25
23
|
TextEditor,
|
|
26
24
|
MinimapPosition
|
|
27
25
|
} from '@theia/editor/lib/browser';
|
|
28
|
-
import { DirtyDiff, LineRange } from './diff-computer';
|
|
26
|
+
import { DirtyDiff, LineRange, Change } from './diff-computer';
|
|
27
|
+
import { URI } from '@theia/core';
|
|
29
28
|
|
|
30
29
|
export enum DirtyDiffDecorationType {
|
|
31
30
|
AddedLine = 'dirty-diff-added-line',
|
|
@@ -84,24 +83,32 @@ const ModifiedLineDecoration = <EditorDecorationOptions>{
|
|
|
84
83
|
isWholeLine: true
|
|
85
84
|
};
|
|
86
85
|
|
|
86
|
+
function getEditorDecorationOptions(change: Change): EditorDecorationOptions {
|
|
87
|
+
if (Change.isAddition(change)) {
|
|
88
|
+
return AddedLineDecoration;
|
|
89
|
+
}
|
|
90
|
+
if (Change.isRemoval(change)) {
|
|
91
|
+
return RemovedLineDecoration;
|
|
92
|
+
}
|
|
93
|
+
return ModifiedLineDecoration;
|
|
94
|
+
}
|
|
95
|
+
|
|
87
96
|
export interface DirtyDiffUpdate extends DirtyDiff {
|
|
88
97
|
readonly editor: TextEditor;
|
|
98
|
+
readonly previousRevisionUri?: URI;
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
@injectable()
|
|
92
102
|
export class DirtyDiffDecorator extends EditorDecorator {
|
|
93
103
|
|
|
94
104
|
applyDecorations(update: DirtyDiffUpdate): void {
|
|
95
|
-
const
|
|
96
|
-
const additions = update.added.map(range => this.toDeltaDecoration(range, AddedLineDecoration));
|
|
97
|
-
const removals = update.removed.map(line => this.toDeltaDecoration(line, RemovedLineDecoration));
|
|
98
|
-
const decorations = [...modifications, ...additions, ...removals];
|
|
105
|
+
const decorations = update.changes.map(change => this.toDeltaDecoration(change));
|
|
99
106
|
this.setDecorations(update.editor, decorations);
|
|
100
107
|
}
|
|
101
108
|
|
|
102
|
-
protected toDeltaDecoration(
|
|
103
|
-
const
|
|
104
|
-
const
|
|
109
|
+
protected toDeltaDecoration(change: Change): EditorDecoration {
|
|
110
|
+
const range = LineRange.toRange(change.currentRange);
|
|
111
|
+
const options = getEditorDecorationOptions(change);
|
|
105
112
|
return { range, options };
|
|
106
113
|
}
|
|
107
114
|
}
|
|
@@ -16,9 +16,18 @@
|
|
|
16
16
|
|
|
17
17
|
import { interfaces } from '@theia/core/shared/inversify';
|
|
18
18
|
import { DirtyDiffDecorator } from './dirty-diff-decorator';
|
|
19
|
+
import { DirtyDiffNavigator } from './dirty-diff-navigator';
|
|
20
|
+
import { DirtyDiffWidget, DirtyDiffWidgetFactory, DirtyDiffWidgetProps } from './dirty-diff-widget';
|
|
19
21
|
|
|
20
22
|
import '../../../src/browser/style/dirty-diff.css';
|
|
21
23
|
|
|
22
24
|
export function bindDirtyDiff(bind: interfaces.Bind): void {
|
|
23
25
|
bind(DirtyDiffDecorator).toSelf().inSingletonScope();
|
|
26
|
+
bind(DirtyDiffNavigator).toSelf().inSingletonScope();
|
|
27
|
+
bind(DirtyDiffWidgetFactory).toFactory(({ container }) => props => {
|
|
28
|
+
const child = container.createChild();
|
|
29
|
+
child.bind(DirtyDiffWidgetProps).toConstantValue(props);
|
|
30
|
+
child.bind(DirtyDiffWidget).toSelf();
|
|
31
|
+
return child.get(DirtyDiffWidget);
|
|
32
|
+
});
|
|
24
33
|
}
|