mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-18 12:21:37 -06:00
Performance improvements in comment emit.
This commit is contained in:
parent
a1518d324f
commit
0dc261d4a2
@ -5,18 +5,9 @@ namespace ts {
|
||||
export interface CommentWriter {
|
||||
reset(): void;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
getLeadingComments(range: TextRange): CommentRange[];
|
||||
getLeadingComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean, getTextRangeCallback: (contextNode: Node) => TextRange): CommentRange[];
|
||||
getTrailingComments(range: TextRange): CommentRange[];
|
||||
getTrailingComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean, getTextRangeCallback: (contextNode: Node) => TextRange): CommentRange[];
|
||||
getTrailingCommentsOfPosition(pos: number): CommentRange[];
|
||||
emitLeadingComments(range: TextRange, comments: CommentRange[]): void;
|
||||
emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode: Node, getTextRangeCallback: (contextNode: Node) => TextRange): void;
|
||||
emitTrailingComments(range: TextRange, comments: CommentRange[]): void;
|
||||
emitLeadingDetachedComments(range: TextRange): void;
|
||||
emitLeadingDetachedComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean): void;
|
||||
emitTrailingDetachedComments(range: TextRange): void;
|
||||
emitTrailingDetachedComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean): void;
|
||||
emitNodeWithComments(node: Node, emitCallback: (node: Node) => void): void;
|
||||
emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
|
||||
emitTrailingCommentsOfPosition(pos: number): void;
|
||||
}
|
||||
|
||||
export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter {
|
||||
@ -24,250 +15,177 @@ namespace ts {
|
||||
const newLine = host.getNewLine();
|
||||
const { emitPos } = sourceMap;
|
||||
|
||||
let containerPos = -1;
|
||||
let containerEnd = -1;
|
||||
let declarationListContainerEnd = -1;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentText: string;
|
||||
let currentLineMap: number[];
|
||||
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[];
|
||||
|
||||
// This maps start->end for a comment range. See `hasConsumedCommentRange` and
|
||||
// `consumeCommentRange` for usage.
|
||||
// Tracks comment ranges that have already been consumed.
|
||||
let consumedCommentRanges: Map<boolean>;
|
||||
let leadingCommentRangePositions: Map<boolean>;
|
||||
let trailingCommentRangePositions: Map<boolean>;
|
||||
|
||||
const commentWriter = compilerOptions.removeComments
|
||||
? createCommentRemovingWriter()
|
||||
: createCommentPreservingWriter();
|
||||
return {
|
||||
reset,
|
||||
setSourceFile,
|
||||
emitNodeWithComments,
|
||||
emitBodyWithDetachedComments,
|
||||
emitTrailingCommentsOfPosition,
|
||||
};
|
||||
|
||||
return compilerOptions.extendedDiagnostics
|
||||
? createCommentWriterWithExtendedDiagnostics(commentWriter)
|
||||
: commentWriter;
|
||||
|
||||
function createCommentRemovingWriter(): CommentWriter {
|
||||
return {
|
||||
reset,
|
||||
setSourceFile,
|
||||
getLeadingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange): CommentRange[] { return undefined; },
|
||||
getTrailingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange): CommentRange[] { return undefined; },
|
||||
getTrailingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
|
||||
emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode?: Node, getTextRangeCallback?: (contextNode: Node) => TextRange): void { },
|
||||
emitTrailingComments(range: TextRange, comments: CommentRange[]): void { },
|
||||
emitLeadingDetachedComments,
|
||||
emitTrailingDetachedComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean): void {}
|
||||
};
|
||||
|
||||
function emitLeadingDetachedComments(node: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean): void {
|
||||
if (ignoreNodeCallback && ignoreNodeCallback(contextNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitDetachedCommentsAndUpdateCommentsInfo(node, /*removeComments*/ true);
|
||||
function emitNodeWithComments(node: Node, emitCallback: (node: Node) => void) {
|
||||
if (compilerOptions.removeComments) {
|
||||
emitCallback(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function createCommentPreservingWriter(): CommentWriter {
|
||||
const noComments: CommentRange[] = [];
|
||||
return {
|
||||
reset,
|
||||
setSourceFile,
|
||||
getLeadingComments,
|
||||
getTrailingComments,
|
||||
getTrailingCommentsOfPosition,
|
||||
emitLeadingComments,
|
||||
emitTrailingComments,
|
||||
emitLeadingDetachedComments,
|
||||
emitTrailingDetachedComments
|
||||
};
|
||||
if (node) {
|
||||
const { pos, end } = node.commentRange || node;
|
||||
if ((pos < 0 && end < 0) || (pos === end)) {
|
||||
// Both pos and end are synthesized, so just emit the node without comments.
|
||||
emitCallback(node);
|
||||
}
|
||||
else {
|
||||
const emitFlags = node.emitFlags;
|
||||
const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement;
|
||||
const skipLeadingComments = pos < 0 || (emitFlags & NodeEmitFlags.NoLeadingComments) !== 0;
|
||||
const skipTrailingComments = end < 0 || (emitFlags & NodeEmitFlags.NoTrailingComments) !== 0;
|
||||
|
||||
function getLeadingComments(range: TextRange): CommentRange[];
|
||||
function getLeadingComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean, getTextRangeCallback: (contextNode: Node) => TextRange): CommentRange[];
|
||||
function getLeadingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange) {
|
||||
let comments: CommentRange[] = [];
|
||||
let ignored = false;
|
||||
if (contextNode) {
|
||||
range = getTextRangeCallback(contextNode) || range;
|
||||
if (ignoreNodeCallback(contextNode)) {
|
||||
ignored = true;
|
||||
// If the node will not be emitted in JS, remove all the comments (normal,
|
||||
// pinned and `///`) associated with the node, unless it is a triple slash
|
||||
// comment at the top of the file.
|
||||
//
|
||||
// For Example:
|
||||
// /// <reference-path ...>
|
||||
// declare var x;
|
||||
// /// <reference-path ...>
|
||||
// interface F {}
|
||||
//
|
||||
// The first `///` will NOT be removed while the second one will be removed
|
||||
// even though both nodes will not be emitted.
|
||||
if (range.pos === 0) {
|
||||
comments = filter(getLeadingCommentsOfPosition(0), isTripleSlashComment);
|
||||
// Emit leading comments if the position is not synthesized and the node
|
||||
// has not opted out from emitting leading comments.
|
||||
if (!skipLeadingComments) {
|
||||
emitLeadingComments(pos, isEmittedNode);
|
||||
}
|
||||
|
||||
// Save current container state on the stack.
|
||||
const savedContainerPos = containerPos;
|
||||
const savedContainerEnd = containerEnd;
|
||||
const savedDeclarationListContainerEnd = declarationListContainerEnd;
|
||||
|
||||
if (!skipLeadingComments) {
|
||||
containerPos = pos;
|
||||
}
|
||||
|
||||
if (!skipTrailingComments) {
|
||||
containerEnd = end;
|
||||
|
||||
// To avoid invalid comment emit in a down-level binding pattern, we
|
||||
// keep track of the last declaration list container's end
|
||||
if (node.kind === SyntaxKind.VariableDeclarationList) {
|
||||
declarationListContainerEnd = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignored) {
|
||||
comments = getLeadingCommentsOfPosition(range.pos);
|
||||
}
|
||||
emitCallback(node);
|
||||
|
||||
return comments;
|
||||
}
|
||||
// Restore previous container state.
|
||||
containerPos = savedContainerPos;
|
||||
containerEnd = savedContainerEnd;
|
||||
declarationListContainerEnd = savedDeclarationListContainerEnd;
|
||||
|
||||
/**
|
||||
* Determine if the given comment is a triple-slash
|
||||
**/
|
||||
function isTripleSlashComment(comment: CommentRange) {
|
||||
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
|
||||
// so that we don't end up computing comment string and doing match for all // comments
|
||||
if (currentText.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
|
||||
comment.pos + 2 < comment.end &&
|
||||
currentText.charCodeAt(comment.pos + 2) === CharacterCodes.slash) {
|
||||
const textSubStr = currentText.substring(comment.pos, comment.end);
|
||||
return fullTripleSlashReferencePathRegEx.test(textSubStr)
|
||||
|| fullTripleSlashAMDReferencePathRegEx.test(textSubStr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getTrailingComments(range: TextRange): CommentRange[];
|
||||
function getTrailingComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (contextNode: Node) => boolean, getTextRangeCallback: (contextNode: Node) => TextRange): CommentRange[];
|
||||
function getTrailingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange) {
|
||||
let ignored = false;
|
||||
if (contextNode) {
|
||||
if (ignoreNodeCallback(contextNode)) {
|
||||
ignored = true;
|
||||
}
|
||||
else {
|
||||
range = getTextRangeCallback(contextNode) || range;
|
||||
// Emit trailing comments if the position is not synthesized and the node
|
||||
// has not opted out from emitting leading comments and is an emitted node.
|
||||
if (!skipTrailingComments && isEmittedNode) {
|
||||
emitTrailingComments(end);
|
||||
}
|
||||
}
|
||||
|
||||
let comments: CommentRange[];
|
||||
if (!ignored) {
|
||||
comments = getTrailingCommentsOfPosition(range.end);
|
||||
}
|
||||
return comments;
|
||||
}
|
||||
|
||||
function getLeadingCommentsOfPosition(pos: number) {
|
||||
if (positionIsSynthesized(pos) || leadingCommentRangePositions[pos]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
leadingCommentRangePositions[pos] = true;
|
||||
const comments = hasDetachedComments(pos)
|
||||
? getLeadingCommentsWithoutDetachedComments()
|
||||
: getLeadingCommentRanges(currentText, pos, consumedCommentRanges);
|
||||
return comments;
|
||||
}
|
||||
|
||||
function getTrailingCommentsOfPosition(pos: number) {
|
||||
if (positionIsSynthesized(pos) || trailingCommentRangePositions[pos]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
trailingCommentRangePositions[pos] = true;
|
||||
const comments = getTrailingCommentRanges(currentText, pos, consumedCommentRanges);
|
||||
return comments;
|
||||
}
|
||||
|
||||
function emitLeadingComments(range: TextRange, comments: CommentRange[]): void;
|
||||
function emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode: Node, getTextRangeCallback: (contextNode: Node) => TextRange): void;
|
||||
function emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode?: Node, getTextRangeCallback?: (contextNode: Node) => TextRange) {
|
||||
if (comments && comments.length > 0) {
|
||||
if (contextNode) {
|
||||
range = getTextRangeCallback(contextNode) || range;
|
||||
}
|
||||
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, range, comments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrailingComments(range: TextRange, comments: CommentRange[]) {
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitLeadingDetachedComments(range: TextRange): void;
|
||||
function emitLeadingDetachedComments(range: TextRange, contextNode: Node, ignoreNodeCallback: (node: Node) => boolean): void;
|
||||
function emitLeadingDetachedComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean): void {
|
||||
if (contextNode && ignoreNodeCallback(contextNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitDetachedCommentsAndUpdateCommentsInfo(range, /*removeComments*/ false);
|
||||
}
|
||||
|
||||
function emitTrailingDetachedComments(range: TextRange): void;
|
||||
function emitTrailingDetachedComments(range: TextRange, contextNode: Node, ignoreNodeCallback?: (node: Node) => boolean): void;
|
||||
function emitTrailingDetachedComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean): void {
|
||||
if (contextNode && ignoreNodeCallback(contextNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
range = collapseRangeToEnd(range);
|
||||
emitLeadingComments(range, getLeadingComments(range));
|
||||
}
|
||||
}
|
||||
|
||||
function createCommentWriterWithExtendedDiagnostics(writer: CommentWriter): CommentWriter {
|
||||
const {
|
||||
reset,
|
||||
setSourceFile,
|
||||
getLeadingComments,
|
||||
getTrailingComments,
|
||||
getTrailingCommentsOfPosition,
|
||||
emitLeadingComments,
|
||||
emitTrailingComments,
|
||||
emitLeadingDetachedComments,
|
||||
emitTrailingDetachedComments
|
||||
} = writer;
|
||||
function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) {
|
||||
const { pos, end } = detachedRange;
|
||||
const emitFlags = node.emitFlags;
|
||||
const skipLeadingComments = pos < 0 || (emitFlags & NodeEmitFlags.NoLeadingComments) !== 0;
|
||||
const skipTrailingComments = end < 0 || (emitFlags & NodeEmitFlags.NoTrailingComments) !== 0 || compilerOptions.removeComments;
|
||||
|
||||
return {
|
||||
reset,
|
||||
setSourceFile,
|
||||
getLeadingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange): CommentRange[] {
|
||||
performance.mark("commentStart");
|
||||
const comments = getLeadingComments(range, contextNode, ignoreNodeCallback, getTextRangeCallback);
|
||||
performance.measure("commentTime", "commentStart");
|
||||
return comments;
|
||||
},
|
||||
getTrailingComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean, getTextRangeCallback?: (contextNode: Node) => TextRange): CommentRange[] {
|
||||
performance.mark("commentStart");
|
||||
const comments = getTrailingComments(range, contextNode, ignoreNodeCallback, getTextRangeCallback);
|
||||
performance.measure("commentTime", "commentStart");
|
||||
return comments;
|
||||
},
|
||||
getTrailingCommentsOfPosition(pos: number): CommentRange[] {
|
||||
performance.mark("commentStart");
|
||||
const comments = getTrailingCommentsOfPosition(pos);
|
||||
performance.measure("commentTime", "commentStart");
|
||||
return comments;
|
||||
},
|
||||
emitLeadingComments(range: TextRange, comments: CommentRange[], contextNode?: Node, getTextRangeCallback?: (contextNode: Node) => TextRange): void {
|
||||
performance.mark("commentStart");
|
||||
emitLeadingComments(range, comments, contextNode, getTextRangeCallback);
|
||||
performance.measure("commentTime", "commentStart");
|
||||
},
|
||||
emitTrailingComments(range: TextRange, comments: CommentRange[]): void {
|
||||
performance.mark("commentStart");
|
||||
emitLeadingComments(range, comments);
|
||||
performance.measure("commentTime", "commentStart");
|
||||
},
|
||||
emitLeadingDetachedComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean): void {
|
||||
performance.mark("commentStart");
|
||||
emitLeadingDetachedComments(range, contextNode, ignoreNodeCallback);
|
||||
performance.measure("commentTime", "commentStart");
|
||||
},
|
||||
emitTrailingDetachedComments(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (contextNode: Node) => boolean): void {
|
||||
performance.mark("commentStart");
|
||||
emitTrailingDetachedComments(range, contextNode, ignoreNodeCallback);
|
||||
performance.measure("commentTime", "commentStart");
|
||||
if (!skipLeadingComments) {
|
||||
emitDetachedCommentsAndUpdateCommentsInfo(detachedRange, compilerOptions.removeComments);
|
||||
}
|
||||
|
||||
emitCallback(node);
|
||||
|
||||
if (!skipTrailingComments) {
|
||||
emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
function emitLeadingComments(pos: number, isEmittedNode: boolean) {
|
||||
let leadingComments: CommentRange[];
|
||||
if (isEmittedNode) {
|
||||
leadingComments = getLeadingCommentsToEmit(pos);
|
||||
}
|
||||
else {
|
||||
// If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node,
|
||||
// unless it is a triple slash comment at the top of the file.
|
||||
// For Example:
|
||||
// /// <reference-path ...>
|
||||
// declare var x;
|
||||
// /// <reference-path ...>
|
||||
// interface F {}
|
||||
// The first /// will NOT be removed while the second one will be removed even though both node will not be emitted
|
||||
if (pos === 0) {
|
||||
leadingComments = filter(getLeadingCommentsToEmit(pos), isTripleSlashComment);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
emitNewLineBeforeLeadingCommentsOfPosition(currentLineMap, writer, pos, leadingComments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitTrailingComments(pos: number) {
|
||||
const trailingComments = getTrailingCommentsToEmit(pos);
|
||||
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitTrailingCommentsOfPosition(pos: number) {
|
||||
if (compilerOptions.removeComments) {
|
||||
return;
|
||||
}
|
||||
|
||||
const trailingComments = getTrailingCommentsToEmit(pos);
|
||||
|
||||
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function getLeadingCommentsToEmit(pos: number) {
|
||||
// Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments
|
||||
if (containerPos === -1 || pos !== containerPos) {
|
||||
return hasDetachedComments(pos)
|
||||
? getLeadingCommentsWithoutDetachedComments()
|
||||
: getLeadingCommentRanges(currentText, pos);
|
||||
}
|
||||
}
|
||||
|
||||
function getTrailingCommentsToEmit(end: number) {
|
||||
// Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments
|
||||
if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) {
|
||||
return getTrailingCommentRanges(currentText, end);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given comment is a triple-slash
|
||||
*
|
||||
* @return true if the comment is a triple-slash comment else false
|
||||
**/
|
||||
function isTripleSlashComment(comment: CommentRange) {
|
||||
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
|
||||
// so that we don't end up computing comment string and doing match for all // comments
|
||||
if (currentText.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
|
||||
comment.pos + 2 < comment.end &&
|
||||
currentText.charCodeAt(comment.pos + 2) === CharacterCodes.slash) {
|
||||
const textSubStr = currentText.substring(comment.pos, comment.end);
|
||||
return textSubStr.match(fullTripleSlashReferencePathRegEx) ||
|
||||
textSubStr.match(fullTripleSlashAMDReferencePathRegEx) ?
|
||||
true : false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
@ -276,8 +194,6 @@ namespace ts {
|
||||
currentLineMap = undefined;
|
||||
detachedCommentsInfo = undefined;
|
||||
consumedCommentRanges = undefined;
|
||||
trailingCommentRangePositions = undefined;
|
||||
leadingCommentRangePositions = undefined;
|
||||
}
|
||||
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
@ -286,8 +202,6 @@ namespace ts {
|
||||
currentLineMap = getLineStarts(currentSourceFile);
|
||||
detachedCommentsInfo = undefined;
|
||||
consumedCommentRanges = {};
|
||||
leadingCommentRangePositions = {};
|
||||
trailingCommentRangePositions = {};
|
||||
}
|
||||
|
||||
function hasDetachedComments(pos: number) {
|
||||
@ -297,7 +211,7 @@ namespace ts {
|
||||
function getLeadingCommentsWithoutDetachedComments() {
|
||||
// get the leading comments from detachedPos
|
||||
const pos = lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos;
|
||||
const leadingComments = getLeadingCommentRanges(currentText, pos, consumedCommentRanges);
|
||||
const leadingComments = getLeadingCommentRanges(currentText, pos);
|
||||
if (detachedCommentsInfo.length - 1) {
|
||||
detachedCommentsInfo.pop();
|
||||
}
|
||||
|
||||
@ -161,13 +161,9 @@ const _super = (function (geti, seti) {
|
||||
|
||||
const comments = createCommentWriter(host, writer, sourceMap);
|
||||
const {
|
||||
getLeadingComments,
|
||||
getTrailingComments,
|
||||
getTrailingCommentsOfPosition,
|
||||
emitLeadingComments,
|
||||
emitTrailingComments,
|
||||
emitLeadingDetachedComments,
|
||||
emitTrailingDetachedComments
|
||||
emitNodeWithComments,
|
||||
emitBodyWithDetachedComments,
|
||||
emitTrailingCommentsOfPosition
|
||||
} = comments;
|
||||
|
||||
let context: TransformationContext;
|
||||
@ -175,7 +171,6 @@ const _super = (function (geti, seti) {
|
||||
let setNodeEmitFlags: (node: Node, flags: NodeEmitFlags) => void;
|
||||
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;
|
||||
@ -240,7 +235,6 @@ const _super = (function (geti, seti) {
|
||||
setNodeEmitFlags = undefined;
|
||||
getSourceMapRange = undefined;
|
||||
getTokenSourceMapRange = undefined;
|
||||
getCommentRange = undefined;
|
||||
isSubstitutionEnabled = undefined;
|
||||
isEmitNotificationEnabled = undefined;
|
||||
onSubstituteNode = undefined;
|
||||
@ -262,7 +256,6 @@ const _super = (function (geti, seti) {
|
||||
setNodeEmitFlags = context.setNodeEmitFlags;
|
||||
getSourceMapRange = context.getSourceMapRange;
|
||||
getTokenSourceMapRange = context.getTokenSourceMapRange;
|
||||
getCommentRange = context.getCommentRange;
|
||||
isSubstitutionEnabled = context.isSubstitutionEnabled;
|
||||
isEmitNotificationEnabled = context.isEmitNotificationEnabled;
|
||||
onSubstituteNode = context.onSubstituteNode;
|
||||
@ -276,7 +269,7 @@ const _super = (function (geti, seti) {
|
||||
currentFileIdentifiers = node.identifiers;
|
||||
sourceMap.setSourceFile(node);
|
||||
comments.setSourceFile(node);
|
||||
emitNodeWithNotificationOption(node, emitWorker);
|
||||
emitNodeWithNotification(node, emitWorker);
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -291,7 +284,7 @@ const _super = (function (geti, seti) {
|
||||
* Emits a node.
|
||||
*/
|
||||
function emit(node: Node) {
|
||||
emitNodeWithNotificationOption(node, emitWithoutNotificationOption);
|
||||
emitNodeWithNotification(node, emitWithComments);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,51 +308,71 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node without calling onEmitNode.
|
||||
* NOTE: Do not call this method directly.
|
||||
* Emits a node with comments.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from emit.
|
||||
*/
|
||||
function emitWithoutNotificationOption(node: Node) {
|
||||
emitNodeWithWorker(node, emitWorker);
|
||||
function emitWithComments(node: Node) {
|
||||
emitNodeWithComments(node, emitWithSourceMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node with source maps.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from emitWithComments.
|
||||
*/
|
||||
function emitWithSourceMap(node: Node) {
|
||||
emitNodeWithSourceMap(node, emitWorker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an expression node.
|
||||
*/
|
||||
function emitExpression(node: Expression) {
|
||||
emitNodeWithNotificationOption(node, emitExpressionWithoutNotificationOption);
|
||||
emitNodeWithNotification(node, emitExpressionWithComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an expression without calling onEmitNode.
|
||||
* NOTE: Do not call this method directly.
|
||||
* Emits an expression with comments.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emitExpression pipeline
|
||||
* and should only be called indirectly from emitExpression.
|
||||
*/
|
||||
function emitExpressionWithoutNotificationOption(node: Expression) {
|
||||
emitNodeWithWorker(node, emitExpressionWorker);
|
||||
function emitExpressionWithComments(node: Expression) {
|
||||
emitNodeWithComments(node, emitExpressionWithSourceMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an expression with source maps.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emitExpression pipeline
|
||||
* and should only be called indirectly from emitExpressionWithComments.
|
||||
*/
|
||||
function emitExpressionWithSourceMap(node: Expression) {
|
||||
emitNodeWithSourceMap(node, emitExpressionWorker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node with emit notification if available.
|
||||
*/
|
||||
function emitNodeWithNotificationOption(node: Node, emit: (node: Node) => void) {
|
||||
function emitNodeWithNotification(node: Node, emitCallback: (node: Node) => void) {
|
||||
if (node) {
|
||||
if (isEmitNotificationEnabled(node)) {
|
||||
onEmitNode(node, emit);
|
||||
onEmitNode(node, emitCallback);
|
||||
}
|
||||
else {
|
||||
emit(node);
|
||||
emitCallback(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitNodeWithWorker(node: Node, emitWorker: (node: Node) => void) {
|
||||
function emitNodeWithSourceMap(node: Node, emitCallback: (node: Node) => void) {
|
||||
if (node) {
|
||||
const leadingComments = getLeadingComments(/*range*/ node, /*contextNode*/ node, shouldSkipLeadingCommentsForNode, getCommentRange);
|
||||
const trailingComments = getTrailingComments(/*range*/ node, /*contextNode*/ node, shouldSkipTrailingCommentsForNode, getCommentRange);
|
||||
emitLeadingComments(/*range*/ node, leadingComments, /*contextNode*/ node, getCommentRange);
|
||||
emitStart(/*range*/ node, /*contextNode*/ node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitWorker(node);
|
||||
emitCallback(node);
|
||||
emitEnd(/*range*/ node, /*contextNode*/ node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitTrailingComments(node, trailingComments);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1642,13 +1655,26 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
increaseIndent();
|
||||
emitLeadingDetachedComments(body.statements, body, shouldSkipLeadingCommentsForNode);
|
||||
|
||||
emitBodyWithDetachedComments(body, body.statements,
|
||||
shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body)
|
||||
? emitBlockFunctionBodyOnSingleLine
|
||||
: emitBlockFunctionBodyWorker);
|
||||
|
||||
decreaseIndent();
|
||||
writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body);
|
||||
}
|
||||
|
||||
function emitBlockFunctionBodyOnSingleLine(body: Block) {
|
||||
emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true);
|
||||
}
|
||||
|
||||
function emitBlockFunctionBodyWorker(body: Block, emitBlockFunctionBodyOnSingleLine?: boolean) {
|
||||
// Emit all the prologue directives (like "use strict").
|
||||
const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true);
|
||||
const helpersEmitted = emitHelpers(body);
|
||||
|
||||
if (statementOffset === 0 && !helpersEmitted && shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body)) {
|
||||
if (statementOffset === 0 && !helpersEmitted && emitBlockFunctionBodyOnSingleLine) {
|
||||
decreaseIndent();
|
||||
emitList(body, body.statements, ListFormat.SingleLineFunctionBodyStatements);
|
||||
increaseIndent();
|
||||
@ -1656,10 +1682,6 @@ const _super = (function (geti, seti) {
|
||||
else {
|
||||
emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, statementOffset);
|
||||
}
|
||||
|
||||
emitTrailingDetachedComments(body.statements, body, shouldSkipTrailingCommentsForNode);
|
||||
decreaseIndent();
|
||||
writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body);
|
||||
}
|
||||
|
||||
function emitClassDeclaration(node: ClassDeclaration) {
|
||||
@ -2004,9 +2026,12 @@ const _super = (function (geti, seti) {
|
||||
// }
|
||||
// "comment1" is not considered to be leading comment for node.initializer
|
||||
// but rather a trailing comment on the previous node.
|
||||
if (!shouldSkipLeadingCommentsForNode(node.initializer)) {
|
||||
emitLeadingComments(/*range*/ node.initializer, getTrailingComments(collapseRangeToStart(node.initializer)), /*contextNode*/ node.initializer, getCommentRange);
|
||||
const initializer = node.initializer;
|
||||
if (!shouldSkipLeadingCommentsForNode(initializer)) {
|
||||
const commentRange = initializer.commentRange || initializer;
|
||||
emitTrailingCommentsOfPosition(commentRange.pos);
|
||||
}
|
||||
|
||||
emitExpression(node.initializer);
|
||||
}
|
||||
|
||||
@ -2034,8 +2059,10 @@ const _super = (function (geti, seti) {
|
||||
function emitSourceFile(node: SourceFile) {
|
||||
writeLine();
|
||||
emitShebang();
|
||||
emitLeadingDetachedComments(node);
|
||||
emitBodyWithDetachedComments(node, node.statements, emitSourceFileWorker);
|
||||
}
|
||||
|
||||
function emitSourceFileWorker(node: SourceFile) {
|
||||
const statements = node.statements;
|
||||
const statementOffset = emitPrologueDirectives(statements);
|
||||
if (getNodeEmitFlags(node) & NodeEmitFlags.NoLexicalEnvironment) {
|
||||
@ -2049,8 +2076,6 @@ const _super = (function (geti, seti) {
|
||||
emitList(node, statements, ListFormat.MultiLine, statementOffset);
|
||||
tempFlags = savedTempFlags;
|
||||
}
|
||||
|
||||
emitTrailingDetachedComments(node.statements);
|
||||
}
|
||||
|
||||
// Transformation nodes
|
||||
@ -2326,7 +2351,8 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
else {
|
||||
// Write the opening line terminator or leading whitespace.
|
||||
let shouldEmitInterveningComments = true;
|
||||
const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0;
|
||||
let shouldEmitInterveningComments = mayEmitInterveningComments;
|
||||
if (shouldWriteLeadingLineTerminator(parentNode, children, format)) {
|
||||
writeLine();
|
||||
shouldEmitInterveningComments = false;
|
||||
@ -2369,10 +2395,11 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
if (shouldEmitInterveningComments) {
|
||||
emitLeadingComments(/*node*/ child, getTrailingCommentsOfPosition(child.pos), /*contextNode*/ child, getCommentRange);
|
||||
const commentRange = child.commentRange || child;
|
||||
emitTrailingCommentsOfPosition(commentRange.pos);
|
||||
}
|
||||
else {
|
||||
shouldEmitInterveningComments = true;
|
||||
shouldEmitInterveningComments = mayEmitInterveningComments;
|
||||
}
|
||||
|
||||
// Emit this child.
|
||||
@ -2876,6 +2903,7 @@ const _super = (function (geti, seti) {
|
||||
// Other
|
||||
PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes.
|
||||
NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list.
|
||||
NoInterveningComments = 1 << 17,// Do not emit comments between each node
|
||||
|
||||
// Precomputed Formats
|
||||
Modifiers = SingleLine | SpaceBetweenSiblings,
|
||||
@ -2890,7 +2918,7 @@ const _super = (function (geti, seti) {
|
||||
ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets,
|
||||
CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis,
|
||||
NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined,
|
||||
TemplateExpressionSpans = SingleLine,
|
||||
TemplateExpressionSpans = SingleLine | NoInterveningComments,
|
||||
SingleLineBlockStatements = SpaceBetweenBraces | SpaceBetweenSiblings | SingleLine,
|
||||
MultiLineBlockStatements = Indented | MultiLine,
|
||||
VariableDeclarationList = CommaDelimited | SpaceBetweenSiblings | SingleLine,
|
||||
@ -2902,8 +2930,8 @@ const _super = (function (geti, seti) {
|
||||
EnumMembers = CommaDelimited | Indented | MultiLine,
|
||||
CaseBlockClauses = Indented | MultiLine,
|
||||
NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces,
|
||||
JsxElementChildren = SingleLine,
|
||||
JsxElementAttributes = SingleLine | SpaceBetweenSiblings,
|
||||
JsxElementChildren = SingleLine | NoInterveningComments,
|
||||
JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments,
|
||||
CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty,
|
||||
HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine,
|
||||
SourceFileStatements = MultiLine | NoTrailingNewLine,
|
||||
|
||||
@ -591,7 +591,7 @@ namespace ts {
|
||||
* and the next token are returned.
|
||||
* If true, comments occurring between the given position and the next line break are returned.
|
||||
*/
|
||||
function getCommentRanges(text: string, pos: number, trailing: boolean, consumedCommentRanges?: Map<boolean>): CommentRange[] {
|
||||
function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] {
|
||||
let result: CommentRange[];
|
||||
let collecting = trailing || pos === 0;
|
||||
while (pos >= 0 && pos < text.length) {
|
||||
@ -643,15 +643,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (collecting && (!consumedCommentRanges || !(startPos in consumedCommentRanges))) {
|
||||
if (collecting) {
|
||||
if (!result) {
|
||||
result = [];
|
||||
}
|
||||
|
||||
result.push({ pos: startPos, end: pos, hasTrailingNewLine, kind });
|
||||
if (consumedCommentRanges) {
|
||||
consumedCommentRanges[startPos] = true;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
@ -673,12 +670,12 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getLeadingCommentRanges(text: string, pos: number, consumedCommentRanges?: Map<boolean>): CommentRange[] {
|
||||
return getCommentRanges(text, pos, /*trailing*/ false, consumedCommentRanges);
|
||||
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] {
|
||||
return getCommentRanges(text, pos, /*trailing*/ false);
|
||||
}
|
||||
|
||||
export function getTrailingCommentRanges(text: string, pos: number, consumedCommentRanges?: Map<boolean>): CommentRange[] {
|
||||
return getCommentRanges(text, pos, /*trailing*/ true, consumedCommentRanges);
|
||||
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] {
|
||||
return getCommentRanges(text, pos, /*trailing*/ true);
|
||||
}
|
||||
|
||||
/** Optionally, get the shebang */
|
||||
|
||||
@ -1526,6 +1526,7 @@ namespace ts {
|
||||
|
||||
const declarationList = createVariableDeclarationList(declarations, /*location*/ node);
|
||||
setOriginalNode(declarationList, node);
|
||||
setCommentRange(declarationList, node);
|
||||
|
||||
if (node.transformFlags & TransformFlags.ContainsBindingPattern
|
||||
&& (isBindingPattern(node.declarations[0].name)
|
||||
|
||||
@ -17,6 +17,7 @@ namespace ts {
|
||||
hoistVariableDeclaration,
|
||||
setNodeEmitFlags,
|
||||
getNodeEmitFlags,
|
||||
setSourceMapRange,
|
||||
} = context;
|
||||
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
@ -926,7 +927,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createExportStatement(name: Identifier, value: Expression, location?: TextRange) {
|
||||
return startOnNewLine(createStatement(createExportAssignment(name, value), location));
|
||||
const statement = createStatement(createExportAssignment(name, value));
|
||||
statement.startsOnNewLine = true;
|
||||
if (location) {
|
||||
setSourceMapRange(statement, location);
|
||||
}
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
function createExportAssignment(name: Identifier, value: Expression) {
|
||||
|
||||
@ -2376,17 +2376,16 @@ namespace ts {
|
||||
* Adds a trailing VariableStatement for an enum or module declaration.
|
||||
*/
|
||||
function addVarForEnumExportedFromNamespace(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) {
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
[createVariableDeclaration(
|
||||
getDeclarationName(node),
|
||||
/*type*/ undefined,
|
||||
getExportName(node)
|
||||
)],
|
||||
/*location*/ node
|
||||
)
|
||||
const statement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
[createVariableDeclaration(
|
||||
getDeclarationName(node),
|
||||
/*type*/ undefined,
|
||||
getExportName(node)
|
||||
)]
|
||||
);
|
||||
setSourceMapRange(statement, node);
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2402,48 +2401,62 @@ namespace ts {
|
||||
}
|
||||
|
||||
const statements: Statement[] = [];
|
||||
|
||||
// We request to be advised when the printer is about to print this node. This allows
|
||||
// us to set up the correct state for later substitutions.
|
||||
let emitFlags = NodeEmitFlags.AdviseOnEmitNode;
|
||||
|
||||
// If needed, we should emit a variable declaration for the enum. If we emit
|
||||
// a leading variable declaration, we should not emit leading comments for the
|
||||
// enum body.
|
||||
if (shouldEmitVarForEnumDeclaration(node)) {
|
||||
addVarForEnumOrModuleDeclaration(statements, node);
|
||||
|
||||
// We should still emit the comments if we are emitting a system module.
|
||||
if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) {
|
||||
emitFlags |= NodeEmitFlags.NoLeadingComments;
|
||||
}
|
||||
}
|
||||
|
||||
const innerName = getNamespaceContainerName(node);
|
||||
const paramName = getNamespaceParameterName(node);
|
||||
// `parameterName` is the declaration name used inside of the enum.
|
||||
const parameterName = getNamespaceParameterName(node);
|
||||
|
||||
// `containerName` is the expression used inside of the enum for assignments.
|
||||
const containerName = getNamespaceContainerName(node);
|
||||
|
||||
// `exportName` is the expression used within this node's container for any exported references.
|
||||
const exportName = getExportName(node);
|
||||
|
||||
// (function (x) {
|
||||
// x[x["y"] = 0] = "y";
|
||||
// ...
|
||||
// })(x || (x = {}));
|
||||
statements.push(
|
||||
setNodeEmitFlags(
|
||||
setOriginalNode(
|
||||
createStatement(
|
||||
createCall(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(paramName)],
|
||||
/*type*/ undefined,
|
||||
transformEnumBody(node, innerName)
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[createLogicalOr(
|
||||
exportName,
|
||||
createAssignment(
|
||||
exportName,
|
||||
createObjectLiteral()
|
||||
)
|
||||
)]
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node
|
||||
const enumStatement = createStatement(
|
||||
createCall(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(parameterName)],
|
||||
/*type*/ undefined,
|
||||
transformEnumBody(node, containerName)
|
||||
),
|
||||
NodeEmitFlags.AdviseOnEmitNode
|
||||
)
|
||||
/*typeArguments*/ undefined,
|
||||
[createLogicalOr(
|
||||
exportName,
|
||||
createAssignment(
|
||||
exportName,
|
||||
createObjectLiteral()
|
||||
)
|
||||
)]
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
|
||||
setOriginalNode(enumStatement, node);
|
||||
setNodeEmitFlags(enumStatement, emitFlags);
|
||||
statements.push(enumStatement);
|
||||
|
||||
if (isNamespaceExport(node)) {
|
||||
addVarForEnumExportedFromNamespace(statements, node);
|
||||
}
|
||||
@ -2614,8 +2627,19 @@ namespace ts {
|
||||
|
||||
const statements: Statement[] = [];
|
||||
|
||||
// We request to be advised when the printer is about to print this node. This allows
|
||||
// us to set up the correct state for later substitutions.
|
||||
let emitFlags = NodeEmitFlags.AdviseOnEmitNode;
|
||||
|
||||
// If needed, we should emit a variable declaration for the module. If we emit
|
||||
// a leading variable declaration, we should not emit leading comments for the
|
||||
// module body.
|
||||
if (shouldEmitVarForModuleDeclaration(node)) {
|
||||
addVarForEnumOrModuleDeclaration(statements, node);
|
||||
// We should still emit the comments if we are emitting a system module.
|
||||
if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) {
|
||||
emitFlags |= NodeEmitFlags.NoLeadingComments;
|
||||
}
|
||||
}
|
||||
|
||||
// `parameterName` is the declaration name used inside of the namespace.
|
||||
@ -2649,30 +2673,25 @@ namespace ts {
|
||||
// (function (x_1) {
|
||||
// x_1.y = ...;
|
||||
// })(x || (x = {}));
|
||||
statements.push(
|
||||
setNodeEmitFlags(
|
||||
setOriginalNode(
|
||||
createStatement(
|
||||
createCall(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(parameterName)],
|
||||
/*type*/ undefined,
|
||||
transformModuleBody(node, containerName)
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[moduleArg]
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node
|
||||
const moduleStatement = createStatement(
|
||||
createCall(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(parameterName)],
|
||||
/*type*/ undefined,
|
||||
transformModuleBody(node, containerName)
|
||||
),
|
||||
NodeEmitFlags.AdviseOnEmitNode
|
||||
)
|
||||
/*typeArguments*/ undefined,
|
||||
[moduleArg]
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
|
||||
setOriginalNode(moduleStatement, node);
|
||||
setNodeEmitFlags(moduleStatement, emitFlags);
|
||||
statements.push(moduleStatement);
|
||||
return statements;
|
||||
}
|
||||
|
||||
@ -2846,16 +2865,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addExportMemberAssignment(statements: Statement[], node: DeclarationStatement) {
|
||||
statements.push(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
getExportName(node),
|
||||
getLocalName(node, /*noSourceMaps*/ true),
|
||||
/*location*/ createRange(node.name.pos, node.end)
|
||||
),
|
||||
/*location*/ createRange(-1, node.end)
|
||||
)
|
||||
const expression = createAssignment(
|
||||
getExportName(node),
|
||||
getLocalName(node, /*noSourceMaps*/ true)
|
||||
);
|
||||
setSourceMapRange(expression, createRange(node.name.pos, node.end));
|
||||
|
||||
const statement = createStatement(expression);
|
||||
setSourceMapRange(statement, createRange(-1, node.end));
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
function createNamespaceExport(exportName: Identifier, exportValue: Expression, location?: TextRange) {
|
||||
|
||||
@ -695,6 +695,7 @@ namespace ts {
|
||||
export let fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^(\/\/\/\s*<reference\s+types\s*=\s*)('|")(.+?)\2.*?\/>/;
|
||||
export let fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*<amd-dependency\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
|
||||
|
||||
|
||||
export function isPartOfTypeNode(node: Node): boolean {
|
||||
if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) {
|
||||
return true;
|
||||
@ -2590,9 +2591,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
|
||||
emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments);
|
||||
}
|
||||
|
||||
export function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: number[], writer: EmitTextWriter, pos: number, leadingComments: CommentRange[]) {
|
||||
// If the leading comments start on different line than the start of node, write new line
|
||||
if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
|
||||
getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) {
|
||||
if (leadingComments && leadingComments.length && pos !== leadingComments[0].pos &&
|
||||
getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user