Permalink
Cannot retrieve contributors at this time
309 lines (248 sloc)
6.99 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/concordance/lib/lineBuilder.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const ACTUAL = Symbol('lineBuilder.gutters.ACTUAL') | |
const EXPECTED = Symbol('lineBuilder.gutters.EXPECTED') | |
function translateGutter (theme, invert, gutter) { | |
if (invert) { | |
if (gutter === ACTUAL) return theme.diffGutters.expected | |
if (gutter === EXPECTED) return theme.diffGutters.actual | |
} else { | |
if (gutter === ACTUAL) return theme.diffGutters.actual | |
if (gutter === EXPECTED) return theme.diffGutters.expected | |
} | |
return theme.diffGutters.padding | |
} | |
class Line { | |
constructor (isFirst, isLast, gutter, stringValue) { | |
this.isFirst = isFirst | |
this.isLast = isLast | |
this.gutter = gutter | |
this.stringValue = stringValue | |
} | |
* [Symbol.iterator] () { | |
yield this | |
} | |
get isEmpty () { | |
return false | |
} | |
get hasGutter () { | |
return this.gutter !== null | |
} | |
get isSingle () { | |
return this.isFirst && this.isLast | |
} | |
append (other) { | |
return this.concat(other) | |
} | |
concat (other) { | |
return new Collection() | |
.append(this) | |
.append(other) | |
} | |
toString (options) { | |
if (options.diff === false) return this.stringValue | |
return translateGutter(options.theme, options.invert, this.gutter) + this.stringValue | |
} | |
mergeWithInfix (infix, other) { | |
if (other.isLine !== true) { | |
return new Collection() | |
.append(this) | |
.mergeWithInfix(infix, other) | |
} | |
return new Line(this.isFirst, other.isLast, other.gutter, this.stringValue + infix + other.stringValue) | |
} | |
withFirstPrefixed (prefix) { | |
if (!this.isFirst) return this | |
return new Line(true, this.isLast, this.gutter, prefix + this.stringValue) | |
} | |
withLastPostfixed (postfix) { | |
if (!this.isLast) return this | |
return new Line(this.isFirst, true, this.gutter, this.stringValue + postfix) | |
} | |
stripFlags () { | |
return new Line(false, false, this.gutter, this.stringValue) | |
} | |
decompose () { | |
return new Collection() | |
.append(this) | |
.decompose() | |
} | |
} | |
Object.defineProperty(Line.prototype, 'isLine', { value: true }) | |
class Collection { | |
constructor () { | |
this.buffer = [] | |
} | |
* [Symbol.iterator] () { | |
for (const appended of this.buffer) { | |
for (const line of appended) yield line | |
} | |
} | |
get isEmpty () { | |
return this.buffer.length === 0 | |
} | |
get hasGutter () { | |
for (const line of this) { | |
if (line.hasGutter) return true | |
} | |
return false | |
} | |
get isSingle () { | |
const iterator = this[Symbol.iterator]() | |
iterator.next() | |
return iterator.next().done === true | |
} | |
append (lineOrLines) { | |
if (!lineOrLines.isEmpty) this.buffer.push(lineOrLines) | |
return this | |
} | |
concat (other) { | |
return new Collection() | |
.append(this) | |
.append(other) | |
} | |
toString (options) { | |
let lines = this | |
if (options.invert) { | |
lines = new Collection() | |
let buffer = new Collection() | |
let prev = null | |
for (const line of this) { | |
if (line.gutter === ACTUAL) { | |
if (prev !== null && prev.gutter !== ACTUAL && !buffer.isEmpty) { | |
lines.append(buffer) | |
buffer = new Collection() | |
} | |
buffer.append(line) | |
} else if (line.gutter === EXPECTED) { | |
lines.append(line) | |
} else { | |
if (!buffer.isEmpty) { | |
lines.append(buffer) | |
buffer = new Collection() | |
} | |
lines.append(line) | |
} | |
prev = line | |
} | |
lines.append(buffer) | |
} | |
return Array.from(lines, line => line.toString(options)).join('\n') | |
} | |
mergeWithInfix (infix, from) { | |
if (from.isEmpty) throw new Error('Cannot merge, `from` is empty.') | |
const otherLines = Array.from(from) | |
if (!otherLines[0].isFirst) throw new Error('Cannot merge, `from` has no first line.') | |
const merged = new Collection() | |
let seenLast = false | |
for (const line of this) { | |
if (seenLast) throw new Error('Cannot merge line, the last line has already been seen.') | |
if (!line.isLast) { | |
merged.append(line) | |
continue | |
} | |
seenLast = true | |
for (const other of otherLines) { | |
if (other.isFirst) { | |
merged.append(line.mergeWithInfix(infix, other)) | |
} else { | |
merged.append(other) | |
} | |
} | |
} | |
return merged | |
} | |
withFirstPrefixed (prefix) { | |
return new Collection() | |
.append(Array.from(this, line => line.withFirstPrefixed(prefix))) | |
} | |
withLastPostfixed (postfix) { | |
return new Collection() | |
.append(Array.from(this, line => line.withLastPostfixed(postfix))) | |
} | |
stripFlags () { | |
return new Collection() | |
.append(Array.from(this, line => line.stripFlags())) | |
} | |
decompose () { | |
const first = { actual: new Collection(), expected: new Collection() } | |
const last = { actual: new Collection(), expected: new Collection() } | |
const remaining = new Collection() | |
for (const line of this) { | |
if (line.isFirst && line.gutter === ACTUAL) { | |
first.actual.append(line) | |
} else if (line.isFirst && line.gutter === EXPECTED) { | |
first.expected.append(line) | |
} else if (line.isLast && line.gutter === ACTUAL) { | |
last.actual.append(line) | |
} else if (line.isLast && line.gutter === EXPECTED) { | |
last.expected.append(line) | |
} else { | |
remaining.append(line) | |
} | |
} | |
return { first, last, remaining } | |
} | |
} | |
Object.defineProperty(Collection.prototype, 'isCollection', { value: true }) | |
function setDefaultGutter (iterable, gutter) { | |
return new Collection() | |
.append(Array.from(iterable, line => { | |
return line.gutter === null | |
? new Line(line.isFirst, line.isLast, gutter, line.stringValue) | |
: line | |
})) | |
} | |
module.exports = { | |
buffer () { | |
return new Collection() | |
}, | |
first (stringValue) { | |
return new Line(true, false, null, stringValue) | |
}, | |
last (stringValue) { | |
return new Line(false, true, null, stringValue) | |
}, | |
line (stringValue) { | |
return new Line(false, false, null, stringValue) | |
}, | |
single (stringValue) { | |
return new Line(true, true, null, stringValue) | |
}, | |
setDefaultGutter (lineOrCollection) { | |
return lineOrCollection | |
}, | |
actual: { | |
first (stringValue) { | |
return new Line(true, false, ACTUAL, stringValue) | |
}, | |
last (stringValue) { | |
return new Line(false, true, ACTUAL, stringValue) | |
}, | |
line (stringValue) { | |
return new Line(false, false, ACTUAL, stringValue) | |
}, | |
single (stringValue) { | |
return new Line(true, true, ACTUAL, stringValue) | |
}, | |
setDefaultGutter (lineOrCollection) { | |
return setDefaultGutter(lineOrCollection, ACTUAL) | |
}, | |
}, | |
expected: { | |
first (stringValue) { | |
return new Line(true, false, EXPECTED, stringValue) | |
}, | |
last (stringValue) { | |
return new Line(false, true, EXPECTED, stringValue) | |
}, | |
line (stringValue) { | |
return new Line(false, false, EXPECTED, stringValue) | |
}, | |
single (stringValue) { | |
return new Line(true, true, EXPECTED, stringValue) | |
}, | |
setDefaultGutter (lineOrCollection) { | |
return setDefaultGutter(lineOrCollection, EXPECTED) | |
}, | |
}, | |
} |