Loading src/context/location.spec.ts +19 −0 Original line number Diff line number Diff line Loading @@ -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, }); }); }); src/context/location.ts +33 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } Loading
src/context/location.spec.ts +19 −0 Original line number Diff line number Diff line Loading @@ -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, }); }); });
src/context/location.ts +33 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; }