Changeset 74142 in webkit
- Timestamp:
- Dec 15, 2010 2:51:46 PM (13 years ago)
- Location:
- trunk/BugsSite
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/BugsSite/ChangeLog
r74130 r74142 1 2010-12-14 Ojan Vafai <ojan@chromium.org> 2 3 Reviewed by Adam Barth. 4 5 add ability to view for file context to the review tool 6 https://bugs.webkit.org/show_bug.cgi?id=51057 7 8 At the beginning/end of each file diff and between each 9 hunk add links to expand the context. For now it grabs the 10 tip of tree version of the file and tries to apply the diff 11 to that file. If it can't apply, then it gives up as we 12 wouldn't want to show the wrong lines of context. 13 14 In the future, we can consider adding the upload svn revision 15 to the diff itself, then we could fallback to the file at that 16 revision if tip of tree doesn't apply. 17 18 * PrettyPatch/PrettyPatch.rb: 19 * code-review.js: 20 1 21 2010-12-08 Ojan Vafai <ojan@chromium.org> 2 22 -
trunk/BugsSite/PrettyPatch/PrettyPatch.rb
r74130 r74142 113 113 } 114 114 115 :link { 116 color: #039; 117 } 118 115 119 .FileDiff { 116 120 background-color: #f8f8f8; … … 142 146 } 143 147 144 .lineNumber { 145 background-color: #eed; 148 .lineNumber, .expansionLineNumber { 146 149 border-bottom: 1px solid #998; 147 150 border-right: 1px solid #ddd; … … 152 155 vertical-align: bottom; 153 156 width: 3em; 157 } 158 159 .lineNumber { 160 background-color: #eed; 161 } 162 163 .expansionLineNumber { 164 background-color: #eee; 154 165 } 155 166 … … 270 281 border-bottom-color: #69F; 271 282 border-right-color: #69F; 283 } 284 285 .ExpandArea { 286 margin: 0; 287 } 288 289 .ExpandText { 290 margin-left: 0.67em; 291 } 292 293 .ExpandLinkContainer a { 294 border: 0; 295 } 296 297 .ExpandLinkContainer a:after { 298 content: " | "; 299 color: black; 300 } 301 302 .ExpandLinkContainer a:last-of-type:after { 303 content: ""; 272 304 } 273 305 -
trunk/BugsSite/code-review.js
r74130 r74142 24 24 25 25 (function() { 26 /** 27 * Create a new function with some of its arguements 28 * pre-filled. 29 * Taken from goog.partial in the Closure library. 30 * @param {Function} fn A function to partially apply. 31 * @param {...*} var_args Additional arguments that are partially 32 * applied to fn. 33 * @return {!Function} A partially-applied form of the function. 34 */ 35 function partial(fn, var_args) { 36 var args = Array.prototype.slice.call(arguments, 1); 37 return function() { 38 // Prepend the bound arguments to the current arguments. 39 var newArgs = Array.prototype.slice.call(arguments); 40 newArgs.unshift.apply(newArgs, args); 41 return fn.apply(this, newArgs); 42 }; 43 }; 44 26 45 function determineAttachmentID() { 27 46 try { … … 42 61 43 62 var next_line_id = 0; 63 var files = {}; 64 var original_file_contents = {}; 65 var patched_file_contents = {}; 66 var WEBKIT_BASE_DIR = "http://svn.webkit.org/repository/webkit/trunk/"; 44 67 45 68 function idForLine(number) { … … 121 144 addCommentFor($('#' + id)); 122 145 } 123 124 var files = {}125 146 126 147 function addPreviousComment(line, author, comment_text) { … … 258 279 var file_name = $(this).children('h1').text(); 259 280 files[file_name] = this; 260 }); 281 addExpandLinks(file_name); 282 }); 283 } 284 285 function addExpandLinks(file_name) { 286 if (file_name.indexOf('ChangeLog') != -1) 287 return; 288 289 var file_diff = files[file_name]; 290 $('.context', file_diff).detach(); 291 292 var expand_bar_index = 0; 293 294 // Don't show the links to expand upwards/downwards if the patch starts/ends without context 295 // lines, i.e. starts/ends with add/remove lines. 296 var first_line = file_diff.querySelector('.Line'); 297 if (!$(first_line).hasClass('add') && !$(first_line).hasClass('remove')) 298 $('h1', file_diff).after(expandBarHtml(file_name, BELOW)) 299 300 $('br').replaceWith(expandBarHtml(file_name)); 301 302 var last_line = file_diff.querySelector('.Line:last-of-type'); 303 // Some patches for new files somehow end up with an empty context line at the end 304 // with a from line number of 0. Don't show expand links in that case either. 305 if (!$(last_line).hasClass('add') && !$(last_line).hasClass('remove') && fromLineNumber(last_line) != 0) 306 $(file_diff).append(expandBarHtml(file_name, ABOVE)); 307 } 308 309 function expandBarHtml(file_name, opt_direction) { 310 var html = '<div class="ExpandBar">' + 311 '<pre class="ExpandArea Expand' + ABOVE + '"></pre>' + 312 '<div class="ExpandLinkContainer"><span class="ExpandText">expand: </span>'; 313 314 // FIXME: If there are <100 line to expand, don't show the expand-100 link. 315 // If there are <20 lines to expand, don't show the expand-20 link. 316 if (!opt_direction || opt_direction == ABOVE) { 317 html += expandLinkHtml(ABOVE, 100) + 318 expandLinkHtml(ABOVE, 20); 319 } 320 321 html += expandLinkHtml(ALL); 322 323 if (!opt_direction || opt_direction == BELOW) { 324 html += expandLinkHtml(BELOW, 20) + 325 expandLinkHtml(BELOW, 100); 326 } 327 328 html += '</div><pre class="ExpandArea Expand' + BELOW + '"></pre></div>'; 329 return html; 330 } 331 332 function expandLinkHtml(direction, amount) { 333 return "<a class='ExpandLink' href='javascript:' data-direction='" + direction + "' data-amount='" + amount + "'>" + 334 (amount ? amount + " " : "") + direction + "</a>"; 335 } 336 337 $(window).bind('click', function (e) { 338 var target = e.target; 339 if (target.className != 'ExpandLink') 340 return; 341 342 // Can't use $ here because something in the window's scope sets $ to something other than jQuery. 343 var expand_bar = jQuery(target).parents('.ExpandBar'); 344 var file_name = expand_bar.parents('.FileDiff').children('h1')[0].textContent; 345 var expand_function = partial(expand, expand_bar[0], file_name, target.getAttribute('data-direction'), Number(target.getAttribute('data-amount'))); 346 if (file_name in original_file_contents) 347 expand_function(); 348 else 349 getWebKitSourceFile(file_name, expand_function, expand_bar); 350 }); 351 352 function getWebKitSourceFile(file_name, onLoad, expand_bar) { 353 function handleLoad(contents) { 354 original_file_contents[file_name] = contents.split('\n'); 355 patched_file_contents[file_name] = applyDiff(original_file_contents[file_name], file_name); 356 onLoad(); 357 }; 358 359 $.ajax({ 360 url: WEBKIT_BASE_DIR + file_name, 361 context: document.body, 362 complete: function(xhr, data) { 363 if (xhr.status == 0) 364 handleLoadError(expand_bar); 365 else 366 handleLoad(xhr.responseText); 367 } 368 }); 369 } 370 371 function replaceExpandLinkContainers(expand_bar, text) { 372 $('.ExpandLinkContainer', $(expand_bar).parents('.FileDiff')).replaceWith('<span class="ExpandText">' + text + '</span>'); 373 } 374 375 function handleLoadError(expand_bar) { 376 // FIXME: In this case, try fetching the source file at the revision the patch was created at, 377 // in case the file has bee deleted. 378 // Might need to modify webkit-patch to include that data in the diff. 379 replaceExpandLinkContainers(expand_bar, "Can't expand. Is this a new or deleted file?"); 380 } 381 382 var ABOVE = 'above'; 383 var BELOW = 'below'; 384 var ALL = 'all'; 385 386 function expand(expand_bar, file_name, direction, amount) { 387 if (file_name in original_file_contents && !patched_file_contents[file_name]) { 388 // FIXME: In this case, try fetching the source file at the revision the patch was created at. 389 // Might need to modify webkit-patch to include that data in the diff. 390 replaceExpandLinkContainers(expand_bar, "Can't expand. Unable to apply patch to tip of tree."); 391 return; 392 } 393 394 var above_expansion = expand_bar.querySelector('.Expand' + ABOVE) 395 var below_expansion = expand_bar.querySelector('.Expand' + BELOW) 396 397 var above_last_line = above_expansion.querySelector('.ExpansionLine:last-of-type'); 398 if (!above_last_line) { 399 var diff_section = expand_bar.previousElementSibling; 400 above_last_line = diff_section.querySelector('.Line:last-of-type'); 401 } 402 403 var above_last_line_num, above_last_from_line_num; 404 if (above_last_line) { 405 above_last_line_num = toLineNumber(above_last_line); 406 above_last_from_line_num = fromLineNumber(above_last_line); 407 } else 408 above_last_from_line_num = above_last_line_num = 0; 409 410 var below_first_line = below_expansion.querySelector('.ExpansionLine'); 411 if (!below_first_line) { 412 var diff_section = expand_bar.nextElementSibling; 413 if (diff_section) 414 below_first_line = diff_section.querySelector('.Line'); 415 } 416 417 var below_first_line_num, below_first_from_line_num; 418 if (below_first_line) { 419 below_first_line_num = toLineNumber(below_first_line) - 1; 420 below_first_from_line_num = fromLineNumber(below_first_line) - 1; 421 } else 422 below_first_from_line_num = below_first_line_num = patched_file_contents[file_name].length - 1; 423 424 var start_line_num, start_from_line_num; 425 var end_line_num; 426 427 if (direction == ABOVE) { 428 start_from_line_num = above_last_from_line_num; 429 start_line_num = above_last_line_num; 430 end_line_num = Math.min(start_line_num + amount, below_first_line_num); 431 } else if (direction == BELOW) { 432 end_line_num = below_first_line_num; 433 start_line_num = Math.max(end_line_num - amount, above_last_line_num) 434 start_from_line_num = Math.max(below_first_from_line_num - amount, above_last_from_line_num) 435 } else { // direction == ALL 436 start_line_num = above_last_line_num; 437 start_from_line_num = above_last_from_line_num; 438 end_line_num = below_first_line_num; 439 } 440 441 var expansion_area; 442 // Filling in all the remaining lines. Overwrite the expand links. 443 if (start_line_num == above_last_line_num && end_line_num == below_first_line_num) { 444 expansion_area = expand_bar.querySelector('.ExpandLinkContainer'); 445 expansion_area.innerHTML = ''; 446 } else { 447 expansion_area = direction == ABOVE ? above_expansion : below_expansion; 448 } 449 450 insertLines(file_name, expansion_area, direction, start_line_num, end_line_num, start_from_line_num); 451 } 452 453 function insertLines(file_name, expansion_area, direction, start_line_num, end_line_num, start_from_line_num) { 454 var fragment = document.createDocumentFragment(); 455 for (var i = 0; i < end_line_num - start_line_num; i++) { 456 var line = document.createElement('div'); 457 line.className = 'ExpansionLine'; 458 // FIXME: from line numbers are wrong 459 line.innerHTML = '<span class="from expansionlineNumber">' + (start_from_line_num + i + 1) + 460 '</span><span class="to expansionlineNumber">' + (start_line_num + i + 1) + 461 '</span> <span class="text"></span>'; 462 line.querySelector('.text').textContent = patched_file_contents[file_name][start_line_num + i]; 463 fragment.appendChild(line); 464 } 465 466 if (direction == BELOW) 467 expansion_area.insertBefore(fragment, expansion_area.firstChild); 468 else 469 expansion_area.appendChild(fragment); 470 } 471 472 function hunkStartingLine(patched_file, context, prev_line, hunk_num) { 473 var PATCH_FUZZ = 2; 474 var current_line = -1; 475 var last_context_line = context[context.length - 1]; 476 if (patched_file[prev_line] == last_context_line) 477 current_line = prev_line + 1; 478 else { 479 for (var i = prev_line - PATCH_FUZZ; i < prev_line + PATCH_FUZZ; i++) { 480 if (patched_file[i] == last_context_line) 481 current_line = i + 1; 482 } 483 484 if (current_line == -1) { 485 console.log('Hunk #' + hunk_num + ' FAILED.'); 486 return -1; 487 } 488 } 489 490 // For paranoia sake, confirm the rest of the context matches; 491 for (var i = 0; i < context.length - 1; i++) { 492 if (patched_file[current_line - context.length + i] != context[i]) { 493 console.log('Hunk #' + hunk_num + ' FAILED. Did not match preceding context.'); 494 return -1; 495 } 496 } 497 498 return current_line; 499 } 500 501 function fromLineNumber(line) { 502 return Number(line.querySelector('.from').textContent); 503 } 504 505 function toLineNumber(line) { 506 return Number(line.querySelector('.to').textContent); 507 } 508 509 function lineNumberForFirstNonContextLine(patched_file, line, prev_line, context, hunk_num) { 510 if (context.length) { 511 var prev_line_num = fromLineNumber(prev_line) - 1; 512 return hunkStartingLine(patched_file, context, prev_line_num, hunk_num); 513 } 514 515 if (toLineNumber(line) == 1 || fromLineNumber(line) == 1) 516 return 0; 517 518 console.log('Failed to apply patch. Adds or removes lines before any context lines.'); 519 return -1; 520 } 521 522 function applyDiff(original_file, file_name) { 523 var diff_sections = files[file_name].getElementsByClassName('DiffSection'); 524 var patched_file = original_file.concat([]); 525 526 // Apply diffs in reverse order to avoid needing to keep track of changing line numbers. 527 for (var i = diff_sections.length - 1; i >= 0; i--) { 528 var section = diff_sections[i]; 529 var lines = section.getElementsByClassName('Line'); 530 var current_line = -1; 531 var context = []; 532 var hunk_num = i + 1; 533 534 for (var j = 0, lines_len = lines.length; j < lines_len; j++) { 535 var line = lines[j]; 536 var line_contents = line.querySelector('.text').textContent; 537 if ($(line).hasClass('add')) { 538 if (current_line == -1) { 539 current_line = lineNumberForFirstNonContextLine(patched_file, line, lines[j-1], context, hunk_num); 540 if (current_line == -1) 541 return null; 542 } 543 544 patched_file.splice(current_line, 0, line_contents); 545 current_line++; 546 } else if ($(line).hasClass('remove')) { 547 if (current_line == -1) { 548 current_line = lineNumberForFirstNonContextLine(patched_file, line, lines[j-1], context, hunk_num); 549 if (current_line == -1) 550 return null; 551 } 552 553 if (patched_file[current_line] != line_contents) { 554 console.log('Hunk #' + hunk_num + ' FAILED.'); 555 return null; 556 } 557 558 patched_file.splice(current_line, 1); 559 } else if (current_line == -1) { 560 context.push(line_contents); 561 } else if (line_contents != patched_file[current_line]) { 562 console.log('Hunk #' + hunk_num + ' FAILED. Context at end did not match'); 563 return null; 564 } else { 565 current_line++; 566 } 567 } 568 } 569 570 return patched_file; 261 571 } 262 572
Note: See TracChangeset
for help on using the changeset viewer.