Skip to content

Commit fcd5025

Browse files
authored
Merge pull request #28886 from Microsoft/sourceMapDecoder
Enhancements to SourceMap decoder from tsserver
2 parents 3e0639a + c156c93 commit fcd5025

File tree

17 files changed

+1101
-201
lines changed

17 files changed

+1101
-201
lines changed

src/compiler/program.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,13 @@ namespace ts {
787787
// Key is a file name. Value is the (non-empty, or undefined) list of files that redirect to it.
788788
let redirectTargetsMap = createMultiMap<string>();
789789

790-
const filesByName = createMap<SourceFile | undefined>();
790+
/**
791+
* map with
792+
* - SourceFile if present
793+
* - false if sourceFile missing for source of project reference redirect
794+
* - undefined otherwise
795+
*/
796+
const filesByName = createMap<SourceFile | false | undefined>();
791797
let missingFilePaths: ReadonlyArray<Path> | undefined;
792798
// stores 'filename -> file association' ignoring case
793799
// used to track cases when two file names differ only in casing
@@ -854,7 +860,7 @@ namespace ts {
854860
}
855861
}
856862

857-
missingFilePaths = arrayFrom(filesByName.keys(), p => <Path>p).filter(p => !filesByName.get(p));
863+
missingFilePaths = arrayFrom(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined));
858864
files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles);
859865
processingDefaultLibFiles = undefined;
860866
processingOtherFiles = undefined;
@@ -1567,7 +1573,7 @@ namespace ts {
15671573
}
15681574

15691575
function getSourceFileByPath(path: Path): SourceFile | undefined {
1570-
return filesByName.get(path);
1576+
return filesByName.get(path) || undefined;
15711577
}
15721578

15731579
function getDiagnosticsHelper<T extends Diagnostic>(
@@ -2104,7 +2110,7 @@ namespace ts {
21042110

21052111
/** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */
21062112
function getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined {
2107-
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName)));
2113+
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName)) || undefined);
21082114
}
21092115

21102116
function getSourceFileFromReferenceWorker(
@@ -2235,7 +2241,7 @@ namespace ts {
22352241
}
22362242
}
22372243

2238-
return file;
2244+
return file || undefined;
22392245
}
22402246

22412247
let redirectedPath: Path | undefined;
@@ -2327,9 +2333,12 @@ namespace ts {
23272333
}
23282334

23292335
function addFileToFilesByName(file: SourceFile | undefined, path: Path, redirectedPath: Path | undefined) {
2330-
filesByName.set(path, file);
23312336
if (redirectedPath) {
23322337
filesByName.set(redirectedPath, file);
2338+
filesByName.set(path, file || false);
2339+
}
2340+
else {
2341+
filesByName.set(path, file);
23332342
}
23342343
}
23352344

src/compiler/scanner.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,14 @@ namespace ts {
337337
return result;
338338
}
339339

340-
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number {
341-
return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text);
342-
}
343-
340+
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number;
344341
/* @internal */
345-
export function getPositionOfLineAndCharacterWithEdits(sourceFile: SourceFileLike, line: number, character: number): number {
346-
return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, /*allowEdits*/ true);
342+
// tslint:disable-next-line:unified-signatures
343+
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number;
344+
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number {
345+
return sourceFile.getPositionOfLineAndCharacter ?
346+
sourceFile.getPositionOfLineAndCharacter(line, character, allowEdits) :
347+
computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, allowEdits);
347348
}
348349

349350
/* @internal */

src/compiler/sourcemap.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,24 @@ namespace ts {
266266
const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\s*$/;
267267
const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
268268

269+
export interface LineInfo {
270+
getLineCount(): number;
271+
getLineText(line: number): string;
272+
}
273+
274+
export function getLineInfo(text: string, lineStarts: ReadonlyArray<number>): LineInfo {
275+
return {
276+
getLineCount: () => lineStarts.length,
277+
getLineText: line => text.substring(lineStarts[line], lineStarts[line + 1])
278+
};
279+
}
280+
269281
/**
270282
* Tries to find the sourceMappingURL comment at the end of a file.
271-
* @param text The source text of the file.
272-
* @param lineStarts The line starts of the file.
273283
*/
274-
export function tryGetSourceMappingURL(text: string, lineStarts: ReadonlyArray<number> = computeLineStarts(text)) {
275-
for (let index = lineStarts.length - 1; index >= 0; index--) {
276-
const line = text.substring(lineStarts[index], lineStarts[index + 1]);
284+
export function tryGetSourceMappingURL(lineInfo: LineInfo) {
285+
for (let index = lineInfo.getLineCount() - 1; index >= 0; index--) {
286+
const line = lineInfo.getLineText(index);
277287
const comment = sourceMapCommentRegExp.exec(line);
278288
if (comment) {
279289
return comment[1];
@@ -573,7 +583,10 @@ namespace ts {
573583
}
574584

575585
function compareSourcePositions(left: SourceMappedPosition, right: SourceMappedPosition) {
576-
return compareValues(left.sourceIndex, right.sourceIndex);
586+
// Compares sourcePosition without comparing sourceIndex
587+
// since the mappings are grouped by sourceIndex
588+
Debug.assert(left.sourceIndex === right.sourceIndex);
589+
return compareValues(left.sourcePosition, right.sourcePosition);
577590
}
578591

579592
function compareGeneratedPositions(left: MappedPosition, right: MappedPosition) {
@@ -592,11 +605,9 @@ namespace ts {
592605
const mapDirectory = getDirectoryPath(mapPath);
593606
const sourceRoot = map.sourceRoot ? getNormalizedAbsolutePath(map.sourceRoot, mapDirectory) : mapDirectory;
594607
const generatedAbsoluteFilePath = getNormalizedAbsolutePath(map.file, mapDirectory);
595-
const generatedCanonicalFilePath = host.getCanonicalFileName(generatedAbsoluteFilePath) as Path;
596-
const generatedFile = host.getSourceFileLike(generatedCanonicalFilePath);
608+
const generatedFile = host.getSourceFileLike(generatedAbsoluteFilePath);
597609
const sourceFileAbsolutePaths = map.sources.map(source => getNormalizedAbsolutePath(source, sourceRoot));
598-
const sourceFileCanonicalPaths = sourceFileAbsolutePaths.map(source => host.getCanonicalFileName(source) as Path);
599-
const sourceToSourceIndexMap = createMapFromEntries(sourceFileCanonicalPaths.map((source, i) => [source, i] as [string, number]));
610+
const sourceToSourceIndexMap = createMapFromEntries(sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i] as [string, number]));
600611
let decodedMappings: ReadonlyArray<MappedPosition> | undefined;
601612
let generatedMappings: SortedReadonlyArray<MappedPosition> | undefined;
602613
let sourceMappings: ReadonlyArray<SortedReadonlyArray<SourceMappedPosition>> | undefined;
@@ -608,16 +619,15 @@ namespace ts {
608619

609620
function processMapping(mapping: Mapping): MappedPosition {
610621
const generatedPosition = generatedFile !== undefined
611-
? getPositionOfLineAndCharacterWithEdits(generatedFile, mapping.generatedLine, mapping.generatedCharacter)
622+
? getPositionOfLineAndCharacter(generatedFile, mapping.generatedLine, mapping.generatedCharacter, /*allowEdits*/ true)
612623
: -1;
613624
let source: string | undefined;
614625
let sourcePosition: number | undefined;
615626
if (isSourceMapping(mapping)) {
616-
const sourceFilePath = sourceFileCanonicalPaths[mapping.sourceIndex];
617-
const sourceFile = host.getSourceFileLike(sourceFilePath);
627+
const sourceFile = host.getSourceFileLike(sourceFileAbsolutePaths[mapping.sourceIndex]);
618628
source = map.sources[mapping.sourceIndex];
619629
sourcePosition = sourceFile !== undefined
620-
? getPositionOfLineAndCharacterWithEdits(sourceFile, mapping.sourceLine, mapping.sourceCharacter)
630+
? getPositionOfLineAndCharacter(sourceFile, mapping.sourceLine, mapping.sourceCharacter, /*allowEdits*/ true)
621631
: -1;
622632
}
623633
return {

src/compiler/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2617,6 +2617,8 @@ namespace ts {
26172617
export interface SourceFileLike {
26182618
readonly text: string;
26192619
lineMap?: ReadonlyArray<number>;
2620+
/* @internal */
2621+
getPositionOfLineAndCharacter?(line: number, character: number, allowEdits?: true): number;
26202622
}
26212623

26222624

@@ -5531,9 +5533,9 @@ namespace ts {
55315533

55325534
/* @internal */
55335535
export interface DocumentPositionMapperHost {
5534-
getSourceFileLike(path: Path): SourceFileLike | undefined;
5536+
getSourceFileLike(fileName: string): SourceFileLike | undefined;
55355537
getCanonicalFileName(path: string): string;
5536-
log?(text: string): void;
5538+
log(text: string): void;
55375539
}
55385540

55395541
/**

src/harness/sourceMapRecorder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ namespace Harness.SourceMapRecorder {
6969
SourceMapDecoder.initializeSourceMapDecoding(sourceMapData);
7070
sourceMapRecorder.WriteLine("===================================================================");
7171
sourceMapRecorder.WriteLine("JsFile: " + sourceMapData.sourceMap.file);
72-
sourceMapRecorder.WriteLine("mapUrl: " + ts.tryGetSourceMappingURL(jsFile.text, jsLineMap));
72+
sourceMapRecorder.WriteLine("mapUrl: " + ts.tryGetSourceMappingURL(ts.getLineInfo(jsFile.text, jsLineMap)));
7373
sourceMapRecorder.WriteLine("sourceRoot: " + sourceMapData.sourceMap.sourceRoot);
7474
sourceMapRecorder.WriteLine("sources: " + sourceMapData.sourceMap.sources);
7575
if (sourceMapData.sourceMap.sourcesContent) {

0 commit comments

Comments
 (0)