Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/source_frame/SourceCodeDiff.js

Issue 2729783002: DevTools: Diff subsystem (Closed)
Patch Set: constant Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 /** 4 /**
5 * @unrestricted 5 * @unrestricted
6 */ 6 */
7 SourceFrame.SourceCodeDiff = class { 7 SourceFrame.SourceCodeDiff = class {
8 /** 8 /**
9 * @param {!Promise<?string>} diffBaseline 9 * @param {!Workspace.UISourceCode} uiSourceCode
10 * @param {!TextEditor.CodeMirrorTextEditor} textEditor 10 * @param {!TextEditor.CodeMirrorTextEditor} textEditor
11 */ 11 */
12 constructor(diffBaseline, textEditor) { 12 constructor(uiSourceCode, textEditor) {
13 this._textEditor = textEditor; 13 this._textEditor = textEditor;
14 this._decorations = []; 14 this._decorations = [];
15 this._textEditor.installGutter(SourceFrame.SourceCodeDiff.DiffGutterType, tr ue); 15 this._textEditor.installGutter(SourceFrame.SourceCodeDiff.DiffGutterType, tr ue);
16 this._diffBaseline = diffBaseline; 16 this._uiSourceCode = uiSourceCode;
17 WorkspaceDiff.workspaceDiff().subscribeToDiffChange(this._uiSourceCode, this ._update, this);
17 /** @type {!Array<!TextEditor.TextEditorPositionHandle>}*/ 18 /** @type {!Array<!TextEditor.TextEditorPositionHandle>}*/
18 this._animatedLines = []; 19 this._animatedLines = [];
19 }
20 20
21 updateDiffMarkersWhenPossible() { 21 this._update();
22 if (this._updateTimeout)
23 clearTimeout(this._updateTimeout);
24 this._updateTimeout =
25 setTimeout(this.updateDiffMarkersImmediately.bind(this), SourceFrame.Sou rceCodeDiff.UpdateTimeout);
26 }
27
28 updateDiffMarkersImmediately() {
29 if (this._updateTimeout)
30 clearTimeout(this._updateTimeout);
31 this._updateTimeout = null;
32 this._diffBaseline.then(this._innerUpdate.bind(this));
33 } 22 }
34 23
35 /** 24 /**
36 * @param {?string} oldContent 25 * @param {?string} oldContent
37 * @param {?string} newContent 26 * @param {?string} newContent
38 */ 27 */
39 highlightModifiedLines(oldContent, newContent) { 28 highlightModifiedLines(oldContent, newContent) {
40 if (typeof oldContent !== 'string' || typeof newContent !== 'string') 29 if (typeof oldContent !== 'string' || typeof newContent !== 'string')
41 return; 30 return;
42 31
43 var diff = this._computeDiff(oldContent, newContent); 32 var diff = this._computeDiff(Diff.Diff.lineDiff(oldContent.split('\n'), newC ontent.split('\n')));
44 var changedLines = []; 33 var changedLines = [];
45 for (var i = 0; i < diff.length; ++i) { 34 for (var i = 0; i < diff.length; ++i) {
46 var diffEntry = diff[i]; 35 var diffEntry = diff[i];
47 if (diffEntry.type === SourceFrame.SourceCodeDiff.GutterDecorationType.Del ete) 36 if (diffEntry.type === SourceFrame.SourceCodeDiff.GutterDecorationType.Del ete)
48 continue; 37 continue;
49 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber) { 38 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber) {
50 var position = this._textEditor.textEditorPositionHandle(lineNumber, 0); 39 var position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
51 if (position) 40 if (position)
52 changedLines.push(position); 41 changedLines.push(position);
53 } 42 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 86
98 function operation() { 87 function operation() {
99 for (var decoration of removed) 88 for (var decoration of removed)
100 decoration.remove(); 89 decoration.remove();
101 for (var decoration of added) 90 for (var decoration of added)
102 decoration.install(); 91 decoration.install();
103 } 92 }
104 } 93 }
105 94
106 /** 95 /**
107 * @param {string} baseline 96 * @param {!Diff.Diff.DiffArray} diff
108 * @param {string} current
109 * @return {!Array<!{type: !SourceFrame.SourceCodeDiff.GutterDecorationType, f rom: number, to: number}>} 97 * @return {!Array<!{type: !SourceFrame.SourceCodeDiff.GutterDecorationType, f rom: number, to: number}>}
110 */ 98 */
111 _computeDiff(baseline, current) { 99 _computeDiff(diff) {
112 var diff = Diff.Diff.lineDiff(baseline.split('\n'), current.split('\n'));
113 var result = []; 100 var result = [];
114 var hasAdded = false; 101 var hasAdded = false;
115 var hasRemoved = false; 102 var hasRemoved = false;
116 var blockStartLineNumber = 0; 103 var blockStartLineNumber = 0;
117 var currentLineNumber = 0; 104 var currentLineNumber = 0;
118 var isInsideBlock = false; 105 var isInsideBlock = false;
119 for (var i = 0; i < diff.length; ++i) { 106 for (var i = 0; i < diff.length; ++i) {
120 var token = diff[i]; 107 var token = diff[i];
121 if (token[0] === Diff.Diff.Operation.Equal) { 108 if (token[0] === Diff.Diff.Operation.Equal) {
122 if (isInsideBlock) 109 if (isInsideBlock)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 type = SourceFrame.SourceCodeDiff.GutterDecorationType.Delete; 145 type = SourceFrame.SourceCodeDiff.GutterDecorationType.Delete;
159 from -= 1; 146 from -= 1;
160 } 147 }
161 result.push({type: type, from: from, to: to}); 148 result.push({type: type, from: from, to: to});
162 isInsideBlock = false; 149 isInsideBlock = false;
163 hasAdded = false; 150 hasAdded = false;
164 hasRemoved = false; 151 hasRemoved = false;
165 } 152 }
166 } 153 }
167 154
155 _update() {
156 WorkspaceDiff.workspaceDiff().requestDiff(this._uiSourceCode).then(this._inn erUpdate.bind(this));
lushnikov 2017/03/10 01:17:04 let's pass this from the outside
157 }
158
168 /** 159 /**
169 * @param {?string} baseline 160 * @param {!Diff.Diff.DiffArray} lineDiff
170 */ 161 */
171 _innerUpdate(baseline) { 162 _innerUpdate(lineDiff) {
172 var current = this._textEditor.text();
173 if (typeof baseline !== 'string') {
174 this._updateDecorations(this._decorations, [] /* added */);
175 this._decorations = [];
176 return;
177 }
178
179 var diff = this._computeDiff(baseline, current);
180
181 /** @type {!Map<number, !SourceFrame.SourceCodeDiff.GutterDecoration>} */ 163 /** @type {!Map<number, !SourceFrame.SourceCodeDiff.GutterDecoration>} */
182 var oldDecorations = new Map(); 164 var oldDecorations = new Map();
183 for (var i = 0; i < this._decorations.length; ++i) { 165 for (var i = 0; i < this._decorations.length; ++i) {
184 var decoration = this._decorations[i]; 166 var decoration = this._decorations[i];
185 var lineNumber = decoration.lineNumber(); 167 var lineNumber = decoration.lineNumber();
186 if (lineNumber === -1) 168 if (lineNumber === -1)
187 continue; 169 continue;
188 oldDecorations.set(lineNumber, decoration); 170 oldDecorations.set(lineNumber, decoration);
189 } 171 }
190 172
173 var diff = this._computeDiff(lineDiff);
174
191 /** @type {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeD iff.GutterDecorationType}>} */ 175 /** @type {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeD iff.GutterDecorationType}>} */
192 var newDecorations = new Map(); 176 var newDecorations = new Map();
193 for (var i = 0; i < diff.length; ++i) { 177 for (var i = 0; i < diff.length; ++i) {
194 var diffEntry = diff[i]; 178 var diffEntry = diff[i];
195 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber) 179 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber)
196 newDecorations.set(lineNumber, {lineNumber: lineNumber, type: diffEntry. type}); 180 newDecorations.set(lineNumber, {lineNumber: lineNumber, type: diffEntry. type});
197 } 181 }
198 182
199 var decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1.type === e2.type); 183 var decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1.type === e2.type);
200 var addedDecorations = decorationDiff.added.map( 184 var addedDecorations = decorationDiff.added.map(
201 entry => new SourceFrame.SourceCodeDiff.GutterDecoration(this._textEdito r, entry.lineNumber, entry.type)); 185 entry => new SourceFrame.SourceCodeDiff.GutterDecoration(this._textEdito r, entry.lineNumber, entry.type));
202 186
203 this._decorations = decorationDiff.equal.concat(addedDecorations); 187 this._decorations = decorationDiff.equal.concat(addedDecorations);
204 this._updateDecorations(decorationDiff.removed, addedDecorations); 188 this._updateDecorations(decorationDiff.removed, addedDecorations);
205 this._decorationsSetForTest(newDecorations); 189 this._decorationsSetForTest(newDecorations);
206 } 190 }
207 191
208 /** 192 /**
209 * @param {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeDif f.GutterDecorationType}>} decorations 193 * @param {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeDif f.GutterDecorationType}>} decorations
210 */ 194 */
211 _decorationsSetForTest(decorations) { 195 _decorationsSetForTest(decorations) {
212 } 196 }
197
198 dispose() {
199 WorkspaceDiff.workspaceDiff().unsubscribeToDiffChange(this._uiSourceCode, th is._update, this);
200 }
213 }; 201 };
214 202
215 /** @type {number} */
216 SourceFrame.SourceCodeDiff.UpdateTimeout = 200;
217
218 /** @type {string} */ 203 /** @type {string} */
219 SourceFrame.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff'; 204 SourceFrame.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff';
220 205
221 /** @enum {symbol} */ 206 /** @enum {symbol} */
222 SourceFrame.SourceCodeDiff.GutterDecorationType = { 207 SourceFrame.SourceCodeDiff.GutterDecorationType = {
223 Insert: Symbol('Insert'), 208 Insert: Symbol('Insert'),
224 Delete: Symbol('Delete'), 209 Delete: Symbol('Delete'),
225 Modify: Symbol('Modify'), 210 Modify: Symbol('Modify'),
226 }; 211 };
227 212
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 } 253 }
269 254
270 remove() { 255 remove() {
271 var location = this._position.resolve(); 256 var location = this._position.resolve();
272 if (!location) 257 if (!location)
273 return; 258 return;
274 this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.Source CodeDiff.DiffGutterType, null); 259 this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.Source CodeDiff.DiffGutterType, null);
275 this._textEditor.toggleLineClass(location.lineNumber, this._className, false ); 260 this._textEditor.toggleLineClass(location.lineNumber, this._className, false );
276 } 261 }
277 }; 262 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698