diff --git a/lib/lines.ts b/lib/lines.ts index 22719536..38cf03ab 100644 --- a/lib/lines.ts +++ b/lib/lines.ts @@ -22,6 +22,10 @@ type LineInfo = { readonly sliceEnd: number; }; +type MutableLineInfo = { + -readonly [K in keyof LineInfo]: LineInfo[K]; +} + export class Lines { public readonly length: number; public readonly name: string | null; @@ -176,7 +180,7 @@ export class Lines { if (skipFirstLine && this.length === 1) return this; const lines = new Lines( - this.infos.map(function (info: any, i: any) { + this.infos.map(function (info, i) { if (info.line && (i > 0 || !skipFirstLine)) { info = { ...info, @@ -190,7 +194,7 @@ export class Lines { if (this.mappings.length > 0) { const newMappings = lines.mappings; invariant(newMappings.length === 0); - this.mappings.forEach(function (mapping: any) { + this.mappings.forEach(function (mapping) { newMappings.push(mapping.indent(width, skipFirstLine, true)); }); } @@ -204,7 +208,7 @@ export class Lines { } const lines = new Lines( - this.infos.map(function (info: any) { + this.infos.map(function (info) { if (info.line && !info.locked) { info = { ...info, @@ -218,7 +222,7 @@ export class Lines { if (this.mappings.length > 0) { const newMappings = lines.mappings; invariant(newMappings.length === 0); - this.mappings.forEach(function (mapping: any) { + this.mappings.forEach(function (mapping) { newMappings.push(mapping.indent(by)); }); } @@ -236,7 +240,7 @@ export class Lines { } const lines = new Lines( - this.infos.map(function (info: any, i: any) { + this.infos.map(function (info, i) { if (i > 0 && info.line && !info.locked) { info = { ...info, @@ -251,7 +255,7 @@ export class Lines { if (this.mappings.length > 0) { const newMappings = lines.mappings; invariant(newMappings.length === 0); - this.mappings.forEach(function (mapping: any) { + this.mappings.forEach(function (mapping) { newMappings.push(mapping.indent(by, true)); }); } @@ -265,7 +269,7 @@ export class Lines { } return new Lines( - this.infos.map((info: any, i: any) => ({ + this.infos.map((info, i) => ({ ...info, locked: i > 0, })), @@ -282,7 +286,7 @@ export class Lines { return this.cachedTabWidth; } - const counts: any[] = []; // Sparse array. + const counts: number[] = []; // Sparse array. let lastIndent = 0; for (let line = 1, last = this.length; line <= last; ++line) { @@ -527,7 +531,7 @@ export class Lines { } else { invariant(start.line < end.line); sliced[0] = sliceInfo(sliced[0], start.column); - sliced.push(sliceInfo(sliced.pop(), 0, end.column)); + sliced.push(sliceInfo(sliced.pop()!, 0, end.column)); } const lines = new Lines(sliced); @@ -535,7 +539,7 @@ export class Lines { if (this.mappings.length > 0) { const newMappings = lines.mappings; invariant(newMappings.length === 0); - this.mappings.forEach(function (this: any, mapping: any) { + this.mappings.forEach(function (this: Lines, mapping) { const sliced = mapping.slice(this, start, end); if (sliced) { newMappings.push(sliced); @@ -618,9 +622,9 @@ export class Lines { join(elements: (string | Lines)[]) { const separator = this; - const infos: any[] = []; - const mappings: any[] = []; - let prevInfo: any; + const infos: LineInfo[] = []; + const mappings: Mapping[] = []; + let prevInfo: MutableLineInfo | undefined; function appendLines(linesOrNull: Lines | null) { if (linesOrNull === null) { @@ -648,7 +652,7 @@ export class Lines { prevInfo.sliceEnd = prevInfo.line.length; if (linesOrNull.mappings.length > 0) { - linesOrNull.mappings.forEach(function (mapping: any) { + linesOrNull.mappings.forEach(function (mapping) { mappings.push(mapping.add(prevLine, prevColumn)); }); } @@ -656,7 +660,7 @@ export class Lines { mappings.push.apply(mappings, linesOrNull.mappings); } - linesOrNull.infos.forEach(function (info: any, i: any) { + linesOrNull.infos.forEach(function (info, i) { if (!prevInfo || i > 0) { prevInfo = { ...info }; infos.push(prevInfo); @@ -670,7 +674,7 @@ export class Lines { } elements - .map(function (elem: any) { + .map(function (elem) { const lines = fromString(elem); if (lines.isEmpty()) return null; return lines; @@ -700,11 +704,11 @@ export class Lines { } } -const fromStringCache: any = {}; +const fromStringCache: Record = {}; const hasOwn = fromStringCache.hasOwnProperty; const maxCacheKeyLen = 10; -export function countSpaces(spaces: any, tabWidth?: number) { +export function countSpaces(spaces: string, tabWidth?: number) { let count = 0; const len = spaces.length; @@ -794,7 +798,7 @@ function isOnlyWhitespace(string: string) { return !/\S/.test(string); } -function sliceInfo(info: any, startCol: number, endCol?: number) { +function sliceInfo(info: LineInfo, startCol: number, endCol?: number) { let sliceStart = info.sliceStart; let sliceEnd = info.sliceEnd; let indent = Math.max(info.indent, 0); @@ -848,7 +852,7 @@ function sliceInfo(info: any, startCol: number, endCol?: number) { }; } -export function concat(elements: any) { +export function concat(elements: (string | Lines)[]) { return emptyLines.join(elements); } diff --git a/test/lines.ts b/test/lines.ts index dcb0ad8e..645bb3cc 100644 --- a/test/lines.ts +++ b/test/lines.ts @@ -3,16 +3,20 @@ import fs from "fs"; import path from "path"; import { fromString, concat, countSpaces, Lines } from "../lib/lines"; import { EOL as eol } from "os"; +import { namedTypes } from "ast-types"; -function check(a: any, b: any) { - assert.strictEqual( - a.toString({ - lineTerminator: eol, - }), - b.toString({ - lineTerminator: eol, - }), - ); +type LinesInput = string | Lines; + +function toString(s: LinesInput): string { + if (typeof s === 'string') { + return s; + } + + return s.toString({ lineTerminator: eol }); +} + +function check(a: LinesInput, b: LinesInput) { + assert.strictEqual(toString(a), toString(b)); } describe("lines", function () { @@ -37,7 +41,7 @@ describe("lines", function () { }); it("FromString", function () { - function checkIsCached(s: any) { + function checkIsCached(s: LinesInput) { assert.strictEqual(fromString(s), fromString(s)); check(fromString(s), s); } @@ -66,19 +70,19 @@ describe("lines", function () { check(lines.indentTail(5).indentTail(-7).indentTail(2), code); }); - function testEachPosHelper(lines: any, code: any) { + function testEachPosHelper(lines: Lines, code: string) { check(lines, code); - const chars: any[] = []; + const chars: string[] = []; let emptyCount = 0; - function iterator(pos: any) { + function iterator(pos: namedTypes.Position) { const ch = lines.charAt(pos); if (ch === "") emptyCount += 1; chars.push(ch); } - lines.eachPos(iterator, null); + lines.eachPos(iterator, undefined); // The character at the position just past the end (as returned by // lastPos) should be the only empty string. @@ -94,7 +98,7 @@ describe("lines", function () { const withoutSpaces = code.replace(/\s+/g, ""); chars.length = emptyCount = 0; - lines.eachPos(iterator, null, true); // Skip spaces this time. + lines.eachPos(iterator, undefined, true); // Skip spaces this time. assert.strictEqual(emptyCount, 0); joined = chars.join(""); assert.strictEqual(joined.length, withoutSpaces.length); @@ -123,7 +127,7 @@ describe("lines", function () { const code = String(CharAtTest).replace(/\r\n/g, "\n"); const lines = fromString(code); - function compare(pos: any) { + function compare(pos: namedTypes.Position) { assert.strictEqual(lines.charAt(pos), lines.bootstrapCharAt(pos)); } @@ -133,7 +137,7 @@ describe("lines", function () { indented = original.indentTail(4), reference = fromString(" ab" + eol + " c"); - function compareIndented(pos: any) { + function compareIndented(pos: namedTypes.Position) { const c = indented.charAt(pos); check(c, reference.charAt(pos)); check(c, indented.bootstrapCharAt(pos)); @@ -197,7 +201,7 @@ describe("lines", function () { }); it("Empty", function () { - function c(s: any) { + function c(s: LinesInput) { const lines = fromString(s); check(lines, s); assert.strictEqual(lines.isEmpty(), s.length === 0); @@ -254,9 +258,9 @@ describe("lines", function () { checkAllSlices(lines); }); - function checkAllSlices(lines: any) { - lines.eachPos(function (start: any) { - lines.eachPos(function (end: any) { + function checkAllSlices(lines: Lines) { + lines.eachPos(function (start) { + lines.eachPos(function (end) { check(lines.slice(start, end), lines.bootstrapSlice(start, end)); check( lines.sliceString(start, end), @@ -266,7 +270,7 @@ describe("lines", function () { }); } - function getSourceLocation(lines: any) { + function getSourceLocation(lines: Lines) { return { start: lines.firstPos(), end: lines.lastPos() }; } @@ -274,7 +278,7 @@ describe("lines", function () { const code = String(GetSourceLocationTest), lines = fromString(code); - function verify(indent: any) { + function verify(indent: number) { const indented = lines.indentTail(indent), loc = getSourceLocation(indented), string = indented.toString(),