diff --git a/src/compat/factory.ts b/src/compat/factory.ts index 39e3d313541..b2603b98454 100644 --- a/src/compat/factory.ts +++ b/src/compat/factory.ts @@ -284,17 +284,6 @@ namespace ts { updateBundle, createImmediatelyInvokedFunctionExpression, createImmediatelyInvokedArrowFunction, - createComma, - createLessThan, - createAssignment, - createStrictEquality, - createStrictInequality, - createAdd, - createSubtract, - createPostfixIncrement, - createLogicalAnd, - createLogicalOr, - createLogicalNot, createVoidZero, createExportDefault, createExternalModuleExport @@ -488,4 +477,379 @@ namespace ts { export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: readonly TypeNode[] | undefined, expression: Expression) { return factory.updateExpressionWithTypeArguments(node, expression, typeArguments); } + + export function createComma(left: Expression, right: Expression): Expression { + return factory.createComma(left, right); + } + + export function createLessThan(left: Expression, right: Expression): Expression { + return factory.createLessThan(left, right); + } + + export function createAssignment(left: Expression, right: Expression): BinaryExpression { + return factory.createAssignment(left, right); + } + + export function createStrictEquality(left: Expression, right: Expression): BinaryExpression { + return factory.createStrictEquality(left, right); + } + + export function createStrictInequality(left: Expression, right: Expression): BinaryExpression { + return factory.createStrictInequality(left, right); + } + + export function createAdd(left: Expression, right: Expression): BinaryExpression { + return factory.createAdd(left, right); + } + + export function createSubtract(left: Expression, right: Expression): BinaryExpression { + return factory.createSubtract(left, right); + } + + export function createLogicalAnd(left: Expression, right: Expression): BinaryExpression { + return factory.createLogicalAnd(left, right); + } + + export function createLogicalOr(left: Expression, right: Expression): BinaryExpression { + return factory.createLogicalOr(left, right); + } + + export function createPostfixIncrement(operand: Expression): PostfixUnaryExpression { + return factory.createPostfixIncrement(operand); + } + + export function createLogicalNot(operand: Expression): PrefixUnaryExpression { + return factory.createLogicalNot(operand); + } + + Debug.deprecateProperties(ts, [ + "createNodeArray", + "createNumericLiteral", + "createBigIntLiteral", + "createStringLiteral", + "createStringLiteralFromNode", + "createRegularExpressionLiteral", + "createLoopVariable", + "createUniqueName", + "createOptimisticUniqueName", + "createFileLevelUniqueName", + "createToken", + "createSuper", + "createThis", + "createNull", + "createTrue", + "createFalse", + "createModifier", + "createModifiersFromModifierFlags", + "createQualifiedName", + "updateQualifiedName", + "createComputedPropertyName", + "updateComputedPropertyName", + "createTypeParameterDeclaration", + "updateTypeParameterDeclaration", + "createDecorator", + "updateDecorator", + "createCallSignature", + "updateCallSignature", + "createConstructSignature", + "updateConstructSignature", + "updateIndexSignature", + "createKeywordTypeNode", + "createTypePredicateNode", + "updateTypePredicateNode", + "createTypeReferenceNode", + "updateTypeReferenceNode", + "createFunctionTypeNode", + "updateFunctionTypeNode", + "createConstructorTypeNode", + "updateConstructorTypeNode", + "createTypeQueryNode", + "updateTypeQueryNode", + "createTypeLiteralNode", + "updateTypeLiteralNode", + "createArrayTypeNode", + "updateArrayTypeNode", + "createTupleTypeNode", + "updateTupleTypeNode", + "createOptionalTypeNode", + "updateOptionalTypeNode", + "createRestTypeNode", + "updateRestTypeNode", + "createUnionTypeNode", + "updateUnionTypeNode", + "createIntersectionTypeNode", + "updateIntersectionTypeNode", + "createConditionalTypeNode", + "updateConditionalTypeNode", + "createInferTypeNode", + "updateInferTypeNode", + "createImportTypeNode", + "updateImportTypeNode", + "createParenthesizedType", + "updateParenthesizedType", + "createThisTypeNode", + "updateTypeOperatorNode", + "createIndexedAccessTypeNode", + "updateIndexedAccessTypeNode", + "createMappedTypeNode", + "updateMappedTypeNode", + "createLiteralTypeNode", + "updateLiteralTypeNode", + "createObjectBindingPattern", + "updateObjectBindingPattern", + "createArrayBindingPattern", + "updateArrayBindingPattern", + "createBindingElement", + "updateBindingElement", + "updateArrayLiteral", + "createObjectLiteral", + "updateObjectLiteral", + "createPropertyAccess", + "updatePropertyAccess", + "createElementAccess", + "updateElementAccess", + "createCall", + "updateCall", + "createNew", + "updateNew", + "createTypeAssertion", + "updateTypeAssertion", + "createParen", + "updateParen", + "createFunctionExpression", + "updateFunctionExpression", + "createArrowFunction", + "updateArrowFunction", + "createDelete", + "updateDelete", + "createTypeOf", + "updateTypeOf", + "createVoid", + "updateVoid", + "createAwait", + "updateAwait", + "createPrefix", + "updatePrefix", + "createPostfix", + "updatePostfix", + "createBinary", + "updateBinary", + "updateConditional", + "createTemplateExpression", + "updateTemplateExpression", + "createTemplateHead", + "createTemplateMiddle", + "createTemplateTail", + "createNoSubstitutionTemplateLiteral", + "updateYield", + "createSpread", + "updateSpread", + "createOmittedExpression", + "createAsExpression", + "updateAsExpression", + "createNonNullExpression", + "updateNonNullExpression", + "createMetaProperty", + "updateMetaProperty", + "createTemplateSpan", + "updateTemplateSpan", + "createSemicolonClassElement", + "createBlock", + "updateBlock", + "createVariableStatement", + "updateVariableStatement", + "createEmptyStatement", + "createExpressionStatement", + "updateExpressionStatement", + "createIf", + "updateIf", + "createDo", + "updateDo", + "createWhile", + "updateWhile", + "createFor", + "updateFor", + "createForIn", + "updateForIn", + "createForOf", + "updateForOf", + "createContinue", + "updateContinue", + "createBreak", + "updateBreak", + "createReturn", + "updateReturn", + "createWith", + "updateWith", + "createSwitch", + "updateSwitch", + "createLabel", + "updateLabel", + "createThrow", + "updateThrow", + "createTry", + "updateTry", + "createDebuggerStatement", + "createVariableDeclaration", + "updateVariableDeclaration", + "createVariableDeclarationList", + "updateVariableDeclarationList", + "createFunctionDeclaration", + "updateFunctionDeclaration", + "createClassDeclaration", + "updateClassDeclaration", + "createInterfaceDeclaration", + "updateInterfaceDeclaration", + "createTypeAliasDeclaration", + "updateTypeAliasDeclaration", + "createEnumDeclaration", + "updateEnumDeclaration", + "createModuleDeclaration", + "updateModuleDeclaration", + "createModuleBlock", + "updateModuleBlock", + "createCaseBlock", + "updateCaseBlock", + "createNamespaceExportDeclaration", + "updateNamespaceExportDeclaration", + "createImportEqualsDeclaration", + "updateImportEqualsDeclaration", + "createImportDeclaration", + "updateImportDeclaration", + "createImportClause", + "updateImportClause", + "createNamespaceImport", + "updateNamespaceImport", + "createNamedImports", + "updateNamedImports", + "createImportSpecifier", + "updateImportSpecifier", + "createExportAssignment", + "updateExportAssignment", + "createExportDeclaration", + "updateExportDeclaration", + "createNamedExports", + "updateNamedExports", + "createExportSpecifier", + "updateExportSpecifier", + "createExternalModuleReference", + "updateExternalModuleReference", + "createJSDocTypeExpression", + "createJSDocTypeTag", + "createJSDocReturnTag", + "createJSDocThisTag", + "createJSDocComment", + "createJsxElement", + "updateJsxElement", + "createJsxSelfClosingElement", + "updateJsxSelfClosingElement", + "createJsxOpeningElement", + "updateJsxOpeningElement", + "createJsxClosingElement", + "updateJsxClosingElement", + "createJsxFragment", + "createJsxText", + "updateJsxText", + "createJsxOpeningFragment", + "createJsxJsxClosingFragment", + "updateJsxFragment", + "createJsxAttribute", + "updateJsxAttribute", + "createJsxAttributes", + "updateJsxAttributes", + "createJsxSpreadAttribute", + "updateJsxSpreadAttribute", + "createJsxExpression", + "updateJsxExpression", + "createCaseClause", + "updateCaseClause", + "createDefaultClause", + "updateDefaultClause", + "createHeritageClause", + "updateHeritageClause", + "createCatchClause", + "updateCatchClause", + "createPropertyAssignment", + "updatePropertyAssignment", + "createShorthandPropertyAssignment", + "updateShorthandPropertyAssignment", + "createSpreadAssignment", + "updateSpreadAssignment", + "createEnumMember", + "updateEnumMember", + "createNotEmittedStatement", + "createEndOfDeclarationMarker", + "createMergeDeclarationMarker", + "createPartiallyEmittedExpression", + "updatePartiallyEmittedExpression", + "createCommaList", + "updateCommaList", + "createBundle", + "updateBundle", + "createImmediatelyInvokedFunctionExpression", + "createImmediatelyInvokedArrowFunction", + "createVoidZero", + "createExportDefault", + "createExternalModuleExport", + "createIdentifier", + "createTempVariable", + "getGeneratedNameForNode", + "createIndexSignature", + "createMethodSignature", + "updateMethodSignature", + "createTypeOperatorNode", + "createTaggedTemplate", + "updateTaggedTemplate", + "createConditional", + "createYield", + "createClassExpression", + "updateClassExpression", + "createPropertySignature", + "updatePropertySignature", + "createExpressionWithTypeArguments", + "updateExpressionWithTypeArguments", + "createComma", + "createLessThan", + "createAssignment", + "createStrictEquality", + "createStrictInequality", + "createAdd", + "createSubtract", + "createLogicalAnd", + "createLogicalOr", + "createPostfixIncrement", + "createLogicalNot", + "createArrayLiteral", + ], { + message: "Please use `factory.{0}` or the factory supplied by your transformation context instead." + }); + + Debug.deprecateProperties(ts, [ + "createParameter", + "updateParameter", + "createProperty", + "updateProperty", + "createMethod", + "updateMethod", + "createConstructor", + "updateConstructor", + "createGetAccessor", + "updateGetAccessor", + "createSetAccessor", + "updateSetAccessor", + ], { + message: "Please use `factory.{0}Declaration` or the factory supplied by your transformation context instead." + }); + + Debug.deprecateProperty(ts, "createStatement", { + message: "Please use `factory.createExpressionStatement` or the factory supplied by your transformation context instead." + }); + + Debug.deprecateProperty(ts, "updateStatement", { + message: "Please use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead." + }); + + Debug.deprecateProperty(ts, "updateSourceFileNode", { + message: "Please use `factory.updateSourceFile` or the factory supplied by your transformation context instead." + }); } \ No newline at end of file diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 264506e13a3..d9feb5988aa 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -35,11 +35,6 @@ namespace ts { entries(): Iterator<[string, T]>; } - export interface MapConstructor { - // tslint:disable-next-line:callable-types - new (): Map; - } - /** ES6 Map interface. */ export interface Map extends ReadonlyMap { set(key: string, value: T): this; @@ -47,6 +42,11 @@ namespace ts { clear(): void; } + export interface MapConstructor { + // tslint:disable-next-line:callable-types + new (): Map; + } + /** ES6 Iterator type. */ export interface Iterator { next(): { value: T, done?: false } | { value: never, done: true }; diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index b8e9869d6bf..ee2b233b444 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -1,8 +1,61 @@ /* @internal */ namespace ts { + export enum LogLevel { + Off, + Error, + Warning, + Info, + Verbose + } + + export interface LoggingHost { + log(level: LogLevel, s: string): void; + } + + export interface DeprecationOptions { + message?: string; + error?: boolean; + since?: string; + until?: string; + } + export namespace Debug { export let currentAssertionLevel = AssertionLevel.None; + export let currentLogLevel = LogLevel.Warning; export let isDebugging = false; + export let loggingHost: LoggingHost | undefined; + + export function shouldLog(level: LogLevel): boolean { + return currentLogLevel <= level; + } + + function logMessage(level: LogLevel, s: string): void { + if (loggingHost && shouldLog(level)) { + loggingHost.log(level, s); + } + } + + export function log(s: string): void { + logMessage(LogLevel.Info, s); + } + + export namespace log { + export function error(s: string): void { + logMessage(LogLevel.Error, s); + } + + export function warn(s: string): void { + logMessage(LogLevel.Warning, s); + } + + export function log(s: string): void { + logMessage(LogLevel.Info, s); + } + + export function trace(s: string): void { + logMessage(LogLevel.Verbose, s); + } + } export function shouldAssert(level: AssertionLevel): boolean { return currentAssertionLevel >= level; @@ -68,12 +121,13 @@ namespace ts { return fail(`${message} ${detail}`, stackCrawlMark || assertNever); } - export function getFunctionName(func: AnyFunction) { + export function getFunctionName(func: AnyFunction): string { if (typeof func !== "function") { return ""; } else if (func.hasOwnProperty("name")) { - return (func).name; + const name = (func).name || ""; + return "" + name; } else { const text = Function.prototype.toString.call(func); @@ -258,5 +312,64 @@ namespace ts { isDebugInfoEnabled = true; } + + export function createDeprecation(name: string, options: DeprecationOptions & { error: true }): () => never; + export function createDeprecation(name: string, options?: DeprecationOptions): () => void; + export function createDeprecation(name: string, options: DeprecationOptions = {}) { + let formattedMessage = options.error ? "DeprecationError: " : "DeprecationWarning: "; + formattedMessage += `'${name}' ${options.since ? `has been deprecated since ${options.since}` : "is deprecated"}`; + formattedMessage += options.error ? " and can no longer be used." : options.until ? ` and will no longer be usable after ${options.until}.` : "."; + formattedMessage += options.message ? ` ${formatStringFromArgs(options.message, [name], 0)}` : ""; + let hasWrittenDeprecation = false; + return handleDeprecation; + + function handleDeprecation(): void { + if (options.error) return fail(formattedMessage, handleDeprecation); + if (hasWrittenDeprecation) return; + hasWrittenDeprecation = true; + log.warn(formattedMessage); + } + } + + function wrapFunction any>(deprecation: () => void, func: F): F { + return function (this: unknown) { + deprecation(); + return func.apply(this, arguments); + } as F; + } + + function wrapAccessor(deprecation: () => void, desc: PropertyDescriptor) { + const newDesc: PropertyDescriptor = { enumerable: desc.enumerable, configurable: desc.configurable }; + if (desc.get) newDesc.get = wrapFunction(deprecation, desc.get); + if (desc.set) newDesc.set = wrapFunction(deprecation, desc.set); + return newDesc; + } + + function wrapValue(deprecation: () => void, desc: PropertyDescriptor) { + const newDesc: PropertyDescriptor = { enumerable: desc.enumerable, configurable: desc.configurable }; + let value = desc.value; + newDesc.get = () => { deprecation(); return value; }; + if (desc.writable) newDesc.set = _value => { deprecation(); value = _value; }; + return newDesc; + } + + export function deprecateProperties any>, string>>(ns: T, keys: K[], options?: DeprecationOptions) { + for (const key of keys) { + deprecateProperty(ns, key, options); + } + } + + export function deprecateProperty any>, string>>(ns: T, key: K, options?: DeprecationOptions) { + const desc = Object.getOwnPropertyDescriptor(ns, key); + if (!desc) return; + const deprecation = createDeprecation(key, options); + const newDesc = desc.get || desc.set ? wrapAccessor(deprecation, desc) : wrapValue(deprecation, desc); + Object.defineProperty(ns, key, newDesc); + } + + export function deprecateFunction any>(func: F, options?: DeprecationOptions): F { + const deprecation = createDeprecation(getFunctionName(func), options); + return wrapFunction(deprecation, func); + } } } diff --git a/src/compiler/factory/base.ts b/src/compiler/factory/baseNodeFactory.ts similarity index 100% rename from src/compiler/factory/base.ts rename to src/compiler/factory/baseNodeFactory.ts diff --git a/src/compiler/factory/converters.ts b/src/compiler/factory/nodeConverters.ts similarity index 100% rename from src/compiler/factory/converters.ts rename to src/compiler/factory/nodeConverters.ts diff --git a/src/compiler/factory/factory.ts b/src/compiler/factory/nodeFactory.ts similarity index 89% rename from src/compiler/factory/factory.ts rename to src/compiler/factory/nodeFactory.ts index 52fbb9c72c7..4c9bdafd3f6 100644 --- a/src/compiler/factory/factory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -8,9 +8,10 @@ namespace ts { // this and determine if it worthwhile to keep this optimization. let skipTransformationFlags = false; - // Defer loading the parenthesizer and node converters until they are requestd - const parenthesizer = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory)); - const getConverters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory)); + // Lazily load the parenthesizer, node converters, and some factory methods until they are used. + const lazyParenthesizer = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory)); + const lazyConverters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory)); + const lazyFactory = memoize(() => createLazyFactoryMembers(factory, asExpression)); // Add tree state observers to base methods. const createNode = observeResult(baseFactory.createBaseNode, treeStateObserver && treeStateObserver.onCreateNode); @@ -25,8 +26,8 @@ namespace ts { const reuse = observeResult(reuseWorker, treeStateObserver && treeStateObserver.onReuseNode); const factory: NodeFactory = { - getParenthesizerRules: parenthesizer, - getConverters, + get parenthesizer() { return lazyParenthesizer(); }, + get converters() { return lazyConverters(); }, setSkipTransformationFlags: value => { const oldValue = skipTransformationFlags; skipTransformationFlags = value; @@ -50,8 +51,8 @@ namespace ts { createFileLevelUniqueName, getGeneratedNameForNode, createToken, - createSuper: createSuperExpression, - createThis: createThisExpression, + createSuper, + createThis, createNull, createTrue, createFalse, @@ -87,7 +88,6 @@ namespace ts { updateConstructSignature, createIndexSignature, updateIndexSignature, - createSignatureDeclaration, createKeywordTypeNode, createTypePredicateNode, updateTypePredicateNode, @@ -335,7 +335,7 @@ namespace ts { createJSDocCallbackTag, createJSDocClassTag, createJSDocEnumTag, - createJSDocTag: createJSDocUnknownTag, + createJSDocUnknownTag: createJSDocUnknownTag, createJSDocComment, createJsxElement, updateJsxElement, @@ -387,49 +387,71 @@ namespace ts { createBundle, updateBundle, - // TODO(rbuckton): Move these to a different object or possibly remove them? - createImmediatelyInvokedFunctionExpression, - createImmediatelyInvokedArrowFunction, - createComma, - createLessThan, - createAssignment, - createStrictEquality, - createStrictInequality, - createAdd, - createSubtract, - createPostfixIncrement, - createLogicalAnd, - createLogicalOr, - createLogicalNot, - createVoidZero, - createExportDefault, - createExternalModuleExport, - createTypeCheck, - createMethodCall, - createGlobalMethodCall, - createFunctionBindCall, - createFunctionCallCall, - createFunctionApplyCall, - createArraySliceCall: createArraySlice, - createArrayConcatCall: createArrayConcat, - createObjectDefinePropertyCall, - createPropertyDescriptor, - createCallBinding, - inlineExpressions, - getInternalName, - getLocalName, - getExportName, - getDeclarationName, - getNamespaceMemberName, - getExternalModuleOrNamespaceExportName, - recreateOuterExpressions, - restoreEnclosingLabel, - createUseStrictPrologue, - copyPrologue, - copyStandardPrologue, - copyCustomPrologue, - ensureUseStrict, - liftToBlock + // Lazily load factory methods for common operator factories and utilities + get createSignatureDeclaration() { return lazyFactory().createSignatureDeclaration; }, + get createComma() { return lazyFactory().createComma; }, + get createAssignment() { return lazyFactory().createAssignment; }, + get createLogicalOr() { return lazyFactory().createLogicalOr; }, + get createLogicalAnd() { return lazyFactory().createLogicalAnd; }, + get createBitwiseOr() { return lazyFactory().createBitwiseOr; }, + get createBitwiseXor() { return lazyFactory().createBitwiseXor; }, + get createBitwiseAnd() { return lazyFactory().createBitwiseAnd; }, + get createStrictEquality() { return lazyFactory().createStrictEquality; }, + get createStrictInequality() { return lazyFactory().createStrictInequality; }, + get createEquality() { return lazyFactory().createEquality; }, + get createInequality() { return lazyFactory().createInequality; }, + get createLessThan() { return lazyFactory().createLessThan; }, + get createLessThanEquals() { return lazyFactory().createLessThanEquals; }, + get createGreaterThan() { return lazyFactory().createGreaterThan; }, + get createGreaterThanEquals() { return lazyFactory().createGreaterThanEquals; }, + get createLeftShift() { return lazyFactory().createLeftShift; }, + get createRightShift() { return lazyFactory().createRightShift; }, + get createUnsignedRightShift() { return lazyFactory().createUnsignedRightShift; }, + get createAdd() { return lazyFactory().createAdd; }, + get createSubtract() { return lazyFactory().createSubtract; }, + get createMultiply() { return lazyFactory().createMultiply; }, + get createDivide() { return lazyFactory().createDivide; }, + get createModulo() { return lazyFactory().createModulo; }, + get createExponent() { return lazyFactory().createExponent; }, + get createPrefixPlus() { return lazyFactory().createPrefixPlus; }, + get createPrefixMinus() { return lazyFactory().createPrefixMinus; }, + get createPrefixIncrement() { return lazyFactory().createPrefixIncrement; }, + get createPrefixDecrement() { return lazyFactory().createPrefixDecrement; }, + get createBitwiseNot() { return lazyFactory().createBitwiseNot; }, + get createLogicalNot() { return lazyFactory().createLogicalNot; }, + get createPostfixIncrement() { return lazyFactory().createPostfixIncrement; }, + get createPostfixDecrement() { return lazyFactory().createPostfixDecrement; }, + get createImmediatelyInvokedFunctionExpression() { return lazyFactory().createImmediatelyInvokedFunctionExpression; }, + get createImmediatelyInvokedArrowFunction() { return lazyFactory().createImmediatelyInvokedArrowFunction; }, + get createVoidZero() { return lazyFactory().createVoidZero; }, + get createExportDefault() { return lazyFactory().createExportDefault; }, + get createExternalModuleExport() { return lazyFactory().createExternalModuleExport; }, + get createTypeCheck() { return lazyFactory().createTypeCheck; }, + get createMethodCall() { return lazyFactory().createMethodCall; }, + get createGlobalMethodCall() { return lazyFactory().createGlobalMethodCall; }, + get createFunctionBindCall() { return lazyFactory().createFunctionBindCall; }, + get createFunctionCallCall() { return lazyFactory().createFunctionCallCall; }, + get createFunctionApplyCall() { return lazyFactory().createFunctionApplyCall; }, + get createArraySliceCall() { return lazyFactory().createArraySliceCall; }, + get createArrayConcatCall() { return lazyFactory().createArrayConcatCall; }, + get createObjectDefinePropertyCall() { return lazyFactory().createObjectDefinePropertyCall; }, + get createPropertyDescriptor() { return lazyFactory().createPropertyDescriptor; }, + get createCallBinding() { return lazyFactory().createCallBinding; }, + get inlineExpressions() { return lazyFactory().inlineExpressions; }, + get getInternalName() { return lazyFactory().getInternalName; }, + get getLocalName() { return lazyFactory().getLocalName; }, + get getExportName() { return lazyFactory().getExportName; }, + get getDeclarationName() { return lazyFactory().getDeclarationName; }, + get getNamespaceMemberName() { return lazyFactory().getNamespaceMemberName; }, + get getExternalModuleOrNamespaceExportName() { return lazyFactory().getExternalModuleOrNamespaceExportName; }, + get restoreOuterExpressions() { return lazyFactory().recreateOuterExpressions; }, + get restoreEnclosingLabel() { return lazyFactory().restoreEnclosingLabel; }, + get createUseStrictPrologue() { return lazyFactory().createUseStrictPrologue; }, + get copyPrologue() { return lazyFactory().copyPrologue; }, + get copyStandardPrologue() { return lazyFactory().copyStandardPrologue; }, + get copyCustomPrologue() { return lazyFactory().copyCustomPrologue; }, + get ensureUseStrict() { return lazyFactory().ensureUseStrict; }, + get liftToBlock() { return lazyFactory().liftToBlock; }, }; return factory; @@ -877,12 +899,12 @@ namespace ts { // // @api - function createSuperExpression() { + function createSuper() { return createToken(SyntaxKind.SuperKeyword) as SuperExpression; } // @api - function createThisExpression() { + function createThis() { return createToken(SyntaxKind.ThisKeyword) as ThisExpression; } @@ -950,7 +972,7 @@ namespace ts { // @api function createComputedPropertyName(expression: Expression) { const node = createBaseNode(SyntaxKind.ComputedPropertyName); - setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfComputedPropertyName(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeExpressionOfComputedPropertyName(expression)); if (!skipTransformationFlags) { markES2015(node); markComputedPropertyName(node); @@ -1010,7 +1032,7 @@ namespace ts { modifiers, name, type, - initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer) + initializer && lazyParenthesizer().parenthesizeExpressionForDisallowedComma(initializer) ); setChild(node, node.dotDotDotToken = dotDotDotToken); setChild(node, node.questionToken = questionToken); @@ -1052,7 +1074,7 @@ namespace ts { // @api function createDecorator(expression: Expression) { const node = createBaseNode(SyntaxKind.Decorator); - setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeLeftSideOfAccess(expression)); if (!skipTransformationFlags) { markTypeScript(node); markTypeScriptClassSyntax(node); @@ -1457,50 +1479,6 @@ namespace ts { : reuse(node); } - // Route signature creation to the appropriate factory method. Used by the NodeBuilder in the checker. - // @api - function createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): T; - function createSignatureDeclaration(kind: SignatureDeclaration["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): SignatureDeclaration { - switch (kind) { - case SyntaxKind.CallSignature: - return createCallSignature(typeParameters, parameters, type); - case SyntaxKind.ConstructSignature: - return createConstructSignature(typeParameters, parameters, type); - case SyntaxKind.MethodSignature: - // NOTE: This creates an *invalid* method signature since `name` is `undefined`, but this is preserved to support existing behavior. - return createMethodSignature(/*modifiers*/ undefined, /*name*/ undefined!, /*questionToken*/ undefined, typeParameters, parameters, type); - case SyntaxKind.MethodDeclaration: - // NOTE: This creates an *invalid* method declaration since `name` is `undefined`, but this is preserved to support existing behavior. - return createMethodDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined!, /*questionToken*/ undefined, typeParameters, parameters, type, /*body*/ undefined); - case SyntaxKind.Constructor: - return createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, /*body*/ undefined); - case SyntaxKind.GetAccessor: - // NOTE: This creates an *invalid* get accessor since `name` is `undefined`, but this is preserved to support existing behavior. - return createGetAccessorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined!, parameters, type, /*body*/ undefined); - case SyntaxKind.SetAccessor: - // NOTE: This creates an *invalid* set accessor since `name` is `undefined`, but this is preserved to support existing behavior. - return createSetAccessorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined!, parameters, /*body*/ undefined); - case SyntaxKind.IndexSignature: - return createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, type); - case SyntaxKind.JSDocFunctionType: - return createJSDocFunctionType(parameters, type); - case SyntaxKind.FunctionType: - return createFunctionTypeNode(typeParameters, parameters, type); - case SyntaxKind.ConstructorType: - return createConstructorTypeNode(typeParameters, parameters, type); - case SyntaxKind.FunctionDeclaration: - return createFunctionDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, typeParameters, parameters, type, /*body*/ undefined); - case SyntaxKind.FunctionExpression: - // NOTE: This creates an *invalid* function expression since `body` is `undefined`, but this is preserved to support existing behavior. - return createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, typeParameters, parameters, type, /*body*/ undefined!); - case SyntaxKind.ArrowFunction: - // NOTE: This creates an *invalid* arrow function since `body` is `undefined`, but this is preserved to support existing behavior. - return createArrowFunction(/*modifiers*/ undefined, typeParameters, parameters, type, /*equalsGreaterThanToken*/ undefined, /*body*/ undefined!); - default: - return Debug.assertNever(kind); - } - } - // @api function createIndexSignature( decorators: readonly Decorator[] | undefined, @@ -1571,7 +1549,7 @@ namespace ts { function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) { const node = createBaseNode(SyntaxKind.TypeReference); setChild(node, node.typeName = asName(typeName)); - setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); + setChildren(node, node.typeArguments = typeArguments && lazyParenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); if (!skipTransformationFlags) { markTypeScriptOnly(node); } @@ -1693,7 +1671,7 @@ namespace ts { // @api function createArrayTypeNode(elementType: TypeNode) { const node = createBaseNode(SyntaxKind.ArrayType); - setChild(node, node.elementType = parenthesizer().parenthesizeElementTypeOfArrayType(elementType)); + setChild(node, node.elementType = lazyParenthesizer().parenthesizeElementTypeOfArrayType(elementType)); if (!skipTransformationFlags) { markTypeScriptOnly(node); } @@ -1727,7 +1705,7 @@ namespace ts { // @api function createOptionalTypeNode(type: TypeNode) { const node = createBaseNode(SyntaxKind.OptionalType); - setChild(node, node.type = parenthesizer().parenthesizeElementTypeOfArrayType(type)); + setChild(node, node.type = lazyParenthesizer().parenthesizeElementTypeOfArrayType(type)); if (!skipTransformationFlags) { markTypeScriptOnly(node); } @@ -1760,7 +1738,7 @@ namespace ts { function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]) { const node = createBaseNode(kind); - setChildren(node, node.types = parenthesizer().parenthesizeConstituentTypesOfUnionOrIntersectionType(createNodeArray(types))); + setChildren(node, node.types = lazyParenthesizer().parenthesizeConstituentTypesOfUnionOrIntersectionType(createNodeArray(types))); if (!skipTransformationFlags) { markTypeScriptOnly(node); } @@ -1796,8 +1774,8 @@ namespace ts { // @api function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { const node = createBaseNode(SyntaxKind.ConditionalType); - setChild(node, node.checkType = parenthesizer().parenthesizeMemberOfConditionalType(checkType)); - setChild(node, node.extendsType = parenthesizer().parenthesizeMemberOfConditionalType(extendsType)); + setChild(node, node.checkType = lazyParenthesizer().parenthesizeMemberOfConditionalType(checkType)); + setChild(node, node.extendsType = lazyParenthesizer().parenthesizeMemberOfConditionalType(extendsType)); setChild(node, node.trueType = trueType); setChild(node, node.falseType = falseType); if (!skipTransformationFlags) { @@ -1838,7 +1816,7 @@ namespace ts { const node = createBaseNode(SyntaxKind.ImportType); setChild(node, node.argument = argument); setChild(node, node.qualifier = qualifier); - setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); + setChildren(node, node.typeArguments = typeArguments && lazyParenthesizer().parenthesizeTypeArguments(createNodeArray(typeArguments))); node.isTypeOf = isTypeOf; if (!skipTransformationFlags) { markTypeScriptOnly(node); @@ -1886,7 +1864,7 @@ namespace ts { function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode { const node = createBaseNode(SyntaxKind.TypeOperator); node.operator = operator; - setChild(node, node.type = parenthesizer().parenthesizeMemberOfElementType(type)); + setChild(node, node.type = lazyParenthesizer().parenthesizeMemberOfElementType(type)); if (!skipTransformationFlags) { markTypeScriptOnly(node); } @@ -1903,7 +1881,7 @@ namespace ts { // @api function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) { const node = createBaseNode(SyntaxKind.IndexedAccessType); - setChild(node, node.objectType = parenthesizer().parenthesizeMemberOfElementType(objectType)); + setChild(node, node.objectType = lazyParenthesizer().parenthesizeMemberOfElementType(objectType)); setChild(node, node.indexType = indexType); if (!skipTransformationFlags) { markTypeScriptOnly(node); @@ -2038,7 +2016,7 @@ namespace ts { // @api function createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean) { const node = createBaseNode(SyntaxKind.ArrayLiteralExpression); - setChildren(node, node.elements = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(elements))); + setChildren(node, node.elements = lazyParenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(elements))); if (multiLine) node.multiLine = true; return finish(node); } @@ -2068,7 +2046,7 @@ namespace ts { // @api function createPropertyAccessExpression(expression: Expression, name: string | Identifier) { const node = createBaseNode(SyntaxKind.PropertyAccessExpression); - setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeLeftSideOfAccess(expression)); setChild(node, node.name = asName(name)); if (!skipTransformationFlags) { // super method calls require a lexical 'this' @@ -2092,7 +2070,7 @@ namespace ts { // @api function createElementAccessExpression(expression: Expression, index: number | Expression) { const node = createBaseNode(SyntaxKind.ElementAccessExpression); - setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeLeftSideOfAccess(expression)); setChild(node, node.argumentExpression = asExpression(index)); if (!skipTransformationFlags) { // super method calls require a lexical 'this' @@ -2116,9 +2094,9 @@ namespace ts { // @api function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { const node = createBaseNode(SyntaxKind.CallExpression); - setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeLeftSideOfAccess(expression)); setChildren(node, node.typeArguments = asNodeArray(typeArguments)); - setChildren(node, node.arguments = parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray))); + setChildren(node, node.arguments = lazyParenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray))); if (!skipTransformationFlags) { if (typeArguments) { markTypeScript(node); @@ -2145,9 +2123,9 @@ namespace ts { // @api function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { const node = createBaseNode(SyntaxKind.NewExpression); - setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfNew(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeExpressionOfNew(expression)); setChildren(node, node.typeArguments = asNodeArray(typeArguments)); - setChildren(node, node.arguments = argumentsArray ? parenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)) : undefined); + setChildren(node, node.arguments = argumentsArray ? lazyParenthesizer().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)) : undefined); if (!skipTransformationFlags) { if (typeArguments) { markTypeScript(node); @@ -2168,7 +2146,7 @@ namespace ts { // @api function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { const node = createBaseNode(SyntaxKind.TaggedTemplateExpression); - setChild(node, node.tag = parenthesizer().parenthesizeLeftSideOfAccess(tag)); + setChild(node, node.tag = lazyParenthesizer().parenthesizeLeftSideOfAccess(tag)); setChildren(node, node.typeArguments = asNodeArray(typeArguments)); setChild(node, node.template = template); if (!skipTransformationFlags) { @@ -2192,7 +2170,7 @@ namespace ts { // @api function createTypeAssertion(type: TypeNode, expression: Expression) { const node = createBaseNode(SyntaxKind.TypeAssertionExpression); - setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeOperandOfPrefixUnary(expression)); setChild(node, node.type = type); if (!skipTransformationFlags) { markTypeScript(node); @@ -2301,7 +2279,7 @@ namespace ts { typeParameters, parameters, type, - parenthesizer().parenthesizeConciseBodyOfArrowFunction(body) + lazyParenthesizer().parenthesizeConciseBodyOfArrowFunction(body) ); setChild(node, node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(SyntaxKind.EqualsGreaterThanToken)); if (!skipTransformationFlags) { @@ -2355,7 +2333,7 @@ namespace ts { // @api function createDeleteExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.DeleteExpression); - setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeOperandOfPrefixUnary(expression)); return finish(node); } @@ -2369,7 +2347,7 @@ namespace ts { // @api function createTypeOfExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.TypeOfExpression); - setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeOperandOfPrefixUnary(expression)); return finish(node); } @@ -2383,7 +2361,7 @@ namespace ts { // @api function createVoidExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.VoidExpression); - setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeOperandOfPrefixUnary(expression)); return finish(node); } @@ -2397,7 +2375,7 @@ namespace ts { // @api function createAwaitExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.AwaitExpression); - setChild(node, node.expression = parenthesizer().parenthesizeOperandOfPrefixUnary(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeOperandOfPrefixUnary(expression)); if (!skipTransformationFlags) { markES2017(node); markES2018(node); @@ -2416,7 +2394,7 @@ namespace ts { function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) { const node = createBaseNode(SyntaxKind.PrefixUnaryExpression); node.operator = operator; - setChild(node, node.operand = parenthesizer().parenthesizeOperandOfPrefixUnary(operand)); + setChild(node, node.operand = lazyParenthesizer().parenthesizeOperandOfPrefixUnary(operand)); return finish(node); } @@ -2431,7 +2409,7 @@ namespace ts { function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) { const node = createBaseNode(SyntaxKind.PostfixUnaryExpression); node.operator = operator; - setChild(node, node.operand = parenthesizer().parenthesizeOperandOfPostfixUnary(operand)); + setChild(node, node.operand = lazyParenthesizer().parenthesizeOperandOfPostfixUnary(operand)); return finish(node); } @@ -2447,9 +2425,9 @@ namespace ts { const node = createBaseNode(SyntaxKind.BinaryExpression); const operatorToken = asToken(operator); const operatorKind = operatorToken.kind; - setChild(node, node.left = parenthesizer().parenthesizeLeftSideOfBinary(operatorKind, left)); + setChild(node, node.left = lazyParenthesizer().parenthesizeLeftSideOfBinary(operatorKind, left)); setChild(node, node.operatorToken = operatorToken); - setChild(node, node.right = parenthesizer().parenthesizeRightSideOfBinary(operatorKind, node.left, right)); + setChild(node, node.right = lazyParenthesizer().parenthesizeRightSideOfBinary(operatorKind, node.left, right)); if (!skipTransformationFlags) { if (operatorKind === SyntaxKind.EqualsToken) { if (node.left.kind === SyntaxKind.ObjectLiteralExpression) { @@ -2480,11 +2458,11 @@ namespace ts { // @api function createConditionalExpression(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression) { const node = createBaseNode(SyntaxKind.ConditionalExpression); - setChild(node, node.condition = parenthesizer().parenthesizeConditionOfConditionalExpression(condition)); + setChild(node, node.condition = lazyParenthesizer().parenthesizeConditionOfConditionalExpression(condition)); setChild(node, node.questionToken = questionToken); - setChild(node, node.whenTrue = parenthesizer().parenthesizeBranchOfConditionalExpression(whenTrue)); + setChild(node, node.whenTrue = lazyParenthesizer().parenthesizeBranchOfConditionalExpression(whenTrue)); setChild(node, node.colonToken = colonToken); - setChild(node, node.whenFalse = parenthesizer().parenthesizeBranchOfConditionalExpression(whenFalse)); + setChild(node, node.whenFalse = lazyParenthesizer().parenthesizeBranchOfConditionalExpression(whenFalse)); return finish(node); } @@ -2615,7 +2593,7 @@ namespace ts { // @api function createSpreadElement(expression: Expression) { const node = createBaseNode(SyntaxKind.SpreadElement); - setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeExpressionForDisallowedComma(expression)); if (!skipTransformationFlags) { markES2015(node); markRestOrSpread(node); @@ -2682,8 +2660,8 @@ namespace ts { // @api function createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined) { const node = createBaseNode(SyntaxKind.ExpressionWithTypeArguments); - setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); - setChildren(node, node.typeArguments = typeArguments && parenthesizer().parenthesizeTypeArguments(typeArguments)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChildren(node, node.typeArguments = typeArguments && lazyParenthesizer().parenthesizeTypeArguments(typeArguments)); if (!skipTransformationFlags) { markES2015(node); } @@ -2720,7 +2698,7 @@ namespace ts { // @api function createNonNullExpression(expression: Expression) { const node = createBaseNode(SyntaxKind.NonNullExpression); - setChild(node, node.expression = parenthesizer().parenthesizeLeftSideOfAccess(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeLeftSideOfAccess(expression)); if (!skipTransformationFlags) { markTypeScript(node); } @@ -2838,7 +2816,7 @@ namespace ts { // @api function createExpressionStatement(expression: Expression): ExpressionStatement { const node = createBaseNode(SyntaxKind.ExpressionStatement); - setChild(node, node.expression = parenthesizer().parenthesizeExpressionOfExpressionStatement(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeExpressionOfExpressionStatement(expression)); return finish(node); } @@ -3033,7 +3011,7 @@ namespace ts { // @api function createSwitchStatement(expression: Expression, caseBlock: CaseBlock): SwitchStatement { const node = createBaseNode(SyntaxKind.SwitchStatement); - setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeExpressionForDisallowedComma(expression)); setChild(node, node.caseBlock = caseBlock); return finish(node); } @@ -3107,7 +3085,7 @@ namespace ts { /*modifiers*/ undefined, name, type, - initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer) + initializer && lazyParenthesizer().parenthesizeExpressionForDisallowedComma(initializer) ); setChild(node, node.exclamationToken = exclamationToken); return finish(node); @@ -3623,8 +3601,8 @@ namespace ts { ); node.isExportEquals = isExportEquals; setChild(node, node.expression = isExportEquals - ? parenthesizer().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) - : parenthesizer().parenthesizeExpressionOfExportDefault(expression)); + ? lazyParenthesizer().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) + : lazyParenthesizer().parenthesizeExpressionOfExportDefault(expression)); return finish(node); } @@ -4157,7 +4135,7 @@ namespace ts { // @api function createCaseClause(expression: Expression, statements: readonly Statement[]) { const node = createBaseNode(SyntaxKind.CaseClause); - setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeExpressionForDisallowedComma(expression)); setChildren(node, node.statements = createNodeArray(statements)); return finish(node); } @@ -4245,7 +4223,7 @@ namespace ts { const node = createBaseNode(SyntaxKind.PropertyAssignment); setChild(node, node.name = asName(name)); setChild(node, node.questionToken = undefined); - setChild(node, node.initializer = parenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); + setChild(node, node.initializer = lazyParenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); return finish(node); } @@ -4274,7 +4252,7 @@ namespace ts { name ); setChild(node, node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined - ? parenthesizer().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer) + ? lazyParenthesizer().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer) : undefined); if (!skipTransformationFlags) { markES2015(node); @@ -4302,7 +4280,7 @@ namespace ts { // @api function createSpreadAssignment(expression: Expression) { const node = createBaseNode(SyntaxKind.SpreadAssignment); - setChild(node, node.expression = parenthesizer().parenthesizeExpressionForDisallowedComma(expression)); + setChild(node, node.expression = lazyParenthesizer().parenthesizeExpressionForDisallowedComma(expression)); if (!skipTransformationFlags) { markES2018(node); markObjectRestOrSpread(node); @@ -4325,7 +4303,7 @@ namespace ts { function createEnumMember(name: string | PropertyName, initializer?: Expression) { const node = createBaseNode(SyntaxKind.EnumMember); setChild(node, node.name = asName(name)); - setChild(node, node.initializer = initializer && parenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); + setChild(node, node.initializer = initializer && lazyParenthesizer().parenthesizeExpressionForDisallowedComma(initializer)); if (!skipTransformationFlags) { markTypeScript(node); } @@ -4517,24 +4495,213 @@ namespace ts { : reuse(node); } - // - // Compound Nodes - // + function asNodeArray(array: readonly T[]): NodeArray; + function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined; + function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined { + return array ? createNodeArray(array) : undefined; + } - // TODO(rbuckton): Consider removing these from NodeFactory and putting them somewhere else. + function asName(name: string | T): T | Identifier { + return typeof name === "string" ? createIdentifier(name) : + name; + } + + function asExpression(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral { + return typeof value === "string" ? createStringLiteral(value) : + typeof value === "number" ? createNumericLiteral(value) : + typeof value === "boolean" ? value ? createTrue() : createFalse() : + value; + } + + function asToken(value: TKind | Token): Token { + return typeof value === "number" ? createToken(value) : value; + } + + function asEmbeddedStatement(statement: T): T | EmptyStatement; + function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined; + function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { + return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; + } + + function setChildWorker(parent: Node, child: Node | undefined): void { + if (!skipTransformationFlags) { + if (child) { + parent.transformFlags |= propagateChildFlags(child); + } + } + } + + function setChildrenWorker(parent: Node, children: NodeArray | undefined): void { + if (!skipTransformationFlags) { + if (children) { + parent.transformFlags |= propagateChildrenFlags(children); + } + } + } + + function finishWorker(node: T) { + if (!skipTransformationFlags) { + node.transformFlags |= TransformFlags.HasComputedFlags; + } + return node; + } + + function updateWorker(updated: T, original: T) { + return updateNode(updated, original); + } + + function reuseWorker(node: T) { + return node; + } + } + + function createLazyFactoryMembers( + factory: NodeFactory, + asExpression: (value: string | number | boolean | T) => T | StringLiteral | NumericLiteral | BooleanLiteral, + ) { + // lazy initializaton of common operator factories + let lazyBinaryFactories: ((left: Expression, right: Expression) => BinaryExpression)[] | undefined; + let lazyPrefixUnaryFactories: ((operand: Expression) => PrefixUnaryExpression)[] | undefined; + let lazyPostfixUnaryFactories: ((operand: Expression) => PostfixUnaryExpression)[] | undefined; + + return { + get createComma() { return getBinaryFactory(SyntaxKind.CommaToken); }, + get createAssignment() { return getBinaryFactory(SyntaxKind.EqualsToken) as NodeFactory["createAssignment"]; }, + get createLogicalOr() { return getBinaryFactory(SyntaxKind.BarBarToken); }, + get createLogicalAnd() { return getBinaryFactory(SyntaxKind.AmpersandAmpersandToken); }, + get createBitwiseOr() { return getBinaryFactory(SyntaxKind.BarToken); }, + get createBitwiseXor() { return getBinaryFactory(SyntaxKind.CaretToken); }, + get createBitwiseAnd() { return getBinaryFactory(SyntaxKind.AmpersandToken); }, + get createStrictEquality() { return getBinaryFactory(SyntaxKind.EqualsEqualsEqualsToken); }, + get createStrictInequality() { return getBinaryFactory(SyntaxKind.ExclamationEqualsEqualsToken); }, + get createEquality() { return getBinaryFactory(SyntaxKind.EqualsEqualsToken); }, + get createInequality() { return getBinaryFactory(SyntaxKind.ExclamationEqualsToken); }, + get createLessThan() { return getBinaryFactory(SyntaxKind.LessThanToken); }, + get createLessThanEquals() { return getBinaryFactory(SyntaxKind.LessThanEqualsToken); }, + get createGreaterThan() { return getBinaryFactory(SyntaxKind.GreaterThanToken); }, + get createGreaterThanEquals() { return getBinaryFactory(SyntaxKind.GreaterThanEqualsToken); }, + get createLeftShift() { return getBinaryFactory(SyntaxKind.LessThanLessThanToken); }, + get createRightShift() { return getBinaryFactory(SyntaxKind.GreaterThanGreaterThanToken); }, + get createUnsignedRightShift() { return getBinaryFactory(SyntaxKind.GreaterThanGreaterThanGreaterThanToken); }, + get createAdd() { return getBinaryFactory(SyntaxKind.PlusToken); }, + get createSubtract() { return getBinaryFactory(SyntaxKind.MinusToken); }, + get createMultiply() { return getBinaryFactory(SyntaxKind.AsteriskToken); }, + get createDivide() { return getBinaryFactory(SyntaxKind.SlashToken); }, + get createModulo() { return getBinaryFactory(SyntaxKind.PercentToken); }, + get createExponent() { return getBinaryFactory(SyntaxKind.AsteriskAsteriskToken); }, + get createPrefixPlus() { return getPrefixUnaryFactory(SyntaxKind.PlusToken); }, + get createPrefixMinus() { return getPrefixUnaryFactory(SyntaxKind.MinusToken); }, + get createPrefixIncrement() { return getPrefixUnaryFactory(SyntaxKind.PlusPlusToken); }, + get createPrefixDecrement() { return getPrefixUnaryFactory(SyntaxKind.MinusMinusToken); }, + get createBitwiseNot() { return getPrefixUnaryFactory(SyntaxKind.TildeToken); }, + get createLogicalNot() { return getPrefixUnaryFactory(SyntaxKind.ExclamationToken); }, + get createPostfixIncrement() { return getPostfixUnaryFactory(SyntaxKind.PlusPlusToken); }, + get createPostfixDecrement() { return getPostfixUnaryFactory(SyntaxKind.MinusMinusToken); }, + + createSignatureDeclaration, + createImmediatelyInvokedFunctionExpression, + createImmediatelyInvokedArrowFunction, + createVoidZero, + createExportDefault, + createExternalModuleExport, + createTypeCheck, + createMethodCall, + createGlobalMethodCall, + createFunctionBindCall, + createFunctionCallCall, + createFunctionApplyCall, + createArraySliceCall, + createArrayConcatCall, + createObjectDefinePropertyCall, + createPropertyDescriptor, + createCallBinding, + inlineExpressions, + getInternalName, + getLocalName, + getExportName, + getDeclarationName, + getNamespaceMemberName, + getExternalModuleOrNamespaceExportName, + recreateOuterExpressions, + restoreEnclosingLabel, + createUseStrictPrologue, + copyPrologue, + copyStandardPrologue, + copyCustomPrologue, + ensureUseStrict, + liftToBlock, + }; + + function getBinaryFactory(operator: BinaryOperator) { + const factories = lazyBinaryFactories || []; + return factories[operator] || (factories[operator] = (left, right) => factory.createBinary(left, operator, right)); + } + + function getPrefixUnaryFactory(operator: PrefixUnaryOperator) { + const factories = lazyPrefixUnaryFactories || []; + return factories[operator] || (factories[operator] = operand => factory.createPrefix(operator, operand)); + } + + function getPostfixUnaryFactory(operator: PostfixUnaryOperator) { + const factories = lazyPostfixUnaryFactories || []; + return factories[operator] || (factories[operator] = operand => factory.createPostfix(operand, operator)); + } + + // Route signature creation to the appropriate factory method. Used by the NodeBuilder in the checker. + function createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): T; + function createSignatureDeclaration(kind: SignatureDeclaration["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): SignatureDeclaration { + switch (kind) { + case SyntaxKind.CallSignature: + return factory.createCallSignature(typeParameters, parameters, type); + case SyntaxKind.ConstructSignature: + return factory.createConstructSignature(typeParameters, parameters, type); + case SyntaxKind.MethodSignature: + // NOTE: This creates an *invalid* method signature since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createMethodSignature(/*modifiers*/ undefined, /*name*/ undefined!, /*questionToken*/ undefined, typeParameters, parameters, type); + case SyntaxKind.MethodDeclaration: + // NOTE: This creates an *invalid* method declaration since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createMethodDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined!, /*questionToken*/ undefined, typeParameters, parameters, type, /*body*/ undefined); + case SyntaxKind.Constructor: + return factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, /*body*/ undefined); + case SyntaxKind.GetAccessor: + // NOTE: This creates an *invalid* get accessor since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createGetAccessorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined!, parameters, type, /*body*/ undefined); + case SyntaxKind.SetAccessor: + // NOTE: This creates an *invalid* set accessor since `name` is `undefined`, but this is preserved to support existing behavior. + return factory.createSetAccessorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined!, parameters, /*body*/ undefined); + case SyntaxKind.IndexSignature: + return factory.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, type); + case SyntaxKind.JSDocFunctionType: + return factory.createJSDocFunctionType(parameters, type); + case SyntaxKind.FunctionType: + return factory.createFunctionTypeNode(typeParameters, parameters, type); + case SyntaxKind.ConstructorType: + return factory.createConstructorTypeNode(typeParameters, parameters, type); + case SyntaxKind.FunctionDeclaration: + return factory.createFunctionDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, typeParameters, parameters, type, /*body*/ undefined); + case SyntaxKind.FunctionExpression: + // NOTE: This creates an *invalid* function expression since `body` is `undefined`, but this is preserved to support existing behavior. + return factory.createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, typeParameters, parameters, type, /*body*/ undefined!); + case SyntaxKind.ArrowFunction: + // NOTE: This creates an *invalid* arrow function since `body` is `undefined`, but this is preserved to support existing behavior. + return factory.createArrowFunction(/*modifiers*/ undefined, typeParameters, parameters, type, /*equalsGreaterThanToken*/ undefined, /*body*/ undefined!); + default: + return Debug.assertNever(kind); + } + } function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { - return createCallExpression( - createFunctionExpression( + return factory.createCall( + factory.createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, /*parameters*/ param ? [param] : [], /*type*/ undefined, - createBlock(statements, /*multiLine*/ true) + factory.createBlock(statements, /*multiLine*/ true) ), /*typeArguments*/ undefined, /*argumentsArray*/ paramValue ? [paramValue] : [] @@ -4544,73 +4711,26 @@ namespace ts { function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { - return createCallExpression( - createArrowFunction( + return factory.createCall( + factory.createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, /*parameters*/ param ? [param] : [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, - createBlock(statements, /*multiLine*/ true) + factory.createBlock(statements, /*multiLine*/ true) ), /*typeArguments*/ undefined, /*argumentsArray*/ paramValue ? [paramValue] : [] ); } - - function createComma(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.CommaToken, right); - } - - function createLessThan(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.LessThanToken, right); - } - - function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; - function createAssignment(left: Expression, right: Expression): BinaryExpression; - function createAssignment(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.EqualsToken, right); - } - - function createStrictEquality(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.EqualsEqualsEqualsToken, right); - } - - function createStrictInequality(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.ExclamationEqualsEqualsToken, right); - } - - function createAdd(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.PlusToken, right); - } - - function createSubtract(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.MinusToken, right); - } - - function createPostfixIncrement(operand: Expression) { - return createPostfixUnaryExpression(operand, SyntaxKind.PlusPlusToken); - } - - function createLogicalAnd(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.AmpersandAmpersandToken, right); - } - - function createLogicalOr(left: Expression, right: Expression) { - return createBinaryExpression(left, SyntaxKind.BarBarToken, right); - } - - function createLogicalNot(operand: Expression) { - return createPrefixUnaryExpression(SyntaxKind.ExclamationToken, operand); - } - function createVoidZero() { - return createVoidExpression(createNumericLiteral("0")); + return factory.createVoid(factory.createNumericLiteral("0")); } function createExportDefault(expression: Expression) { - return createExportAssignment( + return factory.createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, @@ -4618,11 +4738,11 @@ namespace ts { } function createExternalModuleExport(exportName: Identifier) { - return createExportDeclaration( + return factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createNamedExports([ - createExportSpecifier(/*propertyName*/ undefined, exportName) + factory.createNamedExports([ + factory.createExportSpecifier(/*propertyName*/ undefined, exportName) ]) ); } @@ -4633,13 +4753,13 @@ namespace ts { function createTypeCheck(value: Expression, tag: TypeOfTag) { return tag === "undefined" - ? createStrictEquality(value, createVoidZero()) - : createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag)); + ? factory.createStrictEquality(value, createVoidZero()) + : factory.createStrictEquality(factory.createTypeOf(value), factory.createStringLiteral(tag)); } function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) { - return createCallExpression( - createPropertyAccessExpression(object, asName(methodName)), + return factory.createCall( + factory.createPropertyAccess(object, methodName), /*typeArguments*/ undefined, argumentsList ); @@ -4658,14 +4778,14 @@ namespace ts { } function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) { - return createMethodCall(createIdentifier(globalObjectName), methodName, argumentsList); + return createMethodCall(factory.createIdentifier(globalObjectName), methodName, argumentsList); } - function createArraySlice(array: Expression, start?: number | Expression) { + function createArraySliceCall(array: Expression, start?: number | Expression) { return createMethodCall(array, "slice", start === undefined ? [] : [asExpression(start)]); } - function createArrayConcat(array: Expression, argumentsList: readonly Expression[]) { + function createArrayConcatCall(array: Expression, argumentsList: readonly Expression[]) { return createMethodCall(array, "concat", argumentsList); } @@ -4675,7 +4795,7 @@ namespace ts { function tryAddPropertyAssignment(properties: Push, propertyName: string, expression: Expression | undefined) { if (expression) { - properties.push(createPropertyAssignment(propertyName, expression)); + properties.push(factory.createPropertyAssignment(propertyName, expression)); return true; } return false; @@ -4693,16 +4813,16 @@ namespace ts { isAccessor = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor; Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor."); - return createObjectLiteralExpression(properties, !singleLine); + return factory.createObjectLiteral(properties, !singleLine); } function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) { switch (outerExpression.kind) { - case SyntaxKind.ParenthesizedExpression: return updateParenthesizedExpression(outerExpression, expression); - case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression); - case SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type); - case SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression); - case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression); + case SyntaxKind.ParenthesizedExpression: return factory.updateParen(outerExpression, expression); + case SyntaxKind.TypeAssertionExpression: return factory.updateTypeAssertion(outerExpression, outerExpression.type, expression); + case SyntaxKind.AsExpression: return factory.updateAsExpression(outerExpression, expression, outerExpression.type); + case SyntaxKind.NonNullExpression: return factory.updateNonNullExpression(outerExpression, expression); + case SyntaxKind.PartiallyEmittedExpression: return factory.updatePartiallyEmittedExpression(outerExpression, expression); } } @@ -4743,7 +4863,7 @@ namespace ts { if (!outermostLabeledStatement) { return node; } - const updated = updateLabeledStatement( + const updated = factory.updateLabel( outermostLabeledStatement, outermostLabeledStatement.label, outermostLabeledStatement.statement.kind === SyntaxKind.LabeledStatement @@ -4784,26 +4904,26 @@ namespace ts { let thisArg: Expression; let target: LeftHandSideExpression; if (isSuperProperty(callee)) { - thisArg = createThisExpression(); + thisArg = factory.createThis(); target = callee; } else if (callee.kind === SyntaxKind.SuperKeyword) { - thisArg = createThisExpression(); + thisArg = factory.createThis(); target = languageVersion !== undefined && languageVersion < ScriptTarget.ES2015 - ? setTextRange(createIdentifier("_super"), callee) + ? setTextRange(factory.createIdentifier("_super"), callee) : callee; } else if (getEmitFlags(callee) & EmitFlags.HelperName) { thisArg = createVoidZero(); - target = parenthesizer().parenthesizeLeftSideOfAccess(callee); + target = factory.parenthesizer.parenthesizeLeftSideOfAccess(callee); } else if (isPropertyAccessExpression(callee)) { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { // for `a.b()` target is `(_a = a).b` and thisArg is `_a` - thisArg = createTempVariable(recordTempVariable); - target = createPropertyAccessExpression( + thisArg = factory.createTempVariable(recordTempVariable); + target = factory.createPropertyAccess( setTextRange( - createAssignment( + factory.createAssignment( thisArg, callee.expression ), @@ -4821,10 +4941,10 @@ namespace ts { else if (isElementAccessExpression(callee)) { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` - thisArg = createTempVariable(recordTempVariable); - target = createElementAccessExpression( + thisArg = factory.createTempVariable(recordTempVariable); + target = factory.createElementAccess( setTextRange( - createAssignment( + factory.createAssignment( thisArg, callee.expression ), @@ -4842,7 +4962,7 @@ namespace ts { else { // for `a()` target is `a` and thisArg is `void 0` thisArg = createVoidZero(); - target = parenthesizer().parenthesizeLeftSideOfAccess(expression); + target = factory.parenthesizer.parenthesizeLeftSideOfAccess(expression); } return { target, thisArg }; @@ -4852,8 +4972,8 @@ namespace ts { // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call // stack size exceeded" errors. return expressions.length > 10 - ? createCommaListExpression(expressions) - : reduceLeft(expressions, createComma)!; + ? factory.createCommaList(expressions) + : reduceLeft(expressions, factory.createComma)!; } function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) { @@ -4866,7 +4986,7 @@ namespace ts { if (emitFlags) setEmitFlags(name, emitFlags); return name; } - return getGeneratedNameForNode(node); + return factory.getGeneratedNameForNode(node); } /** @@ -4932,7 +5052,7 @@ namespace ts { * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression { - const qualifiedName = createPropertyAccessExpression(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); + const qualifiedName = factory.createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); setTextRange(qualifiedName, name); let emitFlags: EmitFlags = 0; if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; @@ -4976,7 +5096,7 @@ namespace ts { } function createUseStrictPrologue() { - return startOnNewLine(createExpressionStatement(createStringLiteral("use strict"))) as PrologueDirective; + return startOnNewLine(factory.createExpressionStatement(factory.createStringLiteral("use strict"))) as PrologueDirective; } /** @@ -5042,7 +5162,7 @@ namespace ts { const foundUseStrict = findUseStrictPrologue(statements); if (!foundUseStrict) { - return setTextRange(createNodeArray([createUseStrictPrologue(), ...statements]), statements); + return setTextRange(factory.createNodeArray([createUseStrictPrologue(), ...statements]), statements); } return statements; @@ -5055,66 +5175,7 @@ namespace ts { */ function liftToBlock(nodes: readonly Node[]): Statement { Debug.assert(every(nodes, isStatementOrBlock), "Cannot lift nodes to a Block."); - return singleOrUndefined(nodes) || createBlock(nodes); - } - - function asNodeArray(array: readonly T[]): NodeArray; - function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined; - function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined { - return array ? createNodeArray(array) : undefined; - } - - function asName(name: string | T): T | Identifier { - return typeof name === "string" ? createIdentifier(name) : - name; - } - - function asExpression(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral { - return typeof value === "string" ? createStringLiteral(value) : - typeof value === "number" ? createNumericLiteral(value) : - typeof value === "boolean" ? value ? createTrue() : createFalse() : - value; - } - - function asToken(value: TKind | Token): Token { - return typeof value === "number" ? createToken(value) : value; - } - - function asEmbeddedStatement(statement: T): T | EmptyStatement; - function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined; - function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { - return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; - } - - function setChildWorker(parent: Node, child: Node | undefined): void { - if (!skipTransformationFlags) { - if (child) { - parent.transformFlags |= propagateChildFlags(child); - } - } - } - - function setChildrenWorker(parent: Node, children: NodeArray | undefined): void { - if (!skipTransformationFlags) { - if (children) { - parent.transformFlags |= propagateChildrenFlags(children); - } - } - } - - function finishWorker(node: T) { - if (!skipTransformationFlags) { - node.transformFlags |= TransformFlags.HasComputedFlags; - } - return node; - } - - function updateWorker(updated: T, original: T) { - return updateNode(updated, original); - } - - function reuseWorker(node: T) { - return node; + return singleOrUndefined(nodes) || factory.createBlock(nodes); } } diff --git a/src/compiler/factory/parenthesizerRules.ts b/src/compiler/factory/parenthesizerRules.ts index 9ae45f03c69..58273acc293 100644 --- a/src/compiler/factory/parenthesizerRules.ts +++ b/src/compiler/factory/parenthesizerRules.ts @@ -339,7 +339,7 @@ namespace ts { emittedExpression.typeArguments, emittedExpression.arguments ); - return factory.recreateOuterExpressions(expression, updated, OuterExpressionKinds.PartiallyEmittedExpressions); + return factory.restoreOuterExpressions(expression, updated, OuterExpressionKinds.PartiallyEmittedExpressions); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c4bf285dff0..e9aa11c4aa7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6958,7 +6958,7 @@ namespace ts { } function parseUnknownTag(start: number, tagName: Identifier) { - return finishNode(factory.createJSDocTag(tagName), start); + return finishNode(factory.createJSDocUnknownTag(tagName), start); } function addTag(tag: JSDocTag | undefined): void { diff --git a/src/compiler/plugin.ts b/src/compiler/plugin.ts index 91963df3936..a9c4fec4729 100644 --- a/src/compiler/plugin.ts +++ b/src/compiler/plugin.ts @@ -1,6 +1,5 @@ /*@internal*/ namespace ts { - type MatchingKeys = K extends (T[K] extends TMatch ? K : never) ? K : never; type TryExcludeVoid = [T] extends [void] ? void : Exclude; type Replace = T extends Match ? Replace : T; type Promised = T extends PromiseLike ? U : T; diff --git a/src/compiler/shims.ts b/src/compiler/shims.ts index 9d8270fa0f6..c3e056e206a 100644 --- a/src/compiler/shims.ts +++ b/src/compiler/shims.ts @@ -18,8 +18,8 @@ namespace ts { /* @internal */ namespace ts { // Shims - export const Map: MapConstructor = requireShim("./mapShim.js", "createMapShim"); // tslint:disable-line variable-name - export const Promise: PromiseConstructor = requireShim("./promiseShim.js", "createPromiseShim"); // tslint:disable-line variable-name + export const Map: MapConstructor = tryGetNativeMap() || requireShim("./mapShim.js", "createMapShim"); // tslint:disable-line variable-name + export const Promise: PromiseConstructor = tryGetNativePromise() || requireShim("./promiseShim.js", "createPromiseShim"); // tslint:disable-line variable-name function requireShim(shimPath: string, shimFactory: K) { type ShimModule = Record C>; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 0193825a0c6..c5d109226c0 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -921,17 +921,17 @@ namespace ts { tscWatchDirectory === "RecursiveDirectoryUsingDynamicPriorityPolling" ? createWatchDirectoryUsing(dynamicPollingWatchFile || createDynamicPriorityPollingWatchFile({ getModifiedTime, setTimeout })) : watchDirectoryUsingFsWatch; - const watchDirectoryRecursively = createRecursiveDirectoryWatcher({ + const watchDirectoryRecursively = memoize(() => createRecursiveDirectoryWatcher({ useCaseSensitiveFileNames, directoryExists, getAccessibleSortedChildDirectories: path => getAccessibleFileSystemEntries(path).directories, watchDirectory, realpath - }); + })); return (directoryName, callback, recursive) => { if (recursive) { - return watchDirectoryRecursively(directoryName, callback); + return watchDirectoryRecursively()(directoryName, callback); } return watchDirectory(directoryName, callback); }; diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 6ac7f4df0d2..bd3dceafc84 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -494,7 +494,7 @@ namespace ts { } function makeArrayAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { - return factory.createArrayLiteral(map(elements, factory.getConverters().convertToArrayAssignmentElement)); + return factory.createArrayLiteral(map(elements, factory.converters.convertToArrayAssignmentElement)); } function makeObjectBindingPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { @@ -503,7 +503,7 @@ namespace ts { } function makeObjectAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { - return factory.createObjectLiteral(map(elements, factory.getConverters().convertToObjectAssignmentElement)); + return factory.createObjectLiteral(map(elements, factory.converters.convertToObjectAssignmentElement)); } function makeBindingElement(factory: NodeFactory, name: Identifier) { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 6c026dd489e..62b396118df 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3691,11 +3691,11 @@ namespace ts { // Recreate any outer parentheses or partially-emitted expressions to preserve source map // and comment locations. - return factory.recreateOuterExpressions(node.expression, - factory.recreateOuterExpressions(variable.initializer, - factory.recreateOuterExpressions(aliasAssignment && aliasAssignment.right, + return factory.restoreOuterExpressions(node.expression, + factory.restoreOuterExpressions(variable.initializer, + factory.restoreOuterExpressions(aliasAssignment && aliasAssignment.right, factory.updateCall(call, - factory.recreateOuterExpressions(call.expression, + factory.restoreOuterExpressions(call.expression, factory.updateFunctionExpression( func, /*modifiers*/ undefined, diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 7c37e874b80..9a5a65a0928 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -16,10 +16,6 @@ namespace ts { hoistVariableDeclaration } = context; - const { - getConverters: converters, - } = factory; - const resolver = context.getEmitResolver(); const compilerOptions = context.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); @@ -375,7 +371,7 @@ namespace ts { const variables = getInitializedVariables(node); if (variables.length === 0) { if (hasReceiver) { - return visitNode(converters().convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression); + return visitNode(factory.converters.convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression); } return undefined; } @@ -403,7 +399,7 @@ namespace ts { function transformInitializedVariable(node: VariableDeclaration) { const converted = setSourceMapRange( factory.createAssignment( - converters().convertToAssignmentElementTarget(node.name), + factory.converters.convertToAssignmentElementTarget(node.name), node.initializer! ), node @@ -510,7 +506,7 @@ namespace ts { const declarations = endLexicalEnvironment(); if (some(declarations)) { - const block = converters().convertToFunctionBlock(expression); + const block = factory.converters.convertToFunctionBlock(expression); result = factory.updateBlock(block, setTextRange(factory.createNodeArray(concatenate(declarations, block.statements)), block.statements)); } else { @@ -531,7 +527,7 @@ namespace ts { return factory.updateBlock(body, visitNodes(body.statements, asyncBodyVisitor, isStatement, start)); } else { - return converters().convertToFunctionBlock(visitNode(body, asyncBodyVisitor, isConciseBody)); + return factory.converters.convertToFunctionBlock(visitNode(body, asyncBodyVisitor, isConciseBody)); } } diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index a8c26386fb8..4b22c89d0e4 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -14,7 +14,6 @@ namespace ts { hoistVariableDeclaration } = context; - const converters = factory.getConverters; const resolver = context.getEmitResolver(); const compilerOptions = context.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); @@ -830,7 +829,7 @@ namespace ts { addRange(statements, appendObjectRestAssignmentsIfNeeded(/*statements*/ undefined, node)); const leadingStatements = endLexicalEnvironment(); if (statementOffset > 0 || some(statements) || some(leadingStatements)) { - const block = converters().convertToFunctionBlock(body, /*multiLine*/ true); + const block = factory.converters.convertToFunctionBlock(body, /*multiLine*/ true); insertStatementsAfterStandardPrologue(statements, leadingStatements); addRange(statements, block.statements.slice(statementOffset)); return factory.updateBlock(block, setTextRange(factory.createNodeArray(statements), block.statements)); diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 3d1514e6c8e..d0726b43796 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -20,10 +20,10 @@ "diagnosticInformationMap.generated.ts", "scanner.ts", "utilities.ts", + "factory/baseNodeFactory.ts", "factory/parenthesizerRules.ts", - "factory/converters.ts", - "factory/base.ts", - "factory/factory.ts", + "factory/nodeConverters.ts", + "factory/nodeFactory.ts", "factory/emitNode.ts", "factory/emitHelpers.ts", "factory/nodeTests.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ca935b206c5..e82233422b1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5913,8 +5913,8 @@ namespace ts { } export interface NodeFactory { - /* @internal */ getParenthesizerRules(): ParenthesizerRules; - /* @internal */ getConverters(): NodeConverters; + /* @internal */ readonly parenthesizer: ParenthesizerRules; + /* @internal */ readonly converters: NodeConverters; createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; /** @@ -6037,7 +6037,6 @@ namespace ts { updateCallSignature(node: CallSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): CallSignatureDeclaration; createConstructSignature(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): ConstructSignatureDeclaration; updateConstructSignature(node: ConstructSignatureDeclaration, typeParameters: NodeArray | undefined, parameters: NodeArray, type: TypeNode | undefined): ConstructSignatureDeclaration; - /* @internal */ createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): T; createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; /* @internal */ createIndexSignature(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): IndexSignatureDeclaration; // tslint:disable-line unified-signatures updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration; @@ -6305,7 +6304,7 @@ namespace ts { /* @internal */ createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocEnumTag; /* @internal */ createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocParameterTag; /* @internal */ createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocPropertyTag; - /* @internal */ createJSDocTag(tagName: Identifier): JSDocTag; + /* @internal */ createJSDocUnknownTag(tagName: Identifier): JSDocUnknownTag; /* @internal */ createJSDocComment(comment?: string | undefined, tags?: NodeArray | undefined): JSDoc; // @@ -6387,6 +6386,44 @@ namespace ts { createBundle(sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends?: readonly (UnparsedSource | InputFiles)[]): Bundle; + // + // Common operators + // + + createComma(left: Expression, right: Expression): BinaryExpression; + createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + createAssignment(left: Expression, right: Expression): AssignmentExpression; + createLogicalOr(left: Expression, right: Expression): BinaryExpression; + createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + createBitwiseOr(left: Expression, right: Expression): BinaryExpression; + createBitwiseXor(left: Expression, right: Expression): BinaryExpression; + createBitwiseAnd(left: Expression, right: Expression): BinaryExpression; + createStrictEquality(left: Expression, right: Expression): BinaryExpression; + createStrictInequality(left: Expression, right: Expression): BinaryExpression; + createEquality(left: Expression, right: Expression): BinaryExpression; + createInequality(left: Expression, right: Expression): BinaryExpression; + createLessThan(left: Expression, right: Expression): BinaryExpression; + createLessThanEquals(left: Expression, right: Expression): BinaryExpression; + createGreaterThan(left: Expression, right: Expression): BinaryExpression; + createGreaterThanEquals(left: Expression, right: Expression): BinaryExpression; + createLeftShift(left: Expression, right: Expression): BinaryExpression; + createRightShift(left: Expression, right: Expression): BinaryExpression; + createUnsignedRightShift(left: Expression, right: Expression): BinaryExpression; + createAdd(left: Expression, right: Expression): BinaryExpression; + createSubtract(left: Expression, right: Expression): BinaryExpression; + createMultiply(left: Expression, right: Expression): BinaryExpression; + createDivide(left: Expression, right: Expression): BinaryExpression; + createModulo(left: Expression, right: Expression): BinaryExpression; + createExponent(left: Expression, right: Expression): BinaryExpression; + createPrefixPlus(operand: Expression): PrefixUnaryExpression; + createPrefixMinus(operand: Expression): PrefixUnaryExpression; + createPrefixIncrement(operand: Expression): PrefixUnaryExpression; + createPrefixDecrement(operand: Expression): PrefixUnaryExpression; + createBitwiseNot(operand: Expression): PrefixUnaryExpression; + createLogicalNot(operand: Expression): PrefixUnaryExpression; + createPostfixIncrement(operand: Expression): PostfixUnaryExpression; + createPostfixDecrement(operand: Expression): PostfixUnaryExpression; + // // Compound Nodes // @@ -6395,21 +6432,13 @@ namespace ts { createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; - createComma(left: Expression, right: Expression): Expression; - createLessThan(left: Expression, right: Expression): Expression; - createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; - createAssignment(left: Expression, right: Expression): BinaryExpression; - createStrictEquality(left: Expression, right: Expression): BinaryExpression; - createStrictInequality(left: Expression, right: Expression): BinaryExpression; - createAdd(left: Expression, right: Expression): BinaryExpression; - createSubtract(left: Expression, right: Expression): BinaryExpression; - createPostfixIncrement(operand: Expression): PostfixUnaryExpression; - createLogicalAnd(left: Expression, right: Expression): BinaryExpression; - createLogicalOr(left: Expression, right: Expression): BinaryExpression; - createLogicalNot(operand: Expression): PrefixUnaryExpression; + + createVoidZero(): VoidExpression; createExportDefault(expression: Expression): ExportAssignment; createExternalModuleExport(exportName: Identifier): ExportDeclaration; + + /* @internal */ createSignatureDeclaration(kind: T["kind"], typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): T; /* @internal */ createTypeCheck(value: Expression, tag: TypeOfTag): Expression; /* @internal */ createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]): CallExpression; /* @internal */ createGlobalMethodCall(globalObjectName: string, globalMethodName: string, argumentsList: readonly Expression[]): CallExpression; @@ -6490,8 +6519,7 @@ namespace ts { // Utilities // - // TODO(rbuckton): Rename to `restoreOuterExpressions`. - recreateOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; + restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds?: OuterExpressionKinds): Expression; /* @internal */ restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement; /* @internal */ createUseStrictPrologue(): PrologueDirective; /** diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index b5a9c722f40..44a0640d835 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -192,7 +192,7 @@ namespace ts { const updated = visitNode(node, visitor, isConciseBody); const declarations = endLexicalEnvironment(); if (some(declarations)) { - const block = factory.getConverters().convertToFunctionBlock(updated); + const block = factory.converters.convertToFunctionBlock(updated); const statements = mergeLexicalEnvironment(block.statements, declarations); return factory.updateBlock(block, statements); } diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index 19746e48a1d..08c5578c828 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -483,7 +483,7 @@ namespace ts.codefix { getSynthesizedDeepClones(fn.typeParameters), getSynthesizedDeepClones(fn.parameters), getSynthesizedDeepClone(fn.type), - factory.getConverters().convertToFunctionBlock(getSynthesizedDeepClone(fn.body!))); + factory.converters.convertToFunctionBlock(getSynthesizedDeepClone(fn.body!))); } function classExpressionToDeclaration(name: string | undefined, additionalModifiers: ReadonlyArray, cls: ClassExpression): ClassDeclaration { diff --git a/src/testRunner/runner.ts b/src/testRunner/runner.ts index 3532f972230..d94c83a6a9b 100644 --- a/src/testRunner/runner.ts +++ b/src/testRunner/runner.ts @@ -225,6 +225,12 @@ function handleTestConfig() { } function beginTests() { + ts.Debug.loggingHost = { + log(_level: ts.LogLevel, s: string) { + console.log(s || ""); + } + }; + if (ts.Debug.isDebugging) { ts.Debug.enableDebugInfo(); } diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index d65b1b35e4b..3d4e3208de3 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -446,6 +446,12 @@ namespace ts { } } +ts.Debug.loggingHost = { + log(_level: ts.LogLevel, s: string) { + ts.sys.write(`${s || ""}${ts.sys.newLine}`); + } +}; + if (ts.Debug.isDebugging) { ts.Debug.enableDebugInfo(); }