Merge pull request #15935 from chuckjaz/external-file-source-map
Add support for external file references in source maps
This commit is contained in:
commit
b217c39bb1
|
@ -2249,6 +2249,7 @@ namespace ts {
|
|||
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
|
||||
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
|
||||
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
|
||||
getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
|
||||
}
|
||||
|
||||
function Symbol(this: Symbol, flags: SymbolFlags, name: string) {
|
||||
|
@ -2279,6 +2280,12 @@ namespace ts {
|
|||
this.original = undefined;
|
||||
}
|
||||
|
||||
function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) {
|
||||
this.fileName = fileName;
|
||||
this.text = text;
|
||||
this.skipTrivia = skipTrivia || (pos => pos);
|
||||
}
|
||||
|
||||
export let objectAllocator: ObjectAllocator = {
|
||||
getNodeConstructor: () => <any>Node,
|
||||
getTokenConstructor: () => <any>Node,
|
||||
|
@ -2286,7 +2293,8 @@ namespace ts {
|
|||
getSourceFileConstructor: () => <any>Node,
|
||||
getSymbolConstructor: () => <any>Symbol,
|
||||
getTypeConstructor: () => <any>Type,
|
||||
getSignatureConstructor: () => <any>Signature
|
||||
getSignatureConstructor: () => <any>Signature,
|
||||
getSourceMapSourceConstructor: () => <any>SourceMapSource,
|
||||
};
|
||||
|
||||
export const enum AssertionLevel {
|
||||
|
|
|
@ -2314,15 +2314,24 @@ namespace ts {
|
|||
/**
|
||||
* Sets a custom text range to use when emitting source maps.
|
||||
*/
|
||||
export function setSourceMapRange<T extends Node>(node: T, range: TextRange | undefined) {
|
||||
export function setSourceMapRange<T extends Node>(node: T, range: SourceMapRange | undefined) {
|
||||
getOrCreateEmitNode(node).sourceMapRange = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
|
||||
|
||||
/**
|
||||
* Create an external source map source file reference
|
||||
*/
|
||||
export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource {
|
||||
return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange | undefined {
|
||||
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined {
|
||||
const emitNode = node.emitNode;
|
||||
const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges;
|
||||
return tokenSourceMapRanges && tokenSourceMapRanges[token];
|
||||
|
@ -2331,7 +2340,7 @@ namespace ts {
|
|||
/**
|
||||
* Sets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange | undefined) {
|
||||
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: SourceMapRange | undefined) {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []);
|
||||
tokenSourceMapRanges[token] = range;
|
||||
|
|
|
@ -363,7 +363,7 @@ namespace ts {
|
|||
};
|
||||
}
|
||||
|
||||
export function getLineAndCharacterOfPosition(sourceFile: SourceFile, position: number): LineAndCharacter {
|
||||
export function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter {
|
||||
return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace ts {
|
|||
*
|
||||
* @param sourceFile The source file.
|
||||
*/
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
setSourceFile(sourceFile: SourceMapSource): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping.
|
||||
|
@ -81,7 +81,7 @@ namespace ts {
|
|||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentSource: SourceMapSource;
|
||||
let currentSourceText: string;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
|
||||
|
@ -109,6 +109,13 @@ namespace ts {
|
|||
getSourceMappingURL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Skips trivia such as comments and white-space that can optionally overriden by the source map source
|
||||
*/
|
||||
function skipSourceTrivia(pos: number): number {
|
||||
return currentSource.skipTrivia ? currentSource.skipTrivia(pos) : skipTrivia(currentSourceText, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the SourceMapWriter for a new output file.
|
||||
*
|
||||
|
@ -125,7 +132,7 @@ namespace ts {
|
|||
reset();
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentSource = undefined;
|
||||
currentSourceText = undefined;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
|
@ -192,7 +199,7 @@ namespace ts {
|
|||
return;
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentSource = undefined;
|
||||
sourceMapDir = undefined;
|
||||
sourceMapSourceIndex = undefined;
|
||||
lastRecordedSourceMapSpan = undefined;
|
||||
|
@ -263,7 +270,7 @@ namespace ts {
|
|||
performance.mark("beforeSourcemap");
|
||||
}
|
||||
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSource, pos);
|
||||
|
||||
// Convert the location to be one-based.
|
||||
sourceLinePos.line++;
|
||||
|
@ -320,14 +327,22 @@ namespace ts {
|
|||
if (node) {
|
||||
const emitNode = node.emitNode;
|
||||
const emitFlags = emitNode && emitNode.flags;
|
||||
const { pos, end } = emitNode && emitNode.sourceMapRange || node;
|
||||
const range = emitNode && emitNode.sourceMapRange;
|
||||
const { pos, end } = range || node;
|
||||
let source = range && range.source;
|
||||
const oldSource = currentSource;
|
||||
if (source === oldSource) source = undefined;
|
||||
|
||||
if (source) setSourceFile(source);
|
||||
|
||||
if (node.kind !== SyntaxKind.NotEmittedStatement
|
||||
&& (emitFlags & EmitFlags.NoLeadingSourceMap) === 0
|
||||
&& pos >= 0) {
|
||||
emitPos(skipTrivia(currentSourceText, pos));
|
||||
emitPos(skipSourceTrivia(pos));
|
||||
}
|
||||
|
||||
if (source) setSourceFile(oldSource);
|
||||
|
||||
if (emitFlags & EmitFlags.NoNestedSourceMaps) {
|
||||
disabled = true;
|
||||
emitCallback(hint, node);
|
||||
|
@ -337,11 +352,15 @@ namespace ts {
|
|||
emitCallback(hint, node);
|
||||
}
|
||||
|
||||
if (source) setSourceFile(source);
|
||||
|
||||
if (node.kind !== SyntaxKind.NotEmittedStatement
|
||||
&& (emitFlags & EmitFlags.NoTrailingSourceMap) === 0
|
||||
&& end >= 0) {
|
||||
emitPos(end);
|
||||
}
|
||||
|
||||
if (source) setSourceFile(oldSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,7 +381,7 @@ namespace ts {
|
|||
const emitFlags = emitNode && emitNode.flags;
|
||||
const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token];
|
||||
|
||||
tokenPos = skipTrivia(currentSourceText, range ? range.pos : tokenPos);
|
||||
tokenPos = skipSourceTrivia(range ? range.pos : tokenPos);
|
||||
if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) {
|
||||
emitPos(tokenPos);
|
||||
}
|
||||
|
@ -382,13 +401,13 @@ namespace ts {
|
|||
*
|
||||
* @param sourceFile The source file.
|
||||
*/
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
function setSourceFile(sourceFile: SourceMapSource) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentSourceFile = sourceFile;
|
||||
currentSourceText = currentSourceFile.text;
|
||||
currentSource = sourceFile;
|
||||
currentSourceText = currentSource.text;
|
||||
|
||||
// Add the file to tsFilePaths
|
||||
// If sourceroot option: Use the relative path corresponding to the common directory path
|
||||
|
@ -396,7 +415,7 @@ namespace ts {
|
|||
const sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
|
||||
|
||||
const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
|
||||
currentSourceFile.fileName,
|
||||
currentSource.fileName,
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
|
@ -407,10 +426,10 @@ namespace ts {
|
|||
sourceMapData.sourceMapSources.push(source);
|
||||
|
||||
// The one that can be used from program to get the actual source file
|
||||
sourceMapData.inputSourceFileNames.push(currentSourceFile.fileName);
|
||||
sourceMapData.inputSourceFileNames.push(currentSource.fileName);
|
||||
|
||||
if (compilerOptions.inlineSources) {
|
||||
sourceMapData.sourceMapSourcesContent.push(currentSourceFile.text);
|
||||
sourceMapData.sourceMapSourcesContent.push(currentSource.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4013,6 +4013,17 @@ namespace ts {
|
|||
ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
|
||||
}
|
||||
|
||||
export interface SourceMapRange extends TextRange {
|
||||
source?: SourceMapSource;
|
||||
}
|
||||
|
||||
export interface SourceMapSource {
|
||||
fileName: string;
|
||||
text: string;
|
||||
/* @internal */ lineMap: number[];
|
||||
skipTrivia?: (pos: number) => number;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitNode {
|
||||
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
|
||||
|
@ -4020,8 +4031,8 @@ namespace ts {
|
|||
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
|
||||
trailingComments?: SynthesizedComment[]; // Synthesized trailing comments
|
||||
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
|
||||
sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings
|
||||
tokenSourceMapRanges?: TextRange[]; // The text range to use when emitting source mappings for tokens
|
||||
sourceMapRange?: SourceMapRange; // The text range to use when emitting leading or trailing source mappings
|
||||
tokenSourceMapRanges?: SourceMapRange[]; // The text range to use when emitting source mappings for tokens
|
||||
constantValue?: string | number; // The constant value of an expression
|
||||
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
|
||||
helpers?: EmitHelper[]; // Emit helpers for the node
|
||||
|
|
|
@ -732,6 +732,15 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
class SourceMapSourceObject implements SourceMapSource {
|
||||
lineMap: number[];
|
||||
constructor (public fileName: string, public text: string, public skipTrivia?: (pos: number) => number) {}
|
||||
|
||||
public getLineAndCharacterOfPosition(pos: number): LineAndCharacter {
|
||||
return ts.getLineAndCharacterOfPosition(this, pos);
|
||||
}
|
||||
}
|
||||
|
||||
function getServicesObjectAllocator(): ObjectAllocator {
|
||||
return {
|
||||
getNodeConstructor: () => NodeObject,
|
||||
|
@ -742,6 +751,7 @@ namespace ts {
|
|||
getSymbolConstructor: () => SymbolObject,
|
||||
getTypeConstructor: () => TypeObject,
|
||||
getSignatureConstructor: () => SignatureObject,
|
||||
getSourceMapSourceConstructor: () => SourceMapSourceObject,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,10 @@ namespace ts {
|
|||
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
|
||||
}
|
||||
|
||||
export interface SourceMapSource {
|
||||
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an immutable snapshot of a script at a specified time.Once acquired, the
|
||||
* snapshot is observably immutable. i.e. the same calls with the same parameters will return
|
||||
|
|
Loading…
Reference in a new issue