diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index a680d01e102..ec7d3013a1f 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -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(range); - while (additionalRange) { - comments = concatenate( - getLeadingCommentsOfPosition(additionalRange.pos), - comments - ); - - additionalRange = getAdditionalRange(additionalRange); + function getLeadingComments(range: TextRange | Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean) { + if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(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: + // /// + // declare var x; + // /// + // 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(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(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); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index aca4091430f..d132e12e793 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -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, node.parent); if (emitOuterParens) { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index b6e3f3872c6..fd7bee61213 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -413,6 +413,11 @@ namespace ts { return node; } + export function createOmittedExpression(location?: TextRange) { + const node = createNode(SyntaxKind.OmittedExpression, location); + return node; + } + export function createExpressionWithTypeArguments(expression: Expression, location?: TextRange) { const node = 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 = 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 = 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 && (node).operatorToken.kind === SyntaxKind.PlusToken) { + if ((node).cachedLiteralKind !== undefined) { + return (node).cachedLiteralKind; + } + + const leftKind = getLiteralKindOfBinaryPlusOperand((node).left); + const literalKind = isLiteralKind(leftKind) + && leftKind === getLiteralKindOfBinaryPlusOperand((node).right) + ? leftKind + : SyntaxKind.Unknown; + + (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 (expression).arguments - ? expression + return (emittedExpression).arguments + ? 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 || (expression).arguments) - && expression.kind !== SyntaxKind.NumericLiteral) { + const emittedExpression = skipPartiallyEmittedExpressions(expression); + if (isLeftHandSideExpression(emittedExpression) + && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression).arguments) + && emittedExpression.kind !== SyntaxKind.NumericLiteral) { return 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(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 && (node).operatorToken.kind === SyntaxKind.PlusToken) { - const leftKind = getLiteralKindOfBinaryPlusOperand((node).left); - if (leftKind === getLiteralKindOfBinaryPlusOperand((node).right)) { - return leftKind; - } - } - - return SyntaxKind.Unknown; + return newInnerExpression; } function getLeftmostExpression(node: Expression): Expression { @@ -1448,17 +1516,81 @@ namespace ts { case SyntaxKind.PropertyAccessExpression: node = (node).expression; continue; + + case SyntaxKind.PartiallyEmittedExpression: + node = (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 = (node).expression; + export function parenthesizeConciseBody(body: ConciseBody): ConciseBody { + const emittedBody = skipPartiallyEmittedExpressions(body); + if (emittedBody.kind === SyntaxKind.ObjectLiteralExpression) { + return createParen(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 = (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 = (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 = (node).expression; } return node; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d6f77b6abca..aa2e10a52be 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -400,6 +400,8 @@ namespace ts { return visitNode(cbNode, (node).typeExpression); case SyntaxKind.JSDocTemplateTag: return visitNodes(cbNodes, (node).typeParameters); + case SyntaxKind.PartiallyEmittedExpression: + return visitNode(cbNode, (node).expression); } } diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 09f797b9ba0..1300ce585aa 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -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(node); // JSDoc nodes (ignored) + + // Transformation nodes (ignored) } if (isExpression(node)) { @@ -653,6 +656,10 @@ const _super = (function (geti, seti) { return emitJsxOpeningElement(node); case SyntaxKind.JsxExpression: return emitJsxExpression(node); + + // Transformation nodes + case SyntaxKind.PartiallyEmittedExpression: + return emitPartiallyEmittedExpression(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) && diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 137becb259c..d292e7a7060 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -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(range))) { emitPos(getStartPos(range)); } - if (shouldEmitNested && !shouldEmitNested(range)) { + if (shouldIgnoreChildrenCallback && shouldIgnoreChildrenCallback(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(range)) { enable(); } - if (!shouldEmit || shouldEmit(range)) { + if (!(shouldIgnoreNodeCallback && shouldIgnoreNodeCallback(range))) { emitPos(range.end); } diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index c008a754ebd..99c0876a7ee 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -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 = (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 { return convertIterationStatementBodyIfNecessary(node, convertForOfToFor); - // debugger; - // const statementOrStatements = convertIterationStatementBodyIfNecessary(node); - // const lastStatement = isArray(statementOrStatements) ? lastOrUndefined(statementOrStatements) : statementOrStatements; - // const loop = lastStatement.kind === SyntaxKind.LabeledStatement - // ? (lastStatement).statement - // : lastStatement; - - // Debug.assert(loop.kind === SyntaxKind.ForOfStatement); - - // const statement = - // lastStatement.kind === SyntaxKind.LabeledStatement - // ? createLabel((lastStatement).label, convertForOfToFor(loop)) - // : convertForOfToFor(loop); - - // if (isArray(statementOrStatements)) { - // statementOrStatements[statementOrStatements.length - 1] = statement; - // return statementOrStatements; - // } - // else { - // return statement; - // } } function convertForOfToFor(node: ForOfStatement, convertedLoopBodyStatements: Statement[]): ForStatement { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index a74ed97c3da..aa1d878faa4 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -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(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 { 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 { 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.: - // (-A).x; - const expression = visitNode(node.expression, visitor, isExpression); - if (currentParent.kind !== SyntaxKind.ArrowFunction) { - // We have an expression of the form: (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.: - // (new A).foo should be emitted as (new A).foo and not new A.foo - // (typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString() - // new (A()) should be emitted as new (A()) and not new A() - // (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.: + // (-A).x; + const expression = visitNode(node.expression, visitor, isExpression); + + // We have an expression of the form: (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((node).expression, visitor, isExpression); - return trackChildOfNotEmittedNode(node, expression, node.expression); - } - - function trackChildOfNotEmittedNode(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 { if (!shouldEmitModuleDeclaration(node)) { - return undefined; + return createNotEmittedStatement(node); } Debug.assert(isIdentifier(node.name), "TypeScript module should have an Identifier name."); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 23fb90c4437..6fc735fc72c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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` */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 21efafcc3a8..b29cdab8c33 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -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 { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 6c388c3f601..b93d8308d93 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -437,6 +437,10 @@ namespace ts { [SyntaxKind.SourceFile]: [ { name: "statements", test: isStatement }, ], + [SyntaxKind.NotEmittedStatement]: [], + [SyntaxKind.PartiallyEmittedExpression]: [ + { name: "expression", test: isExpression } + ] }; /** diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ba7a5f20dae..1905385f092 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -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); diff --git a/tests/baselines/reference/ambientExternalModuleInsideNonAmbientExternalModule.js b/tests/baselines/reference/ambientExternalModuleInsideNonAmbientExternalModule.js index 8a3e15e7c7f..bb0d3a907ae 100644 --- a/tests/baselines/reference/ambientExternalModuleInsideNonAmbientExternalModule.js +++ b/tests/baselines/reference/ambientExternalModuleInsideNonAmbientExternalModule.js @@ -3,4 +3,5 @@ export declare module "M" { } //// [ambientExternalModuleInsideNonAmbientExternalModule.js] define(["require", "exports"], function (require, exports) { + "use strict"; }); diff --git a/tests/baselines/reference/ambientInsideNonAmbientExternalModule.js b/tests/baselines/reference/ambientInsideNonAmbientExternalModule.js index 5db44bb1ce1..0e2d08ae07b 100644 --- a/tests/baselines/reference/ambientInsideNonAmbientExternalModule.js +++ b/tests/baselines/reference/ambientInsideNonAmbientExternalModule.js @@ -7,4 +7,5 @@ export declare module M { } //// [ambientInsideNonAmbientExternalModule.js] define(["require", "exports"], function (require, exports) { + "use strict"; }); diff --git a/tests/baselines/reference/castParentheses.js b/tests/baselines/reference/castParentheses.js index 936b2e7af07..feeced645e2 100644 --- a/tests/baselines/reference/castParentheses.js +++ b/tests/baselines/reference/castParentheses.js @@ -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; diff --git a/tests/baselines/reference/classExpressionES61.js b/tests/baselines/reference/classExpressionES61.js index afef0909039..eaf013acbaf 100644 --- a/tests/baselines/reference/classExpressionES61.js +++ b/tests/baselines/reference/classExpressionES61.js @@ -3,5 +3,4 @@ var v = class C {}; //// [classExpressionES61.js] var v = class C { -} -; +}; diff --git a/tests/baselines/reference/classExpressionES62.js b/tests/baselines/reference/classExpressionES62.js index 79cede7300d..620d86c6de2 100644 --- a/tests/baselines/reference/classExpressionES62.js +++ b/tests/baselines/reference/classExpressionES62.js @@ -6,5 +6,4 @@ var v = class C extends D {}; class D { } var v = class C extends D { -} -; +}; diff --git a/tests/baselines/reference/classExpressionES63.js b/tests/baselines/reference/classExpressionES63.js index 6b3a06cf7c3..7bb41817079 100644 --- a/tests/baselines/reference/classExpressionES63.js +++ b/tests/baselines/reference/classExpressionES63.js @@ -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; diff --git a/tests/baselines/reference/classExpressionWithStaticProperties1.js b/tests/baselines/reference/classExpressionWithStaticProperties1.js index 23d18d76766..1ede417f980 100644 --- a/tests/baselines/reference/classExpressionWithStaticProperties1.js +++ b/tests/baselines/reference/classExpressionWithStaticProperties1.js @@ -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); diff --git a/tests/baselines/reference/classExpressionWithStaticProperties2.js b/tests/baselines/reference/classExpressionWithStaticProperties2.js index b9fc0345591..bdd6016d49d 100644 --- a/tests/baselines/reference/classExpressionWithStaticProperties2.js +++ b/tests/baselines/reference/classExpressionWithStaticProperties2.js @@ -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; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js index 43f5e7415c4..f81e35fd822 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js @@ -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); diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js index 1efa56ecaa2..222d8af2521 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js @@ -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; diff --git a/tests/baselines/reference/parserRealSource4.js b/tests/baselines/reference/parserRealSource4.js index c06bd191fb5..39d17fb6ef4 100644 --- a/tests/baselines/reference/parserRealSource4.js +++ b/tests/baselines/reference/parserRealSource4.js @@ -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 = []; diff --git a/tests/baselines/reference/systemModuleAmbientDeclarations.js b/tests/baselines/reference/systemModuleAmbientDeclarations.js index 526454166ae..9714f138c5e 100644 --- a/tests/baselines/reference/systemModuleAmbientDeclarations.js +++ b/tests/baselines/reference/systemModuleAmbientDeclarations.js @@ -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: [],