92 lines
2.4 KiB
JavaScript
92 lines
2.4 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const adoptBuffer = require('./adopt-buffer.cjs');
|
||
|
const charCodeDefinitions = require('./char-code-definitions.cjs');
|
||
|
|
||
|
const N = 10;
|
||
|
const F = 12;
|
||
|
const R = 13;
|
||
|
|
||
|
function computeLinesAndColumns(host) {
|
||
|
const source = host.source;
|
||
|
const sourceLength = source.length;
|
||
|
const startOffset = source.length > 0 ? charCodeDefinitions.isBOM(source.charCodeAt(0)) : 0;
|
||
|
const lines = adoptBuffer.adoptBuffer(host.lines, sourceLength);
|
||
|
const columns = adoptBuffer.adoptBuffer(host.columns, sourceLength);
|
||
|
let line = host.startLine;
|
||
|
let column = host.startColumn;
|
||
|
|
||
|
for (let i = startOffset; i < sourceLength; i++) {
|
||
|
const code = source.charCodeAt(i);
|
||
|
|
||
|
lines[i] = line;
|
||
|
columns[i] = column++;
|
||
|
|
||
|
if (code === N || code === R || code === F) {
|
||
|
if (code === R && i + 1 < sourceLength && source.charCodeAt(i + 1) === N) {
|
||
|
i++;
|
||
|
lines[i] = line;
|
||
|
columns[i] = column;
|
||
|
}
|
||
|
|
||
|
line++;
|
||
|
column = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lines[sourceLength] = line;
|
||
|
columns[sourceLength] = column;
|
||
|
|
||
|
host.lines = lines;
|
||
|
host.columns = columns;
|
||
|
host.computed = true;
|
||
|
}
|
||
|
|
||
|
class OffsetToLocation {
|
||
|
constructor() {
|
||
|
this.lines = null;
|
||
|
this.columns = null;
|
||
|
this.computed = false;
|
||
|
}
|
||
|
setSource(source, startOffset = 0, startLine = 1, startColumn = 1) {
|
||
|
this.source = source;
|
||
|
this.startOffset = startOffset;
|
||
|
this.startLine = startLine;
|
||
|
this.startColumn = startColumn;
|
||
|
this.computed = false;
|
||
|
}
|
||
|
getLocation(offset, filename) {
|
||
|
if (!this.computed) {
|
||
|
computeLinesAndColumns(this);
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
source: filename,
|
||
|
offset: this.startOffset + offset,
|
||
|
line: this.lines[offset],
|
||
|
column: this.columns[offset]
|
||
|
};
|
||
|
}
|
||
|
getLocationRange(start, end, filename) {
|
||
|
if (!this.computed) {
|
||
|
computeLinesAndColumns(this);
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
source: filename,
|
||
|
start: {
|
||
|
offset: this.startOffset + start,
|
||
|
line: this.lines[start],
|
||
|
column: this.columns[start]
|
||
|
},
|
||
|
end: {
|
||
|
offset: this.startOffset + end,
|
||
|
line: this.lines[end],
|
||
|
column: this.columns[end]
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exports.OffsetToLocation = OffsetToLocation;
|