Commit cbd77960 authored by David Sveningsson's avatar David Sveningsson

feat(location): allow sliceLocation to wrap line/column

parent d718405d
......@@ -68,4 +68,23 @@ describe("sliceLocation()", () => {
size: null,
});
});
it("should wrap line/column when newlines are present", () => {
const text = "foo\nbar baz\nspam";
(location as any).size = text.length;
expect(sliceLocation(location, 8, 11, text)).toEqual({
filename: "-",
offset: 8,
line: 2,
column: 5,
size: 3,
});
expect(sliceLocation(location, 12, 16, text)).toEqual({
filename: "-",
offset: 12,
line: 3,
column: 1,
size: 4,
});
});
});
......@@ -27,6 +27,14 @@ export interface Location {
readonly size?: number;
}
interface LocationRW {
filename: string;
offset: number;
line: number;
column: number;
size?: number;
}
function sliceSize(size: number, begin: number, end?: number): number {
if (typeof size !== "number") {
return size;
......@@ -43,26 +51,47 @@ function sliceSize(size: number, begin: number, end?: number): number {
/**
* Calculate a new location by offsetting this location.
*
* It is assumed there is no newlines anywhere between current location and
* the new.
* If the references text with newlines the wrap parameter must be set to
* properly calculate line and column information. If not given the text is
* assumed to contain no newlines.
*
* @param location Source location
* @param begin - Start location. Default is 0.
* @param end - End location. Default is size of location. Negative values are
* counted from end, e.g. `-2` means `size - 2`.
* @param wrap - If given, line/column is wrapped for each newline occuring
* before location end.
*/
export function sliceLocation(
location: Location,
begin: number,
end?: number
end?: number,
wrap?: string
): Location {
if (!location) return null;
const size = sliceSize(location.size, begin, end);
return {
const sliced: LocationRW = {
filename: location.filename,
offset: location.offset + begin,
line: location.line,
column: location.column + begin,
size,
};
/* if text content is provided try to find all newlines and modify line/column accordingly */
if (wrap) {
let index = -1;
const col = sliced.column;
do {
index = wrap.indexOf("\n", index + 1);
if (index >= 0 && index < begin) {
sliced.column = col - (index + 1);
sliced.line++;
} else {
break;
}
} while (true); // eslint-disable-line no-constant-condition
}
return sliced;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment