123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- var assert = require("assert");
- var types = require("./types");
- var isString = types.builtInTypes.string;
- var isNumber = types.builtInTypes.number;
- var SourceLocation = types.namedTypes.SourceLocation;
- var Position = types.namedTypes.Position;
- var linesModule = require("./lines");
- var comparePos = require("./util").comparePos;
- function Mapping(sourceLines, sourceLoc, targetLoc) {
- assert.ok(this instanceof Mapping);
- assert.ok(sourceLines instanceof linesModule.Lines);
- SourceLocation.assert(sourceLoc);
- if (targetLoc) {
- // In certain cases it's possible for targetLoc.{start,end}.column
- // values to be negative, which technically makes them no longer
- // valid SourceLocation nodes, so we need to be more forgiving.
- assert.ok(
- isNumber.check(targetLoc.start.line) &&
- isNumber.check(targetLoc.start.column) &&
- isNumber.check(targetLoc.end.line) &&
- isNumber.check(targetLoc.end.column)
- );
- } else {
- // Assume identity mapping if no targetLoc specified.
- targetLoc = sourceLoc;
- }
- Object.defineProperties(this, {
- sourceLines: { value: sourceLines },
- sourceLoc: { value: sourceLoc },
- targetLoc: { value: targetLoc }
- });
- }
- var Mp = Mapping.prototype;
- module.exports = Mapping;
- Mp.slice = function(lines, start, end) {
- assert.ok(lines instanceof linesModule.Lines);
- Position.assert(start);
- if (end) {
- Position.assert(end);
- } else {
- end = lines.lastPos();
- }
- var sourceLines = this.sourceLines;
- var sourceLoc = this.sourceLoc;
- var targetLoc = this.targetLoc;
- function skip(name) {
- var sourceFromPos = sourceLoc[name];
- var targetFromPos = targetLoc[name];
- var targetToPos = start;
- if (name === "end") {
- targetToPos = end;
- } else {
- assert.strictEqual(name, "start");
- }
- return skipChars(
- sourceLines, sourceFromPos,
- lines, targetFromPos, targetToPos
- );
- }
- if (comparePos(start, targetLoc.start) <= 0) {
- if (comparePos(targetLoc.end, end) <= 0) {
- targetLoc = {
- start: subtractPos(targetLoc.start, start.line, start.column),
- end: subtractPos(targetLoc.end, start.line, start.column)
- };
- // The sourceLoc can stay the same because the contents of the
- // targetLoc have not changed.
- } else if (comparePos(end, targetLoc.start) <= 0) {
- return null;
- } else {
- sourceLoc = {
- start: sourceLoc.start,
- end: skip("end")
- };
- targetLoc = {
- start: subtractPos(targetLoc.start, start.line, start.column),
- end: subtractPos(end, start.line, start.column)
- };
- }
- } else {
- if (comparePos(targetLoc.end, start) <= 0) {
- return null;
- }
- if (comparePos(targetLoc.end, end) <= 0) {
- sourceLoc = {
- start: skip("start"),
- end: sourceLoc.end
- };
- targetLoc = {
- // Same as subtractPos(start, start.line, start.column):
- start: { line: 1, column: 0 },
- end: subtractPos(targetLoc.end, start.line, start.column)
- };
- } else {
- sourceLoc = {
- start: skip("start"),
- end: skip("end")
- };
- targetLoc = {
- // Same as subtractPos(start, start.line, start.column):
- start: { line: 1, column: 0 },
- end: subtractPos(end, start.line, start.column)
- };
- }
- }
- return new Mapping(this.sourceLines, sourceLoc, targetLoc);
- };
- Mp.add = function(line, column) {
- return new Mapping(this.sourceLines, this.sourceLoc, {
- start: addPos(this.targetLoc.start, line, column),
- end: addPos(this.targetLoc.end, line, column)
- });
- };
- function addPos(toPos, line, column) {
- return {
- line: toPos.line + line - 1,
- column: (toPos.line === 1)
- ? toPos.column + column
- : toPos.column
- };
- }
- Mp.subtract = function(line, column) {
- return new Mapping(this.sourceLines, this.sourceLoc, {
- start: subtractPos(this.targetLoc.start, line, column),
- end: subtractPos(this.targetLoc.end, line, column)
- });
- };
- function subtractPos(fromPos, line, column) {
- return {
- line: fromPos.line - line + 1,
- column: (fromPos.line === line)
- ? fromPos.column - column
- : fromPos.column
- };
- }
- Mp.indent = function(by, skipFirstLine, noNegativeColumns) {
- if (by === 0) {
- return this;
- }
- var targetLoc = this.targetLoc;
- var startLine = targetLoc.start.line;
- var endLine = targetLoc.end.line;
- if (skipFirstLine && startLine === 1 && endLine === 1) {
- return this;
- }
- targetLoc = {
- start: targetLoc.start,
- end: targetLoc.end
- };
- if (!skipFirstLine || startLine > 1) {
- var startColumn = targetLoc.start.column + by;
- targetLoc.start = {
- line: startLine,
- column: noNegativeColumns
- ? Math.max(0, startColumn)
- : startColumn
- };
- }
- if (!skipFirstLine || endLine > 1) {
- var endColumn = targetLoc.end.column + by;
- targetLoc.end = {
- line: endLine,
- column: noNegativeColumns
- ? Math.max(0, endColumn)
- : endColumn
- };
- }
- return new Mapping(this.sourceLines, this.sourceLoc, targetLoc);
- };
- function skipChars(
- sourceLines, sourceFromPos,
- targetLines, targetFromPos, targetToPos
- ) {
- assert.ok(sourceLines instanceof linesModule.Lines);
- assert.ok(targetLines instanceof linesModule.Lines);
- Position.assert(sourceFromPos);
- Position.assert(targetFromPos);
- Position.assert(targetToPos);
- var targetComparison = comparePos(targetFromPos, targetToPos);
- if (targetComparison === 0) {
- // Trivial case: no characters to skip.
- return sourceFromPos;
- }
- if (targetComparison < 0) {
- // Skipping forward.
- var sourceCursor = sourceLines.skipSpaces(sourceFromPos);
- var targetCursor = targetLines.skipSpaces(targetFromPos);
- var lineDiff = targetToPos.line - targetCursor.line;
- sourceCursor.line += lineDiff;
- targetCursor.line += lineDiff;
- if (lineDiff > 0) {
- // If jumping to later lines, reset columns to the beginnings
- // of those lines.
- sourceCursor.column = 0;
- targetCursor.column = 0;
- } else {
- assert.strictEqual(lineDiff, 0);
- }
- while (comparePos(targetCursor, targetToPos) < 0 &&
- targetLines.nextPos(targetCursor, true)) {
- assert.ok(sourceLines.nextPos(sourceCursor, true));
- assert.strictEqual(
- sourceLines.charAt(sourceCursor),
- targetLines.charAt(targetCursor)
- );
- }
- } else {
- // Skipping backward.
- var sourceCursor = sourceLines.skipSpaces(sourceFromPos, true);
- var targetCursor = targetLines.skipSpaces(targetFromPos, true);
- var lineDiff = targetToPos.line - targetCursor.line;
- sourceCursor.line += lineDiff;
- targetCursor.line += lineDiff;
- if (lineDiff < 0) {
- // If jumping to earlier lines, reset columns to the ends of
- // those lines.
- sourceCursor.column = sourceLines.getLineLength(sourceCursor.line);
- targetCursor.column = targetLines.getLineLength(targetCursor.line);
- } else {
- assert.strictEqual(lineDiff, 0);
- }
- while (comparePos(targetToPos, targetCursor) < 0 &&
- targetLines.prevPos(targetCursor, true)) {
- assert.ok(sourceLines.prevPos(sourceCursor, true));
- assert.strictEqual(
- sourceLines.charAt(sourceCursor),
- targetLines.charAt(targetCursor)
- );
- }
- }
- return sourceCursor;
- }
|