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

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

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month 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
5 /** 4 /**
6 * @constructor 5 * @unrestricted
7 * @param {!Promise<?string>} diffBaseline
8 * @param {!WebInspector.CodeMirrorTextEditor} textEditor
9 */ 6 */
10 WebInspector.SourceCodeDiff = function(diffBaseline, textEditor) 7 WebInspector.SourceCodeDiff = class {
11 { 8 /**
9 * @param {!Promise<?string>} diffBaseline
10 * @param {!WebInspector.CodeMirrorTextEditor} textEditor
11 */
12 constructor(diffBaseline, textEditor) {
12 this._textEditor = textEditor; 13 this._textEditor = textEditor;
13 this._decorations = []; 14 this._decorations = [];
14 this._textEditor.installGutter(WebInspector.SourceCodeDiff.DiffGutterType, t rue); 15 this._textEditor.installGutter(WebInspector.SourceCodeDiff.DiffGutterType, t rue);
15 this._diffBaseline = diffBaseline; 16 this._diffBaseline = diffBaseline;
16 /** @type {!Array<!WebInspector.TextEditorPositionHandle>}*/ 17 /** @type {!Array<!WebInspector.TextEditorPositionHandle>}*/
17 this._animatedLines = []; 18 this._animatedLines = [];
19 }
20
21 updateDiffMarkersWhenPossible() {
22 if (this._updateTimeout)
23 clearTimeout(this._updateTimeout);
24 this._updateTimeout =
25 setTimeout(this.updateDiffMarkersImmediately.bind(this), WebInspector.So urceCodeDiff.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 }
34
35 /**
36 * @param {?string} oldContent
37 * @param {?string} newContent
38 */
39 highlightModifiedLines(oldContent, newContent) {
40 if (typeof oldContent !== 'string' || typeof newContent !== 'string')
41 return;
42
43 var diff = this._computeDiff(oldContent, newContent);
44 var changedLines = [];
45 for (var i = 0; i < diff.length; ++i) {
46 var diffEntry = diff[i];
47 if (diffEntry.type === WebInspector.SourceCodeDiff.GutterDecorationType.De lete)
48 continue;
49 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber) {
50 var position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
51 if (position)
52 changedLines.push(position);
53 }
54 }
55 this._updateHighlightedLines(changedLines);
56 this._animationTimeout = setTimeout(
57 this._updateHighlightedLines.bind(this, []), 400); // // Keep this time out in sync with sourcesView.css.
58 }
59
60 /**
61 * @param {!Array<!WebInspector.TextEditorPositionHandle>} newLines
62 */
63 _updateHighlightedLines(newLines) {
64 if (this._animationTimeout)
65 clearTimeout(this._animationTimeout);
66 this._animationTimeout = null;
67 this._textEditor.operation(operation.bind(this));
68
69 /**
70 * @this {WebInspector.SourceCodeDiff}
71 */
72 function operation() {
73 toggleLines.call(this, false);
74 this._animatedLines = newLines;
75 toggleLines.call(this, true);
76 }
77
78 /**
79 * @param {boolean} value
80 * @this {WebInspector.SourceCodeDiff}
81 */
82 function toggleLines(value) {
83 for (var i = 0; i < this._animatedLines.length; ++i) {
84 var location = this._animatedLines[i].resolve();
85 if (location)
86 this._textEditor.toggleLineClass(location.lineNumber, 'highlight-line- modification', value);
87 }
88 }
89 }
90
91 /**
92 * @param {!Array<!WebInspector.SourceCodeDiff.GutterDecoration>} removed
93 * @param {!Array<!WebInspector.SourceCodeDiff.GutterDecoration>} added
94 */
95 _updateDecorations(removed, added) {
96 this._textEditor.operation(operation);
97
98 function operation() {
99 for (var decoration of removed)
100 decoration.remove();
101 for (var decoration of added)
102 decoration.install();
103 }
104 }
105
106 /**
107 * @param {string} baseline
108 * @param {string} current
109 * @return {!Array<!{type: !WebInspector.SourceCodeDiff.GutterDecorationType, from: number, to: number}>}
110 */
111 _computeDiff(baseline, current) {
112 var diff = WebInspector.Diff.lineDiff(baseline.split('\n'), current.split('\ n'));
113 var result = [];
114 var hasAdded = false;
115 var hasRemoved = false;
116 var blockStartLineNumber = 0;
117 var currentLineNumber = 0;
118 var isInsideBlock = false;
119 for (var i = 0; i < diff.length; ++i) {
120 var token = diff[i];
121 if (token[0] === WebInspector.Diff.Operation.Equal) {
122 if (isInsideBlock)
123 flush();
124 currentLineNumber += token[1].length;
125 continue;
126 }
127
128 if (!isInsideBlock) {
129 isInsideBlock = true;
130 blockStartLineNumber = currentLineNumber;
131 }
132
133 if (token[0] === WebInspector.Diff.Operation.Delete) {
134 hasRemoved = true;
135 } else {
136 currentLineNumber += token[1].length;
137 hasAdded = true;
138 }
139 }
140 if (isInsideBlock)
141 flush();
142 if (result.length > 1 && result[0].from === 0 && result[1].from === 0) {
143 var merged = {type: WebInspector.SourceCodeDiff.GutterDecorationType.Modif y, from: 0, to: result[1].to};
144 result.splice(0, 2, merged);
145 }
146 return result;
147
148 function flush() {
149 var type = WebInspector.SourceCodeDiff.GutterDecorationType.Insert;
150 var from = blockStartLineNumber;
151 var to = currentLineNumber;
152 if (hasAdded && hasRemoved) {
153 type = WebInspector.SourceCodeDiff.GutterDecorationType.Modify;
154 } else if (!hasAdded && hasRemoved && from === 0 && to === 0) {
155 type = WebInspector.SourceCodeDiff.GutterDecorationType.Modify;
156 to = 1;
157 } else if (!hasAdded && hasRemoved) {
158 type = WebInspector.SourceCodeDiff.GutterDecorationType.Delete;
159 from -= 1;
160 }
161 result.push({type: type, from: from, to: to});
162 isInsideBlock = false;
163 hasAdded = false;
164 hasRemoved = false;
165 }
166 }
167
168 /**
169 * @param {?string} baseline
170 */
171 _innerUpdate(baseline) {
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, !WebInspector.SourceCodeDiff.GutterDecoration>} */
182 var oldDecorations = new Map();
183 for (var i = 0; i < this._decorations.length; ++i) {
184 var decoration = this._decorations[i];
185 var lineNumber = decoration.lineNumber();
186 if (lineNumber === -1)
187 continue;
188 oldDecorations.set(lineNumber, decoration);
189 }
190
191 /** @type {!Map<number, !{lineNumber: number, type: !WebInspector.SourceCode Diff.GutterDecorationType}>} */
192 var newDecorations = new Map();
193 for (var i = 0; i < diff.length; ++i) {
194 var diffEntry = diff[i];
195 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNum ber)
196 newDecorations.set(lineNumber, {lineNumber: lineNumber, type: diffEntry. type});
197 }
198
199 var decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1.type === e2.type);
200 var addedDecorations = decorationDiff.added.map(
201 entry => new WebInspector.SourceCodeDiff.GutterDecoration(this._textEdit or, entry.lineNumber, entry.type));
202
203 this._decorations = decorationDiff.equal.concat(addedDecorations);
204 this._updateDecorations(decorationDiff.removed, addedDecorations);
205 this._decorationsSetForTest(newDecorations);
206 }
207
208 /**
209 * @param {!Map<number, !{lineNumber: number, type: !WebInspector.SourceCodeDi ff.GutterDecorationType}>} decorations
210 */
211 _decorationsSetForTest(decorations) {
212 }
18 }; 213 };
19 214
20 /** @type {number} */ 215 /** @type {number} */
21 WebInspector.SourceCodeDiff.UpdateTimeout = 200; 216 WebInspector.SourceCodeDiff.UpdateTimeout = 200;
22 217
23 /** @type {string} */ 218 /** @type {string} */
24 WebInspector.SourceCodeDiff.DiffGutterType = "CodeMirror-gutter-diff"; 219 WebInspector.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff';
25
26 WebInspector.SourceCodeDiff.prototype = {
27 updateDiffMarkersWhenPossible: function()
28 {
29 if (this._updateTimeout)
30 clearTimeout(this._updateTimeout);
31 this._updateTimeout = setTimeout(this.updateDiffMarkersImmediately.bind( this), WebInspector.SourceCodeDiff.UpdateTimeout);
32 },
33
34 updateDiffMarkersImmediately: function()
35 {
36 if (this._updateTimeout)
37 clearTimeout(this._updateTimeout);
38 this._updateTimeout = null;
39 this._diffBaseline.then(this._innerUpdate.bind(this));
40 },
41
42 /**
43 * @param {?string} oldContent
44 * @param {?string} newContent
45 */
46 highlightModifiedLines: function(oldContent, newContent)
47 {
48 if (typeof oldContent !== "string" || typeof newContent !== "string")
49 return;
50
51 var diff = this._computeDiff(oldContent, newContent);
52 var changedLines = [];
53 for (var i = 0; i < diff.length; ++i) {
54 var diffEntry = diff[i];
55 if (diffEntry.type === WebInspector.SourceCodeDiff.GutterDecorationT ype.Delete)
56 continue;
57 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++l ineNumber) {
58 var position = this._textEditor.textEditorPositionHandle(lineNum ber, 0);
59 if (position)
60 changedLines.push(position);
61 }
62 }
63 this._updateHighlightedLines(changedLines);
64 this._animationTimeout = setTimeout(this._updateHighlightedLines.bind(th is, []), 400); // // Keep this timeout in sync with sourcesView.css.
65 },
66
67 /**
68 * @param {!Array<!WebInspector.TextEditorPositionHandle>} newLines
69 */
70 _updateHighlightedLines: function(newLines)
71 {
72 if (this._animationTimeout)
73 clearTimeout(this._animationTimeout);
74 this._animationTimeout = null;
75 this._textEditor.operation(operation.bind(this));
76
77 /**
78 * @this {WebInspector.SourceCodeDiff}
79 */
80 function operation()
81 {
82 toggleLines.call(this, false);
83 this._animatedLines = newLines;
84 toggleLines.call(this, true);
85 }
86
87 /**
88 * @param {boolean} value
89 * @this {WebInspector.SourceCodeDiff}
90 */
91 function toggleLines(value)
92 {
93 for (var i = 0; i < this._animatedLines.length; ++i) {
94 var location = this._animatedLines[i].resolve();
95 if (location)
96 this._textEditor.toggleLineClass(location.lineNumber, "highl ight-line-modification", value);
97 }
98 }
99 },
100
101 /**
102 * @param {!Array<!WebInspector.SourceCodeDiff.GutterDecoration>} removed
103 * @param {!Array<!WebInspector.SourceCodeDiff.GutterDecoration>} added
104 */
105 _updateDecorations: function(removed, added)
106 {
107 this._textEditor.operation(operation);
108
109 function operation()
110 {
111 for (var decoration of removed)
112 decoration.remove();
113 for (var decoration of added)
114 decoration.install();
115 }
116 },
117
118 /**
119 * @param {string} baseline
120 * @param {string} current
121 * @return {!Array<!{type: !WebInspector.SourceCodeDiff.GutterDecorationType , from: number, to: number}>}
122 */
123 _computeDiff: function(baseline, current)
124 {
125 var diff = WebInspector.Diff.lineDiff(baseline.split("\n"), current.spli t("\n"));
126 var result = [];
127 var hasAdded = false;
128 var hasRemoved = false;
129 var blockStartLineNumber = 0;
130 var currentLineNumber = 0;
131 var isInsideBlock = false;
132 for (var i = 0; i < diff.length; ++i) {
133 var token = diff[i];
134 if (token[0] === WebInspector.Diff.Operation.Equal) {
135 if (isInsideBlock)
136 flush();
137 currentLineNumber += token[1].length;
138 continue;
139 }
140
141 if (!isInsideBlock) {
142 isInsideBlock = true;
143 blockStartLineNumber = currentLineNumber;
144 }
145
146 if (token[0] === WebInspector.Diff.Operation.Delete) {
147 hasRemoved = true;
148 } else {
149 currentLineNumber += token[1].length;
150 hasAdded = true;
151 }
152 }
153 if (isInsideBlock)
154 flush();
155 if (result.length > 1 && result[0].from === 0 && result[1].from === 0) {
156 var merged = {
157 type: WebInspector.SourceCodeDiff.GutterDecorationType.Modify,
158 from: 0,
159 to: result[1].to
160 };
161 result.splice(0, 2, merged);
162 }
163 return result;
164
165 function flush()
166 {
167 var type = WebInspector.SourceCodeDiff.GutterDecorationType.Insert;
168 var from = blockStartLineNumber;
169 var to = currentLineNumber;
170 if (hasAdded && hasRemoved) {
171 type = WebInspector.SourceCodeDiff.GutterDecorationType.Modify;
172 } else if (!hasAdded && hasRemoved && from === 0 && to === 0) {
173 type = WebInspector.SourceCodeDiff.GutterDecorationType.Modify;
174 to = 1;
175 } else if (!hasAdded && hasRemoved) {
176 type = WebInspector.SourceCodeDiff.GutterDecorationType.Delete;
177 from -= 1;
178 }
179 result.push({
180 type: type,
181 from: from,
182 to: to
183 });
184 isInsideBlock = false;
185 hasAdded = false;
186 hasRemoved = false;
187 }
188 },
189
190 /**
191 * @param {?string} baseline
192 */
193 _innerUpdate: function(baseline)
194 {
195 var current = this._textEditor.text();
196 if (typeof baseline !== "string") {
197 this._updateDecorations(this._decorations, [] /* added */);
198 this._decorations = [];
199 return;
200 }
201
202 var diff = this._computeDiff(baseline, current);
203
204 /** @type {!Map<number, !WebInspector.SourceCodeDiff.GutterDecoration>} */
205 var oldDecorations = new Map();
206 for (var i = 0; i < this._decorations.length; ++i) {
207 var decoration = this._decorations[i];
208 var lineNumber = decoration.lineNumber();
209 if (lineNumber === -1)
210 continue;
211 oldDecorations.set(lineNumber, decoration);
212 }
213
214 /** @type {!Map<number, !{lineNumber: number, type: !WebInspector.Source CodeDiff.GutterDecorationType}>} */
215 var newDecorations = new Map();
216 for (var i = 0; i < diff.length; ++i) {
217 var diffEntry = diff[i];
218 for (var lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++l ineNumber)
219 newDecorations.set(lineNumber, {lineNumber: lineNumber, type: di ffEntry.type});
220 }
221
222 var decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1. type === e2.type);
223 var addedDecorations = decorationDiff.added.map(entry => new WebInspecto r.SourceCodeDiff.GutterDecoration(this._textEditor, entry.lineNumber, entry.type ));
224
225 this._decorations = decorationDiff.equal.concat(addedDecorations);
226 this._updateDecorations(decorationDiff.removed, addedDecorations);
227 this._decorationsSetForTest(newDecorations);
228 },
229
230 /**
231 * @param {!Map<number, !{lineNumber: number, type: !WebInspector.SourceCode Diff.GutterDecorationType}>} decorations
232 */
233 _decorationsSetForTest: function(decorations) { }
234 };
235 220
236 /** @enum {symbol} */ 221 /** @enum {symbol} */
237 WebInspector.SourceCodeDiff.GutterDecorationType = { 222 WebInspector.SourceCodeDiff.GutterDecorationType = {
238 Insert: Symbol("Insert"), 223 Insert: Symbol('Insert'),
239 Delete: Symbol("Delete"), 224 Delete: Symbol('Delete'),
240 Modify: Symbol("Modify"), 225 Modify: Symbol('Modify'),
241 }; 226 };
242 227
243 /** 228 /**
244 * @constructor 229 * @unrestricted
245 * @param {!WebInspector.CodeMirrorTextEditor} textEditor
246 * @param {number} lineNumber
247 * @param {!WebInspector.SourceCodeDiff.GutterDecorationType} type
248 */ 230 */
249 WebInspector.SourceCodeDiff.GutterDecoration = function(textEditor, lineNumber, type) 231 WebInspector.SourceCodeDiff.GutterDecoration = class {
250 { 232 /**
233 * @param {!WebInspector.CodeMirrorTextEditor} textEditor
234 * @param {number} lineNumber
235 * @param {!WebInspector.SourceCodeDiff.GutterDecorationType} type
236 */
237 constructor(textEditor, lineNumber, type) {
251 this._textEditor = textEditor; 238 this._textEditor = textEditor;
252 this._position = this._textEditor.textEditorPositionHandle(lineNumber, 0); 239 this._position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
253 this._className = ""; 240 this._className = '';
254 if (type === WebInspector.SourceCodeDiff.GutterDecorationType.Insert) 241 if (type === WebInspector.SourceCodeDiff.GutterDecorationType.Insert)
255 this._className = "diff-entry-insert"; 242 this._className = 'diff-entry-insert';
256 else if (type === WebInspector.SourceCodeDiff.GutterDecorationType.Delete) 243 else if (type === WebInspector.SourceCodeDiff.GutterDecorationType.Delete)
257 this._className = "diff-entry-delete"; 244 this._className = 'diff-entry-delete';
258 else if (type === WebInspector.SourceCodeDiff.GutterDecorationType.Modify) 245 else if (type === WebInspector.SourceCodeDiff.GutterDecorationType.Modify)
259 this._className = "diff-entry-modify"; 246 this._className = 'diff-entry-modify';
260 this.type = type; 247 this.type = type;
248 }
249
250 /**
251 * @return {number}
252 */
253 lineNumber() {
254 var location = this._position.resolve();
255 if (!location)
256 return -1;
257 return location.lineNumber;
258 }
259
260 install() {
261 var location = this._position.resolve();
262 if (!location)
263 return;
264 var element = createElementWithClass('div', 'diff-marker');
265 element.textContent = '\u00A0';
266 this._textEditor.setGutterDecoration(location.lineNumber, WebInspector.Sourc eCodeDiff.DiffGutterType, element);
267 this._textEditor.toggleLineClass(location.lineNumber, this._className, true) ;
268 }
269
270 remove() {
271 var location = this._position.resolve();
272 if (!location)
273 return;
274 this._textEditor.setGutterDecoration(location.lineNumber, WebInspector.Sourc eCodeDiff.DiffGutterType, null);
275 this._textEditor.toggleLineClass(location.lineNumber, this._className, false );
276 }
261 }; 277 };
262
263 WebInspector.SourceCodeDiff.GutterDecoration.prototype = {
264 /**
265 * @return {number}
266 */
267 lineNumber: function()
268 {
269 var location = this._position.resolve();
270 if (!location)
271 return -1;
272 return location.lineNumber;
273 },
274
275 install: function()
276 {
277 var location = this._position.resolve();
278 if (!location)
279 return;
280 var element = createElementWithClass("div", "diff-marker");
281 element.textContent = "\u00A0";
282 this._textEditor.setGutterDecoration(location.lineNumber, WebInspector.S ourceCodeDiff.DiffGutterType, element);
283 this._textEditor.toggleLineClass(location.lineNumber, this._className, t rue);
284 },
285
286 remove: function()
287 {
288 var location = this._position.resolve();
289 if (!location)
290 return;
291 this._textEditor.setGutterDecoration(location.lineNumber, WebInspector.S ourceCodeDiff.DiffGutterType, null);
292 this._textEditor.toggleLineClass(location.lineNumber, this._className, f alse);
293 }
294 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698