UNPKG

@rightcapital/phpdoc-parser

Version:

TypeScript version of PHPDoc parser with support for intersection types and generics

112 lines (111 loc) 3.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Differ = void 0; const diff_elem_1 = require("./diff-elem"); class Differ { constructor(isEqual) { this.isEqual = isEqual; } diff(old, newElements) { const [trace, x, y] = this.calculateTrace(old, newElements); return this.extractDiff(trace, x, y, old, newElements); } diffWithReplacements(old, newElements) { return this.coalesceReplacements(this.diff(old, newElements)); } calculateTrace(old, newElements) { const n = old.length; const m = newElements.length; const max = n + m; const v = { 1: 0 }; const trace = []; for (let d = 0; d <= max; d++) { trace.push(Object.assign({}, v)); for (let k = -d; k <= d; k += 2) { let x; if (k === -d || (k !== d && v[k - 1] < v[k + 1])) { x = v[k + 1]; } else { x = v[k - 1] + 1; } let y = x - k; while (x < n && y < m && this.isEqual(old[x], newElements[y])) { x++; y++; } v[k] = x; if (x >= n && y >= m) { return [trace, x, y]; } } } throw new Error('Should not happen'); } extractDiff(trace, x, y, old, newElements) { const result = []; for (let d = trace.length - 1; d >= 0; d--) { const v = trace[d]; const k = x - y; let prevK; if (k === -d || (k !== d && v[k - 1] < v[k + 1])) { prevK = k + 1; } else { prevK = k - 1; } const prevX = v[prevK]; const prevY = prevX - prevK; while (x > prevX && y > prevY) { result.push(new diff_elem_1.DiffElem(diff_elem_1.DiffElemType.KEEP, old[x - 1], newElements[y - 1])); x--; y--; } if (d === 0) { break; } while (x > prevX) { result.push(new diff_elem_1.DiffElem(diff_elem_1.DiffElemType.REMOVE, old[x - 1], null)); x--; } while (y > prevY) { result.push(new diff_elem_1.DiffElem(diff_elem_1.DiffElemType.ADD, null, newElements[y - 1])); y--; } } return result.reverse(); } coalesceReplacements(diff) { const newDiff = []; const c = diff.length; for (let i = 0; i < c; i++) { const diffType = diff[i].type; if (diffType !== diff_elem_1.DiffElemType.REMOVE) { newDiff.push(diff[i]); continue; } let j = i; while (j < c && diff[j].type === diff_elem_1.DiffElemType.REMOVE) { j++; } let k = j; while (k < c && diff[k].type === diff_elem_1.DiffElemType.ADD) { k++; } if (j - i === k - j) { const len = j - i; for (let n = 0; n < len; n++) { newDiff.push(new diff_elem_1.DiffElem(diff_elem_1.DiffElemType.REPLACE, diff[i + n].old, diff[j + n].new)); } } else { for (; i < k; i++) { newDiff.push(diff[i]); } } i = k - 1; } return newDiff; } } exports.Differ = Differ;