mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Fixes some comment emit and other changes
This commit is contained in:
parent
794e0cef8c
commit
15780a9a4c
@ -5,14 +5,14 @@ namespace ts {
|
||||
export interface CommentWriter {
|
||||
reset(): void;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
getLeadingComments(range: Node, getAdditionalRange?: (range: Node) => Node): CommentRange[];
|
||||
getLeadingComments(range: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): CommentRange[];
|
||||
getLeadingComments(range: TextRange): CommentRange[];
|
||||
getLeadingCommentsOfPosition(pos: number): CommentRange[];
|
||||
getTrailingComments(range: Node, getAdditionalRange?: (range: Node) => Node): CommentRange[];
|
||||
getTrailingComments(range: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): CommentRange[];
|
||||
getTrailingComments(range: TextRange): CommentRange[];
|
||||
getTrailingCommentsOfPosition(pos: number): CommentRange[];
|
||||
emitLeadingComments(range: TextRange, comments?: CommentRange[]): void;
|
||||
emitTrailingComments(range: TextRange, comments?: CommentRange[]): void;
|
||||
emitLeadingComments(range: TextRange, comments: CommentRange[]): void;
|
||||
emitTrailingComments(range: TextRange, comments: CommentRange[]): void;
|
||||
emitDetachedComments(range: TextRange): void;
|
||||
}
|
||||
|
||||
@ -40,12 +40,12 @@ namespace ts {
|
||||
return {
|
||||
reset,
|
||||
setSourceFile,
|
||||
getLeadingComments(range: TextRange, getAdditionalRange?: (range: TextRange) => TextRange): CommentRange[] { return undefined; },
|
||||
getLeadingComments(range: TextRange, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): CommentRange[] { return undefined; },
|
||||
getLeadingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
|
||||
getTrailingComments(range: TextRange, getAdditionalRange?: (range: TextRange) => TextRange): CommentRange[] { return undefined; },
|
||||
getTrailingComments(range: TextRange, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): CommentRange[] { return undefined; },
|
||||
getTrailingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
|
||||
emitLeadingComments(range: TextRange, comments?: CommentRange[]): void { },
|
||||
emitTrailingComments(range: TextRange, comments?: CommentRange[]): void { },
|
||||
emitLeadingComments(range: TextRange, comments: CommentRange[]): void { },
|
||||
emitTrailingComments(range: TextRange, comments: CommentRange[]): void { },
|
||||
emitDetachedComments,
|
||||
};
|
||||
|
||||
@ -68,38 +68,48 @@ namespace ts {
|
||||
emitDetachedComments,
|
||||
};
|
||||
|
||||
function getLeadingComments(range: TextRange | Node, getAdditionalRange?: (range: Node) => Node) {
|
||||
let comments = getLeadingCommentsOfPosition(range.pos);
|
||||
if (getAdditionalRange) {
|
||||
let additionalRange = getAdditionalRange(<Node>range);
|
||||
while (additionalRange) {
|
||||
comments = concatenate(
|
||||
getLeadingCommentsOfPosition(additionalRange.pos),
|
||||
comments
|
||||
);
|
||||
|
||||
additionalRange = getAdditionalRange(additionalRange);
|
||||
function getLeadingComments(range: TextRange | Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean) {
|
||||
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(<Node>range)) {
|
||||
// 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) {
|
||||
return filter(getLeadingCommentsOfPosition(0), isTripleSlashComment);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return comments;
|
||||
return getLeadingCommentsOfPosition(range.pos);
|
||||
}
|
||||
|
||||
function getTrailingComments(range: TextRange | Node, getAdditionalRange?: (range: Node) => Node) {
|
||||
let comments = getTrailingCommentsOfPosition(range.end);
|
||||
if (getAdditionalRange) {
|
||||
let additionalRange = getAdditionalRange(<Node>range);
|
||||
while (additionalRange) {
|
||||
comments = concatenate(
|
||||
comments,
|
||||
getTrailingCommentsOfPosition(additionalRange.end)
|
||||
);
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
additionalRange = getAdditionalRange(additionalRange);
|
||||
}
|
||||
function getTrailingComments(range: TextRange | Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean) {
|
||||
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(<Node>range)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return comments;
|
||||
return getTrailingCommentsOfPosition(range.end);
|
||||
}
|
||||
|
||||
function getLeadingCommentsOfPosition(pos: number) {
|
||||
@ -124,14 +134,14 @@ namespace ts {
|
||||
return consumeCommentRanges(comments);
|
||||
}
|
||||
|
||||
function emitLeadingComments(range: TextRange, comments = getLeadingComments(range)) {
|
||||
function emitLeadingComments(range: TextRange, comments: CommentRange[]) {
|
||||
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 = getTrailingComments(range)) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1036,7 +1036,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
return;
|
||||
}
|
||||
|
||||
const emitOuterParens = isPartOfExpression(node.parent)
|
||||
const emitOuterParens = node.parent.kind !== SyntaxKind.ArrowFunction
|
||||
&& isPartOfExpression(node.parent)
|
||||
&& templateNeedsParens(node, <Expression>node.parent);
|
||||
|
||||
if (emitOuterParens) {
|
||||
|
||||
@ -413,6 +413,11 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createOmittedExpression(location?: TextRange) {
|
||||
const node = <OmittedExpression>createNode(SyntaxKind.OmittedExpression, location);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createExpressionWithTypeArguments(expression: Expression, location?: TextRange) {
|
||||
const node = <ExpressionWithTypeArguments>createNode(SyntaxKind.ExpressionWithTypeArguments, location);
|
||||
node.typeArguments = undefined;
|
||||
@ -627,6 +632,34 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
// Transformation nodes
|
||||
|
||||
/**
|
||||
* Creates a synthetic statement to act as a placeholder for a not-emitted statement in
|
||||
* order to preserve comments.
|
||||
*
|
||||
* @param original The original statement.
|
||||
*/
|
||||
export function createNotEmittedStatement(original: Node) {
|
||||
const node = <NotEmittedStatement>createNode(SyntaxKind.NotEmittedStatement, /*location*/ original);
|
||||
node.original = original;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a synthetic expression to act as a placeholder for a not-emitted expression in
|
||||
* order to preserve comments.
|
||||
*
|
||||
* @param expression The inner expression to emit.
|
||||
* @param original The original outer expression.
|
||||
*/
|
||||
export function createPartiallyEmittedExpression(expression: Expression, original: Node) {
|
||||
const node = <PartiallyEmittedExpression>createNode(SyntaxKind.PartiallyEmittedExpression, /*location*/ original);
|
||||
node.expression = expression;
|
||||
node.original = original;
|
||||
return node;
|
||||
}
|
||||
|
||||
// Compound nodes
|
||||
|
||||
export function createComma(left: Expression, right: Expression) {
|
||||
@ -1067,7 +1100,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createCallBinding(expression: Expression, languageVersion?: ScriptTarget): CallBinding {
|
||||
const callee = skipParentheses(expression);
|
||||
const callee = skipOuterExpressions(expression, OuterExpressionKinds.All);
|
||||
let thisArg: Expression;
|
||||
let target: LeftHandSideExpression;
|
||||
if (isSuperProperty(callee)) {
|
||||
@ -1180,8 +1213,10 @@ namespace ts {
|
||||
* BinaryExpression.
|
||||
*/
|
||||
export function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression) {
|
||||
const skipped = skipPartiallyEmittedExpressions(operand);
|
||||
|
||||
// If the resulting expression is already parenthesized, we do not need to do any further processing.
|
||||
if (operand.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
if (skipped.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
return operand;
|
||||
}
|
||||
|
||||
@ -1217,7 +1252,8 @@ namespace ts {
|
||||
// If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve
|
||||
// the intended order of operations: `(a ** b) ** c`
|
||||
const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator);
|
||||
const operandPrecedence = getExpressionPrecedence(operand);
|
||||
const emittedOperand = skipPartiallyEmittedExpressions(operand);
|
||||
const operandPrecedence = getExpressionPrecedence(emittedOperand);
|
||||
switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) {
|
||||
case Comparison.LessThan:
|
||||
return true;
|
||||
@ -1240,8 +1276,8 @@ namespace ts {
|
||||
return binaryOperatorAssociativity === Associativity.Right;
|
||||
}
|
||||
else {
|
||||
if (isBinaryExpression(operand)
|
||||
&& operand.operatorToken.kind === binaryOperator) {
|
||||
if (isBinaryExpression(emittedOperand)
|
||||
&& emittedOperand.operatorToken.kind === binaryOperator) {
|
||||
// No need to parenthesize the right operand when the binary operator and
|
||||
// operand are the same and one of the following:
|
||||
// x*(a*b) => x*a*b
|
||||
@ -1260,7 +1296,7 @@ namespace ts {
|
||||
// "a"+("b"+"c") => "a"+"b"+"c"
|
||||
if (binaryOperator === SyntaxKind.PlusToken) {
|
||||
const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : SyntaxKind.Unknown;
|
||||
if (leftKind === getLiteralKindOfBinaryPlusOperand(operand)) {
|
||||
if (isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1275,7 +1311,7 @@ namespace ts {
|
||||
// associative:
|
||||
// x/(a*b) -> x/(a*b)
|
||||
// x**(a/b) -> x**(a/b)
|
||||
const operandAssociativity = getExpressionAssociativity(operand);
|
||||
const operandAssociativity = getExpressionAssociativity(emittedOperand);
|
||||
return operandAssociativity === Associativity.Left;
|
||||
}
|
||||
}
|
||||
@ -1301,6 +1337,41 @@ namespace ts {
|
||||
|| binaryOperator === SyntaxKind.CaretToken;
|
||||
}
|
||||
|
||||
interface BinaryPlusExpression extends BinaryExpression {
|
||||
cachedLiteralKind: SyntaxKind;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function determines whether an expression consists of a homogeneous set of
|
||||
* literal expressions or binary plus expressions that all share the same literal kind.
|
||||
* It is used to determine whether the right-hand operand of a binary plus expression can be
|
||||
* emitted without parentheses.
|
||||
*/
|
||||
function getLiteralKindOfBinaryPlusOperand(node: Expression): SyntaxKind {
|
||||
node = skipPartiallyEmittedExpressions(node);
|
||||
|
||||
if (isLiteralKind(node.kind)) {
|
||||
return node.kind;
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.PlusToken) {
|
||||
if ((<BinaryPlusExpression>node).cachedLiteralKind !== undefined) {
|
||||
return (<BinaryPlusExpression>node).cachedLiteralKind;
|
||||
}
|
||||
|
||||
const leftKind = getLiteralKindOfBinaryPlusOperand((<BinaryExpression>node).left);
|
||||
const literalKind = isLiteralKind(leftKind)
|
||||
&& leftKind === getLiteralKindOfBinaryPlusOperand((<BinaryExpression>node).right)
|
||||
? leftKind
|
||||
: SyntaxKind.Unknown;
|
||||
|
||||
(<BinaryPlusExpression>node).cachedLiteralKind = literalKind;
|
||||
return literalKind;
|
||||
}
|
||||
|
||||
return SyntaxKind.Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an expression in parentheses if it is needed in order to use the expression
|
||||
* as the expression of a NewExpression node.
|
||||
@ -1308,13 +1379,14 @@ namespace ts {
|
||||
* @param expression The Expression node.
|
||||
*/
|
||||
export function parenthesizeForNew(expression: Expression): LeftHandSideExpression {
|
||||
switch (expression.kind) {
|
||||
const emittedExpression = skipPartiallyEmittedExpressions(expression);
|
||||
switch (emittedExpression.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
return createParen(expression);
|
||||
|
||||
case SyntaxKind.NewExpression:
|
||||
return (<NewExpression>expression).arguments
|
||||
? <NewExpression>expression
|
||||
return (<NewExpression>emittedExpression).arguments
|
||||
? <LeftHandSideExpression>expression
|
||||
: createParen(expression);
|
||||
}
|
||||
|
||||
@ -1336,9 +1408,10 @@ namespace ts {
|
||||
// NumericLiteral
|
||||
// 1.x -> not the same as (1).x
|
||||
//
|
||||
if (isLeftHandSideExpression(expression)
|
||||
&& (expression.kind !== SyntaxKind.NewExpression || (<NewExpression>expression).arguments)
|
||||
&& expression.kind !== SyntaxKind.NumericLiteral) {
|
||||
const emittedExpression = skipPartiallyEmittedExpressions(expression);
|
||||
if (isLeftHandSideExpression(emittedExpression)
|
||||
&& (emittedExpression.kind !== SyntaxKind.NewExpression || (<NewExpression>emittedExpression).arguments)
|
||||
&& emittedExpression.kind !== SyntaxKind.NumericLiteral) {
|
||||
return <LeftHandSideExpression>expression;
|
||||
}
|
||||
|
||||
@ -1378,7 +1451,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function parenthesizeExpressionForList(expression: Expression) {
|
||||
const expressionPrecedence = getExpressionPrecedence(expression);
|
||||
const emittedExpression = skipPartiallyEmittedExpressions(expression);
|
||||
const expressionPrecedence = getExpressionPrecedence(emittedExpression);
|
||||
const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken);
|
||||
return expressionPrecedence > commaPrecedence
|
||||
? expression
|
||||
@ -1386,17 +1460,18 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function parenthesizeExpressionForExpressionStatement(expression: Expression) {
|
||||
if (isCallExpression(expression)) {
|
||||
const callee = expression.expression;
|
||||
if (callee.kind === SyntaxKind.FunctionExpression
|
||||
|| callee.kind === SyntaxKind.ArrowFunction) {
|
||||
const clone = getMutableClone(expression);
|
||||
clone.expression = createParen(callee, /*location*/ callee);
|
||||
return clone;
|
||||
const emittedExpression = skipPartiallyEmittedExpressions(expression);
|
||||
if (isCallExpression(emittedExpression)) {
|
||||
const callee = emittedExpression.expression;
|
||||
const kind = skipPartiallyEmittedExpressions(callee).kind;
|
||||
if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) {
|
||||
const mutableCall = getMutableClone(emittedExpression);
|
||||
mutableCall.expression = createParen(callee, /*location*/ callee);
|
||||
return recreatePartiallyEmittedExpressions(expression, mutableCall);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const leftmostExpressionKind = getLeftmostExpression(expression).kind;
|
||||
const leftmostExpressionKind = getLeftmostExpression(emittedExpression).kind;
|
||||
if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) {
|
||||
return createParen(expression, /*location*/ expression);
|
||||
}
|
||||
@ -1405,27 +1480,20 @@ namespace ts {
|
||||
return expression;
|
||||
}
|
||||
|
||||
export function parenthesizeConciseBody(body: ConciseBody): ConciseBody {
|
||||
if (body.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
return createParen(<Expression>body, /*location*/ body);
|
||||
/**
|
||||
* Clones a series of not-emitted expressions with a new inner expression.
|
||||
*
|
||||
* @param originalOuterExpression The original outer expression.
|
||||
* @param newInnerExpression The new inner expression.
|
||||
*/
|
||||
function recreatePartiallyEmittedExpressions(originalOuterExpression: Expression, newInnerExpression: Expression) {
|
||||
if (isPartiallyEmittedExpression(originalOuterExpression)) {
|
||||
const clone = getMutableClone(originalOuterExpression);
|
||||
clone.expression = recreatePartiallyEmittedExpressions(clone.expression, newInnerExpression);
|
||||
return clone;
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
function getLiteralKindOfBinaryPlusOperand(node: Expression): SyntaxKind {
|
||||
if (isLiteralKind(node.kind)) {
|
||||
return node.kind;
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.PlusToken) {
|
||||
const leftKind = getLiteralKindOfBinaryPlusOperand((<BinaryExpression>node).left);
|
||||
if (leftKind === getLiteralKindOfBinaryPlusOperand((<BinaryExpression>node).right)) {
|
||||
return leftKind;
|
||||
}
|
||||
}
|
||||
|
||||
return SyntaxKind.Unknown;
|
||||
return newInnerExpression;
|
||||
}
|
||||
|
||||
function getLeftmostExpression(node: Expression): Expression {
|
||||
@ -1448,17 +1516,81 @@ namespace ts {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
node = (<CallExpression | PropertyAccessExpression | ElementAccessExpression>node).expression;
|
||||
continue;
|
||||
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
node = (<PartiallyEmittedExpression>node).expression;
|
||||
continue;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
export function skipParentheses(node: Expression): Expression {
|
||||
while (node.kind === SyntaxKind.ParenthesizedExpression
|
||||
|| node.kind === SyntaxKind.TypeAssertionExpression
|
||||
|| node.kind === SyntaxKind.AsExpression) {
|
||||
node = (<ParenthesizedExpression | AssertionExpression>node).expression;
|
||||
export function parenthesizeConciseBody(body: ConciseBody): ConciseBody {
|
||||
const emittedBody = skipPartiallyEmittedExpressions(body);
|
||||
if (emittedBody.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
return createParen(<Expression>body, /*location*/ body);
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
export const enum OuterExpressionKinds {
|
||||
Parentheses = 1 << 0,
|
||||
Assertions = 1 << 1,
|
||||
PartiallyEmittedExpressions = 1 << 2,
|
||||
|
||||
All = Parentheses | Assertions | PartiallyEmittedExpressions
|
||||
}
|
||||
|
||||
export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression;
|
||||
export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node;
|
||||
export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) {
|
||||
let previousNode: Node;
|
||||
do {
|
||||
previousNode = node;
|
||||
if (kinds & OuterExpressionKinds.Parentheses) {
|
||||
node = skipParentheses(node);
|
||||
}
|
||||
|
||||
if (kinds & OuterExpressionKinds.Assertions) {
|
||||
node = skipAssertions(node);
|
||||
}
|
||||
|
||||
if (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) {
|
||||
node = skipPartiallyEmittedExpressions(node);
|
||||
}
|
||||
}
|
||||
while (previousNode !== node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function skipParentheses(node: Expression): Expression;
|
||||
export function skipParentheses(node: Node): Node;
|
||||
export function skipParentheses(node: Node): Node {
|
||||
while (node.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
node = (<ParenthesizedExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function skipAssertions(node: Expression): Expression;
|
||||
export function skipAssertions(node: Node): Node;
|
||||
export function skipAssertions(node: Node): Node {
|
||||
while (isAssertionExpression(node)) {
|
||||
node = (<AssertionExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function skipPartiallyEmittedExpressions(node: Expression): Expression;
|
||||
export function skipPartiallyEmittedExpressions(node: Node): Node;
|
||||
export function skipPartiallyEmittedExpressions(node: Node) {
|
||||
while (node.kind === SyntaxKind.PartiallyEmittedExpression) {
|
||||
node = (<PartiallyEmittedExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
@ -400,6 +400,8 @@ namespace ts {
|
||||
return visitNode(cbNode, (<JSDocTypeTag>node).typeExpression);
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
return visitNodes(cbNodes, (<JSDocTemplateTag>node).typeParameters);
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
return visitNode(cbNode, (<PartiallyEmittedExpression>node).expression);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -295,22 +295,23 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function emitNodeWithWorker(node: Node, emitWorker: (node: Node) => void) {
|
||||
if (node) {
|
||||
const leadingComments = getLeadingComments(node, getNotEmittedParent);
|
||||
const trailingComments = getTrailingComments(node, getNotEmittedParent);
|
||||
const leadingComments = getLeadingComments(node, isNotEmittedStatement);
|
||||
const trailingComments = getTrailingComments(node, isNotEmittedStatement);
|
||||
emitLeadingComments(node, leadingComments);
|
||||
emitStart(node, shouldEmitSourceMap, shouldEmitNestedSourceMap);
|
||||
emitStart(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
|
||||
emitWorker(node);
|
||||
emitEnd(node, shouldEmitSourceMap, shouldEmitNestedSourceMap);
|
||||
emitEnd(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
|
||||
emitTrailingComments(node, trailingComments);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldEmitSourceMap(node: Node) {
|
||||
return (getNodeEmitFlags(node) & NodeEmitFlags.NoSourceMap) === 0;
|
||||
function shouldIgnoreSourceMapForNode(node: Node) {
|
||||
return isNotEmittedOrPartiallyEmittedNode(node)
|
||||
|| (getNodeEmitFlags(node) & NodeEmitFlags.NoSourceMap) !== 0;
|
||||
}
|
||||
|
||||
function shouldEmitNestedSourceMap(node: Node) {
|
||||
return (getNodeEmitFlags(node) & NodeEmitFlags.NoNestedSourceMaps) === 0;
|
||||
function shouldIgnoreSourceMapForChildren(node: Node) {
|
||||
return (getNodeEmitFlags(node) & NodeEmitFlags.NoNestedSourceMaps) !== 0;
|
||||
}
|
||||
|
||||
function emitWorker(node: Node): void {
|
||||
@ -559,6 +560,8 @@ const _super = (function (geti, seti) {
|
||||
return emitSourceFile(<SourceFile>node);
|
||||
|
||||
// JSDoc nodes (ignored)
|
||||
|
||||
// Transformation nodes (ignored)
|
||||
}
|
||||
|
||||
if (isExpression(node)) {
|
||||
@ -653,6 +656,10 @@ const _super = (function (geti, seti) {
|
||||
return emitJsxOpeningElement(<JsxOpeningElement>node);
|
||||
case SyntaxKind.JsxExpression:
|
||||
return emitJsxExpression(<JsxExpression>node);
|
||||
|
||||
// Transformation nodes
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
return emitPartiallyEmittedExpression(<PartiallyEmittedExpression>node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1475,7 +1482,9 @@ const _super = (function (geti, seti) {
|
||||
|
||||
const endingLine = writer.getLine();
|
||||
emitLexicalEnvironment(endLexicalEnvironment(), /*newLine*/ startingLine !== endingLine);
|
||||
emitLeadingComments(collapseRangeToEnd(body.statements));
|
||||
|
||||
const range = collapseRangeToEnd(body.statements);
|
||||
emitLeadingComments(range, getLeadingComments(range));
|
||||
decreaseIndent();
|
||||
}
|
||||
|
||||
@ -1841,7 +1850,13 @@ const _super = (function (geti, seti) {
|
||||
tempFlags = savedTempFlags;
|
||||
}
|
||||
|
||||
emitLeadingComments(node.endOfFileToken);
|
||||
emitLeadingComments(node.endOfFileToken, getLeadingComments(node.endOfFileToken));
|
||||
}
|
||||
|
||||
// Transformation nodes
|
||||
|
||||
function emitPartiallyEmittedExpression(node: PartiallyEmittedExpression) {
|
||||
emitExpression(node.expression);
|
||||
}
|
||||
|
||||
function emitLexicalEnvironment(declarations: Statement[], newLine: boolean) {
|
||||
@ -2217,9 +2232,9 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function writeTokenNode(node: Node) {
|
||||
if (node) {
|
||||
emitStart(node, shouldEmitSourceMap, shouldEmitNestedSourceMap);
|
||||
emitStart(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
|
||||
writeTokenText(node.kind);
|
||||
emitEnd(node, shouldEmitSourceMap, shouldEmitNestedSourceMap);
|
||||
emitEnd(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2400,17 +2415,6 @@ const _super = (function (geti, seti) {
|
||||
&& rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile);
|
||||
}
|
||||
|
||||
function getNotEmittedParent(node: Node): Node {
|
||||
if (getNodeEmitFlags(node) & NodeEmitFlags.EmitCommentsOfNotEmittedParent) {
|
||||
const parent = getOriginalNode(node).parent;
|
||||
if (getNodeEmitFlags(parent) & NodeEmitFlags.IsNotEmittedNode) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isUniqueName(name: string): boolean {
|
||||
return !resolver.hasGlobalName(name) &&
|
||||
!hasProperty(currentFileIdentifiers, name) &&
|
||||
|
||||
@ -6,8 +6,10 @@ namespace ts {
|
||||
getSourceMapData(): SourceMapData;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitPos(pos: number): void;
|
||||
emitStart(range: TextRange, shouldEmit?: (range: TextRange) => boolean, shouldEmitNested?: (range: TextRange) => boolean): void;
|
||||
emitEnd(range: TextRange, shouldEmit?: (range: TextRange) => boolean, shouldEmitNested?: (range: TextRange) => boolean): void;
|
||||
emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
emitStart(range: TextRange): void;
|
||||
emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
emitEnd(range: TextRange): void;
|
||||
/*@deprecated*/ changeEmitSourcePos(): void;
|
||||
/*@deprecated*/ stopOverridingSpan(): void;
|
||||
getText(): string;
|
||||
@ -33,8 +35,8 @@ namespace ts {
|
||||
nullSourceMapWriter = {
|
||||
getSourceMapData(): SourceMapData { return undefined; },
|
||||
setSourceFile(sourceFile: SourceFile): void { },
|
||||
emitStart(range: TextRange): void { },
|
||||
emitEnd(range: TextRange, shouldEmit?: Function, shouldEmitNested?: Function): void { },
|
||||
emitStart(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void { },
|
||||
emitEnd(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void { },
|
||||
emitPos(pos: number): void { },
|
||||
changeEmitSourcePos(): void { },
|
||||
stopOverridingSpan(): void { },
|
||||
@ -320,22 +322,26 @@ namespace ts {
|
||||
return range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1;
|
||||
}
|
||||
|
||||
function emitStart(range: TextRange, shouldEmit?: (range: TextRange) => boolean, shouldEmitNested?: (range: TextRange) => boolean) {
|
||||
if (!shouldEmit || shouldEmit(range)) {
|
||||
function emitStart(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
function emitStart(range: TextRange): void;
|
||||
function emitStart(range: TextRange | Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean) {
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>range))) {
|
||||
emitPos(getStartPos(range));
|
||||
}
|
||||
|
||||
if (shouldEmitNested && !shouldEmitNested(range)) {
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>range)) {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
function emitEnd(range: TextRange, shouldEmit?: (range: TextRange) => boolean, shouldEmitNested?: (range: TextRange) => boolean) {
|
||||
if (shouldEmitNested && !shouldEmitNested(range)) {
|
||||
function emitEnd(node: Node, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean): void;
|
||||
function emitEnd(range: TextRange): void;
|
||||
function emitEnd(range: TextRange, shouldIgnoreNodeCallback?: (node: Node) => boolean, shouldIgnoreChildrenCallback?: (node: Node) => boolean) {
|
||||
if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(<Node>range)) {
|
||||
enable();
|
||||
}
|
||||
|
||||
if (!shouldEmit || shouldEmit(range)) {
|
||||
if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(<Node>range))) {
|
||||
emitPos(range.end);
|
||||
}
|
||||
|
||||
|
||||
@ -1184,6 +1184,7 @@ namespace ts {
|
||||
function transformFunctionBody(node: FunctionLikeDeclaration) {
|
||||
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;
|
||||
|
||||
const statements: Statement[] = [];
|
||||
startLexicalEnvironment();
|
||||
@ -1198,6 +1199,7 @@ namespace ts {
|
||||
|
||||
const body = node.body;
|
||||
if (isBlock(body)) {
|
||||
statementsLocation = body.statements;
|
||||
addRange(statements, visitNodes(body.statements, visitor, isStatement));
|
||||
|
||||
// If the original body was a multi-line block, this must be a multi-line block.
|
||||
@ -1207,6 +1209,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
Debug.assert(node.kind === SyntaxKind.ArrowFunction);
|
||||
statementsLocation = body;
|
||||
|
||||
const equalsGreaterThanToken = (<ArrowFunction>node).equalsGreaterThanToken;
|
||||
if (!nodeIsSynthesized(equalsGreaterThanToken) && !nodeIsSynthesized(body)) {
|
||||
@ -1232,7 +1235,7 @@ namespace ts {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
const block = createBlock(statements, node.body, multiLine);
|
||||
const block = createBlock(createNodeArray(statements, statementsLocation), node.body, multiLine);
|
||||
if (!multiLine && singleLine) {
|
||||
setNodeEmitFlags(block, NodeEmitFlags.SingleLine);
|
||||
}
|
||||
@ -1505,27 +1508,6 @@ namespace ts {
|
||||
*/
|
||||
function visitForOfStatement(node: ForOfStatement): VisitResult<Statement> {
|
||||
return convertIterationStatementBodyIfNecessary(node, convertForOfToFor);
|
||||
// debugger;
|
||||
// const statementOrStatements = convertIterationStatementBodyIfNecessary(node);
|
||||
// const lastStatement = isArray(statementOrStatements) ? lastOrUndefined(statementOrStatements) : statementOrStatements;
|
||||
// const loop = lastStatement.kind === SyntaxKind.LabeledStatement
|
||||
// ? (<LabeledStatement>lastStatement).statement
|
||||
// : lastStatement;
|
||||
|
||||
// Debug.assert(loop.kind === SyntaxKind.ForOfStatement);
|
||||
|
||||
// const statement =
|
||||
// lastStatement.kind === SyntaxKind.LabeledStatement
|
||||
// ? createLabel((<LabeledStatement>lastStatement).label, convertForOfToFor(<ForOfStatement>loop))
|
||||
// : convertForOfToFor(<ForOfStatement>loop);
|
||||
|
||||
// if (isArray(statementOrStatements)) {
|
||||
// statementOrStatements[statementOrStatements.length - 1] = statement;
|
||||
// return statementOrStatements;
|
||||
// }
|
||||
// else {
|
||||
// return statement;
|
||||
// }
|
||||
}
|
||||
|
||||
function convertForOfToFor(node: ForOfStatement, convertedLoopBodyStatements: Statement[]): ForStatement {
|
||||
|
||||
@ -41,8 +41,6 @@ namespace ts {
|
||||
let currentNamespace: ModuleDeclaration;
|
||||
let currentNamespaceLocalName: Identifier;
|
||||
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
|
||||
let currentParent: Node;
|
||||
let currentNode: Node;
|
||||
|
||||
/**
|
||||
* Keeps track of whether expression substitution has been enabled for specific edge cases.
|
||||
@ -97,8 +95,6 @@ namespace ts {
|
||||
function saveStateAndInvoke<T>(node: Node, f: (node: Node) => T): T {
|
||||
// Save state
|
||||
const savedCurrentScope = currentScope;
|
||||
const savedCurrentParent = currentParent;
|
||||
const savedCurrentNode = currentNode;
|
||||
|
||||
// Handle state changes before visiting a node.
|
||||
onBeforeVisitNode(node);
|
||||
@ -107,8 +103,6 @@ namespace ts {
|
||||
|
||||
// Restore state
|
||||
currentScope = savedCurrentScope;
|
||||
currentParent = savedCurrentParent;
|
||||
currentNode = savedCurrentNode;
|
||||
|
||||
return visited;
|
||||
}
|
||||
@ -215,7 +209,9 @@ namespace ts {
|
||||
function visitTypeScript(node: Node): VisitResult<Node> {
|
||||
if (hasModifier(node, ModifierFlags.Ambient)) {
|
||||
// TypeScript ambient declarations are elided.
|
||||
return undefined;
|
||||
return isStatement(node)
|
||||
? createNotEmittedStatement(node)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
@ -261,9 +257,8 @@ namespace ts {
|
||||
case SyntaxKind.Decorator:
|
||||
// TypeScript decorators are elided. They will be emitted as part of transformClassDeclaration.
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
// TypeScript type-only declarations are elided
|
||||
// TypeScript type-only declarations are elided.
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
// TypeScript property declarations are elided.
|
||||
@ -272,6 +267,10 @@ namespace ts {
|
||||
// TypeScript constructors are transformed in `transformClassDeclaration`.
|
||||
return undefined;
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
// TypeScript interfaces are elided, but pinned comments are preserved.
|
||||
return createNotEmittedStatement(node);
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
// This is a class declaration with TypeScript syntax extensions.
|
||||
//
|
||||
@ -376,7 +375,7 @@ namespace ts {
|
||||
|
||||
default:
|
||||
Debug.failBadSyntaxKind(node);
|
||||
return undefined;
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,9 +385,6 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function onBeforeVisitNode(node: Node) {
|
||||
currentParent = currentNode;
|
||||
currentNode = node;
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.CaseBlock:
|
||||
@ -675,9 +671,9 @@ namespace ts {
|
||||
const expressions: Expression[] = [];
|
||||
const temp = createTempVariable();
|
||||
hoistVariableDeclaration(temp);
|
||||
addNode(expressions, createAssignment(temp, classExpression));
|
||||
addNodes(expressions, generateInitializedPropertyExpressions(node, staticProperties, temp));
|
||||
addNode(expressions, temp);
|
||||
addNode(expressions, createAssignment(temp, classExpression), true);
|
||||
addNodes(expressions, generateInitializedPropertyExpressions(node, staticProperties, temp), true);
|
||||
addNode(expressions, temp, true);
|
||||
return inlineExpressions(expressions);
|
||||
}
|
||||
|
||||
@ -1790,13 +1786,12 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Determines whether to emit a function-like declaration. We should not emit the
|
||||
* declaration if it is an overload, is abstract, or is an ambient declaration.
|
||||
* declaration if it does not have a body.
|
||||
*
|
||||
* @param node The declaration node.
|
||||
*/
|
||||
function shouldEmitFunctionLikeDeclaration(node: FunctionLikeDeclaration) {
|
||||
return !nodeIsMissing(node.body)
|
||||
&& !hasModifier(node, ModifierFlags.Abstract | ModifierFlags.Ambient);
|
||||
return !nodeIsMissing(node.body);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1829,12 +1824,12 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Determines whether to emit an accessor declaration. We should not emit the
|
||||
* declaration if it is abstract or is an ambient declaration.
|
||||
* declaration if it does not have a body and is abstract.
|
||||
*
|
||||
* @param node The declaration node.
|
||||
*/
|
||||
function shouldEmitAccessorDeclaration(node: AccessorDeclaration) {
|
||||
return !hasModifier(node, ModifierFlags.Abstract | ModifierFlags.Ambient);
|
||||
return !(nodeIsMissing(node.body) && hasModifier(node, ModifierFlags.Abstract));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1894,7 +1889,7 @@ namespace ts {
|
||||
*/
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return undefined;
|
||||
return createNotEmittedStatement(node);
|
||||
}
|
||||
|
||||
const func = createFunctionDeclaration(
|
||||
@ -1926,6 +1921,7 @@ namespace ts {
|
||||
function visitFunctionExpression(node: FunctionExpression) {
|
||||
if (nodeIsMissing(node.body)) {
|
||||
return createNode(SyntaxKind.OmittedExpression);
|
||||
// return createOmittedExpression(/*location*/ node);
|
||||
}
|
||||
|
||||
return createFunctionExpression(
|
||||
@ -2135,50 +2131,34 @@ namespace ts {
|
||||
* @param node The parenthesized expression node.
|
||||
*/
|
||||
function visitParenthesizedExpression(node: ParenthesizedExpression): Expression {
|
||||
// Make sure we consider all nested cast expressions, e.g.:
|
||||
// (<any><number><any>-A).x;
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
if (currentParent.kind !== SyntaxKind.ArrowFunction) {
|
||||
// We have an expression of the form: (<Type>SubExpr)
|
||||
// Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is.
|
||||
// Omitting the parentheses, however, could cause change in the semantics of the generated
|
||||
// code if the casted expression has a lower precedence than the rest of the expression, e.g.:
|
||||
// (<any>new A).foo should be emitted as (new A).foo and not new A.foo
|
||||
// (<any>typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString()
|
||||
// new (<any>A()) should be emitted as new (A()) and not new A()
|
||||
// (<any>function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} ()
|
||||
if (expression.kind !== SyntaxKind.PrefixUnaryExpression &&
|
||||
expression.kind !== SyntaxKind.VoidExpression &&
|
||||
expression.kind !== SyntaxKind.TypeOfExpression &&
|
||||
expression.kind !== SyntaxKind.DeleteExpression &&
|
||||
expression.kind !== SyntaxKind.PostfixUnaryExpression &&
|
||||
expression.kind !== SyntaxKind.NewExpression &&
|
||||
!(expression.kind === SyntaxKind.CallExpression && currentParent.kind === SyntaxKind.NewExpression) &&
|
||||
!(expression.kind === SyntaxKind.FunctionExpression && currentParent.kind === SyntaxKind.CallExpression) &&
|
||||
!(expression.kind === SyntaxKind.NumericLiteral && currentParent.kind === SyntaxKind.PropertyAccessExpression)) {
|
||||
return trackChildOfNotEmittedNode(node, expression, node.expression);
|
||||
}
|
||||
const innerExpression = skipOuterExpressions(node.expression, ~OuterExpressionKinds.Assertions);
|
||||
if (isAssertionExpression(innerExpression)) {
|
||||
// Make sure we consider all nested cast expressions, e.g.:
|
||||
// (<any><number><any>-A).x;
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
|
||||
// We have an expression of the form: (<Type>SubExpr). Emitting this as (SubExpr)
|
||||
// is really not desirable. We would like to emit the subexpression as-is. Omitting
|
||||
// the parentheses, however, could cause change in the semantics of the generated
|
||||
// code if the casted expression has a lower precedence than the rest of the
|
||||
// expression.
|
||||
//
|
||||
// Due to the auto-parenthesization rules used by the visitor and factory functions
|
||||
// we can safely elide the parentheses here, as a new synthetic
|
||||
// ParenthesizedExpression will be inserted if we remove parentheses too
|
||||
// aggressively.
|
||||
//
|
||||
// To preserve comments, we return a "PartiallyEmittedExpression" here which will
|
||||
// preserve the position information of the original expression.
|
||||
return createPartiallyEmittedExpression(expression, node);
|
||||
}
|
||||
|
||||
return setOriginalNode(
|
||||
createParen(expression, node),
|
||||
node
|
||||
);
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function visitAssertionExpression(node: AssertionExpression): Expression {
|
||||
const expression = visitNode((<TypeAssertion | AsExpression>node).expression, visitor, isExpression);
|
||||
return trackChildOfNotEmittedNode(node, expression, node.expression);
|
||||
}
|
||||
|
||||
function trackChildOfNotEmittedNode<T extends Node>(parent: Node, child: T, original: T) {
|
||||
if (!child.parent && !child.original) {
|
||||
child = getMutableClone(child);
|
||||
}
|
||||
|
||||
setNodeEmitFlags(parent, NodeEmitFlags.IsNotEmittedNode);
|
||||
setNodeEmitFlags(child, NodeEmitFlags.EmitCommentsOfNotEmittedParent);
|
||||
return child;
|
||||
return createPartiallyEmittedExpression(expression, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2380,7 +2360,7 @@ namespace ts {
|
||||
*/
|
||||
function visitModuleDeclaration(node: ModuleDeclaration): VisitResult<Statement> {
|
||||
if (!shouldEmitModuleDeclaration(node)) {
|
||||
return undefined;
|
||||
return createNotEmittedStatement(node);
|
||||
}
|
||||
|
||||
Debug.assert(isIdentifier(node.name), "TypeScript module should have an Identifier name.");
|
||||
|
||||
@ -344,6 +344,10 @@ namespace ts {
|
||||
// Synthesized list
|
||||
SyntaxList,
|
||||
|
||||
// Transformation nodes
|
||||
NotEmittedStatement,
|
||||
PartiallyEmittedExpression,
|
||||
|
||||
// Enum value count
|
||||
Count,
|
||||
// Markers
|
||||
@ -723,6 +727,13 @@ namespace ts {
|
||||
_indexSignatureDeclarationBrand: any;
|
||||
}
|
||||
|
||||
// Represents a member of a class element or object literal that is elided as part of a
|
||||
// transformation to emit comments on a not-emitted node.
|
||||
// @internal
|
||||
// @kind(SyntaxKind.NotEmittedMember)
|
||||
export interface NotEmittedMember extends ClassElement, ObjectLiteralElement {
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.AnyKeyword)
|
||||
// @kind(SyntaxKind.NumberKeyword)
|
||||
// @kind(SyntaxKind.BooleanKeyword)
|
||||
@ -823,6 +834,14 @@ namespace ts {
|
||||
// @kind(SyntaxKind.OmittedExpression)
|
||||
export interface OmittedExpression extends Expression { }
|
||||
|
||||
// Represents an expression that is elided as part of a transformation to emit comments on a
|
||||
// not-emitted node. The 'expression' property of a NotEmittedExpression should be emitted.
|
||||
// @internal
|
||||
// @kind(SyntaxKind.NotEmittedExpression)
|
||||
export interface PartiallyEmittedExpression extends LeftHandSideExpression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface UnaryExpression extends Expression {
|
||||
_unaryExpressionBrand: any;
|
||||
}
|
||||
@ -1099,6 +1118,13 @@ namespace ts {
|
||||
_statementBrand: any;
|
||||
}
|
||||
|
||||
// Represents a statement that is elided as part of a transformation to emit comments on a
|
||||
// not-emitted node.
|
||||
// @internal
|
||||
// @kind(SyntaxKind.NotEmittedStatement)
|
||||
export interface NotEmittedStatement extends Statement {
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.EmptyStatement)
|
||||
export interface EmptyStatement extends Statement { }
|
||||
|
||||
@ -2850,13 +2876,11 @@ namespace ts {
|
||||
NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node, this is primarily used when printing a SystemJS module.
|
||||
SingleLine = 1 << 6, // The contents of this node should be emit on a single line.
|
||||
AdviseOnEmitNode = 1 << 7, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
|
||||
IsNotEmittedNode = 1 << 8, // Is a node that is not emitted but whose comments should be preserved if possible.
|
||||
EmitCommentsOfNotEmittedParent = 1 << 9, // Emits comments of missing parent nodes.
|
||||
NoSubstitution = 1 << 10, // Disables further substitution of an expression.
|
||||
CapturesThis = 1 << 11, // The function captures a lexical `this`
|
||||
NoSourceMap = 1 << 12, // Do not emit a source map location for this node.
|
||||
NoNestedSourceMaps = 1 << 13, // Do not emit source map locations for children of this node.
|
||||
PrefixExportedLocal = 1 << 14,
|
||||
NoSubstitution = 1 << 8, // Disables further substitution of an expression.
|
||||
CapturesThis = 1 << 9, // The function captures a lexical `this`
|
||||
NoSourceMap = 1 << 10, // Do not emit a source map location for this node.
|
||||
NoNestedSourceMaps = 1 << 11, // Do not emit source map locations for children of this node.
|
||||
PrefixExportedLocal = 1 << 12,
|
||||
}
|
||||
|
||||
/** Additional context provided to `visitEachChild` */
|
||||
|
||||
@ -3274,8 +3274,7 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
}
|
||||
|
||||
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
|
||||
const kind = node.kind;
|
||||
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
|
||||
return kind === SyntaxKind.PropertyAccessExpression
|
||||
|| kind === SyntaxKind.ElementAccessExpression
|
||||
|| kind === SyntaxKind.NewExpression
|
||||
@ -3301,8 +3300,11 @@ namespace ts {
|
||||
|| kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
export function isUnaryExpression(node: Node): node is UnaryExpression {
|
||||
const kind = node.kind;
|
||||
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
|
||||
return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind);
|
||||
}
|
||||
|
||||
function isUnaryExpressionKind(kind: SyntaxKind): boolean {
|
||||
return kind === SyntaxKind.PrefixUnaryExpression
|
||||
|| kind === SyntaxKind.PostfixUnaryExpression
|
||||
|| kind === SyntaxKind.DeleteExpression
|
||||
@ -3310,11 +3312,14 @@ namespace ts {
|
||||
|| kind === SyntaxKind.VoidExpression
|
||||
|| kind === SyntaxKind.AwaitExpression
|
||||
|| kind === SyntaxKind.TypeAssertionExpression
|
||||
|| isLeftHandSideExpression(node);
|
||||
|| isLeftHandSideExpressionKind(kind);
|
||||
}
|
||||
|
||||
export function isExpression(node: Node): node is Expression {
|
||||
const kind = node.kind;
|
||||
export function isUnaryExpression(node: Node): node is UnaryExpression {
|
||||
return isUnaryExpressionKind(skipPartiallyEmittedExpressions(node).kind);
|
||||
}
|
||||
|
||||
function isExpressionKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.ConditionalExpression
|
||||
|| kind === SyntaxKind.YieldExpression
|
||||
|| kind === SyntaxKind.ArrowFunction
|
||||
@ -3322,7 +3327,31 @@ namespace ts {
|
||||
|| kind === SyntaxKind.SpreadElementExpression
|
||||
|| kind === SyntaxKind.AsExpression
|
||||
|| kind === SyntaxKind.OmittedExpression
|
||||
|| isUnaryExpression(node);
|
||||
|| isUnaryExpressionKind(kind);
|
||||
}
|
||||
|
||||
export function isExpression(node: Node): node is Expression {
|
||||
return isExpressionKind(skipPartiallyEmittedExpressions(node).kind);
|
||||
}
|
||||
|
||||
export function isAssertionExpression(node: Node): node is AssertionExpression {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.TypeAssertionExpression
|
||||
|| kind === SyntaxKind.AsExpression;
|
||||
}
|
||||
|
||||
export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression {
|
||||
return node.kind === SyntaxKind.PartiallyEmittedExpression;
|
||||
}
|
||||
|
||||
export function isNotEmittedStatement(node: Node): node is NotEmittedMember | NotEmittedStatement {
|
||||
return node.kind === SyntaxKind.NotEmittedStatement;
|
||||
}
|
||||
|
||||
export function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedMember | NotEmittedStatement | PartiallyEmittedExpression {
|
||||
const kind = node.kind;
|
||||
return isNotEmittedStatement(node)
|
||||
|| isPartiallyEmittedExpression(node);
|
||||
}
|
||||
|
||||
// Misc
|
||||
@ -3455,7 +3484,8 @@ namespace ts {
|
||||
|| kind === SyntaxKind.TryStatement
|
||||
|| kind === SyntaxKind.VariableStatement
|
||||
|| kind === SyntaxKind.WhileStatement
|
||||
|| kind === SyntaxKind.WithStatement;
|
||||
|| kind === SyntaxKind.WithStatement
|
||||
|| kind === SyntaxKind.NotEmittedStatement;
|
||||
}
|
||||
|
||||
export function isDeclaration(node: Node): node is Declaration {
|
||||
|
||||
@ -437,6 +437,10 @@ namespace ts {
|
||||
[SyntaxKind.SourceFile]: [
|
||||
{ name: "statements", test: isStatement },
|
||||
],
|
||||
[SyntaxKind.NotEmittedStatement]: [],
|
||||
[SyntaxKind.PartiallyEmittedExpression]: [
|
||||
{ name: "expression", test: isExpression }
|
||||
]
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -2245,8 +2245,7 @@ namespace FourSlash {
|
||||
|
||||
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
|
||||
if (diagnostics.length > 0) {
|
||||
throw new Error(`Error compiling ${fileName}: ` +
|
||||
diagnostics.map(e => ts.flattenDiagnosticMessageText(e.messageText, Harness.IO.newLine())).join("\r\n"));
|
||||
throw new Error(`Error compiling ${fileName}: ${diagnostics.map(e => ts.flattenDiagnosticMessageText(e.messageText, Harness.IO.newLine())).join("\r\n")}`);
|
||||
}
|
||||
|
||||
program.emit(sourceFile);
|
||||
|
||||
@ -3,4 +3,5 @@ export declare module "M" { }
|
||||
|
||||
//// [ambientExternalModuleInsideNonAmbientExternalModule.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
"use strict";
|
||||
});
|
||||
|
||||
@ -7,4 +7,5 @@ export declare module M { }
|
||||
|
||||
//// [ambientInsideNonAmbientExternalModule.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
"use strict";
|
||||
});
|
||||
|
||||
@ -21,6 +21,6 @@ var b = a;
|
||||
var b = a.b;
|
||||
var b = a.b.c;
|
||||
var b = a.b().c;
|
||||
var b = (new a);
|
||||
var b = (new a.b);
|
||||
var b = new a;
|
||||
var b = new a.b;
|
||||
var b = (new a).b;
|
||||
|
||||
@ -3,5 +3,4 @@ var v = class C {};
|
||||
|
||||
//// [classExpressionES61.js]
|
||||
var v = class C {
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
@ -6,5 +6,4 @@ var v = class C extends D {};
|
||||
class D {
|
||||
}
|
||||
var v = class C extends D {
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
@ -11,20 +11,17 @@ let C = class extends class extends class {
|
||||
constructor() {
|
||||
this.a = 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
} {
|
||||
constructor(...args_1) {
|
||||
super(...args_1);
|
||||
this.b = 2;
|
||||
}
|
||||
}
|
||||
{
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
} {
|
||||
constructor(...args_2) {
|
||||
super(...args_2);
|
||||
this.c = 3;
|
||||
}
|
||||
}
|
||||
;
|
||||
};
|
||||
let c = new C();
|
||||
c.a;
|
||||
c.b;
|
||||
|
||||
@ -3,10 +3,10 @@ var v = class C { static a = 1; static b = 2 };
|
||||
|
||||
//// [classExpressionWithStaticProperties1.js]
|
||||
var v = (_a = (function () {
|
||||
function C() {
|
||||
}
|
||||
return C;
|
||||
}()),
|
||||
function C() {
|
||||
}
|
||||
return C;
|
||||
}()),
|
||||
_a.a = 1,
|
||||
_a.b = 2,
|
||||
_a);
|
||||
|
||||
@ -3,10 +3,10 @@ var v = class C { static a = 1; static b };
|
||||
|
||||
//// [classExpressionWithStaticProperties2.js]
|
||||
var v = (_a = (function () {
|
||||
function C() {
|
||||
}
|
||||
return C;
|
||||
}()),
|
||||
function C() {
|
||||
}
|
||||
return C;
|
||||
}()),
|
||||
_a.a = 1,
|
||||
_a);
|
||||
var _a;
|
||||
|
||||
@ -3,7 +3,7 @@ var v = class C { static a = 1; static b = 2 };
|
||||
|
||||
//// [classExpressionWithStaticPropertiesES61.js]
|
||||
var v = (_a = class C {
|
||||
},
|
||||
},
|
||||
_a.a = 1,
|
||||
_a.b = 2,
|
||||
_a);
|
||||
|
||||
@ -3,7 +3,7 @@ var v = class C { static a = 1; static b };
|
||||
|
||||
//// [classExpressionWithStaticPropertiesES62.js]
|
||||
var v = (_a = class C {
|
||||
},
|
||||
},
|
||||
_a.a = 1,
|
||||
_a);
|
||||
var _a;
|
||||
|
||||
@ -319,7 +319,7 @@ var TypeScript;
|
||||
var StringHashTable = (function () {
|
||||
function StringHashTable() {
|
||||
this.itemCount = 0;
|
||||
this.table = (new BlockIntrinsics());
|
||||
this.table = new BlockIntrinsics();
|
||||
}
|
||||
StringHashTable.prototype.getAllKeys = function () {
|
||||
var result = [];
|
||||
|
||||
@ -46,6 +46,7 @@ System.register([], function (exports_1, context_1) {
|
||||
});
|
||||
//// [file2.js]
|
||||
System.register([], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
return {
|
||||
setters: [],
|
||||
@ -55,6 +56,7 @@ System.register([], function (exports_1, context_1) {
|
||||
});
|
||||
//// [file3.js]
|
||||
System.register([], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
return {
|
||||
setters: [],
|
||||
@ -64,6 +66,7 @@ System.register([], function (exports_1, context_1) {
|
||||
});
|
||||
//// [file4.js]
|
||||
System.register([], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
return {
|
||||
setters: [],
|
||||
@ -73,6 +76,7 @@ System.register([], function (exports_1, context_1) {
|
||||
});
|
||||
//// [file5.js]
|
||||
System.register([], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
return {
|
||||
setters: [],
|
||||
@ -82,6 +86,7 @@ System.register([], function (exports_1, context_1) {
|
||||
});
|
||||
//// [file6.js]
|
||||
System.register([], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
return {
|
||||
setters: [],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user