mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 01:04:49 -05:00
Fix source maps for arrow functions, comments in sourcemap writer.
This commit is contained in:
@@ -155,7 +155,8 @@ const _super = (function (geti, seti) {
|
||||
const {
|
||||
emitStart,
|
||||
emitEnd,
|
||||
emitPos
|
||||
emitTokenStart,
|
||||
emitTokenEnd
|
||||
} = sourceMap;
|
||||
|
||||
const comments = createCommentWriter(host, writer, sourceMap);
|
||||
@@ -172,8 +173,9 @@ const _super = (function (geti, seti) {
|
||||
let context: TransformationContext;
|
||||
let getNodeEmitFlags: (node: Node) => NodeEmitFlags;
|
||||
let setNodeEmitFlags: (node: Node, flags: NodeEmitFlags) => void;
|
||||
let getCommentRange: (node: Node) => TextRange;
|
||||
let getSourceMapRange: (node: Node) => TextRange;
|
||||
let getTokenSourceMapRange: (node: Node, token: SyntaxKind) => TextRange;
|
||||
let getCommentRange: (node: Node) => TextRange;
|
||||
let isSubstitutionEnabled: (node: Node) => boolean;
|
||||
let isEmitNotificationEnabled: (node: Node) => boolean;
|
||||
let onSubstituteNode: (node: Node, isExpression: boolean) => Node;
|
||||
@@ -234,8 +236,9 @@ const _super = (function (geti, seti) {
|
||||
|
||||
getNodeEmitFlags = undefined;
|
||||
setNodeEmitFlags = undefined;
|
||||
getCommentRange = undefined;
|
||||
getSourceMapRange = undefined;
|
||||
getTokenSourceMapRange = undefined;
|
||||
getCommentRange = undefined;
|
||||
isSubstitutionEnabled = undefined;
|
||||
isEmitNotificationEnabled = undefined;
|
||||
onSubstituteNode = undefined;
|
||||
@@ -255,8 +258,9 @@ const _super = (function (geti, seti) {
|
||||
context = _context;
|
||||
getNodeEmitFlags = context.getNodeEmitFlags;
|
||||
setNodeEmitFlags = context.setNodeEmitFlags;
|
||||
getCommentRange = context.getCommentRange;
|
||||
getSourceMapRange = context.getSourceMapRange;
|
||||
getTokenSourceMapRange = context.getTokenSourceMapRange;
|
||||
getCommentRange = context.getCommentRange;
|
||||
isSubstitutionEnabled = context.isSubstitutionEnabled;
|
||||
isEmitNotificationEnabled = context.isEmitNotificationEnabled;
|
||||
onSubstituteNode = context.onSubstituteNode;
|
||||
@@ -343,9 +347,9 @@ const _super = (function (geti, seti) {
|
||||
const leadingComments = getLeadingComments(node, shouldSkipLeadingCommentsForNode, getCommentRange);
|
||||
const trailingComments = getTrailingComments(node, shouldSkipTrailingCommentsForNode, getCommentRange);
|
||||
emitLeadingComments(node, leadingComments, getCommentRange);
|
||||
emitStart(node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitStart(/*range*/ node, /*contextNode*/ node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitWorker(node);
|
||||
emitEnd(node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitEnd(/*range*/ node, /*contextNode*/ node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitTrailingComments(node, trailingComments);
|
||||
}
|
||||
}
|
||||
@@ -1646,7 +1650,7 @@ const _super = (function (geti, seti) {
|
||||
|
||||
emitTrailingDetachedComments(body.statements, body, shouldSkipTrailingCommentsForNode);
|
||||
decreaseIndent();
|
||||
writeToken(SyntaxKind.CloseBraceToken, body.statements.end);
|
||||
writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body);
|
||||
}
|
||||
|
||||
function emitClassDeclaration(node: ClassDeclaration) {
|
||||
@@ -2410,12 +2414,10 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
}
|
||||
|
||||
function writeToken(token: SyntaxKind, tokenStartPos: number, contextNode?: Node) {
|
||||
tokenStartPos = skipTrivia(currentText, tokenStartPos);
|
||||
emitPos(tokenStartPos, contextNode, shouldSkipLeadingSourceMapForToken);
|
||||
function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) {
|
||||
const tokenStartPos = emitTokenStart(token, pos, contextNode, shouldSkipLeadingSourceMapForToken, getTokenSourceMapRange);
|
||||
const tokenEndPos = writeTokenText(token, tokenStartPos);
|
||||
emitPos(tokenEndPos, contextNode, shouldSkipTrailingSourceMapForToken);
|
||||
return tokenEndPos;
|
||||
return emitTokenEnd(token, tokenEndPos, contextNode, shouldSkipTrailingSourceMapForToken, getTokenSourceMapRange);
|
||||
}
|
||||
|
||||
function shouldSkipLeadingSourceMapForToken(contextNode: Node) {
|
||||
@@ -2434,9 +2436,9 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function writeTokenNode(node: Node) {
|
||||
if (node) {
|
||||
emitStart(node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitStart(/*range*/ node, /*contextNode*/ node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
writeTokenText(node.kind);
|
||||
emitEnd(node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitEnd(/*range*/ node, /*contextNode*/ node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,25 +3,197 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export interface SourceMapWriter {
|
||||
/**
|
||||
* Initialize the SourceMapWriter for a new output file.
|
||||
*
|
||||
* @param filePath The path to the generated output file.
|
||||
* @param sourceMapFilePath The path to the output source map file.
|
||||
* @param sourceFiles The input source files for the program.
|
||||
* @param isBundledEmit A value indicating whether the generated output file is a bundle.
|
||||
*/
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
|
||||
|
||||
/**
|
||||
* Reset the SourceMapWriter to an empty state.
|
||||
*/
|
||||
reset(): void;
|
||||
|
||||
/**
|
||||
* Gets test data for source maps.
|
||||
*/
|
||||
getSourceMapData(): SourceMapData;
|
||||
|
||||
/**
|
||||
* Set the current source file.
|
||||
*
|
||||
* @param sourceFile The source file.
|
||||
*/
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitPos(pos: number, contextNode: Node, shouldIgnorePosCallback: (node: Node) => boolean): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping.
|
||||
*
|
||||
* If the position is synthetic (undefined or a negative value), no mapping will be
|
||||
* created.
|
||||
*
|
||||
* @param pos The position.
|
||||
*/
|
||||
emitPos(pos: number): void;
|
||||
emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
*
|
||||
* If the range's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
*/
|
||||
emitStart(range: TextRange): void;
|
||||
emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
*
|
||||
* If the node's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param shouldIgnoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this node.
|
||||
* @param shouldIgnoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getCustomSourceMapRangeForNodeCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
emitStart(range: TextRange, contextNode: Node, shouldIgnoreNodeCallback: (node: Node) => boolean, shouldIgnoreChildrenCallback: (node: Node) => boolean, getCustomSourceMapRangeForNodeCallback: (node: Node) => TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the range's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
*/
|
||||
emitEnd(range: TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the node's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param shouldIgnoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this node.
|
||||
* @param shouldIgnoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getCustomSourceMapRangeForNodeCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
emitEnd(range: TextRange, contextNode: Node, shouldIgnoreNodeCallback: (node: Node) => boolean, shouldIgnoreChildrenCallback: (node: Node) => boolean, getCustomSourceMapRangeForNodeCallback: (node: Node) => TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
*/
|
||||
emitTokenStart(token: SyntaxKind, tokenStartPos: number): number;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param shouldIgnoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this token.
|
||||
* @param getCustomSourceMapRangeForTokenCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
*/
|
||||
emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode: Node, shouldIgnoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getCustomSourceMapRangeForTokenCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
emitTokenEnd(token: SyntaxKind, tokenEndPos: number): number;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param shouldIgnoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this token.
|
||||
* @param getCustomSourceMapRangeForTokenCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode: Node, shouldIgnoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getCustomSourceMapRangeForTokenCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
|
||||
/*@deprecated*/ changeEmitSourcePos(): void;
|
||||
/*@deprecated*/ stopOverridingSpan(): void;
|
||||
|
||||
/**
|
||||
* Gets the text for the source map.
|
||||
*/
|
||||
getText(): string;
|
||||
|
||||
/**
|
||||
* Gets the SourceMappingURL for the source map.
|
||||
*/
|
||||
getSourceMappingURL(): string;
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
|
||||
reset(): void;
|
||||
enable(): void;
|
||||
disable(): void;
|
||||
}
|
||||
|
||||
let nullSourceMapWriter: SourceMapWriter;
|
||||
|
||||
export function getNullSourceMapWriter(): SourceMapWriter {
|
||||
if (nullSourceMapWriter === undefined) {
|
||||
nullSourceMapWriter = {
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
|
||||
reset(): void { },
|
||||
getSourceMapData(): SourceMapData { return undefined; },
|
||||
setSourceFile(sourceFile: SourceFile): void { },
|
||||
emitPos(pos: number): void { },
|
||||
emitStart(range: TextRange, contextNode?: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void { },
|
||||
emitEnd(range: TextRange, contextNode?: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void { },
|
||||
emitTokenStart(token: SyntaxKind, pos: number, contextNode?: Node, shouldIgnoreTokenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForTokenCallback?: (node: Node, token: SyntaxKind, pos: number) => TextRange): number { return -1; },
|
||||
emitTokenEnd(token: SyntaxKind, end: number, contextNode?: Node, shouldIgnoreTokenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForTokenCallback?: (node: Node, token: SyntaxKind, pos: number) => TextRange): number { return -1; },
|
||||
changeEmitSourcePos(): void { },
|
||||
stopOverridingSpan(): void { },
|
||||
getText(): string { return undefined; },
|
||||
getSourceMappingURL(): string { return undefined; }
|
||||
};
|
||||
}
|
||||
|
||||
return nullSourceMapWriter;
|
||||
}
|
||||
|
||||
// Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans
|
||||
const defaultLastEncodedSourceMapSpan: SourceMapSpan = {
|
||||
emittedLine: 1,
|
||||
@@ -31,31 +203,10 @@ namespace ts {
|
||||
sourceIndex: 0
|
||||
};
|
||||
|
||||
export function getNullSourceMapWriter(): SourceMapWriter {
|
||||
if (nullSourceMapWriter === undefined) {
|
||||
nullSourceMapWriter = {
|
||||
getSourceMapData(): SourceMapData { return undefined; },
|
||||
setSourceFile(sourceFile: SourceFile): void { },
|
||||
emitStart(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void { },
|
||||
emitEnd(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void { },
|
||||
emitPos(pos: number): void { },
|
||||
changeEmitSourcePos(): void { },
|
||||
stopOverridingSpan(): void { },
|
||||
getText(): string { return undefined; },
|
||||
getSourceMappingURL(): string { return undefined; },
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
|
||||
reset(): void { },
|
||||
enable(): void { },
|
||||
disable(): void { }
|
||||
};
|
||||
}
|
||||
|
||||
return nullSourceMapWriter;
|
||||
}
|
||||
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentSourceText: string;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
let stopOverridingSpan = false;
|
||||
let modifyLastSourcePos = false;
|
||||
@@ -79,27 +230,36 @@ namespace ts {
|
||||
let disableDepth: number;
|
||||
|
||||
return {
|
||||
initialize,
|
||||
reset,
|
||||
getSourceMapData: () => sourceMapData,
|
||||
setSourceFile,
|
||||
emitPos,
|
||||
emitStart,
|
||||
emitEnd,
|
||||
emitTokenStart,
|
||||
emitTokenEnd,
|
||||
changeEmitSourcePos,
|
||||
stopOverridingSpan: () => stopOverridingSpan = true,
|
||||
getText,
|
||||
getSourceMappingURL,
|
||||
initialize,
|
||||
reset,
|
||||
enable,
|
||||
disable,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the SourceMapWriter for a new output file.
|
||||
*
|
||||
* @param filePath The path to the generated output file.
|
||||
* @param sourceMapFilePath The path to the output source map file.
|
||||
* @param sourceFiles The input source files for the program.
|
||||
* @param isBundledEmit A value indicating whether the generated output file is a bundle.
|
||||
*/
|
||||
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
if (sourceMapData) {
|
||||
reset();
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentSourceText = undefined;
|
||||
disableDepth = 0;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
@@ -159,6 +319,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the SourceMapWriter to an empty state.
|
||||
*/
|
||||
function reset() {
|
||||
currentSourceFile = undefined;
|
||||
sourceMapDir = undefined;
|
||||
@@ -272,15 +435,19 @@ namespace ts {
|
||||
sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
|
||||
}
|
||||
|
||||
function emitPos(pos: number, contextNode?: Node, shouldIgnorePosCallback?: (node: Node) => boolean) {
|
||||
/**
|
||||
* Emits a mapping.
|
||||
*
|
||||
* If the position is synthetic (undefined or a negative value), no mapping will be
|
||||
* created.
|
||||
*
|
||||
* @param pos The position.
|
||||
*/
|
||||
function emitPos(pos: number) {
|
||||
if (positionIsSynthesized(pos) || disableDepth > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldIgnorePosCallback && shouldIgnorePosCallback(contextNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
|
||||
// Convert the location to be one-based.
|
||||
@@ -322,54 +489,205 @@ namespace ts {
|
||||
updateLastEncodedAndRecordedSpans();
|
||||
}
|
||||
|
||||
function getStartPos(range: TextRange) {
|
||||
function getStartPosPastDecorators(range: TextRange) {
|
||||
const rangeHasDecorators = !!(range as Node).decorators;
|
||||
return range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1;
|
||||
return skipTrivia(currentSourceText, rangeHasDecorators ? (range as Node).decorators.end : range.pos);
|
||||
}
|
||||
|
||||
function getStartPos(range: TextRange) {
|
||||
return skipTrivia(currentSourceText, range.pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
*
|
||||
* If the range's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.0
|
||||
*/
|
||||
function emitStart(range: TextRange): void;
|
||||
function emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
function emitStart(nodeOrRange: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange) {
|
||||
let range = <TextRange>nodeOrRange;
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>nodeOrRange))) {
|
||||
if (getCustomSourceMapRangeForNode) {
|
||||
range = getCustomSourceMapRangeForNode(<Node>nodeOrRange) || range;
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
*
|
||||
* If the node's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param shouldIgnoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this node.
|
||||
* @param shouldIgnoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getCustomSourceMapRangeForNodeCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
function emitStart(range: TextRange, contextNode: Node, shouldIgnoreNodeCallback: (node: Node) => boolean, shouldIgnoreChildrenCallback: (node: Node) => boolean, getCustomSourceMapRangeForNode: (node: Node) => TextRange): void;
|
||||
function emitStart(range: TextRange, contextNode?: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange) {
|
||||
if (contextNode) {
|
||||
if (!shouldIgnoreNodeCallback(contextNode)) {
|
||||
range = getCustomSourceMapRangeForNode(contextNode) || range;
|
||||
emitPos(getStartPosPastDecorators(range));
|
||||
}
|
||||
|
||||
emitPos(getStartPos(range));
|
||||
if (shouldIgnoreChildrenCallback(contextNode)) {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>nodeOrRange)) {
|
||||
disable();
|
||||
else {
|
||||
emitPos(getStartPosPastDecorators(range));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the range's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
*/
|
||||
function emitEnd(range: TextRange): void;
|
||||
function emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange): void;
|
||||
function emitEnd(nodeOrRange: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange) {
|
||||
let range = <TextRange>nodeOrRange;
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>nodeOrRange)) {
|
||||
enable();
|
||||
}
|
||||
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>nodeOrRange))) {
|
||||
if (getCustomSourceMapRangeForNode) {
|
||||
range = getCustomSourceMapRangeForNode(<Node>nodeOrRange) || range;
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the node's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param shouldIgnoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this node.
|
||||
* @param shouldIgnoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getCustomSourceMapRangeForNodeCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
function emitEnd(range: TextRange, contextNode: Node, shouldIgnoreNodeCallback: (node: Node) => boolean, shouldIgnoreChildrenCallback: (node: Node) => boolean, getCustomSourceMapRangeForNode: (node: Node) => TextRange): void;
|
||||
function emitEnd(range: TextRange, contextNode?: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean, getCustomSourceMapRangeForNode?: (node: Node) => TextRange) {
|
||||
if (contextNode) {
|
||||
if (shouldIgnoreChildrenCallback(contextNode)) {
|
||||
enable();
|
||||
}
|
||||
|
||||
if (!shouldIgnoreNodeCallback(contextNode)) {
|
||||
range = getCustomSourceMapRangeForNode(contextNode) || range;
|
||||
emitPos(range.end);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitPos(range.end);
|
||||
}
|
||||
|
||||
stopOverridingSpan = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
*/
|
||||
function emitTokenStart(token: SyntaxKind, tokenStartPos: number): number;
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param shouldIgnoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this token.
|
||||
* @param getCustomSourceMapRangeForTokenCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
*/
|
||||
function emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode: Node, shouldIgnoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getCustomSourceMapRangeForTokenCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
function emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode?: Node, shouldIgnoreTokenCallback?: (node: Node, token: SyntaxKind) => boolean, getCustomSourceMapRangeForTokenCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
if (contextNode) {
|
||||
if (shouldIgnoreTokenCallback(contextNode, token)) {
|
||||
return skipTrivia(currentSourceText, tokenStartPos);
|
||||
}
|
||||
|
||||
const range = getCustomSourceMapRangeForTokenCallback(contextNode, token);
|
||||
if (range) {
|
||||
tokenStartPos = range.pos;
|
||||
}
|
||||
}
|
||||
|
||||
tokenStartPos = skipTrivia(currentSourceText, tokenStartPos);
|
||||
emitPos(tokenStartPos);
|
||||
return tokenStartPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
function emitTokenEnd(token: SyntaxKind, tokenEndPos: number): number;
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param shouldIgnoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this token.
|
||||
* @param getCustomSourceMapRangeForTokenCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
function emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode: Node, shouldIgnoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getCustomSourceMapRangeForTokenCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
function emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode?: Node, shouldIgnoreTokenCallback?: (node: Node, token: SyntaxKind) => boolean, getCustomSourceMapRangeForTokenCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
if (contextNode) {
|
||||
if (shouldIgnoreTokenCallback(contextNode, token)) {
|
||||
return tokenEndPos;
|
||||
}
|
||||
|
||||
const range = getCustomSourceMapRangeForTokenCallback(contextNode, token);
|
||||
if (range) {
|
||||
tokenEndPos = range.end;
|
||||
}
|
||||
}
|
||||
|
||||
emitPos(tokenEndPos);
|
||||
return tokenEndPos;
|
||||
}
|
||||
|
||||
|
||||
// @deprecated
|
||||
function changeEmitSourcePos() {
|
||||
Debug.assert(!modifyLastSourcePos);
|
||||
modifyLastSourcePos = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current source file.
|
||||
*
|
||||
* @param sourceFile The source file.
|
||||
*/
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
currentSourceFile = sourceFile;
|
||||
currentSourceText = sourceFile.text;
|
||||
|
||||
// Add the file to tsFilePaths
|
||||
// If sourceroot option: Use the relative path corresponding to the common directory path
|
||||
@@ -396,6 +714,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text for the source map.
|
||||
*/
|
||||
function getText() {
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
@@ -410,6 +731,9 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SourceMappingURL for the source map.
|
||||
*/
|
||||
function getSourceMappingURL() {
|
||||
if (compilerOptions.inlineSourceMap) {
|
||||
// Encode the sourceMap into the sourceMap url
|
||||
|
||||
@@ -74,6 +74,8 @@ namespace ts {
|
||||
setNodeEmitFlags,
|
||||
getSourceMapRange,
|
||||
setSourceMapRange,
|
||||
getTokenSourceMapRange,
|
||||
setTokenSourceMapRange,
|
||||
getCommentRange,
|
||||
setCommentRange,
|
||||
hoistVariableDeclaration,
|
||||
@@ -237,6 +239,47 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
function getTokenSourceMapRanges(node: Node) {
|
||||
let current = node;
|
||||
while (current) {
|
||||
const options = getEmitOptions(current);
|
||||
if (options && options.tokenSourceMapRange) {
|
||||
return options.tokenSourceMapRange;
|
||||
}
|
||||
|
||||
current = current.original;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
function getTokenSourceMapRange(node: Node, token: SyntaxKind) {
|
||||
const ranges = getTokenSourceMapRanges(node);
|
||||
if (ranges) {
|
||||
return ranges[token];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange) {
|
||||
const options = getEmitOptions(node, /*create*/ true);
|
||||
if (!options.tokenSourceMapRange) {
|
||||
const existingRanges = getTokenSourceMapRanges(node);
|
||||
const ranges = existingRanges ? clone(existingRanges) : { };
|
||||
options.tokenSourceMapRange = ranges;
|
||||
}
|
||||
|
||||
options.tokenSourceMapRange[token] = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom text range to use when emitting comments.
|
||||
*/
|
||||
|
||||
@@ -149,6 +149,7 @@ namespace ts {
|
||||
setCommentRange,
|
||||
getSourceMapRange,
|
||||
setSourceMapRange,
|
||||
setTokenSourceMapRange,
|
||||
} = context;
|
||||
|
||||
const resolver = context.getEmitResolver();
|
||||
@@ -1313,6 +1314,7 @@ namespace ts {
|
||||
let multiLine = false; // indicates whether the block *must* be emitted as multiple lines
|
||||
let singleLine = false; // indicates whether the block *may* be emitted as a single line
|
||||
let statementsLocation: TextRange;
|
||||
let closeBraceLocation: TextRange;
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const body = node.body;
|
||||
@@ -1363,11 +1365,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
const expression = visitNode(body, visitor, isExpression);
|
||||
if (expression) {
|
||||
const returnStatement = createReturn(expression, /*location*/ statementsLocation);
|
||||
setNodeEmitFlags(returnStatement, NodeEmitFlags.NoTokenSourceMaps);
|
||||
statements.push(returnStatement);
|
||||
}
|
||||
const returnStatement = createReturn(expression);
|
||||
setSourceMapRange(returnStatement, body);
|
||||
setNodeEmitFlags(returnStatement, NodeEmitFlags.NoTokenSourceMaps | NodeEmitFlags.NoTrailingSourceMap);
|
||||
statements.push(returnStatement);
|
||||
|
||||
// To align with the source map emit for the old emitter, we set a custom
|
||||
// source map location for the close brace.
|
||||
closeBraceLocation = body;
|
||||
}
|
||||
|
||||
const lexicalEnvironment = endLexicalEnvironment();
|
||||
@@ -1383,6 +1388,10 @@ namespace ts {
|
||||
setNodeEmitFlags(block, NodeEmitFlags.SingleLine);
|
||||
}
|
||||
|
||||
if (closeBraceLocation) {
|
||||
setTokenSourceMapRange(block, SyntaxKind.CloseBraceToken, closeBraceLocation);
|
||||
}
|
||||
|
||||
setOriginalNode(block, node.body);
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -2963,6 +2963,10 @@ namespace ts {
|
||||
* Specifies a custom range to use when emitting source maps.
|
||||
*/
|
||||
sourceMapRange?: TextRange;
|
||||
/**
|
||||
* Specifies a custom range to use when emitting tokens of a node.
|
||||
*/
|
||||
tokenSourceMapRange?: Map<TextRange>;
|
||||
/**
|
||||
* Specifies a custom range to use when emitting comments.
|
||||
*/
|
||||
@@ -3009,6 +3013,16 @@ namespace ts {
|
||||
*/
|
||||
setSourceMapRange<T extends Node>(node: T, range: TextRange): T;
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange;
|
||||
|
||||
/**
|
||||
* Sets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange): T;
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for comments for the node.
|
||||
*/
|
||||
|
||||
@@ -3058,6 +3058,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases (or decreases) a position by the provided amount.
|
||||
*
|
||||
* @param pos The position.
|
||||
* @param value The delta.
|
||||
*/
|
||||
export function movePos(pos: number, value: number) {
|
||||
return positionIsSynthesized(pos) ? -1 : pos + value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TextRange from the provided pos and end.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user