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

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

Issue 2729783002: DevTools: Diff subsystem (Closed)
Patch Set: nullable diff 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 {!WorkspaceDiff.WorkspaceDiff} workspaceDiff
10 * @param {!Workspace.UISourceCode} uiSourceCode
10 * @param {!TextEditor.CodeMirrorTextEditor} textEditor 11 * @param {!TextEditor.CodeMirrorTextEditor} textEditor
11 */ 12 */
12 constructor(diffBaseline, textEditor) { 13 constructor(workspaceDiff, uiSourceCode, textEditor) {
13 this._textEditor = textEditor; 14 this._textEditor = textEditor;
14 this._decorations = []; 15 this._decorations = [];
15 this._textEditor.installGutter(SourceFrame.SourceCodeDiff.DiffGutterType, tr ue); 16 this._textEditor.installGutter(SourceFrame.SourceCodeDiff.DiffGutterType, tr ue);
16 this._diffBaseline = diffBaseline; 17 this._uiSourceCode = uiSourceCode;
18 this._workspaceDiff = workspaceDiff;
17 /** @type {!Array<!TextEditor.TextEditorPositionHandle>}*/ 19 /** @type {!Array<!TextEditor.TextEditorPositionHandle>}*/
18 this._animatedLines = []; 20 this._animatedLines = [];
19 }
20 21
21 updateDiffMarkersWhenPossible() { 22 this._workspaceDiff.subscribeToDiffChange(this._uiSourceCode, this._update, this);
22 if (this._updateTimeout) 23 this._update();
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 } 24 }
34 25
35 /** 26 /**
36 * @param {?string} oldContent 27 * @param {?string} oldContent
37 * @param {?string} newContent 28 * @param {?string} newContent
38 */ 29 */
39 highlightModifiedLines(oldContent, newContent) { 30 highlightModifiedLines(oldContent, newContent) {
40 if (typeof oldContent !== 'string' || typeof newContent !== 'string') 31 if (typeof oldContent !== 'string' || typeof newContent !== 'string')
41 return; 32 return;
42 33
43 var diff = this._computeDiff(oldContent, newContent); 34 var diff = this._computeDiff(Diff.Diff.lineDiff(oldContent.split('\n'), newC ontent.split('\n')));
44 var changedLines = []; 35 var changedLines = [];
45 for (var i = 0; i < diff.length; ++i) { 36 for (var i = 0; i < diff.length; ++i) {
46 var diffEntry = diff[i]; 37 var diffEntry = diff[i];
47 if (diffEntry.type === SourceFrame.SourceCodeDiff.GutterDecorationType.Del ete) 38 if (diffEntry.type === SourceFrame.SourceCodeDiff.GutterDecorationType.Del ete)
48 continue; 39 continue;
49 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber) { 40 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber) {
50 var position = this._textEditor.textEditorPositionHandle(lineNumber, 0); 41 var position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
51 if (position) 42 if (position)
52 changedLines.push(position); 43 changedLines.push(position);
53 } 44 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 88
98 function operation() { 89 function operation() {
99 for (var decoration of removed) 90 for (var decoration of removed)
100 decoration.remove(); 91 decoration.remove();
101 for (var decoration of added) 92 for (var decoration of added)
102 decoration.install(); 93 decoration.install();
103 } 94 }
104 } 95 }
105 96
106 /** 97 /**
107 * @param {string} baseline 98 * @param {!Diff.Diff.DiffArray} diff
108 * @param {string} current
109 * @return {!Array<!{type: !SourceFrame.SourceCodeDiff.GutterDecorationType, f rom: number, to: number}>} 99 * @return {!Array<!{type: !SourceFrame.SourceCodeDiff.GutterDecorationType, f rom: number, to: number}>}
110 */ 100 */
111 _computeDiff(baseline, current) { 101 _computeDiff(diff) {
112 var diff = Diff.Diff.lineDiff(baseline.split('\n'), current.split('\n'));
113 var result = []; 102 var result = [];
114 var hasAdded = false; 103 var hasAdded = false;
115 var hasRemoved = false; 104 var hasRemoved = false;
116 var blockStartLineNumber = 0; 105 var blockStartLineNumber = 0;
117 var currentLineNumber = 0; 106 var currentLineNumber = 0;
118 var isInsideBlock = false; 107 var isInsideBlock = false;
119 for (var i = 0; i < diff.length; ++i) { 108 for (var i = 0; i < diff.length; ++i) {
120 var token = diff[i]; 109 var token = diff[i];
121 if (token[0] === Diff.Diff.Operation.Equal) { 110 if (token[0] === Diff.Diff.Operation.Equal) {
122 if (isInsideBlock) 111 if (isInsideBlock)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 type = SourceFrame.SourceCodeDiff.GutterDecorationType.Delete; 147 type = SourceFrame.SourceCodeDiff.GutterDecorationType.Delete;
159 from -= 1; 148 from -= 1;
160 } 149 }
161 result.push({type: type, from: from, to: to}); 150 result.push({type: type, from: from, to: to});
162 isInsideBlock = false; 151 isInsideBlock = false;
163 hasAdded = false; 152 hasAdded = false;
164 hasRemoved = false; 153 hasRemoved = false;
165 } 154 }
166 } 155 }
167 156
157 _update() {
158 this._workspaceDiff.requestDiff(this._uiSourceCode).then(this._innerUpdate.b ind(this));
159 }
160
168 /** 161 /**
169 * @param {?string} baseline 162 * @param {?Diff.Diff.DiffArray} lineDiff
170 */ 163 */
171 _innerUpdate(baseline) { 164 _innerUpdate(lineDiff) {
172 var current = this._textEditor.text(); 165 if (!lineDiff)
173 if (typeof baseline !== 'string') {
174 this._updateDecorations(this._decorations, [] /* added */);
175 this._decorations = [];
176 return; 166 return;
177 }
178
179 var diff = this._computeDiff(baseline, current);
180 167
181 /** @type {!Map<number, !SourceFrame.SourceCodeDiff.GutterDecoration>} */ 168 /** @type {!Map<number, !SourceFrame.SourceCodeDiff.GutterDecoration>} */
182 var oldDecorations = new Map(); 169 var oldDecorations = new Map();
183 for (var i = 0; i < this._decorations.length; ++i) { 170 for (var i = 0; i < this._decorations.length; ++i) {
184 var decoration = this._decorations[i]; 171 var decoration = this._decorations[i];
185 var lineNumber = decoration.lineNumber(); 172 var lineNumber = decoration.lineNumber();
186 if (lineNumber === -1) 173 if (lineNumber === -1)
187 continue; 174 continue;
188 oldDecorations.set(lineNumber, decoration); 175 oldDecorations.set(lineNumber, decoration);
189 } 176 }
190 177
178 var diff = this._computeDiff(lineDiff);
179
191 /** @type {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeD iff.GutterDecorationType}>} */ 180 /** @type {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeD iff.GutterDecorationType}>} */
192 var newDecorations = new Map(); 181 var newDecorations = new Map();
193 for (var i = 0; i < diff.length; ++i) { 182 for (var i = 0; i < diff.length; ++i) {
194 var diffEntry = diff[i]; 183 var diffEntry = diff[i];
195 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber) 184 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber)
196 newDecorations.set(lineNumber, {lineNumber: lineNumber, type: diffEntry. type}); 185 newDecorations.set(lineNumber, {lineNumber: lineNumber, type: diffEntry. type});
197 } 186 }
198 187
199 var decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1.type === e2.type); 188 var decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1.type === e2.type);
200 var addedDecorations = decorationDiff.added.map( 189 var addedDecorations = decorationDiff.added.map(
201 entry => new SourceFrame.SourceCodeDiff.GutterDecoration(this._textEdito r, entry.lineNumber, entry.type)); 190 entry => new SourceFrame.SourceCodeDiff.GutterDecoration(this._textEdito r, entry.lineNumber, entry.type));
202 191
203 this._decorations = decorationDiff.equal.concat(addedDecorations); 192 this._decorations = decorationDiff.equal.concat(addedDecorations);
204 this._updateDecorations(decorationDiff.removed, addedDecorations); 193 this._updateDecorations(decorationDiff.removed, addedDecorations);
205 this._decorationsSetForTest(newDecorations); 194 this._decorationsSetForTest(newDecorations);
206 } 195 }
207 196
208 /** 197 /**
209 * @param {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeDif f.GutterDecorationType}>} decorations 198 * @param {!Map<number, !{lineNumber: number, type: !SourceFrame.SourceCodeDif f.GutterDecorationType}>} decorations
210 */ 199 */
211 _decorationsSetForTest(decorations) { 200 _decorationsSetForTest(decorations) {
212 } 201 }
202
203 dispose() {
204 WorkspaceDiff.workspaceDiff().unsubscribeFromDiffChange(this._uiSourceCode, this._update, this);
205 }
213 }; 206 };
214 207
215 /** @type {number} */
216 SourceFrame.SourceCodeDiff.UpdateTimeout = 200;
217
218 /** @type {string} */ 208 /** @type {string} */
219 SourceFrame.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff'; 209 SourceFrame.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff';
220 210
221 /** @enum {symbol} */ 211 /** @enum {symbol} */
222 SourceFrame.SourceCodeDiff.GutterDecorationType = { 212 SourceFrame.SourceCodeDiff.GutterDecorationType = {
223 Insert: Symbol('Insert'), 213 Insert: Symbol('Insert'),
224 Delete: Symbol('Delete'), 214 Delete: Symbol('Delete'),
225 Modify: Symbol('Modify'), 215 Modify: Symbol('Modify'),
226 }; 216 };
227 217
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 } 258 }
269 259
270 remove() { 260 remove() {
271 var location = this._position.resolve(); 261 var location = this._position.resolve();
272 if (!location) 262 if (!location)
273 return; 263 return;
274 this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.Source CodeDiff.DiffGutterType, null); 264 this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.Source CodeDiff.DiffGutterType, null);
275 this._textEditor.toggleLineClass(location.lineNumber, this._className, false ); 265 this._textEditor.toggleLineClass(location.lineNumber, this._className, false );
276 } 266 }
277 }; 267 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698