/
githubmirror
/
TypeScript
Обзор
Документация
Войти
/
githubmirror
/
TypeScript
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/harness/documentsUtil.ts
189 строк
7 KB
Isabel Duan
Enable `--isolatedDeclarations` on TS codebase (#59635)
16 сен 2024, 04:10
Не верифицирован
16 сен 2024, 04:10
52eaa7b
Код
Авторство
О чём код?
import * as Harness from "./_namespaces/Harness.js"; import * as ts from "./_namespaces/ts.js"; // NOTE: The contents of this file are all exported from the namespace 'documents'. This is to // support the eventual conversion of harness into a modular system. export class TextDocument { public readonly meta: Map<string, string>; public readonly file: string; public readonly text: string; private _lineStarts: readonly number[] | undefined; private _testFile: Harness.Compiler.TestFile | undefined; constructor(file: string, text: string, meta?: Map<string, string>) { this.file = file; this.text = text; this.meta = meta || new Map<string, string>(); } public get lineStarts(): readonly number[] { return this._lineStarts || (this._lineStarts = ts.computeLineStarts(this.text)); } public static fromTestFile(file: Harness.Compiler.TestFile): TextDocument { return new TextDocument( file.unitName, file.content, file.fileOptions && Object.keys(file.fileOptions) .reduce((meta, key) => meta.set(key, file.fileOptions[key]), new Map<string, string>()), ); } public asTestFile(): Harness.Compiler.TestFile { return this._testFile || (this._testFile = { unitName: this.file, content: this.text, fileOptions: ts.arrayFrom(this.meta) .reduce((obj, [key, value]) => (obj[key] = value, obj), {} as Record<string, string>), }); } } export interface RawSourceMap { version: number; file: string; sourceRoot?: string; sources: string[]; sourcesContent?: string[]; names: string[]; mappings: string; } export interface Mapping { mappingIndex: number; emittedLine: number; emittedColumn: number; sourceIndex: number; sourceLine: number; sourceColumn: number; nameIndex?: number; } export class SourceMap { public readonly raw: RawSourceMap; public readonly mapFile: string | undefined; public readonly version: number; public readonly file: string; public readonly sourceRoot: string | undefined; public readonly sources: readonly string[] = []; public readonly sourcesContent: readonly string[] | undefined; public readonly mappings: readonly Mapping[] = []; public readonly names: readonly string[] | undefined; private static readonly _mappingRegExp = /([A-Z0-9+/]+),?|(;)|./gi; private static readonly _sourceMappingURLRegExp = /^\/\/[#@]\s*sourceMappingURL\s*=\s*(.*?)\s*$/gim; private static readonly _dataURLRegExp = /^data:application\/json;base64,([a-z0-9+/=]+)$/i; private static readonly _base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; private _emittedLineMappings: Mapping[][] = []; private _sourceLineMappings: Mapping[][][] = []; constructor(mapFile: string | undefined, data: string | RawSourceMap) { this.raw = typeof data === "string" ? JSON.parse(data) as RawSourceMap : data; this.mapFile = mapFile; this.version = this.raw.version; this.file = this.raw.file; this.sourceRoot = this.raw.sourceRoot; this.sources = this.raw.sources; this.sourcesContent = this.raw.sourcesContent; this.names = this.raw.names; // populate mappings const mappings: Mapping[] = []; let emittedLine = 0; let emittedColumn = 0; let sourceIndex = 0; let sourceLine = 0; let sourceColumn = 0; let nameIndex = 0; let match: RegExpExecArray | null; // eslint-disable-line no-restricted-syntax while (match = SourceMap._mappingRegExp.exec(this.raw.mappings)) { if (match[1]) { const segment = SourceMap._decodeVLQ(match[1]); if (segment.length !== 1 && segment.length !== 4 && segment.length !== 5) { throw new Error("Invalid VLQ"); } emittedColumn += segment[0]; if (segment.length >= 4) { sourceIndex += segment[1]; sourceLine += segment[2]; sourceColumn += segment[3]; } const mapping: Mapping = { mappingIndex: mappings.length, emittedLine, emittedColumn, sourceIndex, sourceLine, sourceColumn }; if (segment.length === 5) { nameIndex += segment[4]; mapping.nameIndex = nameIndex; } mappings.push(mapping); const mappingsForEmittedLine = this._emittedLineMappings[mapping.emittedLine] || (this._emittedLineMappings[mapping.emittedLine] = []); mappingsForEmittedLine.push(mapping); const mappingsForSource = this._sourceLineMappings[mapping.sourceIndex] || (this._sourceLineMappings[mapping.sourceIndex] = []); const mappingsForSourceLine = mappingsForSource[mapping.sourceLine] || (mappingsForSource[mapping.sourceLine] = []); mappingsForSourceLine.push(mapping); } else if (match[2]) { emittedLine++; emittedColumn = 0; } else { throw new Error(`Unrecognized character '${match[0]}'.`); } } this.mappings = mappings; } public static getUrl(text: string): string | undefined { let match: RegExpExecArray | null; // eslint-disable-line no-restricted-syntax let lastMatch: RegExpExecArray | undefined; while (match = SourceMap._sourceMappingURLRegExp.exec(text)) { lastMatch = match; } return lastMatch ? lastMatch[1] : undefined; } public static fromUrl(url: string): SourceMap | undefined { const match = SourceMap._dataURLRegExp.exec(url); return match ? new SourceMap(/*mapFile*/ undefined, ts.sys.base64decode!(match[1])) : undefined; } public static fromSource(text: string): SourceMap | undefined { const url = this.getUrl(text); return url === undefined ? undefined : this.fromUrl(url); } public getMappingsForEmittedLine(emittedLine: number): readonly Mapping[] | undefined { return this._emittedLineMappings[emittedLine]; } public getMappingsForSourceLine(sourceIndex: number, sourceLine: number): readonly Mapping[] | undefined { const mappingsForSource = this._sourceLineMappings[sourceIndex]; return mappingsForSource && mappingsForSource[sourceLine]; } private static _decodeVLQ(text: string): number[] { const vlq: number[] = []; let shift = 0; let value = 0; for (let i = 0; i < text.length; i++) { const currentByte = SourceMap._base64Chars.indexOf(text.charAt(i)); value += (currentByte & 31) << shift; if ((currentByte & 32) === 0) { vlq.push(value & 1 ? -(value >>> 1) : value >>> 1); shift = 0; value = 0; } else { shift += 5; } } return vlq; } }